All macros — alphabetical index

Every macro in the standard library, sorted by fully-qualified name and arity. 316 entries total.

Macro

File

Time

Space

Summary

bit._.cmp_next_eq/4

bit/cond_jumps

2@+4

3@+6

1 step of multi-bit bit.cmp.

bit._.print_str_one_char/2

bit/output

16@+32

16@+32

Print one byte from a null-terminated string; jumps to end when it hits \0. Inner loop of bit.print_str.

bit.add/3

bit/math

n(8@+14)

n(8@+14)

dst[:n] += src[:n]

bit.add1/3

bit/math

8@+14

8@+14

{carry:dst} += src

bit.address_and_variable_xor/4

bit/logics

n@

n@

address(bit_address) ^= src

bit.and/2

bit/logics

2@+2

2@+2

dst &= src

bit.and/3

bit/logics

n(2@+2)

n(2@+2)

dst[:n] &= src[:n]

bit.ascii2bin/3

bit/casting

17@+24

17@+24

if ascii is ‘0’/’1’, set bit to 0/1 (end error=0). else, set error=1.

bit.ascii2dec/3

bit/casting

25@+56

25@+56

if ascii is ‘0’-‘9’, set dec to that decimal digit value (end error=0). else, set error=1.

bit.ascii2hex/3

bit/casting

53@+86

53@+86

if ascii is ‘0’-‘9’/’a’-‘f’/’A’-‘F’, set hex to that hexadecimal digit value (end error=0). else, set error=1.

bit.bin2ascii/2

bit/casting

9@-7

9@-7

ascii := the ascii representation of the value of bin.

bit.bit/0

bit/memory

0 (data declaration)

1

Binary variable.

bit.bit/1

bit/memory

0 (data declaration)

1

Binary variable with initial value.

bit.cmp/5

bit/cond_jumps

2@+4

3@+6

Three-way compare on bits: jumps to lt if a<b, eq if a==b, gt if a>b. a, b are bits; lt, eq, gt are addresses.

bit.cmp/6

bit/cond_jumps

n(2@+4)

n(3@+6)

Three-way compare on n-bit vectors: jumps to lt if a[:n]<b[:n], eq if equal, gt if a[:n]>b[:n].

bit.dec/2

bit/math

2n + 5@+12

n(2@+6)

x[:n]--

bit.dec2ascii/2

bit/casting

12@-10

12@-10

ascii := the ascii representation of the value of dec.

bit.div/5

bit/div

n^2(10@+20)

n^2(11@+22)

Unsigned integer division: q = a/b, r = a%b. Jumps to end if b==0. q, a, b, r are bit[:n]. Wasteful in space — prefer …

bit.div.div_step/5

bit/div

n(10@+20)

n(11@+22)

One step of bit-level long division: R[0] ^= N; then if R[:n] >= D[:n], do R -= D and toggle Q[0]. The inner loop of bit.div / …

bit.div10/3

bit/div

n(5@+11)

n(5@+11)

dst[:n], src[:n] = src[:n] / 10, src[:n] % 10.

bit.div10.cmp_sub_10/3

bit/div

4@+12

4@+12

