Discussion:
Support for MIPS r5900
(too old to reply)
Maciej W. Rozycki
2013-01-10 23:24:54 UTC
Permalink
Jürgen,

Adding the binutils list as more appropriate for some concerns discussed
here.
ll, sc, dmult, ddiv, cvt.w.s, 64 bit FPU instructions.
ll and sc is disabled with "-mno-llsc" and works.
cvt.w.s is replaced by trunc.w.s. This seems to work.
Probably showing my ignorance, but I couldn't see this in the patch.
This has raised my attention -- AFAICS the binutils change recently
approved correctly disables DMULT, DDIV, CVT.W.S, etc. for -march=r5900,
but does not do that for LL or SC. I think that should be fixed. And I
gather LLD and SCD should then be disabled as well.
The glibc can only be compiled with support for ll and sc. The Linux
kernel successfully emulates these instructions. When compiling GCC for
mips*r5900*-elf (i.e. not Linux), the instructions ll/sc and lld/scd are
disabled by my patch.
That a particular OS emulates some instructions in software does not
necessarily make them a part of the architecture. GAS needs to support
any target environment, including bare iron, and as such should closely
match the hardware implementation. I think the right place to address it
is glibc.

The library can be built for the base MIPS I ISA that did not have LL or
SC instructions either and therefore already has some provisions in place
to override the processor/ISA selection for the code fragments in question
so that the instructions otherwise missing from the target hardware
selected are nevertheless assembled successfully. This is currently
enabled for the o32 ABI, where .set mips2 is used to enable the assembly
of LL and SC.

Now if that failed for you, then it's a plain bug in GAS that should be
fixed. Can you therefore check whether a piece like:

.set mips2
ll $2, ($3)

assembles correctly with -march=r5900?

Please note that the issue of LLD and SCD remains open -- these
instructions are a part of the base MIPS III 64-bit ISA and therefore they
are assumed by glibc and elsewhere to be present, and they are not
emulated by Linux. So not only you'll have to fix up glibc to surround
their use with .set mips3 for the n64 and n32 ABIs (please note that .set
mips3 is needed for LL and SC for these ABIs as well to avoid a
miscalculation of addresses where applicable), but you'll have to add
emulation code to Linux as well.

And in any case I insist that the instructions are correctly marked in
the opcode table.
Things would get more complicated if one wanted to run a real OS such as
Linux on the R5900 and let the kernel FP emulator handle the missing
double FP automagically -- this is a little bit out of scope here as
regular -mdouble-float would then just do, but makes me wonder whether
-mfp32 should really be enforced (as opposed to just defaulted) for the
R5900, hmm...
I tried to emulate the 64 Bit FPU when the real 32 Bit FPU was enabled
1. When the program starts, I don't know if it needs a 64 Bit or 32 Bit
FPRs. So registers are initialized for 32 bit. When dmfc0 or dmtc0
appears, I need to emulate them using 32 Bit FPU, because some 32 bit
programs use these instructions with a 32 Bit FPU (e.g. Linux 2.6.35
kernel and Debian 5.0). When a 64 bit calculation instructions appears,
I need to switch from 32 bit FPRs to 64 bit FPRs. When the program used
32 bit instructions with the odd FPRs, there is no way to reconstruct
the overwritten part of the 64 bit FPRs.
The mode of the FPU is determined by the ABI -- o32 programs use the
32-bit configuration (CP0.Status.FR set to 0) and n64/n32 programs use the
64-bit arrangement (CP0.Status.FR set to 1). That's already handled
correctly by the kernel, by configuring the FPU on a process-by-process
basis according to data obtained from the ELF file header of the
executable run.

