Skip to main content

CPU flags

The CPU flags are boolean states that can be either 1 (true) or 0 (false). Instructions can set a flag (make it 1) or clear a flag (make it 0).

The flags are represented as bits of a byte called the flags register:

Bit #FlagFlag typeNotes
0Zero (ZF)condition flag
1Negative (NF)condition flagfor signed values
2Overflow (OF)condition flagfor unsigned values
3Carry (CF)condition flagfor unsigned values
4With (WF)control flagset by WITH instructions
5Skip (SF)control flagset by IF instructions

The NF, OF, ZF, and CF flags are called condition flags. They are updated by various instructions to report arithmetic outcomes, which then typically serve as conditions to be checked by the IF instruction.

The WF and SF flags are called control flags. They are updated by WITH or IF and always cleared by all other instructions. Thus, the control flags modify the behavior of next instruction to be executed.

The flags byte can also be accessed directly using the PUSH FLAGS and POP FLAGS instructions. When a CPU event is triggered, the flags byte is stored in IO::CPU_EVENT_FLAGS.

Zero (ZF)

  • Updated by: ADD, AND, COMPARE, CONVERT, DIVIDE, MULTIPLY, NEGATE, OR, SHIFT, SUBTRACT, XOR
  • Tested using: IF ZERO

Instructions set ZF if the result of the operation is zero, and ZF=0 otherwise.

Negative (NF)

  • Updated by: ADD, AND, COMPARE, CONVERT, DIVIDE, MULTIPLY, NEGATE, OR, SHIFT, SUBTRACT, XOR
  • Tested using: IF NEGATIVE
  • Meaningful for signed numbers

Instructions put the most significant bit of their result into NF. For signed arithmetic using two's complement, NF=1 indicates a negative number.

Overflow (OF)

  • Updated by: ADD, AND, COMPARE, CONVERT, DIVIDE, MULTIPLY, NEGATE, OR, SUBTRACT, XOR
  • Tested using: IF OVERFLOW or FAIL IF OVERFLOW
  • Meaningful for signed numbers

When adding or subtracting or comparing, OF=1 indicates that the result exceeded the register's signed range. Similarly, the CONVERT instruction sets OF whenever a narrowing conversion exceeds the target register's signed range.

The other instructions listed above will simply clear OF to avoid confusion.

Note that SHIFT does not affect this flag at all.

Carry (CF)

  • Updated by: ADD, AND, COMPARE, CONVERT, DIVIDE, MULTIPLY, NEGATE, OR, SHIFT, SUBTRACT, XOR
  • Tested using: IF LESS UNSIGNED or FAIL IF CARRY
  • Meaningful for unsigned numbers

When adding or subtracting or comparing, CF=1 indicates that the result exceeded the register's unsigned range. Similarly, the CONVERT instruction sets CF whenever a narrowing conversion exceeds the target register's unsigned range. The SHIFT instruction puts the last shifted bit into the carry flag.

The other instructions listed above will simply clear CF to avoid confusion.

The SUBTRACT instruction uses the subtract-with-carry model (familiar from ARM and 6502 processors), where CF=0 indicates an underflow or "less than" comparison.

With (WF)

  • Set by: WITH CARRY or WITH EUCLID
  • Cleared by every other instruction

This flag enables certain instructions to perform specialized behaviors that are useful but rarely needed. The WITH instruction sets this flag. The two forms WITH CARRY and WITH EUCLID are actually the same opcode, just named for clarity.

WITH CARRY sets WF=1 to cause an immediately following ADD, SUBTRACT, or COMPARE instruction to include the carry flag in its calculation.

WITH EUCLID set WF=1 to cause an immediately following DIVIDE instruction to perform Euclidean integer division instead of truncated division.

Skip (SF)

  • Updated by: IF
  • Cleared by every other instruction except WITH

The IF instruction tests a condition and only executes the next instruction if that condition is satisfied. In other words, if the condition is unsatisfied, then the next Chombit instruction will be skipped over.

This skipping is implemented by the SF flag. When SF=1, the current instruction is skipped; no action is performed other than clearing the SF flag and advancing IP. Skipped instructions only require 1 CPU cycle.

XOR B:1, B:1   # ZF=1 BECAUSE THE RESULT IS ZERO
IF NOT ZERO # CONDITION IS UNSATISFIED, SO SF=1
ADD B:1, 1 # THIS IS SKIPPED OVER, REVERT TO SF=0
ADD B:1, 2 # EXECUTION CONTINUES HERE