aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_machine/core.cpp24
-rw-r--r--qtmips_machine/core.h1
-rw-r--r--qtmips_machine/instruction.cpp28
-rw-r--r--qtmips_machine/instruction.h3
4 files changed, 39 insertions, 17 deletions
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp
index 2d33309..9312a69 100644
--- a/qtmips_machine/core.cpp
+++ b/qtmips_machine/core.cpp
@@ -189,6 +189,7 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) {
.jump = flags & IMF_JUMP,
.bj_not = flags & IMF_BJ_NOT,
.bgt_blez = flags & IMF_BGTZ_BLEZ,
+ .nb_skip_ds = flags & IMF_NB_SKIP_DS,
.forward_m_d_rs = false,
.forward_m_d_rt = false,
.aluop = alu_op,
@@ -366,6 +367,10 @@ void Core::dtDecodeInit(struct dtDecode &dt) {
dt.regwrite = false;
dt.bjr_req_rs = false; // requires rs for beq, bne, blez, bgtz, jr nad jalr
dt.bjr_req_rt = false; // requires rt for beq, bne
+ dt.jump = false;
+ dt.bj_not = false;
+ dt.bgt_blez = false;
+ dt.nb_skip_ds = false;
dt.forward_m_d_rs = false;
dt.forward_m_d_rt = false;
dt.aluop = ALU_OP_SLL;
@@ -423,17 +428,24 @@ void CoreSingle::do_step() {
struct dtFetch f = fetch();
struct dtDecode d = decode(f);
- struct dtExecute e = execute(d);
- struct dtMemory m = memory(e);
- writeback(m);
+ // Handle PC before instruction following jump leaves decode stage
if (jmp_delay_decode != nullptr) {
in_delay_slot = handle_pc(*jmp_delay_decode);
+ if (jmp_delay_decode->nb_skip_ds && !in_delay_slot) {
+ // Discard processing of instruction in delay slot
+ // for BEQL, BNEL, BLEZL, BGTZL, BLTZL, BGEZL, BLTZALL, BGEZALL
+ dtDecodeInit(d);
+ }
jump_branch_pc = jmp_delay_decode->inst_addr;
*jmp_delay_decode = d; // Copy current decode
} else
handle_pc(d);
+ struct dtExecute e = execute(d);
+ struct dtMemory m = memory(e);
+ writeback(m);
+
if (m.excause != EXCAUSE_NONE) {
if (jmp_delay_decode != nullptr)
dtDecodeInit(*jmp_delay_decode);
@@ -575,8 +587,12 @@ void CorePipelined::do_step() {
// Now process program counter (loop connections from decode stage)
if (!stall) {
dt_f = fetch();
- if (handle_pc(dt_d))
+ if (handle_pc(dt_d)) {
dt_f.in_delay_slot = true;
+ } else {
+ if (dt_d.nb_skip_ds)
+ dtFetchInit(dt_f);
+ }
} else {
// Run fetch stage on empty
fetch();
diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h
index fa0d368..8f3acec 100644
--- a/qtmips_machine/core.h
+++ b/qtmips_machine/core.h
@@ -177,6 +177,7 @@ protected:
bool jump; // jump
bool bj_not; // negate branch condition
bool bgt_blez; // BGTZ/BLEZ instead of BGEZ/BLTZ
+ bool nb_skip_ds; // Skip delay slot if branch is not taken
bool forward_m_d_rs; // forwarding required for beq, bne, blez, bgtz, jr nad jalr
bool forward_m_d_rt; // forwarding required for beq, bne
enum AluOp aluop; // Decoded ALU operation
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp
index d72dc7d..3fb8839 100644
--- a/qtmips_machine/instruction.cpp
+++ b/qtmips_machine/instruction.cpp
@@ -235,9 +235,9 @@ static const struct InstructionMap regimm_instruction_map[] = {
{"BGEZ", IT_I, NOALU, NOMEM, nullptr, // BGEZ
.flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_BJ_NOT},
{"BLTZL", IT_I, NOALU, NOMEM, nullptr, // BLTZL
- .flags = IMF_BJR_REQ_RS},
+ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS},
{"BGEZL", IT_I, NOALU, NOMEM, nullptr, // BGEZL
- .flags = IMF_BJR_REQ_RS | IMF_BJ_NOT},
+ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BJ_NOT},
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
@@ -256,14 +256,14 @@ static const struct InstructionMap regimm_instruction_map[] = {
{"TNEI", IT_I, NOALU, NOMEM, nullptr, // TNEI
.flags = IMF_BJR_REQ_RS},
IM_UNKNOWN,
- {"BLTZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BLTZAL
+ {"BLTZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BLTZAL
.flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH},
- {"BGEZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BGEZAL
+ {"BGEZAL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BGEZAL
.flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_BJ_NOT},
- {"BLTZALL", IT_I, NOALU, NOMEM, nullptr, // BLTZALL
- .flags = IMF_BJR_REQ_RS},
- {"BGEZALL", IT_I, NOALU, NOMEM, nullptr, // BGEZALL
- .flags = IMF_BJR_REQ_RS | IMF_BJ_NOT},
+ {"BLTZALL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BLTZALL
+ .flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS },
+ {"BGEZALL", IT_I, ALU_OP_PASS_T, NOMEM, nullptr, // BGEZALL
+ .flags = FLAGS_J_B_PC_TO_R31 | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BJ_NOT},
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
@@ -319,10 +319,14 @@ static const struct InstructionMap instruction_map[] = {
IM_UNKNOWN, // 17
IM_UNKNOWN, // 18
IM_UNKNOWN, // 19
- IM_UNKNOWN, // 20
- IM_UNKNOWN, // 21
- IM_UNKNOWN, // 22
- IM_UNKNOWN, // 23
+ {"BEQL", IT_I, NOALU, NOMEM, nullptr, // BEQL
+ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT | IMF_BRANCH | IMF_NB_SKIP_DS},
+ {"BNEL", IT_I, NOALU, NOMEM, nullptr, // BNEL
+ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BJR_REQ_RT | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BJ_NOT},
+ {"BLEZL", IT_I, NOALU, NOMEM, nullptr, // BLEZL
+ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BGTZ_BLEZ},
+ {"BGTZL", IT_I, NOALU, NOMEM, nullptr, // BGTZL
+ .flags = IMF_SUPPORTED | IMF_BJR_REQ_RS | IMF_BRANCH | IMF_NB_SKIP_DS | IMF_BGTZ_BLEZ | IMF_BJ_NOT},
IM_UNKNOWN, // 24
IM_UNKNOWN, // 25
IM_UNKNOWN, // 26
diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h
index e896ace..d8b9d00 100644
--- a/qtmips_machine/instruction.h
+++ b/qtmips_machine/instruction.h
@@ -67,7 +67,8 @@ enum InstructionFlags {
IMF_JUMP = 1L<<19,
IMF_BJ_NOT = 1L<<20,
IMF_BGTZ_BLEZ = 1L<<21,
- IMF_EXCEPTION = 1L<<22,
+ IMF_NB_SKIP_DS = 1L<<22, // Skip instruction in delay slot if branch not taken
+ IMF_EXCEPTION = 1L<<23,
};
class Instruction {