aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/core.cpp
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-24 23:48:08 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-24 23:48:08 +0100
commit076d85eaeeeb5ca37cfa6836cb8dd3c5368cf424 (patch)
tree15143d93287de21d195e029b8e8addf32ef65d3e /qtmips_machine/core.cpp
parent2b69b415e020901c00ad1699cbd8dedd236442d4 (diff)
downloadqtmips-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/core.cpp')
-rw-r--r--qtmips_machine/core.cpp14
1 files changed, 9 insertions, 5 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;
}