Update all docs and test generator to match verified assembler opcodes
- README.md: Complete project overview with plugin status - ARCHITECTURE.md: Fixed register tables (CNTR in REG1, not REG2) - GETTING_STARTED.md: r2-native workflow, removed Python disasm refs - PRACTICAL_EXAMPLE.md: Uses verified open21xx opcodes with bit layouts - ROM_ANALYSIS_WALKTHROUGH.md: Updated format detection and r2 commands - r2plugin/README.md: Simplified, points to assembler test ROM - gen_isa_test.py: All opcodes from open21xx assembler with labels
This commit is contained in:
@@ -1,75 +1,76 @@
|
||||
# ADSP-219x ROM Analyse Walkthrough
|
||||
# ROM Analysis Walkthrough
|
||||
|
||||
Dieses Dokument beschreibt den systematischen Prozess der Analyse eines ADSP-219x Binär-Dumps. Da wir mit einer 24-Bit Architektur auf einer 8-Bit-basierten Dateisystem-Welt arbeiten, ist der erste Schritt immer die Validierung des Formats.
|
||||
## 1. Determine the ROM Format
|
||||
|
||||
## 1. Phase: Format-Validierung (Padded vs. Packed)
|
||||
ADSP-2191 instructions are 24 bits (3 bytes). A raw dump can be:
|
||||
|
||||
Ein ADSP-2191 Befehl ist **24 Bit (3 Bytes)** groß. In einem ROM-Dump liegen diese meist in einem von zwei Formaten vor:
|
||||
- **Packed (3 bytes/word)**: Most common for SPI flash dumps.
|
||||
Load directly: `r2 -a adsp219x -b 24 dump.bin`
|
||||
- **Padded (4 bytes/word)**: 32-bit aligned with a leading 0x00.
|
||||
Strip padding or use `r2 -s 1` to skip the first pad byte.
|
||||
- **Boot stream**: Contains block headers (target address, byte
|
||||
count, flags) followed by data. Requires parsing the header
|
||||
format first.
|
||||
|
||||
* **Packed (3-Byte):** `[B0][B1][B2] [B3][B4][B5] ...` (Keine Lücken)
|
||||
* **Padded (4-Byte):** `[00][B0][B1][B2] [00][B3][B4][B5] ...` (Oft bei 32-Bit EPROM-Builds)
|
||||
### Quick Format Check
|
||||
|
||||
### Woran erkenne ich das Format?
|
||||
Suche nach dem **NOP** Opcode.
|
||||
* Ein klassischer NOP (Type 30) ist `0x000000`.
|
||||
* Ein Multifunktions-NOP (Type 1) ist `0xC00000`.
|
||||
Look at the first few bytes. If you see `00 00 00` at offset 0
|
||||
(a NOP), you likely have packed 3-byte format. If you see
|
||||
`00 00 00 00` followed by meaningful data at offset 4, it is
|
||||
probably 4-byte padded.
|
||||
|
||||
Wenn du alle 3 oder 4 Bytes lange Ketten von `00` findest, hast du wahrscheinlich das Alignment gefunden.
|
||||
## 2. Find the Entry Point
|
||||
|
||||
## 2. Phase: Den Einstiegspunkt finden (Vector Table)
|
||||
The reset vector is at PM address 0x0000. Typical patterns:
|
||||
|
||||
Der ADSP-2191 startet nach einem Reset bei Adresse `0x0000` im Programm-Memory (PM).
|
||||
Die ersten Adressen sind die Interrupt-Vektoren (jeweils 8 oder 16 Words Platz).
|
||||
0x0000: JUMP main (Type 10a, opcode starts with 0x1C)
|
||||
0x0000: NOP (entry at next instruction)
|
||||
|
||||
**Typisches Muster am Anfang:**
|
||||
```text
|
||||
0x0000: JUMP 0x0100 <-- Reset Vector
|
||||
0x0008: RTI <-- Power Down Vector
|
||||
0x0010: RTI <-- Kernel Interrupt
|
||||
...
|
||||
```
|
||||
The interrupt vector table occupies the first ~128 PM words,
|
||||
with 4-word spacing per vector. Most vectors contain RTI (return
|
||||
from interrupt) or JUMP to a handler.
|
||||
|
||||
Wenn dein Disassembler am Anfang nur `UNKNOWN` auswirkt, ist meistens das Alignment (3 vs 4 Byte) oder die Endianness falsch. ADSP-219x ist standardmäßig **Big-Endian**.
|
||||
## 3. Identify Code vs Data Regions
|
||||
|
||||
## 3. Phase: Den Code "lesen" (Pattern Recognition)
|
||||
**Code regions** produce coherent disassembly: register loads,
|
||||
compute instructions, jumps, and loops in logical sequence.
|
||||
|
||||
### A. Register Initialisierung (Type 6/7)
|
||||
DSP-Code beginnt fast immer damit, die DAGs (Data Address Generators) zu füttern.
|
||||
* `I0 = 0x2000` (Index-Register auf Start eines Buffers)
|
||||
* `M0 = 1` (Modifier auf Schrittweite 1)
|
||||
* `L0 = 0` (Circular Buffering aus)
|
||||
**Data regions** (coefficient tables, lookup tables) produce
|
||||
nonsensical disassembly: random-looking mnemonics, impossible
|
||||
register combinations, jumps to invalid addresses. Mark these
|
||||
as data in r2:
|
||||
|
||||
**In deinem Disassembler:**
|
||||
`AX0 = 0x1234` entspricht Opcode `0x4x....`. Das ist ein Type 6 Befehl.
|
||||
Cd 300 @ 0x1000 # Mark 300 bytes as data at offset 0x1000
|
||||
|
||||
### B. Die "Magic" des DSP: Multifunktions-Opcodes (Type 1)
|
||||
Das ist der Kern des DSPs. In einem einzigen Takt passiert:
|
||||
1. Eine Berechnung (ALU/MAC)
|
||||
2. Ein Read aus dem DM (Data Memory)
|
||||
3. Ein Read aus dem PM (Program Memory)
|
||||
## 4. Recognize DSP Patterns
|
||||
|
||||
**Beispiel:**
|
||||
`MR + X * Y (SS), AX0 = DM(I0 += M0), AY0 = PM(I4 += M4)`
|
||||
### FIR Filter
|
||||
|
||||
* **Identifikation:** Opcodes die mit `0xC` bis `0xF` beginnen.
|
||||
* **Schlussfolgerung:** Das ist oft eine innere Schleife (z.B. ein FIR-Filter). Wenn du viele dieser Befehle hintereinander siehst, hast du den Signalverarbeitungs-Kernel gefunden.
|
||||
CNTR = N;
|
||||
DO loop_end UNTIL CE;
|
||||
MR = MR + MX0*MY0 (SS), MX0 = DM(I0,M0), MY0 = PM(I4,M4);
|
||||
loop_end: ...
|
||||
|
||||
## 4. Phase: Daten vs. Code im PM
|
||||
Look for: Type 11 (DO UNTIL CE) followed by Type 1 multifunction
|
||||
instructions with MAC operations.
|
||||
|
||||
Der ADSP-2191 hat eine Harvard-Architektur. Das Programm-Memory (PM) kann aber auch Daten enthalten (24-Bit breit).
|
||||
Dank des **Visible Instruction State (VIS)** kann der 2191 hocheffizient 24-Bit Koeffizienten aus dem PM laden, während er rechnet.
|
||||
### IIR Filter (Biquad)
|
||||
|
||||
**Woran erkenne ich Daten im PM?**
|
||||
Wenn der Disassembler sinnlose Befehle ausgibt (z.B. hunderte `UNKNOWN` oder seltsame Sprünge in ungültige Bereiche), handelt es sich wahrscheinlich um eine **Koeffizienten-Tabelle** (z.B. Sinus-Werte oder Filter-Taps).
|
||||
Nested loops: outer loop over samples, inner loop over biquad
|
||||
sections. Contains ASHIFT for scaling between stages.
|
||||
|
||||
## 5. Phase: Analyse-Workflow mit radare2
|
||||
### Initialization Sequence
|
||||
|
||||
Wenn du den Dump in `iaito` oder `r2` lädst:
|
||||
Sequences of Type 6/7 instructions loading I/M/L registers.
|
||||
This sets up circular buffers for the signal processing kernel.
|
||||
|
||||
1. **Bit-Breite:** Setze `e asm.bits = 24`.
|
||||
2. **Suchen:** Suche nach `000000` (NOPs), um Funktionsgrenzen zu finden.
|
||||
3. **Cross-References:** Suche nach `CALL` Befehlen (`0x11....`), um die Programmstruktur zu verstehen.
|
||||
4. **I/O Analyse:** Der ADSP-2191 steuert Peripherie über I/O-Register. Suche nach `IO(addr) = Dreg`. Adressen wie `0x00` bis `0x3F` sind oft System-Controller oder Sport (Serial Port) Konfiguration.
|
||||
## 5. Useful r2 Commands
|
||||
|
||||
---
|
||||
**Tipp:** Nutze das beiliegende Skript `analysis/analyze_rom.py`, um eine erste Statistik über die verwendeten Instruktionstypen zu erhalten. Das zeigt dir sofort, ob der Dump primär aus Logik (`JUMP`, `IF`) oder aus Mathe (`Compute`, `Multifunction`) besteht.
|
||||
e asm.arch = adsp219x
|
||||
e asm.bits = 24
|
||||
pd 200 # Disassemble 200 instructions
|
||||
pD 600 # Disassemble 600 bytes (= 200 instructions)
|
||||
/x 1c00 # Find unconditional JUMPs
|
||||
/x 16 # Find DO UNTIL loops
|
||||
/x 0a # Find RTS/RTI instructions
|
||||
V # Enter visual mode
|
||||
|
||||
Reference in New Issue
Block a user