[comp.sys.amiga.programmer] SAS/C Assembler bug + FPU quiz

val@netw23.uucp (Oberon Kenobi) (05/12/91)

     I am a programmer who uses C mostly, but I use assembler for things that
"are difficult or impossible in pure C."  I sometimes resort to optimizing in
assembler.  (The 90/10 rule: 90% of the code is run 10% of the time, and 10% of
the code is run 90% of the time.)  It's more portable to program in a high
level language.

     Now, back to the purpose of this posting.  Following is actual code
compiled and run on an Amiga 3000.  (NOTE: it requires a 68881 or 68882 to run
this code on any system.  The A3000/16 has a 68881, and the A3000/25 has a
68882.)  The purpose of this code is to:
	1) demonstrate a bug in the SAS/C Assembler
	2) give a small quiz on how well you know what's going on in your CPU
	3) provide some useful code

     1) Notice the macro definition (consts.asm).  The commented line is what I
wanted to do, but the assembler has a bug.  No matter which floating poing
constant I ask for, I get constant #0 (pi).  (Beware of this problem when
writing your own code.)  This was frustrating, so I had to actually insert the
instruction words myself.

     2) Notice the self-modifying version, which was the first that I tried. 
All caches were turned off, but it was still one constant behind.  (i.e.: In my
loop, I ask for $3F and I get pi, $3E -> 10^4096, $3D ->10^2048, etc..)  Please
don't mail me nor post the answer.  This is a quiz for which I will post the
answer in two weeks.

     3) This provides a way of getting these floating point constants as
accurately as possible without having to type them into your code.  There are
trade-offs as always.  I was using it to try to find out, for curiosity's sake,
what the undocumented floating point constants are.  (Most of them appear to be
zero by the way.)  The FMOVECR macro may be used in C, but note the cautions in
the SAS/C manual on using the emit() built-in function.

fpconsts.c======================================================================

#include <stdio.h>

/* FMOVECR macro not actually tested, but it should work. */
#define	FMOVECR(fp_reg,const)	emit(0xF200);		\
				emit(0x5C00 | ((fp_reg)<<6) | ((const)&0x3F) )

extern  double  fpconst(int i);

main()
{
int     i;
  for(i=0x3f; i>=0; --i)
    printf("0x%02x\t=%g\n",i,fpconst(i));
}

consts.asm======================================================================

        macro
        retcr   const           ; Return constant register in FP0
;       fmovecr.x const,fp0     ; Move constant to fp0
        dc.w    $F200
        dc.w    $5c00+const     ; Because of a bug in the SAS/C assembler
        rts
        nop                     ; Cause alignment on 4-word (8-byte) boundary
        endm


        csect   text
    xdef        _fpconst        ; Parameter on top of stack entry point
    xdef        _fpconst_d0     ; Parameter-in-R0 entry point
    xdef        _fpconst_sm     ; Self-modifying version
    xdef        _fpconst_sm_r0  ; Parameter-in-R0 entry point for self-modifying V


        csect   code
_fpconst:
        move.l  4(a7),d0	; Get it from the stack if called that way
_fpconst_d0:
        and.l   #63,d0          ; Only pay attention to the lower six bits
        lsl.l   #3,d0           ; Multiply it by eight to get an offset
        jmp     2(pc,d0)        ; Jump to appropriate constant-fetch code
case0:  retcr   $00
        retcr   $01
        retcr   $02
        retcr   $03
        retcr   $04
        retcr   $05
        retcr   $06
        retcr   $07
        retcr   $08
        retcr   $09
        retcr   $0A
        retcr   $0B
        retcr   $0C
        retcr   $0D
        retcr   $0E
        retcr   $0F
        retcr   $10
        retcr   $11
        retcr   $12
        retcr   $13
        retcr   $14
        retcr   $15
        retcr   $16
        retcr   $17
        retcr   $18
        retcr   $19
        retcr   $1A
        retcr   $1B
        retcr   $1C
        retcr   $1D
        retcr   $1E
        retcr   $1F
        retcr   $20
        retcr   $21
        retcr   $22
        retcr   $23
        retcr   $24
        retcr   $25
        retcr   $26
        retcr   $27
        retcr   $28
        retcr   $29
        retcr   $2A
        retcr   $2B
        retcr   $2C
        retcr   $2D
        retcr   $2E
        retcr   $2F
        retcr   $30
        retcr   $31
        retcr   $32
        retcr   $33
        retcr   $34
        retcr   $35
        retcr   $36
        retcr   $37
        retcr   $38
        retcr   $39
        retcr   $3A
        retcr   $3B
        retcr   $3C
        retcr   $3D
        retcr   $3E
        retcr   $3F


