diff options
Diffstat (limited to 'qtmips_machine')
| -rw-r--r-- | qtmips_machine/core.cpp | 67 | ||||
| -rw-r--r-- | qtmips_machine/core.h | 5 | ||||
| -rw-r--r-- | qtmips_machine/tests/testcore.cpp | 4 | 
3 files changed, 45 insertions, 31 deletions
| diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 64c309b..187ca2f 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -554,7 +554,7 @@ void Core::writeback(const struct dtMemory &dt) {          regs->write_gp(dt.rwrite, dt.towrite_val);  } -bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) { +bool Core::handle_pc(const struct dtDecode &dt) {      bool branch = false;      emit instruction_program_counter(dt.inst, dt.inst_addr, EXCAUSE_NONE); @@ -593,7 +593,7 @@ bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) {          std::int32_t rel_offset = dt.inst.immediate() << 2;          if (rel_offset & (1 << 17))              rel_offset -= 1 << 18; -        regs->pc_jmp(rel_offset + rel_adj); +        regs->pc_abs_jmp(dt.inst_addr + rel_offset + 4);      } else {          regs->pc_inc();      } @@ -672,57 +672,66 @@ CoreSingle::CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess                         bool jmp_delay_slot, unsigned int min_cache_row_size, Cop0State *cop0state) :      Core(regs, mem_program, mem_data, min_cache_row_size, cop0state) {      if (jmp_delay_slot) -        jmp_delay_decode = new struct Core::dtDecode(); +        dt_f = new struct Core::dtFetch();      else -        jmp_delay_decode = nullptr; +        dt_f = nullptr;      reset();  }  CoreSingle::~CoreSingle() { -    if (jmp_delay_decode != nullptr) -        delete jmp_delay_decode; +    if (dt_f != nullptr) +        delete dt_f;  }  void CoreSingle::do_step(bool skip_break) { -    bool in_delay_slot = false; -    std::uint32_t jump_branch_pc; +    bool branch_taken = false;      struct dtFetch f = fetch(skip_break); +    if (dt_f != nullptr) { +        struct dtFetch f_swap = *dt_f; +        *dt_f = f; +        f = f_swap; +    }      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 + +    if ((m.stop_if || (m.excause != EXCAUSE_NONE)) && dt_f != nullptr) { +        dtFetchInit(*dt_f); +        emit instruction_fetched(dt_f->inst, dt_f->inst_addr, dt_f->excause); +        emit fetch_inst_addr_value(STAGEADDR_NONE);      } else { -        handle_pc(d, 4); -        jump_branch_pc = d.inst_addr; +        branch_taken = handle_pc(d); +        if (dt_f != nullptr) { +            dt_f->in_delay_slot = branch_taken; +            if (d.nb_skip_ds && !branch_taken) { +                // Discard processing of instruction in delay slot +                // for BEQL, BNEL, BLEZL, BGTZL, BLTZL, BGEZL, BLTZALL, BGEZALL +                dtFetchInit(*dt_f); +            } +        }      } -    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); +        if (dt_f != nullptr) { +            regs->pc_abs_jmp(dt_f->inst_addr); +        }          handle_exception(this, regs, m.excause, m.inst_addr, regs->read_pc(), -                         jump_branch_pc, in_delay_slot, m.mem_addr); +                         prev_inst_addr, m.in_delay_slot, m.mem_addr);          return;      } +    prev_inst_addr = m.inst_addr;  }  void CoreSingle::do_reset() { -    if (jmp_delay_decode != nullptr) { -        Core::dtDecodeInit(*jmp_delay_decode); -        jmp_delay_decode->inst_addr = 0; +    if (dt_f != nullptr) { +        Core::dtFetchInit(*dt_f); +        dt_f->inst_addr = 0;      } +    prev_inst_addr = 0;  }  CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index 5658726..6b025db 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -259,7 +259,7 @@ protected:      struct dtExecute execute(const struct dtDecode&);      struct dtMemory memory(const struct dtExecute&);      void writeback(const struct dtMemory&); -    bool handle_pc(const struct dtDecode&, std::int32_t rel_adj = 0); +    bool handle_pc(const struct dtDecode&);      enum ExceptionCause memory_special(enum AccessControl memctl,                             int mode, bool memread, bool memwrite, @@ -298,7 +298,8 @@ protected:      void do_reset();  private: -    struct Core::dtDecode *jmp_delay_decode; +    struct Core::dtFetch *dt_f; +    std::uint32_t prev_inst_addr;  };  class CorePipelined : public Core { diff --git a/qtmips_machine/tests/testcore.cpp b/qtmips_machine/tests/testcore.cpp index 68da14c..7ba185d 100644 --- a/qtmips_machine/tests/testcore.cpp +++ b/qtmips_machine/tests/testcore.cpp @@ -230,7 +230,9 @@ void MachineTests::singlecore_regs() {      CoreSingle core(&init, &mem_used, &mem_used, true);      core.step(); // Single step should be enought as this is risc without pipeline +    core.step(); +    res.pc_inc();      res.pc_inc(); // We did single step	so increment program counter accordingly      QCOMPARE(init, res); // After doing changes from initial state this should be same state as in case of passed expected result      QCOMPARE(mem, mem_used); // There should be no change in memory @@ -444,8 +446,10 @@ void MachineTests::singlecore_mem() {      CoreSingle core(®s_init, &mem_init, &mem_init, true);      core.step(); +    core.step();      regs_res.pc_inc(); +    regs_res.pc_inc();      QCOMPARE(regs_init, regs_res);      QCOMPARE(mem_init, mem_res);  } | 
