Repository navigation
Expand file tree
/
Copy pathkernels_6502.lua
More file actions
229 lines (221 loc) · 5.11 KB
/
Copy pathkernels_6502.lua
File metadata and controls
229 lines (221 loc) · 5.11 KB
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
-- 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