mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 03:49:24 +08:00
GT-3276: Fixed AVR8 addition/subtraction flag macros
This commit is contained in:
@@ -354,63 +354,27 @@ macro setSflag() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro setResultFlags(result) {
|
macro setResultFlags(result) {
|
||||||
$(Nflag) = (result & 0x80) == 0x80;
|
$(Nflag) = (result s< 0);
|
||||||
$(Zflag) = (result == 0x0);
|
$(Zflag) = (result == 0x0);
|
||||||
setSflag();
|
setSflag();
|
||||||
}
|
}
|
||||||
|
|
||||||
macro setResult16Flags(result) {
|
|
||||||
$(Nflag) = (result & 0x8000) == 0x8000;
|
|
||||||
$(Zflag) = (result == 0x0);
|
|
||||||
setSflag();
|
|
||||||
}
|
|
||||||
|
|
||||||
macro setSubCarry(pre,sub) { # pre - sub
|
|
||||||
$(Cflag) = (pre < sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
# The decompilation looks better when the pcode comparision is used,
|
|
||||||
# rather than walking though the bit examples in the manual.
|
|
||||||
# todo: consolidate these
|
|
||||||
macro setVflagForSub(pre,sub,res) { # res = pre - sub
|
|
||||||
$(Vflag) = sborrow(pre,sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro setVflagForSub16(pre,sub) { # pre - sub
|
|
||||||
$(Vflag) = sborrow(pre,sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro setVflagForAdd(arg1,arg2,res) {
|
|
||||||
local a = (arg1 & 0x80) >> 7;
|
|
||||||
local b = (arg2 & 0x80) >> 7;
|
|
||||||
local c = (res & 0x80) >> 7;
|
|
||||||
local V = (a & b & (~c)) | ((~a) & (~b) & c);
|
|
||||||
$(Vflag) = V & 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro setCflagForAdd(arg1,arg2,res) {
|
|
||||||
local a = (arg1 & 0x80) >> 7;
|
|
||||||
local b = (arg2 & 0x80) >> 7;
|
|
||||||
local c = (res & 0x80) >> 7;
|
|
||||||
local V = (a & b) | (a & (~c)) | (b & (~c));
|
|
||||||
$(Cflag) = V & 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro doSubtract(pre,sub,res) {
|
macro doSubtract(pre,sub,res) {
|
||||||
local x = pre - sub;
|
local x = pre - sub;
|
||||||
setVflagForSub(pre,sub,x);
|
$(Vflag) = sborrow(pre,sub);
|
||||||
setSubCarry(pre, sub);
|
$(Cflag) = (pre < sub);
|
||||||
setResultFlags(x);
|
setResultFlags(x);
|
||||||
$(Sflag) = pre s< sub;
|
$(Sflag) = pre s< sub;
|
||||||
res = x;
|
res = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro doSubtractWithCarry(pre,subNoCarry,res) {
|
macro doSubtractWithCarry(pre,sub,res) {
|
||||||
local sub = subNoCarry + $(Cflag);
|
local partial = pre - sub;
|
||||||
local x = pre - sub;
|
local subCarry = sub + $(Cflag);
|
||||||
|
local x = pre - subCarry;
|
||||||
local oldZflag = $(Zflag);
|
local oldZflag = $(Zflag);
|
||||||
setVflagForSub(pre,subNoCarry,x);
|
$(Vflag) = sborrow(pre,sub) ^^ sborrow(partial, $(Cflag));
|
||||||
$(Cflag) = ((pre < sub) | (sub == 0 & $(Cflag) == 1));
|
$(Cflag) = (pre < sub) || (partial < $(Cflag));
|
||||||
setResultFlags(x);
|
setResultFlags(x);
|
||||||
$(Sflag) = $(Nflag)^$(Vflag);
|
$(Sflag) = $(Nflag)^$(Vflag);
|
||||||
$(Zflag) = oldZflag & $(Zflag);
|
$(Zflag) = oldZflag & $(Zflag);
|
||||||
@@ -491,7 +455,7 @@ K7addr: val is oplow4 & op9to10 & opbit8 [ val = ((1 ^ opbit8) << 7) | (opbit8
|
|||||||
|
|
||||||
# Join against various spaces for dataspace...
|
# Join against various spaces for dataspace...
|
||||||
# #####################################################################################
|
# #####################################################################################
|
||||||
# COMMENTING OUT BECAUSE "Subtable symbol K7addr is not allowed in context block"
|
# COMMENTING OUT BECAUSE "subtable symbol K7addr is not allowed in context block"
|
||||||
#K7Ioaddr: val is K7addr [ val = K7addr - 0x20; ] { tmp:1 = val; export tmp; }
|
#K7Ioaddr: val is K7addr [ val = K7addr - 0x20; ] { tmp:1 = val; export tmp; }
|
||||||
# #####################################################################################
|
# #####################################################################################
|
||||||
# COMMENTING OUT BECAUSE "Subtable symbol K7Ioaddr is not allowed in context block"
|
# COMMENTING OUT BECAUSE "Subtable symbol K7Ioaddr is not allowed in context block"
|
||||||
@@ -536,26 +500,28 @@ define pcodeop break;
|
|||||||
@ifdef FUSION
|
@ifdef FUSION
|
||||||
# add followed by adc
|
# add followed by adc
|
||||||
:addw op1RdPair,op1RrPair is phase=1 & op1hi6=0x3 & op2hi6=0x7 & op1RdPair & op1RrPair & fusion16rrrrPred {
|
:addw op1RdPair,op1RrPair is phase=1 & op1hi6=0x3 & op2hi6=0x7 & op1RdPair & op1RrPair & fusion16rrrrPred {
|
||||||
$(Cflag) = carry(op1RdPair,op1RrPair);
|
|
||||||
local pre = op1RdPair;
|
local pre = op1RdPair;
|
||||||
local post = op1RdPair + op1RrPair;
|
local post = op1RdPair + op1RrPair;
|
||||||
|
$(Cflag) = carry(op1RdPair,op1RrPair);
|
||||||
|
$(Vflag) = scarry(pre,op1RrPair);
|
||||||
op1RdPair = post;
|
op1RdPair = post;
|
||||||
$(Vflag) = (0x0000 == (pre & 0x8000)) & ((post & 0x8000) == 0x8000);
|
setResultFlags(post);
|
||||||
setResult16Flags(post);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@endif
|
@endif
|
||||||
# Rd,Rr
|
# Rd,Rr
|
||||||
:adc RdFull,RrFull is phase=1 & ophi6=0x7 & RdFull & RrFull {
|
:adc RdFull,RrFull is phase=1 & ophi6=0x7 & RdFull & RrFull {
|
||||||
local res = RdFull + RrFull + $(Cflag);
|
local res = RdFull + RrFull + $(Cflag);
|
||||||
setCflagForAdd(RdFull,RrFull,res);
|
$(Cflag) = carry(RdFull, RrFull) || carry(RdFull + RrFull, $(Cflag));
|
||||||
|
$(Vflag) = scarry(RdFull, RrFull) ^^ scarry(RdFull + RrFull, $(Cflag));
|
||||||
setResultFlags(res);
|
setResultFlags(res);
|
||||||
RdFull = res;
|
RdFull = res;
|
||||||
}
|
}
|
||||||
# Rd,Rr
|
# Rd,Rr
|
||||||
:add RdFull,RrFull is phase=1 & ophi6=0x3 & RdFull & RrFull {
|
:add RdFull,RrFull is phase=1 & ophi6=0x3 & RdFull & RrFull {
|
||||||
local res = RdFull + RrFull;
|
local res = RdFull + RrFull;
|
||||||
setCflagForAdd(RdFull,RrFull,res);
|
$(Cflag) = carry(RdFull,RrFull);
|
||||||
|
$(Vflag) = scarry(RdFull,RrFull);
|
||||||
setResultFlags(res);
|
setResultFlags(res);
|
||||||
RdFull = res;
|
RdFull = res;
|
||||||
}
|
}
|
||||||
@@ -564,8 +530,8 @@ define pcodeop break;
|
|||||||
local pre = Rdw2;
|
local pre = Rdw2;
|
||||||
Rdw2 = Rdw2 + zext(K6);
|
Rdw2 = Rdw2 + zext(K6);
|
||||||
$(Cflag) = carry(pre,zext(K6));
|
$(Cflag) = carry(pre,zext(K6));
|
||||||
$(Vflag) = scarry(Rdw2,zext(K6)); #(0x0000 == (pre & 0x8000)) & ((Rdw2 & 0x8000) == 0x8000);
|
$(Vflag) = scarry(Rdw2,zext(K6));
|
||||||
setResult16Flags(Rdw2);
|
setResultFlags(Rdw2);
|
||||||
}
|
}
|
||||||
# and Rd,Rr
|
# and Rd,Rr
|
||||||
:and RdFull,RrFull is phase=1 & ophi6=8 & RdFull & RrFull {
|
:and RdFull,RrFull is phase=1 & ophi6=8 & RdFull & RrFull {
|
||||||
@@ -674,8 +640,8 @@ define pcodeop break;
|
|||||||
}
|
}
|
||||||
:cp RdFull,RrFull is phase=1 & ophi6=0x05 & RdFull & RrFull {
|
:cp RdFull,RrFull is phase=1 & ophi6=0x05 & RdFull & RrFull {
|
||||||
local x = RdFull - RrFull;
|
local x = RdFull - RrFull;
|
||||||
setSubCarry(RdFull,RrFull);
|
$(Cflag) = (RdFull < RrFull);
|
||||||
setVflagForSub(RdFull,RrFull,x);
|
$(Vflag) = sborrow(RdFull,RrFull);
|
||||||
setResultFlags(x);
|
setResultFlags(x);
|
||||||
# but doesn't set result into a register
|
# but doesn't set result into a register
|
||||||
}
|
}
|
||||||
@@ -698,9 +664,9 @@ define pcodeop break;
|
|||||||
# cp; cpc sequence
|
# cp; cpc sequence
|
||||||
:cpw op1RdPair,op1RrPair phase=1 & is op1hi6=0x5 & op2hi6=0x1 & fusion16rrrrPred & op1RdPair & op1RrPair {
|
:cpw op1RdPair,op1RrPair phase=1 & is op1hi6=0x5 & op2hi6=0x1 & fusion16rrrrPred & op1RdPair & op1RrPair {
|
||||||
local res = op1RdPair - op1RrPair;
|
local res = op1RdPair - op1RrPair;
|
||||||
setVflagForSub16(op1RdPair,op1RrPair);
|
$(Vflag) = sborrow(op1RdPair,op1RrPair);
|
||||||
setSubCarry(op1RdPair, op1RrPair);
|
$(Cflag) = (op1RdPair < op1RrPair);
|
||||||
setResult16Flags(res);
|
setResultFlags(res);
|
||||||
$(Sflag) = op1RdPair s< op1RrPair;
|
$(Sflag) = op1RdPair s< op1RrPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,10 +999,10 @@ LpmPlus: Z^"+" is Z {}
|
|||||||
# doSubtract(op1RdPairHi,K16fuse,op1RdPairHi);
|
# doSubtract(op1RdPairHi,K16fuse,op1RdPairHi);
|
||||||
local res = op1RdPairHi - K16fuse;
|
local res = op1RdPairHi - K16fuse;
|
||||||
local pre = op1RdPairHi;
|
local pre = op1RdPairHi;
|
||||||
setVflagForSub16(pre,K16fuse);
|
$(Vflag) = sborrow(pre,K16fuse);
|
||||||
setSubCarry(op1RdPairHi, K16fuse);
|
$(Cflag) = (op1RdPairHi < K16fuse);
|
||||||
op1RdPairHi = res;
|
op1RdPairHi = res;
|
||||||
setResult16Flags(res);
|
setResultFlags(res);
|
||||||
$(Sflag) = pre s< K16fuse;
|
$(Sflag) = pre s< K16fuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1055,9 +1021,9 @@ LpmPlus: Z^"+" is Z {}
|
|||||||
:sbiw Rdw2,K6 is phase=1 & ophi8=0x97 & Rdw2 & K6 {
|
:sbiw Rdw2,K6 is phase=1 & ophi8=0x97 & Rdw2 & K6 {
|
||||||
local pre = Rdw2;
|
local pre = Rdw2;
|
||||||
Rdw2 = Rdw2 - zext(K6);
|
Rdw2 = Rdw2 - zext(K6);
|
||||||
$(Cflag) = zext(K6) > pre;
|
$(Cflag) = (pre < zext(K6));
|
||||||
$(Vflag) = (0x8000 == (pre & 0x8000)) & ((Rdw2 & 0x8000) == 0x0000);
|
$(Vflag) = sborrow(pre,zext(K6));
|
||||||
setResult16Flags(Rdw2);
|
setResultFlags(Rdw2);
|
||||||
}
|
}
|
||||||
# sbr is an alias for ori
|
# sbr is an alias for ori
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user