Subject: Problem and fix for systat/top/ps
To: None <port-vax@netbsd.org>
From: Johnny Billquist <bqt@softjar.se>
List: port-vax
Date: 03/13/2007 18:48:04
I looked at the problems with top and family today, and located the problem.
In a way it's confusing that it exists, but I have an easy solution to 
it, anyway.

The problem comes from the log() function in libm, and the code starts 
like this:

---
         if (x <= 0) {
                 if (_IEEE && x == zero) /* log(0) = -Inf */
                         return (-one/zero);
                 else if (_IEEE)         /* log(neg) = NaN */
                         return (zero/zero);
                 else if (x == zero)     /* NOT REACHED IF _IEEE */
                         return (infnan(-ERANGE));
                 else
                         return (infnan(EDOM));
         } else if (!finite(x)) {
                 if (_IEEE)              /* x = NaN, Inf */
                         return (x+x);
                 else
                         return (infnan(ERANGE));
         }
---

The interesting thing is, if you look at the produced code, it looks 
like this:

---
00000228 <log>:
  228:   00 00           Entry mask 0x0000 = < >
  22a:   c2 04 5e        subl2 $0x4,sp
  22d:   70 ac 04 50     movd 0x4(ap),r0
  231:   73 50           tstd r0
  233:   15 0d           bleq 242 <log+0x1a>
  235:   dd 22           pushl $0x22
  237:   fb 01 ef c2     calls $0x1,0 <__log__D>
  23b:   fd ff ff
  23e:   6e 50 50        cvtld r0,r0
  241:   04              ret
  242:   73 50           tstd r0
  244:   13 0d           beql 253 <log+0x2b>
  246:   dd 21           pushl $0x21
  248:   fb 01 ef b1     calls $0x1,0 <__log__D>
  24c:   fd ff ff
  24f:   6e 50 50        cvtld r0,r0
  252:   04              ret
  253:   d2 21 7e        mcoml $0x21,-(sp)
  256:   fb 01 ef a3     calls $0x1,0 <__log__D>
  25a:   fd ff ff
  25d:   6e 50 50        cvtld r0,r0
  260:   04              ret
---

(all the three "calls $0x1,0" are really calls to infnan.)

Which is rather interesting. Looking at the produced code, it appears 
that the test:
   if (!finite(x)) {
gets optimized away, and is assumed to always be true, so that branch is 
always taken. In effect, the log() function always returns infnan() 
right away. And infnan() on the vax is designed to always give an 
illegal instruction trap.

Now, I haven't really understood how on earth gcc can think that 
finite() itself would always be false, but therein lies the problem. 
I've searched the whole source tree for macro definitions of finite 
without finding any. Anyway, adding the following line before the log() 
function in n_log.c fixes everything:

#define finite(x) 1

And, based on the code in n_support.c, finite() should always return 
true on a VAX.

There are finite() calls in other pieces of code in noieee_src as well, 
but nothing else seems to be used by any code I've stumbled on so far, 
but this fix is applicable to all of those files.

So this leaves us with one question:

Why does gcc optimize away the call to finite()? Is there a built-in 
macro in gcc for this on the vax perhaps???

After this fix, what's left is that gcc crash if you turn on any 
optimizations on the VAX. Someone who knows gcc needs to help out with 
this one. And we'd probably want the PIC ability back in gcc for VAX 
again, so that we can have shared libraries.

Anyone feel like helping out? :-)

	Johnny