u32 Operations
In this section we describe semantics and AIR constraints of operations over u32 values (i.e., 32-bit unsigned integers) as they are implemented in Miden VM. Unless stated otherwise, denotes the top of the stack, the next element, the third element, and so on.
Range checks
Most operations described below require some number of 16-bit range checks (i.e., verifying that the value of a field element is smaller than ). The number of required range checks varies between and , depending on the operation. However, to simplify the constraint system, we force each relevant operation to consume exactly range checks. U32DIV performs two additional range checks for its remainder bound, as described below.
To perform these range checks, the prover puts the values into helper registers
and removes four unit-multiplicity RangeCheck messages from the typed LogUp relation described in
the 16-bit range-check documentation. The fixed And8LookupAir table supplies the
matching messages; there is no range-checker execution-trace component.
This operation is enforced via the following constraint. Note that since constraints cannot include divisions, the actual constraint which is enforced will be expressed equivalently with all denominators multiplied through, resulting in a constraint of degree 5.
Here is the challenge reduction for the typed RangeCheck message. The displayed equation is
only the request side: And8LookupAir adds the matching table messages with their recorded
multiplicities. It also omits the selector flag, which turns
the request on only for the relevant operations.
Checking element validity
Another primitive which is required by most of the operations described below is checking whether four 16-bit values form a valid field element. Assume , , , and are known to be 16-bit values, and we want to verify that is a valid field element.
For simplicity, let's denote:
We can then impose the following constraint to verify element validity:
Where is a value set non-deterministically by the prover.
The above constraint should hold only if either of the following hold:
To satisfy the latter equation, the prover needs to set , which is possible only when .
This constraint is sufficient because modulus in binary representation is 32 ones, followed by 31 zeros, followed by a single one:
This implies that the largest possible 64-bit value encoding a valid field element would be 32 ones, followed by 32 zeros:
Thus, for a 64-bit value to encode a valid field element, either the lower 32 bits must be all zeros, or the upper 32 bits must not be all ones (which is ).
U32SPLIT
Assume is the element at the top of the stack. The U32SPLIT operation computes , where contains the lower 32 bits of , and contains the upper 32 bits of . The output stack is [b, c, ...] with (low limb) on top. The diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in to 16-bit limbs of with being the least significant limb. Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously. Also, we need to make sure that values in , when combined, form a valid field element, which we can do by putting a nondeterministic value into helper register and using the technique described here.
The effect of this operation on the rest of the stack is:
- Right shift starting from position .
U32ASSERT2
Assume (top) and (next) are the elements at the top of the stack. The U32ASSERT2 verifies that both and are smaller than . The diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in and to low and high 16-bit limbs of , and values in and to low and high 16-bit limbs of . Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously.
The effect of this operation on the rest of the stack is:
- No change starting from position - i.e., the state of the stack does not change.
U32ADD
Assume and are the values at the top of the stack which are known to be smaller than . The U32ADD operation computes , where contains the low 32-bits of the result, and is the carry bit. The output stack is [c, d, ...] with on top. The diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in , , and to 16-bit limbs of with being the least significant limb. Value in is set to . Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously.
The effect of this operation on the rest of the stack is:
- No change starting from position .
U32ADD3
Assume , , and are the values at the top of the stack which are known to be smaller than
. The U32ADD3 operation computes ,
where contains the low 32 bits of the result and contains the
high 32 bits. The diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in , , and to 16-bit limbs of with being the least significant limb. Value in is set to . Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously.
The effect of this operation on the rest of the stack is:
- Left shift starting from position .
U32SUB
Assume and are the values at the top of the stack which are known to be smaller than . The U32SUB operation computes , where diff contains the 32-bit result in two's complement, and borrow is the borrow bit. The diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in and to the low and the high 16-bit limbs of respectively. Values in and are set to . Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously.
The effect of this operation on the rest of the stack is:
- No change starting from position .
U32MUL
Assume and are the values at the top of the stack which are known to be smaller than . The U32MUL operation computes , where and contain the low and the high 32-bits of the result respectively. The output stack is [c, d, ...] with on top. The diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in to 16-bit limbs of with being the least significant limb. Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously. Also, we need to make sure that values in , when combined, form a valid field element, which we can do by putting a nondeterministic value into helper register and using the technique described here.
The effect of this operation on the rest of the stack is:
- No change starting from position .
U32MADD
Assume , , and are the values at the top of the stack which are known to be smaller than
. The U32MADD operation computes ,
where and contain the low and the high 32 bits of the result. The
diagram below illustrates this graphically.

To facilitate this operation, the prover sets values in to 16-bit limbs of with being the least significant limb. Thus, stack transition for this operation must satisfy the following constraints:
In addition to the above constraints, we also need to verify that values in are smaller than , which we can do using 16-bit range checks as described previously. Also, we need to make sure that values in , when combined, form a valid field element, which we can do by putting a nondeterministic value into helper register and using the technique described here.
Note: that the above constraints guarantee the correctness of the operation iff cannot overflow field modules (which is the case for the field with modulus ).
The effect of this operation on the rest of the stack is:
- Left shift starting from position .
U32DIV
Assume the divisor is at the top of the stack and the dividend is below it, and both are
smaller than . The U32DIV operation computes , where is
the remainder and is the quotient.

To facilitate this operation, the prover sets values in and to the low and high 16-bit limbs of , values in and to the low and high 16-bit limbs of , and values in and to the low and high 16-bit limbs of . Thus, the stack transition must satisfy the following constraints:
All six helpers are range-checked to 16 bits. This directly bounds and to 32 bits, while the final constraint establishes . The division identity therefore cannot wrap and determines the unique integer quotient and remainder.
The effect of this operation on the rest of the stack is:
- No change starting from position .
U32AND
Assume and are the values at the top of the stack. The U32AND operation computes , where is the result of performing a bitwise AND on and . The diagram below illustrates this graphically.

The operation removes one typed Bitwise message from the
LogUp relation, with multiplicity :
The leading selects AND. The bitwise chiplet adds the matching message with multiplicity .
Note: unlike for many other u32 operations, bitwise AND operation does not assume that the values at the top of the stack are smaller than . This is because the lookup will fail for any inputs which are not 32-bit integers.
The effect of this operation on the rest of the stack is:
- Left shift starting from position .
U32XOR
Assume and are the values at the top of the stack. The U32XOR operation computes , where is the result of performing a bitwise XOR on and . The diagram below illustrates this graphically.

The operation removes one typed Bitwise message from the LogUp relation, with multiplicity :
The leading selects XOR. The bitwise chiplet adds the matching message with multiplicity .
Note: unlike for many other u32 operations, bitwise XOR operation does not assume that the values at the top of the stack are smaller than . This is because the lookup will fail for any inputs which are not 32-bit integers.
The effect of this operation on the rest of the stack is:
- Left shift starting from position .