SBPF arithmetics improvements
- Idea
- Draft
- Review
- Accept
- Implement
- Active
Decision brief
Why this proposal matters
This proposal introduces wide multiplication, signed division and explicit sign extension to SBPF.
Proposal at a glance
What changes
- the MUL instruction (opcodes 0x24, 0x2C, 0x27 and 0x2F)
- the DIV instruction (opcodes 0x34, 0x3C, 0x37 and 0x3F)
- the MOD instruction (opcodes 0x94, 0x9C, 0x97 and 0x9F)
Stakeholder map
Who is affected
Builders & client teams Medium impact
The following must go into effect if and only if a program indicates the SBPF-version (v2) or higher in its program header (see SIMD-0161).
Action may be requiredValidators & operators Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownUsers & stakers Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownGovernance & ecosystem Medium impact
This proposal introduces wide multiplication, signed division and explicit sign extension to SBPF.
Action requirement unknownExact source revision
Full proposal document
0616093b2952Summary
This proposal introduces wide multiplication, signed division and explicit sign extension to SBPF.
Motivation
All major hardware ISAs support 64 x 64 = 128 bit multiplication; BPF does not. This hurts performance of big integer arithmetics. Similarly, signed division and signed remainder / modulo instructions must be emulated in software as well.
Another issue related to arithmetics is that some 32 bit instructions perform sign extension of their results (output, not input, there is a difference) implicitly. This is first of all useless because source languages do not read the 32 MSBs of a 32 bit result stored in a 64 bit register. And second, it requires interpreters and compilers to perform extra work to add sign extension at the end of these instructions. Instead we should go the same route as the underlying hardware ISAs and require sign extension to be made explicit in a dedicated instruction.
Furthermore, the instruction sub dst, imm is redundant as it can also be
encoded as add dst, -imm. If we were to swap the operands meaning of minuend
and subtrahend, then the instruction would become useful and would even render
neg dst redundant. Negation would then be encoded as reg = 0 - reg. This
would also make it clear how sign extension rules work for negation.
Alternatives Considered
None.
New Terminology
None.
Detailed Design
The following must go into effect if and only if a program indicates the SBPF-version (v2) or higher in its program header (see SIMD-0161).
Changes to the Bytecode Verifier
A program containing one of the following instructions must throw
VerifierError::UnknownOpCode during verification:
- the
MULinstruction (opcodes0x24,0x2C,0x27and0x2F) - the
DIVinstruction (opcodes0x34,0x3C,0x37and0x3F) - the
MODinstruction (opcodes0x94,0x9C,0x97and0x9F) - the
NEGinstruction (opcodes0x84and0x87)
A program containing one of the following instructions must not throw
VerifierError::UnknownOpCode during verification anymore (opcodes are for
immediate and register variant each, in that order):
- the
UHMUL64instruction (opcode0x36and0x3E) - the
UDIV32instruction (opcode0x46and0x4E) - the
UDIV64instruction (opcode0x56and0x5E) - the
UREM32instruction (opcode0x66and0x6E) - the
UREM64instruction (opcode0x76and0x7E) - the
LMUL32instruction (opcode0x86and0x8E) - the
LMUL64instruction (opcode0x96and0x9E) - the
SHMUL64instruction (opcode0xB6and0xBE) - the
SDIV32instruction (opcode0xC6and0xCE) - the
SDIV64instruction (opcode0xD6and0xDE) - the
SREM32instruction (opcode0xE6and0xEE) - the
SREM64instruction (opcode0xF6and0xFE)
The verification rule, that an immediate divisor must not be zero or else
VerifierError::DivisionByZero is thrown, is moved to the new division like
instructions: UDIV32_IMM, UDIV64_IMM, UREM32_IMM, UREM64_IMM,
SDIV32_IMM, SDIV64_IMM, SREM32_IMM, SREM64_IMM.
Changes to Execution
PQR Instruction Class
A new instruction class product, quotient and remainder (PQR) is introduced:
- the
UHMUL64instruction (opcode0x36and0x3E) produces the 64 MSBs of the product of an unsigned 64 x 64 bit multiplication (dst * immanddst * src). - the
UDIV32instruction (opcode0x46and0x4E) produces the quotient of an unsigned 32 bit division (dst / immanddst / src). - the
UDIV64instruction (opcode0x56and0x5E) produces the quotient of an unsigned 64 bit division (dst / immanddst / src). - the
UREM32instruction (opcode0x66and0x6E) produces the remainder of an unsigned 64 bit division (dst % immanddst % src). - the
UREM64instruction (opcode0x76and0x7E) produces the remainder of an unsigned 64 bit division (dst % immanddst % src). - the
LMUL32instruction (opcode0x86and0x8E) produces the 32 LSBs of the product of any 32 x 32 bit multiplication (dst * immanddst * src). - the
LMUL64instruction (opcode0x96and0x9E) produces the 64 LSBs of the product of any 64 x 64 bit multiplication (dst * immanddst * src). - the
SHMUL64instruction (opcode0xB6and0xBE) produces the 64 MSBs of the product of a signed 64 x 64 bit multiplication (dst * immanddst * src). - the
SDIV32instruction (opcode0xC6and0xCE) produces the quotient of a signed 32 bit division (dst / immanddst / src). - the
SDIV64instruction (opcode0xD6and0xDE) produces the quotient of a signed 64 bit division (dst / immanddst / src). - the
SREM32instruction (opcode0xE6and0xEE) produces the remainder of a signed 32 bit division (dst / immanddst / src). - the
SREM64instruction (opcode0xF6and0xFE) produces the remainder of a signed 64 bit division (dst / immanddst / src).
Runtime exceptions are:
- If the divisor (
immorsrc) of any division is zero,EbpfError::DivideByZeromust be thrown. - If the dividend (
dst) of a signed division has the minimal value for its bit-width and the divisor (immorsrc) is-1, thenEbpfError::DivideOverflowmust be thrown.
Explicit Sign Extension
The following instructions must stop performing implicit sign extension of
their results, instead filling the 32 MSBs of dst with zeros:
- the
ADD32instruction (opcode0x04and0x0C) - the
SUB32instruction (opcode0x14and0x1C) - all of the new 32 bit PQR instructions:
UDIV32,UREM32,SDIV32,SREM32andLMUL32
Instead the MOV32_REG instruction (opcode 0xBC) which until now did zero
out the 32 MSBs, must now perform sign extension in the 32 MSBs. Meaning this
instruction becomes the explicit sign extension operation.
Register Immediate Subtraction
The operands roles of SUB32_IMM (opcode 0x14) and SUB64_IMM (opcode
0x17) must be swapped: Until now the resulting difference was src - imm and
it must be changed to imm - src.
Impact
The toolchain will emit machine-code according to the selected SBPF version. Big integer arithmetics and signed divisions will become cheaper CU wise.
Security Considerations
None.
Evidence graph
Related proposals and rollout
One or more sources are unavailable.
Upstream review record
Upstream discussion & review
GitHub review is editorial context, not evidence of on-chain support, voting, or outcome.
PR #174 · merged SIMD-0174: SBPF arithmetics improvements 8 comments and reviews · Jan 19, 2026I think these instruction opcodes is a bit of a departure from the pattern we had until now. In BPF, opcode for 32-bit and 64-bit instructions differs in the least significant bits: mul64 dest, reg is 0x2F and mul32 dest, reg is 0x2C. For these new instructions, we change the most significant bits. Maintaining the same pattern simplifies code generation.
GitHub ↗Why is it important to error out for this case? We don't error for any other overflows (add, mul, and sub).
GitHub ↗Yes, but that bit is part of the instruction class. Meaning the 32 bit ALU instruction class and the 64 bit ALU instruction class are two different instruction classes. And this SIMD introduces a new instruction class for PQR because they don't fit into the ALU classes (not enough free opcodes).
GitHub ↗Because some machine code ISAs (such as x86) throw exceptions (divide error) in that case: https://www.felixcloutier.com/x86/idiv
GitHub ↗Let's specify which SBPF version this will be released in.
GitHub ↗SDIV64IMM and SREM64IMM are exceptions. IMM is 32-bit, so it can't be 64-bit -1. I think it'd be better to remove the check for these.
GitHub ↗There is sign extension of the inputs (not the outputs). Thus the name "signed division".
GitHub ↗Just an impl note for UHMUL64IMM: imm is sign extended to 64-bits. Practically speaking, this means that to do 64x64=128 bit umul one should use UHMUL64REG.
GitHub ↗Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity. 1
Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity.SIMD
Deployment Status
F6UVKh1ujTEFK3en2SyAL3cdVnqko1FVEXWhmdLRu6WPExact source revision
Sources & integrity
- Proposal document pinned_commit_blob
0616093b2952ed6de52c4a27d66aadd11d48d4f9 - simd-document document · current · Sep 11, 2026
0616093b2952ed6de52c4a27d66aadd11d48d4f9
One or more sources are unavailable.
simd.watch community discussion · SIMD-0174
Powered by Giscus · Sign in with GitHub to comment
Community comments load when this section approaches the viewport.