Microprocessor Design/ALU Flags
For a number of reasons, it can be important to export a number of status codes from the ALU, for detecting errors, and for making decisions.
Comparisons between two values are typically performed by subtracting them. We can determine the relationship between the two values by examining the difference:
- If the first is larger than the second, the result will be positive
- If the second is larger than the first, the result will be negative
- If the two are equal, the result will be zero.
Determining whether two values are equal requires the ALU to determine whether the result is zero. This can be accomplished by feeding each bit of the result into a NOR gate. The beauty of this is that a single multi-port NOR gate requires less hardware than an entire array of equivalent 2-port gates.
It is good to know when the result of an addition or multiplication is larger than the maximum result size. Likewise, it is also good to know if the result of a subtraction or a division is smaller than possible, and thus creates underflow. Either two separate flags can be used for these conditions, or one flag can be interpreted in different ways, depending on the input operation.
This flag indicates when an operation results in a value larger than the accumulator can represent (carry/overflow) or smaller than the accumulator can represent (borrow/underflow). It can be used by software to implement arbitrary-width arithmetic, such as a "bignum" library.
Many ALUs need to compare data items, and determine if a particular value is greater than or less than another value. In these cases, the ALU will also export flags for these values.
A comparison in a processor can typically be performed by a subtraction operation. If the result is a positive number, the first item is greater than the second item. If the result is a negative number, the first item is less than the second. If the numbers being compared are unsigned, the value of the carry flag will serve the same purpose as the greater-than or less-than flag.
Latch ALU flags or not?
Some instruction sets refer to the ALU flags from some previous instruction:
CMP R1,R2 // compare ... BEQ equal_routine // branch if equal
Such instruction sets force the CPU designer to latch those ALU flags in some sort of "status register", and to be very careful to make sure it is possible to preserve those flags during an interrupt routine.
Other instruction sets never refer to previous ALU flags -- they always use the results from the ALU in the same instruction that they are calculated:
BEQ R1,R2,equal_routine // compare and branch if equal
SKEQ R1,R2 // compare and skip next instruction if equal JMP equal_routine
Some CPU designers prefer such instruction sets that never refer to previous ALU flags. Such instruction sets make out-of-order execution much simpler. Many of Chuck Moore's CPU designs never refer to the ALU flags from any previous instruction.