Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2011-08

Code generation oddity on SPARC Linux

4 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

I have a fragment of code that looks like this:

VAR     z, a, alpha, b, c, d, e: Int64;
         f: DOUBLE;
BEGIN
   td:= td + 0.5;                       // astronomical to civil
   z:= Floor(td);
   f:= td - z;
   IF z < 2299161.0 THEN
     a:= z
   ELSE BEGIN
     alpha:= Floor((z - 1867216.25) / 36524.25);
     a:= z + 1 + alpha - Floor(alpha / 4)
   END;

Using 2.4.4 with -a -al -s this compiles to a .s which looks like this:

.Ll34:
# [439] IF z < 2299161.0 THEN
ld [%i6-32],%o0
ld [%i6-28],%o1
call fpc_int64_to_double
nop
sethi %hi(_$MOONPHASE$_Ld8),%o0
ld [%lo(_$MOONPHASE$_Ld8)+%o0],%f1
fcmpd %f0,%f1
nop
fbl .Lj87
nop
ba .Lj88
nop
.Lj87:
.stabn 68,0,441,.Ll35 - MOONPHASE_JYEAR$DOUBLE$INT64$INT64$DOUBLE .Ll35:
# [441] a:= z

This appears to be the only place in the program where fcmpd %f0,%f1 is generated, although the same opcode is generated with other registers as opeands. Assembling with as (2.17 or 2.18), I get this error:

moonphase.s:629: Error: Illegal operands

If I change the code to look like this:

   f:= td - z;
   IF z - 2299161.0 < 0 THEN
     a:= z
   ELSE BEGIN

it generates this:

.Ll34:
# [440] IF z - 2299161.0 < 0 THEN
ld [%i6-32],%o0
ld [%i6-28],%o1
call fpc_int64_to_double
nop
sethi %hi(_$MOONPHASE$_Ld8),%o0
ld [%lo(_$MOONPHASE$_Ld8)+%o0],%f1
fsubs %f0,%f1,%f0
sethi %hi(_$MOONPHASE$_Ld9),%o0
ld [%lo(_$MOONPHASE$_Ld9)+%o0],%f1
fcmps %f0,%f1
nop
fbl .Lj87

Having a workaround makes this not particularly crucial, but I'd welcome any comments.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Jonas Maebe
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 24 lines
Using 2.4.4 with -a -al -s this compiles to a .s which looks like this: .Ll34: # [439] IF z < 2299161.0 THEN ld [%i6-32],%o0 ld [%i6-28],%o1 call fpc_int64_to_double nop sethi %hi(_$MOONPHASE$_Ld8),%o0 ld [%lo(_$MOONPHASE$_Ld8)+%o0],%f1 fcmpd %f0,%f1 nop fbl .Lj87 nop ba .Lj88 nop .Lj87: .stabn 68,0,441,.Ll35 - MOONPHASE_JYEAR$DOUBLE$INT64$INT64$DOUBLE .Ll35: # [441] a:= z This appears to be the only place in the program where fcmpd %f0,%f1 is generated, although the same opcode is generated with other registers as opeands. Assembling with as (2.17 or 2.18), I get this error: moonphase.s:629: Error: Illegal operands

The sparc only has single precision floating point registers. Double precision values are stored in two consecutive single precision registers, and hence arguments to double precision opcodes must always be even registers. The above demonstrates a bug in the register allocator. Please file a bug report.

Jonas

Reply by email

Mark Morgan Lloyd
to Jonas Maebe
Jonas Maebe wrote
The sparc only has single precision floating point registers. Double precision values are stored in two consecutive single precision registers, and hence arguments to double precision opcodes must always be even registers. The above demonstrates a bug in the register allocator. Please file a bug report.

Thanks Jonas, will do in the morning.

I've worked around it by noticing that I only need integer operations at that point- I'm transcribing Perl (MoonPhase.pm) based on C (moontool.c), and it's not the first instance of bad type handling that I've found.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Jonas Maebe: The sparc only has single precision floating point registers. Double precision values are…
Jonas Maebe wrote 28 lines
On 26 Aug 2011, at 22:42, Mark Morgan Lloyd wrote: > Using 2.4.4 with -a -al -s this compiles to a .s which looks like this: > > .Ll34: > # [439] IF z < 2299161.0 THEN > ld [%i6-32],%o0 > ld [%i6-28],%o1 > call fpc_int64_to_double > nop > sethi %hi(_$MOONPHASE$_Ld8),%o0 > ld [%lo(_$MOONPHASE$_Ld8)+%o0],%f1 > fcmpd %f0,%f1 > nop > fbl .Lj87 > nop > ba .Lj88 > nop > .Lj87: > .stabn 68,0,441,.Ll35 - MOONPHASE_JYEAR$DOUBLE$INT64$INT64$DOUBLE > .Ll35: > # [441] a:= z > > This appears to be the only place in the program where fcmpd %f0,%f1 is generated, although the same opcode is generated with other registers as opeands. Assembling with as (2.17 or 2.18), I get this error: > > moonphase.s:629: Error: Illegal operands The sparc only has single precision floating point registers. Double precision values are stored in two consecutive single precision registers, and hence arguments to double precision opcodes must always be even registers. The above demonstrates a bug in the register allocator. Please file a bug report.

Submitted as 20072

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email