diff options
Diffstat (limited to 'qtmips_machine/instruction.cpp')
-rw-r--r-- | qtmips_machine/instruction.cpp | 202 |
1 files changed, 133 insertions, 69 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index 5743c69..9a7b9c9 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -35,43 +35,73 @@ #include "instruction.h" #include "alu.h" +#include "memory.h" #include "qtmipsexception.h" using namespace machine; -#define IMF_NO_RS (1<<0) // This instruction doesn't have rs field -#define IMF_MEM (1<<1) // This instruction is memory access instruction +#define FLAGS_ALU_I (IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE) +#define FLAGS_ALU_I_ZE (IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_ZERO_EXTEND) + +#define FLAGS_ALU_T_R (IMF_SUPPORTED | IMF_REGD | IMF_REGWRITE) +#define FLAGS_ALU_T_R_STD (IMF_SUPPORTED | IMF_REGD | IMF_REGWRITE \ + | IMF_ALU_REQ_RS | IMF_ALU_REQ_RT) +#define FLAGS_ALU_T_R_ST (IMF_SUPPORTED | IMF_ALU_REQ_RS | IMF_ALU_REQ_RT) +#define FLAGS_ALU_T_R_S (IMF_SUPPORTED | IMF_ALU_REQ_RS) +#define FLAGS_ALU_T_R_D (IMF_SUPPORTED | IMF_REGD | IMF_REGWRITE ) +#define FLAGS_ALU_T_R_SD (IMF_SUPPORTED | IMF_REGD | IMF_REGWRITE | IMF_ALU_REQ_RS) + +#define NOALU .alu = ALU_OP_SLL +#define NOMEM .mem_ctl = AC_NONE + +#define IM_UNKNOWN {"UNKNOWN", Instruction::T_UNKNOWN, NOALU, NOMEM, .flags = 0} struct InstructionMap { const char *name; enum Instruction::Type type; - bool is_store; - unsigned flags; + enum AluOp alu; + enum AccessControl mem_ctl; + unsigned int flags; }; #define IT_R Instruction::T_R #define IT_I Instruction::T_I #define IT_J Instruction::T_J -#define IM_UNKNOWN {"UNKNOWN", Instruction::T_UNKNOWN, false, .flags = 0} // This table is indexed by opcode static const struct InstructionMap instruction_map[] = { - {"ALU", IT_R, false, .flags = 0}, // Alu operations - {"REGIMM", IT_I, false, .flags = 0}, // REGIMM (BLTZ, BGEZ) - {"J", IT_J, false, .flags = 0}, - {"JAL", IT_J, false, .flags = 0}, - {"BEQ", IT_I, false, .flags = 0}, - {"BNE", IT_I, false, .flags = 0}, - {"BLEZ", IT_I, false, .flags = 0}, - {"BGTZ", IT_I, false, .flags = 0}, - {"ADDI", IT_I, false, .flags = 0}, - {"ADDIU", IT_I, false, .flags = 0}, - {"SLTI", IT_I, false, .flags = 0}, - {"SLTIU", IT_I, false, .flags = 0}, - {"ANDI", IT_I, false, .flags = 0}, - {"ORI", IT_I, false, .flags = 0}, - {"XORI", IT_I, false, .flags = 0}, - {"LUI", IT_I, false, .flags = IMF_NO_RS}, + {"ALU", IT_R, NOALU, NOMEM, // Alu operations + .flags = 0}, + {"REGIMM", IT_I, NOALU, NOMEM, // REGIMM (BLTZ, BGEZ) + .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS}, + {"J", IT_J, NOALU, NOMEM, // J + .flags = IMF_SUPPORTED}, + {"JAL", IT_J, ALU_OP_PASS_S, NOMEM, // JAL + .flags = IMF_SUPPORTED | IMF_PC_TO_R31 | IMF_REGWRITE}, + {"BEQ", IT_I, NOALU, NOMEM, // BEQ + .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT}, + {"BNE", IT_I, NOALU, NOMEM, // BNE + .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT}, + {"BLEZ", IT_I, NOALU, NOMEM, // BLEZ + .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS}, + {"BGTZ", IT_I, NOALU, NOMEM, // BGTZ + .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS}, + {"ADDI", IT_I, ALU_OP_ADD, NOMEM, // ADDI + .flags = FLAGS_ALU_I}, + {"ADDIU", IT_I, ALU_OP_ADDU, NOMEM, // ADDIU + .flags = FLAGS_ALU_I}, + {"SLTI", IT_I, ALU_OP_SLT, NOMEM, // SLTI + .flags = FLAGS_ALU_I}, + {"SLTIU", IT_I, ALU_OP_SLTU, NOMEM, // SLTIU + .flags = FLAGS_ALU_I}, + {"ANDI", IT_I, ALU_OP_AND, NOMEM, // ANDI + .flags = FLAGS_ALU_I_ZE}, + {"ORI", IT_I, ALU_OP_OR, NOMEM, // ORI + .flags = FLAGS_ALU_I_ZE}, + {"XORI", IT_I, ALU_OP_XOR, NOMEM, // XORI + .flags = FLAGS_ALU_I_ZE}, + {"LUI", IT_I, ALU_OP_LUI, NOMEM, // LUI + .flags = FLAGS_ALU_I}, IM_UNKNOWN, // 16 IM_UNKNOWN, // 17 IM_UNKNOWN, // 18 @@ -88,22 +118,35 @@ static const struct InstructionMap instruction_map[] = { IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 IM_UNKNOWN, // 31 - {"LB", IT_I, false, .flags = IMF_MEM}, - {"LH", IT_I, false, .flags = IMF_MEM}, - {"LWL", IT_I, false, .flags = IMF_MEM}, - {"LW", IT_I, false, .flags = IMF_MEM}, - {"LBU", IT_I, false, .flags = IMF_MEM}, - {"LHU", IT_I, false, .flags = IMF_MEM}, - {"LWR", IT_I, false, .flags = IMF_MEM}, + {"LB", IT_I, ALU_OP_ADDU, AC_BYTE, // LB + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_MEMREAD | IMF_MEM}, + {"LH", IT_I, ALU_OP_ADDU, AC_HALFWORD, // LH + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_MEMREAD | IMF_MEM}, + {"LWL", IT_I, ALU_OP_ADDU, NOMEM, // LWL - unsupported + .flags = IMF_MEM}, + {"LW", IT_I, ALU_OP_ADDU, AC_WORD, // LW + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_MEMREAD | IMF_MEM}, + {"LBU", IT_I, ALU_OP_ADDU, AC_BYTE_UNSIGNED, // LBU + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_MEMREAD | IMF_MEM }, + {"LHU", IT_I, ALU_OP_ADDU, AC_HALFWORD_UNSIGNED, // LHU + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_MEMREAD | IMF_MEM,}, + {"LWR", IT_I, ALU_OP_ADDU, NOMEM, // LWR - unsupported + .flags = IMF_MEM}, IM_UNKNOWN, // 39 - {"SB", IT_I, true, .flags = IMF_MEM}, - {"SH", IT_I, true, .flags = IMF_MEM}, - {"SWL", IT_I, true, .flags = IMF_MEM}, - {"SW", IT_I, true, .flags = IMF_MEM}, - IM_UNKNOWN, // 44 - IM_UNKNOWN, // 45 - {"SWR", IT_I, true, .flags = IMF_MEM}, - {"CACHE", IT_I, true, .flags = IMF_MEM}, // 47 + {"SB", IT_I, ALU_OP_ADDU, AC_BYTE, // SB + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_MEMWRITE | IMF_MEM | IMF_MEM_STORE}, + {"SH", IT_I, ALU_OP_ADDU, AC_HALFWORD, // SH + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_MEMWRITE | IMF_MEM | IMF_MEM_STORE}, + {"SWL", IT_I, ALU_OP_ADDU, NOMEM, // SWL + .flags = IMF_MEM | IMF_MEM_STORE}, + {"SW", IT_I, ALU_OP_ADDU, AC_WORD, // SW + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_MEMWRITE | IMF_MEM | IMF_MEM_STORE}, + IM_UNKNOWN, // 44,NOPE, // 44 + IM_UNKNOWN, // 45,NOPE, // 45 + {"SWR", IT_I, ALU_OP_ADDU, NOMEM, // SWR + .flags = IMF_MEM | IMF_MEM_STORE}, + {"CACHE", IT_I, ALU_OP_ADDU, AC_CACHE_OP, // CACHE + .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_MEM| IMF_MEM_STORE}, IM_UNKNOWN, // 48 IM_UNKNOWN, // 49 IM_UNKNOWN, // 50 @@ -118,63 +161,63 @@ static const struct InstructionMap instruction_map[] = { IM_UNKNOWN, // 59 IM_UNKNOWN, // 60 IM_UNKNOWN, // 61 - IM_UNKNOWN, // 61 IM_UNKNOWN, // 62 - IM_UNKNOWN // 63 + IM_UNKNOWN, // 63 }; #undef IM_UNKNOWN struct AluInstructionMap { const char *name; + unsigned int flags; }; #define AIM_UNKNOWN {"UNKNOWN"} // This table is indexed by funct static const struct AluInstructionMap alu_instruction_map[] = { - {"SLL"}, + {"SLL", FLAGS_ALU_T_R_STD}, AIM_UNKNOWN, - {"SRL"}, - {"SRA"}, - {"SLLV"}, + {"SRL", FLAGS_ALU_T_R_SD}, + {"SRA", FLAGS_ALU_T_R_SD}, + {"SLLV", FLAGS_ALU_T_R_STD}, AIM_UNKNOWN, - {"SRLV"}, - {"SRAV"}, - {"JR"}, - {"JALR"}, - {"MOVZ"}, - {"MOVN"}, + {"SRLV", FLAGS_ALU_T_R_STD}, + {"SRAV", FLAGS_ALU_T_R_STD}, + {"JR", FLAGS_ALU_T_R_S}, + {"JALR", FLAGS_ALU_T_R_SD}, + {"MOVZ", FLAGS_ALU_T_R_STD}, + {"MOVN", FLAGS_ALU_T_R_STD}, AIM_UNKNOWN, - {"BREAK"}, + {"BREAK", IMF_SUPPORTED}, AIM_UNKNOWN, AIM_UNKNOWN, - {"MFHI"}, - {"MTHI"}, - {"MFLO"}, - {"MTLO"}, + {"MFHI", FLAGS_ALU_T_R_D | IMF_READ_HILO}, + {"MTHI", FLAGS_ALU_T_R_S | IMF_WRITE_HILO}, + {"MFLO", FLAGS_ALU_T_R_D | IMF_READ_HILO}, + {"MTLO", FLAGS_ALU_T_R_S | IMF_WRITE_HILO}, AIM_UNKNOWN, AIM_UNKNOWN, AIM_UNKNOWN, AIM_UNKNOWN, - {"MULT"}, // 24 - {"MULTU"}, // 25 - {"DIV"}, // 26 - {"DIVU"}, // 27 + {"MULT", FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 24 + {"MULTU", FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 25 + {"DIV", FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 26 + {"DIVU", FLAGS_ALU_T_R_ST | IMF_WRITE_HILO}, // 27 AIM_UNKNOWN, // 28 AIM_UNKNOWN, // 29 AIM_UNKNOWN, // 30 AIM_UNKNOWN, // 31 - {"ADD"}, // 32 - {"ADDU"}, - {"SUB"}, - {"SUBU"}, - {"AND"}, - {"OR"}, - {"XOR"}, - {"NOR"}, + {"ADD", FLAGS_ALU_T_R_STD}, // 32 + {"ADDU", FLAGS_ALU_T_R_STD}, + {"SUB", FLAGS_ALU_T_R_STD}, + {"SUBU", FLAGS_ALU_T_R_STD}, + {"AND", FLAGS_ALU_T_R_STD}, + {"OR", FLAGS_ALU_T_R_STD}, + {"XOR", FLAGS_ALU_T_R_STD}, + {"NOR", FLAGS_ALU_T_R_STD}, AIM_UNKNOWN, AIM_UNKNOWN, - {"SLT"}, - {"SLTU"} + {"SLT", FLAGS_ALU_T_R_STD}, + {"SLTU", FLAGS_ALU_T_R_STD} }; #undef AIM_UNKNOWN @@ -260,11 +303,33 @@ enum Instruction::Type Instruction::type() const { return im.type; } +enum InstructionFlags Instruction::flags() const { + if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) + return (enum InstructionFlags)0; + if (opcode() == 0) { + return (enum InstructionFlags)alu_instruction_map[funct()].flags; + } + const struct InstructionMap &im = instruction_map[opcode()]; + return (enum InstructionFlags)im.flags; +} +enum AluOp Instruction::alu_op() const { + if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) + return ALU_OP_UNKNOWN; + const struct InstructionMap &im = instruction_map[opcode()]; + return im.alu; +} +enum AccessControl Instruction::mem_ctl() const { + if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) + return AC_NONE; + const struct InstructionMap &im = instruction_map[opcode()]; + return im.mem_ctl; +} + bool Instruction::is_store() const { if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) return false; const struct InstructionMap &im = instruction_map[opcode()]; - return im.is_store; + return im.flags & IMF_MEM_STORE; } bool Instruction::is_break() const { @@ -285,7 +350,6 @@ Instruction &Instruction::operator=(const Instruction &c) { return *this; } - QString Instruction::to_str() const { // TODO there are exception where some fields are zero and such so we should not print them in such case if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) |