Graphical-Micro-Architecture-Simulator
Graphical-Micro-Architecture-Simulator copied to clipboard
Problems with C & V flags when using the SUBS instruction
Hi, I have encountered issues that arise from the setting of the C and V flags when trying to use conditional branches (B.HI and B.LE)
The sequence movz x1, #36 movz x2, #54 subs x5, x1, x2 b.LE lse does not work properly. The V flag is set but 36-54 = -18 is not a signed overflow.
The sequence movz x1, #54 movz x2, #36 subx x5, x1, x2 b.GT gtr does not work properly as 54-36=18 does not set the carry bit as it should.
In the setVflag(long result, long op1, long op2) { replacing
with Vflag = (((long) op1 & 0x80000000L) == ((long) op2 & 0x80000000L)) && ((long) result != (long)op1; may work but I don't have the experience with GWT projects to rebuild.
I haven't had a chance to figure the issue with setting the C flag in the other scenario.
Thanks, Dave
I have observed a similar issue as well, and it applies to ADDS as well. My issue is the C flag not being set under certain circumstances, whereas the expected behavior dictates that it should.
The issue occurs when the dest register is the same as one of the src registers. For example:
# Example 1: assume the following register values:
# x0: (-1, 64 bit) 0xFFFFFFFF_FFFFFFFF
# x1: (3, 64 bit) 0x3
# Correctly sets the C flag to 1
ADDS x2, x1, x0
# Example 2: assume same register values as example 1 above
# INCORRECTLY does not set the C flag
ADDS x0, x1, x0
I believe the culprit to be the following function:
// File src/.../client/cpu/CPU.java
private void ADDS(int destReg, int op1Reg, int op2Reg) {
long result = registerFile[op1Reg] + registerFile[op2Reg];
if (destReg == XZR) {
cpuLog.append("Ignored attempted assignment to XZR. \n");
} else {
registerFile[destReg] = result;
cpuLog.append("ADDS \t X" + destReg + ", X" + op1Reg + ", X" + op2Reg + "\n");
}
ADDSetFlags(result, registerFile[op1Reg], registerFile[op2Reg]);
cpuLog.append("Set flags + \n");
}
Note the ADDSetFlags function call: It uses the new modified register values rather than the original register values. This is different from the behavior on real ARM Silicon (Apple M1); on the real silicon, the C flag gets set in both examples I illustrated