File size: 5,233 Bytes
50dd446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
-- 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