Files
Sylpheed/tools/ppc-manual/fpu/frspx.md
sim 9bfe96e44d fix(ppc-manual): 543 dead links, from two generator bugs and wrong relative paths
- Category pages linked each family as `<slug>.md`, relative to categories/,
  where no family page lives. They now link `../<category>/<slug>.md`.
- Form pages linked a member into its *own* category directory, so every
  VMX128 sibling (`vsldoi128`) pointed at vmx128/ although its family page is
  under vmx/. They now link into the family's directory.
- Hand-written "Related" and sibling mentions linked other categories' pages
  as if they were in the same directory. 109 are retargeted through the page
  index; 29 that pointed a family page at itself (`vrefp128` on vrefp.md) and
  6 naming instructions the manual has no page for are plain text now.

Regenerated at the existing Canary pin (f21ebd49e): upstream has moved on, and
re-pinning belongs in its own change. The generator reports 0 family pages
changed and is idempotent; the only dead links left are TEMPLATE.md's
placeholders.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 22:37:12 +02:00

134 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `frspx` — Floating Round to Single
> **Category:** [Floating-Point](../categories/fpu.md) · **Form:** [X](../forms/X.md) · **Opcode:** `0xfc000018`
<!-- GENERATED: BEGIN -->
## Assembler Mnemonics
| Mnemonic | XML entry | Flags | Description |
| --- | --- | --- | --- |
| `frsp` | `frspx` | — | Floating Round to Single |
| `frsp.` | `frspx` | Rc=1 | Floating Round to Single |
## Syntax
```asm
frsp[Rc] [FD], [FB]
```
## Encoding
### `frspx` — form `X`
- **Opcode word:** `0xfc000018`
- **Primary opcode (bits 05):** `63`
- **Extended opcode:** `12`
- **Synchronising:** no
| Bits | Field | Meaning |
| --- | --- | --- |
| 05 | `OPCD` | primary opcode |
| 610 | `RT/FRT/VRT` | destination |
| 1115 | `RA/FRA/VRA` | source A |
| 1620 | `RB/FRB/VRB` | source B |
| 2130 | `XO` | extended opcode (10 bits) |
| 31 | `Rc` | record-form flag |
## Operands
| Field | Role | Description |
| --- | --- | --- |
| `FB` | frspx: read | Source B floating-point register. |
| `FD` | frspx: write | Destination floating-point register. |
| `CR` | frspx: write (conditional) | Condition-register update. When `Rc=1`, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result. |
| `FPSCR` | frspx: write | Floating-Point Status and Control Register. |
## Register Effects
### `frspx`
- **Reads (always):** `FB`
- **Reads (conditional):** _none_
- **Writes (always):** `FD`, `FPSCR`
- **Writes (conditional):** `CR`
## Status-Register Effects
- `frspx`: **CR0** ← signed-compare(result, 0) with `SO ← XER[SO]`, when `Rc=1`.; **FPSCR** updated per IEEE-754 flags (FX, FEX, FPRF, FR, FI, exceptions).
## Operation (pseudocode)
```
; No hand-written pseudocode for this instruction yet.
; The authoritative semantics are the Canary emitter snapshot under
; Implementation References; about half of Canary's emitters open
; with the PPC-style definition as a comment (`RD <- (RA) + (RB)`).
; Every side effect is also enumerated in the Register Effects and
; Status-Register Effects tables above.
```
## C Translation Example
```c
/* No hand-written C yet. Translate the Canary emitter snapshot */
/* under Implementation References; its HIR maps directly: */
/* f.LoadGPR(n) / f.StoreGPR(n, v) -> r[n] / r[n] = v */
/* f.LoadFPR / StoreFPR, f.LoadVR / StoreVR -> f[n], v[n] */
/* f.Load(ea, T), f.Store(ea, v) -> raw read / write; emitters */
/* wrap them in f.ByteSwap for the big-endian guest value */
/* f.UpdateCR(n, v) -> CR field n from v's LOW 32 BITS vs 0 */
/* f.LoadCA / f.StoreCA -> xer.CA; f.StoreSAT -> vscr.SAT */
/* i.XO.RA, i.D.DS, ... -> the bit-fields listed under Operands */
/* The Register Effects and Status-Register Effects tables above */
/* enumerate every side effect a faithful translation must emit. */
```
## Implementation References
**`frspx`**
- Canary XML: [`tools/ppc-instructions.xml` — search for `mnem="frspx"`](https://github.com/xenia-canary/xenia-canary/blob/f21ebd49e979e44f081f474df78c3fbfee9cb3f2/tools/ppc-instructions.xml)
- Canary emitter: [`src/xenia/cpu/ppc/ppc_emit_fpu.cc:318`](https://github.com/xenia-canary/xenia-canary/blob/f21ebd49e979e44f081f474df78c3fbfee9cb3f2/src/xenia/cpu/ppc/ppc_emit_fpu.cc#L318)
- Sylpheed opcode: [`crates/sylpheed-ppc/src/opcode.rs:90`](../../../crates/sylpheed-ppc/src/opcode.rs#L90)
- Sylpheed decoder: [`crates/sylpheed-ppc/src/decoder.rs:1013`](../../../crates/sylpheed-ppc/src/decoder.rs#L1013)
<details><summary>Canary emitter (frozen snapshot @ <code>f21ebd49e9</code>)</summary>
```cpp
int InstrEmit_frspx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- Round_single(frB)
Value* v = f.Convert(f.LoadFPR(i.X.RB), FLOAT32_TYPE, ROUND_DYNAMIC);
v = f.Convert(v, FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
```
</details>
<!-- GENERATED: END -->
## Special Cases & Edge Conditions
- **Round to single-precision.** Rounds the binary64 value in `FRB` to binary32 using `FPSCR[RN]`, then re-encodes the result back into the destination as a binary64 representation of that single value. Canary emits `Convert(b, FLOAT32, ROUND_DYNAMIC)` then `Convert(v, FLOAT64)``vcvtsd2ss` + `vcvtss2sd` under the host rounding mode, with a fix-up on each step that carries a NaN's quiet/signalling bit across unchanged.
- **`FPSCR[RN]` honoured in Canary.** `ROUND_DYNAMIC` converts under the host rounding mode, which Canary loads from `FPSCR[RN]` whenever the guest writes it through `mtfsf`/`mtfsfi`.
- **Overflow.** Values whose magnitude exceeds binary32's max (~3.4e38) round to ±∞ and set `FPSCR[OX, XX, FX]`.
- **Underflow.** Values whose magnitude is below binary32's smallest normal (~1.2e-38) flush to zero or denormal per `FPSCR[NI]`; `UX`/`XX`/`FX` set on hardware. Canary produces the host's denormal — or zero once the guest has set `NI`, which turns on `MXCSR.FZ` — and sets no FPSCR bit.
- **NaN propagation.** Quiet NaNs pass through; signalling NaNs are quietened on hardware. Canary's conversion fix-ups deliberately carry the quiet/signalling bit across, so a signalling NaN stays signalling; **Canary quirk** for SNaN bit-level inspection.
- **Inexact.** Most rounding produces inexact; sets `FPSCR[XX, FX]`. Canary does not update FPSCR (`UpdateFPSCR` is a stub).
- **`Rc=1` (`frsp.`)** copies `FPSCR[FX, FEX, VX, OX]` into CR1.
- **Encoding.** X-form, primary 63, XO 12. Reads `FRB` only.
- **Use case.** Compilers emit `frsp` after a chain of `fadd`/`fmul`/etc. when storing the value with `stfs` (store single). Without an explicit `frsp`, the in-FPR double would not match the `stfs`-rounded single.
## Related Instructions
- [`faddsx`](faddsx.md), [`fsubsx`](fsubsx.md), [`fmulsx`](fmulsx.md), [`fdivsx`](fdivsx.md) — single-precision arithmetic; equivalent to `frsp(double_op(...))`.
- [`fmaddsx`](fmaddsx.md), [`fmsubsx`](fmsubsx.md), [`fnmaddsx`](fnmaddsx.md), [`fnmsubsx`](fnmsubsx.md) — single-precision fused FMA family.
- `stfs` — store single; expects an FPR already rounded to single via `frsp` or via single-precision arithmetic.
- [`fcfidx`](fcfidx.md) — `fcfid` + `frsp` is the standard `i64 → float` conversion.
- [`mffsx`](../control/mffsx.md), [`mtfsfx`](../control/mtfsfx.md) — FPSCR rounding-mode control.
## IBM Reference
- [AIX 7.3 — `frsp` (Floating Round to Single)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-frsp-floating-round-single-precision-instruction)
- [PowerISA v2.07B, Book I, Chapter 4 — Floating-Point Processor](https://openpowerfoundation.org/specifications/isa/) (single-precision rounding rules; SNaN quietening).