https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125058
--- Comment #1 from migraineman33 at gmail dot com ---
---
Following up on this report with a precise root cause, a one-line fix,
and field validation.
ROOT CAUSE
In gcc/config/pdp11/pdp11.md, the `lshr<mode>3` define_expand's QImode
branch emits the shift without negating the count:
if (<QHSint:e_mname> == E_QImode)
{
r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode,
operands[1]));
emit_insn (gen_aslhi_op (r, r, operands[2]));
emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
}
`aslhi_op` maps to the PDP-11 ASH instruction, whose count is signed:
positive shifts left, negative shifts right. A logical right shift of a
QImode value therefore compiles to a LEFT shift — silent wrong code, no
diagnostic. Compare the `ashr<mode>3` expander immediately above, which
correctly performs `operands[2] = negate_rtx (HImode, operands[2]);`
before the same QImode sequence; `lshr<mode>3`'s non-QImode arm also
accounts for direction (via the 1-bit lshiftrt + adjusted count). Only
the QImode arm of lshr<mode>3 is missing the negation.
The defect is present in releases at least through 13.3.0 and is still
present in current master (checked gcc-mirror HEAD as of 2026-07-04).
The affected path is taken when pdp11_expand_shift() declines the
small-constant sequence — i.e. variable shift counts (and large
constants), e.g.:
unsigned char f (unsigned char x, int n) { return x >> n; }
which emits `ash` with the positive count in place of the negated one.
FIX (one line, mirrors ashr<mode>3):
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ (define_expand "lshr<mode>3") @@
if (<QHSint:e_mname> == E_QImode)
{
r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode,
operands[1]));
+ operands[2] = negate_rtx (HImode, operands[2]);
emit_insn (gen_aslhi_op (r, r, operands[2]));
emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r,
0)));
}
FIELD VALIDATION
This is not a synthetic finding. With the one-line patch applied to
GCC 13.3.0 (pdp11-aout), we have built a complete operating system —
the Fuzix 0.4.1 kernel, C library, and a 35-program userland — and run
it multi-process with MMU address separation and swap on PDP-11
hardware (a cycle-faithful FPGA recreation of an 11/20+11/40-class
MMU on a Lattice iCE40-UP5K), interactively verified at the console
on 2026-07-04. Before the patch, byte right-shifts in the kernel's
tty/device paths produced corrupt results and required source-level
workarounds (word-widening reads); with the patch, the system is fully
operational and no regressions have been observed anywhere in the
kernel or userland.