# `lmw` — Load Multiple Word > **Category:** [Memory](../categories/memory.md) · **Form:** [D](../forms/D.md) · **Opcode:** `0xb8000000` ## Assembler Mnemonics | Mnemonic | XML entry | Flags | Description | | --- | --- | --- | --- | | `lmw` | `lmw` | — | Load Multiple Word | ## Syntax ```asm (no disassembly template) ``` ## Encoding ### `lmw` — form `D` - **Opcode word:** `0xb8000000` - **Primary opcode (bits 0–5):** `46` - **Extended opcode:** — - **Synchronising:** no | Bits | Field | Meaning | | --- | --- | --- | | 0–5 | `OPCD` | primary opcode | | 6–10 | `RT` | destination GPR (or RS when storing) | | 11–15 | `RA` | source GPR (0 ⇒ literal 0 for RA0 forms) | | 16–31 | `D/SI/UI` | 16-bit signed or unsigned immediate | ## Operands | Field | Role | Description | | --- | --- | --- | ## Register Effects ### `lmw` - **Reads (always):** _none_ - **Reads (conditional):** _none_ - **Writes (always):** _none_ - **Writes (conditional):** _none_ ## Status-Register Effects _No condition-register or status-register effects._ ## Operation (pseudocode) ``` ; Pseudocode derives directly from the xenia-rs interpreter ; arm (see Implementation References). Operation semantics: ; - Read source operands from the fields listed under Operands. ; - Apply the arithmetic / logical / memory action described ; in the Description field above. ; - Write results to the destination register(s); update any ; status bits enumerated under Status-Register Effects. ; Consult the IBM AIX reference link under IBM Reference for ; canonical PPC-style pseudocode where xenia's expression is ; terse. ``` ## C Translation Example ```c /* C translation: the xenia-rs interpreter arm below in */ /* Implementation References is the authoritative semantic */ /* snapshot. Translate it line-by-line: */ /* - ctx.gpr[N] -> r[N] (or f[]/v[] for FPRs/VRs) */ /* - mem.read_u*/write_u* -> mem_read_u*_be / mem_write_u*_be */ /* - ctx.update_cr_signed(fld, v) -> update_cr_signed(fld, v) */ /* - ctx.xer_ca / xer_ov / xer_so -> xer.CA / xer.OV / xer.SO */ /* The Register Effects and Status-Register Effects tables above */ /* enumerate every side effect a faithful translation must emit. */ ``` ## Implementation References **`lmw`** - xenia-canary XML: [`tools/ppc-instructions.xml` — search for `mnem="lmw"`](../../xenia-canary/tools/ppc-instructions.xml) - xenia-canary emit: [`src/xenia/cpu/ppc/ppc_emit_memory.cc:705`](../../xenia-canary/src/xenia/cpu/ppc/ppc_emit_memory.cc#L705) - xenia-rs opcode: [`crates/xenia-cpu/src/opcode.rs:42`](../../xenia-rs/crates/xenia-cpu/src/opcode.rs#L42) - xenia-rs decoder: [`crates/xenia-cpu/src/decoder.rs:369`](../../xenia-rs/crates/xenia-cpu/src/decoder.rs#L369) - xenia-rs interpreter: [`crates/xenia-cpu/src/interpreter.rs:1720-1734`](../../xenia-rs/crates/xenia-cpu/src/interpreter.rs#L1720-L1734)
xenia-rs interpreter body (frozen snapshot) ```rust PpcOpcode::lmw => { // PPCBUG-125: PowerISA marks `lmw` invalid when rA is in [rT..31]; // canary skips the write to rA in that case to preserve the EA base. let mut ea = if instr.ra() == 0 { 0u64 } else { ctx.gpr[instr.ra()] }; ea = ea.wrapping_add(instr.d() as i64 as u64); for r in instr.rd()..32 { if r == instr.ra() { ea = ea.wrapping_add(4); continue; } ctx.gpr[r] = mem.read_u32(ea as u32) as u64; ea = ea.wrapping_add(4); } ctx.pc += 4; } ```
## Special Cases & Edge Conditions - **Bulk register restore.** Loads `(32 - RT)` consecutive 32-bit words starting at `EA` into `RT`, `RT+1`, …, `r31`. Used by AIX/PowerPC ABI prologues/epilogues to restore non-volatile GPRs in one instruction. Modern compilers prefer multiple `lwz` for scheduling; `lmw` survives in older code and hand-rolled context-switch routines. - **Loop bound from encoding.** Xenia's snapshot iterates `for r in instr.rd()..32`, exactly matching IBM's "load until r31 inclusive" semantic. With `RT = 28`, four registers (r28..r31) are loaded. - **Each word is zero-extended.** Like `lwz`, every loaded 32-bit word zero-extends into the destination's 64-bit GPR. The high 32 bits of each `r[k]` become zero. - **Big-endian read.** Word at `EA` goes to `r[RT]`, word at `EA+4` goes to `r[RT+1]`, etc. Each word is itself loaded most-significant-byte-first. - **`RA0` semantics.** When `RA = 0`, base is literal zero. Useful for absolute-address restoration. - **Invalid forms.** AIX docs declare it invalid for `RA` to be in the destination range `[RT, 31]` — a load could overwrite the base register mid-sequence. Xenia performs loads in order without this check. - **Alignment.** PowerISA requires word-aligned `EA`; an unaligned `lmw` may raise an alignment exception on real hardware. Xenia tolerates it. - **Performance trap.** On modern PowerPC implementations `lmw` is microcoded — slower than the equivalent sequence of `lwz`. Compilers avoid it. ## Related Instructions - [`stmw`](stmw.md) — symmetric "store multiple words" (the matching epilogue/prologue partner). - [`lwz`](lwz.md), [`lwzx`](lwz.md) — single-word loads; the modern preferred form. - [`lswi`](lswi.md), [`lswx`](lswx.md) — load string (byte-granular bulk transfer). ## IBM Reference - [AIX 7.3 — `lmw` (Load Multiple Word)](https://www.ibm.com/docs/en/aix/7.3.0?topic=set-lmw-load-multiple-word-instruction) - `PowerISA v2.07B Book II` § "Load and Store Multiple" for invalid-form rules.