| -- kernels_6502.lua | |
| -- 6502 assembly source strings for the Trinity Kernel math operations. | |
| -- Assembled at LuaLaTeX load time by assembler.lua | |
| -- | |
| -- Memory Map: | |
| -- $2000 : ANU Quantum Entropy (4 bytes) | |
| -- $2004 : Input A (16-bit lo/hi) | |
| -- $2006 : Input B (16-bit lo/hi) | |
| -- $2008 : Degree / Length | |
| -- $2010 : Output (16-bit) | |
| -- $0080 : Parity lookup table (256 bytes, loaded at startup) | |
| -- $00F0-$00FF : Zero-page workspace | |
| -- | |
| -- Authors: Ahmad Ali Parr, Jessica L. Williams (SNAPKITTYWEST) | |
| local kernels = {} | |
| -- ββ MoA Routing (ANU seed β agent selection) βββββββββββββββββββββββββββββββββ | |
| -- Input: $2000 = ANU seed byte | |
| -- Output: $2001 = multiplier (115 = conservative, 95 = aggressive) | |
| kernels.moa_routing = [[ | |
| LDA $2000 | |
| CMP #$80 | |
| BCC AGGRESSIVE | |
| LDA #$73 | |
| STA $2001 | |
| BRK | |
| AGGRESSIVE: | |
| LDA #$5F | |
| STA $2001 | |
| BRK | |
| ]] | |
| -- ββ GF(2) parity of one byte via lookup ββββββββββββββββββββββββββββββββββββββ | |
| -- Input: A = byte to compute parity of | |
| -- Output: A = parity (0 or 1), uses $0080 parity table | |
| -- Clobbers: Y | |
| kernels.gf2_parity_byte = [[ | |
| TAY | |
| LDA $0080,Y | |
| RTS | |
| ]] | |
| -- ββ GF(2) dot product (2 bytes Γ 2 bytes) ββββββββββββββββββββββββββββββββββββ | |
| -- Input: $00F0/$00F1 = ptr to 2-byte row | |
| -- $00F2/$00F3 = ptr to 2-byte vector | |
| -- Output: A = parity of AND reduction | |
| -- Clobbers: X, Y, $00F9 | |
| kernels.gf2_dot_16 = [[ | |
| LDA #$00 | |
| STA $F9 | |
| LDX #$02 | |
| BYTE_LOOP: | |
| LDY #$00 | |
| LDA ($F0),Y | |
| LDY #$00 | |
| ; AND with vector byte (via EOR accumulation) | |
| ; Load vec byte into Y, AND with matrix byte | |
| EOR ($F2),Y | |
| ; Parity via lookup | |
| TAY | |
| LDA $0080,Y | |
| EOR $F9 | |
| STA $F9 | |
| INC $F0 | |
| BNE NO_CARRY_ROW | |
| INC $F1 | |
| NO_CARRY_ROW: | |
| INC $F2 | |
| BNE NO_CARRY_VEC | |
| INC $F3 | |
| NO_CARRY_VEC: | |
| DEX | |
| BNE BYTE_LOOP | |
| LDA $F9 | |
| RTS | |
| ]] | |
| -- ββ Holographic key: Horner's method over GF(256) ββββββββββββββββββββββββββββ | |
| -- Evaluates P(x) = c0 + x*(c1 + x*(c2 + ... cn)) | |
| -- Input: $2000 = x (ANU seed, 1 byte) | |
| -- $00F4/$00F5 = ptr to coefficients (n+1 bytes) | |
| -- $2008 = degree n (0..7) | |
| -- Output: $2010 = result byte | |
| -- Uses GF(256) multiplication via log/exp tables at $0100/$0200 | |
| -- Note: Tables must be loaded before calling (init_gf256_tables) | |
| kernels.holographic_key = [[ | |
| LDA #$00 | |
| STA $10 | |
| LDX $2008 | |
| HORNER_LOOP: | |
| ; Acc = Acc * x (GF256 multiply) | |
| ; GF256_MUL: A=Acc, $2000=x -> result in A | |
| ; Using Russian Peasant if tables absent, else log/exp | |
| ; Load Acc | |
| LDA $10 | |
| ; Multiply by x via log/exp (tables at $0100=LOG, $0200=EXP) | |
| TAY | |
| LDA $0100,Y ; log(Acc) | |
| STA $FA | |
| LDA $2000 ; x | |
| TAY | |
| LDA $0100,Y ; log(x) | |
| CLC | |
| ADC $FA ; log(Acc) + log(x) [no mod 255 wrap for demo] | |
| TAY | |
| LDA $0200,Y ; exp(log(Acc)+log(x)) = Acc*x in GF256 | |
| ; Add (XOR) next coefficient | |
| LDY #$00 | |
| EOR ($F4),Y | |
| STA $10 | |
| ; Advance coefficient pointer | |
| INC $F4 | |
| BNE NO_CARRY | |
| INC $F5 | |
| NO_CARRY: | |
| DEX | |
| BNE HORNER_LOOP | |
| LDA $10 | |
| STA $2010 | |
| BRK | |
| ]] | |
| -- ββ Euclidean GCD (binary / Stein's, 8-bit) ββββββββββββββββββββββββββββββββββ | |
| -- Input: $2004 = A, $2005 = B | |
| -- Output: $2010 = GCD(A, B) | |
| kernels.euclid_gcd = [[ | |
| LDA $2004 | |
| BNE A_NONZERO | |
| LDA $2005 | |
| STA $2010 | |
| BRK | |
| A_NONZERO: | |
| LDA $2005 | |
| BNE B_NONZERO | |
| LDA $2004 | |
| STA $2010 | |
| BRK | |
| B_NONZERO: | |
| ; Load A and B | |
| LDA $2004 | |
| STA $F0 | |
| LDA $2005 | |
| STA $F1 | |
| GCD_LOOP: | |
| ; If A == B: done | |
| LDA $F0 | |
| CMP $F1 | |
| BEQ GCD_DONE | |
| ; If A > B: A = A - B | |
| BCC A_SMALLER | |
| SEC | |
| SBC $F1 | |
| STA $F0 | |
| JMP GCD_LOOP | |
| A_SMALLER: | |
| ; B = B - A | |
| LDA $F1 | |
| SEC | |
| SBC $F0 | |
| STA $F1 | |
| JMP GCD_LOOP | |
| GCD_DONE: | |
| LDA $F0 | |
| STA $2010 | |
| BRK | |
| ]] | |
| -- ββ Fixed-point dot product (8.8 format, 2 vectors of length 4) ββββββββββββββ | |
| -- Input: $00F0/$00F1 = ptr to vector A (4 bytes) | |
| -- $00F2/$00F3 = ptr to vector B (4 bytes) | |
| -- Output: $2010/$2011 = 16-bit result (integer part of dot product) | |
| kernels.fixed_dot = [[ | |
| LDA #$00 | |
| STA $FA | |
| STA $FB | |
| LDX #$04 | |
| FDOT_LOOP: | |
| LDY #$00 | |
| LDA ($F0),Y | |
| ; Multiply A * B[i] (8x8 -> 16 bit, simple shift-add) | |
| STA $FC ; multiplicand | |
| LDA ($F2),Y | |
| STA $FD ; multiplier | |
| ; 8x8 multiply via shift-add into $FE/$FF | |
| LDA #$00 | |
| STA $FE | |
| STA $FF | |
| LDY #$08 | |
| MUL_LOOP: | |
| LSR $FD | |
| BCC MUL_NO_ADD | |
| CLC | |
| ADC $FC | |
| TAX | |
| LDA $FE | |
| ADC #$00 | |
| STA $FE | |
| TXA | |
| MUL_NO_ADD: | |
| ASL $FC | |
| DEY | |
| BNE MUL_LOOP | |
| ; Accumulate into $FA/$FB | |
| CLC | |
| ADC $FA | |
| STA $FA | |
| LDA $FE | |
| ADC $FB | |
| STA $FB | |
| ; Advance pointers | |
| INC $F0 | |
| BNE NO_CARRY_A | |
| INC $F1 | |
| NO_CARRY_A: | |
| INC $F2 | |
| BNE NO_CARRY_B | |
| INC $F3 | |
| NO_CARRY_B: | |
| DEX | |
| BNE FDOT_LOOP | |
| LDA $FA | |
| STA $2010 | |
| LDA $FB | |
| STA $2011 | |
| BRK | |
| ]] | |
| return kernels | |