From 10aefcbf8e809d86a9d52a61e5795781e42fc676 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 24 Feb 2019 22:27:59 +0100 Subject: Implement ROTR and ROTRV and full decode of WSBH, SEB and SEH. Signed-off-by: Pavel Pisa --- qtmips_machine/alu.cpp | 38 ++++++++++++--------- qtmips_machine/instruction.cpp | 75 +++++++++++++++++++++++++++++++++++++----- qtmips_machine/instruction.h | 2 +- qtmips_machine/machinedefs.h | 7 +++- 4 files changed, 97 insertions(+), 25 deletions(-) diff --git a/qtmips_machine/alu.cpp b/qtmips_machine/alu.cpp index de38c96..83c94bd 100644 --- a/qtmips_machine/alu.cpp +++ b/qtmips_machine/alu.cpp @@ -98,6 +98,7 @@ std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, ExceptionCause &excause) { std::int64_t s64_val; std::uint64_t u64_val; + std::uint32_t u32_val; discard = false; switch(operation) { @@ -107,16 +108,25 @@ std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, return t << sa; case ALU_OP_SRL: return t >> sa; + case ALU_OP_ROTR: + if (!sa) + return t; + return (t >> sa) | (t << (32 - sa)); case ALU_OP_SRA: // Note: This might be broken with some compilers but works with gcc return (std::int32_t)t >> sa; case ALU_OP_SLLV: - return t << s; + return t << (s & 0x1f); case ALU_OP_SRLV: - return t >> s; + return t >> (s & 0x1f); + case ALU_OP_ROTRV: + u32_val = s & 0x1f; + if (!u32_val) + return t; + return (t >> u32_val) | (t << (32 - u32_val)); case ALU_OP_SRAV: // Note: same note as in case of SRA - return (std::int32_t)t >> s; + return (std::int32_t)t >> (s & 0x1f); case ALU_OP_MOVZ: // Signal discard of result when condition is not true discard = t != 0; @@ -228,19 +238,17 @@ std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, return 0; case ALU_OP_LUI: return t << 16; - case ALU_OP_BSHFL: - switch (sa) { - case 0x02: - return ((t << 8) & 0xff00ff00) | ((t >> 8) & 0x00ff00ff); - case 0x10: - return (uint32_t)(int32_t)(int8_t)t; - case 0x18: - return (uint32_t)(int32_t)(int16_t)t; - default: - throw QTMIPS_EXCEPTION(UnsupportedAluOperation, "Unknown BSHFL variant", QString::number(sa, 16)); - } + case ALU_OP_WSBH: + return ((t << 8) & 0xff00ff00) | ((t >> 8) & 0x00ff00ff); + case ALU_OP_SEB: + return (uint32_t)(int32_t)(int8_t)t; + case ALU_OP_SEH: + return (uint32_t)(int32_t)(int16_t)t; case ALU_OP_EXT: - return (s >> sa) & ((1 << sz) - 1); + return (s >> sa) & ((1 << (sz + 1)) - 1); + case ALU_OP_INS: + u32_val = (1 << (sz + 1)) - 1; + return ((s & u32_val) << sa) | (t & ~(u32_val << sa)); case ALU_OP_CLZ: return alu_op_clz(s); case ALU_OP_CLO: diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index d0e0a67..41cfb5c 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -35,6 +35,7 @@ #include #include +#include #include "instruction.h" #include "alu.h" #include "memory.h" @@ -87,20 +88,34 @@ struct InstructionMap { #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, + .flags = FLAGS_ALU_T_R_TD_SHAMT}, + {"ROTR", IT_R, ALU_OP_ROTR, NOMEM, nullptr, + .flags = FLAGS_ALU_T_R_TD_SHAMT}, +}; + +static const struct InstructionMap srlv_rotrv_instruction_map[] = { + {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, nullptr, + .flags = FLAGS_ALU_T_R_STD_SHV}, + {"ROTRV", IT_R, ALU_OP_ROTRV, NOMEM, nullptr, + .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, .flags = FLAGS_ALU_T_R_TD_SHAMT}, IM_UNKNOWN, - {"SRL", IT_R, ALU_OP_SRL, NOMEM, nullptr, - .flags = FLAGS_ALU_T_R_TD_SHAMT}, + {"SRL", IT_R, ALU_OP_SRL, NOMEM, srl_rotr_instruction_map, + .flags = IMF_SUB_ENCODE(1, 21)}, {"SRA", IT_R, ALU_OP_SRA, NOMEM, nullptr, .flags = FLAGS_ALU_T_R_TD_SHAMT}, {"SLLV", IT_R, ALU_OP_SLLV, NOMEM, nullptr, .flags = FLAGS_ALU_T_R_STD_SHV}, IM_UNKNOWN, - {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, nullptr, - .flags = FLAGS_ALU_T_R_STD_SHV}, + {"SRLV", IT_R, ALU_OP_SRLV, NOMEM, srlv_rotrv_instruction_map, + .flags = IMF_SUB_ENCODE(1, 6)}, {"SRAV", IT_R, ALU_OP_SRAV, NOMEM, nullptr, .flags = FLAGS_ALU_T_R_STD_SHV}, {"JR", IT_R, ALU_OP_NOP, NOMEM, nullptr, @@ -195,7 +210,7 @@ static const struct InstructionMap alu_instruction_map[] = { static const struct InstructionMap special2_instruction_map[] = { {"MADD", IT_R, ALU_OP_MADD, NOMEM, nullptr, .flags = FLAGS_ALU_T_R_ST | IMF_READ_HILO | IMF_WRITE_HILO}, - {"MADD", IT_R, ALU_OP_MADDU, NOMEM, nullptr, + {"MADDU", IT_R, ALU_OP_MADDU, NOMEM, nullptr, .flags = FLAGS_ALU_T_R_ST | IMF_READ_HILO | IMF_WRITE_HILO}, {"MUL", IT_R, ALU_OP_MUL, NOMEM, nullptr, .flags = FLAGS_ALU_T_R_STD}, // 32 @@ -266,13 +281,52 @@ static const struct InstructionMap special2_instruction_map[] = { IM_UNKNOWN, // 63 }; +static const struct InstructionMap bshfl_instruction_map[] = { + IM_UNKNOWN, // 0 + IM_UNKNOWN, // 1 + {"WSBH", IT_R, ALU_OP_WSBH, NOMEM, nullptr, + .flags = FLAGS_ALU_T_R_TD}, + IM_UNKNOWN, // 3 + IM_UNKNOWN, // 4 + IM_UNKNOWN, // 5 + IM_UNKNOWN, // 6 + IM_UNKNOWN, // 7 + IM_UNKNOWN, // 8 + IM_UNKNOWN, // 9 + IM_UNKNOWN, // 10 + IM_UNKNOWN, // 11 + IM_UNKNOWN, // 12 + IM_UNKNOWN, // 13 + IM_UNKNOWN, // 14 + IM_UNKNOWN, // 15 + {"SEB", IT_R, ALU_OP_SEB, NOMEM, nullptr, + .flags = FLAGS_ALU_T_R_TD}, + IM_UNKNOWN, // 17 + IM_UNKNOWN, // 18 + IM_UNKNOWN, // 19 + IM_UNKNOWN, // 20 + IM_UNKNOWN, // 21 + IM_UNKNOWN, // 22 + IM_UNKNOWN, // 23 + {"SEH", IT_R, ALU_OP_SEH, NOMEM, nullptr, + .flags = FLAGS_ALU_T_R_TD}, + IM_UNKNOWN, // 25 + IM_UNKNOWN, // 26 + IM_UNKNOWN, // 27 + IM_UNKNOWN, // 28 + IM_UNKNOWN, // 29 + IM_UNKNOWN, // 30 + IM_UNKNOWN, // 31 +}; + static const struct InstructionMap special3_instruction_map[] = { {"EXT", IT_I, ALU_OP_EXT, NOMEM, nullptr, .flags = IMF_SUPPORTED | IMF_REGWRITE | IMF_ALU_REQ_RS}, IM_UNKNOWN, // 1 IM_UNKNOWN, // 2 IM_UNKNOWN, // 3 - IM_UNKNOWN, // 4 + {"INS", IT_I, ALU_OP_EXT, NOMEM, nullptr, + .flags = IMF_SUPPORTED | IMF_REGWRITE | IMF_ALU_REQ_RS | IMF_ALU_REQ_RT}, IM_UNKNOWN, // 5 IM_UNKNOWN, // 6 IM_UNKNOWN, // 7 @@ -300,8 +354,8 @@ static const struct InstructionMap special3_instruction_map[] = { IM_UNKNOWN, // 29 IM_UNKNOWN, // 30 IM_UNKNOWN, // 31 - {"BSHFL", IT_R, ALU_OP_BSHFL, NOMEM, nullptr, - .flags = FLAGS_ALU_T_R_TD}, + {"BSHFL", IT_I, NOALU, NOMEM, bshfl_instruction_map, + .flags = IMF_SUB_ENCODE(5, 6)}, IM_UNKNOWN, // 33 IM_UNKNOWN, // 34 IM_UNKNOWN, // 35 @@ -759,6 +813,11 @@ void instruction_from_string_build_base(const InstructionMap *im = nullptr, continue; str_to_instruction_code_map.insert(im->name, code); } +#if 0 + for (auto i = str_to_instruction_code_map.begin(); + i != str_to_instruction_code_map.end(); i++) + std::cout << i.key().toStdString() << ' '; +#endif } static int parse_reg_from_string(QString str) diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index 0d76eeb..b7ae4bd 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -37,7 +37,7 @@ #define INSTRUCTION_H #include -#include +#include #include "machinedefs.h" diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h index bad585f..f575648 100644 --- a/qtmips_machine/machinedefs.h +++ b/qtmips_machine/machinedefs.h @@ -70,9 +70,11 @@ enum AluOp : std::uint8_t { ALU_OP_NOP, ALU_OP_SLL, ALU_OP_SRL, + ALU_OP_ROTR, ALU_OP_SRA, ALU_OP_SLLV, ALU_OP_SRLV, + ALU_OP_ROTRV, ALU_OP_SRAV, ALU_OP_MOVZ, ALU_OP_MOVN, @@ -106,8 +108,11 @@ enum AluOp : std::uint8_t { ALU_OP_TEQ, ALU_OP_TNE, ALU_OP_LUI, - ALU_OP_BSHFL, + ALU_OP_WSBH, + ALU_OP_SEB, + ALU_OP_SEH, ALU_OP_EXT, + ALU_OP_INS, ALU_OP_CLZ, ALU_OP_CLO, ALU_OP_PASS_T, // Pass t argument without change for JAL -- cgit v1.2.3