if (val &gt; 10) {

bit.div_loop/5

bit/div

n^2(18@+18)

n(25@+22)

Compact unsigned integer division (slower than bit.div, but uses much less program space): q = a/b, r = a%b. Jumps to end if b==0.

bit.double_exact_xor/3

bit/logics

@

@

dst1(bit_address) ^= src

bit.exact_not/1

bit/logics

1

1

dst(bit_address) ^= 1

bit.exact_xor/2

bit/logics

@-1

@-1

dst(bit_address) ^= src

bit.exact_xor_from_ptr/2

bit/pointers

8w@

8w@

Effectively:  bit.exact_xor dst, *ptr

bit.hex2ascii/2

bit/casting

15@+7

21@+30

ascii := the ascii representation of the value of hex (digits & capital-letters).

bit.idiv/5

bit/div

n^2(10@+20)

n^2(11@+22)

Signed integer division: q = a/b, r = a%b with sign(r)==sign(a). Jumps to end if b==0. q, a, b, r are bit[:n]. Wasteful …

bit.idiv_loop/5

bit/div

n^2(18@+18)

n(37@+58)

Compact signed integer division (slower than bit.idiv, but uses much less program space): q = a/b, r = a%b with sign(r)==sign(a). …

bit.if/3

bit/cond_jumps

@+2

@+2

if x == 0 jump to l0, else jump to l1

bit.if/4

bit/cond_jumps

n(@+2)

n(@+2)

if x[:n] == 0 jump to l0, else jump to l1

bit.if0/2

bit/cond_jumps

@+2

@+2

if x == 0 jump to l0

bit.if0/3

bit/cond_jumps

n(@+2)

n(@+2)

if x[:n] == 0 jump to l0

bit.if1/2

bit/cond_jumps

@+2

@+2

if x == 1 jump to l1

bit.if1/3

bit/cond_jumps

n(@+2)

n(@+2)

if the x[:n] != 0 jump to l1

bit.inc/2

bit/math

5@+12 in average

n(2@+6)

x[:n]++

bit.inc.inc1_with_carry0_jump/3

bit/math

2@+6

2@+6

{carry:dst}++

bit.inc1/2

bit/math

2@+6

2@+6

{carry:dst}++

bit.input/1

bit/input

16@-16

16@-16

input one byte into dst[:8] (lsb first)

bit.input/2

bit/input

n(16@-16)

n(16@-16)

Effectively inputs an 8*n bits little endian number into dst[:8n].

bit.input_bit/1

bit/input

2@-2

2@-2

input one bit into the bit-variable, ‘dst’.

bit.mov/2

bit/memory

2@-1

2@-1

dst = src

bit.mov/3

bit/memory

n(2@-2)

n(2@-2)

dst[:n] = src[:n]

bit.mul/3

bit/mul

n*b(8@+14)    if b==n/2:  n^2(4@+7)

n^2(8@+14)

dst[:n] *= src[:n]

bit.mul.mul_add_if/4

bit/mul

n(8@+14)

n(8@+14)

if flag: dst[:n] += src[:n] — conditional in-place add. flag is a bit.

bit.mul10/2

bit/mul

n(14@+10)

n(14@+10)

x[:n] *= 10

bit.mul_loop/3

bit/mul

n^2(6@+2) + n*b(8@+14)    if b==n/2:  n^2(10@+9)

n(21@+11)

dst[:n] *= src[:n]

bit.neg/2

bit/math

n + 5@+12

n(2@+6)

x[:n] = -x[:n]

bit.not/1

bit/logics

1

1

dst ^= 1

bit.not/2

bit/logics

n

n

dst[:n] ^= (1&lt;&lt;n)-1

bit.one/1

bit/memory

@

@

bit = 1

bit.one/2

bit/memory

n@

n@

x[:n] = (1&lt;&lt;n) - 1   // all 1's

bit.or/2

bit/logics

2@+2

2@+2

dst |= src

bit.or/3

bit/logics

n(2@+2)

n(2@+2)

dst[:n] |= src[:n]

bit.output/1

bit/output

@+2

@+2

outputs the bit ‘x’.

bit.pointers.advance_by_one_and_flip__ptr_wflip/2

bit/pointers

@+n+1

@+n+1

Advances *to_flip by 1 (which takes n flips, from bit0 to bit1, bit2,…).

bit.pointers.ptr_init/0

bit/pointers

O(1)

2w+2

Initializes the global opcodes and pointer-copies required for the pointers macros.

bit.pointers.set_flip_pointer/1

bit/pointers

2w@

2w@

Sets both to_flip and to_flip_var to point to the given pointer.

bit.pointers.set_jump_pointer/1

bit/pointers

2n@

2n@

Sets both to_jump and to_jump_var to point to the given pointer.

bit.print/1

bit/output

8@+16

8@+16

outputs a byte from x[:8] (a bit vector. from lsb to msb).

bit.print/2

bit/output

n(8@+16)

n(8@+16)

outputs n bytes from x[:8n] (a bit vector. from lsb to msb).

bit.print_as_digit/1

bit/output

@+9

@+9

prints the ascii character ‘0’/’1’, based on x’s value.

bit.print_as_digit/2

bit/output

@+9

@+9

prints x[:n] as n ascii-characters (‘0’s and ‘1’s, lsb first).

bit.print_dec_int/2

bit/output

n^2(2@+4)  // actually: nd(7@+12)  (for d number of decimal digits)

n(16@+23)

prints x[:n] as a signed decimal number (without leading zeros).

bit.print_dec_uint/2

bit/output

n^2(2@+4)  // actually: nd(7@+12)  (for d number of decimal digits)

n(14@+16)

prints x[:n] as an unsigned decimal number (without leading zeros).

bit.print_dec_uint.div10_step/8

bit/output

n(7@+12)

11@-3

One step inside bit.print_dec_uint: divides src by 10, stashes the remainder as an ASCII digit, and trips char_flag to make this …

bit.print_dec_uint.print_char/2

bit/output

5@+12

5@+12

if char_flag: print the ascii representation of the decimal digit ascii4[:4].

bit.print_hex_int/3

bit/output

n(7@+13)

n(7@+13)

print x[:n] as a signed hexadecimal number, without leading zeros (digits & capital-letters).

bit.print_hex_uint/3

bit/output

n(7@+11)

n(7@+11)

print x[:n] as an unsigned hexadecimal number, without leading zeros (digits & capital-letters).

bit.print_hex_uint.print_digit/2

bit/output

29@+34

35@+57

Print one hex digit, but only after the first non-zero digit has been seen (suppresses leading zeros). Inner loop of bit.print_hex_uint.

bit.print_str/2

bit/output

min(n, len+1)*(16@+32)

min(n, len+1)*(16@+32)

Prints the first n-chars of the string at x[:8n], or until reaches the first '\0' (the earlier).

bit.ptr_dec/1

bit/pointers

2w + 5@+12

w(2@+6)

ptr[:n] -= 2w

bit.ptr_flip/1

bit/pointers

2w@ + @

2w@ + @

Flip the bit whose address is stored in ptr. Effectively *ptr;.

bit.ptr_flip_dbit/1

bit/pointers

2w@ + 2@

2w@ + 2@

Effectively:  (*ptr)+dbit;

bit.ptr_inc/1

bit/pointers

5@+12

w(2@+6)

ptr += 2w — advance a w-wide bit-pointer by one dw-aligned word.

bit.ptr_jump/1

bit/pointers

2w@ + 2

2w@ + 2

Jump to the address stored in ptr. Effectively ;*ptr.

bit.ptr_wflip/2

bit/pointers

Effectively:  wflip *ptr, value

bit.ptr_wflip_2nd_word/2

bit/pointers

3w@

3w@

Effectively:  wflip (*ptr)+w, value

bit.rol/2

bit/shifts

n(2@-1)

n(2@-1)

rotate x[:n] left by 1-bit

bit.ror/2

bit/shifts

n(2@-1)

n(2@-1)

rotate x[:n] right by 1-bit

bit.shl/2

bit/shifts

n(2@-1)

n(2@-1)

x[:n] &lt;&lt;= 1

bit.shl/3

bit/shifts

n(2@-1)

n(2@-1)

x[:n] &lt;&lt;= times

bit.shr/2

bit/shifts

n(2@-1)

n(2@-1)

x[:n] &gt;&gt;= 1

bit.shr/3

bit/shifts

n(2@-1)

n(2@-1)

x[:n] &gt;&gt;= times

bit.shra/3

bit/shifts

n(2@-1)

n(2@-1)

x[:n] >>= times (arithmetic shift right)

bit.str/1

bit/casting

0 (data declaration)

(#str+15)&(~7)  // which is (strlen(str)+1)*8

used to initialize a string, like:   bit.str "Hello, World!\n"

bit.sub/3

bit/math

n(8@+16)

n(8@+16)

dst[:n] -= src[:n]

bit.swap/2

bit/memory

2@+5

3@+8

a, b = b, a

bit.swap/3

bit/memory

n(2@+5)

n(3@+8)

a[:n], b[:n] = b[:n], a[:n]

bit.unsafe_mov/2

bit/memory

2@-2

2@-2

dst = src

bit.vec/1

bit/memory

0 (data declaration)

n

Binary vector.

bit.vec/2

bit/memory

0 (data declaration)

n

Binary vector with initial value.

bit.xor/2

bit/logics

@-1

@-1

dst ^= src

bit.xor/3

bit/logics

n(@-1)

n(@-1)

dst[:n] ^= src[:n]

bit.xor_from_ptr/2

bit/pointers

8w@

8w@

Effectively: bit.xor dst, *ptr

bit.xor_to_ptr/2

bit/pointers

2w@ + 2@+2

2w@ + 2@+2

Effectively:  bit.xor *ptr, bit

bit.xor_zero/2

bit/logics

@

@

dst ^= src

bit.xor_zero/3

bit/logics

n@

n@

dst[:n] ^= src[:n]

bit.zero/1

bit/memory

@-1

@-1

bit = 0

bit.zero/2

bit/memory

n(@-1)

n(@-1)

x[:n] = 0

hex.abs/2

hex/math_basic

2@+4n

n(1.5@+20)

x[:n] = |x[:n]| (two’s complement; the minimal value -2^(4n-1) stays itself)

hex.add/2

hex/math

4@+12

4@+52

dst += src

hex.add/3

hex/math

n(4@+12)

n(4@+52)

dst[:n] += src[:n]

hex.add.add_constant_with_leading_zeros/4

hex/math

n_const(4@+12) + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

Internal helper for hex.add_constant: strips const’s trailing zero nibbles, then adds the result back into dst[:n] at the matching …

hex.add.add_hex_shifted_constant/4

hex/math

n_const(4@+12) + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

Wrapper around the 5-arity add_hex_shifted_constant: derives n_const = (#const + 3) / 4 automatically so the caller doesn’t have to …

hex.add.add_hex_shifted_constant/5

hex/math

n_const(4@+12)   + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

dst[:dst_n] += const &lt;&lt; (4*hex_shift)

hex.add.clear_carry/0

hex/math

2@

2@+12

carry = 0

hex.add.clear_carry/2

hex/math

2@+1

2@+16

carry = 0. jump to c0 if it was 0, and to c1 otherwise.

hex.add.init/0

hex/math

8 (when jumping to dst, until finished)

1570

Its 9-bits are expected to be {carry&lt;<8 | src&lt;<4 | dst} at the jump to it (for the src,dst hexes, and the carry bit, of the …

hex.add.not_carry/0

hex/math

1

1

carry = !carry

hex.add.set_carry/0

hex/math

2@+1

2@+13

carry = 1

hex.add_constant/3

hex/math

n_const(4@+12)   + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

dst[:n] += const

hex.add_count_bits/3

hex/math_basic

2.27@-1                // (2@-10 + 2 + 4 + 3 + 0.25*[16@/15])

0.5@+109 + n(1.5@+13)  // (2@-10 + 16(1+4+1+2) + 4 + (n-1)(1.5@+13))

dst[:n] += src.#on-bits (between 0-&gt;4)

hex.add_mul/2

hex/mul

5@+26

4@+52

res += x * dst + carry_dst — one shift-and-add (multiply-accumulate) step used by hex.mul. Reads/writes the global multiplication carry.

hex.add_mul/4

hex/mul

n(5@+26)

n(4@+52)

res[n] += a[n] * b[1]

hex.add_shifted/5

hex/math

src_n(4@+12)   + 5@+1        // It's on average, see the note in hex.inc.

src_n(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+28

dst[:dst_n] += src[:src_n] &lt;&lt; (4*hex_shift)

hex.address_and_variable_double_xor/6

hex/logics

n(@+12)

n(@+60)

address1(bit_address) ^= src

hex.address_and_variable_xor/4

hex/logics

n(@+4)

n(@+28)

address(bit_address) ^= src

hex.and/2

hex/logics

4@+10

4@+52

dst &amp;= src

hex.and/3

hex/logics

n(4@+10)

n(4@+52)

dst[:n] &amp;= src[:n]

hex.and.init/0

hex/logics

6 (when jumping to dst, until finished)

595

Its 8-bits are expected to be {src&lt;<4 | dst} at the jump to it (for the src,dst hexes of the and operation).

hex.cmp/5

hex/cond_jumps

3@+8

3@+30

Three-way compare on hex nibbles: jumps to lt if a<b, eq if a==b, gt if a>b. a, b are hexes; lt, eq, gt are addresses.

hex.cmp/6

hex/cond_jumps

m(3@+8)        // m=(n-i), where i is the most-significant index such that a[i] != b[i] (if a==b, then m==n).

n(3@+30)

Three-way compare on n-nibble hex vectors: jumps to lt if a[:n]<b[:n], eq if equal, gt if a[:n]>b[:n].

hex.cmp.cmp_eq_next/4

hex/cond_jumps

3@+8

3@+30

1 step of multi-nibble hex.cmp.

hex.cmp.init/0

hex/cond_jumps

6 (when jumping to dst, until finished)

514

Its 8-bits are expected to be {src&lt;<4 | dst} at the jump to it (for the src,dst hexes of the cmp operation).

hex.copy_bytes/3

hex/strings

count(w(1.75@+10) + 45@+80)

w(4.5@+90) + 55@+450

Copies “count[:w/4]” bytes from the src-pointed buffer to the dst-pointed buffer.

hex.count_bits/3

hex/math_basic

n(2.27@-1)

n(3.5@+135)    // on 16-255 bit-numbers. (a bit bigger on bigger numbers).

dst[:small_n] = x[:n].#on-bits

hex.dec/2

hex/math_basic

1.067@     // It's on average. To be exact: 16/15 * @.

n(1.5@+13)

hex[:n]--

hex.dec.step/2

hex/math_basic

@

1.5@+13

One nibble of a propagating decrement: decrement hex by 1; on underflow continue to the next nibble, else jump to end.

hex.dec1/3

hex/math_basic

@

1.5@+13

hex-- (if underflows - jump to borrow1; else jump to borrow0)

hex.div/7

hex/div

n^2(2@+8) + n*nb(34@+92)   so if nb==n:  n^2(36@+100)

n(4@+81)  + nb(16@+243)    so if nb==n:  n(20@+324)

Unsigned integer division: q = a/b, r = a%b. Jumps to div0 if b==0. q, a are hex[:n]; r, b are hex[:nb].

hex.double_exact_xor/9

hex/logics

@+4

@+28

{t3,t2,t1,t0} ^= src

hex.double_xor/3

hex/logics

@+4

@+28

dst1 ^= src

hex.exact_xor/5

hex/logics

@

@+12

{d3,d2,d1,d0} ^= src

hex.fill_bytes/3

hex/strings

count(w(@+5) + 28@+55)

w(2.25@+44) + 35@+300

Fills “count[:w/4]” bytes of the pointed buffer with the value byte.

hex.hex/0

hex/memory

0 (data declaration)

1

Hexadecimal variable.

hex.hex/1

hex/memory

0 (data declaration)

1

Hexadecimal variable with initial value.

hex.idiv/8

hex/div

n^2(2@+8) + n*nb(34@+92)   so if nb==n:  n^2(36@+100)

n(8.5@+132)  + nb(21.5@+309)    so if nb==n:  n(30@+441)

Signed integer division with configurable remainder convention (rem_opt: 0 = sign(r)==sign(b), Python-style floor division; 1 = …

hex.if/3

hex/cond_jumps

@-1

@+15

if hex==0 goto l0, else goto l1.

hex.if/4

hex/cond_jumps

n(@-1)

n(@+15)

if hex[:n]==0 goto l0, else goto l1.

hex.if0/2

hex/cond_jumps

@-1

@+15

if hex==0 goto l0, else continue.

hex.if0/3

hex/cond_jumps

n(@-1)

n(@+15)

if hex[:n]==0 goto l0, else continue.

hex.if1/2

hex/cond_jumps

@-1

@+15

if hex!=0 goto l1, else continue.

hex.if1/3

hex/cond_jumps

n(@-1)

n(@+15)

if hex[:n]!=0 goto l1, else continue.

hex.if_flags/4

hex/cond_jumps

@-1

@+15

Jumps to l1 if bit hex of the 16-bit flags constant is set, else l0.

hex.inc/2

hex/math_basic

1.067@     // It's on average. To be exact: 16/15 * @.

n(1.5@+13)

hex[:n]++

hex.inc.step/2

hex/math_basic

@

1.5@+13

One nibble of a propagating increment: increment hex by 1; on overflow continue to the next nibble, else jump to end.

hex.inc1/3

hex/math_basic

@

1.5@+13

hex++ (if overflows - jump to carry1; else jump to carry0)

hex.init/0

hex/tables_init

O(1)

6500   (6464+@)

Initialise every truth table that the hex.* macros depend on. Call this exactly once at program start; bundled into …

hex.input/1

hex/input

4@+14

4@+36

byte[:2] = input(8bits) // lsb first

hex.input/2

hex/input

n(4@+14)

n(4@+36)

bytes[:2n] = input(8n-bits) // lsb first

hex.input_as_hex/2

hex/input

7@+11

8.5@+92

hex = hex_from_ascii(input(1byte))

hex.input_as_hex/3

hex/input

n(7@+11)

n(8.5@+92)

hex[:n] = hex_from_ascii(input(n-bytes))

hex.input_dec_int/3

hex/input

~ nd(10@+39)    (d = number of digits)

~ n(10.5@+167)

dst[:n] = the signed decimal number read from input (two’s complement, mod 16^n).

hex.input_dec_int_until/3

hex/input

~ nd(10@+39)    (d = number of digits)

~ n(10.5@+149)

dst[:n] = the signed decimal number read from input (two’s complement, mod 16^n).

hex.input_dec_uint/3

hex/input

~ nd(10@+39)    (d = number of digits)

~ n(9@+150)

dst[:n] = the unsigned decimal number read from input (mod 16^n).

hex.input_dec_uint_until/3

hex/input

~ nd(10@+39)    (d = number of digits)

~ n(9@+132)

dst[:n] = the unsigned decimal number read from input (mod 16^n).

hex.input_hex/1

hex/input

2@+7

2@+18

hex := input(4bits) // lsb first

hex.input_ptr_line/2

hex/strings

len(w(0.75@+5) + 39@+79)

w(2.25@+44) + 34@+381

Reads bytes from input into the pointed buffer, until a '\n' or a 0-byte (EOF); writes the byte count into len[:w/4].

hex.max/4

hex/cond_jumps

n(5@+8)     (cmp is data-dependent; worst case)

n(6@+66)

dst[:n] = max(a[:n], b[:n])   (unsigned)

hex.min/4

hex/cond_jumps

n(5@+8)     (cmp is data-dependent; worst case)

n(6@+66)

dst[:n] = min(a[:n], b[:n])   (unsigned)

hex.mov/2

hex/memory

2@+1

2@+25

dst = src

hex.mov/3

hex/memory

n(2@)

n(2@+24)

dst[:n] = src[:n]

hex.mul/4

hex/mul

n^2(3@+7) + n*b(5@+26)

n(21@+479)

for n==b/2: n^2(5.5@+20)

hex.mul.clear_carry/0

hex/mul

3@+1

3@+1

Reset the per-multiplication carry-tracking variable to zero. Called by hex.add_mul at the start and end of each addition step (and …

hex.mul.init/0

hex/mul

@+24 (when jumping to dst, until finished)

1620+@

dst[1] is zeroed after finishing this multiplication.

hex.mul10/2

hex/mul

n(6@+27)

n(5@+80)

x[n] *= 10

hex.neg/2

hex/math_basic

~@+4n

n(1.5@+17)

x[:n] = -x[:n]

hex.not/1

hex/logics

4

4

hex = !hex  (15-hex)

hex.not/2

hex/logics

4n

4n

x[:n] = !x[:n]

hex.or/2

hex/logics

4@+10

4@+52

dst |= src

hex.or/3

hex/logics

n(4@+10)

n(4@+52)

dst[:n] |= src[:n]

hex.or.init/0

hex/logics

6 (when jumping to dst, until finished)

595

Its 8-bits are expected to be {src&lt;<4 | dst} at the jump to it (for the src,dst hexes of the or operation).

hex.output/1

hex/output

@

@+26

output 4 bits from hex (lsb first)

hex.pointers.advance_by_one_and_flip__ptr_wflip/2

hex/pointers/xor_to_pointer

@+n+1

@+n+1

Advances *to_flip by 1 (which takes n flips, from bit0 to bit1, bit2,…).

hex.pointers.ptr_init/0

hex/pointers/basic_pointers

O(1)

0.75w+261

One-time initialisation of the pointer dispatch infrastructure: global opcodes, pointer-copies, and the read-byte handling table. Must be …

hex.pointers.read_byte_from_inners_ptrs/0

hex/pointers/xor_from_pointer

5@+13

5@+24

hex.pointers.read_byte[:2] = *ptr — read one byte through the currently-set flip/jump pointers. Use after …

hex.pointers.set_flip_and_jump_pointers/1

hex/pointers/basic_pointers

w(0.75@+5)

w(0.75@+29)

Sets both to_flip and to_flip_var, and to_jump and to_jump_var to point to the given pointer.

hex.pointers.set_flip_pointer/1

hex/pointers/basic_pointers

w(0.5@+2)

w(0.5@+14)

Sets both to_flip and to_flip_var to point to the given pointer.

hex.pointers.set_jump_pointer/1

hex/pointers/basic_pointers

w(0.5@+2)

w(0.5@+14)

Sets both to_jump and to_jump_var to point to the given pointer.

hex.pointers.stack_init/1

hex/pointers/basic_pointers

O(1)

n+w/4 + 330

Initializes a stack of size n (maximal capacity of n hexes / return-addresses).

hex.pointers.xor_byte_to_flip_ptr/1

hex/pointers/xor_to_pointer

10@+24

10@+152

xors (the byte hex[2:]) to the byte pointed by the memory-word hex.pointers.to_flip.

hex.pointers.xor_byte_to_ptr_and_inc/2

hex/pointers/xor_to_pointer

w(0.5@+2)  + 19@+38

w(0.9@+17) + 15@+207

Effectively:  hex.xor *ptr, hex[:2]

hex.pointers.xor_hex_to_flip_ptr/1

hex/pointers/xor_to_pointer

5@+12

5@+76

xors (the parameter hex) to the hex pointed by the memory-word hex.pointers.to_flip.

hex.pointers.xor_hex_to_flip_ptr/2

hex/pointers/xor_to_pointer

5@+12

5@+76

xors (the parameter hex, shifted left by bit_shift) to the hex/byte pointed by the memory-word hex.pointers.to_flip.

hex.pointers.xor_hex_to_ptr_and_inc/2

hex/pointers/xor_to_pointer

w(0.5@+2)  + 14@+26

w(0.9@+17) + 10@+131

Effectively:  hex.xor *ptr, hex

hex.pop/2

hex/pointers/stack

n(w(0.38@+ 3) + 9@+18)

n(w(0.56@+16) + 7@+70)

Effectively:  sp -= M

hex.pop_byte/1

hex/pointers/stack

w(0.75@+ 5) + 18@+ 36

w(1.13@+32) + 14@+139

Effectively:  byte[:2] = stack[sp--]

hex.pop_hex/1

hex/pointers/stack

w(0.75@+ 5) + 16@+ 36

w(1.13@+32) + 12@+115

Effectively:  hex = stack[sp--]

hex.pop_ret_address/1

hex/pointers/stack

w(  1.5@+ 5) + 9@+23

w(1.875@+20) + 5@+67

Effectively:  stack[sp--] = 0

hex.print/1

hex/output

2@

2@+52

output 8 bits from x[:2] (lsb first)

hex.print/2

hex/output

n(2@)

n(2@+52)

output n bytes from x[:2n] (lsb first)

hex.print_as_digit/2

hex/output

@+4

@+36

prints the ascii of the hexadecimal representation of hex.

hex.print_as_digit/3

hex/output

n(@+4)

n(@+36)

prints the ascii of the hexadecimal representation of x[:n].

hex.print_dec_int/2

hex/output

nd(28@+48) + n(5@+4)    (for d number of decimal digits)

n(59@+98)

prints x[:n] as a signed DECIMAL number (without leading zeros).

hex.print_dec_uint/2

hex/output

nd(28@+48) + n(5@-4)    (for d number of decimal digits)

n(56@+64)

prints x[:n] as an unsigned DECIMAL number (without leading zeros).

hex.print_int/4

hex/output

n(2@+10)

n(4.5@+71)

print the signed x[:n], without leading zeros.

hex.print_ptr_line/2

hex/strings

len(w(0.75@+5) + 29@+41)

w(2.25@+45) + 28@+220

Prints bytes from the pointed buffer, until a '\n' or a 0-byte (EOF); writes the byte count into len[:w/4].

hex.print_ptr_text/2

hex/strings

len(w(@+5) + 21@+27)

w(3@+55) + 16@+179

Prints len[:w/4] bytes from the pointed buffer.

hex.print_uint/4

hex/output

n(2@+6)

n(3@+54)

print the unsigned x[:n], without leading zeros.

hex.print_uint.print_digit/3

hex/output

2@+6

3@+54

print the ascii of the hexadecimal representation of hex (skip leading zeros, based on printed_something)

hex.ptr_add/2

hex/pointers/pointer_arithmetics

13@+26

w(0.375@ + 3.25) + 7.5@+94

ptr[:w/4] += value * 2w (advance ptr by value)

hex.ptr_dec/1

hex/pointers/pointer_arithmetics

9@+23

w(0.375@ + 3.25)  + 5@+67  (for log(w) in 16,32,64,128)

ptr[:w/4] -= 2w

hex.ptr_flip/1

hex/pointers/xor_to_pointer

w(0.5@+2)  + @

w(0.5@+14) + @

Flip the bit whose address is stored in ptr. Effectively *ptr;.

hex.ptr_flip_dbit/1

hex/pointers/xor_to_pointer

w(0.5@+2)  + @+6

w(0.5@+14) + @+6

Effectively:  (*ptr)+dbit;

hex.ptr_inc/1

hex/pointers/pointer_arithmetics

9@+14

w(0.375@ + 3.25)  + 5@+55  (for log(w) in 16,32,64,128)

ptr[:w/4] += 2w

hex.ptr_index/3

hex/pointers/pointer_arithmetics

w(2.25@+5.25)

w(2.25@+40)

dst[:w/4] = ptr + index*2w — the address of the index-th dw-aligned op past *ptr.

hex.ptr_jump/1

hex/pointers/basic_pointers

w(0.5@+2)

w(0.5@+14)

Jump to the address stored in ptr. Effectively ;*ptr.

hex.ptr_sub/2

hex/pointers/pointer_arithmetics

13@+35

w(0.375@ + 3.25)  + 7.5@+106

ptr[:w/4] -= value * 2w (retreat ptr by value)

hex.ptr_wflip/2

hex/pointers/xor_to_pointer

w(1.5@+5)

w(1.5@+17)

Effectively:  wflip *ptr, value

hex.ptr_wflip_2nd_word/2

hex/pointers/xor_to_pointer

w(1.5@+5)

w(1.5@+17)

Effectively:  wflip (*ptr)+w, value

hex.push/2

hex/pointers/stack

n(w(0.38@+ 3) + 13@+ 25)

n(w(0.56@+16) + 11@+128)

Effectively:  stack[sp+1:][:M] = hex[:n];  sp += n.

hex.push_byte/1

hex/pointers/stack

w(0.75@+ 5) + 26@+ 51

w(1.13@+32) + 22@+255

Effectively:  stack[++sp] = byte[:2]

hex.push_hex/1

hex/pointers/stack

w(0.75@+ 5) + 20@+ 39

w(1.13@+32) + 16@+167

Effectively:  stack[++sp] = hex

hex.push_ret_address/1

hex/pointers/stack

w(2.25@+10) +  9@+ 51

w(2.62@+49) + 20@+231

Effectively:  stack[++sp] = return_address

hex.quadrupled_exact_xor/17

hex/logics

@+12

@+60

{q3,q2,q1,q0} ^= src

hex.read_byte/2

hex/pointers/read_pointers

w(0.75@+ 5) + 9@+13

w(0.75@+29) + 9@+72

Effectively:  dst[:2] = *ptr

hex.read_byte/3

hex/pointers/read_pointers

n(w(0.75@+ 5) + 18@+27)

n(w(1.13@+32) + 14@+127)

Effectively:  dst[:2n] = *ptr[:n]

hex.read_byte_and_inc/2

hex/pointers/read_pointers

w(0.75@+ 5) + 18@+27

w(1.13@+32) + 14@+127

Effectively:  dst[:2] = *ptr

hex.read_hex/2

hex/pointers/read_pointers

w(0.75@+ 5) + 7@+13

w(0.75@+29) + 7@+48

Effectively:  dst = *ptr

hex.read_hex/3

hex/pointers/read_pointers

n(w(0.75@+ 5) + 16@+27)

n(w(1.13@+32) + 12@+103)

Effectively:  dst[:n] = *ptr[:n]

hex.read_hex_and_inc/2

hex/pointers/read_pointers

w(0.75@+ 5) + 16@+27

w(1.13@+32) + 12@+103

Effectively:  dst = *ptr

hex.read_nth_byte/3

hex/pointers/read_pointers

w(3@+10.25) + 9@+13

w(3@+69)    + 9@+72

dst[:2] = *(ptr + index*2w) — read the index-th byte past *ptr.

hex.read_nth_hex/3

hex/pointers/read_pointers

w(3@+10.25) + 7@+13

w(3@+69)    + 7@+48

dst = *(ptr + index*2w) — read the index-th hex past *ptr.

hex.scmp/6

hex/cond_jumps

n(7@+8) + 8

n(7@+80) + 8

Three-way SIGNED compare (two’s complement) on n-nibble hex vectors: jumps to lt if a[:n]<b[:n], eq if equal, gt if a[:n]>b[:n]. …

hex.set/2

hex/memory

@+4

@+16

hex = val (constant)

hex.set/3

hex/memory

n(@+4)

n(@+16)

hex[:n] = val (constant)

hex.shifts.shl_bit_once/2

hex/shifts

@+1

@+28

{next(1bit),dst(1hex)} = dst &lt;&lt; 1

hex.shifts.shr_bit_once/2

hex/shifts

@+1

@+28

{next(1bit),dst(1hex)} = dst &gt;&gt; 1

hex.shl_bit/2

hex/shifts

n(@+1)

n(@+28)

dst[:n] &lt;&lt;= 1

hex.shl_hex/2

hex/shifts

n(@+4)

n(@+28)

dst[:n] &lt;&lt;= 4

hex.shl_hex/3

hex/shifts

n(@+4)

n(@+28)

dst[:n] &lt;&lt;= 4*times

hex.shr_bit/2

hex/shifts

n(@+1)

n(@+28)

dst[:n] &gt;&gt;= 1

hex.shr_hex/2

hex/shifts

n(@+4)

n(@+28)

dst[:n] &gt;&gt;= 4

hex.shr_hex/3

hex/shifts

n(@+4)

n(@+28)

dst[:n] &gt;&gt;= 4*times

hex.sign/4

hex/cond_jumps

@-1

@+15

if number[:n] < 0 jump to neg, else jump to zpos (Zero POSitive).

hex.sign_extend/3

hex/math_basic

(full_n - signed_n)(@+4)

(full_n - signed_n)(@+16)

sign-extends hex[:signed_n] into hex[:full_n]

hex.sp_add/1

hex/pointers/stack

13@+26

w(0.375@ + 3.25) + 7.5@+94

Effectively:  sp += value

hex.sp_dec/0

hex/pointers/stack

9@+23

w(0.375@ + 3.25)  + 5@+67

Effectively:  sp--

hex.sp_inc/0

hex/pointers/stack

9@+14

w(0.375@ + 3.25)  + 5@+55

Effectively:  sp++

hex.sp_sub/1

hex/pointers/stack

13@+35

w(0.375@ + 3.25)  + 7.5@+106

Effectively:  sp -= value

hex.sub/2

hex/math

4@+12

4@+52

dst -= src

hex.sub/3

hex/math

n(4@+12)

n(4@+52)

dst[:n] -= src[:n]

hex.sub.clear_carry/0

hex/math

2@+5

2@+20

carry = 0

hex.sub.clear_carry/2

hex/math

2@+5

2@+20

carry = 0. jump to c0 if it was 0, and to c1 otherwise.

hex.sub.init/0

hex/math

8 (when jumping to dst, until finished)

1570

Its 9-bits are expected to be {carry&lt;<8 | src&lt;<4 | dst} at the jump to it (for the src,dst hexes, and the carry bit, of the …

hex.sub.not_carry/0

hex/math

1

1

carry = !carry

hex.sub.set_carry/0

hex/math

2@+6

2@+21

carry = 1

hex.sub.sub_constant_with_leading_zeros/4

hex/math

n_const(4@+12) + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

Internal helper for hex.sub_constant: strips const’s trailing zero nibbles, then subtracts the result from dst[:n] at the matching …

hex.sub.sub_hex_shifted_constant/4

hex/math

n_const(4@+12) + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

Wrapper around the 5-arity sub_hex_shifted_constant: derives n_const = (#const + 3) / 4 automatically so the caller doesn’t have to …

hex.sub.sub_hex_shifted_constant/5

hex/math

n_const(4@+12)   + 5@+2

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+29

dst[:dst_n] -= const &lt;&lt; (4*hex_shift)

hex.sub_constant/3

hex/math

n_const(4@+12)   + 5@+11

n_const(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+41

dst[:dst_n] -= const

hex.sub_shifted/5

hex/math

src_n(4@+12)   + 5@+10        // It's on average, see the note in hex.inc.

src_n(2.5@+39) + (dst_n - hex_shift)(1.5@+13) + 4@+40

dst[:dst_n] -= src[:src_n] &lt;&lt; (4*hex_shift)

hex.swap/2

hex/memory

3@+1

3@+37

hex1, hex2 = hex2, hex1

hex.swap/3

hex/memory

n(3@)

n(3@+36)

hex1[:n], hex2[:n] = hex2[:n], hex1[:n]

hex.tables.clean_table_entry__table/1

hex/tables_init

4

256

A table. When jumping to entry d - it xors d into dst, and jumps to hex.tables.ret

hex.tables.clean_table_entry__table/3

hex/tables_init

log(n) / 2     (an overage over all entries, of jumping to an entry in this table)

n

Generic n-entry XOR-dispatch table: when jumped to at entry d, XORs d into dst and jumps to ret. n must be a power of two and the …

hex.tables.init_all/0

hex/tables_init

1

6464+@

Inner macro of hex.init — emits every per-operation hex.*.init block (or, and, mul, cmp, add, sub) in sequence. Don’t call this …

hex.tables.init_shared/0

hex/tables_init

0

2

Allocate the shared ret and res symbols used by every table-driven hex operation. Called once by hex.init.

hex.tables.jump_to_table_entry/3

hex/tables_init

4@+4

4@+52

Dispatch into a 256-padded table at entry (src<<4 | dst), then XOR hex.tables.res into dst on return. The hot path of every …

hex.vec/1

hex/memory

0 (data declaration)

n

Hexadecimal vector.

hex.vec/2

hex/memory

0 (data declaration)

n

Hexadecimal vector with initial value.

hex.write_byte/2

hex/pointers/write_pointers

w(0.75@+5)  + 17@+37

w(0.75@+29) + 17@+200

Effectively:  *ptr = src[:2]

hex.write_byte/3

hex/pointers/write_pointers

n(w(0.75@+5)  + 26@+51)

n(w(1.13@+32) + 22@+255)

Effectively:  *ptr[:n] = src[:2n]

hex.write_byte_and_inc/2

hex/pointers/write_pointers

w(0.75@+5)  + 26@+51

w(1.13@+32) + 22@+255

Effectively:  *ptr = src[:2]

hex.write_hex/2

hex/pointers/write_pointers

w(0.75@+5)  + 11@+25

w(0.75@+29) + 11@+112

Effectively:  *ptr = src

hex.write_hex/3

hex/pointers/write_pointers

n(w(0.75@+5)  + 20@+39)

n(w(1.13@+32) + 16@+167)

Effectively:  *ptr[:n] = src[:n]

hex.write_hex_and_inc/2

hex/pointers/write_pointers

w(0.75@+5)  + 20@+39

w(1.13@+32) + 16@+167

Effectively:  *ptr = src

hex.write_nth_byte/3

hex/pointers/write_pointers

w(3@+10.25) + 17@+37

w(3@+69)    + 17@+200

*(ptr + index*2w)[:2] = src[:2] — write the index-th byte past *ptr.

hex.write_nth_hex/3

hex/pointers/write_pointers

w(3@+10.25) + 11@+25

w(3@+69)    + 11@+112

*(ptr + index*2w) = src — write src into the index-th hex past *ptr.

hex.xor/2

hex/logics

@

@+12

dst ^= src

hex.xor/3

hex/logics

n@

n(@+12)

dst[:n] ^= src[:n]

hex.xor_by/2

hex/memory

4 (avg. 2: #on-bits)

4 (avg. 2: #on-bits)

hex ^= val (constant)

hex.xor_by/3

hex/memory

4n (avg. 2n: #on-bits)

4n (avg. 2n: #on-bits)

hex[:n] ^= val (constant)

hex.xor_byte_from_ptr/2

hex/pointers/xor_from_pointer

w(0.75@+ 5) + 7@+13

w(0.75@+29) + 7@+48

Effectively:  dst[:2] ^= *ptr

hex.xor_byte_to_ptr/2

hex/pointers/xor_to_pointer

w(0.5@+2)  + 10@+24

w(0.5@+14) + 10@+152

Effectively:  hex.xor *ptr, hex[:2]

hex.xor_byte_to_ptr/3

hex/pointers/xor_to_pointer

n(w(0.5@+2)  + 19@+38)

n(w(0.9@+17) + 15@+207)

Effectively:  hex.xor *ptr[:n], hex[:2n]

hex.xor_hex_from_ptr/2

hex/pointers/xor_from_pointer

w(0.75@+ 5) + 6@+13

w(0.75@+29) + 6@+36

Effectively:  dst ^= *ptr

hex.xor_hex_to_ptr/2

hex/pointers/xor_to_pointer

w(0.5@+2)  + 5@+12

w(0.5@+14) + 5@+76

Effectively:  hex.xor *ptr, hex

hex.xor_hex_to_ptr/3

hex/pointers/xor_to_pointer

n(w(0.5@+2)  + 14@+26)

n(w(0.9@+17) + 10@+131)

Effectively:  hex.xor *ptr[:n], hex[:n]

hex.xor_zero/2

hex/logics

@+4

@+28

dst ^= src

hex.xor_zero/3

hex/logics

n(@+4)

n(@+28)

dst[:n] ^= src[:n]

hex.zero/1

hex/memory

@

@+12

hex = 0

hex.zero/2

hex/memory

n@

n(@+12)

x[:n] = 0

hex.zero_ptr/1

hex/pointers/write_pointers

w(0.75@+5)  + 15@+37

w(0.75@+29) + 15@+176

Effectively:  *ptr = 0

stl.bit2hex/2

casting

2@-1

2@+11

hex = bit

stl.bit2hex/3

casting

n(1.25@-1)

n(1.25@+2)

hex[:(n+3)/4] = bit[:n]

stl.call/1

ptrlib

~2.5w@  (exact: w(2.25@+10)   + 24@+51)

<3w@    (exact: w(2.625@+49) + 20@+231)

Saves the return address to the stack and jumps to the given “address”.

stl.call/2

ptrlib

<3w@  (exact: w(2.25@+10)  + 37@+57)

<3w@  (exact: w(2.625@+49) + 43@+251)

Saves the return address to the stack and jumps to the given “address”.

stl.comp_flip_if/2

runlib

1

1

if expr != 0 (compilation time), flip the given bit.

stl.comp_if/3

runlib

1

1

if expression is 0 (compilation time), jump to l0. else jump to l1

stl.comp_if0/2

runlib

1

1

if expression is 0 (compilation time), jump to l0. else continue

stl.comp_if1/2

runlib

1

1

if expression is not 0 (compilation time), jump to l1. else continue

stl.fcall/2

ptrlib

@-1

@-1

Jumps to label, and saves the return address in the given “ret_reg” variable.

stl.fj/2

runlib

1

1

macro for 1 flipjump op

stl.fret/1

ptrlib

1

1

Return into the address written in the “ret_reg” variable.

stl.get_sp/1

ptrlib

n(2@)

n(2@+24)

dst[:w/4] = sp

stl.hex2bit/2

casting

5@-4

5@+8

bit[:4] = hex

stl.hex2bit/3

casting

n(5@-4)

n(5@+8)

bit[:4n] = hex[:n]

stl.loop/0

runlib

(infinite self-loop)

1

finish (loop to self)

stl.output/1

runlib

8 * string_length

8 * string_length

str is a constant. The macro outputs the bytes of it (from lsB to msB) until it becomes all zeros.

stl.output_bit/1

runlib

1

1

bit is a constant. 0 will output 0, anything else will output 1.

stl.output_char/1

runlib

8

8

ascii is a constant. The macro outputs the byte (ascii & 0xff)

stl.ptr_init/0

ptrlib

2.5w+263

2.5w+263

One-time initialisation of the pointer dispatch infrastructure. Use stl.startup_and_init_pointers, which calls this for you.

stl.return/0

ptrlib

w(2@+7)      + 9@+23

w(2.375@+34) + 5@+67

Returns to the calling function (gets the return-address from the top of the stack).

stl.skip/0

runlib

1

1

skip the next flipjump op

stl.stack_init/1

ptrlib

O(1)

n+w/4

Initializes a stack of size n (maximal capacity of n hexes / return-addresses).

stl.startup/0

runlib

2

2

Inits the IO variable, and jumps to the next instruction.

stl.startup/1

runlib

2

2

Inits the IO variable, and jumps to the given code start.

stl.startup_and_init_all/0

runlib

~7000  (7026 for w=64, 6894 for w=16)

~7000  (7026 for w=64, 6894 for w=16)

Initialize anything needed for the standard library.

stl.startup_and_init_all/1

runlib

6725 + 2.75w+@ + n

6725 + 2.75w+@ + n

Startup macro — should be the first piece of code in your program. Initialises everything needed for the standard library.

stl.startup_and_init_all/2

runlib

6725 + 2.75w+@ + n

6725 + 2.75w+@ + n

Initialize anything needed for the standard library.

stl.startup_and_init_pointers/0

runlib

2.5w+265

2.5w+265

Inits the IO variable, and the pointers globals.

stl.startup_and_init_pointers/1

runlib

2.5w+265

2.5w+265

Inits the IO variable, and the pointers globals.

stl.wflip_macro/2

runlib

@

@

macro for 1 wflip op

stl.wflip_macro/3

runlib

@

@

macro for 1 wflip op (with jump)