Of course all double arithmetic would have to be handled by the emulator,
by trapping the Unimplemented Operation exception. This would clearly be
a new mode of operation and not supported out of the box with current
code as that would have to be tweaked to handle the case where only half
the register state is stored in hardware.
2. Some undefined instructions (e.g. c.eq.d) doesn't lead to an
exception on an r5900, but have undefined behavior. So there is no
emulation possible. It just calculates random stuff.
Oh well, that rules out any practical use of the FPU under Linux then.
So the FPU needs to be disabled and completely emulated by the kernel,
because then all FPU instructions lead to an exception. This is working
with Linux 2.6 on PS2.
Naturally, as long as they got the Coprocessor Unusable exception right.
There are even more problems when running unchanged code from official
Fedora 12 on PS2, because of some different opcode encoding. The users
of my PS2 Linux 2.6 complain about low speed, because many instructions
are emulated. I need some fast implementation, even if the size of the
floating point data types is smaller. So 32 bit FPU must be default for
r5900.
That sounds weird -- why would anyone want to use a non-standard encoding
for any instructions? The base MIPS III 64-bit ISA was set as far back as
in 1991. Is R5900 documentation publicly available BTW?

Maciej
Richard Sandiford
2013-01-11 09:49:12 UTC
Permalink
Post by Maciej W. Rozycki
And in any case I insist that the instructions are correctly marked in
the opcode table.
I agree that it would be better to exclude the unimplemented instructions.
Jürgen: if you're happy to submit a patch along those lines, I promise
to review it.

BTW Maciej, sorry to be prickly about this, but: where I live, "I insist"
has a very domineering ring to it, at least in this kind of context.
The implication tends to be that "having insisted, I really expect it to
happen, simply because it is _I_ who insisted". Maybe it's not the same
everywhere though.

Richard
Maciej W. Rozycki
2013-01-11 16:54:51 UTC
Permalink
Post by Richard Sandiford
BTW Maciej, sorry to be prickly about this, but: where I live, "I insist"
has a very domineering ring to it, at least in this kind of context.
The implication tends to be that "having insisted, I really expect it to
happen, simply because it is _I_ who insisted". Maybe it's not the same
everywhere though.
That's probably a shortcoming of my English skills -- sorry about that --
I didn't want to sound impolite or to insult anyone, especially you,
Jürgen. Your contribution is very welcome even if there are minor issues
there or some design decisions are not immediately obvious to everyone.
Please feel free to disagree or argue if you think any opinion expressed
does not convince you.

Maciej
Jürgen Urban
2013-01-13 14:15:55 UTC
Permalink
Hello Maciej,
Post by Maciej W. Rozycki
Now if that failed for you, then it's a plain bug in GAS that should be
.set mips2
ll $2, ($3)
assembles correctly with -march=r5900?
This seems to work. I didn't know that this would work. I thought it would never be possible to generate ll and sc.
Post by Maciej W. Rozycki
Please note that the issue of LLD and SCD remains open -- these
instructions are a part of the base MIPS III 64-bit ISA and therefore they
are assumed by glibc and elsewhere to be present, and they are not
emulated by Linux. So not only you'll have to fix up glibc to surround
their use with .set mips3 for the n64 and n32 ABIs (please note that .set
mips3 is needed for LL and SC for these ABIs as well to avoid a
miscalculation of addresses where applicable), but you'll have to add
emulation code to Linux as well.
I didn't see any code yet that uses lld/scd, so it doesn't seem to be a problem.
I will create a patch which includes tests that will ensure that .set mips3 will work.
Post by Maciej W. Rozycki
So the FPU needs to be disabled and completely emulated by the kernel,
because then all FPU instructions lead to an exception. This is working
with Linux 2.6 on PS2.
Naturally, as long as they got the Coprocessor Unusable exception right.
Yes, this exception is also working for instructions with undefined behavior.
Post by Maciej W. Rozycki
There are even more problems when running unchanged code from official
Fedora 12 on PS2, because of some different opcode encoding. The users
of my PS2 Linux 2.6 complain about low speed, because many instructions
are emulated. I need some fast implementation, even if the size of the
floating point data types is smaller. So 32 bit FPU must be default for
r5900.
That sounds weird -- why would anyone want to use a non-standard encoding
for any instructions? The base MIPS III 64-bit ISA was set as far back as
in 1991. Is R5900 documentation publicly available BTW?
The documentation for r5900 is available on the first DVD of Sony's Linux Toolkit and in the SDK for the PS2 which is only available for people which I would call "verified Sony customers".
The TX79 core is similar to the r5900:
http://www.lukasz.dk/files/tx79architecture.pdf
But the TX79 has a 64 Bit FPU, so there are no real problems with opcode encoding. This document also says that mips isa III is supported, but not ll,sc,lld,scd,dmult and ddiv.
In binutils/opcodes/mips-opc.c you can see the different opcode encoding for c.lt.s and trunc.w.s, the missing c.olt.s and cvt.w.s instructions. These are caused by the FPU. This is no problem on the TX79.
For Fedora 12 I need to disable the FPU and emulate everything.
One of the biggest problem is that most Linux programs use the rdhwr instruction (0x7c03e83b). I don't know any MIPS CPU which supports this instruction. This has the same encoding as the "sq v1,-6085(zero)" instruction on the r5900. Luckily this always leads to an alignment exception which is handled correctly by my Linux kernel to emulate rdhwr.

