plonky2/evm/src/cpu/kernel/asm/mpt/hex_prefix.asm

105 lines
3.8 KiB
NASM
Raw Normal View History

2022-10-01 10:33:05 -07:00
// Computes the RLP encoding of the hex-prefix encoding of the given nibble list
// and termination flag. Writes the result to @SEGMENT_RLP_RAW starting at the
// given position, and returns the updated position, i.e. a pointer to the next
// unused offset.
//
// Pre stack: rlp_start_pos, num_nibbles, packed_nibbles, terminated, retdest
// Post stack: rlp_end_pos
global hex_prefix_rlp:
// stack: rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
// We will iterate backwards, from i = num_nibbles / 2 to i = 0, so that we
// can take nibbles from the least-significant end of packed_nibbles.
PUSH 2 DUP3 DIV // i = num_nibbles / 2
// stack: i, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
// Compute the length of the hex-prefix string, in bytes:
// hp_len = num_nibbles / 2 + 1 = i + 1
DUP1 %increment
2022-10-01 10:33:05 -07:00
// stack: hp_len, i, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
// Write the RLP header.
DUP1 %gt_const(55) %jumpi(rlp_header_large)
DUP1 %gt_const(1) %jumpi(rlp_header_medium)
// The hex-prefix is a single byte. It must be <= 127, since its first
// nibble only has two bits. So this is the "small" RLP string case, where
// the byte is its own RLP encoding.
// stack: hp_len, i, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
%jump(start_loop)
rlp_header_medium:
// stack: hp_len, i, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
2022-10-01 21:55:47 -07:00
DUP1 %add_const(0x80) // value = 0x80 + hp_len
2022-10-01 10:33:05 -07:00
DUP4 // offset = rlp_pos
%mstore_rlp
// rlp_pos += 1
SWAP2 %increment SWAP2
2022-10-01 10:33:05 -07:00
%jump(start_loop)
rlp_header_large:
// stack: hp_len, i, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
// In practice hex-prefix length will never exceed 256, so the length of the
// length will always be 1 byte in this case.
2022-10-01 21:55:47 -07:00
PUSH 0xb8 // value = 0xb7 + len_of_len = 0xb8
2022-10-01 10:33:05 -07:00
DUP4 // offset = rlp_pos
%mstore_rlp
DUP1 // value = hp_len
DUP4 %increment // offset = rlp_pos + 1
2022-10-01 10:33:05 -07:00
%mstore_rlp
// rlp_pos += 2
SWAP2 %add_const(2) SWAP2
start_loop:
// stack: hp_len, i, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
SWAP1
2022-09-30 13:04:16 -07:00
loop:
2022-10-01 10:33:05 -07:00
// stack: i, hp_len, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
2022-09-30 13:04:16 -07:00
// If i == 0, break to first_byte.
DUP1 ISZERO %jumpi(first_byte)
2022-10-01 10:33:05 -07:00
// stack: i, hp_len, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
DUP5 // packed_nibbles
2022-09-30 13:04:16 -07:00
%and_const(0xFF)
2022-10-01 10:33:05 -07:00
// stack: byte_i, i, hp_len, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
DUP4 // rlp_pos
DUP3 // i
ADD // We'll write to offset rlp_pos + i
%mstore_rlp
// stack: i, hp_len, rlp_pos, num_nibbles, packed_nibbles, terminated, retdest
%decrement
2022-10-01 10:33:05 -07:00
SWAP4 %shr_const(8) SWAP4 // packed_nibbles >>= 8
2022-09-30 13:04:16 -07:00
%jump(loop)
first_byte:
2022-10-01 10:33:05 -07:00
// stack: 0, hp_len, rlp_pos, num_nibbles, first_nibble_or_zero, terminated, retdest
2022-09-30 13:04:16 -07:00
POP
2022-10-01 10:33:05 -07:00
// stack: hp_len, rlp_pos, num_nibbles, first_nibble_or_zero, terminated, retdest
DUP2 ADD
// stack: rlp_end_pos, rlp_pos, num_nibbles, first_nibble_or_zero, terminated, retdest
SWAP4
// stack: terminated, rlp_pos, num_nibbles, first_nibble_or_zero, rlp_end_pos, retdest
2022-09-30 13:04:16 -07:00
%mul_const(2)
2022-10-01 10:33:05 -07:00
// stack: terminated * 2, rlp_pos, num_nibbles, first_nibble_or_zero, rlp_end_pos, retdest
%stack (terminated_x2, rlp_pos, num_nibbles, first_nibble_or_zero)
-> (num_nibbles, terminated_x2, first_nibble_or_zero, rlp_pos)
// stack: num_nibbles, terminated * 2, first_nibble_or_zero, rlp_pos, rlp_end_pos, retdest
%mod_const(2) // parity
2022-09-30 13:04:16 -07:00
ADD
2022-10-01 10:33:05 -07:00
// stack: parity + terminated * 2, first_nibble_or_zero, rlp_pos, rlp_end_pos, retdest
2022-09-30 13:04:16 -07:00
%mul_const(16)
ADD
2022-10-01 10:33:05 -07:00
// stack: first_byte, rlp_pos, rlp_end_pos, retdest
SWAP1
%mstore_rlp
// stack: rlp_end_pos, retdest
2022-09-30 13:04:16 -07:00
SWAP1
JUMP