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:
164
migration/project-root/ppc-manual/branch/bcctrx.md
Normal file
164
migration/project-root/ppc-manual/branch/bcctrx.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# `bcctrx` — Branch Conditional to Count Register
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000420` · _sync_
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `bcctr` | `bcctrx` | — | Branch Conditional to Count Register |
|
||||
| `bcctrl` | `bcctrx` | LK=1 | Branch Conditional to Count Register |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
bcctr[LK] [BO], [BI]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `bcctrx` — form `XL`
|
||||
|
||||
- **Opcode word:** `0x4c000420`
|
||||
- **Primary opcode (bits 0–5):** `19`
|
||||
- **Extended opcode:** `528`
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `LK` | bcctrx: read | Link bit. When 1, LR ← address-of-next-instruction before the branch is taken. |
|
||||
| `BO` | bcctrx: read | 5-bit branch options — selects CTR decrement, CTR test polarity, and CR bit test polarity. See `forms/XL.md`. |
|
||||
| `BI` | bcctrx: read | CR bit index (0–31) selected by BO's condition test. |
|
||||
| `CR` | bcctrx: read | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
|
||||
| `CTR` | bcctrx: read | Count register. Decremented and optionally tested by conditional branches when `BO[2]=0`. |
|
||||
| `LR` | bcctrx: write (conditional) | Link register. Written by `bl`/`bla`/`bcl`/`bclrl`/`bcctrl`; read by `bclr`/`bclrl`. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `bcctrx`
|
||||
|
||||
- **Reads (always):** `LK`, `BO`, `BI`, `CR`, `CTR`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** `LR`
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
cond_ok <- BO[0] | (CR[BI] ≡ BO[1])
|
||||
if cond_ok then NIA <- CTR[0:61] || 0b00
|
||||
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
|
||||
|
||||
**`bcctrx`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="bcctrx"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:250`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L250)
|
||||
- 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:721`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L721)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:962-981`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L962-L981)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::bcctrx => {
|
||||
let bo = instr.bo();
|
||||
let bi = instr.bi();
|
||||
|
||||
let cond_ok = (bo & 0b10000) != 0
|
||||
|| (ctx.get_cr_bit(bi) == ((bo & 0b01000) != 0));
|
||||
|
||||
if cond_ok {
|
||||
let next_pc = ctx.pc + 4;
|
||||
ctx.pc = (ctx.ctr as u32) & !3;
|
||||
if instr.lk() {
|
||||
ctx.lr = next_pc as u64;
|
||||
}
|
||||
} else {
|
||||
if instr.lk() {
|
||||
ctx.lr = (ctx.pc + 4) as u64;
|
||||
}
|
||||
ctx.pc += 4;
|
||||
}
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **No CTR decrement.** Unlike [`bcx`](bcx.md) and [`bclrx`](bclrx.md), `bcctr` cannot decrement CTR (the CTR is the *target*). The PowerISA reserves `BO[2] = 0` encodings — they are *invalid* on `bcctrx`. xenia silently ignores `BO[2]`/`BO[3]` and treats every `bcctr` as a pure CR-conditional branch, which matches both the canary emit and real Xenon hardware behaviour.
|
||||
- **CTR alignment mask.** The target is `CTR & ~3`. Like `bclr`, the low two bits are stripped — a misaligned CTR is silently rounded down rather than trapping.
|
||||
- **BO encoding (CR-only subset).** Because CTR-test bits are unused, only four `BO` patterns are meaningful:
|
||||
|
||||
| BO (binary) | Meaning |
|
||||
| --- | --- |
|
||||
| `0100z` | branch if `CR[BI]` false |
|
||||
| `0101z` | branch if `CR[BI]` true |
|
||||
| `1z1zz` | branch always (`bctr`) |
|
||||
| `0000z`/`001at`/etc. | reserved — implementation-defined |
|
||||
|
||||
- **Indirect call/dispatch idiom.** `mtctr rN; bctrl` is the canonical PPC indirect call: load function pointer into CTR, call. The xenia interpreter writes `LR ← CIA + 4` only when the branch is taken — this matches the PowerISA, but contrast with `bcx` where `LK` always writes LR (even if the branch is not taken). The C-translation reference handles this asymmetry explicitly.
|
||||
- **`bctr` for switch tables.** Compilers emit `bctr` (not `bctrl`) for jump-table dispatch, with CTR loaded from a base + (index*4) lookup. Xenia honours this by simply jumping to `CTR & ~3`.
|
||||
- **Synchronisation.** Marked `sync` in xenia's XML — context-synchronising. JIT backends must ensure prior side effects have committed before the indirect transfer.
|
||||
- **No prediction hint sensitivity.** Xenon predicts indirect branches via a separate target cache; the `BO[4]` hint is mostly cosmetic for `bcctr`.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`bclrx`](bclrx.md) — branch conditional to **LR** (function returns).
|
||||
- [`bcx`](bcx.md) — branch conditional to displacement (B-form).
|
||||
- [`bx`](bx.md) — unconditional displacement branch (I-form).
|
||||
- [`mtctr`](../control/mtspr.md), [`mfctr`](../control/mfspr.md) — load/read CTR via `mtspr 9` / `mfspr 9`.
|
||||
- [`sc`](sc.md) — alternative control-flow exit (system call).
|
||||
|
||||
### Simplified Mnemonics
|
||||
|
||||
| Simplified | Expansion |
|
||||
| --- | --- |
|
||||
| `bctr` | `bcctr BO=0b10100, BI=0` — unconditional indirect branch |
|
||||
| `bctrl` | `bcctrl BO=0b10100, BI=0` — unconditional indirect call |
|
||||
| `beqctr crN` | `bcctr BO=0b01100, BI=4·N+2` — call CTR if `crN.EQ` |
|
||||
| `bnectr crN` | `bcctr BO=0b00100, BI=4·N+2` — call CTR if `crN.NE` |
|
||||
| `bltctr crN` | `bcctr BO=0b01100, BI=4·N+0` — call CTR if `crN.LT` |
|
||||
| `bgectr crN` | `bcctr BO=0b00100, BI=4·N+0` — call CTR if `crN.GE` |
|
||||
| `bgtctr crN` | `bcctr BO=0b01100, BI=4·N+1` — call CTR if `crN.GT` |
|
||||
| `blectr crN` | `bcctr BO=0b00100, BI=4·N+1` — call CTR if `crN.LE` |
|
||||
|
||||
The unconditional `bctr`/`bctrl` are by far the most common in Xbox 360 disassembly (compiler-emitted indirect calls and switch dispatch).
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `bcctr` (Branch Conditional to Count Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-bcctr-bcctrl-branch-conditional-count-register-instruction)
|
||||
- [AIX 7.3 — Branch simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-branch-simplified)
|
||||
180
migration/project-root/ppc-manual/branch/bclrx.md
Normal file
180
migration/project-root/ppc-manual/branch/bclrx.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# `bclrx` — Branch Conditional to Link Register
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000020` · _sync_
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `bclr` | `bclrx` | — | Branch Conditional to Link Register |
|
||||
| `bclrl` | `bclrx` | LK=1 | Branch Conditional to Link Register |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
bclr[LK] [BO], [BI]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `bclrx` — form `XL`
|
||||
|
||||
- **Opcode word:** `0x4c000020`
|
||||
- **Primary opcode (bits 0–5):** `19`
|
||||
- **Extended opcode:** `16`
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `LK` | bclrx: read | Link bit. When 1, LR ← address-of-next-instruction before the branch is taken. |
|
||||
| `BO` | bclrx: read | 5-bit branch options — selects CTR decrement, CTR test polarity, and CR bit test polarity. See `forms/XL.md`. |
|
||||
| `BI` | bclrx: read | CR bit index (0–31) selected by BO's condition test. |
|
||||
| `CR` | bclrx: 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` | bclrx: read (conditional); bclrx: write (conditional) | Count register. Decremented and optionally tested by conditional branches when `BO[2]=0`. |
|
||||
| `LR` | bclrx: write (conditional) | Link register. Written by `bl`/`bla`/`bcl`/`bclrl`/`bcctrl`; read by `bclr`/`bclrl`. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `bclrx`
|
||||
|
||||
- **Reads (always):** `LK`, `BO`, `BI`
|
||||
- **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 <- LR[0:61] || 0b00
|
||||
if LK then LR <- CIA + 4
|
||||
```
|
||||
|
||||
## C Translation Example
|
||||
|
||||
```c
|
||||
/* bclr/bclrl — branch conditional to LR */
|
||||
if (!(insn.BO & 4)) ctr -= 1;
|
||||
bool ctr_ok = (insn.BO & 4) || ((ctr != 0) ^ !!(insn.BO & 2));
|
||||
bool cond_ok = (insn.BO & 16) || (cr_bit(insn.BI) == !!(insn.BO & 8));
|
||||
uint32_t next = pc + 4;
|
||||
if (ctr_ok && cond_ok) pc = lr & ~3u; else pc = next;
|
||||
if (insn.LK) lr = next;
|
||||
```
|
||||
|
||||
## Implementation References
|
||||
|
||||
**`bclrx`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="bclrx"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:282`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L282)
|
||||
- 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:711`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L711)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:939-961`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L939-L961)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::bclrx => {
|
||||
let bo = instr.bo();
|
||||
let bi = instr.bi();
|
||||
|
||||
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));
|
||||
|
||||
let next_pc = ctx.pc + 4;
|
||||
if ctr_ok && cond_ok {
|
||||
ctx.pc = (ctx.lr as u32) & !3;
|
||||
} else {
|
||||
ctx.pc = next_pc;
|
||||
}
|
||||
if instr.lk() {
|
||||
ctx.lr = next_pc as u64;
|
||||
}
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## BO Encoding (5 bits)
|
||||
|
||||
`BO` controls two independent tests and two "hints". Bit 0 is the MSB.
|
||||
|
||||
| BO (binary) | CTR decrement? | CTR test | CR test | Meaning |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `0000z` | yes | `CTR ≠ 0` | `¬CR[BI]` | decrement, branch if CTR ≠ 0 **and** CR[BI] false |
|
||||
| `0001z` | yes | `CTR = 0` | `¬CR[BI]` | decrement, branch if CTR = 0 **and** CR[BI] false |
|
||||
| `001at` | yes | `CTR ≠ 0` / `CTR = 0` | — | decrement, branch on CTR only |
|
||||
| `0100z` | no | — | `¬CR[BI]` | branch if CR[BI] false |
|
||||
| `0101z` | no | — | `CR[BI]` | branch if CR[BI] true |
|
||||
| `011at` | no | — | — | branch always (`z` and `t` are prediction hints) |
|
||||
| `1z00z` | yes | `CTR ≠ 0` | — | decrement, branch if CTR ≠ 0 |
|
||||
| `1z01z` | yes | `CTR = 0` | — | decrement, branch if CTR = 0 |
|
||||
| `1z1zz` | no | — | — | branch always |
|
||||
|
||||
Bit **`BO[0]` = 1** disables the CR test; **`BO[2]` = 1** disables the CTR decrement/test. `BO[1]` and `BO[3]` select the polarity of each test. `BO[4]` is a branch-prediction hint (0 = not taken, 1 = taken; ignored on the Xenon in most cases).
|
||||
|
||||
The most common bclr instance in Xbox 360 disassembly is `BO = 0b10100` → `blr` (branch always to LR), the function epilogue. `BO = 0b01100, BI = 2` → `beqlr` (return if `cr0.EQ`), also common.
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **LR alignment mask.** The target address is `LR & ~3` — the low 2 bits are cleared. This silently ignores a misaligned LR; incoming code should always produce 4-byte-aligned LR values.
|
||||
- **Ordering of CTR decrement and branch.** The CTR is decremented **first**, then compared to zero **after** the decrement. So after `bdnz` at `CTR = 1`, the CTR becomes `0` and the branch is not taken.
|
||||
- **Self-referential LR write.** `bclrl` writes `LR ← CIA + 4` **before** reading `LR` to set `NIA`. Per the PowerISA, `bclrl` reads the *old* `LR` for the branch target and writes the *new* `LR` with the return address, atomically from software's perspective. Xenia implements it this way (`next_pc` captured first, then `lr` written).
|
||||
- **Branch prediction hints (`BO[4]`).** The Xenon does static prediction on the basis of these hints, but behaviour is architecturally unobservable. Translators may ignore them.
|
||||
- **Synchronisation.** `bclr` is **context-synchronising** (hence the `sync` flag in xenia's XML). Translators must ensure side-effecting instructions preceding the branch have committed — trivial in a sequential C translation but relevant for JIT backends.
|
||||
- **xenia's `LR_HALT_SENTINEL`.** Xenia sets `LR` to `0xBCBCBCBC` at thread start; when the top-level guest function returns via `blr`, the interpreter loop halts cleanly. Translators replicating guest behaviour don't need this — but if you generate a test harness, the sentinel is a convenient "function returned" signal.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`bcctrx`](bcctrx.md) — branch conditional to **CTR** (used by indirect calls / vtables).
|
||||
- [`bcx`](bcx.md) — branch conditional to an immediate displacement (D-form).
|
||||
- [`bx`](bx.md) — unconditional branch (I-form).
|
||||
- [`mtlr`](../control/mtspr.md), [`mflr`](../control/mfspr.md) — set/get LR via `mtspr 8, …` / `mfspr …, 8`.
|
||||
- [`sc`](sc.md) — system call (alternative control-flow exit).
|
||||
|
||||
## Simplified Mnemonics
|
||||
|
||||
Assemblers fold common `BO`/`BI` patterns to single mnemonics:
|
||||
|
||||
| Simplified | Expansion |
|
||||
| --- | --- |
|
||||
| `blr` | `bclr BO=0b10100, BI=0` — branch always to LR |
|
||||
| `blrl` | `bclrl BO=0b10100, BI=0` — branch always to LR with link (tail-call trampoline) |
|
||||
| `beqlr crN` | `bclr BO=0b01100, BI=4·N+2` — return if `crN.EQ` |
|
||||
| `bnelr crN` | `bclr BO=0b00100, BI=4·N+2` — return if `crN.NE` |
|
||||
| `bltlr crN` | `bclr BO=0b01100, BI=4·N+0` — return if `crN.LT` |
|
||||
| `bgelr crN` | `bclr BO=0b00100, BI=4·N+0` — return if `crN.GE` |
|
||||
| `bgtlr crN` | `bclr BO=0b01100, BI=4·N+1` — return if `crN.GT` |
|
||||
| `blelr crN` | `bclr BO=0b00100, BI=4·N+1` — return if `crN.LE` |
|
||||
|
||||
Xbox 360 disassemblers almost always emit the simplified form; the translation agent should learn to recognise them.
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `bclr` (Branch Conditional to Link Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-bclr-bclrl-branch-conditional-link-register-instruction)
|
||||
- [AIX 7.3 — Branch simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-branch-simplified)
|
||||
192
migration/project-root/ppc-manual/branch/bcx.md
Normal file
192
migration/project-root/ppc-manual/branch/bcx.md
Normal 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 0–5):** `16`
|
||||
- **Extended opcode:** —
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 | `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 (0–31) 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)
|
||||
133
migration/project-root/ppc-manual/branch/bx.md
Normal file
133
migration/project-root/ppc-manual/branch/bx.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# `bx` — Branch
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [I](../forms/I.md) · **Opcode:** `0x48000000` · _sync_
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `b` | `bx` | — | Branch |
|
||||
| `bl` | `bx` | LK=1 | Branch |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
b[LK][AA] [ADDR]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `bx` — form `I`
|
||||
|
||||
- **Opcode word:** `0x48000000`
|
||||
- **Primary opcode (bits 0–5):** `18`
|
||||
- **Extended opcode:** —
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–29 | `LI` | signed 24-bit word-offset target |
|
||||
| 30 | `AA` | absolute-address flag |
|
||||
| 31 | `LK` | link flag (bl/ba/bla) |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `LK` | bx: read | Link bit. When 1, LR ← address-of-next-instruction before the branch is taken. |
|
||||
| `AA` | bx: 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. |
|
||||
| `ADDR` | bx: read | Encoded branch target displacement (24-bit for I-form, 14-bit for B-form, word-shifted). |
|
||||
| `LR` | bx: write (conditional) | Link register. Written by `bl`/`bla`/`bcl`/`bclrl`/`bcctrl`; read by `bclr`/`bclrl`. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `bx`
|
||||
|
||||
- **Reads (always):** `LK`, `AA`, `ADDR`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** `LR`
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
NIA <- (CIA + EXTS(LI || 0b00)) if AA=0
|
||||
<- EXTS(LI || 0b00) if AA=1
|
||||
if LK then LR <- CIA + 4
|
||||
```
|
||||
|
||||
## C Translation Example
|
||||
|
||||
```c
|
||||
/* b / bl / ba / bla — unconditional branch (I-form, primary 18) */
|
||||
int32_t li = (int32_t)(insn.LI << 2); /* sign-extended word-offset */
|
||||
uint32_t target = insn.AA ? (uint32_t)li : (uint32_t)(pc + li);
|
||||
uint32_t next = pc + 4;
|
||||
if (insn.LK) lr = next; /* bl / bla save return addr */
|
||||
pc = target;
|
||||
```
|
||||
|
||||
## Implementation References
|
||||
|
||||
**`bx`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="bx"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:154`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L154)
|
||||
- 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:342`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L342)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:897-907`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L897-L907)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::bx => {
|
||||
let target = if instr.aa() {
|
||||
instr.li() as u32
|
||||
} else {
|
||||
ctx.pc.wrapping_add(instr.li() as u32)
|
||||
};
|
||||
if instr.lk() {
|
||||
ctx.lr = (ctx.pc + 4) as u64;
|
||||
}
|
||||
ctx.pc = target;
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **24-bit word-aligned target.** `LI` is a 24-bit signed word-count. Hardware concatenates `LI || 0b00` (adds the implicit two low zero bits) and sign-extends to 64 bits before using it as an address. The displacement range is therefore ±32 MiB in bytes (`−2^25 … +2^25 − 4`).
|
||||
- **Four mnemonics, one opcode.** The four runtime variants selected by `AA` and `LK`:
|
||||
- `b` — `AA = 0, LK = 0` — PC-relative, no link.
|
||||
- `bl` — `AA = 0, LK = 1` — PC-relative, `LR = CIA + 4` (the ubiquitous function-call primitive).
|
||||
- `ba` — `AA = 1, LK = 0` — absolute, no link.
|
||||
- `bla` — `AA = 1, LK = 1` — absolute, link.
|
||||
Xbox 360 code almost exclusively uses `b` and `bl`; `ba` / `bla` appear only in kernel / firmware stubs.
|
||||
- **Target alignment.** `LI` is scaled by 4, so all targets are 4-byte aligned by construction. There is no low-bit encoding of ARM-style Thumb — PPC has one instruction width.
|
||||
- **LR write is *before* the branch.** In `bl`, `LR` receives `CIA + 4` (the address of the instruction *after* the branch) before execution transfers to the target. Nested calls naturally overwrite LR; callees must spill it ([`mflr`](../control/mfspr.md) + `std`) before making their own `bl`.
|
||||
- **Indirect tail calls.** A tail call to an indirect target is encoded as `mtctr` + `bctr` (see [`bcctrx`](bcctrx.md)), not `bx` — `bx` has no register-based form.
|
||||
- **No condition test.** Use [`bcx`](bcx.md) for conditional displacement branches or [`bclrx`](bclrx.md) / [`bcctrx`](bcctrx.md) for conditional LR/CTR jumps.
|
||||
- **Speculative execution.** The Xenon fetches past `bx`; translators that mask control flow must treat the target as a single-destination control transfer.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`bcx`](bcx.md) — conditional displacement branch (B-form, ±32 KiB range).
|
||||
- [`bclrx`](bclrx.md), [`bcctrx`](bcctrx.md) — branch to LR / CTR, conditional and unconditional.
|
||||
- [`mtlr`](../control/mtspr.md), [`mflr`](../control/mfspr.md) — LR save/restore for nested `bl` calls.
|
||||
- [`sc`](sc.md) — system call; an alternative control-flow exit to the kernel.
|
||||
|
||||
## Simplified Mnemonics
|
||||
|
||||
Assemblers emit `b`, `bl`, `ba`, `bla` for the four runtime combinations. There is no further simplification.
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `b` (Branch)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-b-branch-instruction)
|
||||
- [AIX 7.3 — `bl` (Branch with Link, simplified mnemonic)](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-branch-simplified)
|
||||
129
migration/project-root/ppc-manual/branch/sc.md
Normal file
129
migration/project-root/ppc-manual/branch/sc.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# `sc` — System Call
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [SC](../forms/SC.md) · **Opcode:** `0x44000002` · _sync_
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `sc` | `sc` | — | System Call |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
sc [LEV]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `sc` — form `SC`
|
||||
|
||||
- **Opcode word:** `0x44000002`
|
||||
- **Primary opcode (bits 0–5):** `17`
|
||||
- **Extended opcode:** —
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (17) |
|
||||
| 6–19 | `—` | reserved |
|
||||
| 20–26 | `LEV` | exception level |
|
||||
| 27–29 | `—` | reserved |
|
||||
| 30 | `1` | fixed 1 |
|
||||
| 31 | `—` | reserved |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `LEV` | sc: read | System-call exception level (for `sc`). |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `sc`
|
||||
|
||||
- **Reads (always):** `LEV`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** _none_
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
system_call_exception(LEV)
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
**`sc`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="sc"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:455`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L455)
|
||||
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:63`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L63)
|
||||
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:341`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L341)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:984-997`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L984-L997)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::sc => {
|
||||
// PPCBUG-064: log non-zero LEV (`sc 2` is the Xbox 360 hypervisor-call
|
||||
// convention; canary dispatches it to a different handler than `sc 0`).
|
||||
// Routing LEV=2 requires a StepResult variant extension; deferred.
|
||||
let lev = (instr.raw >> 5) & 0x7F;
|
||||
if lev != 0 {
|
||||
tracing::warn!(
|
||||
"sc with LEV={} at {:#010x}: dispatched as plain SystemCall (HVcall routing not implemented)",
|
||||
lev, ctx.pc
|
||||
);
|
||||
}
|
||||
ctx.pc += 4;
|
||||
return StepResult::SystemCall;
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **`LEV` field — kernel vs hypervisor.** The 7-bit `LEV` operand selects the privilege level of the syscall:
|
||||
- `LEV = 0` — supervisor (kernel) syscall. Standard application → kernel transition; targets the `0xC00` system-call vector.
|
||||
- `LEV = 1` — reserved.
|
||||
- `LEV = 2` — **hypervisor syscall** (`HVcall`). On the Xenon, `sc 2` traps to the Xbox 360 hypervisor; this is how the kernel itself talks to the supervisor below it (e.g., for security operations, encrypted-memory accesses, page table updates).
|
||||
- **`sc` as written by titles.** Almost all guest game code uses `LEV = 0` to call `XboxKrnl.exe`. Game disassembly will show large jump tables of small thunks each ending in `li r0, syscall_no; sc; blr`.
|
||||
- **No condition or status side effects.** `sc` updates *no* general-purpose register on entry — neither LR nor CR. The kernel sees the GPR/FPR snapshot as-is and reads the syscall number out of `r0` (Xbox 360 ABI convention, not architectural).
|
||||
- **Return path.** Hardware returns from `sc` via [`rfid`](../control/mtmsrd.md)-class instructions in the kernel handler; from the application's perspective execution resumes at `CIA + 4`. Xenia's interpreter realises this by simply pre-incrementing `pc` then returning `StepResult::SystemCall` — the host driver dispatches the syscall and re-enters the loop.
|
||||
- **xenia divergence vs hardware.** xenia-rs *does not* model the `0xC00` exception vector or save SRR0/SRR1; the `LEV` operand is currently ignored. All `sc` instructions are treated identically and serviced by the host. This is sufficient because Xbox 360 titles don't observe SRR registers and the host kernel is implemented natively.
|
||||
- **Synchronisation.** Marked `sync` in xenia's XML — `sc` is context-synchronising (hardware completes all prior instructions before raising the exception). JITs must flush pending state before emitting the host call.
|
||||
- **Reserved bits.** Bit 30 is fixed `1`; bits 6–19 and 27–29 are reserved (must be 0). The 1-bit field at position 30 distinguishes the `sc` encoding from `scv` (later PowerISA addition, not present on the Xenon).
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`bx`](bx.md), [`bcx`](bcx.md), [`bclrx`](bclrx.md), [`bcctrx`](bcctrx.md) — ordinary control flow alternatives.
|
||||
- [`tw`](tw.md), [`twi`](twi.md), [`td`](td.md), [`tdi`](tdi.md) — synchronous *trap* exceptions; another way to enter the kernel.
|
||||
- [`mtmsr`](../control/mtmsr.md), [`mtmsrd`](../control/mtmsrd.md) — machine-state changes used by the kernel's `sc` handler on return (`rfid`/`hrfid` chain not separately documented in this manual).
|
||||
- [`isync`](../control/mtmsr.md) — context-synchronising sibling; `sc` itself implies an isync-like fence.
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `sc` (System Call)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-sc-system-call-instruction)
|
||||
- PowerISA v2.07B, Book III §7 — System Linkage interrupt definitions and `LEV` field semantics.
|
||||
184
migration/project-root/ppc-manual/branch/td.md
Normal file
184
migration/project-root/ppc-manual/branch/td.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# `td` — Trap Doubleword
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c000088`
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `td` | `td` | — | Trap Doubleword |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
td [TO], [RA], [RB]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `td` — form `X`
|
||||
|
||||
- **Opcode word:** `0x7c000088`
|
||||
- **Primary opcode (bits 0–5):** `31`
|
||||
- **Extended opcode:** `68`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `TO` | td: read | Trap-on condition mask (5 bits) — LT, GT, EQ, LGT, LLT bits. |
|
||||
| `RA` | td: read | Source GPR (`r0`–`r31`). |
|
||||
| `RB` | td: read | Source GPR. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `td`
|
||||
|
||||
- **Reads (always):** `TO`, `RA`, `RB`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** _none_
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
; Pseudocode derives directly from the xenia-rs interpreter
|
||||
; arm (see Implementation References). Operation semantics:
|
||||
; - Read source operands from the fields listed under Operands.
|
||||
; - Apply the arithmetic / logical / memory action described
|
||||
; in the Description field above.
|
||||
; - Write results to the destination register(s); update any
|
||||
; status bits enumerated under Status-Register Effects.
|
||||
; Consult the IBM AIX reference link under IBM Reference for
|
||||
; canonical PPC-style pseudocode where xenia's expression is
|
||||
; terse.
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
**`td`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="td"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:552`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L552)
|
||||
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:87`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L87)
|
||||
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:769`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L769)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1762-1796`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1762-L1796)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::tw | PpcOpcode::twi | PpcOpcode::td | PpcOpcode::tdi => {
|
||||
// PPCBUG-063: save CIA before incrementing so a trap handler reads
|
||||
// the faulting instruction address, not CIA+4.
|
||||
// PPCBUG-065: log the SIMM type code on `twi 31, r0, IMM` (Xbox 360
|
||||
// typed-trap convention used by the CRT/kernel for C++ exception
|
||||
// class dispatch). The audit notes this is relevant to the Sylpheed
|
||||
// throw investigation; routing the type code via a payload requires
|
||||
// a StepResult enum extension that's deferred for now.
|
||||
let trap_pc = ctx.pc;
|
||||
let a = ctx.gpr[instr.ra()];
|
||||
let b = match instr.opcode {
|
||||
PpcOpcode::twi | PpcOpcode::tdi => instr.simm16() as i64 as u64,
|
||||
_ => ctx.gpr[instr.rb()],
|
||||
};
|
||||
let width = match instr.opcode {
|
||||
PpcOpcode::tw | PpcOpcode::twi => trap::TrapWidth::Word,
|
||||
_ => trap::TrapWidth::Doubleword,
|
||||
};
|
||||
let fired = trap::evaluate(instr.to(), a, b, width);
|
||||
if fired {
|
||||
let typed_trap_simm = if matches!(instr.opcode, PpcOpcode::twi)
|
||||
&& instr.to() == 31 && instr.ra() == 0 {
|
||||
Some(instr.simm16() as u16)
|
||||
} else { None };
|
||||
tracing::warn!(
|
||||
"Trap fired at {:#010x}: {:?} TO={} a={:#x} b={:#x}{}",
|
||||
trap_pc, instr.opcode, instr.to(), a, b,
|
||||
typed_trap_simm.map_or(String::new(), |t| format!(" typed_trap_simm={:#06x}", t))
|
||||
);
|
||||
// Leave ctx.pc at CIA (NOT NIA) so trap handlers / SEH delivery
|
||||
// can read the faulting instruction address from ctx.pc.
|
||||
return StepResult::Trap;
|
||||
}
|
||||
ctx.pc += 4;
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **`TO` mask encoding (5 bits, MSB-first).** Each bit selects one comparison; the trap fires if *any* selected condition is true. Both operands are treated as 64-bit doublewords:
|
||||
|
||||
| Bit | Mnemonic | Triggered when |
|
||||
| --- | --- | --- |
|
||||
| `TO[0]` (16) | LT | `(int64) RA < (int64) RB` |
|
||||
| `TO[1]` (8) | GT | `(int64) RA > (int64) RB` |
|
||||
| `TO[2]` (4) | EQ | `RA == RB` |
|
||||
| `TO[3]` (2) | LGT | `(uint64) RA < (uint64) RB` (logical less) |
|
||||
| `TO[4]` (1) | LLT | `(uint64) RA > (uint64) RB` (logical greater — historical naming) |
|
||||
|
||||
- **`TO = 31` is unconditional trap.** All five bits set ⇒ the trap fires regardless of operand values; the simplified mnemonic `trap` is `tw 31, 0, 0` for words and **`td 31, 0, 0`** for doublewords. The PowerISA also uses `tdi 31, 0, 0` (or `twi`) as a debugger break.
|
||||
- **64-bit comparison.** Unlike [`tw`](tw.md), `td` always compares the full 64-bit GPRs. On the Xenon (64-bit) this is meaningful; PPC32 implementations don't have `td`.
|
||||
- **No register effects.** Only the side effect is the trap. No CR/LR/CTR/XER updates.
|
||||
- **Hardware behaviour.** When the trap fires, hardware raises a Program interrupt with `SRR1[TRAP]` set and vectors to `0x700`. The Xbox 360 hypervisor / kernel handles it (assertion failure, debugger trap, etc.).
|
||||
- **xenia simplification.** xenia-rs collapses all four trap variants (`td`, `tdi`, `tw`, `twi`) into one match arm that *unconditionally* logs and returns `StepResult::Trap` — it does **not** evaluate `TO` against the operands. This is a material divergence from the spec: in xenia every trap fires even if the condition is false. Real Xenon code rarely uses non-trivial `TO` masks (typical use is the unconditional `trap` for `__assert` / debugger break), so the divergence is normally invisible.
|
||||
- **Distinguishing assert vs. break.** Compilers commonly emit `tdne r3, r3` (impossible) or `tdi 0, r0, 0` patterns that *cannot* trap as inert markers. Xenia's blanket trap would mis-fire on these — a small known bug; track it if you see spurious traps.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`tdi`](tdi.md) — same condition test against a 16-bit signed immediate (D-form).
|
||||
- [`tw`](tw.md) / [`twi`](twi.md) — 32-bit (word) variants for comparing low halves of GPRs.
|
||||
- [`sc`](sc.md) — synchronous kernel entry via system-call exception (different vector, different intent).
|
||||
- [`mtmsr`](../control/mtmsr.md) — kernel returns from the trap handler via `rfid`-family instructions.
|
||||
|
||||
### Simplified Mnemonics
|
||||
|
||||
| Simplified | Expansion | Triggered when |
|
||||
| --- | --- | --- |
|
||||
| `td RA, RB` (=`tdu`) | `td 31, RA, RB` | unconditional trap |
|
||||
| `tdeq RA, RB` | `td 4, RA, RB` | `RA == RB` |
|
||||
| `tdne RA, RB` | `td 24, RA, RB` | `RA != RB` |
|
||||
| `tdlt RA, RB` | `td 16, RA, RB` | signed less than |
|
||||
| `tdle RA, RB` | `td 20, RA, RB` | signed less or equal |
|
||||
| `tdgt RA, RB` | `td 8, RA, RB` | signed greater than |
|
||||
| `tdge RA, RB` | `td 12, RA, RB` | signed greater or equal |
|
||||
| `tdllt RA, RB` | `td 2, RA, RB` | unsigned less than |
|
||||
| `tdlge RA, RB` | `td 5, RA, RB` | unsigned greater or equal |
|
||||
| `tdlgt RA, RB` | `td 1, RA, RB` | unsigned greater than |
|
||||
| `tdlle RA, RB` | `td 6, RA, RB` | unsigned less or equal |
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `td` (Trap Doubleword)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-td-trap-doubleword-instruction)
|
||||
- [AIX 7.3 — Trap simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-trap-simplified)
|
||||
- PowerISA v2.07B, Book I §3.3.11 — fixed-point trap instructions (`TO` semantics).
|
||||
173
migration/project-root/ppc-manual/branch/tdi.md
Normal file
173
migration/project-root/ppc-manual/branch/tdi.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# `tdi` — Trap Doubleword Immediate
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [D](../forms/D.md) · **Opcode:** `0x08000000`
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `tdi` | `tdi` | — | Trap Doubleword Immediate |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
tdi [TO], [RA], [SIMM]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `tdi` — form `D`
|
||||
|
||||
- **Opcode word:** `0x08000000`
|
||||
- **Primary opcode (bits 0–5):** `2`
|
||||
- **Extended opcode:** —
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `TO` | tdi: read | Trap-on condition mask (5 bits) — LT, GT, EQ, LGT, LLT bits. |
|
||||
| `RA` | tdi: read | Source GPR (`r0`–`r31`). |
|
||||
| `SIMM` | tdi: read | 16-bit signed immediate. Sign-extended to 64 bits before use. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `tdi`
|
||||
|
||||
- **Reads (always):** `TO`, `RA`, `SIMM`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** _none_
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
; Pseudocode derives directly from the xenia-rs interpreter
|
||||
; arm (see Implementation References). Operation semantics:
|
||||
; - Read source operands from the fields listed under Operands.
|
||||
; - Apply the arithmetic / logical / memory action described
|
||||
; in the Description field above.
|
||||
; - Write results to the destination register(s); update any
|
||||
; status bits enumerated under Status-Register Effects.
|
||||
; Consult the IBM AIX reference link under IBM Reference for
|
||||
; canonical PPC-style pseudocode where xenia's expression is
|
||||
; terse.
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
**`tdi`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="tdi"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:568`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L568)
|
||||
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:87`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L87)
|
||||
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:327`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L327)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1762-1796`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1762-L1796)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::tw | PpcOpcode::twi | PpcOpcode::td | PpcOpcode::tdi => {
|
||||
// PPCBUG-063: save CIA before incrementing so a trap handler reads
|
||||
// the faulting instruction address, not CIA+4.
|
||||
// PPCBUG-065: log the SIMM type code on `twi 31, r0, IMM` (Xbox 360
|
||||
// typed-trap convention used by the CRT/kernel for C++ exception
|
||||
// class dispatch). The audit notes this is relevant to the Sylpheed
|
||||
// throw investigation; routing the type code via a payload requires
|
||||
// a StepResult enum extension that's deferred for now.
|
||||
let trap_pc = ctx.pc;
|
||||
let a = ctx.gpr[instr.ra()];
|
||||
let b = match instr.opcode {
|
||||
PpcOpcode::twi | PpcOpcode::tdi => instr.simm16() as i64 as u64,
|
||||
_ => ctx.gpr[instr.rb()],
|
||||
};
|
||||
let width = match instr.opcode {
|
||||
PpcOpcode::tw | PpcOpcode::twi => trap::TrapWidth::Word,
|
||||
_ => trap::TrapWidth::Doubleword,
|
||||
};
|
||||
let fired = trap::evaluate(instr.to(), a, b, width);
|
||||
if fired {
|
||||
let typed_trap_simm = if matches!(instr.opcode, PpcOpcode::twi)
|
||||
&& instr.to() == 31 && instr.ra() == 0 {
|
||||
Some(instr.simm16() as u16)
|
||||
} else { None };
|
||||
tracing::warn!(
|
||||
"Trap fired at {:#010x}: {:?} TO={} a={:#x} b={:#x}{}",
|
||||
trap_pc, instr.opcode, instr.to(), a, b,
|
||||
typed_trap_simm.map_or(String::new(), |t| format!(" typed_trap_simm={:#06x}", t))
|
||||
);
|
||||
// Leave ctx.pc at CIA (NOT NIA) so trap handlers / SEH delivery
|
||||
// can read the faulting instruction address from ctx.pc.
|
||||
return StepResult::Trap;
|
||||
}
|
||||
ctx.pc += 4;
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **Immediate is sign-extended.** `SIMM` is treated as a 16-bit signed value, then sign-extended to 64 bits before comparison. To trap against a small unsigned constant, the same encoding works because both signed and unsigned interpretations agree for `SIMM ∈ [0, 0x7FFF]`.
|
||||
- **`TO` mask.** Identical bit layout to [`td`](td.md): bit 0 = signed LT, 1 = signed GT, 2 = EQ, 3 = unsigned LT (LGT), 4 = unsigned GT (LLT). Trap fires if any selected bit's condition is true.
|
||||
- **`TO = 31` is unconditional.** `tdi 31, 0, 0` is a debugger / assert trap. Compilers sometimes use it as a "should not reach" marker.
|
||||
- **64-bit comparison only.** Unlike [`twi`](twi.md), `tdi` always compares the full 64-bit GPR — it has no PPC32 analogue. The Xenon's PPC64 mode makes this meaningful.
|
||||
- **No register effects.** Pure side effect on success: Program interrupt → vector `0x700` with `SRR1[TRAP]=1`.
|
||||
- **xenia simplification.** xenia-rs unconditionally treats `tdi` as a fired trap, regardless of `TO`/`RA`/`SIMM` values. This diverges from the spec — real hardware would silently fall through when no `TO` bit's condition holds. Most title code uses only the unconditional `trap` form, so the divergence is normally invisible; non-firing assertion patterns (e.g. `tdi 0, r0, 0`) will mis-fire under xenia.
|
||||
- **Reserved bits.** Bits 6–10 carry the `TO` field; there is no `Rc` / `OE` on D-form trap immediates.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`td`](td.md) — register-register doubleword trap (X-form).
|
||||
- [`twi`](twi.md) / [`tw`](tw.md) — 32-bit-comparison siblings.
|
||||
- [`sc`](sc.md) — kernel-entry counterpart via system call exception.
|
||||
- [`mtmsrd`](mtmsrd.md) (control category) — kernel `rfid`-style return path after handling.
|
||||
|
||||
### Simplified Mnemonics
|
||||
|
||||
| Simplified | Expansion | Triggered when |
|
||||
| --- | --- | --- |
|
||||
| `tdi RA, value` | `tdi 31, RA, value` | unconditional trap |
|
||||
| `tdeqi RA, value` | `tdi 4, RA, value` | `RA == EXTS(value)` |
|
||||
| `tdnei RA, value` | `tdi 24, RA, value` | `RA != EXTS(value)` |
|
||||
| `tdlti RA, value` | `tdi 16, RA, value` | signed less than |
|
||||
| `tdlei RA, value` | `tdi 20, RA, value` | signed less or equal |
|
||||
| `tdgti RA, value` | `tdi 8, RA, value` | signed greater than |
|
||||
| `tdgei RA, value` | `tdi 12, RA, value` | signed greater or equal |
|
||||
| `tdllti RA, value` | `tdi 2, RA, value` | unsigned less than |
|
||||
| `tdlgei RA, value` | `tdi 5, RA, value` | unsigned greater or equal |
|
||||
| `tdlgti RA, value` | `tdi 1, RA, value` | unsigned greater than |
|
||||
| `tdllei RA, value` | `tdi 6, RA, value` | unsigned less or equal |
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `tdi` (Trap Doubleword Immediate)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-tdi-trap-doubleword-immediate-instruction)
|
||||
- [AIX 7.3 — Trap simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-trap-simplified)
|
||||
- PowerISA v2.07B, Book I §3.3.11 — fixed-point trap instructions.
|
||||
184
migration/project-root/ppc-manual/branch/tw.md
Normal file
184
migration/project-root/ppc-manual/branch/tw.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# `tw` — Trap Word
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c000008`
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `tw` | `tw` | — | Trap Word |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
tw [TO], [RA], [RB]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `tw` — form `X`
|
||||
|
||||
- **Opcode word:** `0x7c000008`
|
||||
- **Primary opcode (bits 0–5):** `31`
|
||||
- **Extended opcode:** `4`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `TO` | tw: read | Trap-on condition mask (5 bits) — LT, GT, EQ, LGT, LLT bits. |
|
||||
| `RA` | tw: read | Source GPR (`r0`–`r31`). |
|
||||
| `RB` | tw: read | Source GPR. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `tw`
|
||||
|
||||
- **Reads (always):** `TO`, `RA`, `RB`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** _none_
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
; Pseudocode derives directly from the xenia-rs interpreter
|
||||
; arm (see Implementation References). Operation semantics:
|
||||
; - Read source operands from the fields listed under Operands.
|
||||
; - Apply the arithmetic / logical / memory action described
|
||||
; in the Description field above.
|
||||
; - Write results to the destination register(s); update any
|
||||
; status bits enumerated under Status-Register Effects.
|
||||
; Consult the IBM AIX reference link under IBM Reference for
|
||||
; canonical PPC-style pseudocode where xenia's expression is
|
||||
; terse.
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
**`tw`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="tw"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:583`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L583)
|
||||
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:87`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L87)
|
||||
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:750`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L750)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1762-1796`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1762-L1796)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::tw | PpcOpcode::twi | PpcOpcode::td | PpcOpcode::tdi => {
|
||||
// PPCBUG-063: save CIA before incrementing so a trap handler reads
|
||||
// the faulting instruction address, not CIA+4.
|
||||
// PPCBUG-065: log the SIMM type code on `twi 31, r0, IMM` (Xbox 360
|
||||
// typed-trap convention used by the CRT/kernel for C++ exception
|
||||
// class dispatch). The audit notes this is relevant to the Sylpheed
|
||||
// throw investigation; routing the type code via a payload requires
|
||||
// a StepResult enum extension that's deferred for now.
|
||||
let trap_pc = ctx.pc;
|
||||
let a = ctx.gpr[instr.ra()];
|
||||
let b = match instr.opcode {
|
||||
PpcOpcode::twi | PpcOpcode::tdi => instr.simm16() as i64 as u64,
|
||||
_ => ctx.gpr[instr.rb()],
|
||||
};
|
||||
let width = match instr.opcode {
|
||||
PpcOpcode::tw | PpcOpcode::twi => trap::TrapWidth::Word,
|
||||
_ => trap::TrapWidth::Doubleword,
|
||||
};
|
||||
let fired = trap::evaluate(instr.to(), a, b, width);
|
||||
if fired {
|
||||
let typed_trap_simm = if matches!(instr.opcode, PpcOpcode::twi)
|
||||
&& instr.to() == 31 && instr.ra() == 0 {
|
||||
Some(instr.simm16() as u16)
|
||||
} else { None };
|
||||
tracing::warn!(
|
||||
"Trap fired at {:#010x}: {:?} TO={} a={:#x} b={:#x}{}",
|
||||
trap_pc, instr.opcode, instr.to(), a, b,
|
||||
typed_trap_simm.map_or(String::new(), |t| format!(" typed_trap_simm={:#06x}", t))
|
||||
);
|
||||
// Leave ctx.pc at CIA (NOT NIA) so trap handlers / SEH delivery
|
||||
// can read the faulting instruction address from ctx.pc.
|
||||
return StepResult::Trap;
|
||||
}
|
||||
ctx.pc += 4;
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **32-bit comparison only.** `tw` compares the *low 32 bits* of `RA` and `RB`. The high halves of the 64-bit GPRs on the Xenon are ignored. Use [`td`](td.md) for full 64-bit comparisons.
|
||||
- **`TO` mask (5 bits, MSB-first).** Same encoding as the doubleword form:
|
||||
|
||||
| Bit | Mnemonic | Triggered when |
|
||||
| --- | --- | --- |
|
||||
| `TO[0]` (16) | LT | `(int32) RA < (int32) RB` |
|
||||
| `TO[1]` (8) | GT | `(int32) RA > (int32) RB` |
|
||||
| `TO[2]` (4) | EQ | `(uint32) RA == (uint32) RB` |
|
||||
| `TO[3]` (2) | LGT | `(uint32) RA < (uint32) RB` |
|
||||
| `TO[4]` (1) | LLT | `(uint32) RA > (uint32) RB` |
|
||||
|
||||
- **`tw 31, 0, 0` is `trap`.** The simplified mnemonic `trap` expands to `tw 31, r0, r0` — all five `TO` bits set ⇒ unconditional trap. Compilers and the kernel use this as the assertion / debugger break primitive; it appears as `0x7FE00008` in raw bytes.
|
||||
- **Conditional asserts.** GCC's `__builtin_trap` and MSVC's `__assert` macros emit `tw` variants like `twge`/`twlt` to fault on bound-check failures.
|
||||
- **No register effects.** Side effect only: Program interrupt (`0x700`) with `SRR1[TRAP]=1`.
|
||||
- **xenia simplification.** xenia-rs collapses `td/tdi/tw/twi` into a single arm that *unconditionally* logs and returns `StepResult::Trap` — the `TO` operand is **not evaluated**. Real hardware would silently fall through when no `TO` bit's condition holds. In practice titles use mostly the unconditional `trap`, so the divergence rarely manifests, but inert-marker patterns like `tw 0, r0, r0` will fire under xenia.
|
||||
- **Inert encoding.** `tw 0, r0, r0` (no `TO` bits set) can never trap on real hardware. It encodes as `0x7C000008` — sometimes used as a structured-NOP marker. Watch for it in xenia traces.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`twi`](twi.md) — same 32-bit comparison against a 16-bit signed immediate.
|
||||
- [`td`](td.md) / [`tdi`](tdi.md) — 64-bit (doubleword) variants.
|
||||
- [`sc`](sc.md) — kernel entry via system-call exception (different vector).
|
||||
- [`mtmsr`](../control/mtmsr.md) — kernel returns from `0x700` via `rfid`.
|
||||
|
||||
### Simplified Mnemonics
|
||||
|
||||
| Simplified | Expansion | Triggered when |
|
||||
| --- | --- | --- |
|
||||
| `trap` | `tw 31, 0, 0` | unconditional |
|
||||
| `tweq RA, RB` | `tw 4, RA, RB` | `RA == RB` |
|
||||
| `twne RA, RB` | `tw 24, RA, RB` | `RA != RB` |
|
||||
| `twlt RA, RB` | `tw 16, RA, RB` | signed less than |
|
||||
| `twle RA, RB` | `tw 20, RA, RB` | signed less or equal |
|
||||
| `twgt RA, RB` | `tw 8, RA, RB` | signed greater than |
|
||||
| `twge RA, RB` | `tw 12, RA, RB` | signed greater or equal |
|
||||
| `twllt RA, RB` | `tw 2, RA, RB` | unsigned less than |
|
||||
| `twlge RA, RB` | `tw 5, RA, RB` | unsigned greater or equal |
|
||||
| `twlgt RA, RB` | `tw 1, RA, RB` | unsigned greater than |
|
||||
| `twlle RA, RB` | `tw 6, RA, RB` | unsigned less or equal |
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `tw` (Trap Word)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-tw-trap-word-instruction)
|
||||
- [AIX 7.3 — Trap simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-trap-simplified)
|
||||
- PowerISA v2.07B, Book I §3.3.11 — fixed-point trap instructions.
|
||||
172
migration/project-root/ppc-manual/branch/twi.md
Normal file
172
migration/project-root/ppc-manual/branch/twi.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# `twi` — Trap Word Immediate
|
||||
|
||||
> **Category:** [Branch & System](../categories/branch.md) · **Form:** [D](../forms/D.md) · **Opcode:** `0x0c000000`
|
||||
|
||||
<!-- GENERATED: BEGIN -->
|
||||
|
||||
## Assembler Mnemonics
|
||||
|
||||
| Mnemonic | XML entry | Flags | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `twi` | `twi` | — | Trap Word Immediate |
|
||||
|
||||
## Syntax
|
||||
|
||||
```asm
|
||||
tw [TO], [RA], [SIMM]
|
||||
```
|
||||
|
||||
## Encoding
|
||||
|
||||
### `twi` — form `D`
|
||||
|
||||
- **Opcode word:** `0x0c000000`
|
||||
- **Primary opcode (bits 0–5):** `3`
|
||||
- **Extended opcode:** —
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 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 |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `TO` | twi: read | Trap-on condition mask (5 bits) — LT, GT, EQ, LGT, LLT bits. |
|
||||
| `RA` | twi: read | Source GPR (`r0`–`r31`). |
|
||||
| `SIMM` | twi: read | 16-bit signed immediate. Sign-extended to 64 bits before use. |
|
||||
|
||||
## Register Effects
|
||||
|
||||
### `twi`
|
||||
|
||||
- **Reads (always):** `TO`, `RA`, `SIMM`
|
||||
- **Reads (conditional):** _none_
|
||||
- **Writes (always):** _none_
|
||||
- **Writes (conditional):** _none_
|
||||
|
||||
## Status-Register Effects
|
||||
|
||||
_No condition-register or status-register effects._
|
||||
|
||||
## Operation (pseudocode)
|
||||
|
||||
```
|
||||
; Pseudocode derives directly from the xenia-rs interpreter
|
||||
; arm (see Implementation References). Operation semantics:
|
||||
; - Read source operands from the fields listed under Operands.
|
||||
; - Apply the arithmetic / logical / memory action described
|
||||
; in the Description field above.
|
||||
; - Write results to the destination register(s); update any
|
||||
; status bits enumerated under Status-Register Effects.
|
||||
; Consult the IBM AIX reference link under IBM Reference for
|
||||
; canonical PPC-style pseudocode where xenia's expression is
|
||||
; terse.
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
**`twi`**
|
||||
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="twi"`](../../xenia-canary/tools/ppc-instructions.xml)
|
||||
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:601`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L601)
|
||||
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:87`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L87)
|
||||
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:328`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L328)
|
||||
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1762-1796`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1762-L1796)
|
||||
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
|
||||
|
||||
```rust
|
||||
PpcOpcode::tw | PpcOpcode::twi | PpcOpcode::td | PpcOpcode::tdi => {
|
||||
// PPCBUG-063: save CIA before incrementing so a trap handler reads
|
||||
// the faulting instruction address, not CIA+4.
|
||||
// PPCBUG-065: log the SIMM type code on `twi 31, r0, IMM` (Xbox 360
|
||||
// typed-trap convention used by the CRT/kernel for C++ exception
|
||||
// class dispatch). The audit notes this is relevant to the Sylpheed
|
||||
// throw investigation; routing the type code via a payload requires
|
||||
// a StepResult enum extension that's deferred for now.
|
||||
let trap_pc = ctx.pc;
|
||||
let a = ctx.gpr[instr.ra()];
|
||||
let b = match instr.opcode {
|
||||
PpcOpcode::twi | PpcOpcode::tdi => instr.simm16() as i64 as u64,
|
||||
_ => ctx.gpr[instr.rb()],
|
||||
};
|
||||
let width = match instr.opcode {
|
||||
PpcOpcode::tw | PpcOpcode::twi => trap::TrapWidth::Word,
|
||||
_ => trap::TrapWidth::Doubleword,
|
||||
};
|
||||
let fired = trap::evaluate(instr.to(), a, b, width);
|
||||
if fired {
|
||||
let typed_trap_simm = if matches!(instr.opcode, PpcOpcode::twi)
|
||||
&& instr.to() == 31 && instr.ra() == 0 {
|
||||
Some(instr.simm16() as u16)
|
||||
} else { None };
|
||||
tracing::warn!(
|
||||
"Trap fired at {:#010x}: {:?} TO={} a={:#x} b={:#x}{}",
|
||||
trap_pc, instr.opcode, instr.to(), a, b,
|
||||
typed_trap_simm.map_or(String::new(), |t| format!(" typed_trap_simm={:#06x}", t))
|
||||
);
|
||||
// Leave ctx.pc at CIA (NOT NIA) so trap handlers / SEH delivery
|
||||
// can read the faulting instruction address from ctx.pc.
|
||||
return StepResult::Trap;
|
||||
}
|
||||
ctx.pc += 4;
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
<!-- GENERATED: END -->
|
||||
|
||||
## Special Cases & Edge Conditions
|
||||
|
||||
- **32-bit comparison against sign-extended immediate.** `SIMM` is a 16-bit signed value, sign-extended to 32 bits, then compared against the low 32 bits of `RA`. The high half of `RA` is *ignored*.
|
||||
- **`TO` mask.** Identical to [`tw`](tw.md): bit 0 = signed LT, 1 = signed GT, 2 = EQ, 3 = unsigned LT (LGT), 4 = unsigned GT (LLT). Trap fires if any selected bit's condition is true.
|
||||
- **`twi 31, 0, 0` is unconditional trap.** All `TO` bits set ⇒ guaranteed trap. The simplified mnemonic family (`twnei`, `twgei`, …) is much more common in real code: bound checks, null checks, integer-divide-by-zero pre-checks.
|
||||
- **Compiler usage.** Xbox 360 GCC emits `twnei rN, -1` and similar to validate handle-style return values; the kernel handler turns the trap into an exception delivered to the title.
|
||||
- **No register effects.** Side effect: Program interrupt → vector `0x700` with `SRR1[TRAP]=1`.
|
||||
- **xenia simplification.** Same as the other three trap forms — xenia-rs unconditionally returns `StepResult::Trap` whenever it decodes any of `tdi`/`twi`/`td`/`tw`, regardless of the `TO` mask or operands. This means `twi 0, r0, 0` (architecturally a guaranteed-no-trap encoding) will spuriously fire under xenia. Keep this in mind when triaging unexpected trap signals.
|
||||
- **No `Rc` / `OE`.** D-form trap immediates have neither.
|
||||
|
||||
## Related Instructions
|
||||
|
||||
- [`tw`](tw.md) — register-register 32-bit trap (X-form).
|
||||
- [`tdi`](tdi.md) / [`td`](td.md) — 64-bit (doubleword) siblings.
|
||||
- [`sc`](sc.md) — alternative synchronous kernel entry.
|
||||
- [`cmpi`](../alu/cmpi.md), [`cmpli`](../alu/cmpli.md) — set CR for a subsequent [`bcx`](bcx.md) when you want a regular branch instead of a trap.
|
||||
|
||||
### Simplified Mnemonics
|
||||
|
||||
| Simplified | Expansion | Triggered when |
|
||||
| --- | --- | --- |
|
||||
| `tweqi RA, value` | `twi 4, RA, value` | `RA == EXTS(value)` |
|
||||
| `twnei RA, value` | `twi 24, RA, value` | `RA != EXTS(value)` |
|
||||
| `twlti RA, value` | `twi 16, RA, value` | signed less than |
|
||||
| `twlei RA, value` | `twi 20, RA, value` | signed less or equal |
|
||||
| `twgti RA, value` | `twi 8, RA, value` | signed greater than |
|
||||
| `twgei RA, value` | `twi 12, RA, value` | signed greater or equal |
|
||||
| `twllti RA, value` | `twi 2, RA, value` | unsigned less than |
|
||||
| `twlgei RA, value` | `twi 5, RA, value` | unsigned greater or equal |
|
||||
| `twlgti RA, value` | `twi 1, RA, value` | unsigned greater than |
|
||||
| `twllei RA, value` | `twi 6, RA, value` | unsigned less or equal |
|
||||
|
||||
## IBM Reference
|
||||
|
||||
- [AIX 7.3 — `twi` (Trap Word Immediate)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-twi-trap-word-immediate-instruction)
|
||||
- [AIX 7.3 — Trap simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-trap-simplified)
|
||||
- PowerISA v2.07B, Book I §3.3.11 — fixed-point trap instructions.
|
||||
Reference in New Issue
Block a user