Here is some information from the EE core user's manual regarding FPU:
This unit is not IEEE 754 compatible.
Supports single-precision format as defined in the IEEE 754 specification.
Plus/Minus "0" in line with IEEE 754 specification are supported.
NaNs and plus/minus infinities are not supported.
No hardware exception mechanism to affect instruction execution.

The FPU only supports "Rounding towards 0".
... the results may differ from the IEEE 754 Rounding to 0. This difference is usually restricted to the least significant bit only.

NaN, +inf, -inf and denormalized numbers are not supported
The FPU does not use the Guard, Round and Sticky bits during computations.
Invalid Operation exceptions due to NaN, +/-inf and Inexact exceptions are not supported.

Operations with different results:
- 0/0
- Sqrt (negative number)
- Division by zero
- Exponent overflow
- Exponent underflow
- Conversion of Floating-point to Integer Overflow

Best regards
Jürgen
Maciej W. Rozycki
2013-01-14 18:42:11 UTC
Permalink
Hi Jürgen,
Post by Jürgen Urban
Post by Maciej W. Rozycki
Now if that failed for you, then it's a plain bug in GAS that should be
.set mips2
ll $2, ($3)
assembles correctly with -march=r5900?
This seems to work. I didn't know that this would work. I thought it
would never be possible to generate ll and sc.
Excellent, I hoped that it would work as we've been using these overrides
for years, except that usually they are used to tweak the ISA selected
rather than a specific CPU (with -march= you can request either an ISA or
a CPU). Your case is the first I've personally encountered where the CPU
selected needs an override, so I'm glad that it just works.
Post by Jürgen Urban
Post by Maciej W. Rozycki
Please note that the issue of LLD and SCD remains open -- these
instructions are a part of the base MIPS III 64-bit ISA and therefore they
are assumed by glibc and elsewhere to be present, and they are not
emulated by Linux. So not only you'll have to fix up glibc to surround
their use with .set mips3 for the n64 and n32 ABIs (please note that .set
mips3 is needed for LL and SC for these ABIs as well to avoid a
miscalculation of addresses where applicable), but you'll have to add
emulation code to Linux as well.
I didn't see any code yet that uses lld/scd, so it doesn't seem to be a
problem. I will create a patch which includes tests that will ensure
that .set mips3 will work.
Glibc uses them exactly where it uses 32-bit LL/SC, except where a 64-bit
data type is involved. Of course that also requires a 64-bit ABI, either
n64 or n32, as these are 64-bit instructions -- from what you wrote thus
far I've gathered, perhaps incorrectly, that you've been using either or
both too, in addition to o32 -- is my understanding correct?
Post by Jürgen Urban
Post by Maciej W. Rozycki
There are even more problems when running unchanged code from official
Fedora 12 on PS2, because of some different opcode encoding. The users
of my PS2 Linux 2.6 complain about low speed, because many instructions
are emulated. I need some fast implementation, even if the size of the
floating point data types is smaller. So 32 bit FPU must be default for
r5900.
That sounds weird -- why would anyone want to use a non-standard encoding
for any instructions? The base MIPS III 64-bit ISA was set as far back as
in 1991. Is R5900 documentation publicly available BTW?
The documentation for r5900 is available on the first DVD of Sony's
Linux Toolkit and in the SDK for the PS2 which is only available for
people which I would call "verified Sony customers".
OK, I see, so not really public, sigh...
Post by Jürgen Urban
http://www.lukasz.dk/files/tx79architecture.pdf
But the TX79 has a 64 Bit FPU, so there are no real problems with opcode
encoding. This document also says that mips isa III is supported, but
not ll,sc,lld,scd,dmult and ddiv. In binutils/opcodes/mips-opc.c you can
see the different opcode encoding for c.lt.s and trunc.w.s, the missing
c.olt.s and cvt.w.s instructions. These are caused by the FPU. This is
no problem on the TX79.
Oh well, missing instructions are not that much of a problem, they can
always be emulated. Instruction words that implement operation different
to one expected are a show-stopper though.

