Bundles state that lives OUTSIDE the xenia-rs repo so a fresh clone on
another machine can be brought up to identical configuration via
migration/setup.sh:
- claude-memory/ ~/.claude/projects/-home-fabi-RE-Project-Sylpheed/memory/
(103 files, 1.1 MB - MEMORY.md + every
project_xenia_rs_*.md from audits
addis_signext through audit-058)
- project-root/dot-claude/ <project-root>/.claude/settings.json
(Stop hook + permissions)
- project-root/ppc-manual/ <project-root>/ppc-manual/
(PowerPC reference docs, 397 files, 3.7 MB)
- project-root/run-canary.sh <project-root>/run-canary.sh
- README.md Human-readable setup checklist
- setup.sh Idempotent installer (also reclones
xenia-canary at pinned HEAD 6de80dffe)
- MANIFEST.md Per-file mapping + per-file-not-bundled
restoration recipe
Excluded from bundle (not shippable via git):
- Sylpheed ISO (7.8 GB; copyright; manual copy required)
- sylpheed.db (395 MB; regenerable from XEX via analysis tooling)
- target/ build artifacts (rebuild on target)
- audit-runs probe firehoses (.log/.stdout/.stderr ~11 GB; rerun if needed)
- audit-runs memory dumps (.bin ~4.5 GB; rerun audit-026/027/029 if needed)
- xenia-canary checkout (setup.sh reclones from
git.mc02.dev/fabi/Xenia-Canary.git at HEAD 6de80dffe)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
267 lines
10 KiB
Python
267 lines
10 KiB
Python
"""
|
||
Canonical bit layout per PPC instruction form.
|
||
|
||
Tables derived from xenia-canary/src/xenia/cpu/ppc/ppc_instr.h (struct
|
||
PPCOpcodeBits union). In PPC notation bit 0 is the MSB of the 32-bit
|
||
word (big-endian bit numbering).
|
||
|
||
Each entry is a list of (bit_start, bit_end_inclusive, field_name,
|
||
notes) tuples laid out from MSB (bit 0) to LSB (bit 31).
|
||
"""
|
||
|
||
|
||
# NOTE: bit ranges use PPC big-endian numbering (0 = MSB, 31 = LSB).
|
||
|
||
FORM_LAYOUTS: dict[str, list[tuple[int, int, str, str]]] = {
|
||
"I": [
|
||
(0, 5, "OPCD", "primary opcode"),
|
||
(6, 29, "LI", "signed 24-bit word-offset target"),
|
||
(30, 30, "AA", "absolute-address flag"),
|
||
(31, 31, "LK", "link flag (bl/ba/bla)"),
|
||
],
|
||
"B": [
|
||
(0, 5, "OPCD", "primary opcode"),
|
||
(6, 10, "BO", "branch options"),
|
||
(11, 15, "BI", "CR bit to test"),
|
||
(16, 29, "BD", "signed 14-bit word-offset target"),
|
||
(30, 30, "AA", "absolute-address flag"),
|
||
(31, 31, "LK", "link flag"),
|
||
],
|
||
"SC": [
|
||
(0, 5, "OPCD", "primary opcode (17)"),
|
||
(6, 19, "—", "reserved"),
|
||
(20, 26, "LEV", "exception level"),
|
||
(27, 29, "—", "reserved"),
|
||
(30, 30, "1", "fixed 1"),
|
||
(31, 31, "—", "reserved"),
|
||
],
|
||
"D": [
|
||
(0, 5, "OPCD", "primary opcode"),
|
||
(6, 10, "RT", "destination GPR (or RS when storing)"),
|
||
(11, 15, "RA", "source GPR (0 ⇒ literal 0 for RA0 forms)"),
|
||
(16, 31, "D/SI/UI", "16-bit signed or unsigned immediate"),
|
||
],
|
||
"DS": [
|
||
(0, 5, "OPCD", "primary opcode"),
|
||
(6, 10, "RT", "destination GPR (or RS)"),
|
||
(11, 15, "RA", "source GPR (0 ⇒ literal 0)"),
|
||
(16, 29, "DS", "14-bit signed word-scaled displacement"),
|
||
(30, 31, "XO", "extended opcode"),
|
||
],
|
||
"X": [
|
||
(0, 5, "OPCD", "primary opcode"),
|
||
(6, 10, "RT/FRT/VRT", "destination"),
|
||
(11, 15, "RA/FRA/VRA", "source A"),
|
||
(16, 20, "RB/FRB/VRB", "source B"),
|
||
(21, 30, "XO", "extended opcode (10 bits)"),
|
||
(31, 31, "Rc", "record-form flag"),
|
||
],
|
||
"XL": [
|
||
(0, 5, "OPCD", "primary opcode (19)"),
|
||
(6, 10, "BT/BO", "target / branch options"),
|
||
(11, 15, "BA/BI", "source A / CR bit to test"),
|
||
(16, 20, "BB", "source B"),
|
||
(21, 30, "XO", "extended opcode (10 bits)"),
|
||
(31, 31, "LK", "link flag"),
|
||
],
|
||
"XFX": [
|
||
(0, 5, "OPCD", "primary opcode (31)"),
|
||
(6, 10, "RT", "destination / source GPR"),
|
||
(11, 20, "spr/tbr/FXM", "SPR/TBR number (byte-swapped halves) or CR field mask"),
|
||
(21, 30, "XO", "extended opcode"),
|
||
(31, 31, "—", "reserved"),
|
||
],
|
||
"XFL": [
|
||
(0, 5, "OPCD", "primary opcode (63)"),
|
||
(6, 6, "L", "field-select behaviour"),
|
||
(7, 14, "FM", "FPSCR field mask"),
|
||
(15, 15, "W", "immediate-value flag"),
|
||
(16, 20, "FRB", "source FPR"),
|
||
(21, 30, "XO", "extended opcode"),
|
||
(31, 31, "Rc", "record-form flag (updates CR1)"),
|
||
],
|
||
"XS": [
|
||
(0, 5, "OPCD", "primary opcode (31)"),
|
||
(6, 10, "RS", "source GPR"),
|
||
(11, 15, "RA", "destination GPR"),
|
||
(16, 20, "sh", "shift amount low 5 bits"),
|
||
(21, 29, "XO", "extended opcode (9 bits)"),
|
||
(30, 30, "sh5", "shift amount high bit"),
|
||
(31, 31, "Rc", "record-form flag"),
|
||
],
|
||
"XO": [
|
||
(0, 5, "OPCD", "primary opcode (31)"),
|
||
(6, 10, "RT", "destination GPR"),
|
||
(11, 15, "RA", "source A"),
|
||
(16, 20, "RB", "source B"),
|
||
(21, 21, "OE", "overflow-enable flag"),
|
||
(22, 30, "XO", "extended opcode (9 bits)"),
|
||
(31, 31, "Rc", "record-form flag"),
|
||
],
|
||
"A": [
|
||
(0, 5, "OPCD", "primary opcode (59 or 63)"),
|
||
(6, 10, "FRT", "destination FPR"),
|
||
(11, 15, "FRA", "source A FPR"),
|
||
(16, 20, "FRB", "source B FPR"),
|
||
(21, 25, "FRC", "source C FPR (multiplier for madd-style ops)"),
|
||
(26, 30, "XO", "extended opcode (5 bits)"),
|
||
(31, 31, "Rc", "record-form flag (updates CR1)"),
|
||
],
|
||
"M": [
|
||
(0, 5, "OPCD", "primary opcode"),
|
||
(6, 10, "RS", "source GPR"),
|
||
(11, 15, "RA", "destination GPR"),
|
||
(16, 20, "SH/RB", "shift amount or source B"),
|
||
(21, 25, "MB", "mask begin"),
|
||
(26, 30, "ME", "mask end"),
|
||
(31, 31, "Rc", "record-form flag"),
|
||
],
|
||
"MD": [
|
||
(0, 5, "OPCD", "primary opcode (30)"),
|
||
(6, 10, "RS", "source GPR"),
|
||
(11, 15, "RA", "destination GPR"),
|
||
(16, 20, "sh", "shift amount low 5 bits"),
|
||
(21, 26, "mb/me", "6-bit mask field (swapped halves)"),
|
||
(27, 29, "XO", "extended opcode"),
|
||
(30, 30, "sh5", "shift amount high bit"),
|
||
(31, 31, "Rc", "record-form flag"),
|
||
],
|
||
"MDS": [
|
||
(0, 5, "OPCD", "primary opcode (30)"),
|
||
(6, 10, "RS", "source GPR"),
|
||
(11, 15, "RA", "destination GPR"),
|
||
(16, 20, "RB", "source B GPR"),
|
||
(21, 26, "mb/me", "6-bit mask field (swapped halves)"),
|
||
(27, 30, "XO", "extended opcode"),
|
||
(31, 31, "Rc", "record-form flag"),
|
||
],
|
||
"DCBZ": [
|
||
(0, 5, "OPCD", "primary opcode (31)"),
|
||
(6, 10, "—", "reserved"),
|
||
(11, 15, "RA", "base register (0 ⇒ literal 0)"),
|
||
(16, 20, "RB", "offset register"),
|
||
(21, 30, "XO", "extended opcode (1014 for dcbz / 1010 for dcbz128)"),
|
||
(31, 31, "—", "reserved"),
|
||
],
|
||
"VX": [
|
||
(0, 5, "OPCD", "primary opcode (4)"),
|
||
(6, 10, "VRT/VD", "destination vector register"),
|
||
(11, 15, "VRA/VA", "source A vector register"),
|
||
(16, 20, "VRB/VB", "source B vector register"),
|
||
(21, 31, "XO", "extended opcode (11 bits)"),
|
||
],
|
||
"VA": [
|
||
(0, 5, "OPCD", "primary opcode (4)"),
|
||
(6, 10, "VRT", "destination vector register"),
|
||
(11, 15, "VRA", "source A"),
|
||
(16, 20, "VRB", "source B"),
|
||
(21, 25, "VRC", "source C / shift"),
|
||
(26, 31, "XO", "extended opcode (6 bits)"),
|
||
],
|
||
"VC": [
|
||
(0, 5, "OPCD", "primary opcode (4)"),
|
||
(6, 10, "VRT", "destination vector register"),
|
||
(11, 15, "VRA", "source A"),
|
||
(16, 20, "VRB", "source B"),
|
||
(21, 21, "Rc", "record-form flag (updates CR6)"),
|
||
(22, 31, "XO", "extended opcode (10 bits)"),
|
||
],
|
||
"VX128": [
|
||
(0, 5, "OPCD", "primary opcode (4 or 5)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "VA128l", "source A low 5 bits"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 21, "VA128H", "source A high bit"),
|
||
(22, 22, "—", "reserved"),
|
||
(23, 25, "VC", "optional VC / XO sub-field"),
|
||
(26, 26, "VA128h", "source A middle bit"),
|
||
(27, 27, "—", "reserved"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
"VX128_1": [
|
||
(0, 5, "OPCD", "primary opcode (4)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "RA", "address register"),
|
||
(16, 20, "RB", "offset register"),
|
||
(21, 27, "XO", "extended opcode"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "—", "reserved"),
|
||
],
|
||
"VX128_2": [
|
||
(0, 5, "OPCD", "primary opcode (5)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "VA128l", "source A low 5 bits"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 21, "VA128H", "source A high bit"),
|
||
(23, 25, "VC", "source C 3-bit field"),
|
||
(26, 26, "VA128h", "source A middle bit"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
"VX128_3": [
|
||
(0, 5, "OPCD", "primary opcode (6)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "IMM", "5-bit immediate"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 27, "XO", "extended opcode"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
"VX128_4": [
|
||
(0, 5, "OPCD", "primary opcode (6)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "IMM", "5-bit immediate"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 23, "XO", "extended opcode"),
|
||
(24, 25, "z", "sub-operation selector"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
"VX128_5": [
|
||
(0, 5, "OPCD", "primary opcode (4)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "VA128l", "source A low 5 bits"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 21, "VA128H", "source A high bit"),
|
||
(22, 25, "SH", "4-bit shift amount"),
|
||
(26, 26, "VA128h", "source A middle bit"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
"VX128_P": [
|
||
(0, 5, "OPCD", "primary opcode (6)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "PERMl", "permute selector low 5 bits"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 22, "—", "reserved"),
|
||
(23, 25, "PERMh", "permute selector high 3 bits"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
"VX128_R": [
|
||
(0, 5, "OPCD", "primary opcode (4)"),
|
||
(6, 10, "VD128l", "destination low 5 bits"),
|
||
(11, 15, "VA128l", "source A low 5 bits"),
|
||
(16, 20, "VB128l", "source B low 5 bits"),
|
||
(21, 21, "VA128H", "source A high bit"),
|
||
(22, 25, "XO", "extended opcode (compare)"),
|
||
(26, 26, "VA128h", "source A middle bit"),
|
||
(27, 27, "Rc", "record-form flag (updates CR6)"),
|
||
(28, 29, "VD128h", "destination high 2 bits"),
|
||
(30, 31, "VB128h", "source B high 2 bits"),
|
||
],
|
||
}
|
||
|
||
|
||
def render_bit_table(form: str) -> str:
|
||
"""Return a markdown table of the form's bit layout."""
|
||
layout = FORM_LAYOUTS.get(form)
|
||
if not layout:
|
||
return f"_Unknown form_ `{form}` _— see `forms/` for details._"
|
||
rows = ["| Bits | Field | Meaning |", "| --- | --- | --- |"]
|
||
for start, end, name, notes in layout:
|
||
span = f"{start}" if start == end else f"{start}–{end}"
|
||
rows.append(f"| {span} | `{name}` | {notes} |")
|
||
return "\n".join(rows)
|