diff --git a/Ghidra/Processors/Atmel/data/languages/avr8.sinc b/Ghidra/Processors/Atmel/data/languages/avr8.sinc index 1d8648be01..ca966ea5a3 100644 --- a/Ghidra/Processors/Atmel/data/languages/avr8.sinc +++ b/Ghidra/Processors/Atmel/data/languages/avr8.sinc @@ -354,63 +354,27 @@ macro setSflag() { } macro setResultFlags(result) { - $(Nflag) = (result & 0x80) == 0x80; + $(Nflag) = (result s< 0); $(Zflag) = (result == 0x0); 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) { local x = pre - sub; - setVflagForSub(pre,sub,x); - setSubCarry(pre, sub); + $(Vflag) = sborrow(pre,sub); + $(Cflag) = (pre < sub); setResultFlags(x); $(Sflag) = pre s< sub; res = x; } -macro doSubtractWithCarry(pre,subNoCarry,res) { - local sub = subNoCarry + $(Cflag); - local x = pre - sub; +macro doSubtractWithCarry(pre,sub,res) { + local partial = pre - sub; + local subCarry = sub + $(Cflag); + local x = pre - subCarry; local oldZflag = $(Zflag); - setVflagForSub(pre,subNoCarry,x); - $(Cflag) = ((pre < sub) | (sub == 0 & $(Cflag) == 1)); + $(Vflag) = sborrow(pre,sub) ^^ sborrow(partial, $(Cflag)); + $(Cflag) = (pre < sub) || (partial < $(Cflag)); setResultFlags(x); $(Sflag) = $(Nflag)^$(Vflag); $(Zflag) = oldZflag & $(Zflag); @@ -491,7 +455,7 @@ K7addr: val is oplow4 & op9to10 & opbit8 [ val = ((1 ^ opbit8) << 7) | (opbit8 # 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; } # ##################################################################################### # COMMENTING OUT BECAUSE "Subtable symbol K7Ioaddr is not allowed in context block" @@ -536,26 +500,28 @@ define pcodeop break; @ifdef FUSION # add followed by adc :addw op1RdPair,op1RrPair is phase=1 & op1hi6=0x3 & op2hi6=0x7 & op1RdPair & op1RrPair & fusion16rrrrPred { - $(Cflag) = carry(op1RdPair,op1RrPair); local pre = op1RdPair; local post = op1RdPair + op1RrPair; + $(Cflag) = carry(op1RdPair,op1RrPair); + $(Vflag) = scarry(pre,op1RrPair); op1RdPair = post; - $(Vflag) = (0x0000 == (pre & 0x8000)) & ((post & 0x8000) == 0x8000); - setResult16Flags(post); + setResultFlags(post); } @endif # Rd,Rr :adc RdFull,RrFull is phase=1 & ophi6=0x7 & RdFull & RrFull { 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); RdFull = res; } # Rd,Rr :add RdFull,RrFull is phase=1 & ophi6=0x3 & RdFull & RrFull { local res = RdFull + RrFull; - setCflagForAdd(RdFull,RrFull,res); + $(Cflag) = carry(RdFull,RrFull); + $(Vflag) = scarry(RdFull,RrFull); setResultFlags(res); RdFull = res; } @@ -564,8 +530,8 @@ define pcodeop break; local pre = Rdw2; Rdw2 = Rdw2 + zext(K6); $(Cflag) = carry(pre,zext(K6)); - $(Vflag) = scarry(Rdw2,zext(K6)); #(0x0000 == (pre & 0x8000)) & ((Rdw2 & 0x8000) == 0x8000); - setResult16Flags(Rdw2); + $(Vflag) = scarry(Rdw2,zext(K6)); + setResultFlags(Rdw2); } # and Rd,Rr :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 { local x = RdFull - RrFull; - setSubCarry(RdFull,RrFull); - setVflagForSub(RdFull,RrFull,x); + $(Cflag) = (RdFull < RrFull); + $(Vflag) = sborrow(RdFull,RrFull); setResultFlags(x); # but doesn't set result into a register } @@ -700,9 +666,9 @@ define pcodeop break; # cp; cpc sequence :cpw op1RdPair,op1RrPair phase=1 & is op1hi6=0x5 & op2hi6=0x1 & fusion16rrrrPred & op1RdPair & op1RrPair { local res = op1RdPair - op1RrPair; - setVflagForSub16(op1RdPair,op1RrPair); - setSubCarry(op1RdPair, op1RrPair); - setResult16Flags(res); + $(Vflag) = sborrow(op1RdPair,op1RrPair); + $(Cflag) = (op1RdPair < op1RrPair); + setResultFlags(res); $(Sflag) = op1RdPair s< op1RrPair; } @@ -1035,10 +1001,10 @@ LpmPlus: Z^"+" is Z {} # doSubtract(op1RdPairHi,K16fuse,op1RdPairHi); local res = op1RdPairHi - K16fuse; local pre = op1RdPairHi; - setVflagForSub16(pre,K16fuse); - setSubCarry(op1RdPairHi, K16fuse); + $(Vflag) = sborrow(pre,K16fuse); + $(Cflag) = (op1RdPairHi < K16fuse); op1RdPairHi = res; - setResult16Flags(res); + setResultFlags(res); $(Sflag) = pre s< K16fuse; } @@ -1057,9 +1023,9 @@ LpmPlus: Z^"+" is Z {} :sbiw Rdw2,K6 is phase=1 & ophi8=0x97 & Rdw2 & K6 { local pre = Rdw2; Rdw2 = Rdw2 - zext(K6); - $(Cflag) = zext(K6) > pre; - $(Vflag) = (0x8000 == (pre & 0x8000)) & ((Rdw2 & 0x8000) == 0x0000); - setResult16Flags(Rdw2); + $(Cflag) = (pre < zext(K6)); + $(Vflag) = sborrow(pre,zext(K6)); + setResultFlags(Rdw2); } # sbr is an alias for ori