Graphical-Micro-Architecture-Simulator icon indicating copy to clipboard operation
Graphical-Micro-Architecture-Simulator copied to clipboard

Problems with C & V flags when using the SUBS instruction

Open 4dvpitts opened this issue 3 years ago • 1 comments

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

4dvpitts avatar Jun 08 '22 17:06 4dvpitts

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

Ayilay avatar Sep 27 '22 20:09 Ayilay