_fpconst_sm:
        move.l  4(a7),d0        ; Get it from the stack if called that way
_fpconst_sm_r0:
        and.b   #63,d0          ; Only pay attention to the lower six bits
        lea     7(pc),a0        ; The location that is going to be changed
        move.b  d0,(a0)         ; Change the location
        fmovecr.x #0,fp0        ; Move the constant
        rts

        end

constants======================================================================

     ROM Constants from FMOVECR instruction in "Programmer's Reference Manual"
(M68000PM/AD) from Motorola.  (Quoted without permission.)

	Offset	Constant
	------	--------
	$00	pi
	$0B	log10(2)
	$0C	e
	$0D	log2(e)
	$0E	log10(e)
	$0F	0.0
	$30	ln(2)
	$31	ln(10)
	$32	10^0
	$33	10^1
	$34	10^2
	$35	10^4
	$36	10^8
	$37	10^16
	$38	10^32
	$39	10^64
	$3A	10^128
	$3B	10^256
	$3C	10^512
	$3D	10^1024
	$3E	10^2048
	$3F	10^4096

The on-chip ROM contains other constants useful only to the on-chip microcode
routines.  The values contained at offsets other than those defined above are
reserved for the use of Motorola, and may be different on various mask sets of
the FPCP.


signature=======================================================================

____  ____  ____ |=============================================================|
\   \/    \/   / |   "vi?  Because I don't have a real editor." -- U*x user    |
 \Weber  State/  |=============================================================|
  \University/   | Internet: val@csulx.weber.edu, val@net23.weber.edu   |Oberon|
   \___/\___/    |   Usenet: uunet!viusys!uxui!unislc!bryce!netw23!val  |Kenobi|
Computer Science |=============================================================|

end of message==================================================================

val@netw23.uucp (Oberon Kenobi) (05/26/91)

In article <177235@netw23.uucp>, val@netw23.uucp (Oberon Kenobi) writes:
> ...
>      2) Notice the self-modifying version, which was the first that I tried. 
> All caches were turned off, but it was still one constant behind.  (i.e.: In
> my loop, I ask for $3F and I get pi, $3E -> 10^4096, $3D ->10^2048, etc..)
> Please don't mail me nor post the answer.  This is a quiz for which I will
> post the answer in two weeks.
> ...
> consts.asm====================================================================
> ...
> _fpconst_sm:
>         move.l  4(a7),d0        ; Get it from the stack if called that way
> _fpconst_sm_r0:
>         and.b   #63,d0          ; Only pay attention to the lower six bits
>         lea     7(pc),a0        ; The location that is going to be changed
>         move.b  d0,(a0)         ; Change the location
	  fnop			  ; Flush the FPU pipeline
>         fmovecr.x #0,fp0        ; Move the constant
>         rts
> ...
     Two weeks are up.  As I promised, here is the answer:
     Since the 68030 has a three instruction pipeline (I think), the FMOVECR is
being fetched before the instruction is being changed.  The next time it
executes the instruction, it gets the instruction as changed by the previous
iteration.  The FNOP effectively flushes the execution pipeline.  (I haven't
actually tried it, but this should work.)

-- 
____  ____  ____ |=============================================================|
\   \/    \/   / |   "vi?  Because I don't have a real editor." -- U*x user    |
 \Weber  State/  |=============================================================|
  \University/   |Oberon| Internet: val@csulx.weber.edu, val@net23.weber.edu   |
   \___/\___/    |Kenobi|   Usenet: uunet!viusys!uxui!unislc!bryce!netw23!val  |
Computer Science |=============================================================|