From 016e377fec0cb898bbdea9df7a1cebbef5d2030c Mon Sep 17 00:00:00 2001 From: ComradePenguin-1917 <3069573702@qq.com> Date: Sat, 19 Sep 2026 01:09:43 +0800 Subject: [PATCH] fix(printer): split-window ureg operand decode overwrote instead of merging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `format_ureg_raw` assigns each uniform-register slice: "ureg_shr3" => ureg = Some(f.value << 3), so when one operand scalar is decomposed across disjoint fields the later slice clobbers the earlier one. A split-window operand therefore decoded wrong: on SM120 the OMMA block-scale operand (`URi`, PTX `byte-id-a`) is an 8-bit uniform-register index carried as ureg[0:3)@60 + ureg_shr3[3:8)@73, and the high slice overwrote the low one — an operand encoded as UR6 rendered back as UR0. OR the slice into the accumulator so the pieces recombine. The high slice also has to set the 0x100 "wide window" sentinel itself: it carries bits [3:8) of an 8-bit operand, whereas the low `ureg` slice does not (its own width is 3). Without the sentinel, URZ — low=7, high=31, raw 255 — rendered as "UR255", and the architectural UR63 stopped being distinguishable from the sink. A lone `ureg_shr3` slice is unaffected: 5 bits shifted left by 3 top out at 248, never 255. No table in this revision uses `ureg_shr3` yet, so this is a no-op for the shipped tables; it is the code-side prerequisite for the sm120 URi field-geometry correction (companion data change, blackwell-isa). Verified: full suite green (1406 passed). An OMMA word encoded as UR6/URZ round-trips exactly with the companion table fix applied. --- src/printer.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/printer.rs b/src/printer.rs index c5eded6..14b5704 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -1418,7 +1418,23 @@ fn format_ureg_raw(fields: &[&DecodedField], raw: u128) -> String { // 6-bit ureg fields: 63 = URZ. Keep the source width to tell them apart. "ureg" => { ureg = Some(f.value | (if f.bits >= 8 { 0x100 } else { 0 })); } "ureg_ff" => { ureg = Some(f.value | 0x100); } - "ureg_shr3" => ureg = Some(f.value << 3), + // Split-window ureg slice: one operand scalar decomposed into + // disjoint fields — e.g. OMMA URi = ureg[0:3)@60 + ureg_shr3[3:8)@73. + // OR the slice in so a multi-segment operand recombines; a lone + // slice behaves exactly as the previous assignment did. + // + // This slice carries bits [3:8) of the operand, so it belongs to an + // 8-bit window and must set the 0x100 sentinel itself — the low + // `ureg` slice does not, because its own `bits` is only 3. Without + // that, URZ (low=7, high=31, raw 255) would render as "UR255" + // instead of "URZ", and the architectural UR63 would stop being + // distinguishable. A lone `ureg_shr3` slice is unaffected: 5 bits + // shifted left by 3 top out at 248, which is not 255. + "ureg_shr3" => { + let prev = ureg.unwrap_or(0); + let v = ((prev & 0xFF) | (f.value << 3)) | 0x100; + ureg = Some(v); + } "neg" => neg = f.value != 0, "abs" => abs_u = f.value != 0, "inv" => inv = f.value != 0,