From 241957bced929f0ae235f52b8bd1bcf38595edb0 Mon Sep 17 00:00:00 2001 From: Matiq Date: Wed, 19 Aug 2026 23:17:31 +0300 Subject: [PATCH] P1.2: f_52d990 = memmove/memcpy thunk, NOT a multiply; corrected step-3/5 FIR window semantics (copy window tail + const fill); xmm9/xmm13 remain --- handoff/NOTES_LEVEL.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/handoff/NOTES_LEVEL.md b/handoff/NOTES_LEVEL.md index d915a72..30c34ac 100644 --- a/handoff/NOTES_LEVEL.md +++ b/handoff/NOTES_LEVEL.md @@ -160,6 +160,47 @@ Остаток 0.7 dB (Q=0.1) = LUT-колено 0.574 -> нужен FFT-уровень (0x535a70 + окно 0x540658 + freq-axis 0x540698), см. SESSION_HANDOFF §5-6. +## ============ UPDATE 2026-08-19d: f_52d990 / f_52d920 / f_52db50 DECODED (CORRECTION) ============ +Disasm: handoff/nls_dasm/f_52d990.dis (52 B), f_52d920.dis, f_52db50.dis; caller f_52b570.dis. + +### Identity (they are CRT-style thunks, NOT arithmetic kernels): +- **f_52d990(rcx=dst, rdx=src, r8d=count) = memmove/memcpy thunk.** + Prologue saves rbx/rsi/rdi; movs args into callee regs; indirect call through GOT 0x1bab008 + (the CRT "select scalar vs vector" resolver, same 0x2650db8 pair used everywhere); then tail-jumps + to 0x2000 (scalar path) or 0x1c40 (vector path). Returns void. This is a COPY, not a multiply. +- **f_52d920(rcx=dst, xmm1=val, r8d=count) = scalar fill (low-half filler).** tail 0x2030(float)/0x1d30(double). +- **f_52db50(rcx=dst, xmm1=val, r8d=count) = scalar fill variant.** tail 0x19a0/0x22d0. +=> The earlier NOTES "0x52d990 = FIR *= WINDOW" was WRONG. Corrected step map below. + +### Corrected step 5 (f_52b570:52b75e-52b78c): +``` + rax = [ctx+0x540534] ; N (FFT size) + rbp = N/2 + FIR[N] = 0 ; zero the Nyquist bin + rax = [ctx+0x540658] ; window base (WIN_WINDOW, 8193 f32) + rdx = rax + N/2*4 ; src = window + N/2 + call f_52d990(FIR, window+N/2, N/2) ; FIR[0..N/2-1] = window[N/2..N-1] (COPY) + call f_52db50(FIR+N/2, xmm9, N/2) ; FIR[N/2..N-1] = xmm9 (const fill) + inverse FFT +``` +So step 5 replaces the FIR's lower half with the SECOND half of the captured window +(window[N/2:] is the 0.75→1.0 rising segment) and fills the upper half with a constant xmm9. + +### Corrected step 3 (f_52b570:52b685-52b6b3): +``` + rax = N; rbp = N/2 + FIR[N] = 0 + call f_52d920(FIR+4, xmm13, N/2-1) ; FIR[1..N/2-1] = xmm13 (LOW fill) + call f_52db50(FIR+4+N/2, xmm9, N/2-1) ; FIR[N/2+1..N-1] = xmm9 (HIGH fill) + inverse FFT +``` + +### Remaining unknowns (now narrowed): +- xmm9 / xmm13 scalar values = still the FUN_180529fe0 prologue constants (need prologue read or live capture). +- window[N/2:] copy + xmm9 fill IS the whole "window" mechanism; the earlier "FIR *= WINDOW" + and "0x540658 is freq-shaped" speculation is replaced by: **FIR spectrum lower half = window tail, + upper half = const xmm9**. Window content already captured (rtwin_freq_44100.npy → WIN_WINDOW). + ## ============ UPDATE 2026-08-18c: FFT-CONV LOOP FULLY MAPPED (Phase 5 step 3 partial) ============ Per-band FFT-conv loop disasm: /tmp/opencode/f_52b570.dis (0x52b550-0x52b8b5 == consumers :1195-1271).