aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_gui/coreview.cpp2
-rw-r--r--qtmips_machine/alu.cpp2
-rw-r--r--qtmips_machine/alu.h5
-rw-r--r--qtmips_machine/core.cpp17
-rw-r--r--qtmips_machine/core.h3
5 files changed, 23 insertions, 6 deletions
diff --git a/qtmips_gui/coreview.cpp b/qtmips_gui/coreview.cpp
index 897f92e..71c8113 100644
--- a/qtmips_gui/coreview.cpp
+++ b/qtmips_gui/coreview.cpp
@@ -98,6 +98,7 @@ CoreViewScene::CoreViewScene(machine::QtMipsMachine *machine) : QGraphicsScene()
con->setAxes({CON_AXIS_Y(710), CON_AXIS_X(510), CON_AXIS_Y(172)});
// Control unit labels
+ new_label("JalPcToR31", 300, 92);
new_label("MemToReg", 300, 106);
new_label("MemWrite", 300, 112);
new_label("MemRead", 300, 119);
@@ -114,6 +115,7 @@ CoreViewScene::CoreViewScene(machine::QtMipsMachine *machine) : QGraphicsScene()
NEW_V(360, 250, decode_reg1_value); // Register output 1
NEW_V(360, 270, decode_reg2_value); // Register output 2
NEW_V(335, 415, decode_immediate_value); // Sign extended immediate value
+ NEW_V(370, 99, decode_regd31_value, false, 1);
NEW_V(370, 113, decode_memtoreg_value, false, 1);
NEW_V(360, 120, decode_memwrite_value, false, 1);
NEW_V(370, 127, decode_memread_value, false, 1);
diff --git a/qtmips_machine/alu.cpp b/qtmips_machine/alu.cpp
index 2e36d4c..36b1ac7 100644
--- a/qtmips_machine/alu.cpp
+++ b/qtmips_machine/alu.cpp
@@ -71,6 +71,8 @@ std::uint32_t machine::alu_operate(enum AluOp operation, std::uint32_t s, std::u
return (s < t) ? 1 : 0;
case ALU_OP_LUI:
return t << 16;
+ case ALU_OP_PASS_S: // Pass s argument without change for JAL
+ return s;
default:
throw QTMIPS_EXCEPTION(UnsupportedAluOperation, "Unknown ALU operation", QString::number(operation, 16));
}
diff --git a/qtmips_machine/alu.h b/qtmips_machine/alu.h
index 786bba0..f0ce6c2 100644
--- a/qtmips_machine/alu.h
+++ b/qtmips_machine/alu.h
@@ -33,8 +33,9 @@ enum AluOp : std::uint8_t {
ALU_OP_NOR,
ALU_OP_SLT = 42,
ALU_OP_SLTU,
- ALU_OP_LUI, // We don't care about exact index for this one
- ALU_OP_LAST = 64 // First impossible operation (just to be sure that we don't overflow)
+ ALU_OP_LUI = 64, // We don't care about exact index for this one
+ ALU_OP_PASS_S, // Pass s argument without change for JAL
+ ALU_OP_LAST // First impossible operation (just to be sure that we don't overflow)
};
// Do ALU operation.
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp
index f6f0cdd..6443be1 100644
--- a/qtmips_machine/core.cpp
+++ b/qtmips_machine/core.cpp
@@ -11,6 +11,7 @@ using namespace machine;
#define DM_REGD (1L<<4)
#define DM_REGWRITE (1L<<5)
#define DM_ZERO_EXTEND (1L<<6)
+#define DM_PC_TO_R31 (1L<<7)
struct DecodeMap {
long flags;
@@ -30,7 +31,7 @@ static const struct DecodeMap dmap[] = {
{ .flags = DM_SUPPORTED | DM_REGD | DM_REGWRITE, NOALU, NOMEM }, // Alu operations (aluop is decoded from function explicitly)
{ .flags = DM_SUPPORTED, NOALU, NOMEM }, // REGIMM (BLTZ, BGEZ)
{ .flags = DM_SUPPORTED, NOALU, NOMEM }, // J
- NOPE, // JAL
+ { .flags = DM_SUPPORTED | DM_PC_TO_R31 | DM_REGWRITE, .alu = ALU_OP_PASS_S, NOMEM }, // JAL
{ .flags = DM_SUPPORTED, NOALU, NOMEM }, // BEQ
{ .flags = DM_SUPPORTED, NOALU, NOMEM }, // BNE
{ .flags = DM_SUPPORTED, NOALU, NOMEM }, // BLEZ
@@ -115,10 +116,12 @@ unsigned Core::cycles() {
}
struct Core::dtFetch Core::fetch() {
- Instruction inst(mem_program->read_word(regs->read_pc()));
+ std::uint32_t inst_addr = regs->read_pc();
+ Instruction inst(mem_program->read_word(inst_addr));
emit instruction_fetched(inst);
return {
- .inst = inst
+ .inst = inst,
+ .inst_addr = inst_addr,
};
}
@@ -150,6 +153,11 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) {
emit decode_rs_num_value(dt.inst.rs());
emit decode_rt_num_value(dt.inst.rt());
emit decode_rd_num_value(dt.inst.rd());
+ emit decode_regd31_value((bool)(dec.flags & DM_PC_TO_R31));
+
+ if (dec.flags & DM_PC_TO_R31) {
+ val_rs = dt.inst_addr + 8;
+ }
return {
.inst = dt.inst,
@@ -157,6 +165,7 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) {
.memwrite = dec.flags & DM_MEMWRITE,
.alusrc = dec.flags & DM_ALUSRC,
.regd = dec.flags & DM_REGD,
+ .regd31 = dec.flags & DM_PC_TO_R31,
.regwrite = dec.flags & DM_REGWRITE,
.aluop = dt.inst.opcode() == 0 ? (enum AluOp)dt.inst.funct() : dec.alu,
.memctl = dec.mem_ctl,
@@ -181,7 +190,7 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) {
alu_sec = dt.immediate_val; // Sign or zero extend immediate value
std::uint32_t alu_val = alu_operate(dt.aluop, dt.val_rs, alu_sec, dt.inst.shamt(), regs);
- std::uint8_t rwrite = dt.regd ? dt.inst.rd() : dt.inst.rt();
+ std::uint8_t rwrite = dt.regd31 ? 31: dt.regd ? dt.inst.rd() : dt.inst.rt();
emit execute_alu_value(alu_val);
emit execute_reg1_value(dt.val_rs);
diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h
index 625fe29..66eb1e6 100644
--- a/qtmips_machine/core.h
+++ b/qtmips_machine/core.h
@@ -49,6 +49,7 @@ signals:
void decode_rs_num_value(std::uint32_t);
void decode_rt_num_value(std::uint32_t);
void decode_rd_num_value(std::uint32_t);
+ void decode_regd31_value(std::uint32_t);
void execute_alu_value(std::uint32_t);
void execute_reg1_value(std::uint32_t);
void execute_reg2_value(std::uint32_t);
@@ -83,6 +84,7 @@ protected:
struct dtFetch {
Instruction inst; // Loaded instruction
+ uint32_t inst_addr; // Address of instruction
};
struct dtDecode {
Instruction inst;
@@ -90,6 +92,7 @@ protected:
bool memwrite; // If memory should write input
bool alusrc; // If second value to alu is immediate value (rt used otherwise)
bool regd; // If rd is used (otherwise rt is used for write target)
+ bool regd31; // Use R31 as destionation for JAL
bool regwrite; // If output should be written back to register (which one depends on regd)
enum AluOp aluop; // Decoded ALU operation
enum MemoryAccess::AccessControl memctl; // Decoded memory access type