diff options
Diffstat (limited to 'qtmips_machine')
-rw-r--r-- | qtmips_machine/instruction.cpp | 689 | ||||
-rw-r--r-- | qtmips_machine/instruction.h | 2 |
2 files changed, 366 insertions, 325 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index 3b5f567..388e88c 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -35,6 +35,8 @@ #include <QMultiMap> #include <QVector> +#include <QStringList> +#include <QChar> #include <iostream> #include "instruction.h" #include "alu.h" @@ -43,6 +45,93 @@ using namespace machine; +#define IMF_SUB_ENCODE(bits, shift) (((bits) << 8) | (shift)) +#define IMF_SUB_GET_BITS(subcode) (((subcode) >> 8) & 0xff) +#define IMF_SUB_GET_SHIFT(subcode) ((subcode) & 0xff) + +#define RS_SHIFT 21 +#define RT_SHIFT 16 +#define RD_SHIFT 11 +#define SHAMT_SHIFT 6 + +#define FIELD_RS IMF_SUB_ENCODE(5, RS_SHIFT) +#define FIELD_RT IMF_SUB_ENCODE(5, RT_SHIFT) +#define FIELD_RD IMF_SUB_ENCODE(5, RD_SHIFT) +#define FIELD_SHAMT IMF_SUB_ENCODE(5, SHAMT_SHIFT) +#define FIELD_IMMEDIATE IMF_SUB_ENCODE(16, 0) +#define FIELD_DELTA IMF_SUB_ENCODE(16, 0) +#define FIELD_TARGET IMF_SUB_ENCODE(26, 0) +#define FIELD_COPZ IMF_SUB_ENCODE(25, 0) +#define FIELD_CODE IMF_SUB_ENCODE(10,16) +#define FIELD_PREFX IMF_SUB_ENCODE(5, 11) +#define FIELD_CACHE IMF_SUB_ENCODE(5, 16) +#define FIELD_CODE2 IMF_SUB_ENCODE(10, 6) +#define FIELD_CODE20 IMF_SUB_ENCODE(20, 6) +#define FIELD_CODE19 IMF_SUB_ENCODE(19, 6) +#define FIELD_SEL IMF_SUB_ENCODE(3, 0) +#define FIELD_IGNORE 0 + +struct ArgumentDesc { + inline ArgumentDesc(char name, char kind, std::uint32_t loc, std::int64_t min, std::int64_t max, unsigned shift) { + this->name = name; + this->kind = kind; + this->loc = loc; + this->min = min; + this->max = max; + this->shift = shift; + } + char name; + char kind; + std::uint32_t loc; + std::int64_t min; + std::int64_t max; + unsigned shift; +}; + +static const ArgumentDesc argdeslist[] = { + ArgumentDesc('1', 'n', FIELD_SHAMT, 0, 31, 0), // 5 bit sync type {OP_*_SHAMT} + ArgumentDesc('<', 'n', FIELD_SHAMT, 0, 31, 0), // 5 bit shift amount {OP_*_SHAMT} + ArgumentDesc('>', 'n', FIELD_SHAMT, 32, 63, 0), // shift amount between 32 and 63, stored after subtracting 32 {OP_*_SHAMT} + ArgumentDesc('a', 'a', FIELD_TARGET, 0, 0x3ffffff, 2), // 26 bit target address {OP_*_TARGET} + ArgumentDesc('b', 'g', FIELD_RS, 0, 31, 0), // 5 bit base register {OP_*_RS} + ArgumentDesc('c', 'g', FIELD_CODE, 0, 0x3ff, 0), // 10 bit breakpoint code {OP_*_CODE} + ArgumentDesc('d', 'g', FIELD_RD, 0, 31, 0), // 5 bit destination register specifier {OP_*_RD} + ArgumentDesc('h', 'h', FIELD_PREFX, 0, 31, 0), // 5 bit prefx hint {OP_*_PREFX} + ArgumentDesc('H', 'n', FIELD_SEL, 0, 7, 0), // 3 select field of MTC0, MFC0 + ArgumentDesc('i', 'n', FIELD_IMMEDIATE, 0, 0xffff, 0) , // 16 bit unsigned immediate {OP_*_IMMEDIATE} + ArgumentDesc('j', 'n', FIELD_IMMEDIATE, -0x8000, 0x7fff, 0) , // 16 bit signed immediate {OP_*_DELTA} + ArgumentDesc('k', 'n', FIELD_CACHE, 0, 31, 0), // 5 bit cache opcode in target register position {OP_*_CACHE} + // Also used for immediate operands in vr5400 vector insns. + ArgumentDesc('o', 'o', FIELD_DELTA, -0x8000, 0x7fff, 0) , // 16 bit signed offset {OP_*_DELTA} + ArgumentDesc('p', 'p', FIELD_DELTA, -0x8000, 0x7fff, 2) , // 16 bit PC relative branch target address {OP_*_DELTA} + ArgumentDesc('q', 'n', FIELD_CODE2, 0, 0x3ff, 0) , // 10 bit extra breakpoint code {OP_*_CODE2} + ArgumentDesc('r', 'g', FIELD_RS, 0, 31, 0) , // 5 bit same register used as both source and target {OP_*_RS} + ArgumentDesc('s', 'g', FIELD_RS, 0, 31, 0) , // 5 bit source register specifier {OP_*_RS} + ArgumentDesc('t', 'g', FIELD_RT, 0, 31, 0) , // 5 bit target register {OP_*_RT} + ArgumentDesc('u', 'n', FIELD_IMMEDIATE, 0, 0xffff, 0) , // 16 bit upper 16 bits of address {OP_*_IMMEDIATE} + ArgumentDesc('v', 'g', FIELD_RS, 0, 31, 0) , // 5 bit same register used as both source and destination {OP_*_RS} + ArgumentDesc('w', 'g', FIELD_RT, 0, 31, 0) , // 5 bit same register used as both target and destination {OP_*_RT} + ArgumentDesc('U', 'g', FIELD_RD, 0, 31, 0) , // 5 bit same destination register in both OP_*_RD and OP_*_RT + ArgumentDesc('G', 'g', FIELD_RD, 0, 31, 0) , // 5 destination register used in MFC0, MTC0 + // {used by clo and clz} + ArgumentDesc('C', 'n', FIELD_COPZ, 0, 0x1ffffff, 0) , // 25 bit coprocessor function code {OP_*_COPZ} + ArgumentDesc('B', 'n', FIELD_CODE20, 0, 0xfffff, 0) , // 20 bit syscall/breakpoint function code {OP_*_CODE20} + ArgumentDesc('J', 'n', FIELD_CODE19, 0, 0x7ffff, 0) , // 19 bit wait function code {OP_*_CODE19} + ArgumentDesc('x', 'g', FIELD_IGNORE, 0, 31, 0) , // accept and ignore register name + ArgumentDesc('z', 'n', FIELD_IGNORE, 0, 0, 0) , // must be zero register +}; + +static const ArgumentDesc *argdesbycode[(int)('z' + 1)]; + +static bool fill_argdesbycode() { + uint i; + for (i = 0; i < sizeof(argdeslist)/sizeof(*argdeslist); i++) + argdesbycode[(uint)argdeslist[i].name] = &argdeslist[i]; + return true; +} + +bool argdesbycode_filled = fill_argdesbycode(); + #define FLAGS_ALU_I_NO_RS (IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE) #define FLAGS_ALU_I (IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_ALU_REQ_RS) #define FLAGS_ALU_I_ZE (FLAGS_ALU_I | IMF_ZERO_EXTEND) @@ -69,132 +158,131 @@ using namespace machine; #define NOALU .alu = ALU_OP_SLL #define NOMEM .mem_ctl = AC_NONE -#define IM_UNKNOWN {"UNKNOWN", Instruction::T_UNKNOWN, NOALU, NOMEM, nullptr, .flags = 0} +#define IM_UNKNOWN {"UNKNOWN", Instruction::T_UNKNOWN, NOALU, NOMEM, nullptr, {}, 0, 0, 0} struct InstructionMap { const char *name; enum Instruction::Type type; enum AluOp alu; enum AccessControl mem_ctl; - const struct InstructionMap *subclass; // when subclass is used then flags has special meaning + const struct InstructionMap *subclass; // when subclass is used then flags has special meaning + const QStringList args; + std::uint32_t code; + std::uint32_t mask; unsigned int flags; }; -#define IMF_SUB_ENCODE(bits, shift) (((bits) << 8) | (shift)) -#define IMF_SUB_GET_BITS(subcode) (((subcode) >> 8) & 0xff) -#define IMF_SUB_GET_SHIFT(subcode) ((subcode) & 0xff) - #define IT_R Instruction::T_R #define IT_I Instruction::T_I #define IT_J Instruction::T_J static const struct InstructionMap srl_rotr_instruction_map[] = { - {"SRL", IT_R, ALU_OP_SRL, NOMEM, nullptr, + {"SRL", IT_R, ALU_OP_SRL, NOMEM, nullptr, {"d", "w", "<"}, 0x00000002, 0xffe0003f, .flags = FLAGS_ALU_T_R_TD_SHAMT}, - {"ROTR", IT_R, ALU_OP_ROTR, NOMEM, nullptr, + {"ROTR", IT_R, ALU_OP_ROTR, NOMEM, nullptr, {"d", "w", "<"}, 0x00200002, 0xffe0003f, .flags = FLAGS_ALU_T_R_TD_SHAMT}, }; static const struct InstructionMap srlv_rotrv_instruction_map[] = { - {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, nullptr, + {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, nullptr, {"d", "t", "s"}, 0x00000006, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD_SHV}, - {"ROTRV", IT_R, ALU_OP_ROTRV, NOMEM, nullptr, + {"ROTRV", IT_R, ALU_OP_ROTRV, NOMEM, nullptr, {"d", "t", "s"}, 0x00000046, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD_SHV}, }; // This table is indexed by funct static const struct InstructionMap alu_instruction_map[] = { - {"SLL", IT_R, ALU_OP_SLL, NOMEM, nullptr, + {"SLL", IT_R, ALU_OP_SLL, NOMEM, nullptr, {"d", "w", "<"}, 0x00000000, 0xffe0003f, .flags = FLAGS_ALU_T_R_TD_SHAMT}, IM_UNKNOWN, - {"SRL", IT_R, ALU_OP_SRL, NOMEM, srl_rotr_instruction_map, + {"SRL", IT_R, ALU_OP_SRL, NOMEM, srl_rotr_instruction_map, {}, 0, 0, .flags = IMF_SUB_ENCODE(1, 21)}, - {"SRA", IT_R, ALU_OP_SRA, NOMEM, nullptr, + {"SRA", IT_R, ALU_OP_SRA, NOMEM, nullptr, {"d", "w", "<"}, 0x00000003, 0xffe0003f, .flags = FLAGS_ALU_T_R_TD_SHAMT}, - {"SLLV", IT_R, ALU_OP_SLLV, NOMEM, nullptr, + {"SLLV", IT_R, ALU_OP_SLLV, NOMEM, nullptr, {"d", "t", "s"}, 0x00000004, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD_SHV}, IM_UNKNOWN, - {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, srlv_rotrv_instruction_map, + {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, srlv_rotrv_instruction_map, {"d", "t", "s"}, 0x00000006, 0xfc0007ff, .flags = IMF_SUB_ENCODE(1, 6)}, - {"SRAV", IT_R, ALU_OP_SRAV, NOMEM, nullptr, + {"SRAV", IT_R, ALU_OP_SRAV, NOMEM, nullptr, {"d", "t", "s"}, 0x00000007, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD_SHV}, - {"JR", IT_R, ALU_OP_NOP, NOMEM, nullptr, + {"JR", IT_R, ALU_OP_NOP, NOMEM, nullptr, {"s"}, 0x00000008, 0xfc1fffff, .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_JUMP}, - {"JALR", IT_R, ALU_OP_PASS_T, NOMEM, nullptr, + {"JALR", IT_R, ALU_OP_PASS_T, NOMEM, nullptr, {"d", "s"}, 0x00000009, 0xfc1f07ff, .flags = IMF_SUPPORTED | IMF_REGD | IMF_REGWRITE | IMF_BJR_REQ_RS | IMF_PC8_TO_RT | IMF_JUMP}, - {"MOVZ", IT_R, ALU_OP_MOVZ, NOMEM, nullptr, + {"MOVZ", IT_R, ALU_OP_MOVZ, NOMEM, nullptr, {"d", "v", "t"}, 0x0000000a, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"MOVN", IT_R, ALU_OP_MOVN, NOMEM, nullptr, + {"MOVN", IT_R, ALU_OP_MOVN, NOMEM, nullptr, {"d", "v", "t"}, 0x0000000b, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"SYSCALL",IT_R, ALU_OP_SYSCALL, NOMEM, nullptr, + {"SYSCALL",IT_R, ALU_OP_SYSCALL, NOMEM, nullptr, {nullptr}, 0x0000000c, 0xffffffff, .flags = IMF_SUPPORTED | IMF_EXCEPTION}, - {"BREAK", IT_R, ALU_OP_BREAK, NOMEM, nullptr, + {"BREAK", IT_R, ALU_OP_BREAK, NOMEM, nullptr, {nullptr}, 0x0000000d, 0xffffffff, .flags = IMF_SUPPORTED | IMF_EXCEPTION}, IM_UNKNOWN, - {"SYNC", IT_I, NOALU, NOMEM, nullptr, // SYNC + {"SYNC", IT_I, NOALU, NOMEM, nullptr, {nullptr}, 0x0000000f, 0xffffffff, // SYNC .flags = IMF_SUPPORTED}, - {"MFHI", IT_R, ALU_OP_MFHI, NOMEM, nullptr, + {"MFHI", IT_R, ALU_OP_MFHI, NOMEM, nullptr, {"d"}, 0x00000010, 0xffff07ff, .flags = FLAGS_ALU_T_R_D | IMF_READ_HILO}, - {"MTHI", IT_R, ALU_OP_MTHI, NOMEM, nullptr, + {"MTHI", IT_R, ALU_OP_MTHI, NOMEM, nullptr, {"s"}, 0x00000011, 0xfc1fffff, .flags = FLAGS_ALU_T_R_S | IMF_WRITE_HILO}, - {"MFLO", IT_R, ALU_OP_MFLO, NOMEM, nullptr, + {"MFLO", IT_R, ALU_OP_MFLO, NOMEM, nullptr, {"d"}, 0x00000012, 0xffff07ff, .flags = FLAGS_ALU_T_R_D | IMF_READ_HILO}, - {"MTLO", IT_R, ALU_OP_MTLO, NOMEM, nullptr, + {"MTLO", IT_R, ALU_OP_MTLO, NOMEM, nullptr, {"s"}, 0x00000013, 0xfc1fffff, .flags = FLAGS_ALU_T_R_S | IMF_WRITE_HILO}, IM_UNKNOWN, IM_UNKNOWN, IM_UNKNOWN, IM_UNKNOWN, - {"MULT", IT_R, ALU_OP_MULT, NOMEM, nullptr, + {"MULT", IT_R, ALU_OP_MULT, NOMEM, nullptr, {"s", "t"}, 0x00000018, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 24 - {"MULTU", IT_R, ALU_OP_MULTU, NOMEM, nullptr, + {"MULTU", IT_R, ALU_OP_MULTU, NOMEM, nullptr, {"s", "t"}, 0x00000019, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 25 - {"DIV", IT_R, ALU_OP_DIV, NOMEM, nullptr, + {"DIV", IT_R, ALU_OP_DIV, NOMEM, nullptr, {"z", "s", "t"}, 0x0000001a, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 26 - {"DIVU", IT_R, ALU_OP_DIVU, NOMEM, nullptr, + {"DIVU", IT_R, ALU_OP_DIVU, NOMEM, nullptr, {"z", "s", "t"}, 0x0000001b, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 27 IM_UNKNOWN, // 28 IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 IM_UNKNOWN, // 31 - {"ADD", IT_R, ALU_OP_ADD, NOMEM, nullptr, + {"ADD", IT_R, ALU_OP_ADD, NOMEM, nullptr, {"d", "v", "t"}, 0x00000020, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, // 32 - {"ADDU", IT_R, ALU_OP_ADDU, NOMEM, nullptr, + {"ADDU", IT_R, ALU_OP_ADDU, NOMEM, nullptr, {"d", "v", "t"}, 0x00000021, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"SUB", IT_R, ALU_OP_SUB, NOMEM, nullptr, + {"SUB", IT_R, ALU_OP_SUB, NOMEM, nullptr, {"d", "v", "t"}, 0x00000022, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"SUBU", IT_R, ALU_OP_SUBU, NOMEM, nullptr, + {"SUBU", IT_R, ALU_OP_SUBU, NOMEM, nullptr, {"d", "v", "t"}, 0x00000023, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"AND", IT_R, ALU_OP_AND, NOMEM, nullptr, + {"AND", IT_R, ALU_OP_AND, NOMEM, nullptr, {"d", "v", "t"}, 0x00000024, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"OR", IT_R, ALU_OP_OR, NOMEM, nullptr, + {"OR", IT_R, ALU_OP_OR, NOMEM, nullptr, {"d", "v", "t"}, 0x00000025, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"XOR", IT_R, ALU_OP_XOR, NOMEM, nullptr, + {"XOR", IT_R, ALU_OP_XOR, NOMEM, nullptr, {"d", "v", "t"}, 0x00000026, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"NOR", IT_R, ALU_OP_NOR, NOMEM, nullptr, + {"NOR", IT_R, ALU_OP_NOR, NOMEM, nullptr, {"d", "v", "t"}, 0x00000027, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, IM_UNKNOWN, IM_UNKNOWN, - {"SLT", IT_R, ALU_OP_SLT, NOMEM, nullptr, + {"SLT", IT_R, ALU_OP_SLT, NOMEM, nullptr, {"d", "v", "t"}, 0x0000002a, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, - {"SLTU", IT_R, ALU_OP_SLTU, NOMEM, nullptr, + {"SLTU", IT_R, ALU_OP_SLTU, NOMEM, nullptr, {"d", "v", "t"}, 0x0000002b, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, IM_UNKNOWN, // 44 IM_UNKNOWN, // 45 IM_UNKNOWN, // 46 IM_UNKNOWN, // 47 - {"TGE", IT_I, ALU_OP_TGE, NOMEM, nullptr, // TGE 48 + {"TGE", IT_I, ALU_OP_TGE, NOMEM, nullptr, {"s", "t"}, 0x00000030, 0xfc00ffff, // TGE 48 .flags = FLAGS_ALU_TRAP_ST}, - {"TGEU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, // TGEU 49 + {"TGEU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, {"s", "t"}, 0x00000031, 0xfc00ffff, // TGEU 49 .flags = FLAGS_ALU_TRAP_ST}, - {"TLT", IT_I, ALU_OP_TLT, NOMEM, nullptr, // TLT 50 + {"TLT", IT_I, ALU_OP_TLT, NOMEM, nullptr, {"s", "t"}, 0x00000032, 0xfc00ffff, // TLT 50 .flags = FLAGS_ALU_TRAP_ST}, - {"TLTU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, // TLTU 51 + {"TLTU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, {"s", "t"}, 0x00000033, 0xfc00ffff, // TLTU 51 .flags = FLAGS_ALU_TRAP_ST}, - {"TEQ", IT_I, ALU_OP_TEQ, NOMEM, nullptr, // TEQ 52 + {"TEQ", IT_I, ALU_OP_TEQ, NOMEM, nullptr, {"s", "t"}, 0x00000034, 0xfc00ffff, // TEQ 52 .flags = FLAGS_ALU_TRAP_ST}, IM_UNKNOWN, // 53 - {"TNE", IT_I, ALU_OP_TNE, NOMEM, nullptr, // TNE 54 + {"TNE", IT_I, ALU_OP_TNE, NOMEM, nullptr, {"s", "t"}, 0x00000036, 0xfc00ffff, // TNE 54 .flags = FLAGS_ALU_TRAP_ST}, IM_UNKNOWN, // 55 IM_UNKNOWN, // 56 @@ -208,16 +296,16 @@ static const struct InstructionMap alu_instruction_map[] = { }; static const struct InstructionMap special2_instruction_map[] = { - {"MADD", IT_R, ALU_OP_MADD, NOMEM, nullptr, + {"MADD", IT_R, ALU_OP_MADD, NOMEM, nullptr, {"s", "t"}, 0x70000000, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_READ_HILO | IMF_WRITE_HILO}, - {"MADDU", IT_R, ALU_OP_MADDU, NOMEM, nullptr, + {"MADDU", IT_R, ALU_OP_MADDU, NOMEM, nullptr, {"s", "t"}, 0x70000001, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_READ_HILO | IMF_WRITE_HILO}, - {"MUL", IT_R, ALU_OP_MUL, NOMEM, nullptr, + {"MUL", IT_R, ALU_OP_MUL, NOMEM, nullptr, {"d", "v", "t"}, 0x70000002, 0xfc0007ff, .flags = FLAGS_ALU_T_R_STD}, // 32 IM_UNKNOWN, // 3 - {"MSUB", IT_R, ALU_OP_MSUB, NOMEM, nullptr, + {"MSUB", IT_R, ALU_OP_MSUB, NOMEM, nullptr, {"s", "t"}, 0x70000004, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_READ_HILO | IMF_WRITE_HILO}, - {"MSUBU", IT_R, ALU_OP_MSUBU, NOMEM, nullptr, + {"MSUBU", IT_R, ALU_OP_MSUBU, NOMEM, nullptr, {"s", "t"}, 0x70000005, 0xfc00ffff, .flags = FLAGS_ALU_T_R_ST | IMF_READ_HILO | IMF_WRITE_HILO}, IM_UNKNOWN, // 6 IM_UNKNOWN, // 7 @@ -245,9 +333,9 @@ static const struct InstructionMap special2_instruction_map[] = { IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 IM_UNKNOWN, // 31 - {"CLZ", IT_R, ALU_OP_CLZ, NOMEM, nullptr, + {"CLZ", IT_R, ALU_OP_CLZ, NOMEM, nullptr, {"U", "s"}, 0x70000020, 0xfc0007ff, .flags = FLAGS_ALU_T_R_SD}, - {"CLO", IT_R, ALU_OP_CLO, NOMEM, nullptr, + {"CLO", IT_R, ALU_OP_CLO, NOMEM, nullptr, {"U", "s"}, 0x70000021, 0xfc0007ff, .flags = FLAGS_ALU_T_R_SD}, IM_UNKNOWN, // 34 IM_UNKNOWN, // 35 @@ -284,7 +372,7 @@ static const struct InstructionMap special2_instruction_map[] = { static const struct InstructionMap bshfl_instruction_map[] = { IM_UNKNOWN, // 0 IM_UNKNOWN, // 1 - {"WSBH", IT_R, ALU_OP_WSBH, NOMEM, nullptr, + {"WSBH", IT_R, ALU_OP_WSBH, NOMEM, nullptr, {"d", "w"}, 0x7c0000a0, 0xffe007ff, .flags = FLAGS_ALU_T_R_TD}, IM_UNKNOWN, // 3 IM_UNKNOWN, // 4 @@ -299,7 +387,7 @@ static const struct InstructionMap bshfl_instruction_map[] = { IM_UNKNOWN, // 13 IM_UNKNOWN, // 14 IM_UNKNOWN, // 15 - {"SEB", IT_R, ALU_OP_SEB, NOMEM, nullptr, + {"SEB", IT_R, ALU_OP_SEB, NOMEM, nullptr, {"d", "w"}, 0x7c000420, 0xffe007ff, .flags = FLAGS_ALU_T_R_TD}, IM_UNKNOWN, // 17 IM_UNKNOWN, // 18 @@ -308,7 +396,7 @@ static const struct InstructionMap bshfl_instruction_map[] = { IM_UNKNOWN, // 21 IM_UNKNOWN, // 22 IM_UNKNOWN, // 23 - {"SEH", IT_R, ALU_OP_SEH, NOMEM, nullptr, + {"SEH", IT_R, ALU_OP_SEH, NOMEM, nullptr, {"d", "w"}, 0x7c000620, 0xffe007ff, .flags = FLAGS_ALU_T_R_TD}, IM_UNKNOWN, // 25 IM_UNKNOWN, // 26 @@ -320,12 +408,12 @@ static const struct InstructionMap bshfl_instruction_map[] = { }; static const struct InstructionMap special3_instruction_map[] = { - {"EXT", IT_I, ALU_OP_EXT, NOMEM, nullptr, + {"EXT", IT_I, ALU_OP_EXT, NOMEM, nullptr, {"t", "r", "+A", "+C"}, 0x7c000000, 0xfc00003f, .flags = IMF_SUPPORTED | IMF_REGWRITE | IMF_ALU_REQ_RS}, IM_UNKNOWN, // 1 IM_UNKNOWN, // 2 IM_UNKNOWN, // 3 - {"INS", IT_I, ALU_OP_EXT, NOMEM, nullptr, + {"INS", IT_I, ALU_OP_EXT, NOMEM, nullptr, {"t", "r", "+A", "+B"}, 0x7c000004, 0xfc00003f, .flags = IMF_SUPPORTED | IMF_REGWRITE | IMF_ALU_REQ_RS | IMF_ALU_REQ_RT}, IM_UNKNOWN, // 5 IM_UNKNOWN, // 6 @@ -354,7 +442,7 @@ static const struct InstructionMap special3_instruction_map[] = { IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 IM_UNKNOWN, // 31 - {"BSHFL", IT_I, NOALU, NOMEM, bshfl_instruction_map, + {"BSHFL", IT_I, NOALU, NOMEM, bshfl_instruction_map, {}, 0, 0, .flags = IMF_SUB_ENCODE(5, 6)}, IM_UNKNOWN, // 33 IM_UNKNOWN, // 34 @@ -382,7 +470,7 @@ static const struct InstructionMap special3_instruction_map[] = { IM_UNKNOWN, // 56 IM_UNKNOWN, // 57 IM_UNKNOWN, // 58 - {"RDHWR", IT_R, ALU_OP_RDHWR, NOMEM, nullptr, + {"RDHWR", IT_R, ALU_OP_RDHWR, NOMEM, nullptr, {"t", "K"}, 0x7c00003b, 0xffe007ff, .flags = IMF_SUPPORTED | IMF_REGWRITE}, IM_UNKNOWN, // 60 IM_UNKNOWN, // 61 @@ -391,39 +479,39 @@ static const struct InstructionMap special3_instruction_map[] = { }; static const struct InstructionMap regimm_instruction_map[] = { - {"BLTZ", IT_I, NOALU, NOMEM, nullptr, // BLTZ + {"BLTZ", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x04000000, 0xfc1f0000, // BLTZ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH}, - {"BGEZ", IT_I, NOALU, NOMEM, nullptr, // BGEZ + {"BGEZ", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x04010000, 0xfc1f0000, // BGEZ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_BJ_NOT}, - {"BLTZL", IT_I, NOALU, NOMEM, nullptr, // BLTZL + {"BLTZL", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x04020000, 0xfc1f0000, // BLTZL .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS}, - {"BGEZL", IT_I, NOALU, NOMEM, nullptr, // BGEZL + {"BGEZL", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x04030000, 0xfc1f0000, // BGEZL .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BJ_NOT}, IM_UNKNOWN, IM_UNKNOWN, IM_UNKNOWN, IM_UNKNOWN, - {"TGEI", IT_I, ALU_OP_TGE, NOMEM, nullptr, // TGEI 16 + {"TGEI", IT_I, ALU_OP_TGE, NOMEM, nullptr, {"s", "j"}, 0x04080000, 0xfc1f0000, // TGEI 16 .flags = FLAGS_ALU_TRAP_SI}, - {"TGEIU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, // TGEIU 17 + {"TGEIU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, {"s", "j"}, 0x04090000, 0xfc1f0000, // TGEIU 17 .flags = FLAGS_ALU_TRAP_SI}, - {"TLTI", IT_I, ALU_OP_TLT, NOMEM, nullptr, // TLTI 18 + {"TLTI", IT_I, ALU_OP_TLT, NOMEM, nullptr, {"s", "j"}, 0x040a0000, 0xfc1f0000, // TLTI 18 .flags = FLAGS_ALU_TRAP_SI}, - {"TLTIU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, // TLTIU 19 + {"TLTIU", IT_I, ALU_OP_TGEU, NOMEM, nullptr, {"s", "j"}, 0x040b0000, 0xfc1f0000, // TLTIU 19 .flags = FLAGS_ALU_TRAP_SI}, - {"TEQI", IT_I, ALU_OP_TEQ, NOMEM, nullptr, // TEQI 20 + {"TEQI", IT_I, ALU_OP_TEQ, NOMEM, nullptr, {"s", "j"}, 0x040c0000, 0xfc1f0000, // TEQI 20 .flags = FLAGS_ALU_TRAP_SI}, IM_UNKNOWN, // 21 - {"TNEI", IT_I, ALU_OP_TNE, NOMEM, nullptr, // TNEI 22 + {"TNEI", IT_I, ALU_OP_TNE, NOMEM, nullptr, {"s", "j"}, 0x040e0000, 0xfc1f0000, // TNEI 22 .flags = FLAGS_ALU_TRAP_SI}, IM_UNKNOWN, // 23 - {"BLTZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BLTZAL + {"BLTZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, {"s", "p"}, 0x04100000, 0xfc1f0000, // BLTZAL .flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH}, - {"BGEZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BGEZAL + {"BGEZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, {"s", "p"}, 0x04110000, 0xfc1f0000, // BGEZAL .flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_BJ_NOT}, - {"BLTZALL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BLTZALL + {"BLTZALL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, {"s", "p"}, 0x04120000, 0xfc1f0000, // BLTZALL .flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS }, - {"BGEZALL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BGEZALL + {"BGEZALL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, {"s", "p"}, 0x04130000, 0xfc1f0000, // BGEZALL .flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BJ_NOT}, IM_UNKNOWN, IM_UNKNOWN, @@ -436,7 +524,7 @@ static const struct InstructionMap regimm_instruction_map[] = { IM_UNKNOWN, IM_UNKNOWN, IM_UNKNOWN, - {"SYNCI", IT_I, ALU_OP_ADDU, AC_CACHE_OP, nullptr, // SYNCI + {"SYNCI", IT_I, ALU_OP_ADDU, AC_CACHE_OP, nullptr, {"o(b)"}, 0x041f0000, 0xfc1f0000, // SYNCI .flags = IMF_SUPPORTED | IMF_STOP_IF | IMF_BJR_REQ_RS}, }; @@ -465,7 +553,7 @@ static const struct InstructionMap cop0_func_instruction_map[] = { IM_UNKNOWN, // 21 IM_UNKNOWN, // 22 IM_UNKNOWN, // 23 - {"ERET", IT_I, ALU_OP_ERET, NOMEM, nullptr, + {"ERET", IT_I, ALU_OP_ERET, NOMEM, nullptr, {nullptr}, 0x42000018, 0xffffffff, .flags = IMF_SUPPORTED | IMF_STOP_IF}, IM_UNKNOWN, // 25 IM_UNKNOWN, // 26 @@ -509,12 +597,12 @@ static const struct InstructionMap cop0_func_instruction_map[] = { }; static const struct InstructionMap cop0_instruction_map[] = { - {"MFC0", IT_I, ALU_OP_MFC0, NOMEM, nullptr, + {"MFC0", IT_I, ALU_OP_MFC0, NOMEM, nullptr, {"t", "G", "H"}, 0x40000000, 0xffe007ff, .flags = IMF_SUPPORTED | IMF_REGWRITE}, IM_UNKNOWN, // 1 IM_UNKNOWN, // 2 MFH IM_UNKNOWN, // 3 - {"MTC0", IT_I, ALU_OP_MTC0, NOMEM, nullptr, + {"MTC0", IT_I, ALU_OP_MTC0, NOMEM, nullptr, {"t", "G", "H"}, 0x40800000, 0xffe007ff, .flags = IMF_SUPPORTED | IMF_ALU_REQ_RT}, IM_UNKNOWN, // 5 IM_UNKNOWN, // 6 MTH @@ -522,43 +610,43 @@ static const struct InstructionMap cop0_instruction_map[] = { IM_UNKNOWN, // 8 IM_UNKNOWN, // 9 IM_UNKNOWN, // 10 RDPGPR - {"MFMC0", IT_I, ALU_OP_MFMC0, NOMEM, nullptr, + {"MFMC0", IT_I, ALU_OP_MFMC0, NOMEM, nullptr, {"t"}, 0x41600000, 0xffe0ffdf, // TODO .flags = IMF_SUPPORTED | IMF_REGWRITE}, IM_UNKNOWN, // 12 IM_UNKNOWN, // 13 IM_UNKNOWN, // 13 WRPGPR IM_UNKNOWN, // 15 - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, - {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, + {"C0", IT_I, NOALU, NOMEM, cop0_func_instruction_map, {"C"}, 0x42000000, 0xfe000000, .flags = IMF_SUB_ENCODE(6, 0)}, }; @@ -566,110 +654,110 @@ const std::int32_t instruction_map_opcode_field = IMF_SUB_ENCODE(6, 26); // This table is indexed by opcode static const struct InstructionMap instruction_map[] = { - {"ALU", IT_R, NOALU, NOMEM, alu_instruction_map, // Alu operations + {"ALU", IT_R, NOALU, NOMEM, alu_instruction_map, {}, 0, 0, // Alu operations .flags = IMF_SUB_ENCODE(6, 0)}, - {"REGIMM", IT_I, NOALU, NOMEM, regimm_instruction_map, // REGIMM (BLTZ, BGEZ) + {"REGIMM", IT_I, NOALU, NOMEM, regimm_instruction_map, {}, 0, 0, // REGIMM (BLTZ, nullptr, 0, 0 BGEZ) .flags = IMF_SUB_ENCODE(5, 16)}, - {"J", IT_J, NOALU, NOMEM, nullptr, // J + {"J", IT_J, NOALU, NOMEM, nullptr, {"a"}, 0x08000000, 0xfc000000, // J .flags = IMF_SUPPORTED | IMF_JUMP}, - {"JAL", IT_J, ALU_OP_PASS_T, NOMEM, nullptr, // JAL + {"JAL", IT_J, ALU_OP_PASS_T, NOMEM, nullptr, {"a"}, 0x0c000000, 0xfc000000, // JAL .flags = FLAGS_J_B_PC_TO_R31 | IMF_JUMP}, - {"BEQ", IT_I, NOALU, NOMEM, nullptr, // BEQ + {"BEQ", IT_I, NOALU, NOMEM, nullptr, {"s", "t", "p"}, 0x10000000, 0xfc000000, // BEQ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT | IMF_BRANCH}, - {"BNE", IT_I, NOALU, NOMEM, nullptr, // BNE + {"BNE", IT_I, NOALU, NOMEM, nullptr, {"s", "t", "p"}, 0x14000000, 0xfc000000, // BNE .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT | IMF_BRANCH | IMF_BJ_NOT}, - {"BLEZ", IT_I, NOALU, NOMEM, nullptr, // BLEZ + {"BLEZ", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x18000000, 0xfc1f0000, // BLEZ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_BGTZ_BLEZ}, - {"BGTZ", IT_I, NOALU, NOMEM, nullptr, // BGTZ + {"BGTZ", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x1c000000, 0xfc1f0000, // BGTZ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_BGTZ_BLEZ | IMF_BJ_NOT}, - {"ADDI", IT_I, ALU_OP_ADD, NOMEM, nullptr, // ADDI + {"ADDI", IT_I, ALU_OP_ADD, NOMEM, nullptr, {"t", "r", "j"}, 0x20000000, 0xfc000000, // ADDI .flags = FLAGS_ALU_I}, - {"ADDIU", IT_I, ALU_OP_ADDU, NOMEM, nullptr, // ADDIU + {"ADDIU", IT_I, ALU_OP_ADDU, NOMEM, nullptr, {"t", "r", "j"}, 0x24000000, 0xfc000000, // ADDIU .flags = FLAGS_ALU_I}, - {"SLTI", IT_I, ALU_OP_SLT, NOMEM, nullptr, // SLTI + {"SLTI", IT_I, ALU_OP_SLT, NOMEM, nullptr, {"t", "r", "j"}, 0x28000000, 0xfc000000, // SLTI .flags = FLAGS_ALU_I}, - {"SLTIU", IT_I, ALU_OP_SLTU, NOMEM, nullptr, // SLTIU + {"SLTIU", IT_I, ALU_OP_SLTU, NOMEM, nullptr, {"t", "r", "j"}, 0x2c000000, 0xfc000000, // SLTIU .flags = FLAGS_ALU_I}, - {"ANDI", IT_I, ALU_OP_AND, NOMEM, nullptr, // ANDI + {"ANDI", IT_I, ALU_OP_AND, NOMEM, nullptr, {"t", "r", "i"}, 0x30000000, 0xfc000000, // ANDI .flags = FLAGS_ALU_I_ZE}, - {"ORI", IT_I, ALU_OP_OR, NOMEM, nullptr, // ORI + {"ORI", IT_I, ALU_OP_OR, NOMEM, nullptr, {"t", "r", "i"}, 0x34000000, 0xfc000000, // ORI .flags = FLAGS_ALU_I_ZE}, - {"XORI", IT_I, ALU_OP_XOR, NOMEM, nullptr, // XORI + {"XORI", IT_I, ALU_OP_XOR, NOMEM, nullptr, {"t", "r", "i"}, 0x38000000, 0xfc000000, // XORI .flags = FLAGS_ALU_I_ZE}, - {"LUI", IT_I, ALU_OP_LUI, NOMEM, nullptr, // LUI + {"LUI", IT_I, ALU_OP_LUI, NOMEM, nullptr, {"t", "u"}, 0x3c000000, 0xffe00000, // LUI .flags = FLAGS_ALU_I_NO_RS}, - {"COP0", IT_I, NOALU, NOMEM, cop0_instruction_map, // COP0 + {"COP0", IT_I, NOALU, NOMEM, cop0_instruction_map, {"C"}, 0x00000000, 0x00000000, // COP0 .flags = IMF_SUB_ENCODE(5, 21)}, IM_UNKNOWN, // 17 IM_UNKNOWN, // 18 IM_UNKNOWN, // 19 - {"BEQL", IT_I, NOALU, NOMEM, nullptr, // BEQL + {"BEQL", IT_I, NOALU, NOMEM, nullptr, {"s", "t", "p"}, 0x50000000, 0xfc000000, // BEQL .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT | IMF_BRANCH | IMF_NB_SKIP_DS}, - {"BNEL", IT_I, NOALU, NOMEM, nullptr, // BNEL + {"BNEL", IT_I, NOALU, NOMEM, nullptr, {"s", "t", "p"}, 0x54000000, 0xfc000000, // BNEL .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BJ_NOT}, - {"BLEZL", IT_I, NOALU, NOMEM, nullptr, // BLEZL + {"BLEZL", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x58000000, 0xfc1f0000, // BLEZL .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BGTZ_BLEZ}, - {"BGTZL", IT_I, NOALU, NOMEM, nullptr, // BGTZL + {"BGTZL", IT_I, NOALU, NOMEM, nullptr, {"s", "p"}, 0x5c000000, 0xfc1f0000, // BGTZL .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BGTZ_BLEZ | IMF_BJ_NOT}, IM_UNKNOWN, // 24 IM_UNKNOWN, // 25 IM_UNKNOWN, // 26 IM_UNKNOWN, // 27 - {"REGIMM", IT_I, NOALU, NOMEM, special2_instruction_map, // SPECIAL2 + {"REGIMM", IT_I, NOALU, NOMEM, special2_instruction_map, {}, 0, 0, // SPECIAL2 .flags = IMF_SUB_ENCODE(6, 0)}, IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 - {"SPECIAL3", IT_R, NOALU, NOMEM, special3_instruction_map, // + {"SPECIAL3", IT_R, NOALU, NOMEM, special3_instruction_map, {}, 0, 0, // .flags = IMF_SUB_ENCODE(6, 0)}, - {"LB", IT_I, ALU_OP_ADDU, AC_BYTE, nullptr, // LB + {"LB", IT_I, ALU_OP_ADDU, AC_BYTE, nullptr, {"t", "o(b)"}, 0x80000000, 0xfc000000, // LB .flags = FLAGS_ALU_I_LOAD}, - {"LH", IT_I, ALU_OP_ADDU, AC_HALFWORD, nullptr, // LH + {"LH", IT_I, ALU_OP_ADDU, AC_HALFWORD, nullptr, {"t", "o(b)"}, 0x84000000, 0xfc000000, // LH .flags = FLAGS_ALU_I_LOAD}, - {"LWL", IT_I, ALU_OP_ADDU, AC_WORD_LEFT, nullptr, // LWL - unsupported + {"LWL", IT_I, ALU_OP_ADDU, AC_WORD_LEFT, nullptr, {"t", "o(b)"}, 0x88000000, 0xfc000000, // LWL - unsupported .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RT}, - {"LW", IT_I, ALU_OP_ADDU, AC_WORD, nullptr, // LW + {"LW", IT_I, ALU_OP_ADDU, AC_WORD, nullptr, {"t", "o(b)"}, 0x8c000000, 0xfc000000, // LW .flags = FLAGS_ALU_I_LOAD}, - {"LBU", IT_I, ALU_OP_ADDU, AC_BYTE_UNSIGNED, nullptr, // LBU + {"LBU", IT_I, ALU_OP_ADDU, AC_BYTE_UNSIGNED, nullptr, {"t", "o(b)"}, 0x90000000, 0xfc000000, // LBU .flags = FLAGS_ALU_I_LOAD}, - {"LHU", IT_I, ALU_OP_ADDU, AC_HALFWORD_UNSIGNED, nullptr, // LHU + {"LHU", IT_I, ALU_OP_ADDU, AC_HALFWORD_UNSIGNED, nullptr, {"t", "o(b)"}, 0x94000000, 0xfc000000, // LHU .flags = FLAGS_ALU_I_LOAD}, - {"LWR", IT_I, ALU_OP_ADDU, AC_WORD_RIGHT, nullptr, // LWR - unsupported + {"LWR", IT_I, ALU_OP_ADDU, AC_WORD_RIGHT, nullptr, {"t", "o(b)"}, 0x98000000, 0xfc000000, // LWR - unsupported .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RT}, IM_UNKNOWN, // 39 - {"SB", IT_I, ALU_OP_ADDU, AC_BYTE, nullptr, // SB + {"SB", IT_I, ALU_OP_ADDU, AC_BYTE, nullptr, {"t", "o(b)"}, 0xa0000000, 0xfc000000, // SB .flags = FLAGS_ALU_I_STORE}, - {"SH", IT_I, ALU_OP_ADDU, AC_HALFWORD, nullptr, // SH + {"SH", IT_I, ALU_OP_ADDU, AC_HALFWORD, nullptr, {"t", "o(b)"}, 0xa4000000, 0xfc000000, // SH .flags = FLAGS_ALU_I_STORE}, - {"SWL", IT_I, ALU_OP_ADDU, AC_WORD_LEFT, nullptr, // SWL + {"SWL", IT_I, ALU_OP_ADDU, AC_WORD_LEFT, nullptr, {"t", "o(b)"}, 0xa8000000, 0xfc000000, // SWL .flags = FLAGS_ALU_I_STORE}, - {"SW", IT_I, ALU_OP_ADDU, AC_WORD, nullptr, // SW + {"SW", IT_I, ALU_OP_ADDU, AC_WORD, nullptr, {"t", "o(b)"}, 0xac000000, 0xfc000000, // SW .flags = FLAGS_ALU_I_STORE}, IM_UNKNOWN, // 44 IM_UNKNOWN, // 45 - {"SWR", IT_I, ALU_OP_ADDU, AC_WORD_RIGHT, nullptr, // SWR + {"SWR", IT_I, ALU_OP_ADDU, AC_WORD_RIGHT, nullptr, {"t", "o(b)"}, 0xb8000000, 0xfc000000, // SWR .flags = FLAGS_ALU_I_STORE}, - {"CACHE", IT_I, ALU_OP_ADDU, AC_CACHE_OP, nullptr, // CACHE + {"CACHE", IT_I, ALU_OP_ADDU, AC_CACHE_OP, nullptr, {"k", "o(b)"}, 0xbc000000, 0xfc000000, // CACHE .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_MEM}, - {"LL", IT_I, ALU_OP_ADDU, AC_LOAD_LINKED, nullptr, // LL + {"LL", IT_I, ALU_OP_ADDU, AC_LOAD_LINKED, nullptr, {"t", "o(b)"}, 0xc0000000, 0xfc000000, // LL .flags = FLAGS_ALU_I_LOAD}, - {"LWC1", IT_I, NOALU, NOMEM, nullptr, + {"LWC1", IT_I, NOALU, NOMEM, nullptr, {"T", "o(b)"}, 0xc4000000, 0xfc000000, .flags = IMF_SUPPORTED}, IM_UNKNOWN, // 50 - {"PREF", IT_I, NOALU, NOMEM, nullptr, // PREF + {"PREF", IT_I, NOALU, NOMEM, nullptr, {"k", "o(b)"}, 0xcc000000, 0xfc000000, // PREF .flags = IMF_SUPPORTED}, IM_UNKNOWN, // 52 - {"LWD1", IT_I, NOALU, NOMEM, nullptr, + {"LWD1", IT_I, NOALU, NOMEM, nullptr, {"T", "o(b)"}, 0xd4000000, 0xfc000000, .flags = IMF_SUPPORTED}, IM_UNKNOWN, // 54 IM_UNKNOWN, // 55 - {"SC", IT_I, ALU_OP_ADDU, AC_STORE_CONDITIONAL, nullptr, // SW + {"SC", IT_I, ALU_OP_ADDU, AC_STORE_CONDITIONAL, nullptr, {"t", "o(b)"}, 0xe0000000, 0xfc000000, // SW .flags = FLAGS_ALU_I_STORE | IMF_MEMREAD | IMF_REGWRITE}, - {"SWC1", IT_I, NOALU, NOMEM, nullptr, + {"SWC1", IT_I, NOALU, NOMEM, nullptr, {"T", "o(b)"}, 0xe4000000, 0xfc000000, .flags = IMF_SUPPORTED}, IM_UNKNOWN, // 58 IM_UNKNOWN, // 59 IM_UNKNOWN, // 60 - {"SDC1", IT_I, NOALU, NOMEM, nullptr, + {"SDC1", IT_I, NOALU, NOMEM, nullptr, {"T", "o(b)"}, 0xf4000000, 0xfc000000, .flags = IMF_SUPPORTED}, IM_UNKNOWN, // 62 IM_UNKNOWN, // 63 @@ -729,11 +817,6 @@ Instruction::Instruction(const Instruction &i) { #define MASK(LEN,OFF) ((this->dt >> (OFF)) & ((1 << (LEN)) - 1)) -#define RS_SHIFT 21 -#define RT_SHIFT 16 -#define RD_SHIFT 11 -#define SHAMT_SHIFT 6 - std::uint8_t Instruction::opcode() const { return (std::uint8_t) MASK(6, 26); } @@ -840,78 +923,53 @@ QString Instruction::to_str(std::int32_t inst_addr) const { // TODO there are exception where some fields are zero and such so we should not print them in such case if (dt == 0) return QString("NOP"); + SANITY_ASSERT(argdesbycode_filled, QString("argdesbycode_filled not initialized")); QString res; QString next_delim = " "; - switch (im.type) { - case T_I: - res += im.name; - if (im.flags & IMF_MEM) { - res += " $" + QString::number(rt()); - res += ", 0x" + QString::number(immediate(), 16).toUpper() + "($" + QString::number(rs()) + ")"; - } else { - if (im.flags & IMF_REGWRITE) { - res += next_delim + "$" + QString::number(rt()); - next_delim = ", "; - } - if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { - res += next_delim + "$" + QString::number(rs()); - next_delim = ", "; - } - if (im.flags & (IMF_BJR_REQ_RT | IMF_ALU_REQ_RT) && !(im.flags & IMF_REGWRITE)) { - res += next_delim + "$" + QString::number(rt()); - next_delim = ", "; - } - if (im.flags & IMF_BRANCH) { - std::uint32_t target = inst_addr + ((int16_t)immediate() << 2) + 4; - res += next_delim + "0x" + QString::number(target, 16).toUpper(); - } else if (im.flags & IMF_ZERO_EXTEND) { - res += next_delim + "0x" + QString::number(immediate(), 16).toUpper(); - } else { - res += next_delim + QString::number((std::int16_t)immediate(), 10).toUpper(); - } - } - break; - case T_J: - res += im.name; - { - std::uint32_t target = (inst_addr & 0xF0000000) | (address() << 2); - res += " 0x" + QString::number(target, 16).toUpper(); - } - break; - case T_R: - { - res += im.name; - if (im.flags & IMF_REGD) { - res += next_delim + "$" + QString::number(rd()); - next_delim = ", "; - } - if (!(im.flags & IMF_ALU_SHIFT)) { - if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { - res += next_delim + "$" + QString::number(rs()); - next_delim = ", "; + if (im.type == T_UNKNOWN) + return QString("UNKNOWN"); + + res += im.name; + foreach (const QString &arg, im.args) { + res += next_delim; + next_delim = ", "; + foreach (QChar ao, arg) { + uint a = ao.toLatin1(); + if (!a) + continue; + const ArgumentDesc *adesc = argdesbycode[a]; + if (adesc == nullptr) { + res += ao; + continue; } - } - if (im.flags & (IMF_BJR_REQ_RT | IMF_ALU_REQ_RT)) { - res += next_delim + "$" + QString::number(rt()); - next_delim = ", "; - } - if (im.flags & IMF_ALU_SHIFT) { - if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { - res += next_delim + "$" + QString::number(rs()); - next_delim = ", "; - } else { - res += next_delim + QString::number(shamt()); - next_delim = ", "; + uint bits = IMF_SUB_GET_BITS(adesc->loc); + uint shift = IMF_SUB_GET_SHIFT(adesc->loc); + std::uint32_t field = MASK(bits, shift); + if ((adesc->min < 0) && (field & (1 << (bits - 1)))) + field -= 1 << bits; + + field <<= adesc->shift; + switch (adesc->kind) { + case 'g': + res += "$" + QString::number(field); + break; + case 'o': + case 'n': + if (adesc->min < 0) + res += QString::number((std::int32_t)field, 10).toUpper(); + else + res += "0x" + QString::number(field, 16).toUpper(); + break; + case 'p': + field += inst_addr + 4; + res += "0x" + QString::number((std::uint32_t)field, 16).toUpper(); + break; + case 'a': + std::uint32_t target = (inst_addr & 0xF0000000) | (address() << 2); + res += " 0x" + QString::number(target, 16).toUpper(); + break; } } - if ((im.flags & IMF_REGWRITE) && !(im.flags & IMF_REGD)) { - res += next_delim + "$" + QString::number(rd()); - next_delim = ", "; - } - break; - } - case T_UNKNOWN: - return QString("UNKNOWN"); } return res; } @@ -939,6 +997,11 @@ void instruction_from_string_build_base(const InstructionMap *im = nullptr, if (!(im->flags & IMF_SUPPORTED)) continue; str_to_instruction_code_map.insert(im->name, code); + #if 0 + if (im->code != code) { + printf("code mitchmatch %s computed 0x%08x found 0x%08x\n", im->name, code, im->code); + } + #endif } #if 0 for (auto i = str_to_instruction_code_map.begin(); @@ -947,24 +1010,25 @@ void instruction_from_string_build_base(const InstructionMap *im = nullptr, #endif } -static int parse_reg_from_string(QString str) +static int parse_reg_from_string(QString str, uint *chars_taken = nullptr) { - bool ok; int res; if (str.count() < 2 || str.at(0) != '$') return -1; - str = str.mid(1, str.count() - 1); - res = str.toULong(&ok, 10); - if (!ok) + const char *p = str.toLatin1().data() + 1; + char *r; + res = std::strtol(p, &r, 0); + if (p == r) return -1; if (res > 31) return -1; + if (chars_taken != nullptr) + *chars_taken = r - p; return res; } -Instruction Instruction::from_string(QString str, bool *pok) { +Instruction Instruction::from_string(QString str, bool *pok, uint32_t inst_addr) { std::uint32_t code; - int val; bool ok = false; if (str_to_instruction_code_map.isEmpty()) @@ -1031,121 +1095,98 @@ Instruction Instruction::from_string(QString str, bool *pok) { const InstructionMap &im = InstructionMapFind(code); field = 0; - switch (im.type) { - case T_I: - if (im.flags & IMF_MEM) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RT_SHIFT; - if (field >= inst_fields.count()) - continue; - int lpar = inst_fields.at(field).indexOf('('); - int rpar = inst_fields.at(field).indexOf(')'); - if (lpar == -1 || rpar == -1) - continue; - if ((val = parse_reg_from_string(inst_fields. - at(field).mid(lpar+1, rpar - lpar - 1))) < 0) - continue; - code |= val << RS_SHIFT; - - val = inst_fields.at(field).mid(0, lpar).toLong(&ok, 0); - if (!ok) + foreach (const QString &arg, im.args) { + if (field >= inst_fields.count()) { + field = -1; + break; + } + QString fl = inst_fields.at(field++); + foreach (QChar ao, arg) { + const char *p; + char *r; + uint a = ao.toLatin1(); + if (!a) continue; - ok = false; - code |= val & 0xffff; - field ++; - } else { - if (im.flags & IMF_REGWRITE) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RT_SHIFT; + fl = fl.trimmed(); + const ArgumentDesc *adesc = argdesbycode[a]; + if (adesc == nullptr) { + if (!fl.count()) { + field = -1; + break; + } + if (fl.at(0) != ao) { + field = -1; + break; + } + continue; } - if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RS_SHIFT; + uint bits = IMF_SUB_GET_BITS(adesc->loc); + uint shift = IMF_SUB_GET_SHIFT(adesc->loc); + std::uint64_t val = 0; + uint chars_taken = 0; + + // if ((adesc->min < 0) && (field & (1 << bits - 1))) + // field -= 1 << bits; + // field <<= adesc->shift; + + switch (adesc->kind) { + case 'g': + val += parse_reg_from_string(fl, &chars_taken); + break; + case 'p': + val -= (inst_addr + 4); + case 'o': + case 'n': + // Qt functions are limited, toLongLong would be usable + // but does not return information how many characters + // are processed. Used solution has horrible overhead + // but is usable for now + p = fl.toLatin1().data(); + if (adesc->min < 0) + val += std::strtoll(p, &r, 0); + else + val += std::strtoull(p, &r, 0); + chars_taken = r - p; + break; + case 'a': + p = fl.toLatin1().data(); + val -= (inst_addr + 4) & 0xf0000000; + val += std::strtoull(p, &r, 0); + chars_taken = r - p; + break; } - if (im.flags & (IMF_BJR_REQ_RT | IMF_ALU_REQ_RT) && !(im.flags & IMF_REGWRITE)) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RT_SHIFT; + if (chars_taken <= 0) { + field = -1; + break; } - if (field >= inst_fields.count()) - continue; - val = inst_fields.at(field++).toLong(&ok, 0); - if (!ok) - continue; - ok = false; - code |= val & 0xffff; - } - break; - case T_J: - if (field >= inst_fields.count()) - continue; - val = inst_fields.at(field++).toLong(&ok, 0); - code |= (val >> 2) & ~0xF0000000; - break; - case T_R: - if (im.flags & IMF_REGD) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RD_SHIFT; - } - if (!(im.flags & IMF_ALU_SHIFT)) { - if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RS_SHIFT; + if (val & ((1 << adesc->shift) - 1)) { + field = -1; + break; } - } - if (im.flags & (IMF_BJR_REQ_RT | IMF_ALU_REQ_RT)) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RT_SHIFT; - } - if (im.flags & IMF_ALU_SHIFT) { - if (im.flags & (IMF_BJR_REQ_RS | IMF_ALU_REQ_RS)) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RS_SHIFT; + if (adesc->min >= 0) + val = (val >> adesc->shift) ; + else + val = (std::uint64_t)((std::int64_t)val >> adesc->shift) ; + if (adesc->min < 0) { + if (((std::int64_t)val < adesc->min) || + ((std::int64_t)val > adesc->max)) { + field = -1; + break; + } } else { - if (field >= inst_fields.count()) - continue; - val = inst_fields.at(field++).toLong(&ok, 0); - if (!ok) - continue; - ok = false; - code |= val << (SHAMT_SHIFT & 0x1f); + if ((val < (std::uint64_t)adesc->min) || + (val > (std::uint64_t)adesc->max)) { + field = -1; + break; + } } + val = (val & ((1 << bits) - 1)) << shift; + code += val; + fl = fl.mid(chars_taken); } - if ((im.flags & IMF_REGWRITE) && !(im.flags & IMF_REGD)) { - if (field >= inst_fields.count()) - continue; - if ((val = parse_reg_from_string(inst_fields.at(field++))) < 0) - continue; - code |= val << RD_SHIFT; - } - break; - case T_UNKNOWN: - break; + if (field == -1) + break; } - if (field != inst_fields.count()) continue; diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index a3bfb79..f86d10c 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -117,7 +117,7 @@ public: QString to_str(std::int32_t inst_addr = 0) const; - static Instruction from_string(QString str, bool *pok = nullptr); + static Instruction from_string(QString str, bool *pok = nullptr, std::uint32_t inst_addr = 0); private: std::uint32_t dt; }; |