From fc91a1067314cdec0486e33c8255f9aef29c1db7 Mon Sep 17 00:00:00 2001 From: VGKintsugi <7758500+VGKintsugi@users.noreply.github.com> Date: Mon, 17 May 2021 15:49:53 -0400 Subject: [PATCH] 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. --- .../SuperH/data/languages/superh.sinc | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Ghidra/Processors/SuperH/data/languages/superh.sinc b/Ghidra/Processors/SuperH/data/languages/superh.sinc index ee7e5a7c41..12b80e25dd 100644 --- a/Ghidra/Processors/SuperH/data/languages/superh.sinc +++ b/Ghidra/Processors/SuperH/data/languages/superh.sinc @@ -1653,8 +1653,9 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 { @if (SH_VERSION == "2") || (SH_VERSION == "2A") :bf"/s" target00_07 is opcode_08_15=0b10001111 & target00_07 { + local cond = $(T_FLAG); delayslot(1); - if ($(T_FLAG)==0) goto target00_07; + if (cond==0) goto target00_07; } @endif @@ -1666,8 +1667,9 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 { @if (SH_VERSION == "2") || (SH_VERSION == "2A") :bt"/s" target00_07 is opcode_08_15=0b10001101 & target00_07 { + local cond = $(T_FLAG); delayslot(1); - if ($(T_FLAG)==1) goto target00_07; + if (cond==1) goto target00_07; } @endif @@ -1680,47 +1682,61 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 { @if (SH_VERSION == "2") || (SH_VERSION == "2A") :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); - goto [temp]; + goto [dest]; } @endif :bsr target00_11 is opcode_12_15=0b1011 & target00_11 { - pr = inst_next; + local _pr:4 = inst_next; + delayslot(1); + + pr = _pr; call target00_11; } @if (SH_VERSION == "2") || (SH_VERSION == "2A") :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; delayslot(1); + + pr = _pr; call [dest]; } @endif :jmp @rm_08_11 is opcode_12_15=0b0100 & rm_08_11 & opcode_00_07=0b00101011 { + local _pc:4 = rm_08_11; 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 { - pr = inst_next; + local _pr:4 = inst_next; + local _pc:4 = rm_08_11; + delayslot(1); - call [rm_08_11]; + + pr = _pr; + pc = _pc; + call [_pc]; } :rts is opcode_00_15=0b0000000000001011 { + local _pc = pr; delayslot(1); - return [pr]; + pc = _pc; + return [pc]; } @if SH_VERSION == "2A"