diff options
-rw-r--r-- | qtmips_machine/core.cpp | 24 | ||||
-rw-r--r-- | qtmips_machine/core.h | 1 | ||||
-rw-r--r-- | qtmips_machine/instruction.cpp | 28 | ||||
-rw-r--r-- | qtmips_machine/instruction.h | 3 |
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 { |