From 88422034f541887eda0a4ff064c6d1bc55b0adf3 Mon Sep 17 00:00:00 2001 From: Matiq Date: Thu, 20 Aug 2026 02:25:59 +0300 Subject: [PATCH] P3.1: extract FFT code from rt snap (extract_fft.py); decode cplx_mul 0x8440 = in-place elementwise double mult, twiddle loader 0x39b00 stride copy, dispatcher 0x535a70->0x140a10/70->jumptable[0x1826159a0]=4; implement cplx_mul_scalar_inplace --- dsp/fft_stage.cpp | 7 ++++++ dsp/fft_stage.hpp | 6 +++++ handoff/extract_fft.py | 56 ++++++++++++++++++++++++++++++++++++++++++ notes_giant_fft.md | 32 ++++++++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 handoff/extract_fft.py diff --git a/dsp/fft_stage.cpp b/dsp/fft_stage.cpp index bc0ef6e..0f62ee0 100644 --- a/dsp/fft_stage.cpp +++ b/dsp/fft_stage.cpp @@ -3,6 +3,13 @@ namespace fft_stage { +// 0x180008440: dst[i] *= src[i] (double, in-place elementwise; kernel 0x18003fa20) +void cplx_mul_scalar_inplace(double* dst, const double* src, uint32_t n) { + for (uint32_t i = 0; i < n; i++) { + dst[i] *= src[i]; + } +} + // cplx_mul — complex elementwise multiply: out = in1 * in2 (conjugated 2nd) void cplx_mul(double* out, const double* in1, const double* in2, uint32_t n) { for (uint32_t i = 0; i < n * 2; i += 2) { diff --git a/dsp/fft_stage.hpp b/dsp/fft_stage.hpp index 7435d35..f88dffa 100644 --- a/dsp/fft_stage.hpp +++ b/dsp/fft_stage.hpp @@ -4,6 +4,12 @@ namespace fft_stage { +// 0x180008440 (kernel 0x18003fa20): IN-PLACE elementwise double multiply +// dst[i] *= src[i]. NOT a complex multiply — the complex op is done via separate +// re/im passes on the interleaved layout. +void cplx_mul_scalar_inplace(double* dst, const double* src, uint32_t n); + +// complex elementwise multiply (interleaved re,im): out = in1 * in2 void cplx_mul(double* out, const double* in1, const double* in2, uint32_t n); void stage_complex(double* out, const double* in, const double* tw, uint32_t n); void stage_double(double* out, const double* in, const double* tw, uint32_t n); diff --git a/handoff/extract_fft.py b/handoff/extract_fft.py new file mode 100644 index 0000000..379d523 --- /dev/null +++ b/handoff/extract_fft.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""extract_fft.py — extract FFT-related code regions from the rt snap into raw bins.""" +import struct, mmap, os + +SNAP = '/tmp/snap_rt.bin' +OUT = '/tmp/fft/' + +# (name, addr, size) +TARGETS = [ + ('cplx_mul_8440', 0x180008440, 0x80), + ('cplx_mul_kernel_c440', 0x18000c440, 0x100), + ('stage_bfc0', 0x18000bfc0, 0x600), + ('stage_c5e0', 0x18000c5e0, 0x600), + ('twiddle_loader_39b00', 0x180039b00, 0x400), + ('plan_gen_2f980', 0x18002f980, 0x1200), + ('dispatcher_535a70', 0x180535a70, 0x100), + ('scalar_140a10', 0x180140a10, 0x200), + ('vector_140a70', 0x180140a70, 0x200), + ('fft_kernel_a5a0', 0x18001a5a0, 0x100), +] + + +def main(): + os.makedirs(OUT, exist_ok=True) + fd = os.open(SNAP, os.O_RDONLY) + sz = os.fstat(fd).st_size + mm = mmap.mmap(fd, 0, access=mmap.ACCESS_READ) + # parse region index once + regs = [] + i = 0 + while i + 16 <= sz: + lo, n = struct.unpack_from('1024 separate (two-pass) branch (unresolved). - Stage kernels (FUN_18000bfc0/18000c5e0) consume these with 0x40-complex chunks, cplx-mul=180008440, acc=FUN_1800437c0/180044700. + +## ============ UPDATE 2026-08-20 (P3: code extracted from rt snap, objdump) ============ +Raw code extracted from /tmp/snap_rt.bin via handoff/extract_fft.py → /tmp/fft/*.bin. + +### cplx_mul 0x180008440 = IN-PLACE ELEMENTWISE DOUBLE MULTIPLY (not complex!): + signature (rcx=dst, rdx=src, r8d=count): dst[i] *= src[i] (double). + kernel 0x18003fa20: scalar path mulsd, vector path mulpd (4-wide). Corrects the + "cplx-mul=180008440" label — the complex multiply is done via SEPARATE re/im passes + (interleaved layout), 0x8440 is the scalar elementwise multiply. + +### twiddle loader FUN_180039b00 (log2N=ecx, dst=rdx): + N = 1< 10: separate two-pass branch (0x180039dc9). + else stride = 1 << (10-log2N); copy sin_table[0x182616800 + k*stride*8] -> dst[k], k=0..N/4-1. + sin_table DAT_182616800 = sin(k·2π/1024) for k=0..256 (257 valid doubles, then garbage). + => twiddle[k] = sin(k·stride·2π/1024), the quarter-period sample set. + +### stage kernels FUN_18000bfc0 / 18000c5e0 (butterfly): + prologue stack 0x470 (scratch 0x200×2 doubles). Per 0x40-complex chunk: + 0x180140c40(src, scratch, scratch+0x200, 0x40) — load/format twiddle into scratch + 0x8440(dst, scratch, 0x40) — dst *= scratch (elementwise) + 0x8440(dst, scratch+0x200, 0x40) — dst *= scratch+0x200 + then butterfly arithmetic + acc (FUN_1800437c0/044700). Full loop still to transcribe. + +### dispatcher 0x535a70 → 0x140a10 (scalar) / 0x140a70 (vector) (per NOTES:166). +Second-level dispatch: 0x140a10/140a70 read global index [0x1826159a0] (=4 at capture) +then jump through tables: + scalar 0x182617548 = {0x180141380, 0x1801413a0, ..., 0x1801414a0} (12 entries, [4]=0x180141400) + vector 0x182617588 = {0x180141440, ..., 0x180141560} ([4]=0x1801414c0) +These are the per-size/per-type stage kernels (0x1801413xx/1415xx family). + +