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 |=============================================================|