On Fri, 2008-09-05 at 11:18 +0200, Henning Rogge wrote:
> Am Freitag 05 September 2008 11:02:26 schrieb Bernd Petrovitsch:
> > Basically yes (and I can as well live with that).
> > I purposely normalized it to ==-1/==0/==1 similar to the other function.
> > And it's not that uncommon since e.g. strcmp() also return s <0/==0/>0.
> >
> > So it's a question of - to exaggerate a bit;-) - "API design".
> >
> > That's also why I mentioned the sgn() function which is the
> > "normalization" part.
> I don't know anything about x86 assembler, but on my old Amiga (motorola 68000 
> cpu) it was faster to do a >0,==0,<0 than to compare to a number to 1 (as an 
> example). This might be the reason C never used normalized output.

It's similar (and I suppose for most other architectures too) as
conditional branches usually implemented over flags which are set on
(usually) all arithmetic operations to avoid extra compares.
- There is a ZERO-flag (which is just an "or" of all bits - cheap and 
  fast in silicon)
- < 0 is stored in the SIGN-flag (and is merely the copy of the most
  valued bit as we have twos-complement and that will IMHO never
  change[0])
And the 6 conditional branch operations (<0, ==0, >0, <=0, !=0, >=0)
just test the appropriate bits for the appropriate values.

Testing on ==1/==-1 is more effort as the CPU needs one more compare of
the result. And that compare needs usually RAM access (to load the -1 or
1) which is
- quite expensive an all archs due an additional memory access to load
  the value,
- clobbers an additional register on RISC CPUs (which may not really
  hurt if you have lots of them)
Some CPUs (e.g. SPARC IIRC) have a register hard-wired to "0" (which is
returned if you read it and all you write is discarded).

The rationale for such a "zero register" (R0) is (and I don't know if
CISC CPUs ever had such a thing)
- 0 is often needed (but as all asm hackers know, "XOR R9, R9" also
  produces 0 in that register). But a "mov R9,R0" may not block an ALU
  on modern CPUs.
- Sparc has a 3 address assembler. If you have such a "/dev/null"
  register, you can implement a(n assembler) "compare" as a(n assembler)
  "subtract" with the same machine code (saving something there) and
  discard the result by storing it in the "zero register".

But x86_64 doesn't have one AFAIK (but I don't know x86_634 asm - I
played around with it in the times when i386 and i486 CPUs where
bleeding edge - and run in real mode - ages ago).
With such a zero register, a ==1/==-1 can avoid the memory access (but
clobbers the register again if you do "MOV R9,R0;DEC R9" or so).
And as far as I understand the thinking of hardware designers, they
won't sacrifice 3 registers for -1, 0 and 1 (perhaps if we are at 128
registers ....).

Ooops, sorry for off-topic,
	Bernd

[0]: Because e.g. add's and sub' are identical in hardware and that
     saves space on the CPU.
-- 
Firmix Software GmbH                   http://www.firmix.at/
mobil: +43 664 4416156                 fax: +43 1 7890849-55
          Embedded Linux Development and Services




