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,127 @@
# `crand` — Condition Register AND
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000202`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `crand` | `crand` | — | Condition Register AND |
## Syntax
```asm
crand [CRBD], [CRBA], [CRBB]
```
## Encoding
### `crand` — form `XL`
- **Opcode word:** `0x4c000202`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `257`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | crand: read | CR source bit A (031). |
| `CRBB` | crand: read | CR source bit B (031). |
| `CRBD` | crand: write | CR destination bit (031). |
## Register Effects
### `crand`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`crand`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="crand"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:352`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L352)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:717`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L717)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Bit-level granularity.** All eight CR-logical instructions operate on **single CR bits**, not whole 4-bit fields. `CRBD`, `CRBA`, `CRBB` are 5-bit absolute indices into the 32-bit CR register: `BI = 4·field + bit-within-field`, where bit 0 = LT, 1 = GT, 2 = EQ, 3 = SO.
- **Operation.** `CR[CRBD] ← CR[CRBA] AND CR[CRBB]`. All other CR bits are preserved.
- **Same-source / same-destination quirks.** Identical sources and destinations are legal: `crand 6, 6, 6` is a NOP-style "force CR bit 6 to itself"; `crand bt, bt, bt` reads-then-writes the same bit (no observable change). Compilers exploit `crxor BT,BT,BT` ("clear bit") and `creqv BT,BT,BT` ("set bit") for similar tricks — see those pages.
- **Combining branch conditions.** The classic use: synthesise complex branch conditions from multiple compare results. Example: `cmpw cr0, r3, r4; cmpw cr1, r5, r6; crand 4*cr0+2, 4*cr0+2, 4*cr1+2; beq cr0, label` branches if `r3==r4 AND r5==r6` using a single conditional branch.
- **No `Rc` / `OE`.** XL-form CR-logical ops never set CR0 or XER; they only update the named CR bit.
- **Not synchronising.** Pure data-flow on CR; freely reorderable.
- **xenia status.** xenia-rs decodes `crand` (decoder slot 540) but the interpreter snapshot is not embedded on this page — implementation lives in [`crates/xenia-cpu/src/interpreter.rs`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs). xenia-canary's `InstrEmit_crand` emits the equivalent host AND of the two CR bits.
## Related Instructions
- [`crandc`](crandc.md) — AND with complement: `CR[BT] ← CR[BA] AND ¬CR[BB]`.
- [`cror`](cror.md), [`crorc`](crorc.md) — OR / OR-with-complement.
- [`crnand`](crnand.md), [`crnor`](crnor.md) — negated AND / OR.
- [`crxor`](crxor.md), [`creqv`](creqv.md) — XOR and equivalence (XNOR).
- [`mcrf`](mcrf.md) — copy a whole 4-bit CR field.
- [`bcx`](../branch/bcx.md) consumers — the typical reason to compute composite CR bits.
### Simplified Mnemonics
- `crmove BT, BA``cror BT, BA, BA` (use `cror`, not `crand`).
- `crset BT``creqv BT, BT, BT` (set to 1).
- `crclr BT``crxor BT, BT, BT` (clear to 0).
`crand` itself has no dedicated simplified mnemonic.
## IBM Reference
- [AIX 7.3 — `crand` (Condition Register AND)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-crand-condition-register-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,119 @@
# `crandc` — Condition Register AND with Complement
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000102`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `crandc` | `crandc` | — | Condition Register AND with Complement |
## Syntax
```asm
crandc [CRBD], [CRBA], [CRBB]
```
## Encoding
### `crandc` — form `XL`
- **Opcode word:** `0x4c000102`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `129`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | crandc: read | CR source bit A (031). |
| `CRBB` | crandc: read | CR source bit B (031). |
| `CRBD` | crandc: write | CR destination bit (031). |
## Register Effects
### `crandc`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`crandc`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="crandc"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:361`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L361)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:713`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L713)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← CR[CRBA] AND ¬CR[CRBB]` — a one-instruction "A and not B" that would otherwise need a complement-then-AND sequence. All other CR bits are preserved.
- **Bit-level operands.** `CRBD`, `CRBA`, `CRBB` are 5-bit indices into the 32 CR bits (0=CR0.LT, 1=CR0.GT, 2=CR0.EQ, 3=CR0.SO, 4=CR1.LT, …, 31=CR7.SO). They need not lie in the same CR field.
- **Identity / corner cases.** `crandc BT, BA, BA` always yields 0 (a clear-bit idiom, equivalent to but slower than `crxor BT, BT, BT`). `crandc BT, BA, BB` with `BB` always 0 reduces to `crmove BT, BA`.
- **Use case.** Synthesises "branch if A *and not* B" predicates without a dedicated `cmp` of `B`. Example: branch only if `cr0.EQ` *and not* `cr1.SO``crandc 2, 2, 7` then `beq` on `cr0`.
- **No `Rc` / `OE`.** Pure CR-bit dataflow; doesn't update CR0 or XER.
- **Not synchronising.** Reorderable.
- **xenia status.** Interpreter handles via the generic CR-logical helper. xenia-canary's `InstrEmit_crandc` emits a host AND of `A` and bitwise-NOT of `B`.
## Related Instructions
- [`crand`](crand.md), [`cror`](cror.md), [`crorc`](crorc.md) — closest siblings.
- [`crnand`](crnand.md), [`crnor`](crnor.md), [`crxor`](crxor.md), [`creqv`](creqv.md) — full set of CR Boolean ops.
- [`mcrf`](mcrf.md) — copy entire CR field; complementary "broad" CR move.
- [`bcx`](../branch/bcx.md) — typical consumer of synthesised CR bits.
`crandc` has no dedicated simplified mnemonic. See [`crand`](crand.md) for the standard `crmove` / `crset` / `crclr` family.
## IBM Reference
- [AIX 7.3 — `crandc` (Condition Register AND with Complement)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-crandc-condition-register-complement-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,124 @@
# `creqv` — Condition Register Equivalent
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000242`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `creqv` | `creqv` | — | Condition Register Equivalent |
## Syntax
```asm
creqv [CRBD], [CRBA], [CRBB]
```
## Encoding
### `creqv` — form `XL`
- **Opcode word:** `0x4c000242`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `289`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | creqv: read | CR source bit A (031). |
| `CRBB` | creqv: read | CR source bit B (031). |
| `CRBD` | creqv: write | CR destination bit (031). |
## Register Effects
### `creqv`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`creqv`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="creqv"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:370`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L370)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:718`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L718)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← ¬(CR[CRBA] XOR CR[CRBB])` — i.e. logical equivalence (XNOR). Result is 1 iff `CRBA` and `CRBB` agree.
- **`crset BT` idiom.** With identical operands, `creqv BT, BT, BT` always yields 1 (any bit XNOR'd with itself is 1). This is the canonical PowerPC **set-to-1** for a single CR bit; assemblers recognise the simplified mnemonic `crset BT`.
- **Bit-level operands.** Like all CR-logical ops, the three operands are 5-bit absolute CR-bit indices (0..31). Mixing CR fields is fine.
- **Use case.** Branch on "A == B" of two prior compare results. Example: `crxor` of CR0.SO and CR1.SO gives "differ"; `creqv` gives "agree".
- **No `Rc` / `OE`.** Doesn't touch CR0, XER, or any other state beyond the named bit.
- **Not synchronising.** Reorderable.
- **xenia status.** Interpreter dispatches through the generic CR-logical helper; canary emits the host XNOR equivalent. The `crset` simplified form is the most common occurrence in real Xbox 360 code.
## Related Instructions
- [`crand`](crand.md), [`crandc`](crandc.md) — AND family.
- [`cror`](cror.md), [`crorc`](crorc.md), [`crnor`](crnor.md), [`crnand`](crnand.md) — OR family.
- [`crxor`](crxor.md) — the dual; `crxor BT, BT, BT` is the standard **clear-to-0** idiom.
- [`mcrf`](mcrf.md) — bulk CR-field move.
- [`bcx`](../branch/bcx.md) — consumes the synthesised bit.
### Simplified Mnemonics
| Simplified | Expansion | Effect |
| --- | --- | --- |
| `crset BT` | `creqv BT, BT, BT` | force `CR[BT] ← 1` |
## IBM Reference
- [AIX 7.3 — `creqv` (Condition Register Equivalent)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-creqv-condition-register-equivalent-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,121 @@
# `crnand` — Condition Register NAND
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c0001c2`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `crnand` | `crnand` | — | Condition Register NAND |
## Syntax
```asm
crnand [CRBD], [CRBA], [CRBB]
```
## Encoding
### `crnand` — form `XL`
- **Opcode word:** `0x4c0001c2`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `225`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | crnand: read | CR source bit A (031). |
| `CRBB` | crnand: read | CR source bit B (031). |
| `CRBD` | crnand: write | CR destination bit (031). |
## Register Effects
### `crnand`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`crnand`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="crnand"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:379`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L379)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:716`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L716)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← ¬(CR[CRBA] AND CR[CRBB])`. Result is 0 only when both source bits are 1; otherwise 1.
- **Bit-level operands.** 5-bit absolute CR-bit indices, identical to the rest of the CR-logical family. Source and destination bits may all be in different CR fields.
- **Identity case.** `crnand BT, BA, BA``¬CR[BA]` — a one-instruction CR-bit invert. Less common than `crxor` against a `crset`-prepared 1-bit, but legal.
- **Use case.** Branch on "NOT (A AND B)". Less common than the De Morgan equivalent (`cror BT, ¬A, ¬B`), but saves an extra `crnot` step.
- **No `Rc` / `OE`.** No CR0 / XER side effects.
- **Not synchronising.** Reorderable.
- **xenia status.** Decoded by the generic XL-form CR-logical handler; the interpreter snapshot is shared with `crand`/`cror`/etc. xenia-canary's `InstrEmit_crnand` emits a host AND followed by NOT.
## Related Instructions
- [`crand`](crand.md), [`crandc`](crandc.md) — non-negated AND siblings.
- [`crnor`](crnor.md) — negated OR (the De Morgan dual).
- [`cror`](cror.md), [`crorc`](crorc.md) — OR family.
- [`crxor`](crxor.md), [`creqv`](creqv.md) — XOR / XNOR.
- [`mcrf`](mcrf.md) — copy a 4-bit CR field wholesale.
- [`bcx`](../branch/bcx.md) — typical consumer.
`crnand` has no dedicated simplified mnemonic. Use `crand` + a separate complement, or use `crnand BT, BA, BA` to invert a single bit.
## IBM Reference
- [AIX 7.3 — `crnand` (Condition Register NAND)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-crnand-condition-register-nand-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,125 @@
# `crnor` — Condition Register NOR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000042`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `crnor` | `crnor` | — | Condition Register NOR |
## Syntax
```asm
crnor [CRBD], [CRBA], [CRBB]
```
## Encoding
### `crnor` — form `XL`
- **Opcode word:** `0x4c000042`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `33`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | crnor: read | CR source bit A (031). |
| `CRBB` | crnor: read | CR source bit B (031). |
| `CRBD` | crnor: write | CR destination bit (031). |
## Register Effects
### `crnor`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`crnor`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="crnor"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:388`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L388)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:712`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L712)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← ¬(CR[CRBA] OR CR[CRBB])`. Result is 1 only when both source bits are 0; otherwise 0.
- **`crnot BT, BA` idiom.** With `BA == BB`, `crnor BT, BA, BA``¬CR[BA]` — this is the canonical PowerPC **single-bit invert**, recognised by assemblers as the simplified mnemonic `crnot BT, BA`.
- **Bit-level operands.** 5-bit absolute CR-bit indices (0..31). The three bits may live in any combination of the eight CR fields.
- **Use case.** Branch on "neither A nor B"; or, with `crnot`, simply complement a CR bit before consuming it in a `bcx`.
- **No `Rc` / `OE`.** Pure CR-bit dataflow; CR0/XER untouched.
- **Not synchronising.** Reorderable.
- **xenia status.** Decoded via the generic CR-logical handler. xenia-canary's `InstrEmit_crnor` emits a host OR followed by NOT.
## Related Instructions
- [`cror`](cror.md), [`crorc`](crorc.md) — non-negated OR siblings.
- [`crnand`](crnand.md) — negated AND (the De Morgan dual).
- [`crand`](crand.md), [`crandc`](crandc.md) — AND family.
- [`crxor`](crxor.md), [`creqv`](creqv.md) — XOR / XNOR.
- [`mcrf`](mcrf.md) — bulk CR-field copy.
- [`bcx`](../branch/bcx.md) — typical consumer of synthesised CR bits.
### Simplified Mnemonics
| Simplified | Expansion | Effect |
| --- | --- | --- |
| `crnot BT, BA` | `crnor BT, BA, BA` | `CR[BT] ← ¬CR[BA]` (invert single bit) |
## IBM Reference
- [AIX 7.3 — `crnor` (Condition Register NOR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-crnor-condition-register-nor-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,125 @@
# `cror` — Condition Register OR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000382`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `cror` | `cror` | — | Condition Register OR |
## Syntax
```asm
cror [CRBD], [CRBA], [CRBB]
```
## Encoding
### `cror` — form `XL`
- **Opcode word:** `0x4c000382`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `449`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | cror: read | CR source bit A (031). |
| `CRBB` | cror: read | CR source bit B (031). |
| `CRBD` | cror: write | CR destination bit (031). |
## Register Effects
### `cror`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`cror`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="cror"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:397`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L397)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:720`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L720)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← CR[CRBA] OR CR[CRBB]`. All other CR bits are preserved.
- **`crmove BT, BA` idiom.** With `BA == BB`, `cror BT, BA, BA` is the canonical PowerPC **single-bit copy** between CR bits, recognised by assemblers as the simplified mnemonic `crmove BT, BA`. This is the standard way to relocate a CR bit (e.g., promote `cr1.EQ` to `cr0.EQ` so a default-`cr0` branch can consume it).
- **Bit-level operands.** Three independent 5-bit CR-bit indices; mixing CR fields is the whole point of this family.
- **Use case.** Branch on "A OR B" of two prior compare results — saves an extra branch by collapsing two conditions.
- **No `Rc` / `OE`.** Pure CR-bit dataflow.
- **Not synchronising.** Reorderable.
- **xenia status.** Most-used CR-logical instruction in real code (almost always as `crmove`). Decoded by the generic XL-form CR-logical handler; canary emits a host OR.
## Related Instructions
- [`crand`](crand.md), [`crandc`](crandc.md) — AND family.
- [`crorc`](crorc.md) — OR with complement.
- [`crnor`](crnor.md), [`crnand`](crnand.md) — negated forms.
- [`crxor`](crxor.md), [`creqv`](creqv.md) — XOR / XNOR.
- [`mcrf`](mcrf.md) — copy a 4-bit CR field wholesale.
- [`bcx`](../branch/bcx.md), [`bclrx`](../branch/bclrx.md), [`bcctrx`](../branch/bcctrx.md) — typical consumers.
### Simplified Mnemonics
| Simplified | Expansion | Effect |
| --- | --- | --- |
| `crmove BT, BA` | `cror BT, BA, BA` | `CR[BT] ← CR[BA]` (single-bit copy) |
## IBM Reference
- [AIX 7.3 — `cror` (Condition Register OR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-cror-condition-register-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,121 @@
# `crorc` — Condition Register OR with Complement
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000342`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `crorc` | `crorc` | — | Condition Register OR with Complement |
## Syntax
```asm
crorc [CRBD], [CRBA], [CRBB]
```
## Encoding
### `crorc` — form `XL`
- **Opcode word:** `0x4c000342`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `417`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | crorc: read | CR source bit A (031). |
| `CRBB` | crorc: read | CR source bit B (031). |
| `CRBD` | crorc: write | CR destination bit (031). |
## Register Effects
### `crorc`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`crorc`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="crorc"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:406`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L406)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:719`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L719)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← CR[CRBA] OR ¬CR[CRBB]` — a one-instruction "A or not B" implication. Result is 0 only when `A=0` and `B=1`.
- **Logical implication.** `B → A``¬B A`, which is exactly `crorc BT, BA, BB`. Useful for predicates of the form "if B holds, then A must hold".
- **Identity case.** `crorc BT, BA, BA` always yields 1 (`A ¬A`), an alternative to `creqv` for setting a bit.
- **Bit-level operands.** 5-bit absolute CR-bit indices; sources and destination may all be in different CR fields.
- **Use case.** Compose "if B then A" guards without a separate complement step.
- **No `Rc` / `OE`.** Doesn't update CR0 or XER.
- **Not synchronising.** Reorderable.
- **xenia status.** Decoded by the generic CR-logical handler; canary emits OR-with-NOT directly.
## Related Instructions
- [`cror`](cror.md), [`crnor`](crnor.md) — non-complement OR / NOR.
- [`crand`](crand.md), [`crandc`](crandc.md), [`crnand`](crnand.md) — AND family.
- [`crxor`](crxor.md), [`creqv`](creqv.md) — XOR / XNOR.
- [`mcrf`](mcrf.md) — bulk CR-field copy.
- [`bcx`](../branch/bcx.md) — typical consumer.
`crorc` has no dedicated simplified mnemonic. See [`cror`](cror.md) for `crmove`.
## IBM Reference
- [AIX 7.3 — `crorc` (Condition Register OR with Complement)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-crorc-condition-register-complement-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,124 @@
# `crxor` — Condition Register XOR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000182`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `crxor` | `crxor` | — | Condition Register XOR |
## Syntax
```asm
crxor [CRBD], [CRBA], [CRBB]
```
## Encoding
### `crxor` — form `XL`
- **Opcode word:** `0x4c000182`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `193`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRBA` | crxor: read | CR source bit A (031). |
| `CRBB` | crxor: read | CR source bit B (031). |
| `CRBD` | crxor: write | CR destination bit (031). |
## Register Effects
### `crxor`
- **Reads (always):** `CRBA`, `CRBB`
- **Reads (conditional):** _none_
- **Writes (always):** `CRBD`
- **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
**`crxor`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="crxor"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:415`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L415)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:17`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L17)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:715`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L715)
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** `CR[CRBD] ← CR[CRBA] XOR CR[CRBB]`. Result is 1 iff the two source bits differ.
- **`crclr BT` idiom.** With identical operands, `crxor BT, BT, BT` always yields 0 (any bit XOR'd with itself is 0). This is the canonical PowerPC **clear-to-0** for a single CR bit; assemblers recognise the simplified mnemonic `crclr BT`. Compilers emit it before variadic-argument calls (PPC ABI uses `cr1.SO` to flag presence of FP arguments).
- **Bit-level operands.** Three independent 5-bit absolute CR-bit indices (0..31).
- **Use case.** Branch on "A != B"; or, with the `crclr` idiom, zero a CR bit before fall-through CR computation.
- **No `Rc` / `OE`.** No CR0 / XER side effects.
- **Not synchronising.** Reorderable.
- **xenia status.** Common enough in real code (typically as `crclr 6` for the variadic-FP marker) that translators often special-case the `crclr` pattern. xenia-canary's `InstrEmit_crxor` emits a host XOR; xenia-rs decodes via the generic CR-logical handler.
## Related Instructions
- [`creqv`](creqv.md) — the dual; `creqv BT, BT, BT` is the standard **set-to-1** idiom.
- [`crand`](crand.md), [`crandc`](crandc.md), [`crnand`](crnand.md) — AND family.
- [`cror`](cror.md), [`crorc`](crorc.md), [`crnor`](crnor.md) — OR family.
- [`mcrf`](mcrf.md) — bulk CR-field copy.
- [`bcx`](../branch/bcx.md), [`bclrx`](../branch/bclrx.md) — typical consumers of synthesised CR bits.
### Simplified Mnemonics
| Simplified | Expansion | Effect |
| --- | --- | --- |
| `crclr BT` | `crxor BT, BT, BT` | force `CR[BT] ← 0` |
## IBM Reference
- [AIX 7.3 — `crxor` (Condition Register XOR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-crxor-condition-register-xor-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,129 @@
# `mcrf` — Move Condition Register Field
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XL](../forms/XL.md) · **Opcode:** `0x4c000000`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mcrf` | `mcrf` | — | Move Condition Register Field |
## Syntax
```asm
mcrf [CRFD], [CRFS]
```
## Encoding
### `mcrf` — form `XL`
- **Opcode word:** `0x4c000000`
- **Primary opcode (bits 05):** `19`
- **Extended opcode:** `0`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (19) |
| 610 | `BT/BO` | target / branch options |
| 1115 | `BA/BI` | source A / CR bit to test |
| 1620 | `BB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `LK` | link flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRFS` | mcrf: read | CR source field. |
| `CRFD` | mcrf: write | CR destination field (`crf`, 07). |
## Register Effects
### `mcrf`
- **Reads (always):** `CRFS`
- **Reads (conditional):** _none_
- **Writes (always):** `CRFD`
- **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
**`mcrf`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mcrf"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:424`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L424)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:51`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L51)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:710`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L710)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1683-1686`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1683-L1686)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mcrf => {
ctx.cr[instr.crfd()] = ctx.cr[instr.crfs()];
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Field-level (4-bit) move.** Unlike the bit-level CR-logical family ([`crand`](crand.md), …, [`crxor`](crxor.md)), `mcrf` copies *all four* bits of a CR field (LT, GT, EQ, SO) in one instruction. `CRFD` and `CRFS` are 3-bit field indices (0..7), each naming a 4-bit slice of the 32-bit CR.
- **No source-field clobber.** The source field is read, not modified — `mcrf 0, 1` copies CR1 into CR0 leaving CR1 intact.
- **Same-field is a NOP.** `mcrf cr0, cr0` reads-then-writes the same field; xenia's interpreter still does the assignment but the architectural state is unchanged.
- **Use case.** Promote a non-default compare result into `cr0` so a default-`cr0` simplified branch (`beq label`) can consume it without spelling out `cr1`/`cr2`/etc. The alternative — `crmove` — would require four `cror` instructions to move all four bits.
- **No CR0/XER side effects.** Pure CR-field dataflow.
- **Not synchronising.** Reorderable.
- **xenia exact match.** xenia-rs models the CR as an array of eight 4-bit fields, so `mcrf` is a single struct copy (`ctx.cr[crfd] = ctx.cr[crfs]`). Matches PowerISA semantics exactly.
## Related Instructions
- [`mfcr`](mfcr.md) — read the entire 32-bit CR into a GPR.
- [`mtcrf`](mtcrf.md) — write selected CR fields from a GPR (uses an 8-bit field-mask).
- [`mcrxr`](mcrxr.md) — copy `XER[SO..CA]` into a CR field and clear them.
- [`mcrfs`](mcrfs.md) — copy an FPSCR field into a CR field.
- [`crand`](crand.md), [`crandc`](crandc.md), [`creqv`](creqv.md), [`crnand`](crnand.md), [`crnor`](crnor.md), [`cror`](cror.md), [`crorc`](crorc.md), [`crxor`](crxor.md) — bit-level alternatives.
- [`bcx`](../branch/bcx.md) — typical consumer.
`mcrf` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mcrf` (Move Condition Register Field)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mcrf-move-condition-register-field-instruction)

View File

@@ -0,0 +1,155 @@
# `mcrfs` — Move to Condition Register from FPSCR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0xfc000080`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mcrfs` | `mcrfs` | — | Move to Condition Register from FPSCR |
## Syntax
```asm
mcrfs [CRFD], [CRFS]
```
## Encoding
### `mcrfs` — form `X`
- **Opcode word:** `0xfc000080`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `64`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CRFS` | mcrfs: read | CR source field. |
| `FPSCR` | mcrfs: read; mcrfs: write | Floating-Point Status and Control Register. |
| `CRFD` | mcrfs: write | CR destination field (`crf`, 07). |
## Register Effects
### `mcrfs`
- **Reads (always):** `CRFS`, `FPSCR`
- **Reads (conditional):** _none_
- **Writes (always):** `CRFD`, `FPSCR`
- **Writes (conditional):** _none_
## Status-Register Effects
- `mcrfs`: **FPSCR** updated per IEEE-754 flags (FX, FEX, FPRF, FR, FI, exceptions).
## 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
**`mcrfs`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mcrfs"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:371`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L371)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:51`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L51)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:904`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L904)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:4716-4745`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L4716-L4745)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mcrfs => {
let crfd = instr.crfd();
let crfs = instr.crfs();
let shift = 28 - (crfs as u32 * 4);
let nibble = ((ctx.fpscr >> shift) & 0xF) as u8;
ctx.cr[crfd] = crate::context::CrField::from_u8(nibble);
// Clearable exception bits: 0 (FX), 3 (OX), 4 (UX), 5 (ZX),
// 6 (XX), 7 (VXSNAN), 8 (VXISI), 9 (VXIDI), 10 (VXZDZ),
// 11 (VXIMZ), 12 (VXVC), 21 (VXSOFT), 22 (VXSQRT), 23 (VXCVI).
// (Bit positions are PowerISA MSB-0; here 'FPSCR bit n' means
// the bit at (31-n) in our little-endian u32.)
const CLEARABLE_MASK: u32 =
(1 << 31) | (1 << (31 - 3)) | (1 << (31 - 4)) |
(1 << (31 - 5)) | (1 << (31 - 6)) | (1 << (31 - 7)) |
(1 << (31 - 8)) | (1 << (31 - 9)) | (1 << (31 - 10)) |
(1 << (31 - 11)) | (1 << (31 - 12)) |
(1 << (31 - 21)) | (1 << (31 - 22)) | (1 << (31 - 23));
let nibble_mask = 0xFu32 << shift;
ctx.fpscr &= !(nibble_mask & CLEARABLE_MASK);
// PPCBUG-068: recompute the VX summary bit. If any VX* exception
// bit remains set, VX must remain set; if all are cleared, VX
// must clear. (FEX recomputation omitted — xenia doesn't model
// enabled-exception dispatch.)
if ctx.fpscr & fpscr::VX_ALL != 0 {
ctx.fpscr |= fpscr::VX;
} else {
ctx.fpscr &= !fpscr::VX;
}
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Copies one 4-bit FPSCR field into the chosen CR field, then **clears the source FPSCR exception-status bits** (sticky-bit reset). The non-exception status bits (FPRF, etc.) are *not* cleared.
- **Bits cleared in FPSCR.** The architectural rule is: any bit in the source FPSCR field that is one of {FX, OX, UX, ZX, XX, VXSNAN, VXISI, VXIDI, VXZDZ, VXIMZ, VXVC, VXSOFT, VXSQRT, VXCVI} is reset to 0 after the copy. FEX and VX (summary bits) are subsequently re-derived. Many other FPSCR bits (rounding mode, FPRF, FR/FI) are not affected — even if they fall in `CRFS`.
- **CR field destination.** `CRFD` is a 3-bit field index (0..7); the four bits land in their natural positions (LT, GT, EQ, SO) of the chosen CR field. After `mcrfs`, `crf` can be tested with the usual conditional branches.
- **Use case.** Inspect a particular FPSCR exception group, then act on it with a `bc` — e.g. test FPSCR[24..27] (the FI / FR / VXSNAN / VXISI cluster) and branch.
- **Privilege.** Non-privileged on the Xenon — application-visible.
- **xenia status.** Decoded (decoder slot 727), but the interpreter does **not** ship a body in the snapshot on this page — `mcrfs` is rare in title code. xenia's FPSCR model is incomplete (most exception bits are stubbed), so even when implemented, the cleared bits typically have no observable effect.
- **No `Rc`.** X-form, but the `Rc` bit position is unused (reserved 0).
## Related Instructions
- [`mffsx`](mffsx.md) — read entire FPSCR into an FPR.
- [`mtfsfx`](mtfsfx.md), [`mtfsb0x`](mtfsb0x.md), [`mtfsb1x`](mtfsb1x.md), [`mtfsfix`](mtfsfix.md) — write FPSCR bits/fields.
- [`mcrf`](mcrf.md) — copy a CR field to another CR field.
- [`mcrxr`](mcrxr.md) — analogous copy from XER (also clears).
`mcrfs` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mcrfs` (Move to Condition Register from FPSCR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mcrfs-move-condition-register-from-fpscr-instruction)
- PowerISA v2.07B, Book I §4.6 — FPSCR layout (sticky exception bits and which clear semantics apply).

View File

@@ -0,0 +1,145 @@
# `mcrxr` — Move to Condition Register from XER
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c000400`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mcrxr` | `mcrxr` | — | Move to Condition Register from XER |
## Syntax
```asm
mcrxr [CRFD]
```
## Encoding
### `mcrxr` — form `X`
- **Opcode word:** `0x7c000400`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `512`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CR` | mcrxr: read | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
| `CRFD` | mcrxr: write | CR destination field (`crf`, 07). |
## Register Effects
### `mcrxr`
- **Reads (always):** `CR`
- **Reads (conditional):** _none_
- **Writes (always):** `CRFD`
- **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
**`mcrxr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mcrxr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:433`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L433)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:51`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L51)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:814`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L814)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:4694-4706`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L4694-L4706)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mcrxr => {
let crfd = instr.crfd();
ctx.cr[crfd] = crate::context::CrField {
lt: ctx.xer_so != 0,
gt: ctx.xer_ov != 0,
eq: ctx.xer_ca != 0,
so: false,
};
ctx.xer_so = 0;
ctx.xer_ov = 0;
ctx.xer_ca = 0;
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Copies XER's top 4 status bits into a CR field, **then atomically clears those XER bits**. Layout in the destination CR field after the move:
| CR bit | Source XER bit | Meaning |
| --- | --- | --- |
| LT | XER[SO] | summary overflow (sticky) |
| GT | XER[OV] | overflow (last `OE=1` op) |
| EQ | XER[CA] | carry |
| SO | 0 (cleared) | — |
- **Sticky-bit reset.** XER[SO], XER[OV], and XER[CA] are all *zeroed* after the copy. This is the **only** architecturally clean way to sample-then-clear XER's overflow/carry state — `mfxer` reads but does not clear.
- **Use case.** Saturating-arithmetic loops sample XER[OV] periodically; `mcrxr cr0; bso cr0, overflow` is the canonical "did overflow happen since last check?" idiom.
- **CR field destination.** `CRFD` is a 3-bit index (0..7). All other CR fields are preserved.
- **No reads of GPRs.** `mcrxr` reads only XER, writes only the chosen CR field and XER.
- **xenia exact match.** xenia-rs implements the full sample-and-clear semantics: writes `lt = SO`, `gt = OV`, `eq = CA`, `so = false`, then zeroes `xer_so`, `xer_ov`, `xer_ca`. Matches PowerISA exactly.
- **Deprecated in newer PowerISA.** PowerISA v2.06+ marked `mcrxr` deprecated in favour of `mcrxrx` and explicit `mfxer`/`mtxer` patterns, but the Xenon predates that; titles still emit it freely.
## Related Instructions
- [`mfcr`](mfcr.md), [`mtcrf`](mtcrf.md) — bulk CR <-> GPR moves.
- [`mcrf`](mcrf.md) — CR-field copy.
- [`mcrfs`](mcrfs.md) — analogous copy from FPSCR (also clears certain bits).
- [`mfspr`](mfspr.md) (with `SPR=1`, i.e. `mfxer`) — non-clearing read of XER into a GPR.
- [`mtspr`](mtspr.md) (with `SPR=1`, i.e. `mtxer`) — explicit XER write.
`mcrxr` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mcrxr` (Move to Condition Register from XER)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mcrxr-move-condition-register-from-xer-instruction)

View File

@@ -0,0 +1,117 @@
# `mfcr` — Move from Condition Register
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c000026`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mfcr` | `mfcr` | — | Move from Condition Register |
## Syntax
```asm
mfcr [RD]
```
## Encoding
### `mfcr` — form `X`
- **Opcode word:** `0x7c000026`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `19`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `CR` | mfcr: read | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
| `RD` | mfcr: write | Destination GPR. |
## Register Effects
### `mfcr`
- **Reads (always):** `CR`
- **Reads (conditional):** _none_
- **Writes (always):** `RD`
- **Writes (conditional):** _none_
## Status-Register Effects
_No condition-register or status-register effects._
## Operation (pseudocode)
```
RT <- 0x00000000 || CR
```
## 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
**`mfcr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mfcr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:625`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L625)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:53`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L53)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:753`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L753)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1627-1630`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1627-L1630)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mfcr => {
ctx.gpr[instr.rd()] = ctx.cr() as u64;
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Packs all 32 CR bits into the low half of `RD`; the upper 32 bits of `RD` are zeroed. CR field 0 ends up in bits 32..35 of `RD` (i.e. bits 0..3 of the 32-bit packed value), CR field 7 in bits 60..63 (bits 28..31).
- **No CR side effect.** `mfcr` is a read; CR is unmodified. The XL-form's nominal `Rc` bit is unused on this opcode.
- **Saving CR across calls.** The Xbox 360 / SysV ABI requires non-volatile CR fields (CR2..CR4) to be preserved across calls. Standard prologue: `mfcr r12; stw r12, 8(r1)`. Epilogue restores via [`mtcrf`](mtcrf.md).
- **Bit ordering.** PowerPC numbers bits big-endian (bit 0 = MSB). The encoding into the GPR follows the same convention: CR0.LT lands in bit 32 of the doubleword (the MSB of the low word). C-side translations should mask with `0xFFFFFFFFu` before consuming.
- **`mfocrf` variant.** PowerISA defines `mfocrf` (one CR field), encoded as `mfcr` with the high bit of FXM set. xenia-rs decodes both as the same opcode and ignores the FXM hint, returning the entire CR. This is benign — the spec says implementations may treat `mfocrf` as `mfcr`.
- **Not synchronising.** Reorderable.
- **xenia exact match.** xenia-rs packs its eight `CrField` structs into a `u64` via `ctx.cr()`, mirroring spec semantics.
## Related Instructions
- [`mtcrf`](mtcrf.md) — inverse: write selected CR fields from a GPR.
- [`mcrf`](mcrf.md), [`mcrxr`](mcrxr.md), [`mcrfs`](mcrfs.md) — narrower CR-field moves.
- [`mfspr`](mfspr.md), [`mtspr`](mtspr.md) — generic SPR moves; CR is *not* an SPR (it has its own opcode).
`mfcr` has no simplified mnemonics. `mfocrf RT, FXM` is a related encoding handled by the same xenia-rs slot.
## IBM Reference
- [AIX 7.3 — `mfcr` (Move from Condition Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mfcr-move-from-condition-register-instruction)

View File

@@ -0,0 +1,132 @@
# `mffsx` — Move from FPSCR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0xfc00048e`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mffs` | `mffsx` | — | Move from FPSCR |
| `mffs.` | `mffsx` | Rc=1 | Move from FPSCR |
## Syntax
```asm
mffs[Rc] [RD]
```
## Encoding
### `mffsx` — form `X`
- **Opcode word:** `0xfc00048e`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `583`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `FPSCR` | mffsx: read | Floating-Point Status and Control Register. |
| `FD` | mffsx: write | Destination floating-point register. |
| `CR` | mffsx: write (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
## Register Effects
### `mffsx`
- **Reads (always):** `FPSCR`
- **Reads (conditional):** _none_
- **Writes (always):** `FD`
- **Writes (conditional):** `CR`
## Status-Register Effects
- `mffsx`: **CR0** ← signed-compare(result, 0) with `SO ← XER[SO]`, when `Rc=1`.
## 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
**`mffsx`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mffsx"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:397`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L397)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:53`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L53)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:910`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L910)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:3035-3040`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L3035-L3040)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mffsx => {
// Move from FPSCR: frD = FPSCR as double (low 32 bits)
ctx.fpr[instr.rd()] = f64::from_bits(ctx.fpscr as u64);
if instr.rc_bit() { update_cr1_from_fpscr(ctx); }
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Reads the 32-bit FPSCR and places it in the **low 32 bits** of `FRT`. The high 32 bits of the destination FPR are architecturally undefined; xenia leaves them as the bit-pattern of the FPSCR cast to `u64` (i.e. the high bits are zero, since FPSCR is 32-bit). PowerISA explicitly permits implementations to leave anything there.
- **Destination is an FPR, not a GPR.** Use [`stfd`](../memory/stfd.md) to spill the FPR to memory and reload via a GPR if the value is needed in the integer file.
- **`mffs.` (`Rc=1`) updates CR1.** The `Rc` bit copies the high four FPSCR bits (FX, FEX, VX, OX) into CR1's LT/GT/EQ/SO. xenia-rs implements this via `update_cr1_from_fpscr`.
- **No FPSCR side effect.** Pure read; FPSCR is not modified (unlike [`mcrfs`](mcrfs.md), which clears sticky exception bits).
- **xenia simplification.** xenia-rs models FPSCR as a `u32` field but **does not actively maintain** most of the IEEE-754 sticky bits — the FPU paths typically leave FPSCR untouched. So `mffs` will return whatever was last explicitly set (often 0 / boot defaults). Real titles use it mostly to save/restore the rounding-mode field around library calls, which xenia happens to handle correctly.
- **Not synchronising.** Reorderable with non-FPU instructions.
## Related Instructions
- [`mtfsfx`](mtfsfx.md) — write fields of FPSCR from an FPR (the inverse).
- [`mtfsb0x`](mtfsb0x.md), [`mtfsb1x`](mtfsb1x.md) — set/clear individual FPSCR bits.
- [`mtfsfix`](mtfsfix.md) — load a 4-bit immediate into one FPSCR field.
- [`mcrfs`](mcrfs.md) — copy an FPSCR field into a CR field (and clear sticky bits).
- [`mfspr`](mfspr.md) — for non-FPSCR special registers.
`mffs` is the simplified mnemonic for the base form (`Rc=0`); `mffs.` is the recording variant.
## IBM Reference
- [AIX 7.3 — `mffs` (Move from FPSCR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mffs-move-from-fpscr-instruction)
- PowerISA v2.07B, Book I §4.6 — FPSCR layout and the high-half-undefined rule.

View File

@@ -0,0 +1,139 @@
# `mfmsr` — Move from Machine State Register
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c0000a6` · _sync_
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mfmsr` | `mfmsr` | — | Move from Machine State Register |
## Syntax
```asm
mfmsr [RD]
```
## Encoding
### `mfmsr` — form `X`
- **Opcode word:** `0x7c0000a6`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `83`
- **Synchronising:** yes
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `MSR` | mfmsr: read | Machine State Register. |
| `RD` | mfmsr: write | Destination GPR. |
## Register Effects
### `mfmsr`
- **Reads (always):** `MSR`
- **Reads (conditional):** _none_
- **Writes (always):** `RD`
- **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
**`mfmsr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mfmsr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:814`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L814)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:53`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L53)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:771`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L771)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1645-1648`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1645-L1648)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mfmsr => {
ctx.gpr[instr.rd()] = ctx.msr;
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Privileged.** `mfmsr` is supervisor-only; executing it from problem state on real hardware raises a Privileged Instruction interrupt. Xbox 360 game code never executes it directly — it appears only in the kernel image (`xboxkrnl.exe`) and in xenia's HLE bridge.
- **MSR layout (Xenon-relevant fields, big-endian bit numbering).**
| Bit | Name | Meaning |
| --- | --- | --- |
| 32 | EE | external interrupts enabled |
| 33 | PR | problem state (1 = user) |
| 34 | FP | floating-point available |
| 35 | ME | machine-check enable |
| 38 | DR | data address translation |
| 39 | IR | instruction address translation |
| 50 | LE | little-endian (always 0 on Xenon) |
| 63 | RI | recoverable interrupt |
The Xenon also exposes `MSR[SF]` (bit 0) = 1 for 64-bit mode; `MSR[HV]` (bit 3) for hypervisor. See PowerISA Book III for the full table.
- **Synchronisation.** Marked `sync` in xenia's XML — `mfmsr` is execution-synchronising on real hardware (drains the pipeline before sampling MSR).
- **xenia model.** xenia-rs stores MSR as a flat `u64` and returns it raw. No real bit semantics are modelled — the kernel HLE never observes individual MSR fields. The interpreter ignores privilege.
- **Read of an undocumented field returns 0.** Most of the MSR is zero in xenia because no path explicitly initialises it.
## Related Instructions
- [`mtmsr`](mtmsr.md) — write MSR from a GPR (32-bit form).
- [`mtmsrd`](mtmsrd.md) — write the full 64-bit MSR (PPC64 form).
- [`mfspr`](mfspr.md) — for non-MSR special registers; MSR has its own dedicated opcode.
- [`sc`](../branch/sc.md) — kernel entry where MSR transitions occur via `rfid`/`hrfid`.
`mfmsr` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mfmsr` (Move from Machine State Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mfmsr-move-from-machine-state-register-instruction)
- PowerISA v2.07B, Book III §4.3 — MSR field definitions.

View File

@@ -0,0 +1,179 @@
# `mfspr` — Move from Special-Purpose Register
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XFX](../forms/XFX.md) · **Opcode:** `0x7c0002a6`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mfspr` | `mfspr` | — | Move from Special-Purpose Register |
## Syntax
```asm
mfspr [RD], [SPR]
```
## Encoding
### `mfspr` — form `XFX`
- **Opcode word:** `0x7c0002a6`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `339`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (31) |
| 610 | `RT` | destination / source GPR |
| 1120 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
| 2130 | `XO` | extended opcode |
| 31 | `—` | reserved |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `SPR` | mfspr: read | Special-Purpose-Register number. Encoded with the two 5-bit halves swapped (bits 11-15 become the high half, bits 16-20 the low half). |
| `RD` | mfspr: write | Destination GPR. |
## Register Effects
### `mfspr`
- **Reads (always):** `SPR`
- **Reads (conditional):** _none_
- **Writes (always):** `RD`
- **Writes (conditional):** _none_
## Status-Register Effects
_No condition-register or status-register effects._
## Operation (pseudocode)
```
n <- spr_number(SPR) ; SPR field has its two 5-bit halves swapped
RT <- SPR(n)
```
## C Translation Example
```c
/* mfspr RT, SPR — SPR field has swapped halves */
uint32_t n = ((insn.SPR & 0x1F) << 5) | ((insn.SPR >> 5) & 0x1F);
switch (n) {
case 1: r[insn.RT] = xer_pack(); break; /* XER */
case 8: r[insn.RT] = lr; break; /* LR */
case 9: r[insn.RT] = ctr; break; /* CTR */
case 256: r[insn.RT] = vrsave; break; /* VRSAVE*/
case 268: r[insn.RT] = tb & 0xFFFFFFFFu; break; /* TBL */
case 269: r[insn.RT] = tb >> 32; break; /* TBU */
default: r[insn.RT] = 0; break;
}
```
## Implementation References
**`mfspr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mfspr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:666`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L666)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:53`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L53)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:799`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L799)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1567-1595`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1567-L1595)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mfspr => {
let spr = instr.spr();
ctx.gpr[instr.rd()] = match spr {
crate::context::spr::XER => ctx.xer() as u64,
crate::context::spr::LR => ctx.lr,
crate::context::spr::CTR => ctx.ctr,
crate::context::spr::DEC => ctx.dec as u64,
crate::context::spr::TBL => ctx.timebase & 0xFFFF_FFFF,
crate::context::spr::TBU => ctx.timebase >> 32,
crate::context::spr::VRSAVE => ctx.vrsave as u64,
// Xbox 360 Xenon processor signature (from canary).
crate::context::spr::PVR => 0x0071_0800,
// Benign SPRs — titles read these but we don't model them.
crate::context::spr::SPRG0
| crate::context::spr::SPRG1
| crate::context::spr::SPRG2
| crate::context::spr::SPRG3
| crate::context::spr::HID0
| crate::context::spr::HID1
| crate::context::spr::DAR
| crate::context::spr::DSISR
| crate::context::spr::PIR => 0,
_ => {
tracing::warn!("mfspr: unimplemented SPR {}", spr);
0
}
};
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## SPR Number Encoding — the "halves swap"
The 10-bit `spr` field in the XFX form is **stored in a transposed order**: the bits that software names the *high* half (bits 5..9 of the SPR number) occupy instruction bits **16..20**, and the *low* half (bits 0..4) occupies instruction bits **11..15**. Software (and this manual) always refers to the logical, unswapped SPR number.
```
decoded_spr = ((field & 0x1F) << 5) | ((field >> 5) & 0x1F)
```
So a programmer writing `mfspr RT, 8` (read LR) encodes `spr-field = 0x100`*not* `8`. Assemblers handle this transparently; disassemblers reverse it. When writing a translator that parses raw instruction words, swap the halves explicitly.
## SPR Map (Xenon subset modelled by xenia)
| Decoded # | Name | Meaning | xenia-rs behaviour |
| --- | --- | --- | --- |
| 1 | `XER` | Fixed-point exception register (CA / OV / SO + length field) | packed with `ctx.xer()` |
| 8 | `LR` | Link register | `ctx.lr` |
| 9 | `CTR` | Count register | `ctx.ctr` |
| 18 | `DSISR` | Data-storage interrupt syndrome | returns 0 (stubbed) |
| 19 | `DAR` | Data-access register | returns 0 (stubbed) |
| 256 | `VRSAVE` | Vector-register save mask | `ctx.vrsave` |
| 268 | `TBL` | Time-base lower 32 bits | `ctx.timebase & 0xFFFFFFFF` |
| 269 | `TBU` | Time-base upper 32 bits | `ctx.timebase >> 32` |
| 272275 | `SPRG0..3` | Software scratch registers (kernel) | returns 0 (stubbed) |
| 287 | `PVR` | Processor-version register | `0x00710800` (Xenon signature) |
| 10081009 | `HID0/1` | Hardware implementation registers | returns 0 (stubbed) |
| 1023 | `PIR` | Processor-ID register | returns 0 (stubbed) |
Unrecognised SPRs return 0 and log a warning. Games rarely read unmodelled SPRs; when they do it's usually clock-skew or sanity checks.
## Special Cases & Edge Conditions
- **Privilege.** Some SPRs are privileged on real hardware (MSR, HID0/1, SPRG0..3, DSISR, DAR, PIR). Xbox 360 titles run in a mixed privilege model under the hypervisor; xenia exposes all SPRs without a privilege check because the captured title binaries never contain a real privileged read that should trap.
- **`LR` and `CTR` have dedicated simplified mnemonics.** Assemblers recognise `mflr RT``mfspr RT, 8` and `mfctr RT``mfspr RT, 9`. Similarly `mfxer RT``mfspr RT, 1`. Disassemblers emit the simplified forms; the translation agent should map both forms to the same abstract operation.
- **`mftb` vs. `mfspr TBL/TBU`.** Reading the time-base has a dedicated X-form variant [`mftb`](mftb.md) that uses a separate opcode. Post-Xbox-360 PowerISA deprecated `mfspr TBL/TBU`, but xenia accepts both. Prefer `mftb` in new translations.
- **Side-effect-free.** `mfspr` has no effect on any register beyond `RT`. It can be freely reordered with non-SPR-touching instructions.
- **No `Rc` / `OE`.** This is an XFX-form instruction; bit 31 is reserved (0).
## Related Instructions
- [`mtspr`](mtspr.md) — the inverse; write a GPR to an SPR.
- [`mftb`](mftb.md) — read time-base (preferred over `mfspr TBL/TBU`).
- [`mflr`](mfspr.md), [`mfctr`](mfspr.md), [`mfxer`](mfspr.md) — simplified mnemonics of this instruction.
- [`mcrxr`](mcrxr.md) — move `XER[SO..CA]` to a CR field and clear them.
## Simplified Mnemonics
| Simplified | Expansion |
| --- | --- |
| `mfxer RT` | `mfspr RT, 1` |
| `mflr RT` | `mfspr RT, 8` |
| `mfctr RT` | `mfspr RT, 9` |
## IBM Reference
- [AIX 7.3 — `mfspr` (Move from Special Purpose Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mfspr-move-from-special-purpose-register-instruction)
- [PowerISA v2.07B — SPR number table and privilege rules](https://openpowerfoundation.org/specifications/isa/)

View File

@@ -0,0 +1,150 @@
# `mftb` — Move from Time Base
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XFX](../forms/XFX.md) · **Opcode:** `0x7c0002e6`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mftb` | `mftb` | — | Move from Time Base |
## Syntax
```asm
mftb [RD], [TBR]
```
## Encoding
### `mftb` — form `XFX`
- **Opcode word:** `0x7c0002e6`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `371`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (31) |
| 610 | `RT` | destination / source GPR |
| 1120 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
| 2130 | `XO` | extended opcode |
| 31 | `—` | reserved |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `TBR` | mftb: read | Time-Base Register selector for `mftb`. |
| `RD` | mftb: write | Destination GPR. |
## Register Effects
### `mftb`
- **Reads (always):** `TBR`
- **Reads (conditional):** _none_
- **Writes (always):** `RD`
- **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
**`mftb`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mftb"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:719`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L719)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:53`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L53)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:803`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L803)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1664-1672`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1664-L1672)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mftb => {
let tbr = instr.spr();
ctx.gpr[instr.rd()] = match tbr {
268 => ctx.timebase & 0xFFFF_FFFF,
269 => ctx.timebase >> 32,
_ => 0,
};
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Time-base register selectors.** The 10-bit `tbr` field encodes the same way as `mfspr`'s `spr` field (two halves swapped). The two values defined for the Xenon:
| Decoded | Name | Meaning |
| --- | --- | --- |
| 268 | TBL | Time Base, lower 32 bits |
| 269 | TBU | Time Base, upper 32 bits |
Other selectors return 0 in xenia and are not used by titles.
- **Atomic 64-bit read pattern.** Because `mftb` reads only 32 bits at a time, software performs the canonical retry loop to avoid TBL→TBU rollover skew:
```asm
retry:
mftbu rH ; read upper
mftb rL ; read lower (TBR=268)
mftbu rH2 ; read upper again
cmpw rH, rH2
bne retry
```
- **Xenon clock rate.** Real hardware ticks the time base at ~3.2 GHz (one tick per CPU clock divided by the architectural ratio). The PVR signature the kernel exposes (`0x00710800`) and the kernel-reported tick rate jointly let titles convert TB ticks to seconds.
- **xenia behaviour.** xenia-rs stores `ctx.timebase` as a `u64` and **increments it once per interpreted instruction**, not per real-time wall clock. This guarantees deterministic replay (same trace ⇒ same TB readings) at the cost of decoupling guest time from host time. Games that rely on TB for real-time sync will run faster or slower depending on host throughput.
- **`mftb RT` (no operand)** is the simplified mnemonic for `mftb RT, 268` — read the lower half. `mftbu RT` ≡ `mftb RT, 269`.
- **Deprecated alternative.** `mfspr RT, 268`/`269` works on the Xenon (xenia accepts both) but post-PowerISA v2.06 deprecated reading TB through `mfspr`. Prefer `mftb`.
## Related Instructions
- [`mfspr`](mfspr.md) — generic SPR read; can also read TBL/TBU on Xenon (deprecated).
- [`mtspr`](mtspr.md) — TBL/TBU writes are privileged; not user-accessible.
- [`isync`](mtmsr.md) — context-synchronising fence sometimes paired with `mftb` for tight measurement loops.
### Simplified Mnemonics
| Simplified | Expansion | Notes |
| --- | --- | --- |
| `mftb RT` | `mftb RT, 268` | read TBL |
| `mftbu RT` | `mftb RT, 269` | read TBU |
## IBM Reference
- [AIX 7.3 — `mftb` (Move from Time Base)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mftb-move-from-time-base-instruction)
- PowerISA v2.07B, Book II §6.1 — Time Base description and the canonical 64-bit read sequence.

View File

@@ -0,0 +1,137 @@
# `mfvscr` — Move from VSCR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [VX](../forms/VX.md) · **Opcode:** `0x10000604`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mfvscr` | `mfvscr` | — | Move from VSCR |
## Syntax
```asm
(no disassembly template)
```
## Encoding
### `mfvscr` — form `VX`
- **Opcode word:** `0x10000604`
- **Primary opcode (bits 05):** `4`
- **Extended opcode:** `1540`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (4) |
| 610 | `VRT/VD` | destination vector register |
| 1115 | `VRA/VA` | source A vector register |
| 1620 | `VRB/VB` | source B vector register |
| 2131 | `XO` | extended opcode (11 bits) |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `VSCR` | mfvscr: read | Vector Status and Control Register (NJ/SAT bits). |
| `VD` | mfvscr: write | Destination vector register. |
## Register Effects
### `mfvscr`
- **Reads (always):** `VSCR`
- **Reads (conditional):** _none_
- **Writes (always):** `VD`
- **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
**`mfvscr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mfvscr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_altivec.cc:303`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_altivec.cc#L303)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:53`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L53)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:539`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L539)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:2506-2513`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L2506-L2513)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mfvscr => {
// PPCBUG-080: ISA places VSCR in the rightmost word of VD with
// bytes 0-11 zeroed. Previously the full 128-bit ctx.vscr was
// copied (leaking stale upper data to guest).
let vscr_word = ctx.vscr.as_u32x4()[3];
ctx.vr[instr.rd()] = xenia_types::Vec128::from_u32x4_array([0, 0, 0, vscr_word]);
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Reads the 32-bit Vector Status and Control Register (VSCR) into the **low 32 bits of the rightmost word** of `VD` (the 128-bit vector register). The other 96 bits of `VD` are zeroed. PowerISA places the result at byte offset 12..15 (big-endian within the 128-bit register).
- **VSCR contents (Xenon-relevant).**
| Bit | Name | Meaning |
| --- | --- | --- |
| 16 | NJ | Non-Java mode (denormal handling for IEEE-754 single-prec vector ops) |
| 31 | SAT | Saturation — sticky; set whenever a saturating vector op clamps |
All other bits are reserved (zero).
- **`SAT` is sticky.** Once a saturating vector instruction clamps a result, `VSCR[SAT]` becomes 1 and stays 1 until explicitly cleared via [`mtvscr`](mtvscr.md). Software polls it after a vector batch to detect overflow.
- **`NJ` controls denormals.** When `NJ=1` (the Xenon's default), AltiVec single-precision ops flush denormal inputs/outputs to zero (non-IEEE behaviour); `NJ=0` enforces full IEEE.
- **VRSAVE.** Writing the entire 128-bit `VD` consumes a vector register slot; software wishing to honour [`VRSAVE`](mtspr.md) bookkeeping should ensure the chosen `VD` is in the live mask.
- **xenia simplification.** xenia-rs stores VSCR as a single value of the same `vr` type (effectively a u128) and copies it directly into `ctx.vr[VD]`. Saturating ops in xenia-rs **do** maintain SAT correctly for the vector ops that are implemented; NJ is honoured for the denormal-flush paths but its effect is small in practice.
- **Not synchronising.**
## Related Instructions
- [`mtvscr`](mtvscr.md) — write VSCR from a vector register (the inverse).
- [`mfspr`](mfspr.md) — for non-vector status registers; VSCR has its own opcode.
- AltiVec saturating-arithmetic ops (e.g., `vaddubs`, `vsubuhs`) — primary writers of `VSCR[SAT]`.
`mfvscr` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mfvscr` (Move from VSCR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mfvscr-move-from-vector-status-control-register-instruction)
- PowerISA v2.07B, Book I §6.6 — VSCR layout and the SAT / NJ definitions.

View File

@@ -0,0 +1,136 @@
# `mtcrf` — Move to Condition Register Fields
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XFX](../forms/XFX.md) · **Opcode:** `0x7c000120`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtcrf` | `mtcrf` | — | Move to Condition Register Fields |
## Syntax
```asm
mtcrf [CRM], [RS]
```
## Encoding
### `mtcrf` — form `XFX`
- **Opcode word:** `0x7c000120`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `144`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (31) |
| 610 | `RT` | destination / source GPR |
| 1120 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
| 2130 | `XO` | extended opcode |
| 31 | `—` | reserved |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `RS` | mtcrf: read | Source GPR (alias for RD in some stores). |
| `CRM` | mtcrf: write | 8-bit CR field mask used by `mtcrf` — one bit per CR field. |
## Register Effects
### `mtcrf`
- **Reads (always):** `RS`
- **Reads (conditional):** _none_
- **Writes (always):** `CRM`
- **Writes (conditional):** _none_
## Status-Register Effects
_No condition-register or status-register effects._
## Operation (pseudocode)
```
for i in 0..7:
if CRM[i] then CR[i] <- (RS)[32+i*4 : 35+i*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
**`mtcrf`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtcrf"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:732`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L732)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:779`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L779)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1631-1644`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1631-L1644)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtcrf => {
let crm = instr.crm();
let val = ctx.gpr[instr.rs()] as u32;
let old = ctx.cr();
let mut new = old;
for i in 0..8u32 {
if crm & (1 << (7 - i)) != 0 {
let mask = 0xF << (28 - i * 4);
new = (new & !mask) | (val & mask);
}
}
ctx.set_cr(new);
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **`CRM` is an 8-bit field-mask, MSB-first.** Each bit of `CRM` corresponds to one CR field: `CRM[0]` (mask bit `0x80`) selects CR0, `CRM[1]` (`0x40`) selects CR1, …, `CRM[7]` (`0x01`) selects CR7. Each *set* mask bit causes the corresponding 4-bit slice of `RS[32:63]` to overwrite that CR field; clear mask bits leave the field untouched.
- **Slice positions inside `RS`.** Big-endian: bits 32..35 of `RS` map to CR0, bits 36..39 to CR1, …, bits 60..63 to CR7. The high 32 bits of `RS` are ignored.
- **`mtcr RS` simplified mnemonic.** When `CRM = 0xFF`, all eight CR fields are written; assemblers fold this into `mtcr RS`. This is the dominant form (function epilogue restoring the saved CR).
- **`mtocrf` variant.** PowerISA defines `mtocrf` as the single-field variant — encoded with the high bit of FXM set and exactly one CRM bit set. xenia-rs treats both as the same opcode and processes whatever `CRM` mask is present, so `mtocrf` works correctly without special handling.
- **Use case in ABI.** Save/restore non-volatile CR fields (CR2, CR3, CR4 on the Xbox 360 ABI). The standard restore is `lwz r12, 8(r1); mtcrf 0x38, r12``0x38` = bits for CR2|CR3|CR4 — preserving the volatile fields the callee may have already updated.
- **No CR0 / XER side effects.** `mtcrf` does not record into CR0; XER is untouched.
- **xenia exact match.** xenia-rs decomposes the CR into a `u32`, applies a per-field mask, and reassembles via `set_cr`. The 8-bit `CRM` walk matches the spec exactly.
- **Not synchronising.** Reorderable.
## Related Instructions
- [`mfcr`](mfcr.md) — read the entire CR into a GPR.
- [`mcrf`](mcrf.md) — copy one CR field to another (no GPR involved).
- [`mcrxr`](mcrxr.md), [`mcrfs`](mcrfs.md) — narrower CR-field moves from XER / FPSCR.
- [`crand`](crand.md), [`cror`](cror.md), … — bit-level CR manipulation.
### Simplified Mnemonics
| Simplified | Expansion | Notes |
| --- | --- | --- |
| `mtcr RS` | `mtcrf 0xFF, RS` | write all eight CR fields from low half of RS |
`mtocrf RS, FXM` is a related encoding handled by the same xenia-rs slot.
## IBM Reference
- [AIX 7.3 — `mtcrf` (Move to Condition Register Fields)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtcrf-move-condition-register-fields-instruction)
- [AIX 7.3 — Condition register simplified mnemonics](https://www.ibm.com/docs/en/aix/7.3.0?topic=mnemonics-condition-register-logical-simplified)

View File

@@ -0,0 +1,133 @@
# `mtfsb0x` — Move to FPSCR Bit 0
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0xfc00008c`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtfsb0` | `mtfsb0x` | — | Move to FPSCR Bit 0 |
| `mtfsb0.` | `mtfsb0x` | Rc=1 | Move to FPSCR Bit 0 |
## Syntax
```asm
mtfsb0[Rc] [FPSCRD]
```
## Encoding
### `mtfsb0x` — form `X`
- **Opcode word:** `0xfc00008c`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `70`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `FPSCRD` | mtfsb0x: write | FPSCR destination field. |
| `CR` | mtfsb0x: write (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
## Register Effects
### `mtfsb0x`
- **Reads (always):** _none_
- **Reads (conditional):** _none_
- **Writes (always):** `FPSCRD`
- **Writes (conditional):** `CR`
## Status-Register Effects
- `mtfsb0x`: **CR0** ← signed-compare(result, 0) with `SO ← XER[SO]`, when `Rc=1`.
## 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
**`mtfsb0x`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtfsb0x"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:406`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L406)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:905`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L905)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:3055-3061`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L3055-L3061)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtfsb0x => {
// Clear FPSCR bit crbd
let bit = instr.crbd();
ctx.fpscr &= !(1 << (31 - bit));
if instr.rc_bit() { update_cr1_from_fpscr(ctx); }
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Clears (sets to 0) **a single named bit** of the 32-bit FPSCR. The bit is selected by `FPSCRD` (a 5-bit absolute index 0..31, big-endian: 0 = MSB = FX).
- **The mnemonic name "Bit 0" is misleading.** "0" refers to the *value being written*, not to bit position 0. Pair with [`mtfsb1x`](mtfsb1x.md) which writes a 1.
- **Restricted bits.** Per PowerISA, `mtfsb0` cannot clear bits 1 (FEX) or 2 (VX) — those are summary bits, derived from other FPSCR bits. xenia-rs does **not** enforce this restriction; it will happily flip any bit. In practice no Xbox 360 title relies on the restriction's enforcement.
- **`Rc=1`.** `mtfsb0.` (`Rc=1`) updates **CR1** with the high four FPSCR bits (FX, FEX, VX, OX) after the clear. This is the FPU's record-form analogue.
- **Common use.** Reset a sticky exception bit ahead of a sequence of FP ops you want to monitor (e.g. `mtfsb0 5` to clear ZX before a divide series, then read it back).
- **xenia simplification.** xenia-rs maintains FPSCR as a `u32` and does the bit clear correctly, but most downstream FP instructions in xenia **do not update** FPSCR exception bits — so monitoring them after `mtfsb0` will see the bits stay at their seed value. Acceptable for titles that use FPSCR only to manage rounding / non-exception state.
- **Not synchronising.** Reorderable.
## Related Instructions
- [`mtfsb1x`](mtfsb1x.md) — set a single FPSCR bit to 1.
- [`mtfsfx`](mtfsfx.md) — write fields of FPSCR from an FPR.
- [`mtfsfix`](mtfsfix.md) — write a 4-bit immediate into one FPSCR field.
- [`mffsx`](mffsx.md) — read FPSCR.
- [`mcrfs`](mcrfs.md) — copy FPSCR field → CR field (and clear sticky bits).
`mtfsb0` is itself the simplified form (`Rc=0`); `mtfsb0.` is the recording variant.
## IBM Reference
- [AIX 7.3 — `mtfsb0` (Move to FPSCR Bit 0)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtfsb0-move-fpscr-bit-0-instruction)
- PowerISA v2.07B, Book I §4.6 — FPSCR bit definitions and the FX/FEX/VX restriction.

View File

@@ -0,0 +1,133 @@
# `mtfsb1x` — Move to FPSCR Bit 1
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0xfc00004c`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtfsb1` | `mtfsb1x` | — | Move to FPSCR Bit 1 |
| `mtfsb1.` | `mtfsb1x` | Rc=1 | Move to FPSCR Bit 1 |
## Syntax
```asm
mtfsb1[Rc] [FPSCRD]
```
## Encoding
### `mtfsb1x` — form `X`
- **Opcode word:** `0xfc00004c`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `38`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `FPSCRD` | mtfsb1x: write | FPSCR destination field. |
| `CR` | mtfsb1x: write (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
## Register Effects
### `mtfsb1x`
- **Reads (always):** _none_
- **Reads (conditional):** _none_
- **Writes (always):** `FPSCRD`
- **Writes (conditional):** `CR`
## Status-Register Effects
- `mtfsb1x`: **CR0** ← signed-compare(result, 0) with `SO ← XER[SO]`, when `Rc=1`.
## 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
**`mtfsb1x`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtfsb1x"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:411`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L411)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:902`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L902)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:3062-3068`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L3062-L3068)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtfsb1x => {
// Set FPSCR bit crbd
let bit = instr.crbd();
ctx.fpscr |= 1 << (31 - bit);
if instr.rc_bit() { update_cr1_from_fpscr(ctx); }
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Sets (writes 1 to) **a single named bit** of FPSCR. `FPSCRD` is a 5-bit absolute index (0..31), big-endian (0 = MSB = FX).
- **Mnemonic name.** "1" denotes the *value written*, not bit position. Pair with [`mtfsb0x`](mtfsb0x.md) for clears.
- **Restricted bits.** PowerISA forbids `mtfsb1` from setting FEX (bit 1) or VX (bit 2) directly — both are summary bits derived from other state. `mtfsb1` *can* set FX (bit 0), which is itself a sticky summary; this is occasionally used to force a `Program` interrupt for testing. xenia-rs does **not** enforce the restriction; setting summary bits will stick until cleared explicitly.
- **`Rc=1`.** `mtfsb1.` (`Rc=1`) updates CR1 with the high four FPSCR bits (FX, FEX, VX, OX) after the set.
- **Common use.** Force-set a sticky exception bit to test exception-handling code paths. Also seen in floating-point library setup that wants a known FPSCR seed.
- **xenia simplification.** Same caveat as `mtfsb0`: xenia maintains FPSCR but most FP paths don't read it, so the set has limited downstream effect. The bit will read back correctly via [`mffsx`](mffsx.md).
- **Not synchronising.** Reorderable.
## Related Instructions
- [`mtfsb0x`](mtfsb0x.md) — clear a single FPSCR bit.
- [`mtfsfx`](mtfsfx.md) — write 4-bit FPSCR fields from an FPR.
- [`mtfsfix`](mtfsfix.md) — write 4-bit immediate into a single FPSCR field.
- [`mffsx`](mffsx.md) — read FPSCR.
- [`mcrfs`](mcrfs.md) — FPSCR field → CR field (clears sticky bits).
`mtfsb1` is the simplified form (`Rc=0`); `mtfsb1.` is the recording variant.
## IBM Reference
- [AIX 7.3 — `mtfsb1` (Move to FPSCR Bit 1)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtfsb1-move-fpscr-bit-1-instruction)
- PowerISA v2.07B, Book I §4.6 — FPSCR bit definitions and FX/FEX/VX restriction.

View File

@@ -0,0 +1,135 @@
# `mtfsfix` — Move to FPSCR Field Immediate
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0xfc00010c`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtfsfi` | `mtfsfix` | — | Move to FPSCR Field Immediate |
| `mtfsfi.` | `mtfsfix` | Rc=1 | Move to FPSCR Field Immediate |
## Syntax
```asm
mtfsfi[Rc] [CRFD], [IMM]
```
## Encoding
### `mtfsfix` — form `X`
- **Opcode word:** `0xfc00010c`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `134`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `IMM` | mtfsfix: read | Generic immediate field. |
| `CRFD` | mtfsfix: write | CR destination field (`crf`, 07). |
| `CR` | mtfsfix: write (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
## Register Effects
### `mtfsfix`
- **Reads (always):** `IMM`
- **Reads (conditional):** _none_
- **Writes (always):** `CRFD`
- **Writes (conditional):** `CR`
## Status-Register Effects
- `mtfsfix`: **CR0** ← signed-compare(result, 0) with `SO ← XER[SO]`, when `Rc=1`.
## 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
**`mtfsfix`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtfsfix"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:452`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L452)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:907`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L907)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:3069-3077`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L3069-L3077)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtfsfix => {
// Move to FPSCR field immediate: crfD = IMM (4 bits)
let crfd = instr.crfd();
let imm = (instr.raw >> 12) & 0xF;
let shift = 28 - crfd as u32 * 4;
ctx.fpscr = (ctx.fpscr & !(0xF << shift)) | (imm << shift);
if instr.rc_bit() { update_cr1_from_fpscr(ctx); }
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Loads a **4-bit immediate** (`IMM`, encoded in instruction bits 16..19) into a single FPSCR field selected by `CRFD` (3-bit, 0..7). All other FPSCR fields are preserved.
- **Most common use: rounding-mode set.** `mtfsfi 7, 0` selects round-to-nearest, `mtfsfi 7, 1` round-toward-zero, `mtfsfi 7, 2` round-toward-+∞, `mtfsfi 7, 3` round-toward-−∞. The four immediate values map to RN per IEEE-754. Compilers emit this when transitioning into and out of strict-IEEE regions.
- **No FPR source.** Unlike [`mtfsfx`](mtfsfx.md), `mtfsfi` doesn't need an FPR — it carries its 4-bit value in the instruction word, making it cheaper for constant updates.
- **`Rc=1`.** `mtfsfi.` copies FPSCR's top 4 bits (FX, FEX, VX, OX) into CR1 after the write.
- **Restrictions in newer PowerISA.** v2.05+ disallows writing FEX/VX (summary bits) via `mtfsfi`. xenia-rs does **not** enforce this — the immediate goes straight into the chosen field.
- **xenia simplification.** xenia stores FPSCR as a `u32` and applies the field-shift correctly. Same caveat as `mtfsf`: most xenia FP paths don't honour FPSCR, so the rounding-mode change is architecturally visible (via [`mffsx`](mffsx.md)) but typically does not change subsequent FP results.
- **Not synchronising.** PowerISA recommends `isync` after rounding-mode changes if subsequent FP correctness depends on the new mode.
## Related Instructions
- [`mtfsfx`](mtfsfx.md) — write FPSCR fields from an FPR (uses 8-bit field-mask).
- [`mtfsb0x`](mtfsb0x.md), [`mtfsb1x`](mtfsb1x.md) — clear / set a single FPSCR bit.
- [`mffsx`](mffsx.md) — read FPSCR.
- [`mcrfs`](mcrfs.md) — FPSCR field → CR field (also clears sticky bits).
`mtfsfi` is the simplified form (`Rc=0`); `mtfsfi.` is the recording variant.
## IBM Reference
- [AIX 7.3 — `mtfsfi` (Move to FPSCR Field Immediate)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtfsfi-move-fpscr-field-immediate-instruction)
- PowerISA v2.07B, Book I §4.6.6 — FPSCR-field write semantics and the FEX/VX restriction.

View File

@@ -0,0 +1,142 @@
# `mtfsfx` — Move to FPSCR Fields
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XFL](../forms/XFL.md) · **Opcode:** `0xfc00058e`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtfsf` | `mtfsfx` | — | Move to FPSCR Fields |
| `mtfsf.` | `mtfsfx` | Rc=1 | Move to FPSCR Fields |
## Syntax
```asm
mtfsf[Rc] [FM], [FB]
```
## Encoding
### `mtfsfx` — form `XFL`
- **Opcode word:** `0xfc00058e`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `711`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (63) |
| 6 | `L` | field-select behaviour |
| 714 | `FM` | FPSCR field mask |
| 15 | `W` | immediate-value flag |
| 1620 | `FRB` | source FPR |
| 2130 | `XO` | extended opcode |
| 31 | `Rc` | record-form flag (updates CR1) |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `FM` | mtfsfx: read | 8-bit FPSCR field-mask used by `mtfsf`. |
| `FB` | mtfsfx: read | Source B floating-point register. |
| `FPSCR` | mtfsfx: write | Floating-Point Status and Control Register. |
| `CR` | mtfsfx: write (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
## Register Effects
### `mtfsfx`
- **Reads (always):** `FM`, `FB`
- **Reads (conditional):** _none_
- **Writes (always):** `FPSCR`
- **Writes (conditional):** `CR`
## Status-Register Effects
- `mtfsfx`: **CR1** ← FPSCR[FX, FEX, VX, OX] when `Rc=1`.; **FPSCR** updated per IEEE-754 flags (FX, FEX, FPRF, FR, FI, exceptions).
## 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
**`mtfsfx`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtfsfx"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:416`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L416)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:911`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L911)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:3041-3054`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L3041-L3054)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtfsfx => {
// Move to FPSCR fields: fm mask in bits 7-14, frB value
let fm = (instr.raw >> 17) & 0xFF;
let val = ctx.fpr[instr.rb()].to_bits() as u32;
let mut mask = 0u32;
for i in 0..8 {
if fm & (1 << (7 - i)) != 0 {
mask |= 0xF << (28 - i * 4);
}
}
ctx.fpscr = (ctx.fpscr & !mask) | (val & mask);
if instr.rc_bit() { update_cr1_from_fpscr(ctx); }
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **`FM` is an 8-bit field-mask.** Each of the eight bits selects one 4-bit FPSCR field (0..7). `FM[0]` (`0x80`) selects FPSCR field 0 (bits 0..3 = FX, FEX, VX, OX), …, `FM[7]` (`0x01`) selects FPSCR field 7 (rounding-mode bits RN). Set bits cause that field of `FRB`'s low 32 bits to overwrite the corresponding FPSCR field; clear bits leave the field unchanged.
- **Source is the LOW 32 bits of `FRB`.** The high 32 bits are ignored. Software that wants to write a 32-bit pattern typically constructs it in a GPR, stores to memory, and reloads as a double via [`lfd`](../memory/lfd.md).
- **Most common use: setting rounding mode.** Compilers wrap calls to `<fenv.h>`-style functions with `mtfsf 1, fX` to update only the rounding-mode field (RN, FPSCR field 7).
- **`Rc=1` updates CR1.** `mtfsf.` copies FPSCR's top 4 bits (FX, FEX, VX, OX) into CR1 after the write.
- **`L`/`W` bits.** PowerISA v2.05+ adds `L=1` to mean "write all FPSCR bits regardless of FM" and `W=1` to select the upper or lower 32 bits. xenia-rs **ignores** `L` and `W` (always treats `L=0, W=0`), which matches every real Xbox 360 use.
- **xenia simplification.** xenia maintains FPSCR as a `u32` and applies the field mask correctly. However, most FP instructions in xenia don't *read* FPSCR (e.g., divides ignore the rounding mode), so the architecturally-set rounding mode often has no actual effect on results. Acceptable for the title set xenia targets.
- **Not synchronising.** Reorderable; PowerISA recommends an `isync` after FPSCR changes that affect subsequent FP behaviour.
## Related Instructions
- [`mtfsfix`](mtfsfix.md) — write a 4-bit immediate into one FPSCR field (no FPR source needed).
- [`mtfsb0x`](mtfsb0x.md), [`mtfsb1x`](mtfsb1x.md) — single-bit FPSCR write.
- [`mffsx`](mffsx.md) — read FPSCR into an FPR.
- [`mcrfs`](mcrfs.md) — copy FPSCR field → CR field.
`mtfsf` is the simplified form (`Rc=0`); `mtfsf.` is the recording variant.
## IBM Reference
- [AIX 7.3 — `mtfsf` (Move to FPSCR Fields)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtfsf-move-fpscr-fields-instruction)
- PowerISA v2.07B, Book I §4.6.6 — `mtfsf` definition and `L`/`W` extensions.

View File

@@ -0,0 +1,139 @@
# `mtmsr` — Move to Machine State Register
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c000124` · _sync_
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtmsr` | `mtmsr` | — | Move to Machine State Register |
## Syntax
```asm
mtmsr [RS]
```
## Encoding
### `mtmsr` — form `X`
- **Opcode word:** `0x7c000124`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `146`
- **Synchronising:** yes
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `RS` | mtmsr: read | Source GPR (alias for RD in some stores). |
| `MSR` | mtmsr: write | Machine State Register. |
## Register Effects
### `mtmsr`
- **Reads (always):** `RS`
- **Reads (conditional):** _none_
- **Writes (always):** `MSR`
- **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
**`mtmsr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtmsr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:822`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L822)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:780`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L780)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1649-1663`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1649-L1663)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtmsr | PpcOpcode::mtmsrd => {
// PPCBUG-078: mtmsrd L=1 is a partial-MSR-write — only MSR[EE]
// (u64 bit 15) and MSR[RI] (u64 bit 0) are modified; all other
// MSR bits preserved. Used by kernel code to re-enable external
// interrupts without disturbing the rest of the MSR.
let l = (instr.raw >> (31 - 15)) & 1;
let rs = ctx.gpr[instr.rs()];
if matches!(instr.opcode, PpcOpcode::mtmsrd) && l == 1 {
let mask: u64 = (1u64 << 15) | 1u64;
ctx.msr = (ctx.msr & !mask) | (rs & mask);
} else {
ctx.msr = rs;
}
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Privileged.** `mtmsr` is supervisor-only on real hardware. Executing it from problem state raises a Privileged Instruction interrupt. Game code never emits it; only the kernel and exception-return paths use it.
- **32-bit form.** `mtmsr` writes the **low 32 bits** of MSR (legacy PPC32 form). On the Xenon (a PPC64 implementation), use [`mtmsrd`](mtmsrd.md) for the full 64-bit MSR. Some Xenon kernel sequences still use `mtmsr` to leave the high half untouched while flipping low-half flags like EE/PR.
- **Synchronisation.** Marked `sync``mtmsr` is **execution-synchronising**. The Xenon must drain all preceding instructions before the new MSR takes effect, and PowerISA recommends a following `isync` to guarantee subsequent instructions execute under the new MSR.
- **`L` operand.** Modern PowerISA defines an `L` bit selecting "EE/RI only" (`L=1`) versus "all" (`L=0`); xenia-rs ignores `L` and writes the entire MSR. Real Xbox 360 kernel code uses both `L=0` and `L=1`.
- **xenia model.** Treats MSR as a flat `u64` field. Both `mtmsr` and `mtmsrd` execute the same body — `ctx.msr = ctx.gpr[rs]`. No privilege or atomicity is enforced; no side effects on TLB / interrupt mask / endianness are simulated.
- **No CR / XER side effects.**
- **Caveat for translators.** Because the host kernel runs natively in xenia, the guest MSR has no architectural meaning beyond storage. Code that reads it back via [`mfmsr`](mfmsr.md) will see exactly what was last written.
## Related Instructions
- [`mfmsr`](mfmsr.md) — read MSR.
- [`mtmsrd`](mtmsrd.md) — 64-bit form (writes the entire MSR).
- [`sc`](../branch/sc.md) — kernel entry; the kernel handler typically uses `mtmsr`/`rfid` to return.
- [`isync`](mtmsr.md) — companion fence after MSR writes.
`mtmsr` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mtmsr` (Move to Machine State Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtmsr-move-machine-state-register-instruction)
- PowerISA v2.07B, Book III §4.3.1 — MSR field definitions and `L`-bit semantics.

View File

@@ -0,0 +1,138 @@
# `mtmsrd` — Move to Machine State Register Doubleword
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0x7c000164` · _sync_
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtmsrd` | `mtmsrd` | — | Move to Machine State Register Doubleword |
## Syntax
```asm
mtmsrd [RS]
```
## Encoding
### `mtmsrd` — form `X`
- **Opcode word:** `0x7c000164`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `178`
- **Synchronising:** yes
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `RS` | mtmsrd: read | Source GPR (alias for RD in some stores). |
| `MSR` | mtmsrd: write | Machine State Register. |
## Register Effects
### `mtmsrd`
- **Reads (always):** `RS`
- **Reads (conditional):** _none_
- **Writes (always):** `MSR`
- **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
**`mtmsrd`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtmsrd"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:827`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L827)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:785`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L785)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1649-1663`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1649-L1663)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtmsr | PpcOpcode::mtmsrd => {
// PPCBUG-078: mtmsrd L=1 is a partial-MSR-write — only MSR[EE]
// (u64 bit 15) and MSR[RI] (u64 bit 0) are modified; all other
// MSR bits preserved. Used by kernel code to re-enable external
// interrupts without disturbing the rest of the MSR.
let l = (instr.raw >> (31 - 15)) & 1;
let rs = ctx.gpr[instr.rs()];
if matches!(instr.opcode, PpcOpcode::mtmsrd) && l == 1 {
let mask: u64 = (1u64 << 15) | 1u64;
ctx.msr = (ctx.msr & !mask) | (rs & mask);
} else {
ctx.msr = rs;
}
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Privileged.** Like [`mtmsr`](mtmsr.md), supervisor-only. Game code never emits it.
- **64-bit form.** Writes all 64 MSR bits — including `MSR[SF]` (bit 0) which selects 64-bit mode, `MSR[HV]` (bit 3, hypervisor), `MSR[EE]` (32, external interrupts), `MSR[PR]` (33, problem state), `MSR[FP]` (34), `MSR[ME]` (35, machine-check enable), `MSR[DR]`/`MSR[IR]` (data/instruction translation, 38/39), `MSR[RI]` (63, recoverable interrupt). On the Xenon kernel this is the canonical MSR-write instruction.
- **`L` operand.** Same `L`-bit selector as `mtmsr`: `L=1` updates only `MSR[EE]` and `MSR[RI]`; `L=0` updates the full register. xenia-rs ignores `L` and always writes the full doubleword (matching the typical kernel use).
- **Synchronisation.** Marked `sync` — execution-synchronising. PowerISA recommends `isync` afterwards if subsequent fetch / data semantics depend on the new MSR.
- **xenia model.** Shares one interpreter arm with `mtmsr`: `ctx.msr = ctx.gpr[rs]`. No architectural side effects beyond writing the storage; no privilege check.
- **No CR / XER updates.**
- **Used in interrupt return paths.** Kernel handlers commonly write SRR1 (saved MSR) into MSR via `mtmsrd` followed by `rfid` to atomically restore state and jump to SRR0.
## Related Instructions
- [`mfmsr`](mfmsr.md) — read MSR.
- [`mtmsr`](mtmsr.md) — 32-bit form (low half only).
- [`sc`](../branch/sc.md) — kernel entry; the kernel typically pairs `mtmsrd` + `rfid` to return.
`mtmsrd` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mtmsrd` (Move to Machine State Register Doubleword)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtmsrd-move-machine-state-register-doubleword-instruction)
- PowerISA v2.07B, Book III §4.3.1 — MSR field definitions, `L`-bit semantics, and 64-bit-mode rules.

View File

@@ -0,0 +1,161 @@
# `mtspr` — Move to Special-Purpose Register
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [XFX](../forms/XFX.md) · **Opcode:** `0x7c0003a6`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtspr` | `mtspr` | — | Move to Special-Purpose Register |
## Syntax
```asm
mtspr [SPR], [RS]
```
## Encoding
### `mtspr` — form `XFX`
- **Opcode word:** `0x7c0003a6`
- **Primary opcode (bits 05):** `31`
- **Extended opcode:** `467`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (31) |
| 610 | `RT` | destination / source GPR |
| 1120 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
| 2130 | `XO` | extended opcode |
| 31 | `—` | reserved |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `RS` | mtspr: read | Source GPR (alias for RD in some stores). |
| `SPR` | mtspr: write | Special-Purpose-Register number. Encoded with the two 5-bit halves swapped (bits 11-15 become the high half, bits 16-20 the low half). |
## Register Effects
### `mtspr`
- **Reads (always):** `RS`
- **Reads (conditional):** _none_
- **Writes (always):** `SPR`
- **Writes (conditional):** _none_
## Status-Register Effects
_No condition-register or status-register effects._
## Operation (pseudocode)
```
n <- spr_number(SPR)
SPR(n) <- (RS)
```
## 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
**`mtspr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtspr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_control.cc:771`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_control.cc#L771)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:810`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L810)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1596-1626`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1596-L1626)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtspr => {
let spr = instr.spr();
let val = ctx.gpr[instr.rs()];
match spr {
crate::context::spr::XER => ctx.set_xer(val as u32),
crate::context::spr::LR => ctx.lr = val,
crate::context::spr::CTR => ctx.ctr = val as u32 as u64,
crate::context::spr::DEC => ctx.dec = val as u32,
crate::context::spr::TBL_WRITE => {
ctx.timebase = (ctx.timebase & 0xFFFF_FFFF_0000_0000) | (val & 0xFFFF_FFFF);
}
crate::context::spr::TBU_WRITE => {
ctx.timebase = (ctx.timebase & 0x0000_0000_FFFF_FFFF) | ((val & 0xFFFF_FFFF) << 32);
}
crate::context::spr::VRSAVE => ctx.vrsave = val as u32,
// Benign writes — swallow silently to avoid false Unimplemented
// warnings on SPRs that have no observable effect in userspace.
crate::context::spr::SPRG0
| crate::context::spr::SPRG1
| crate::context::spr::SPRG2
| crate::context::spr::SPRG3
| crate::context::spr::HID0
| crate::context::spr::HID1
| crate::context::spr::DAR
| crate::context::spr::DSISR => {}
_ => {
tracing::warn!("mtspr: unimplemented SPR {}", spr);
}
}
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **SPR halves are swapped in the encoding.** As with [`mfspr`](mfspr.md), the 10-bit `spr` field stores the two 5-bit halves transposed. Software always names the *logical* SPR number; assemblers handle the swap. Decoded number `n = ((field & 0x1F) << 5) | ((field >> 5) & 0x1F)`.
- **SPRs writable from userspace (Xenon, modelled by xenia).**
| Decoded # | Name | Effect |
| --- | --- | --- |
| 1 | XER | unpacked into `ctx.xer_so/xer_ov/xer_ca` and length field |
| 8 | LR | `ctx.lr ← RS` |
| 9 | CTR | `ctx.ctr ← RS` |
| 256 | VRSAVE | `ctx.vrsave ← RS & 0xFFFFFFFF` |
- **SPRs xenia silently swallows (no observable effect).** SPRG0..3, HID0, HID1, DAR, DSISR — these are kernel/diagnostic registers; xenia accepts the write to avoid spurious "unimplemented SPR" warnings, but the value is discarded.
- **Privileged SPRs.** On real hardware, writes to MSR-visible kernel SPRs (SPRG0..3, HID0/1, DSISR, DAR, PIR, etc.) require supervisor mode and trap from problem state. xenia does **not** enforce privilege.
- **Time-base writes are privileged.** `mtspr 268/269` (TBL/TBU) only works in supervisor mode on real hardware. xenia will warn `mtspr: unimplemented SPR` for these — do **not** assume the time base can be guest-written.
- **Simplified mnemonics.** `mtxer RS``mtspr 1, RS`, `mtlr RS``mtspr 8, RS`, `mtctr RS``mtspr 9, RS`. These dominate Xbox 360 disassembly.
- **No CR / XER side effects.** `mtspr` itself doesn't record (the *target* SPR may itself be XER, in which case XER is being directly overwritten).
- **Not synchronising.** xenia's XML omits the `sync` flag; PowerISA does require some `mtspr` cases (e.g. SDR1, MMU regs) to be context-synchronising — none of them appear in title binaries.
## Related Instructions
- [`mfspr`](mfspr.md) — inverse: read an SPR into a GPR.
- [`mftb`](mftb.md) — read time-base (preferred over `mfspr TBL/TBU`).
- [`mtmsr`](mtmsr.md), [`mtmsrd`](mtmsrd.md) — write MSR (separate opcode).
- [`mcrxr`](mcrxr.md) — sample-and-clear XER's overflow/carry bits.
### Simplified Mnemonics
| Simplified | Expansion |
| --- | --- |
| `mtxer RS` | `mtspr 1, RS` |
| `mtlr RS` | `mtspr 8, RS` |
| `mtctr RS` | `mtspr 9, RS` |
## IBM Reference
- [AIX 7.3 — `mtspr` (Move to Special Purpose Register)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtspr-move-special-purpose-register-instruction)
- PowerISA v2.07B, Book III §4 — SPR number table and privilege rules.

View File

@@ -0,0 +1,125 @@
# `mtvscr` — Move to VSCR
> **Category:** [Control / CR / SPR](../categories/control.md) · **Form:** [VX](../forms/VX.md) · **Opcode:** `0x10000644`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `mtvscr` | `mtvscr` | — | Move to VSCR |
## Syntax
```asm
(no disassembly template)
```
## Encoding
### `mtvscr` — form `VX`
- **Opcode word:** `0x10000644`
- **Primary opcode (bits 05):** `4`
- **Extended opcode:** `1604`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode (4) |
| 610 | `VRT/VD` | destination vector register |
| 1115 | `VRA/VA` | source A vector register |
| 1620 | `VRB/VB` | source B vector register |
| 2131 | `XO` | extended opcode (11 bits) |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `VB` | mtvscr: read | Source B vector register. |
| `VSCR` | mtvscr: write | Vector Status and Control Register (NJ/SAT bits). |
## Register Effects
### `mtvscr`
- **Reads (always):** `VB`
- **Reads (conditional):** _none_
- **Writes (always):** `VSCR`
- **Writes (conditional):** _none_
## Status-Register Effects
- `mtvscr`: **VSCR[SAT]** may be stickied on saturating vector operations.
## 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
**`mtvscr`**
- xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="mtvscr"`](../../xenia-canary/tools/ppc-instructions.xml)
- xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_altivec.cc:310`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_altivec.cc#L310)
- xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:55`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L55)
- xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:542`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L542)
- xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:2514-2517`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L2514-L2517)
<details><summary>xenia-rs interpreter body (frozen snapshot)</summary>
```rust
PpcOpcode::mtvscr => {
ctx.vscr = ctx.vr[instr.rb()];
ctx.pc += 4;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Operation.** Reads the **low 32 bits of the rightmost word** of `VB` (bytes 12..15 in big-endian) and stores them into VSCR. Other bits of `VB` are ignored.
- **Bits actually significant.** Of the 32 source bits, only **NJ (bit 16)** and **SAT (bit 31)** are architecturally meaningful on the Xenon. All other bits should be written as zero; behaviour for non-zero values is implementation-defined.
- **Clearing SAT.** The dominant use is `mtvscr vN` with `vN` zeroed via `vxor vN, vN, vN`, which writes VSCR=0 and thereby clears the sticky SAT bit before a fresh batch of saturating vector ops.
- **Setting NJ.** Switching to/from "Java mode" (`NJ=0`, full IEEE denormal handling) versus "Non-Java mode" (`NJ=1`, flush-to-zero) is the other meaningful use. Game audio / DSP code occasionally toggles this to match a precise IEEE expectation.
- **xenia simplification.** xenia-rs stores VSCR identically to a vector register and copies the source straight in: `ctx.vscr = ctx.vr[VB]`. Subsequent xenia AltiVec ops do consult `VSCR[SAT]` for sticky updates, so the architecturally-relevant behaviour is preserved. NJ's flush-to-zero semantics are honoured by xenia's vector denormal paths.
- **Not synchronising.** PowerISA does not require `isync` after `mtvscr`, but library code occasionally pairs them as a defensive measure.
## Related Instructions
- [`mfvscr`](mfvscr.md) — read VSCR into a vector register (the inverse).
- AltiVec saturating ops (`vaddubs`, `vsubuhs`, …) — primary writers of `VSCR[SAT]`; `mtvscr` is the only way to clear it.
- [`mtspr`](mtspr.md) — for non-vector control registers; VSCR has its own opcode.
`mtvscr` has no simplified mnemonics.
## IBM Reference
- [AIX 7.3 — `mtvscr` (Move to VSCR)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-mtvscr-move-vector-status-control-register-instruction)
- PowerISA v2.07B, Book I §6.6 — VSCR layout, SAT / NJ semantics.