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:
127
migration/project-root/ppc-manual/control/crand.md
Normal file
127
migration/project-root/ppc-manual/control/crand.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `257`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | crand: read | CR source bit A (0–31). |
|
||||
| `CRBB` | crand: read | CR source bit B (0–31). |
|
||||
| `CRBD` | crand: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
119
migration/project-root/ppc-manual/control/crandc.md
Normal file
119
migration/project-root/ppc-manual/control/crandc.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `129`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | crandc: read | CR source bit A (0–31). |
|
||||
| `CRBB` | crandc: read | CR source bit B (0–31). |
|
||||
| `CRBD` | crandc: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
124
migration/project-root/ppc-manual/control/creqv.md
Normal file
124
migration/project-root/ppc-manual/control/creqv.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `289`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | creqv: read | CR source bit A (0–31). |
|
||||
| `CRBB` | creqv: read | CR source bit B (0–31). |
|
||||
| `CRBD` | creqv: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
121
migration/project-root/ppc-manual/control/crnand.md
Normal file
121
migration/project-root/ppc-manual/control/crnand.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `225`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | crnand: read | CR source bit A (0–31). |
|
||||
| `CRBB` | crnand: read | CR source bit B (0–31). |
|
||||
| `CRBD` | crnand: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
125
migration/project-root/ppc-manual/control/crnor.md
Normal file
125
migration/project-root/ppc-manual/control/crnor.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `33`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | crnor: read | CR source bit A (0–31). |
|
||||
| `CRBB` | crnor: read | CR source bit B (0–31). |
|
||||
| `CRBD` | crnor: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
125
migration/project-root/ppc-manual/control/cror.md
Normal file
125
migration/project-root/ppc-manual/control/cror.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `449`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | cror: read | CR source bit A (0–31). |
|
||||
| `CRBB` | cror: read | CR source bit B (0–31). |
|
||||
| `CRBD` | cror: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
121
migration/project-root/ppc-manual/control/crorc.md
Normal file
121
migration/project-root/ppc-manual/control/crorc.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `417`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | crorc: read | CR source bit A (0–31). |
|
||||
| `CRBB` | crorc: read | CR source bit B (0–31). |
|
||||
| `CRBD` | crorc: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
124
migration/project-root/ppc-manual/control/crxor.md
Normal file
124
migration/project-root/ppc-manual/control/crxor.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `193`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRBA` | crxor: read | CR source bit A (0–31). |
|
||||
| `CRBB` | crxor: read | CR source bit B (0–31). |
|
||||
| `CRBD` | crxor: write | CR destination bit (0–31). |
|
||||
|
||||
## 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)
|
||||
129
migration/project-root/ppc-manual/control/mcrf.md
Normal file
129
migration/project-root/ppc-manual/control/mcrf.md
Normal 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 0–5):** `19`
|
||||
- **Extended opcode:** `0`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (19) |
|
||||
| 6–10 | `BT/BO` | target / branch options |
|
||||
| 11–15 | `BA/BI` | source A / CR bit to test |
|
||||
| 16–20 | `BB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `LK` | link flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRFS` | mcrf: read | CR source field. |
|
||||
| `CRFD` | mcrf: write | CR destination field (`crf`, 0–7). |
|
||||
|
||||
## 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)
|
||||
155
migration/project-root/ppc-manual/control/mcrfs.md
Normal file
155
migration/project-root/ppc-manual/control/mcrfs.md
Normal 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 0–5):** `63`
|
||||
- **Extended opcode:** `64`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `CRFS` | mcrfs: read | CR source field. |
|
||||
| `FPSCR` | mcrfs: read; mcrfs: write | Floating-Point Status and Control Register. |
|
||||
| `CRFD` | mcrfs: write | CR destination field (`crf`, 0–7). |
|
||||
|
||||
## 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).
|
||||
145
migration/project-root/ppc-manual/control/mcrxr.md
Normal file
145
migration/project-root/ppc-manual/control/mcrxr.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `512`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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`, 0–7). |
|
||||
|
||||
## 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)
|
||||
117
migration/project-root/ppc-manual/control/mfcr.md
Normal file
117
migration/project-root/ppc-manual/control/mfcr.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `19`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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)
|
||||
132
migration/project-root/ppc-manual/control/mffsx.md
Normal file
132
migration/project-root/ppc-manual/control/mffsx.md
Normal 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 0–5):** `63`
|
||||
- **Extended opcode:** `583`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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.
|
||||
139
migration/project-root/ppc-manual/control/mfmsr.md
Normal file
139
migration/project-root/ppc-manual/control/mfmsr.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `83`
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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.
|
||||
179
migration/project-root/ppc-manual/control/mfspr.md
Normal file
179
migration/project-root/ppc-manual/control/mfspr.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `339`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (31) |
|
||||
| 6–10 | `RT` | destination / source GPR |
|
||||
| 11–20 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
|
||||
| 21–30 | `XO` | extended opcode |
|
||||
| 31 | `—` | 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` |
|
||||
| 272–275 | `SPRG0..3` | Software scratch registers (kernel) | returns 0 (stubbed) |
|
||||
| 287 | `PVR` | Processor-version register | `0x00710800` (Xenon signature) |
|
||||
| 1008–1009 | `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/)
|
||||
150
migration/project-root/ppc-manual/control/mftb.md
Normal file
150
migration/project-root/ppc-manual/control/mftb.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `371`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (31) |
|
||||
| 6–10 | `RT` | destination / source GPR |
|
||||
| 11–20 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
|
||||
| 21–30 | `XO` | extended opcode |
|
||||
| 31 | `—` | 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.
|
||||
137
migration/project-root/ppc-manual/control/mfvscr.md
Normal file
137
migration/project-root/ppc-manual/control/mfvscr.md
Normal 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 0–5):** `4`
|
||||
- **Extended opcode:** `1540`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (4) |
|
||||
| 6–10 | `VRT/VD` | destination vector register |
|
||||
| 11–15 | `VRA/VA` | source A vector register |
|
||||
| 16–20 | `VRB/VB` | source B vector register |
|
||||
| 21–31 | `XO` | extended opcode (11 bits) |
|
||||
|
||||
## 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.
|
||||
136
migration/project-root/ppc-manual/control/mtcrf.md
Normal file
136
migration/project-root/ppc-manual/control/mtcrf.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `144`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (31) |
|
||||
| 6–10 | `RT` | destination / source GPR |
|
||||
| 11–20 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
|
||||
| 21–30 | `XO` | extended opcode |
|
||||
| 31 | `—` | 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)
|
||||
133
migration/project-root/ppc-manual/control/mtfsb0x.md
Normal file
133
migration/project-root/ppc-manual/control/mtfsb0x.md
Normal 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 0–5):** `63`
|
||||
- **Extended opcode:** `70`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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.
|
||||
133
migration/project-root/ppc-manual/control/mtfsb1x.md
Normal file
133
migration/project-root/ppc-manual/control/mtfsb1x.md
Normal 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 0–5):** `63`
|
||||
- **Extended opcode:** `38`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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.
|
||||
135
migration/project-root/ppc-manual/control/mtfsfix.md
Normal file
135
migration/project-root/ppc-manual/control/mtfsfix.md
Normal 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 0–5):** `63`
|
||||
- **Extended opcode:** `134`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `IMM` | mtfsfix: read | Generic immediate field. |
|
||||
| `CRFD` | mtfsfix: write | CR destination field (`crf`, 0–7). |
|
||||
| `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.
|
||||
142
migration/project-root/ppc-manual/control/mtfsfx.md
Normal file
142
migration/project-root/ppc-manual/control/mtfsfx.md
Normal 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 0–5):** `63`
|
||||
- **Extended opcode:** `711`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (63) |
|
||||
| 6 | `L` | field-select behaviour |
|
||||
| 7–14 | `FM` | FPSCR field mask |
|
||||
| 15 | `W` | immediate-value flag |
|
||||
| 16–20 | `FRB` | source FPR |
|
||||
| 21–30 | `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.
|
||||
139
migration/project-root/ppc-manual/control/mtmsr.md
Normal file
139
migration/project-root/ppc-manual/control/mtmsr.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `146`
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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.
|
||||
138
migration/project-root/ppc-manual/control/mtmsrd.md
Normal file
138
migration/project-root/ppc-manual/control/mtmsrd.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `178`
|
||||
- **Synchronising:** yes
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode |
|
||||
| 6–10 | `RT/FRT/VRT` | destination |
|
||||
| 11–15 | `RA/FRA/VRA` | source A |
|
||||
| 16–20 | `RB/FRB/VRB` | source B |
|
||||
| 21–30 | `XO` | extended opcode (10 bits) |
|
||||
| 31 | `Rc` | record-form flag |
|
||||
|
||||
## Operands
|
||||
|
||||
| Field | Role | Description |
|
||||
| --- | --- | --- |
|
||||
| `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.
|
||||
161
migration/project-root/ppc-manual/control/mtspr.md
Normal file
161
migration/project-root/ppc-manual/control/mtspr.md
Normal 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 0–5):** `31`
|
||||
- **Extended opcode:** `467`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (31) |
|
||||
| 6–10 | `RT` | destination / source GPR |
|
||||
| 11–20 | `spr/tbr/FXM` | SPR/TBR number (byte-swapped halves) or CR field mask |
|
||||
| 21–30 | `XO` | extended opcode |
|
||||
| 31 | `—` | 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.
|
||||
125
migration/project-root/ppc-manual/control/mtvscr.md
Normal file
125
migration/project-root/ppc-manual/control/mtvscr.md
Normal 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 0–5):** `4`
|
||||
- **Extended opcode:** `1604`
|
||||
- **Synchronising:** no
|
||||
|
||||
| Bits | Field | Meaning |
|
||||
| --- | --- | --- |
|
||||
| 0–5 | `OPCD` | primary opcode (4) |
|
||||
| 6–10 | `VRT/VD` | destination vector register |
|
||||
| 11–15 | `VRA/VA` | source A vector register |
|
||||
| 16–20 | `VRB/VB` | source B vector register |
|
||||
| 21–31 | `XO` | extended opcode (11 bits) |
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user