aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-24 22:27:59 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-24 22:27:59 +0100
commit10aefcbf8e809d86a9d52a61e5795781e42fc676 (patch)
tree8e0341f1d1138185cc5b7f26188020820da2c08a
parent75ff39499dbf285257dabf1258f35f543d713c0a (diff)
downloadqtmips-10aefcbf8e809d86a9d52a61e5795781e42fc676.tar.gz
qtmips-10aefcbf8e809d86a9d52a61e5795781e42fc676.tar.bz2
qtmips-10aefcbf8e809d86a9d52a61e5795781e42fc676.zip
Implement ROTR and ROTRV and full decode of WSBH, SEB and SEH.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_machine/alu.cpp38
-rw-r--r--qtmips_machine/instruction.cpp75
-rw-r--r--qtmips_machine/instruction.h2
-rw-r--r--qtmips_machine/machinedefs.h7
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 <QMultiMap>
#include <QVector>
+#include <iostream>
#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 <QObject>
-#include <qstring.h>
+#include <QString>
#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