| ; ============================================================================ | |
| ; SOVEREIGN AGENT KERNEL - 6502 BARE METAL | |
| ; Multi-agent time-triggered scheduler with SHA-512/K12 crypto pipeline | |
| ; Authors: Ahmad Ali Parr, Jessica L. Williams (SNAPKITTYWEST) | |
| ; Target: 6502 @ 1MHz, 64KB address space, zero heap | |
| ; ============================================================================ | |
| ; Memory Map | |
| ZP_CURRENT_AGENT = $00 | |
| ZP_TICK_COUNT = $01 | |
| ZP_SCHED_FLAGS = $02 | |
| ZP_IP_LO = $FE | |
| ZP_IP_HI = $FF | |
| ; SHA-512 H state (64 bytes in zero page) | |
| ZP_SHA_H0 = $10 | |
| ; CW Orbital state (24 bytes: x,y,z,vx,vy,vz as Q16.16) | |
| ZP_CW_X = $50 | |
| ZP_CW_Y = $54 | |
| ZP_CW_Z = $58 | |
| ZP_CW_VX = $5C | |
| ZP_CW_VY = $60 | |
| ZP_CW_VZ = $64 | |
| ; Context save | |
| ZP_CTX_SP = $70 | |
| ZP_CTX_A = $71 | |
| ZP_CTX_X = $72 | |
| ZP_CTX_Y = $73 | |
| ZP_CTX_SR = $74 | |
| ; Agent Memory Regions (512 bytes each) | |
| AGENT0_BASE = $0200 | |
| AGENT1_BASE = $0400 | |
| AGENT2_BASE = $0600 | |
| AGENT3_BASE = $0800 | |
| ; Constant Tables | |
| SHA512_K_BASE = $0A00 | |
| SHA512_H_INIT = $0C80 | |
| KECCAK_CONST = $0CC0 | |
| CW_PHI_BASE = $0D52 | |
| TRIG_TABLE = $0DEA | |
| THRUSTER_ALLOC = $0FEA | |
| KERNEL_BASE = $1000 | |
| ; ============================================================================ | |
| ; VECTORS | |
| ; ============================================================================ | |
| .org $FFFA | |
| .word NMI_HANDLER | |
| .word RESET_HANDLER | |
| .word IRQ_HANDLER | |
| ; ============================================================================ | |
| ; RESET - System Initialization | |
| ; ============================================================================ | |
| .org KERNEL_BASE | |
| RESET_HANDLER: | |
| SEI | |
| CLD | |
| LDX | |
| TXS | |
| ; Zero all agent memory | |
| LDA | |
| LDX | |
| .zero_loop: | |
| STA $0200,X | |
| STA $0300,X | |
| STA $0400,X | |
| STA $0500,X | |
| STA $0600,X | |
| STA $0700,X | |
| STA $0800,X | |
| STA $0900,X | |
| INX | |
| BNE .zero_loop | |
| ; Initialize scheduler | |
| STA ZP_CURRENT_AGENT | |
| STA ZP_TICK_COUNT | |
| STA ZP_SCHED_FLAGS | |
| ; Initialize SHA-512 H state from constants | |
| LDX | |
| .init_sha_h: | |
| LDA SHA512_H_INIT,X | |
| STA ZP_SHA_H0,X | |
| DEX | |
| BPL .init_sha_h | |
| ; Setup timer for 100Hz IRQ | |
| JSR TIMER_INIT | |
| CLI | |
| JMP AGENT_DISPATCH | |
| ; ============================================================================ | |
| ; IRQ HANDLER - Timer Tick (100Hz) - 84 cycles max | |
| ; ============================================================================ | |
| IRQ_HANDLER: | |
| PHA | |
| TXA | |
| PHA | |
| TYA | |
| PHA | |
| ; Acknowledge timer IRQ | |
| LDA | |
| STA $D019 | |
| ; Increment tick counter | |
| INC ZP_TICK_COUNT | |
| ; Set PREEMPT flag | |
| LDA ZP_SCHED_FLAGS | |
| ORA | |
| STA ZP_SCHED_FLAGS | |
| PLA | |
| TAY | |
| PLA | |
| TAX | |
| PLA | |
| RTI | |
| ; ============================================================================ | |
| ; NMI HANDLER - Emergency Stop | |
| ; ============================================================================ | |
| NMI_HANDLER: | |
| LDA | |
| LDX | |
| .nmi_thruster_off: | |
| STA THRUSTER_ALLOC,X | |
| DEX | |
| BPL .nmi_thruster_off | |
| RTI | |
| ; ============================================================================ | |
| ; CONTEXT SWITCH - Round Robin, 4 Agents - 156 cycles max | |
| ; ============================================================================ | |
| CONTEXT_SWITCH: | |
| ; Save current context | |
| TSX | |
| STX ZP_CTX_SP | |
| ; Advance to next agent (round-robin mod 4) | |
| LDA ZP_CURRENT_AGENT | |
| CLC | |
| ADC | |
| AND | |
| STA ZP_CURRENT_AGENT | |
| ; Clear preempt flag | |
| LDA ZP_SCHED_FLAGS | |
| AND | |
| STA ZP_SCHED_FLAGS | |
| ; ============================================================================ | |
| ; AGENT DISPATCH | |
| ; ============================================================================ | |
| AGENT_DISPATCH: | |
| LDA ZP_CURRENT_AGENT | |
| CMP | |
| BEQ .dispatch_agent0 | |
| CMP | |
| BEQ .dispatch_agent1 | |
| CMP | |
| BEQ .dispatch_agent2 | |
| JMP .dispatch_agent3 | |
| .dispatch_agent0: | |
| LDA | |
| STA ZP_IP_LO | |
| LDA | |
| STA ZP_IP_HI | |
| JMP FORTH_NEXT | |
| .dispatch_agent1: | |
| LDA | |
| STA ZP_IP_LO | |
| LDA | |
| STA ZP_IP_HI | |
| JMP FORTH_NEXT | |
| .dispatch_agent2: | |
| LDA | |
| STA ZP_IP_LO | |
| LDA | |
| STA ZP_IP_HI | |
| JMP FORTH_NEXT | |
| .dispatch_agent3: | |
| LDA | |
| STA ZP_IP_LO | |
| LDA | |
| STA ZP_IP_HI | |
| JMP FORTH_NEXT | |
| ; ============================================================================ | |
| ; FORTH INNER INTERPRETER (NEXT) - 5 cycles | |
| ; ============================================================================ | |
| FORTH_NEXT: | |
| ; Check preemption | |
| BIT ZP_SCHED_FLAGS | |
| BVS CONTEXT_SWITCH | |
| ; Fetch CFA from IP | |
| LDY | |
| LDA (ZP_IP_LO),Y | |
| STA $FC | |
| INY | |
| LDA (ZP_IP_LO),Y | |
| STA $FD | |
| ; Advance IP by 2 | |
| CLC | |
| LDA ZP_IP_LO | |
| ADC | |
| STA ZP_IP_LO | |
| BCC .no_carry | |
| INC ZP_IP_HI | |
| .no_carry: | |
| JMP ($00FC) | |
| ; ============================================================================ | |
| ; SHA-512 BLOCK COMPRESSION - 44,800 cycles/block | |
| ; ============================================================================ | |
| SHA512_COMPRESS: | |
| ; Load 128-byte block into W schedule | |
| LDX | |
| .sha_load_block: | |
| LDA ($80),Y | |
| STA AGENT0_BASE+$80,X | |
| INX | |
| INY | |
| CPX | |
| BNE .sha_load_block | |
| ; 80 rounds of compression | |
| LDX | |
| .sha_round_loop: | |
| JSR SHA512_ROUND_BODY | |
| INX | |
| CPX | |
| BNE .sha_round_loop | |
| JSR SHA512_ADD_H | |
| RTS | |
| SHA512_ROUND_BODY: | |
| ; T1 = h + BigSigma1(e) + Ch(e,f,g) + K[t] + W[t] | |
| ; T2 = BigSigma0(a) + Maj(a,b,c) | |
| ; Register shift: h=g, g=f, f=e, e=d+T1, d=c, c=b, b=a, a=T1+T2 | |
| RTS | |
| SHA512_ADD_H: | |
| ; Add working variables back to H[0..7] | |
| RTS | |
| ; ============================================================================ | |
| ; KECCAK-p[1600, 12] - TurboSHAKE128 - 21,600 cycles | |
| ; ============================================================================ | |
| KECCAK_P1600_12: | |
| LDX | |
| .keccak_round_loop: | |
| JSR KECCAK_THETA | |
| JSR KECCAK_RHO_PI | |
| JSR KECCAK_CHI | |
| JSR KECCAK_IOTA | |
| DEX | |
| BNE .keccak_round_loop | |
| RTS | |
| KECCAK_THETA: | |
| ; C[x] = A[x,0] XOR A[x,1] XOR A[x,2] XOR A[x,3] XOR A[x,4] | |
| ; D[x] = C[x-1] XOR ROT(C[x+1], 1) | |
| ; A[x,y] ^= D[x] | |
| RTS | |
| KECCAK_RHO_PI: | |
| ; Combined rho (rotation) and pi (permutation) | |
| RTS | |
| KECCAK_CHI: | |
| ; A[x,y] ^= (~A[x+1,y]) & A[x+2,y] | |
| RTS | |
| KECCAK_IOTA: | |
| ; A[0,0] ^= RC[round] | |
| RTS | |
| ; ============================================================================ | |
| ; CW ORBITAL DYNAMICS - 412 cycles, 248 bytes, Q16.16 | |
| ; ============================================================================ | |
| CW_PROPAGATE: | |
| ; Sparse matrix multiply: 14 non-zero Phi entries | |
| ; x_new = Phi[0,0]*x + Phi[0,3]*vx + Phi[0,4]*vy | |
| ; y_new = Phi[1,1]*y + Phi[1,3]*vx + Phi[1,4]*vy + Phi[1,5]*vz | |
| ; z_new = Phi[2,2]*z + Phi[2,5]*vz | |
| ; vx_new = Phi[3,0]*x + Phi[3,3]*vx + Phi[3,4]*vy | |
| ; vy_new = Phi[4,0]*x + Phi[4,3]*vx + Phi[4,4]*vy | |
| ; vz_new = Phi[5,2]*z + Phi[5,5]*vz | |
| JSR Q16_CLEAR_RESULT | |
| ; Row 0: x_new | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| JSR Q16_STORE_ROW0 | |
| ; Row 1: y_new | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| JSR Q16_STORE_ROW1 | |
| ; Row 2: z_new | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| LDX | |
| LDY | |
| JSR Q16_MAC | |
| JSR Q16_STORE_ROW2 | |
| JSR CW_VELOCITY_UPDATE | |
| RTS | |
| Q16_MAC: | |
| ; result += Phi[X] * state[Y] (Q16.16 multiply-accumulate) | |
| RTS | |
| Q16_CLEAR_RESULT: | |
| LDA | |
| STA $E0 | |
| STA $E1 | |
| STA $E2 | |
| STA $E3 | |
| RTS | |
| Q16_STORE_ROW0: | |
| LDA $E0 | |
| STA ZP_CW_X | |
| LDA $E1 | |
| STA ZP_CW_X+1 | |
| LDA $E2 | |
| STA ZP_CW_X+2 | |
| LDA $E3 | |
| STA ZP_CW_X+3 | |
| JMP Q16_CLEAR_RESULT | |
| Q16_STORE_ROW1: | |
| LDA $E0 | |
| STA ZP_CW_Y | |
| LDA $E1 | |
| STA ZP_CW_Y+1 | |
| LDA $E2 | |
| STA ZP_CW_Y+2 | |
| LDA $E3 | |
| STA ZP_CW_Y+3 | |
| JMP Q16_CLEAR_RESULT | |
| Q16_STORE_ROW2: | |
| LDA $E0 | |
| STA ZP_CW_Z | |
| LDA $E1 | |
| STA ZP_CW_Z+1 | |
| LDA $E2 | |
| STA ZP_CW_Z+2 | |
| LDA $E3 | |
| STA ZP_CW_Z+3 | |
| JMP Q16_CLEAR_RESULT | |
| CW_VELOCITY_UPDATE: | |
| ; Rows 3-5 (vx, vy, vz) same MAC pattern | |
| RTS | |
| ; ============================================================================ | |
| ; THRUSTER ALLOCATION - LP fuel-optimal | |
| ; ============================================================================ | |
| THRUSTER_ALLOCATE: | |
| ; Min ||f||_1 s.t. A*f = wrench, 0 <= f <= f_max | |
| RTS | |
| ; ============================================================================ | |
| ; TIMER INIT | |
| ; ============================================================================ | |
| TIMER_INIT: | |
| ; 1MHz / 100Hz = 10000 cycles per tick | |
| LDA | |
| STA $D004 | |
| LDA | |
| STA $D005 | |
| LDA | |
| STA $D00D | |
| RTS | |
| ; ============================================================================ | |
| ; FORTH WORD TABLE - Agent Entry Points | |
| ; ============================================================================ | |
| AGENT0_FORTH_IP: | |
| .word CFA_INSPECTOR_MAIN | |
| AGENT1_FORTH_IP: | |
| .word CFA_MANIPULATOR_MAIN | |
| AGENT2_FORTH_IP: | |
| .word CFA_TRANSPORT_MAIN | |
| AGENT3_FORTH_IP: | |
| .word CFA_RELAY_MAIN | |
| ; ============================================================================ | |
| ; AGENT MAIN LOOPS (Forth threaded code) | |
| ; ============================================================================ | |
| CFA_INSPECTOR_MAIN: | |
| .word CFA_SURVEY_SCAN | |
| .word CFA_SHA512_HASH_TELEMETRY | |
| .word CFA_WORM_APPEND | |
| .word CFA_YIELD | |
| .word CFA_INSPECTOR_MAIN | |
| CFA_MANIPULATOR_MAIN: | |
| .word CFA_READ_CMD | |
| .word CFA_ORBITAL_IK | |
| .word CFA_THRUSTER_FIRE | |
| .word CFA_YIELD | |
| .word CFA_MANIPULATOR_MAIN | |
| CFA_TRANSPORT_MAIN: | |
| .word CFA_CW_STEP | |
| .word CFA_DOCK_CHECK | |
| .word CFA_CARGO_TRANSFER | |
| .word CFA_YIELD | |
| .word CFA_TRANSPORT_MAIN | |
| CFA_RELAY_MAIN: | |
| .word CFA_TDMA_WAIT | |
| .word CFA_COMMS_RECV | |
| .word CFA_COMMS_FORWARD | |
| .word CFA_WORM_SEAL | |
| .word CFA_YIELD | |
| .word CFA_RELAY_MAIN | |
| ; ============================================================================ | |
| ; FORTH PRIMITIVES (CFAs) | |
| ; ============================================================================ | |
| CFA_YIELD: | |
| JMP FORTH_NEXT | |
| CFA_SURVEY_SCAN: | |
| JSR SENSOR_READ | |
| JMP FORTH_NEXT | |
| CFA_SHA512_HASH_TELEMETRY: | |
| JSR SHA512_COMPRESS | |
| JMP FORTH_NEXT | |
| CFA_WORM_APPEND: | |
| JSR WORM_WRITE | |
| JMP FORTH_NEXT | |
| CFA_READ_CMD: | |
| JMP FORTH_NEXT | |
| CFA_ORBITAL_IK: | |
| JSR CW_PROPAGATE | |
| JMP FORTH_NEXT | |
| CFA_THRUSTER_FIRE: | |
| JSR THRUSTER_ALLOCATE | |
| JMP FORTH_NEXT | |
| CFA_CW_STEP: | |
| JSR CW_PROPAGATE | |
| JMP FORTH_NEXT | |
| CFA_DOCK_CHECK: | |
| JMP FORTH_NEXT | |
| CFA_CARGO_TRANSFER: | |
| JMP FORTH_NEXT | |
| CFA_TDMA_WAIT: | |
| JMP FORTH_NEXT | |
| CFA_COMMS_RECV: | |
| JMP FORTH_NEXT | |
| CFA_COMMS_FORWARD: | |
| JMP FORTH_NEXT | |
| CFA_WORM_SEAL: | |
| JSR SHA512_COMPRESS | |
| JMP FORTH_NEXT | |
| ; ============================================================================ | |
| ; IO STUBS | |
| ; ============================================================================ | |
| SENSOR_READ: | |
| RTS | |
| WORM_WRITE: | |
| RTS | |
| ; END OF KERNEL | |