SuperH: Additional delay slot bug fixes

Review of all delay slot instructions.
SuperH: Delay slot fix for bf/s and and bt/s
Code now caches the value of the $(T_FLAG) before executing the delay slot. Previously the instruction executed in delay slot could potentially change the value of $(T_FLAG) and thereby resulting in incorrect behavior. Credit to Slinga and Waterfuell from SegaXtreme for reporting the issue.
This commit is contained in:
VGKintsugi
2021-05-17 15:49:53 -04:00
committed by ghidorahrex
parent b9e67994b1
commit fc91a10673

View File

@@ -1653,8 +1653,9 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 {
@if (SH_VERSION == "2") || (SH_VERSION == "2A") @if (SH_VERSION == "2") || (SH_VERSION == "2A")
:bf"/s" target00_07 is opcode_08_15=0b10001111 & target00_07 :bf"/s" target00_07 is opcode_08_15=0b10001111 & target00_07
{ {
local cond = $(T_FLAG);
delayslot(1); delayslot(1);
if ($(T_FLAG)==0) goto target00_07; if (cond==0) goto target00_07;
} }
@endif @endif
@@ -1666,8 +1667,9 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 {
@if (SH_VERSION == "2") || (SH_VERSION == "2A") @if (SH_VERSION == "2") || (SH_VERSION == "2A")
:bt"/s" target00_07 is opcode_08_15=0b10001101 & target00_07 :bt"/s" target00_07 is opcode_08_15=0b10001101 & target00_07
{ {
local cond = $(T_FLAG);
delayslot(1); delayslot(1);
if ($(T_FLAG)==1) goto target00_07; if (cond==1) goto target00_07;
} }
@endif @endif
@@ -1680,47 +1682,61 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 {
@if (SH_VERSION == "2") || (SH_VERSION == "2A") @if (SH_VERSION == "2") || (SH_VERSION == "2A")
:braf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00100011 :braf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00100011
{ {
local temp:4 = inst_start + 4 + rm_08_11; local dest:4 = inst_start + 4 + rm_08_11;
delayslot(1); delayslot(1);
goto [temp]; goto [dest];
} }
@endif @endif
:bsr target00_11 is opcode_12_15=0b1011 & target00_11 :bsr target00_11 is opcode_12_15=0b1011 & target00_11
{ {
pr = inst_next; local _pr:4 = inst_next;
delayslot(1); delayslot(1);
pr = _pr;
call target00_11; call target00_11;
} }
@if (SH_VERSION == "2") || (SH_VERSION == "2A") @if (SH_VERSION == "2") || (SH_VERSION == "2A")
:bsrf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00000011 :bsrf rm_08_11 is opcode_12_15=0b0000 & rm_08_11 & opcode_00_07=0b00000011
{ {
pr = inst_next; local _pr = inst_next;
local dest = rm_08_11 + inst_next; local dest = rm_08_11 + inst_next;
delayslot(1); delayslot(1);
pr = _pr;
call [dest]; call [dest];
} }
@endif @endif
:jmp @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00101011 :jmp @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00101011
{ {
local _pc:4 = rm_08_11;
delayslot(1); delayslot(1);
goto [rm_08_11]; pc = _pc;
goto [pc];
} }
:jsr @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00001011 :jsr @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00001011
{ {
pr = inst_next; local _pr:4 = inst_next;
local _pc:4 = rm_08_11;
delayslot(1); delayslot(1);
call [rm_08_11];
pr = _pr;
pc = _pc;
call [_pc];
} }
:rts is opcode_00_15=0b0000000000001011 :rts is opcode_00_15=0b0000000000001011
{ {
local _pc = pr;
delayslot(1); delayslot(1);
return [pr]; pc = _pc;
return [pc];
} }
@if SH_VERSION == "2A" @if SH_VERSION == "2A"