DIVIDE
Divide the left operand by the right operand as signed integers to calculate a quotient and optional remainder.
| Opcode | Bytes | Cycles | Form | Example |
|---|---|---|---|---|
| $a5 | 3 | 29 | divide i:_, {s_byte} | divide i:4, 123 |
| $a7 | 3 | 29 | divide i:_, i:_ | divide i:4, i:8 |
| $dc | 4 | 29 | divide i:_, {s_byte}, remainder i:_ | divide i:4, 123, remainder i:8 |
| $de | 4 | 29 | divide i:_, i:_, remainder i:_ | divide i:4, i:8, remainder i:12 |
| Condition flag | Output |
|---|---|
| zero (ZF) | If the quotient is zero, this flag is 1; otherwise it is 0. |
| negative (NF) | If the quotient is negative, this flag is 1; otherwise it is 0. |
| overflow (OF) | If the quotient cannot be correctly represented, this flag is 1; otherwise it is 0. |
| carry (CF) | This flag is always 0. |
Notes
-
Terminology: If we write
a / b = q,ais called the dividend,bis the divisor, andqis the quotient. If the division is not exact, the remainder will be nonzero. -
For example,
divide i:4, i:8, remainder i:12dividesi:4(the dividend) byi:8(the divisor), storing the quotient back intoi:4. The remainder is stored ini:12. -
The remainder's register will always be assigned after the quotient's register. This allows a modulus expression such as
x <- x %% 123to be compiled asdivide i:4, 123, remainder i:4without need for a temporary register to discard the quotient. -
If the divisor is zero, then the quotient result and remainder result will both be zero, and
OFwill be set to1. -
If
-2147483648is divided by-1, then the quotient result will be-2147483648, the remainder result will be0, andOFis set to1. -
For these overflow cases, you can use the
fail if overflowinstruction to trap incorrect arithmetic results. -
The
with euclidmode does not affect these overflow cases. -
This instruction performs signed division only. An unsigned form could be added, but aside from problems involving data sizes beyond this machine's limits, the cases that genuinely require unsigned division are already advanced enough to implement it by combining signed
divideandshift.
Euclidean division
For historical reasons, most CPUs and programming languages such as C and Rust implement truncated division, where the remainder can be a negative number if the dividend is negative. Chombit's divide instruction performs truncated division by default. The Hybrix language's / and % operators are implemented this way.
Euclidean division ensures that the remainder is never a negative number. It is the most mathematically correct way to divide. This method is selected if a with euclid instruction immediately precedes the divide instruction. The Hybrix language's // and %% operators are implemented this way.
The table below illustrates the differences:
| Truncated quotient | Truncated remainder |
|---|---|
17 / 5 = 3 | 17 % 5 = 2 |
-17 / 5 = -3 | -17 % 5 = -2 |
17 / -5 = -3 | 17 % -5 = 2 |
-17 / -5 = 3 | -17 % -5 = -2 |
| Euclidean quotient | Euclidean remainder |
|---|---|
17 // 5 = 3 | 17 %% 5 = 2 |
-17 // 5 = -4 | -17 %% 5 = 3 |
17 // -5 = -3 | 17 %% -5 = 2 |
-17 // -5 = 4 | -17 %% -5 = 3 |