From eab6cf4fc5720b330ba89c38e9e6119a8a6fabfa Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Thu, 31 Jan 2019 11:02:03 +0100 Subject: Initial support for JAL. The JR, BEQ, BNE are most probably incorrect still. There is missing forwarding for pipelined execution. Signed-off-by: Pavel Pisa --- qtmips_gui/coreview.cpp | 2 ++ qtmips_machine/alu.cpp | 2 ++ qtmips_machine/alu.h | 5 +++-- qtmips_machine/core.cpp | 17 +++++++++++++---- qtmips_machine/core.h | 3 +++ 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 -- cgit v1.2.3