DSP Bytecode Interpreter

The KN5000’s dual DSP chips (IC310 MN19413 and IC311 NEC uPD6383GF) are programmed via a two-level bytecode interpreter running on the SubCPU. This page documents the interpreter architecture, opcodes, and register write protocol.

Status: Architecture and opcode tables decoded from SubCPU firmware. The programs themselves — every bytecode stream and parameter record for all 100 effect numbers — are now carved and labelled in the disassembly (Wave 3a, 2026-08-07). Register-to-effect parameter mapping is still incomplete: eight translator opcodes have measured semantics, the rest are named from their code shape only.

Note: This page predates the identification of IC311. It formerly called the chip “DS3613GF-3BA, a custom ASIC” — that was a transcription error; the part is the NEC uPD6383GF-3BA. Everything below about the SubCPU-side interpreter remains valid; for the DSP chip’s own architecture, instruction word, decoded algorithms and the full effect/parameter catalogue, see the newer Effects DSP (NEC uPD6383GF) page.

The programs this interpreter runs now have their own page. The bytecode streams and parameter record tables live in a 39,372-byte zone at Sub-CPU 0x0147B3-0x01E17E, carved block-by-block in 2026-08. Both stream grammars, the four 100-entry pointer arrays and a per-effect address table are documented in DSP Effect Data Zone (Sub-CPU ROM). Addresses on the present page were re-checked against that carve; the corrections are marked inline.

Architecture

The interpreter has two levels:

Level 1 — Low-level Bytecode Interpreter

  • Entry: DSP_BytecodeInterpreter_Init (0x03C259); loop body DSP_BytecodeInterpreter_Loop (0x03C2CB)
  • Called by: DSP_WriteGlobalConfig (0x03C181) and DSP_WriteEFFConfig (0x03C161)
  • Programs: the effect data zone at 0x0147B3-0x01E17E, part of the Sub CPU payload image the Main CPU ships at boot — so they are in Sub CPU RAM at run time, but they are ROM content and are fully carved in the disassembly
  • Format: 2-byte header per instruction — high nibble of b0 = opcode, and the remaining 12 bits ((b0 & 0x0F) << 8) | b1 are the total instruction length in bytes, header included (a big-endian 12-bit count, not an element count)

Level 2 — Translator (Parameter Descriptor Engine)

  • Entry: DSP_Translator_ReadOpcode (0x03CB18); per-parameter walker DSP_PerParameterTranslator (0x03CAAE)
  • Called by: DSP_ParameterWriteEngine (0x03C9E6)
  • Programs: parameter value records and descriptor records, both in the same Sub CPU effect data zone. DSP_WriteParam_Generic (0x03C20E) fetches them from the two 100-entry u32 arrays at 0x01F22C (descriptors) and 0x01F09C (values) — corrected 2026-08: an earlier revision of this page sourced them from the main-CPU table at 0xEE75F6; that table is a separate main-CPU-side DSP-config field table (its first entries are u32 pointers into 0xEE64DA-0xEE69E8, i.e. main-CPU program ROM) and is not this engine’s program source
  • Format: records [len_hi, len_lo, id, payload…], big-endian length covering the whole record, 0xF0 as the end-of-table sentinel. Inside a value record the id byte is dispatched as an opcode, then { id, field-index, operands } repeat until 0x7A

Dispatch Router

DSP_DispatchCommand(wa=cmd_byte, bc=chip_id) (0x036A2E) routes to DSP1 (chip=0, IC311, parallel bus) or DSP2 (chip=1, IC310, SPI serial). DSP_DispatchData (0x036A4F) similarly routes data bytes.

The chip id is not passed down from the caller — it is looked up per effect slot in the 5-byte table at Sub-CPU 0x01ED6D, whose contents are 00 00 01 01 01: slots 0-1 are IC311, slots 2-4 are IC310. DSP_WriteEFFConfig, EFF_Disconnect and the parameter-write front door all do the same byte(0x01ED6D + slot) fetch.

Level 1 Opcodes (Low-level)

Opcode Handler Description
0x0N Handler 0 CMD + preamble + groups-of-5 (3-way branch: 0x00=static, 0x0A=raw, else=param-modified)
0x1N Handler 1 CMD + preamble + groups-of-5 (12-bit address computation)
0x2N Handler 2 CMD + preamble + groups-of-3 (pure raw data writes)
0x3N Handler 3 CMD + 16-bit address + raw tail
0x4N Handler 4 Single command byte only
0x5N Handler 5 CMD + preamble + groups-of-5 (variant with IZH mask)
0x0D Op0D SPI bus idle + state change notification
0x0E Op0E DispatchCommand + DispatchData loop (register write)
0xFN End Terminate program