I see that the encodings supposed to implement C.OLT.S and C.OLE.S are
interpreted as C.LT.S and C.LE.S, respectively. However the former
instructions differ from the latters only in how quiet NaNs are treated.
Given that, as you say, the processor does not support NaNs anyway, this
may well be considered correct operation. You may still need to emulate
the other encoding though.

How are unsupported floating-point data treated, BTW -- what results does
the processor produce for floating-point encodings that would normally be
interpreted as not-a-number, an infinity or a denormalised number? Are
they treated numerically, beyond the range IEEE-754 single provides? You
say that the Invalid Operation exception is not raised, so they cannot be
trapped and emulated.
Post by Jürgen Urban
For Fedora 12 I need to disable the FPU and emulate everything.
Well, given the lack of full IEEE-754 support you'll always have to do
that for generic MIPS code. The kernel could interpret E_MIPS_MACH_5900
set in the ELF file header flags though and enable the FPU selectively for
compatible binaries. Such binaries might produce computational results
different to expected of course. You'd have to enforce object-file
compatibility though and make sure R5900 binaries do not run with the FPU
enabled on other hardware too.

That might be an interesting project if you'd like to dive into it.
Post by Jürgen Urban
One of the biggest problem is that most Linux programs use the rdhwr
instruction (0x7c03e83b). I don't know any MIPS CPU which supports this
instruction.
Oh, pretty much all modern MIPS processors do -- this instruction has
been mandatory since the introduction of the MIPS32r2 and MIPS64r2 ISA
level. The UserLocal CP0 register accessible with RDHWR <rt>, $29 is
however optional, so the instruction may still trap on some processors
that otherwise support it, but there are such that do not, e.g. the 74K
family processors.
Post by Jürgen Urban
This has the same encoding as the "sq v1,-6085(zero)"
instruction on the r5900. Luckily this always leads to an alignment
exception which is handled correctly by my Linux kernel to emulate
rdhwr.
Good.
Post by Jürgen Urban
This unit is not IEEE 754 compatible.
Supports single-precision format as defined in the IEEE 754 specification.
Plus/Minus "0" in line with IEEE 754 specification are supported.
NaNs and plus/minus infinities are not supported.
No hardware exception mechanism to affect instruction execution.
The FPU only supports "Rounding towards 0".
... the results may differ from the IEEE 754 Rounding to 0. This
difference is usually restricted to the least significant bit only.
NaN, +inf, -inf and denormalized numbers are not supported
The FPU does not use the Guard, Round and Sticky bits during computations.
Invalid Operation exceptions due to NaN, +/-inf and Inexact exceptions are not supported.
- 0/0
- Sqrt (negative number)
- Division by zero
- Exponent overflow
- Exponent underflow
- Conversion of Floating-point to Integer Overflow
OK, I guess you could still make it a supported processing unit with GCC,
however I can't speak for GCC maintainers as to whether they would be
willing to accept such support for inclusion. Both ISO C and GCC do
permit non-IEEE-754 floating point arithmetic (cf. VAX, that does not
support qNaNs, infinities or denormals; sNaNs in a sense are supported).
You'd probably have to bail out on sources referring to unsupported
features, e.g. __builtin_inf; I reckon the VAX port does that.

