ghidra
ghidra copied to clipboard
i8085: set parity flag from arithmetic and logical operations
Decompilation of the IBM System/23 DataMaster RST0 test routine showed that P flag was never properly set.
I've used this reference to check for operations changing the P flag: https://gpbarkot.org.in/download/file/ihoN4LlRHP.pdf with ctrl-f 'S, Z, P are modified to reflect the result of the operation'
Before
After
There are several additional operations that set the P flag (notably all the arithmetic instructions which are listed as modifying all flags). That slide deck is also missing flag updates from several instructions such as INR
and DCR
. Check out the MCS80/85 Users Manual from 1983. That is much more thorough.
Thanks @GhidorahRex I'll goo through all these again.
It appears there were previous attempts in 8085.slaspec for setting P_flag at, e.g. at https://github.com/NationalSecurityAgency/ghidra/blob/master/Ghidra/Processors/8085/data/languages/8085.slaspec#L415C1-L419C2
:DAA is op0_8=0x27 {
A = BCDadjust(A);
setResultFlags(A);
P_flag = hasEvenParity(A);
}
Are there 'Pseudo Instructions' like BCDadjust and hasEvenParity that the decompiler knows to interpret?
Should these commented lines be removed? https://github.com/NationalSecurityAgency/ghidra/blob/master/Ghidra/Processors/8085/data/languages/8085.slaspec#L82
macro setAddCarryFlags(op1,op2) {
CY_flag = (carry(op1,zext(CY_flag)) || carry(op2,op1 + zext(CY_flag)));
# P_flag = (scarry(op1,CY_flag) || scarry(op2,op1 + CY_flag));
# AC_flag = ??
}
macro setAddFlags(op1,op2) {
CY_flag = carry(op1,op2);
# P_flag = scarry(op1,op2);
# AC_flag = ??
}
This looks wrong to me unless increment/decrement have a different meaning for parity result. Are these correct? https://github.com/NationalSecurityAgency/ghidra/blob/master/Ghidra/Processors/8085/data/languages/8085.slaspec#L387
:INR reg3_3 is op6_2=0x0 & reg3_3 & bits0_3=0x4 {
P_flag = (reg3_3 == 0x7f);
reg3_3 = reg3_3 + 1;
setResultFlags(reg3_3);
}
:INR (HL) is op0_8=0x34 & HL {
val:1 = *:1 HL;
P_flag = (val == 0x7f);
val = val + 1;
*:1 HL = val;
setResultFlags(val);
}
:DCR reg3_3 is op6_2=0x0 & reg3_3 & bits0_3=0x5 {
P_flag = (reg3_3 == 0x80);
reg3_3 = reg3_3 - 1;
setResultFlags(reg3_3);
}
:DCR (HL) is op0_8=0x35 & HL {
val:1 = *:1 HL;
P_flag = (val == 0x80);
val = val - 1;
*:1 HL = val;
setResultFlags(val);
}
In MCS80/85 Users Manual it first states that parity reflects the state of the accumulator
And later that the parity flag reflects the result of an operation - so for
:INR (HL)
it means the parity of the value at HL ?
@hjanetzek Those calculations are completely wrong. The ones you've introduced are correct however.
There are pseudo pcode ops. These can either be abstract or they can be defined by the emulator. In this case, the BCDAdjust and hasEvenParity operations are abstract. The decompiler treats them as as an abstract function call more or less.