Opcodes 0x6-0xC are consumed and ignored. Termination is by peek: the stream ends when the next byte’s high nibble is 0xF, so the 0xF0 terminator is not executed.

Handler dispatch table: OFFSETS_14739 at 0x014739 — 6 signed u16 offsets relative to base 0x03C32E, decoding to handlers at 0x03C32E, 0x03C568, 0x03C661, 0x03C708, 0x03C7A1, 0x03C7BB. Handler code: 1,613 bytes of embedded machine code at DSP_Bytecode_Programs (0x03C32E), still kept as raw bytes in the disassembly because of unsupported addressing modes.

Level 2 Opcodes (Translator)

Opcode Handler Output Purpose
0x21 ParamInterp_2Point WriteOscParam 2-point linear interpolation
0x24 ParamInterp_MultiStep WriteOscParam Multi-step interpolation
0x40 PanScale_Simple WriteOscParam Pan position scaling
0x61 ParamFetch_SingleTable WriteOscParam Direct parameter lookup
0x62 ParamFetch_AlgoTypeTable WriteFreqParam_AlgoType Algorithm-dependent freq param
0x63 AlgoParam_Decode WriteOscParam Algorithm parameter decode
0x64 PitchParam_Scale WriteFreqParam Pitch scaling with freq write
0x65 VolumeParam_Scale WriteOscParam Volume scaling
0x66 ParamInterp_2Point WriteOscParam 2-point interpolation (oscillator)
0x67 ParamInterp_FPScale WriteOscParam_Offset FP scale with offset
0x68 ParamInterp_Div0xB4 WriteFreqParam Frequency interp (divide by 0xB4)
0x69 VolumeCurve_FP WriteOscParam Fixed-point volume curve
0x6A FreqCurve_FP WriteFreqParam Fixed-point frequency curve
0x6B FreqInterp_2Point WriteFreqParam 2-point frequency interp
0x6C ParamInterp_3Point_WithOffset WriteFreqParam 3-point interp with offset
0x6D ReverbCurve_FP WriteOscParam Reverb-specific curve
0x6E ParamInterp_FPComplex WriteOscParam Complex FP interpolation
0x6F PanCurve_PiecewiseLin WriteOscParam Piecewise-linear pan curve
0x70 BiquadCoeff_Compute (direct) Biquad IIR filter coefficient
0x71 DetuneCurve_SignedFP WriteOscParam Signed FP detune curve
0x72 BiquadWarp_FP (direct) Bilinear transform warping
0x73 ParamInterp_Div0xC6 WriteOscParam Interpolation (divide by 0xC6)
0x74 WriteLUTParamSet (direct) Lookup table parameter set
0x75 ParamEQ_Curve_FP WriteOscParam Parametric EQ curve
0x76 SOS_Coeff_Compute (direct) Second-order section coefficient
0x77 ParamInterp_2Point_B WriteOscParam 2-point interp variant B
0x78 VolScale_B WriteOscParam Volume scaling variant B
0x7A (end) — Terminate bytecode block
0xF0 (separator) — Separator between parameter slots

Translator dispatch table: OFFSETS_14745 at 0x014745 — 25 signed u16 offsets relative to base 0x03CB8E, indexed by opcode - 0x61 for opcodes 0x61-0x79. Opcodes 0x21, 0x24 and 0x40 are special-cased before this table; anything else aborts via DSP_Op_Unknown_Error. Note that opcode 0x79 is a real entry (offset 0x88, target 0x03CC16) — the table covers 0x61-0x79, not 0x61-0x78.

The measured semantics of the settled subset are on the DSP Effect Data Zone page (0x21 universal tail level, 0x62 CURVE_D volume law at 1.00 dB/step, 0x68 ms→DRAM words at 44.1 kHz, 0x69 degrees, 0x70 biquad, 0x72 compressor threshold/ratio). Where that page and the inferred descriptions in the table above disagree, the measured page wins.

SPI Protocol (DSP2 Register Writes)

Physical layer: GPIO bit-banging on SubCPU ports.

Signal Port Bit
SDA Port F (0x3C) bit 0
SCLK Port F (0x3C) bit 2
CS2 Port E (0x38) bit 6

Each SPI transaction produces 9 SCLK rising edges (confirmed by DSP2_Send_Command at subcpu line 32980).

CMD 0x30 Register Write Sequence

A register write sends 5 SPI transactions:

  1. Command 0x30 (register write command)
  2. Data 0x00 (constant preamble byte)
  3. Data register_address (8-bit DSP register)
  4. Data value_high (MSB of 16-bit value)
  5. Data value_low (LSB of 16-bit value)

Boot-time Writes

Register Value Purpose
0xD0 0x0000 Initialization
0xD3 0x0000 Initialization
0x3C 0x4000 Configuration

DSP Register Address Space

Registers use a structured addressing scheme:

Parametric EQ (detected from opcode 0x70 = BiquadCoeff_Compute)

5-band parametric EQ, each band with 3 coefficients:

Band Frequency Q Factor Gain
0 0x0000 0x0010 0x0020
1 0x0100 0x0110 0x0120
2 0x0200 0x0210 0x0220
3 0x0300 0x0310 0x0320
4 0x0400 0x0410 0x0420

Effect Algorithm Types

The firmware supports 12 algorithm types (indices 0-11). The Wave-3a carve of the sub-CPU data zones turned up the whole supporting table family, all of which agree on that count:

table address shape
AlgoJumpTable1 0x00FB66 12 × u16 offsets, base 0x033812 (DSP_AlgoType_Dispatch1_TableData)
AlgoJumpTable2 0x00FB7E 12 × u16, base 0x0339DE
AlgoJumpTable3 0x00FB96 12 × u16, base 0x033E44
AlgoJumpTable4/5/6 0x00FBAE / 0x00FBC0 / 0x00FBD2 9 × u16, bases 0x0340CC / 0x0341BE / 0x03429D
DSP_EFFPARAM_APPLY_JUMPTABLE 0x00F99B 12 × u16, base 0x02F2D9 (DSP_EffParam_Apply_By_AlgoType)
DSP_AlgoChannel_SelectorRecords 0x010FCE 12 × 6 bytes — three 2-byte channel pairs per type, 0xFF = no entry
DSP_AlgoDescriptor_Records 0x011E16 14 × 39-byte (0x27) records; types 12 and 13 are all zero

Correction (2026-08). An earlier revision of this page said DSP_WriteEFFConfig “looks up the algorithm type from a table at 0x1ED6D[wa]”. It does not: 0x01ED6D is the 5-byte chip-id table described above (00 00 01 01 01, indexed by effect slot). DSP_WriteEFFConfig fetches that chip id, then calls DSP_BytecodeInterpreter_Init(chip, slot, XDE = 0x014777, bytecode stream). 0x014777 is a run of 12-byte interpreter-frame descriptors indexed by slot (+0,+2,+4,+6 are copied into the interpreter frame, +8 is a long); the disassembly still carries the inherited ELF label ToneGen_WorkArea there, which is a misnomer — it is DSP program/parameter data, not a tone-generator work area. DSP_WriteGlobalConfig does the same with the sibling descriptor table at 0x0147B3 and program index 0.

Key Functions (SubCPU)

Addresses, not source line numbers — the disassembly moved from .asm to .s modules and the old line references were stale. These are the current entries in symbols/subcpu_symbols_reference.txt.

Function Address Purpose
DSP_BytecodeInterpreter_Init 0x03C259 Low-level interpreter entry
DSP_BytecodeInterpreter_Loop 0x03C2CB Fetch/decode/dispatch loop
DSP_Bytecode_Programs 0x03C32E 1,613 bytes of handler machine code
DSP_Bytecode_NotifyStateChange 0x03C253 Tail-jumps into the scheduler (yields between register groups)
DSP_ParameterWriteEngine 0x03C9E6 Translator entry point
DSP_PerParameterTranslator 0x03CAAE Walks one value record to its 0x7A
DSP_Translator_ReadOpcode 0x03CB18 Opcode decode + dispatch
DSP_TableWalk_Search 0x03CF53 Finds the descriptor record with a given id
DSP_TableWalk_SearchWithState 0x03CFA5 Same, stateful variant
DSP_DispatchCommand 0x036A2E Route command to DSP1/DSP2
DSP_DispatchData 0x036A4F Route data to DSP1/DSP2
DSP2_Send_Command 0x03666B SPI bit-bang: 9 SCLK rising edges
DSP2_SPI_BusIdle 0x0364C4 SPI CS deassert + state change
DSP_WriteGlobalConfig 0x03C181 Global config via bytecode (descriptor table 0x0147B3)
DSP_WriteEFFConfig 0x03C161 Effect config via bytecode (descriptor table 0x014777)
DSP_WriteParameter 0x03C190 “Write parameter set N of effect M” front door
DSP_WriteParam_Generic 0x03C20E Generic arm: descriptors from 0x01F22C, values from 0x01F09C
DSP_MixerCoeff_Compute 0x03C067 Two-stage mixer gain via DSP_MixerGain_Curve
DSP_WriteParamCmd30 0x038439 CMD 0x30 register write (5 SPI transactions)
DSP_WriteOscParam 0x0387E6 Write oscillator/effect parameter
DSP_WriteFreqParam 0x038539 Write frequency parameter
DSP_Read_Status 0x0383F7 Poll DSP1 ready via Port PH bit 0
EFF_Change_WithDebug 0x0380EC Uploads algorithm then coefficients for one slot