From f1fc3a29caca835ec09b3e67257405742ee785a3 Mon Sep 17 00:00:00 2001 From: VGKintsugi <7758500+VGKintsugi@users.noreply.github.com> Date: Thu, 25 Mar 2021 02:08:22 -0400 Subject: [PATCH 1/4] 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. --- Ghidra/Processors/SuperH/data/languages/superh.sinc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Ghidra/Processors/SuperH/data/languages/superh.sinc b/Ghidra/Processors/SuperH/data/languages/superh.sinc index ee7e5a7c41..417d55c8fd 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 From 27ad2f4b8c4faf585199372289a49ee4b2cefaca Mon Sep 17 00:00:00 2001 From: VGKintsugi <7758500+VGKintsugi@users.noreply.github.com> Date: Thu, 25 Mar 2021 02:38:21 -0400 Subject: [PATCH 2/4] SuperH: simplify div1 logic asdf-prime's modifications to div1 instruction. See PR: https://github.com/NationalSecurityAgency/ghidra/pull/2478 --- .../SuperH/data/languages/superh.sinc | 69 +++---------------- 1 file changed, 10 insertions(+), 59 deletions(-) diff --git a/Ghidra/Processors/SuperH/data/languages/superh.sinc b/Ghidra/Processors/SuperH/data/languages/superh.sinc index 417d55c8fd..399a0a76f0 100644 --- a/Ghidra/Processors/SuperH/data/languages/superh.sinc +++ b/Ghidra/Processors/SuperH/data/languages/superh.sinc @@ -1021,74 +1021,25 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 { local tmp1:1; local tmp2:4; local old_q:1; + local old_q_eq_m:1; + local m_eq_q:1; old_q = $(Q_FLAG); $(Q_FLAG) = (0x80000000 & rn_08_11) != 0; tmp2 = rm_04_07; rn_08_11 = rn_08_11 << 1; rn_08_11 = rn_08_11 | zext($(T_FLAG)); + old_q_eq_m = old_q == $(M_FLAG); + m_eq_q = $(M_FLAG) == $(Q_FLAG); - # FIXME: cleaner way to do this?? tmp0 = rn_08_11; + # rn_08_11 = old_q_eq_m ? rn_08_11 - tmp2 : rn_08_11 + tmp2; + rn_08_11 = (sext(old_q_eq_m) & (rn_08_11 - tmp2)) | (sext(~old_q_eq_m) & (rn_08_11 + tmp2)); + # tmp1 = old_q_eq_m ? rn_08_11 > tmp0 : rn_08_11 < tmp0; + tmp1 = (old_q_eq_m & (rn_08_11 > tmp0)) | (~old_q_eq_m & (rn_08_11 <= tmp0)); + # $(Q_FLAG) = m_eq_q ? tmp1 : tmp1 == 0; + $(Q_FLAG) = (m_eq_q & tmp1) | (~m_eq_q & (tmp1 == 0)); - if(old_q == 0 && $(M_FLAG) == 0 && $(Q_FLAG) == 0) goto ; - if(old_q == 0 && $(M_FLAG) == 0 && $(Q_FLAG) == 1) goto ; - if(old_q == 0 && $(M_FLAG) == 1 && $(Q_FLAG) == 0) goto ; - if(old_q == 0 && $(M_FLAG) == 1 && $(Q_FLAG) == 1) goto ; - if(old_q == 1 && $(M_FLAG) == 0 && $(Q_FLAG) == 0) goto ; - if(old_q == 1 && $(M_FLAG) == 0 && $(Q_FLAG) == 1) goto ; - if(old_q == 1 && $(M_FLAG) == 1 && $(Q_FLAG) == 0) goto ; - if(old_q == 1 && $(M_FLAG) == 1 && $(Q_FLAG) == 1) goto ; - - - rn_08_11 = rn_08_11 - tmp2; - tmp1 = rn_08_11 > tmp0; - $(Q_FLAG) = tmp1; - goto ; - - - rn_08_11 = rn_08_11 - tmp2; - tmp1 = rn_08_11 > tmp0; - $(Q_FLAG) = tmp1 == 0; - goto ; - - - rn_08_11 = rn_08_11 + tmp2; - tmp1 = rn_08_11 < tmp0; - $(Q_FLAG) = tmp1 == 0; - goto ; - - - rn_08_11 = rn_08_11 + tmp2; - tmp1 = rn_08_11 < tmp0; - $(Q_FLAG) = tmp1; - goto ; - - - rn_08_11 = rn_08_11 + tmp2; - tmp1 = rn_08_11 < tmp0; - $(Q_FLAG) = tmp1; - goto ; - - - rn_08_11 = rn_08_11 + tmp2; - tmp1 = rn_08_11 < tmp0; - $(Q_FLAG) = tmp1; - goto ; - - - rn_08_11 = rn_08_11 - tmp2; - tmp1 = rn_08_11 > tmp0; - $(Q_FLAG) = tmp1 == 0; - goto ; - - - rn_08_11 = rn_08_11 - tmp2; - tmp1 = rn_08_11 > tmp0; - $(Q_FLAG) = tmp1; - goto ; - - $(T_FLAG) = $(Q_FLAG) == $(M_FLAG); } From 0f50356e73a641a44f8200bdf27e188022882bc5 Mon Sep 17 00:00:00 2001 From: VGKintsugi <7758500+VGKintsugi@users.noreply.github.com> Date: Sat, 17 Apr 2021 03:03:36 -0400 Subject: [PATCH 3/4] SuperH: Div1 Code Review Changes --- Ghidra/Processors/SuperH/data/languages/superh.sinc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Ghidra/Processors/SuperH/data/languages/superh.sinc b/Ghidra/Processors/SuperH/data/languages/superh.sinc index 399a0a76f0..b0abb7f5a5 100644 --- a/Ghidra/Processors/SuperH/data/languages/superh.sinc +++ b/Ghidra/Processors/SuperH/data/languages/superh.sinc @@ -1034,11 +1034,11 @@ MovMUReg2: MovMUReg2_15 is MovMUReg2_15 { tmp0 = rn_08_11; # rn_08_11 = old_q_eq_m ? rn_08_11 - tmp2 : rn_08_11 + tmp2; - rn_08_11 = (sext(old_q_eq_m) & (rn_08_11 - tmp2)) | (sext(~old_q_eq_m) & (rn_08_11 + tmp2)); + rn_08_11 = (zext(old_q_eq_m) * (rn_08_11 - tmp2)) + (zext(!old_q_eq_m) * (rn_08_11 + tmp2)); # tmp1 = old_q_eq_m ? rn_08_11 > tmp0 : rn_08_11 < tmp0; - tmp1 = (old_q_eq_m & (rn_08_11 > tmp0)) | (~old_q_eq_m & (rn_08_11 <= tmp0)); + tmp1 = (old_q_eq_m * (rn_08_11 > tmp0)) + (!old_q_eq_m * (rn_08_11 < tmp0)); # $(Q_FLAG) = m_eq_q ? tmp1 : tmp1 == 0; - $(Q_FLAG) = (m_eq_q & tmp1) | (~m_eq_q & (tmp1 == 0)); + $(Q_FLAG) = (m_eq_q * tmp1) + (!m_eq_q & (tmp1 == 0)); $(T_FLAG) = $(Q_FLAG) == $(M_FLAG); } From 89f6e9bb7de0eae791d474570d51c3ad23f10581 Mon Sep 17 00:00:00 2001 From: VGKintsugi <7758500+VGKintsugi@users.noreply.github.com> Date: Thu, 1 Apr 2021 02:24:05 -0400 Subject: [PATCH 4/4] SuperH: Additional delay slot bug fixes Review of all delay slot instructions. --- .../SuperH/data/languages/superh.sinc | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/Ghidra/Processors/SuperH/data/languages/superh.sinc b/Ghidra/Processors/SuperH/data/languages/superh.sinc index b0abb7f5a5..8455dde2f4 100644 --- a/Ghidra/Processors/SuperH/data/languages/superh.sinc +++ b/Ghidra/Processors/SuperH/data/languages/superh.sinc @@ -1633,47 +1633,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"