SBPF instruction encoding improvements
- Idea
- Draft
- Review
- Accept
- Implement
- Active
Decision brief
Why this proposal matters
There are some instructions with questionable encodings, that when slightly adjusted, could significantly simplify verification and execution of programs.
Proposal at a glance
What changes
- the LDDW instruction (opcodes 0x18 and 0x00)
- the LE instruction (opcode 0xD4)
- the moved opcodes:
Stakeholder map
Who is affected
Builders & client teams Medium impact
The toolchain will emit machinecode according to the selected SBPF version. As most proposed changes affect the encoding only, and not the functionallity, we expect to see no impact on dApp developers. The only exception is that 64-bit immediate loads will now cost 2 CU instead of 1 CU.
Action requirement unknownValidators & 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 Impact unknown
No proposal-specific evidence was found for this group.
Action requirement unknownExact source revision
Full proposal document
0616093b2952Summary
There are some instructions with questionable encodings, that when slightly adjusted, could significantly simplify verification and execution of programs.
Motivation
The instruction lddw dst, imm is currently the only instruction which takes
two instruction slots. This proposal splits it into a two one-slot instruction
sequence: mov32 dst, imm and an introduced hor64 dst, imm. This way all
instructions will be exactly one slot long which will simplify:
- Calculating the number of instructons in a program will no longer require a full linear scan. A division of the length of the text section by the instruction slot size will suffice.
- The instruction meter will no longer have to skip one instruction slot when
counting a
LDDWinstruction. - Jump and call instructions will no longer have to verify that the desination
is not the second half of a
LDDWinstruction. - The verifier will no longer have to check that
LDDWinstructions are complete and its first or second half does not occur without the other on its own.
The LE instruction is essentially useless as only BE performs a byte-swap.
Its runtime behavior is close to no-op and can be replicated by other
instructions:
le dst, 16behaves the same asand32 dst, 0xFFFFle dst, 32behaves the same asand32 dst, 0xFFFFFFFFle dst, 64behaves the same asmov64 dst, src
The CALLX instruction encodes its source register in the immediate field.
This is makes the instruction decoder more complex because it is the only case
in which a register is encoded in the immediate field, for no reason.
With all of the above changes and the ones defined in SIMD-0174, the memory related instructions can be moved into the ALU instruction classes. Doing so would free up 8 instruction classes completely, giving us back three bits of instruction encoding.
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). Some now
unreachable verification and execution checks around LDDW can be safely
removed (see motivation).
Changes to the Bytecode Verifier
A program containing one of the following instructions must throw
VerifierError::UnknownOpCode during verification:
- the
LDDWinstruction (opcodes0x18and0x00) - the
LEinstruction (opcode0xD4) - the moved opcodes:
0x72,0x71,0x73(STB,LDXB,STXB)0x6A,0x69,0x6B(STH,LDXH,STXH)0x62,0x61,0x63(STW,LDXW,STXW)0x7A,0x79,0x7B(STDW,LDXDW,STXDW)
A program containing one of the following instructions must not throw
VerifierError::UnknownOpCode during verification anymore:
- the
HOR64instruction (opcode0xF7) - the moved opcodes:
0x27,0x2C,0x2F(STB,LDXB,STXB)0x37,0x3C,0x3F(STH,LDXH,STXH)0x87,0x8C,0x8F(STW,LDXW,STXW)0x97,0x9C,0x9F(STDW,LDXDW,STXDW)
When a CALLX instruction (opcode 0x8D) is encountered during verification,
the src register field must be verified instead of the imm immediate field.
Otherwise, the verification rule stays the same: The src register must be in
the inclusive range from R0 to R9.
Changes to Execution
The introduced HOR64 instruction (opcode 0xF7) must take its immediate
value, shift it 32 bit towards the MSBs (multiplication-like left shift) and
then bitwise OR it into the given dst register.
For the CALLX instruction (opcode 0x8D) the jump destination must be read
from the src register field instead of the imm immediate field.
The execution behavior of the moved instructions is transferred to their new opcodes:
0x72=>0x27,0x71=>0x2C,0x73=>0x2F0x6A=>0x37,0x69=>0x3C,0x6B=>0x3F0x62=>0x87,0x61=>0x8C,0x63=>0x8F0x7A=>0x97,0x79=>0x9C,0x7B=>0x9F
Impact
The toolchain will emit machinecode according to the selected SBPF version. As most proposed changes affect the encoding only, and not the functionallity, we expect to see no impact on dApp developers. The only exception is that 64-bit immediate loads will now cost 2 CU instead of 1 CU.
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 #173 · merged SIMD-0173: SBPF instruction encoding improvements 13 comments and reviews · Jan 26, 2026I think you should use say that the behavior will be transferred to the new opcodes. mapped may sound as if you would map the old instruction to new new ones, if the former appears in a programs.
GitHub ↗We should aim to bundle all of the ISA/opcode changes in the current set of ABIv1 SIMDs into the same SBPF version.
GitHub ↗The idea to split them in different versions was to avoid huge modifications and facilitate debugging in case an unforeseen problem arises after the ISA changes have been deployed.
GitHub ↗For information, (upstream) LLVM recently changed the encoding of CALLX to use dst register instead of the imm immediate field: https://github.com/llvm/llvm-project/pull/81546 (this landed in LLVM 19.1.0). Would modifying the proposal to use dst instead of src be acceptable?
GitHub ↗We could but it would require backports to v2.2. Also, the "dst" field? The destination is for registers to be written to, which callx does not. They probably thought: Oh, the jump destination, that must be the destination field.
GitHub ↗We could but it would require backports to v2.2. Thanks for the information. I was wondering whether SIMD-0173 was already frozen/not subject to change, as this Pull Request is not merged. It seems SBPF v2 (and v3 ?) are already frozen standards and a version bump would be needed to make other changes. It feels like much effort for only few improvements, to change the register used by CALLX. I don't have the bandwidth (or motivation) to work on this. Feel free to mark this comment as resolved. Also, the "dst" field? The destination is for registers to be written to, which callx does not. They probably thought: Oh, the jump destination, that must be the destination field. I don't know the rat
GitHub ↗Probably a little late for my comment, but the critique is still valid. Repurposing instruction classes brings no immediate benefit for either the validator or developers. We can only reap potential positive effects of this change if coupled with a future SIMD. Having said that, modifications like this could be postponed to when the gains are clear and well documented.
GitHub ↗For information (for future readers stumbling on this thread), modifying the encoding of callx to use the destination register (and to revert SIMD-0173) is now being discussed in SIMD-0377: eBPF ISA compatibility(https://github.com/solana-foundation/solana-improvement-documents/pull/377). The sBPF implementation was already modified: https://github.com/anza-xyz/sbpf/pull/89
GitHub ↗Provenance
Evidence & technical details
Rollout or chain data, source revisions, freshness and integrity. 2
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 · stale · Sep 10, 2026
0616093b2952ed6de52c4a27d66aadd11d48d4f9
One or more sources are unavailable.
simd.watch community discussion · SIMD-0173
Powered by Giscus · Sign in with GitHub to comment
Community comments load when this section approaches the viewport.