diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-02-24 23:48:08 +0100 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-02-24 23:48:08 +0100 |
commit | 076d85eaeeeb5ca37cfa6836cb8dd3c5368cf424 (patch) | |
tree | 15143d93287de21d195e029b8e8addf32ef65d3e /qtmips_machine | |
parent | 2b69b415e020901c00ad1699cbd8dedd236442d4 (diff) | |
download | qtmips-076d85eaeeeb5ca37cfa6836cb8dd3c5368cf424.tar.gz qtmips-076d85eaeeeb5ca37cfa6836cb8dd3c5368cf424.tar.bz2 qtmips-076d85eaeeeb5ca37cfa6836cb8dd3c5368cf424.zip |
Correct relative jumps range and adjust it for single core without delay-slot.
Setting bits 16 to 31 to 1 is incorrect, offset is shift
by two so bit 16 can be zero for jumps in range -64k to -128k.
Adjust relative offsets to compute target address same, as if there
is delay slot, for CPU variant without delay slot.
This allows to use same/standard MIPS assembler for mode
without delay slots.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
Diffstat (limited to 'qtmips_machine')
-rw-r--r-- | qtmips_machine/core.cpp | 14 | ||||
-rw-r--r-- | qtmips_machine/core.h | 2 |
2 files changed, 10 insertions, 6 deletions
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 980a736..f290659 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -462,7 +462,7 @@ void Core::writeback(const struct dtMemory &dt) { regs->write_gp(dt.rwrite, dt.towrite_val); } -bool Core::handle_pc(const struct dtDecode &dt) { +bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) { bool branch = false; emit instruction_program_counter(dt.inst, dt.inst_addr, EXCAUSE_NONE); @@ -497,10 +497,14 @@ bool Core::handle_pc(const struct dtDecode &dt) { emit fetch_jump_reg_value(false); emit fetch_branch_value(branch); - if (branch) - regs->pc_jmp((std::int32_t)(((dt.inst.immediate() & 0x8000) ? 0xFFFF0000 : 0) | (dt.inst.immediate() << 2))); - else + if (branch) { + 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); + } else { regs->pc_inc(); + } return branch; } @@ -596,7 +600,7 @@ void CoreSingle::do_step(bool skip_break) { jump_branch_pc = jmp_delay_decode->inst_addr; *jmp_delay_decode = d; // Copy current decode } else { - handle_pc(d); + handle_pc(d, 4); jump_branch_pc = d.inst_addr; } diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index f70a19d..1c44550 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -245,7 +245,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&); + bool handle_pc(const struct dtDecode&, std::int32_t rel_adj = 0); enum ExceptionCause memory_special(enum AccessControl memctl, int mode, bool memread, bool memwrite, |