chore: add migration/ bundle for cross-machine setup

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>
This commit is contained in:
MechaCat02
2026-05-10 21:38:38 +02:00
parent 8e709b0a24
commit e6d43a23ac
505 changed files with 86028 additions and 0 deletions

View File

@@ -0,0 +1,192 @@
# `bcx` — Branch Conditional
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [B](../forms/B.md) · **Opcode:** `0x40000000` · _sync_
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `bc` | `bcx` | — | Branch Conditional |
| `bcl` | `bcx` | LK=1 | Branch Conditional |
## Syntax
```asm
bc[LK][AA] [BO], [BI], [ADDR]
```
## Encoding
### `bcx` — form `B`
- **Opcode word:** `0x40000000`
- **Primary opcode (bits 05):** `16`
- **Extended opcode:** —
- **Synchronising:** yes
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `BO` | branch options |
| 1115 | `BI` | CR bit to test |
| 1629 | `BD` | signed 14-bit word-offset target |
| 30 | `AA` | absolute-address flag |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `LK` | bcx: read | Link bit. When 1, LR ← address-of-next-instruction before the branch is taken. |
| `AA` | bcx: read | Absolute-address bit. When 1, the branch target is the sign-extended displacement itself; when 0, it is added to the current instruction address. |
| `BO` | bcx: read | 5-bit branch options — selects CTR decrement, CTR test polarity, and CR bit test polarity. See `forms/XL.md`. |
| `BI` | bcx: read | CR bit index (031) selected by BO's condition test. |
| `ADDR` | bcx: read | Encoded branch target displacement (24-bit for I-form, 14-bit for B-form, word-shifted). |
| `CR` | bcx: read (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
| `CTR` | bcx: read (conditional); bcx: write (conditional) | Count register. Decremented and optionally tested by conditional branches when `BO[2]=0`. |
| `LR` | bcx: write (conditional) | Link register. Written by `bl`/`bla`/`bcl`/`bclrl`/`bcctrl`; read by `bclr`/`bclrl`. |
## Register Effects
### `bcx`
- **Reads (always):** `LK`, `AA`, `BO`, `BI`, `ADDR`
- **Reads (conditional):** `CR`, `CTR`
- **Writes (always):** _none_
- **Writes (conditional):** `CTR`, `LR`
## Status-Register Effects
_No condition-register or status-register effects._
## Operation (pseudocode)
```
if ¬BO[2] then CTR <- CTR 1
ctr_ok <- BO[2] | ((CTR ≠ 0) XOR BO[3])
cond_ok <- BO[0] | (CR[BI] ≡ BO[1])
if ctr_ok & cond_ok then NIA <- CIA + EXTS(BD || 0b00) (AA=0)
EXTS(BD || 0b00) (AA=1)
if LK then LR <- CIA + 4
```
## C Translation Example
```c
/* C translation: the xenia-rs interpreter arm below in */
/* Implementation References is the authoritative semantic */
/* snapshot. Translate it line-by-line: */
/* - ctx.gpr[N] -> r[N] (or f[]/v[] for FPRs/VRs) */
/* - mem.read_u*/write_u* -> mem_read_u*_be / mem_write_u*_be */
/* - ctx.update_cr_signed(fld, v) -> update_cr_signed(fld, v) */
/* - ctx.xer_ca / xer_ov / xer_so -> xer.CA / xer.OV / xer.SO */
/* The Register Effects and Status-Register Effects tables above */
/* enumerate every side effect a faithful translation must emit. */
```
## Implementation References
**`bcx`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="bcx"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:173`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L173)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:11`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L11)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:340`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L340)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:908-938`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L908-L938)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::bcx => {
let bo = instr.bo();
let bi = instr.bi();
// Decrement CTR if needed
if bo & 0b00100 == 0 {
ctx.ctr = ctx.ctr.wrapping_sub(1);
}
let ctr_ok = (bo & 0b00100) != 0
|| (((ctx.ctr as u32) != 0) ^ ((bo & 0b00010) != 0));
let cond_ok = (bo & 0b10000) != 0
|| (ctx.get_cr_bit(bi) == ((bo & 0b01000) != 0));
if ctr_ok && cond_ok {
let target = if instr.aa() {
instr.bd() as u32
} else {
ctx.pc.wrapping_add(instr.bd() as u32)
};
if instr.lk() {
ctx.lr = (ctx.pc + 4) as u64;
}
ctx.pc = target;
} else {
if instr.lk() {
ctx.lr = (ctx.pc + 4) as u64;
}
ctx.pc += 4;
}
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **14-bit signed displacement.** `BD` is a 14-bit signed word-count, scaled by 4 — yielding a ±32 KiB byte range (`2^15 … +2^15 4`). For longer-range conditional control flow, compilers emit a short `bc` over an unconditional `b`.
- **CTR decrement happens before the test.** `BO[2]=0` decrements CTR *first*, then `ctr_ok` evaluates against the new value. The classic `bdnz loop` loops `N` times when CTR is initialised to `N`.
- **LR write is unconditional in xenia.** Xenia writes `LR ← CIA + 4` whenever `LK=1`, even on the not-taken path. This matches the PowerISA: `bcl` always sets `LR` regardless of branch outcome — exploited by `bcl 20, 31, $+4` as a self-PC capture (PIC trick).
- **`BO` encoding** — see `bclrx.md` for the full 5-bit table. `bcx` supports the full set, including CTR-only branches (`bdnz`, `bdz`).
- **Branch hint encoding.** PPC overloads `BO[4]` as a static prediction hint: 0 = "predict not taken", 1 = "predict taken". The Xenon honours it for forward branches; backwards conditional branches are predicted taken regardless. Translators may ignore the hint.
- **Synchronisation.** Marked `sync` — like all branches, `bcx` is context-synchronising. Trivial in interpretation; matters for JIT reorder windows.
- **No `Rc`.** B-form has no record bit; the apparent `Rc` operand-table entry under "Status-Register Effects" is N/A here.
### BO/BI encoding (compact table)
| BO | Effect | Common simplified |
| --- | --- | --- |
| `0000z` | dec CTR, branch if `CTR≠0` & `¬CR[BI]` | `bdnzf BI, addr` |
| `0001z` | dec CTR, branch if `CTR=0` & `¬CR[BI]` | `bdzf BI, addr` |
| `0010y` | dec CTR, branch if `CTR≠0` | `bdnz addr` |
| `0011y` | dec CTR, branch if `CTR=0` | `bdz addr` |
| `0100z` | branch if `¬CR[BI]` | `bf BI, addr` (or `bne`/`bge`/...) |
| `0101z` | branch if `CR[BI]` | `bt BI, addr` (or `beq`/`blt`/...) |
| `1z1zz` | branch always | `b addr` (prefer plain `b` though) |
Bit `z` is the prediction hint (`0` = not taken, `1` = taken).
## Related Instructions
- [`bx`](bx.md) — unconditional displacement branch (24-bit range).
- [`bclrx`](bclrx.md) — branch conditional to LR (function return).
- [`bcctrx`](bcctrx.md) — branch conditional to CTR (indirect call / dispatch).
- [`crand`](../control/crand.md), [`cror`](../control/cror.md), … — combine multiple CR bits before a single `bc`.
- [`mtctr`](../control/mtspr.md), [`mfctr`](../control/mfspr.md) — set/get loop counter for `bdnz`/`bdz`.
- [`sc`](sc.md) — alternative control-flow exit.
### Simplified Mnemonics
The `bc` mnemonic is rarely written directly; assemblers fold most uses into form-specific aliases:
| Simplified | Expansion |
| --- | --- |
| `beq crN, addr` | `bc 0b01100, 4·N+2, addr` — branch if `crN.EQ` |
| `bne crN, addr` | `bc 0b00100, 4·N+2, addr` — branch if `crN.NE` |
| `blt crN, addr` | `bc 0b01100, 4·N+0, addr` — branch if `crN.LT` |
| `bge crN, addr` | `bc 0b00100, 4·N+0, addr` — branch if `crN.GE` |
| `bgt crN, addr` | `bc 0b01100, 4·N+1, addr` — branch if `crN.GT` |
| `ble crN, addr` | `bc 0b00100, 4·N+1, addr` — branch if `crN.LE` |
| `bso crN, addr` | `bc 0b01100, 4·N+3, addr` — branch on summary overflow |
| `bns crN, addr` | `bc 0b00100, 4·N+3, addr` — branch on no SO |
| `bdnz addr` | `bc 0b10000, 0, addr` — decrement CTR, branch if non-zero |
| `bdz addr` | `bc 0b10010, 0, addr` — decrement CTR, branch if zero |
| `bdnzt BI, addr` | combined CTR + CR test (rare) |
When `crN` is omitted in disassembly, `cr0` is implied.
## IBM Reference
- [AIX 7.3 — `bc` (Branch Conditional)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-bc-branch-conditional-instruction)
- [AIX 7.3 — Branch simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-branch-simplified)