aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-03-05 21:25:24 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-03-05 21:25:24 +0100
commit576c4381be6980f95d63ea91f8737dfc22fa8dbe (patch)
tree23fc5f9b613babae0c89e4e726649e12317796dd /qtmips_machine
parent675ede8c34671415bc423e6360ffe0de12d49ec8 (diff)
downloadqtmips-576c4381be6980f95d63ea91f8737dfc22fa8dbe.tar.gz
qtmips-576c4381be6980f95d63ea91f8737dfc22fa8dbe.tar.bz2
qtmips-576c4381be6980f95d63ea91f8737dfc22fa8dbe.zip
Complete revamp of disassembler and assembler arguments processing.
Instructions description in instruction.cpp has been pragmatically augmented by tool based on Python MIPS simulator, hazards analyzer https://github.com/ppisa/apo-simarch That code has been originally distilled from from GNU binutils sources. Implementation is now inline with my original proposal Previous solution gets untenable with more complex instructions and its complexity would grow extremely. MIPS instruction set with coprocessor instructions which use sel field, rd used as index, rt as destination and other peculiarities in newer versions cannot be processed based on basic CPU control signals. Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/instruction.cpp689
-rw-r--r--qtmips_machine/instruction.h2
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;
};