https://sourceware.org/bugzilla/show_bug.cgi?id=34981
Bug ID: 34981
Summary: fmovex bug in m68k gas
Product: binutils
Version: 2.47
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: gas
Assignee: unassigned at sourceware dot org
Reporter: edercarneiru at gmail dot com
Target Milestone: ---
[ AI found this bug, not me ]
Title
-----
m68k gas: floating immediates for .x instructions are encoded wrongly
(no 16-bit gap, hidden integer bit); inf/NaN also emit uninitialised memory
Version and host
----------------
GNU assembler (GNU Binutils; openSUSE Tumbleweed) 2.47.0.20260921-2
Package cross-m68k-binutils-2.47-2.1.x86_64
Host x86_64-linux, target m68k-suse-linux
The same results were obtained earlier with 2.45.0.20251103-4. Git master has
not been tested.
Summary
-------
The 68881 extended format is 12 bytes: sign and exponent (16 bits), 16 zero
bits, then a 64-bit mantissa with an explicit integer bit.
For a decimal immediate on an extended-precision instruction, gas emits a
different layout: no 16-bit gap, and no explicit integer bit. Every non-zero
finite value is therefore wrong.
For an infinity or NaN immediate, gas writes a double-precision pattern into
the first 8 bytes and leaves the last 4 bytes unwritten. Those bytes come from
uninitialised stack memory, so the output can change from run to run.
The .extend directive produces correct values in all these cases.
How to reproduce
----------------
finite.s:
.text
fmovex #0e1.5,%fp0
.extend 1.5
fmovex #0e1.0,%fp0
.extend 1.0
fmovex #0e-2.0,%fp0
.extend -2.0
fmovex #0e0.1,%fp0
.extend 0.1
inf.s:
.text
fmovex #0einf,%fp0
Commands (run inf.s several times):
m68k-suse-linux-as -m68040 -o finite.o finite.s
m68k-suse-linux-objdump -s -j .text finite.o
m68k-suse-linux-as -m68040 -o inf.o inf.s
m68k-suse-linux-objdump -s -j .text inf.o
Actual and expected results
---------------------------
The first word of each instruction, f23c4800, is correct and omitted here.
value emitted for the immediate .extend (correct)
1.5 3fff8000 00000000 00000000 3fff0000 c0000000 00000000
1.0 3fff0000 00000000 00000000 3fff0000 80000000 00000000
-2.0 c0000000 00000000 00000000 c0000000 80000000 00000000
0.1 3ffb9999 99999999 9999999a 3ffb0000 cccccccc cccccccd
inf 7ff00000 00000000 ???????? 7fff0000 00000000 00000000
-inf fff00000 00000000 ???????? ffff0000 00000000 00000000
nan 7fffffff ffffffff ???????? 7fff0000 ffffffff ffffffff
When the inf or NaN is the only immediate in the file, the last word changes
on every run. Three runs each gave:
inf f7e832c3 f7e879a3 f7e80963
-inf f7e88063 f7e814c3 f7e85dc3
nan f7e8cb83 f7e88b03 f7e82683
When a finite immediate comes earlier in the file, the last word is left over
from it. After fmovex #0e0.1, the inf, -inf and nan immediates all end in
9999999a, the last word of the 0.1 immediate.
Cause
-----
In m68k_ip (gas/config/tc-m68k.c), an 'x' operand sets baseo = 6, outro = 15,
and then calls:
gen_to_words (words, baseo, (long) outro);
So gen_to_words is called with precision 6, while atof-ieee.c defines
X_PRECISION as 5 and adds the m68k gap itself. Because 6 != X_PRECISION:
- the code for the 16-bit gap and the explicit integer bit is skipped, which
gives the wrong finite values;
- the inf and NaN cases take their final "else" branch, for double
precision, which writes only words[0..3]. words is a local array in
m68k_ip that is not initialised, and all 6 words are then emitted.
A possible fix is to pass X_PRECISION to gen_to_words for 'x' while still
emitting 6 words. This has not been built or tested. The 'p' case also uses
baseo = 6 and was not examined.
Valgrind
--------
A file holding only "fmovex #0einf,%fp0", assembled under
valgrind --track-origins=yes, reports:
Syscall param write(buf) points to uninitialised byte(s)
...
Uninitialised value was created by a stack allocation
Other observations
------------------
The inf and finite results are the same with -m68020, -m68030 -m68881, and
-m68060. The inf result is the same with fcmpx, faddx, and Motorola-style
fmove.x.
The shorter formats are correct:
fmoves #0e-inf f23c4400 ff800000
fmoved #0e-inf f23c5400 fff00000 00000000
Workaround
----------
Give the 12 bytes in hexadecimal:
fmovex #0x3fff0000c000000000000000,%fp0
--
You are receiving this mail because:
You are on the CC list for the bug.