Maciej
Jürgen Urban
2013-01-17 22:20:59 UTC
Permalink
Hello Maciej,
Post by Maciej W. Rozycki
Post by Jürgen Urban
Post by Maciej W. Rozycki
Please note that the issue of LLD and SCD remains open -- these
instructions are a part of the base MIPS III 64-bit ISA and therefore
they
Post by Jürgen Urban
Post by Maciej W. Rozycki
are assumed by glibc and elsewhere to be present, and they are not
emulated by Linux. So not only you'll have to fix up glibc to
surround
Post by Jürgen Urban
Post by Maciej W. Rozycki
their use with .set mips3 for the n64 and n32 ABIs (please note that
.set
Post by Jürgen Urban
Post by Maciej W. Rozycki
mips3 is needed for LL and SC for these ABIs as well to avoid a
miscalculation of addresses where applicable), but you'll have to add
emulation code to Linux as well.
I didn't see any code yet that uses lld/scd, so it doesn't seem to be a
problem. I will create a patch which includes tests that will ensure
that .set mips3 will work.
Glibc uses them exactly where it uses 32-bit LL/SC, except where a 64-bit
data type is involved. Of course that also requires a 64-bit ABI, either
n64 or n32, as these are 64-bit instructions -- from what you wrote thus
far I've gathered, perhaps incorrectly, that you've been using either or
both too, in addition to o32 -- is my understanding correct?
I used o32 and n32 for Linux programs and with the OS of the PS2. I tried to use o64 for the Linux kernel, but I've got problems with the 64 bit TLBs and that the type "long" is used for pointers, so I decided to use the o32 kernel which was patched to support n32 user space. I never tried n64. I was not able to find an option to enable n64 in the gcc 4.3 (I mean more than -mabi=n64; i.e. multilib).
Post by Maciej W. Rozycki
How are unsupported floating-point data treated, BTW -- what results does
the processor produce for floating-point encodings that would normally be
interpreted as not-a-number, an infinity or a denormalised number? Are
they treated numerically, beyond the range IEEE-754 single provides? You
say that the Invalid Operation exception is not raised, so they cannot be
trapped and emulated.
The manual says that the traps can be emulated by a conditional trap instructions. I saw such code before, but I can't remember if this was x86, ARM, mipsel or r5900.
I tested the calculation with the type "float".
ABI o32 with -mhard-float and -msingle-float produces the following results:
1.000000 (0x3f800000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / nan (0x7fc00000) = 0.000000 (0x00000000)
1.000000 (0x3f800000) + 1.000000 (0x3f800000) = 2.000000 (0x40000000)
1.000000 (0x3f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + inf (0x7f800000) = nan (0x7fffffff)
inf (0x7f800000) + -inf (0xff800000) = 0.000000 (0x00000000)
nan (0x7fc00000) + nan (0x7fc00000) = nan (0x7fffffff)
nan (0x7fc00000) + nan (0xffc00000) = 0.000000 (0x00000000)

The r5900 manual calls the result of 0/0 Fmax. So 0x7fffffff seems to be Fmax.

ABI n32 with -msoft-float and -mdouble-float produces the following results (this should be correct):
1.000000 (0x3f800000) / 0.000000 (0x00000000) = inf (0x7f800000)
0.000000 (0x00000000) / 0.000000 (0x00000000) = nan (0x7f8fffff)
0.000000 (0x00000000) / nan (0x7fc00000) = nan (0x7fcfffff)
1.000000 (0x3f800000) + 1.000000 (0x3f800000) = 2.000000 (0x40000000)
1.000000 (0x3f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + -inf (0xff800000) = nan (0x7f8fffff)
nan (0x7fc00000) + nan (0x7fc00000) = nan (0x7fcfffff)
nan (0x7fc00000) + nan (0xffc00000) = nan (0x7fcfffff)

Just for comparison: x86_64, Intel(R) Core(TM) i7-2600 CPU
1.000000 (0x3f800000) / 0.000000 (0x00000000) = inf (0x7f800000)
0.000000 (0x00000000) / 0.000000 (0x00000000) = -nan (0xffc00000)
0.000000 (0x00000000) / nan (0x7fc00000) = nan (0x7fc00000)
1.000000 (0x3f800000) + 1.000000 (0x3f800000) = 2.000000 (0x40000000)
1.000000 (0x3f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + -inf (0xff800000) = -nan (0xffc00000)
nan (0x7fc00000) + nan (0x7fc00000) = nan (0x7fc00000)
nan (0x7fc00000) + -nan (0xffc00000) = -nan (0xffc00000)
Post by Maciej W. Rozycki
Post by Jürgen Urban
This unit is not IEEE 754 compatible.
Supports single-precision format as defined in the IEEE 754
specification.
Post by Jürgen Urban
Plus/Minus "0" in line with IEEE 754 specification are supported.
NaNs and plus/minus infinities are not supported.
No hardware exception mechanism to affect instruction execution.
The FPU only supports "Rounding towards 0".
... the results may differ from the IEEE 754 Rounding to 0. This
difference is usually restricted to the least significant bit only.
NaN, +inf, -inf and denormalized numbers are not supported
The FPU does not use the Guard, Round and Sticky bits during
computations.
Post by Jürgen Urban
Invalid Operation exceptions due to NaN, +/-inf and Inexact exceptions
are not supported.
- 0/0
- Sqrt (negative number)
- Division by zero
- Exponent overflow
- Exponent underflow
- Conversion of Floating-point to Integer Overflow
OK, I guess you could still make it a supported processing unit with GCC,
however I can't speak for GCC maintainers as to whether they would be
willing to accept such support for inclusion. Both ISO C and GCC do
permit non-IEEE-754 floating point arithmetic (cf. VAX, that does not
support qNaNs, infinities or denormals; sNaNs in a sense are supported).
You'd probably have to bail out on sources referring to unsupported
features, e.g. __builtin_inf; I reckon the VAX port does that.
I am thinking on using the MIPS soft float ABI. This means everything is passed in GPRs. Then I plan to implement the libgcc softfloat functions in an optimized way using the FPU when possible.

Best regards
Jürgen
Maciej W. Rozycki
2013-01-17 23:22:36 UTC
Permalink
Hi Jürgen,
Post by Jürgen Urban
Post by Maciej W. Rozycki
Glibc uses them exactly where it uses 32-bit LL/SC, except where a 64-bit
data type is involved. Of course that also requires a 64-bit ABI, either
n64 or n32, as these are 64-bit instructions -- from what you wrote thus
far I've gathered, perhaps incorrectly, that you've been using either or
both too, in addition to o32 -- is my understanding correct?
I used o32 and n32 for Linux programs and with the OS of the PS2. I
tried to use o64 for the Linux kernel, but I've got problems with the 64
bit TLBs and that the type "long" is used for pointers, so I decided to
use the o32 kernel which was patched to support n32 user space. I never
tried n64. I was not able to find an option to enable n64 in the gcc 4.3
(I mean more than -mabi=n64; i.e. multilib).
Well, -mabi= is exactly the option that switches between the three ABIs
supported under Linux. The o64 ABI is not supported with Linux, neither
for userland programs nor for building the kernel.

The kernel can be built either for 32-bit or for 64-bit support. In the
former case the resulting binary is o32 and can only run o32 user
programs. In the latter case the kernel binary is n64 and can run n64
user programs, and can optionally be configured to run either or both o32
and n32 user programs as well.

Of course to be able to build and run user programs for the respective
ABIs you need to have the right development environment and shared
libraries installed.

For 32-bit systems it's easy as you only have one ABI to choose from.
The mips-unknown-linux-gnu and mipsel-unknown-linux-gnu targets are the
canonical configuration triplets to configure all the pieces for, starting
from binutils and GCC, for the big and the little endianness respectively.
That'll build an o32 development environment.

For 64-bit systems all the three ABIs are supported so it gets a tad more
complicated. The mips64-unknown-linux-gnu mips64el-unknown-linux-gnu
targets are the canonical configuration triplets here and that'll build
binutils and GCC that support all the three ABIs. Then the compiler
chooses among them by using different library paths -- there are multiple
of them for each of the ABIs supported, but the rule of thumb is the
actual directories where the libraries are located in is called "lib" for
the n32 ABI, "lib64" for the n64 ABI and "lib32" for the o32 ABI. You
need to take that into account and set the correct library path -- e.g.
with --libdir=\${exec_prefix}/lib64 for GNU autoconf scripts and the n64
ABI -- when building further libraries as they are not normally
automatically built for all the three ABIs. Of course you then need to
include -mabi=n64 among CFLAGS somewhere too.
Post by Jürgen Urban
Post by Maciej W. Rozycki
How are unsupported floating-point data treated, BTW -- what results does
the processor produce for floating-point encodings that would normally be
interpreted as not-a-number, an infinity or a denormalised number? Are
they treated numerically, beyond the range IEEE-754 single provides? You
say that the Invalid Operation exception is not raised, so they cannot be
trapped and emulated.
The manual says that the traps can be emulated by a conditional trap instructions. I saw such code before, but I can't remember if this was x86, ARM, mipsel or r5900.
Yeah, but then you'd have to put these explicit trap instructions
througout code somehow -- it's not like the affected floating-point
instructions are going to trap themselves as expected.
Post by Jürgen Urban
I tested the calculation with the type "float".
1.000000 (0x3f800000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / nan (0x7fc00000) = 0.000000 (0x00000000)
1.000000 (0x3f800000) + 1.000000 (0x3f800000) = 2.000000 (0x40000000)
1.000000 (0x3f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + inf (0x7f800000) = nan (0x7fffffff)
inf (0x7f800000) + -inf (0xff800000) = 0.000000 (0x00000000)
nan (0x7fc00000) + nan (0x7fc00000) = nan (0x7fffffff)
nan (0x7fc00000) + nan (0xffc00000) = 0.000000 (0x00000000)
The r5900 manual calls the result of 0/0 Fmax. So 0x7fffffff seems to be Fmax.
So presumably you can get 0x7fffffff as an arithmetic result of a
calculation involving regular numbers as well, right? Say 0x7f7ffffe +
0x74000000 (using the binary-encoded notation)? That would be beyond the
IEEE-754 single range.
Post by Jürgen Urban
Post by Maciej W. Rozycki
OK, I guess you could still make it a supported processing unit with GCC,
however I can't speak for GCC maintainers as to whether they would be
willing to accept such support for inclusion. Both ISO C and GCC do
permit non-IEEE-754 floating point arithmetic (cf. VAX, that does not
support qNaNs, infinities or denormals; sNaNs in a sense are supported).
You'd probably have to bail out on sources referring to unsupported
features, e.g. __builtin_inf; I reckon the VAX port does that.
I am thinking on using the MIPS soft float ABI. This means everything is
passed in GPRs. Then I plan to implement the libgcc softfloat functions
in an optimized way using the FPU when possible.
That's sounds like a good idea to me, although you'll probably still have
to sort out the issue of using the FPU for R5900 binaries, but not use it
by accident for regular MIPS binaries somehow. That could be handled by
the kernel, by enabling the FPU selectively, for example using the way I
previously outlined.

Maciej
Richard Sandiford
2013-01-19 10:53:28 UTC
Permalink
Post by Maciej W. Rozycki
Post by Jürgen Urban
I tested the calculation with the type "float".
1.000000 (0x3f800000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / nan (0x7fc00000) = 0.000000 (0x00000000)
1.000000 (0x3f800000) + 1.000000 (0x3f800000) = 2.000000 (0x40000000)
1.000000 (0x3f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + inf (0x7f800000) = nan (0x7fffffff)
inf (0x7f800000) + -inf (0xff800000) = 0.000000 (0x00000000)
nan (0x7fc00000) + nan (0x7fc00000) = nan (0x7fffffff)
nan (0x7fc00000) + nan (0xffc00000) = 0.000000 (0x00000000)
The r5900 manual calls the result of 0/0 Fmax. So 0x7fffffff seems to be Fmax.
So presumably you can get 0x7fffffff as an arithmetic result of a
calculation involving regular numbers as well, right? Say 0x7f7ffffe +
0x74000000 (using the binary-encoded notation)? That would be beyond the
IEEE-754 single range.
Yeah, if I recall correctly. We already support what I think is the
same format for SPU (spu_single_format), which I suppose makes sense
given its heritage. Hopefully the format itself won't need much
work in GCC.

Richard
Jürgen Urban
2013-01-20 21:42:41 UTC
Permalink
Hello Maciej,
Post by Maciej W. Rozycki
Post by Jürgen Urban
I tested the calculation with the type "float".
ABI o32 with -mhard-float and -msingle-float produces the following
1.000000 (0x3f800000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / 0.000000 (0x00000000) = nan (0x7fffffff)
0.000000 (0x00000000) / nan (0x7fc00000) = 0.000000 (0x00000000)
1.000000 (0x3f800000) + 1.000000 (0x3f800000) = 2.000000 (0x40000000)
1.000000 (0x3f800000) + inf (0x7f800000) = inf (0x7f800000)
inf (0x7f800000) + inf (0x7f800000) = nan (0x7fffffff)
inf (0x7f800000) + -inf (0xff800000) = 0.000000 (0x00000000)
nan (0x7fc00000) + nan (0x7fc00000) = nan (0x7fffffff)
nan (0x7fc00000) + nan (0xffc00000) = 0.000000 (0x00000000)
The r5900 manual calls the result of 0/0 Fmax. So 0x7fffffff seems to be
Fmax.
So presumably you can get 0x7fffffff as an arithmetic result of a
calculation involving regular numbers as well, right? Say 0x7f7ffffe +
0x74000000 (using the binary-encoded notation)? That would be beyond the
IEEE-754 single range.
The FPU of the r5900 calculates the following:
340282306073709652508363335590014353408.000000 (0x7f7ffffd) + 40564819207303340847894502572032.000000 (0x74000000) = 340282346638528859811704183484516925440.000000 (0x7f7fffff)
340282326356119256160033759537265639424.000000 (0x7f7ffffe) + 40564819207303340847894502572032.000000 (0x74000000) = inf (0x7f800000)
340282346638528859811704183484516925440.000000 (0x7f7fffff) + 40564819207303340847894502572032.000000 (0x74000000) = inf (0x7f800000)
inf (0x7f800000) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7f800001)
nan (0x7f800001) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7f800002)
nan (0x7f900000) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7f900001)
nan (0x7f900001) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7f900002)
nan (0x7ffffff1) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7ffffff2)
nan (0x7ffffffc) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7ffffffd)
nan (0x7ffffffd) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7ffffffe)
nan (0x7ffffffe) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7fffffff)
nan (0x7fffffff) + 40564819207303340847894502572032.000000 (0x74000000) = nan (0x7fffffff)

So it seems that it interprets nan and inf as normal numbers, but it stops at 0x7fffffff. So 0x7fffffff should be interpreted as overflow.

Best regards
Jürgen

Continue reading on narkive:
Loading...