mirror of
https://github.com/cc65/cc65.git
synced 2025-02-20 14:29:03 +00:00
beginning of float libraries and test programs
This commit is contained in:
parent
1fb7c896b4
commit
00fabb8caf
3
test/float/.gitignore
vendored
Normal file
3
test/float/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.bin
|
||||
*.prg
|
||||
|
197
test/float/Makefile
Normal file
197
test/float/Makefile
Normal file
@ -0,0 +1,197 @@
|
||||
|
||||
OPT=
|
||||
|
||||
FILES=\
|
||||
quick.prg \
|
||||
\
|
||||
float-minimal.prg \
|
||||
float-minimal.bin \
|
||||
float-minimal.woz.bin \
|
||||
\
|
||||
float-basic.prg \
|
||||
float-basic.bin \
|
||||
float-basic.woz.bin \
|
||||
\
|
||||
float-basic-cmp.prg \
|
||||
float-basic-cmp.bin \
|
||||
float-basic-cmp.woz.bin
|
||||
|
||||
#
|
||||
# floattest.prg
|
||||
|
||||
##############################################################################
|
||||
HEADER=\
|
||||
include/_float.h \
|
||||
include/math.h
|
||||
|
||||
CBMRUNTIME=\
|
||||
cbmkernal/float.s \
|
||||
cbmkernal/ftoa.c \
|
||||
cbmkernal/ffloor.c \
|
||||
cbmkernal/cc65wrapper.s
|
||||
|
||||
IEEERUNTIME=\
|
||||
ieee754/feaxint.s \
|
||||
ieee754/feaxlong.s \
|
||||
ieee754/fbnegeax.s \
|
||||
ieee754/eaxufloat.s \
|
||||
ieee754/eaxfloat.s \
|
||||
ieee754/axufloat.s \
|
||||
ieee754/axfloat.s \
|
||||
ieee754/aufloat.s \
|
||||
ieee754/afloat.s \
|
||||
ieee754/ftosaddeax.s \
|
||||
ieee754/ftossubeax.s \
|
||||
ieee754/ftosdiveax.s \
|
||||
ieee754/ftosmuleax.s \
|
||||
ieee754/ftoseqeax.s \
|
||||
ieee754/ftosneeax.s \
|
||||
ieee754/ftosgteax.s \
|
||||
ieee754/ftoslteax.s \
|
||||
ieee754/ftosgeeax.s \
|
||||
ieee754/ftosleeax.s \
|
||||
ieee754/_ftostr.c
|
||||
|
||||
WOZRUNTIME=\
|
||||
woz/feaxint.s \
|
||||
woz/feaxlong.s \
|
||||
woz/fbnegeax.s \
|
||||
woz/eaxufloat.s \
|
||||
woz/eaxfloat.s \
|
||||
woz/axufloat.s \
|
||||
woz/axfloat.s \
|
||||
woz/aufloat.s \
|
||||
woz/afloat.s \
|
||||
woz/ftosaddeax.s \
|
||||
woz/ftossubeax.s \
|
||||
woz/ftosdiveax.s \
|
||||
woz/ftosmuleax.s \
|
||||
woz/ftoseqeax.s \
|
||||
woz/ftosneeax.s \
|
||||
woz/ftosgteax.s \
|
||||
woz/ftoslteax.s \
|
||||
woz/ftosgeeax.s \
|
||||
woz/ftosleeax.s \
|
||||
woz/_ftostr.c \
|
||||
woz/wozfp.s
|
||||
|
||||
##############################################################################
|
||||
|
||||
all: $(FILES)
|
||||
|
||||
float-minimal.s: float-minimal.c $(HEADER) $(IEEERUNTIME)
|
||||
cc65 $(OPT) -t sim6502 -I ./include --add-source -o float-minimal.s float-minimal.c
|
||||
float-minimal.bin: float-minimal.s $(HEADER) $(IEEERUNTIME)
|
||||
cl65 $(OPT) -t sim6502 -I ./include -o float-minimal.bin float-minimal.s $(IEEERUNTIME)
|
||||
|
||||
float-basic.s: float-basic.c $(HEADER) $(IEEERUNTIME)
|
||||
cc65 $(OPT) -t sim6502 -I ./include --add-source -o float-basic.s float-basic.c
|
||||
float-basic.bin: float-basic.s $(HEADER) $(IEEERUNTIME)
|
||||
cl65 $(OPT) -t sim6502 -I ./include -o float-basic.bin float-basic.s $(IEEERUNTIME)
|
||||
|
||||
float-basic-cmp.s: float-basic-cmp.c $(HEADER) $(IEEERUNTIME)
|
||||
cc65 $(OPT) -t sim6502 -I ./include --add-source -o float-basic-cmp.s float-basic-cmp.c
|
||||
float-basic-cmp.bin: float-basic-cmp.s $(HEADER) $(IEEERUNTIME)
|
||||
cl65 $(OPT) -t sim6502 -I ./include -o float-basic-cmp.bin float-basic-cmp.s $(IEEERUNTIME)
|
||||
|
||||
###############################################################################
|
||||
float-minimal.woz.s: float-minimal.c $(HEADER) $(WOZRUNTIME)
|
||||
cc65 $(OPT) -t sim6502 -I ./include --add-source -o float-minimal.woz.s float-minimal.c
|
||||
float-minimal.woz.bin: float-minimal.woz.s $(HEADER) $(WOZRUNTIME)
|
||||
cl65 $(OPT) -t sim6502 -I ./include -o float-minimal.woz.bin float-minimal.woz.s $(WOZRUNTIME)
|
||||
|
||||
float-basic.woz.s: float-basic.c $(HEADER) $(WOZRUNTIME)
|
||||
cc65 $(OPT) -t sim6502 -I ./include --add-source -o float-basic.woz.s float-basic.c
|
||||
float-basic.woz.bin: float-basic.woz.s $(HEADER) $(WOZRUNTIME)
|
||||
cl65 $(OPT) -t sim6502 -I ./include -o float-basic.woz.bin float-basic.woz.s $(WOZRUNTIME)
|
||||
|
||||
float-basic-cmp.woz.s: float-basic-cmp.c $(HEADER) $(WOZRUNTIME)
|
||||
cc65 $(OPT) -t sim6502 -I ./include --add-source -o float-basic-cmp.woz.s float-basic-cmp.c
|
||||
float-basic-cmp.woz.bin: float-basic-cmp.woz.s $(HEADER) $(WOZRUNTIME)
|
||||
cl65 $(OPT) -t sim6502 -I ./include -o float-basic-cmp.woz.bin float-basic-cmp.woz.s $(WOZRUNTIME)
|
||||
|
||||
###############################################################################
|
||||
float-minimal.c64.s: float-minimal.c $(HEADER) $(CBMRUNTIME)
|
||||
cc65 $(OPT) -DCONIO -t c64 -I ./include -I ./cbmkernal --add-source -o float-minimal.c64.s float-minimal.c
|
||||
float-minimal.prg: float-minimal.c64.s $(HEADER) $(CBMRUNTIME)
|
||||
cl65 $(OPT) -t c64 -I ./include -I ./cbmkernal -o float-minimal.prg float-minimal.c64.s $(CBMRUNTIME)
|
||||
|
||||
float-basic.c64.s: float-basic.c $(HEADER) $(CBMRUNTIME)
|
||||
cc65 $(OPT) -DCONIO -t c64 -I ./include -I ./cbmkernal --add-source -o float-basic.c64.s float-basic.c
|
||||
float-basic.prg: float-basic.c64.s $(HEADER) $(CBMRUNTIME)
|
||||
cl65 $(OPT) -t c64 -I ./include -I ./cbmkernal -o float-basic.prg float-basic.c64.s $(CBMRUNTIME)
|
||||
|
||||
float-basic-cmp.c64.s: float-basic-cmp.c $(HEADER) $(CBMRUNTIME)
|
||||
cc65 $(OPT) -DCONIO -t c64 -I ./include -I ./cbmkernal --add-source -o float-basic-cmp.c64.s float-basic-cmp.c
|
||||
float-basic-cmp.prg: float-basic-cmp.c64.s $(HEADER) $(CBMRUNTIME)
|
||||
cl65 $(OPT) -t c64 -I ./include -I ./cbmkernal -o float-basic-cmp.prg float-basic-cmp.c64.s $(CBMRUNTIME)
|
||||
|
||||
floattest.c64.s: floattest.c $(HEADER) $(CBMRUNTIME)
|
||||
cc65 $(OPT) -DCONIO -t c64 -I ./include -I ./cbmkernal --add-source -o floattest.c64.s floattest.c
|
||||
floattest.prg: floattest.c64.s $(HEADER) $(CBMRUNTIME)
|
||||
cl65 $(OPT) -t c64 -I ./include -I ./cbmkernal -o floattest.prg floattest.c64.s $(CBMRUNTIME)
|
||||
|
||||
quick.c64.s: quick.c $(HEADER) $(CBMRUNTIME)
|
||||
cc65 $(OPT) -DCONIO -t c64 -I ./include -I ./cbmkernal --add-source -o quick.c64.s quick.c
|
||||
quick.prg: quick.c64.s $(HEADER) $(CBMRUNTIME)
|
||||
cl65 $(OPT) -t c64 -I ./include -I ./cbmkernal -o quick.prg quick.c64.s $(CBMRUNTIME)
|
||||
runquick: quick.prg
|
||||
x64sc -autostartprgmode 1 quick.prg
|
||||
###############################################################################
|
||||
gccminimal: float-minimal.c gccstubs.c
|
||||
gcc -I ./include "-D__fastcall__= " -o minimal float-minimal.c gccstubs.c -lm
|
||||
gccbasic: float-basic.c gccstubs.c
|
||||
gcc -I ./include "-D__fastcall__= " -o basic float-basic.c gccstubs.c -lm
|
||||
gccbasiccmp: float-basic-cmp.c gccstubs.c
|
||||
gcc -I ./include "-D__fastcall__= " -o basiccmp float-basic-cmp.c gccstubs.c -lm
|
||||
gccfloattest: floattest.c gccstubs.c
|
||||
gcc -I ./include "-D__fastcall__= " -o floattest floattest.c gccstubs.c -lm
|
||||
|
||||
rungcc: gccminimal gccbasic gccbasiccmp gccfloattest
|
||||
./minimal
|
||||
./basic
|
||||
./basiccmp
|
||||
./floattest
|
||||
|
||||
###############################################################################
|
||||
|
||||
runminimal: float-minimal.bin
|
||||
sim65 float-minimal.bin
|
||||
runbasic: float-basic.bin
|
||||
sim65 float-basic.bin
|
||||
runbasiccmp: float-basic-cmp.bin
|
||||
sim65 float-basic-cmp.bin
|
||||
|
||||
run: runminimal runbasic runbasiccmp
|
||||
sim65 float-minimal.bin
|
||||
sim65 float-basic.bin
|
||||
sim65 float-basic-cmp.bin
|
||||
|
||||
runwoz: float-minimal.woz.bin float-basic.woz.bin float-basic-cmp.woz.bin
|
||||
sim65 float-minimal.woz.bin
|
||||
sim65 float-basic.woz.bin
|
||||
sim65 float-basic-cmp.woz.bin
|
||||
|
||||
###############################################################################
|
||||
|
||||
clean:
|
||||
$(RM) ./minimal
|
||||
$(RM) ./basic
|
||||
$(RM) ./basiccmp
|
||||
$(RM) ./floattest
|
||||
|
||||
$(RM) $(FILES)
|
||||
|
||||
$(RM) quick.c64.s
|
||||
|
||||
$(RM) float-minimal.s
|
||||
$(RM) float-minimal.c64.s
|
||||
$(RM) float-minimal.woz.s
|
||||
|
||||
$(RM) float-basic.s
|
||||
$(RM) float-basic.c64.s
|
||||
$(RM) float-basic.woz.s
|
||||
|
||||
$(RM) float-basic-cmp.s
|
||||
$(RM) float-basic-cmp.c64.s
|
||||
$(RM) float-basic-cmp.woz.s
|
121
test/float/cbmkernal/cbmfp.h
Normal file
121
test/float/cbmkernal/cbmfp.h
Normal file
@ -0,0 +1,121 @@
|
||||
|
||||
#ifndef _CBMFS_H_
|
||||
#define _CBMFS_H_
|
||||
|
||||
|
||||
/*
|
||||
|
||||
format used in basic-variables
|
||||
|
||||
we dont use this format, although it saves one byte per variable, since that
|
||||
removes the need of constantly converting between both formats. (someday
|
||||
we may use an entire different (not cbm-specific), more accurate, format anyway)
|
||||
|
||||
sign
|
||||
exponent / /mantissa
|
||||
33333333 3 3222222222111111111110000000000
|
||||
98765432 1 0987654321098765432109876543210
|
||||
|
||||
* The exponent can be computed from bits 39-32 by subtracting 129 (!)
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char exponent;
|
||||
unsigned char mantissa[4];
|
||||
} FLOATBAS;
|
||||
|
||||
/* CBM format used in floating-point akku
|
||||
*
|
||||
* this format can be directly used with most CBM BASIC routines
|
||||
*
|
||||
* exponent mantissa sign
|
||||
* 44444444 33333333332222222222111111111100 00000000
|
||||
* 76543210 98765432109876543210987654321098 76543210
|
||||
*
|
||||
* truncated to 32bit:
|
||||
*
|
||||
* exponent mantissa sign
|
||||
* 33222222 2222111111111100 00000000
|
||||
* 10987654 3210987654321098 76543210
|
||||
*
|
||||
* The exponent can be computed from bits 47-40 by subtracting 129 (!) (130 = 2^1)
|
||||
* MSB of the Mantissa must always be 1, if it is 0 the value is 0
|
||||
*
|
||||
* 1.0 = exp=129, mantissa=$80
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char exponent;
|
||||
unsigned char mantissa[4];
|
||||
unsigned char sign;
|
||||
} FLOATFAC;
|
||||
|
||||
/* integer conversion functions */
|
||||
float __fastcall__ _ctof(char v);
|
||||
float __fastcall__ _utof(unsigned char v);
|
||||
float __fastcall__ _itof(int v);
|
||||
float __fastcall__ _stof(unsigned short v);
|
||||
|
||||
int __fastcall__ _ftoi(float f);
|
||||
|
||||
/* compare two floats, returns 0 if f = a, 1 if f < a, 255 if f > a */
|
||||
unsigned char __fastcall__ _fcmp(float f, float a);
|
||||
|
||||
/* arithmetic functions */
|
||||
float __fastcall__ _fadd(float f, float a); /* ftosaddeax */
|
||||
float __fastcall__ _fsub(float f, float a); /* ftossubeax */
|
||||
float __fastcall__ _fmul(float f, float a); /* ftosmuleax */
|
||||
float __fastcall__ _fdiv(float f, float a); /* ftosdiveax */
|
||||
|
||||
/* math functions */
|
||||
float __fastcall__ _fpow(float f, float a); /* math.h powf */
|
||||
float __fastcall__ _fsin(float s); /* math.h sinf */
|
||||
float __fastcall__ _fcos(float s); /* math.h cosf */
|
||||
|
||||
float __fastcall__ _flog(float s); /* math.h logf */
|
||||
float __fastcall__ _fexp(float s); /* math.h expf */
|
||||
float __fastcall__ _fsqr(float s); /* math.h sqrtf */
|
||||
|
||||
float __fastcall__ _ftan(float s); /* math.h tanf */
|
||||
float __fastcall__ _fatn(float s); /* math.h atanf */
|
||||
|
||||
float __fastcall__ _fabs(float s); /* math.h fabsf */
|
||||
|
||||
/* logical functions */
|
||||
float __fastcall__ _fand(float f, float a);
|
||||
float __fastcall__ _for(float f, float a);
|
||||
float __fastcall__ _fnot(float f);
|
||||
|
||||
/* misc */
|
||||
float __fastcall__ _frnd(float s);
|
||||
|
||||
float __fastcall__ _fneg(float f); /* negate (flip sign) */
|
||||
unsigned char __fastcall__ _ftestsgn(float f); /* FIXME */
|
||||
|
||||
float __fastcall__ _fsgn(float s);
|
||||
float __fastcall__ _fint(float s);
|
||||
|
||||
#if 0
|
||||
|
||||
typedef struct {
|
||||
unsigned char exponent;
|
||||
FLOATBAS coffs[8]; /* ? */
|
||||
} FLOATPOLY;
|
||||
|
||||
#define fpoly FLOATPOLY
|
||||
|
||||
/* polynom1 f(x)=a1+a2*x^2+a3*x^3+...+an*x^n */
|
||||
void _fpoly1(float *d,fpoly *a,float *x);
|
||||
/* polynom2 f(x)=a1+a2*x^3+a3*x^5+...+an*x^(2n-1) */
|
||||
void _fpoly2(float *d,fpoly *a,float *x);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
todo:
|
||||
|
||||
acos,asin,ceil,cosh,fmod,hypot,ldexp,log10,modf,poly,pow10,sinh
|
||||
tanh,cabs,_matherr,matherr,
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
388
test/float/cbmkernal/cc65wrapper.s
Normal file
388
test/float/cbmkernal/cc65wrapper.s
Normal file
@ -0,0 +1,388 @@
|
||||
|
||||
.import __ctof
|
||||
.import __utof
|
||||
.import __itof
|
||||
.import __stof
|
||||
|
||||
; 8bit signed -> float
|
||||
.export afloat
|
||||
afloat:
|
||||
jmp __ctof
|
||||
|
||||
; 8bit unsigned -> float
|
||||
.export aufloat
|
||||
aufloat:
|
||||
jmp __utof
|
||||
|
||||
; 16bit signed -> float
|
||||
.export axfloat
|
||||
axfloat:
|
||||
jmp __itof
|
||||
|
||||
; 16bit unsigned -> float
|
||||
.export axufloat
|
||||
axufloat:
|
||||
jmp __stof
|
||||
|
||||
; FIXME: this might be more accurate when done directly in one step (but the
|
||||
; kernal can not do this for 32bit)
|
||||
; 32bit signed -> float
|
||||
.importzp sreg, tmp1
|
||||
.import pusheax
|
||||
|
||||
.export eaxfloat
|
||||
eaxfloat:
|
||||
|
||||
sta tmp1
|
||||
|
||||
lda sreg
|
||||
pha
|
||||
lda sreg+1
|
||||
pha
|
||||
|
||||
; get lower 16bit
|
||||
lda tmp1
|
||||
|
||||
; convert lower 16 bit
|
||||
jsr __stof
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; / 65536
|
||||
ldx #$00
|
||||
lda #$80
|
||||
sta sreg
|
||||
lda #$47
|
||||
sta sreg+1
|
||||
|
||||
jsr __fdiv
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; get higher 16bit
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
; convert higher 16 bit
|
||||
jsr __itof
|
||||
|
||||
jsr __fadd
|
||||
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; * 65536
|
||||
ldx #$00
|
||||
lda #$80
|
||||
sta sreg
|
||||
lda #$47
|
||||
sta sreg+1
|
||||
|
||||
jmp __fmul
|
||||
|
||||
; FIXME: this might be more accurate when done directly in one step (but the
|
||||
; kernal can not do this for 32bit)
|
||||
; 32bit unsigned -> float
|
||||
.importzp sreg, tmp1
|
||||
.import pusheax
|
||||
|
||||
.export eaxufloat
|
||||
eaxufloat:
|
||||
|
||||
sta tmp1
|
||||
|
||||
lda sreg
|
||||
pha
|
||||
lda sreg+1
|
||||
pha
|
||||
|
||||
; get lower 16bit
|
||||
lda tmp1
|
||||
|
||||
; convert lower 16 bit
|
||||
jsr __stof
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; / 65536
|
||||
ldx #$00
|
||||
lda #$80
|
||||
sta sreg
|
||||
lda #$47
|
||||
sta sreg+1
|
||||
|
||||
jsr __fdiv
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; get higher 16bit
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
; convert higher 16 bit
|
||||
jsr __stof
|
||||
|
||||
jsr __fadd
|
||||
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; * 65536
|
||||
ldx #$00
|
||||
lda #$80
|
||||
sta sreg
|
||||
lda #$47
|
||||
sta sreg+1
|
||||
|
||||
jmp __fmul
|
||||
|
||||
;--------------------------------------------------------------
|
||||
|
||||
.import __ftoi
|
||||
|
||||
; float -> 16bit int
|
||||
.export feaxint
|
||||
feaxint:
|
||||
jmp __ftoi
|
||||
|
||||
; FIXME: this might be more accurate when done directly in one step (but the
|
||||
; kernal can not do this for 32bit)
|
||||
; float -> 32bit int
|
||||
.importzp tmp1, tmp2
|
||||
.export feaxlong
|
||||
feaxlong:
|
||||
|
||||
jsr pusheax
|
||||
|
||||
; primary = primary / 65536
|
||||
jsr pusheax ; push eax to stack
|
||||
ldx #$00
|
||||
lda #$80
|
||||
sta sreg
|
||||
lda #$47
|
||||
sta sreg+1
|
||||
jsr __fdiv ; primary / TOS
|
||||
; convert result to int and save
|
||||
jsr __ftoi
|
||||
sta tmp1
|
||||
stx tmp2
|
||||
; convert back to float
|
||||
jsr __stof
|
||||
; primary = primary * 65536
|
||||
jsr pusheax ; push eax to stack
|
||||
ldx #$00
|
||||
lda #$80
|
||||
sta sreg
|
||||
lda #$47
|
||||
sta sreg+1
|
||||
jsr __fmul ; primary * TOS
|
||||
; substract the result from the total number to get the rest
|
||||
jsr __fsub
|
||||
; convert rest to int
|
||||
jsr __ftoi
|
||||
|
||||
ldy tmp2
|
||||
sty sreg+1
|
||||
ldy tmp1
|
||||
sty sreg
|
||||
rts
|
||||
|
||||
;--------------------------------------------------------------
|
||||
.import __fnot
|
||||
.import __fneg
|
||||
|
||||
; binary negate (not) for the ! operator. returns a bool!
|
||||
.export fbnegeax
|
||||
.import bnegax
|
||||
fbnegeax:
|
||||
jsr __ftoi
|
||||
jmp bnegax
|
||||
|
||||
;--------------------------------------------------------------
|
||||
; math ops
|
||||
|
||||
.import __fadd
|
||||
.import __fsub
|
||||
.import __fdiv
|
||||
.import __fmul
|
||||
|
||||
; Primary = TOS + Primary (like tosaddeax)
|
||||
.export ftosaddeax
|
||||
ftosaddeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
|
||||
; FAC: ieee float is in A/X/sreg/sreg+1
|
||||
jmp __fadd
|
||||
|
||||
.export ftossubeax
|
||||
ftossubeax:
|
||||
jmp __fsub
|
||||
.export ftosdiveax
|
||||
ftosdiveax:
|
||||
jmp __fdiv
|
||||
.export ftosmuleax
|
||||
ftosmuleax:
|
||||
jmp __fmul
|
||||
|
||||
;--------------------------------------------------------------
|
||||
|
||||
.import __fcmp
|
||||
|
||||
; test for equal
|
||||
.export ftoseqeax
|
||||
ftoseqeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr __fcmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
cmp #0
|
||||
beq @equal
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
@equal:
|
||||
ldx #0
|
||||
lda #1
|
||||
rts
|
||||
|
||||
; test for not equal
|
||||
.export ftosneeax
|
||||
ftosneeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr __fcmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
cmp #0
|
||||
beq @equal
|
||||
ldx #0
|
||||
lda #1
|
||||
rts
|
||||
@equal:
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
; Test for greater than
|
||||
.export ftosgteax
|
||||
ftosgteax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr __fcmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
cmp #255
|
||||
bne @biggerorequal
|
||||
; less
|
||||
ldx #0
|
||||
lda #1
|
||||
rts
|
||||
@biggerorequal:
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
; Test for less than
|
||||
.export ftoslteax
|
||||
ftoslteax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr __fcmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
cmp #1
|
||||
beq @bigger
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
@bigger:
|
||||
ldx #0
|
||||
lda #1
|
||||
rts
|
||||
|
||||
; Test for greater than or equal to
|
||||
.export ftosgeeax
|
||||
ftosgeeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr __fcmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
cmp #1
|
||||
beq @bigger
|
||||
; less than or equal
|
||||
ldx #0
|
||||
lda #1
|
||||
rts
|
||||
@bigger:
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
; Test for less than or equal to
|
||||
.export ftosleeax
|
||||
ftosleeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr __fcmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
cmp #255
|
||||
beq @smaller
|
||||
; greater than or equal
|
||||
ldx #0
|
||||
lda #1
|
||||
rts
|
||||
@smaller:
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
|
||||
;--------------------------------------------------------------
|
||||
; math.h
|
||||
|
||||
.import __fpow
|
||||
.import __fsin
|
||||
.import __fcos
|
||||
.import __flog
|
||||
.import __fexp
|
||||
.import __fsqr
|
||||
.import __ftan
|
||||
.import __fatn
|
||||
.import __fabs
|
||||
|
||||
.export _powf
|
||||
_powf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp __fpow
|
||||
|
||||
.export _sinf
|
||||
_sinf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fsin
|
||||
|
||||
.export _cosf
|
||||
_cosf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fcos
|
||||
|
||||
.export _logf
|
||||
_logf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __flog
|
||||
|
||||
.export _expf
|
||||
_expf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fexp
|
||||
|
||||
.export _sqrtf
|
||||
_sqrtf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fsqr
|
||||
|
||||
.export _tanf
|
||||
_tanf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __ftan
|
||||
|
||||
.export _atanf
|
||||
_atanf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fatn
|
||||
|
||||
.export _fabsf
|
||||
_fabsf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fabs
|
24
test/float/cbmkernal/ffloor.c
Normal file
24
test/float/cbmkernal/ffloor.c
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#include <_float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <cbmfp.h>
|
||||
|
||||
#define _fcmplt(_d, _s) (_fcmp((_d), (_s)) == 1)
|
||||
#define _fcmpgt(_d, _s) (_fcmp((_d), (_s)) == 255)
|
||||
#define _fcmpeq(_d, _s) (_fcmp((_d), (_s)) == 0)
|
||||
|
||||
/* FIXME: this is really too simple */
|
||||
float ffloor(float x)
|
||||
{
|
||||
signed long n;
|
||||
float d;
|
||||
|
||||
n = _ftoi(x); /* FIXME: long */
|
||||
d = _itof(n); /* FIXME: long */
|
||||
|
||||
if (_fcmpeq(d, x) || _fcmplt(_itof(0), x)) {
|
||||
return d;
|
||||
}
|
||||
return _fsub(d, 1);
|
||||
}
|
63
test/float/cbmkernal/float-vic20.inc
Normal file
63
test/float/cbmkernal/float-vic20.inc
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
FAC_EXPONENT = $61
|
||||
FAC_MANTISSA0 = $62
|
||||
FAC_MANTISSA1 = $63
|
||||
FAC_MANTISSA2 = $64
|
||||
FAC_MANTISSA3 = $65
|
||||
FAC_SIGN = $66
|
||||
|
||||
ARG_EXPONENT = $69
|
||||
ARG_MANTISSA0 = $6a
|
||||
ARG_MANTISSA1 = $6b
|
||||
ARG_MANTISSA2 = $6c
|
||||
ARG_MANTISSA3 = $6d
|
||||
ARG_SIGN = $6e
|
||||
|
||||
FAC_SIGN_COMPARE = $6f
|
||||
FAC_ROUNDING = $70
|
||||
|
||||
; addresses of the floating point routines in CBM BASIC V2
|
||||
|
||||
; the following are the addresses in the VIC-20 ROM - the library can probably be
|
||||
; used with other CBM targets just by adjusting these addresses
|
||||
|
||||
BASIC_FAC_Not = $ced4 ; in/out: FAC ; yup, c64 & vic are this different
|
||||
BASIC_FAC_Cos = $e261 ; in/out: FAC
|
||||
BASIC_FAC_Sin = $e268 ; in/out: FAC
|
||||
BASIC_FAC_Tan = $e2b1 ; in/out: FAC
|
||||
BASIC_FAC_Atn = $e30b ; in/out: FAC
|
||||
BASIC_FAC_Rnd = $e094 ; in/out: FAC
|
||||
BASIC_FAC_Int = $dccc ; in/out: FAC
|
||||
BASIC_FAC_Sqr = $df71 ; in/out: FAC
|
||||
BASIC_FAC_Exp = $dfed ; in/out: FAC
|
||||
BASIC_FAC_Log = $d9ea ; in/out: FAC
|
||||
BASIC_FAC_Round = $dc1b ; in/out: FAC
|
||||
BASIC_FAC_Sgn = $dc39 ; in/out: FAC
|
||||
BASIC_FAC_Abs = $dc58 ; in/out: FAC
|
||||
|
||||
BASIC_ARG_FAC_Or = $cfe6 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_And = $cfe9 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Sub = $d853 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Add = $d86a ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Mul = $da2b ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Div = $db12 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Pow = $df7b ; in: ARG,FAC out:FAC
|
||||
|
||||
BASIC_u8_to_FAC = $d3a2 ; y: value
|
||||
BASIC_s8_to_FAC = $dc3c ; a: value
|
||||
BASIC_u16_to_FAC = $dc49 ; a/y:lo/hi value (sta $62 sty $63 sec ldx#$90 jsr...)
|
||||
BASIC_s16_to_FAC = $d395 ; a/y:lo/hi value
|
||||
|
||||
BASIC_FAC_to_u16 = $dc9b ; in:FAC out: y/a:lo/hi value
|
||||
|
||||
BASIC_string_to_FAC = $d7b5 ; in: $22/$23 ptr to str,a=strlen out: FAC value
|
||||
BASIC_FAC_to_string = $dddd ; in: FAC value out: str at $0100 a/y ptr to str
|
||||
|
||||
BASIC_LoadARG = $da8c ; a/y:lo/hi ptr to 5-byte float
|
||||
BASIC_LoadFAC = $dba2 ; a/y:lo/hi ptr to 5-byte float
|
||||
|
||||
BASIC_FAC_testsgn = $dc2b ; in: FAC(x1) out: a=0 (x1=0) a=1 (x1>0) a=255 (x1<0)
|
||||
BASIC_FAC_cmp = $dc5b ; in: FAC(x1) a/y ptr lo/hi to x2 out: a=0 (x1=x2) a=1 (x1>x2) a=255 (x1<x2)
|
||||
|
||||
BASIC_FAC_Poly2 = $e040 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)
|
||||
BASIC_FAC_Poly1 = $e056 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)
|
64
test/float/cbmkernal/float.inc
Normal file
64
test/float/cbmkernal/float.inc
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
FAC_EXPONENT = $61
|
||||
FAC_MANTISSA0 = $62
|
||||
FAC_MANTISSA1 = $63
|
||||
FAC_MANTISSA2 = $64
|
||||
FAC_MANTISSA3 = $65
|
||||
FAC_SIGN = $66
|
||||
|
||||
ARG_EXPONENT = $69
|
||||
ARG_MANTISSA0 = $6a
|
||||
ARG_MANTISSA1 = $6b
|
||||
ARG_MANTISSA2 = $6c
|
||||
ARG_MANTISSA3 = $6d
|
||||
ARG_SIGN = $6e
|
||||
|
||||
FAC_SIGN_COMPARE = $6f
|
||||
FAC_ROUNDING = $70
|
||||
|
||||
; addresses of the floating point routines in CBM BASIC V2
|
||||
|
||||
; the following are the addresses in the C64 ROM - the library can probably be
|
||||
; used with other CBM targets just by adjusting these addresses
|
||||
|
||||
BASIC_FAC_Not = $aed4 ; in/out: FAC
|
||||
BASIC_FAC_Cos = $e264 ; in/out: FAC
|
||||
BASIC_FAC_Sin = $e26b ; in/out: FAC
|
||||
BASIC_FAC_Tan = $e2b4 ; in/out: FAC
|
||||
BASIC_FAC_Atn = $e30e ; in/out: FAC
|
||||
BASIC_FAC_Rnd = $e097 ; in/out: FAC
|
||||
BASIC_FAC_Int = $bccc ; in/out: FAC
|
||||
BASIC_FAC_Sqr = $bf71 ; in/out: FAC
|
||||
BASIC_FAC_Exp = $bfed ; in/out: FAC
|
||||
BASIC_FAC_Log = $b9ea ; in/out: FAC
|
||||
BASIC_FAC_Round = $bc1b ; in/out: FAC
|
||||
BASIC_FAC_Sgn = $bc39 ; in/out: FAC
|
||||
BASIC_FAC_Abs = $bc58 ; in/out: FAC
|
||||
|
||||
BASIC_ARG_FAC_Or = $afe6 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_And = $afe9 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Sub = $b853 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Add = $b86a ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Mul = $ba2b ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Div = $bb12 ; in: ARG,FAC out:FAC
|
||||
BASIC_ARG_FAC_Pow = $bf7b ; in: ARG,FAC out:FAC
|
||||
|
||||
BASIC_u8_to_FAC = $b3a2 ; y: value
|
||||
BASIC_s8_to_FAC = $bc3c ; a: value
|
||||
BASIC_u16_to_FAC = $bc49 ; a/y:lo/hi value (sta $62 sty $63 sec ldx#$90 jsr...)
|
||||
BASIC_s16_to_FAC = $b395 ; a/y:lo/hi value
|
||||
|
||||
BASIC_FAC_to_u16 = $bc9b ; in:FAC out: y/a:lo/hi value
|
||||
|
||||
BASIC_string_to_FAC = $b7b5 ; in: $22/$23 ptr to str,a=strlen out: FAC value
|
||||
BASIC_FAC_to_string = $bddd ; in: FAC value out: str at $0100 a/y ptr to str
|
||||
|
||||
BASIC_LoadARG = $ba8c ; a/y:lo/hi ptr to 5-byte float
|
||||
BASIC_LoadFAC = $bba2 ; a/y:lo/hi ptr to 5-byte float
|
||||
|
||||
BASIC_FAC_testsgn = $bc2b ; in: FAC(x1) out: a=0 (x1=0) a=1 (x1>0) a=255 (x1<0)
|
||||
BASIC_FAC_cmp = $bc5b ; in: FAC(x1) a/y ptr lo/hi to x2 out: a=0 (x1=x2) a=1 (x1>x2) a=255 (x1<x2)
|
||||
|
||||
BASIC_FAC_Poly2 = $e043 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)
|
||||
BASIC_FAC_Poly1 = $e059 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)
|
||||
|
849
test/float/cbmkernal/float.s
Normal file
849
test/float/cbmkernal/float.s
Normal file
@ -0,0 +1,849 @@
|
||||
|
||||
BINARYFORMAT_CBM_UNPACKED = 0
|
||||
BINARYFORMAT_CBM_PACKED = 1
|
||||
BINARYFORMAT_IEEE754 = 2
|
||||
|
||||
; BEWARE: also change in float.h
|
||||
;BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
|
||||
;BINARYFORMAT = BINARYFORMAT_CBM_PACKED
|
||||
BINARYFORMAT = BINARYFORMAT_IEEE754
|
||||
|
||||
.segment "LOWCODE"
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
.if .defined(__C64__)
|
||||
__basicon:
|
||||
sei
|
||||
ldx #$37
|
||||
stx $01
|
||||
rts
|
||||
|
||||
__basicoff:
|
||||
ldx #$36
|
||||
stx $01
|
||||
cli
|
||||
rts
|
||||
.endif
|
||||
|
||||
.macro __enable_basic_if_needed
|
||||
.if .defined(__C64__)
|
||||
jsr __basicon
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
.macro __disable_basic_if_needed
|
||||
.if .defined(__C64__)
|
||||
jsr __basicoff
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
.macro __return_with_cleanup
|
||||
.if .defined(__C64__)
|
||||
jmp __basicoff
|
||||
.else
|
||||
rts
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; first come the actual stubs to floating point routines, these are ment to be
|
||||
; used from further written ml-math routines aswell. (maybe also from the compiler?!)
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
.if .defined(__VIC20__)
|
||||
.include "float-vic20.inc"
|
||||
.else
|
||||
.include "float.inc"
|
||||
.endif
|
||||
|
||||
.importzp sreg, ptr1
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; converter integer types to float
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
___float_s8_to_fac:
|
||||
;a: low
|
||||
__float_s8_to_fac:
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_s8_to_FAC
|
||||
__return_with_cleanup
|
||||
|
||||
___float_u8_to_fac:
|
||||
;a: low
|
||||
tay
|
||||
;y: low
|
||||
__float_u8_to_fac:
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_u8_to_FAC
|
||||
__return_with_cleanup
|
||||
|
||||
; get C-parameter (signed int), convert to FAC
|
||||
___float_s16_to_fac:
|
||||
;a: low x: high
|
||||
tay
|
||||
txa
|
||||
;y: low a: high
|
||||
|
||||
; convert signed int (YA) to FAC
|
||||
__float_s16_to_fac:
|
||||
__enable_basic_if_needed ; enable BASIC (trashes X)
|
||||
jsr BASIC_s16_to_FAC
|
||||
__return_with_cleanup
|
||||
|
||||
; get C-parameter (unsigned short), convert to FAC
|
||||
___float_u16_to_fac:
|
||||
;a: low x: high
|
||||
tay
|
||||
txa
|
||||
;y: low a: high
|
||||
|
||||
__float_u16_to_fac:
|
||||
sta FAC_MANTISSA0
|
||||
sty FAC_MANTISSA1
|
||||
__enable_basic_if_needed
|
||||
ldx #$90
|
||||
sec
|
||||
jsr BASIC_u16_to_FAC
|
||||
__return_with_cleanup
|
||||
|
||||
; return to C, FAC as unsigned int
|
||||
__float_fac_to_u16:
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_FAC_to_u16
|
||||
__disable_basic_if_needed
|
||||
ldx FAC_MANTISSA2
|
||||
lda FAC_MANTISSA3
|
||||
rts
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; converter float to string and back
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
; this converts to exponential form, ie what %e in printf would give you
|
||||
__float_fac_to_str:
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_FAC_to_string
|
||||
__return_with_cleanup
|
||||
|
||||
___float_str_to_fac:
|
||||
; jsr popax
|
||||
__float_str_to_fac:
|
||||
sta $22
|
||||
stx $23
|
||||
ldy #$00
|
||||
@l: lda ($22),y
|
||||
beq @s
|
||||
iny
|
||||
bne @l
|
||||
@s: tya
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_string_to_FAC
|
||||
__return_with_cleanup
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
; get C-parameter (float), convert to FAC
|
||||
___float_float_to_fac:
|
||||
.if BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
|
||||
sta FAC_MANTISSA1 ; 3
|
||||
stx FAC_MANTISSA0 ; 2
|
||||
ldy sreg ; 1
|
||||
sty FAC_EXPONENT
|
||||
ldy sreg+1 ; 0
|
||||
sty FAC_SIGN
|
||||
|
||||
ldx #$00
|
||||
stx FAC_MANTISSA2
|
||||
stx FAC_MANTISSA3
|
||||
stx FAC_ROUNDING
|
||||
.endif
|
||||
.if BINARYFORMAT = BINARYFORMAT_CBM_PACKED
|
||||
sta FAC_MANTISSA2 ; 3
|
||||
stx FAC_MANTISSA1 ; 2
|
||||
lda sreg ; 1
|
||||
ora #$80
|
||||
sta FAC_MANTISSA0
|
||||
|
||||
; bit7=0 sign=0
|
||||
; bit7=1 sign=$ff
|
||||
ldx #0
|
||||
lda sreg
|
||||
bpl @pos
|
||||
dex
|
||||
@pos:
|
||||
stx FAC_SIGN
|
||||
|
||||
ldy sreg+1 ; 0
|
||||
sty FAC_EXPONENT
|
||||
|
||||
ldx #$00
|
||||
stx FAC_MANTISSA3
|
||||
stx FAC_ROUNDING
|
||||
.endif
|
||||
.if BINARYFORMAT = BINARYFORMAT_IEEE754
|
||||
; ieee float is in A/X/sreg/sreg+1
|
||||
sta FAC_MANTISSA2
|
||||
stx FAC_MANTISSA1
|
||||
|
||||
; shift msb from mantissa into exponent
|
||||
asl sreg ; mantissa msb
|
||||
rol sreg+1 ; exp
|
||||
|
||||
; sign is in carry
|
||||
lda #$ff
|
||||
bcs @l
|
||||
lda #0
|
||||
@l:
|
||||
sta FAC_SIGN
|
||||
|
||||
lda sreg ; mantissa msb
|
||||
lsr
|
||||
ora #$80 ; msb of mantissa is always 1
|
||||
sta FAC_MANTISSA0
|
||||
|
||||
lda sreg+1 ; exp
|
||||
clc
|
||||
adc #2
|
||||
sta FAC_EXPONENT
|
||||
|
||||
ldx #$00
|
||||
stx FAC_MANTISSA3
|
||||
stx FAC_ROUNDING
|
||||
.endif
|
||||
rts
|
||||
|
||||
; load BASIC float into FAC
|
||||
; in: pointer (a/x) to BASIC float (not packed)
|
||||
__float_float_to_fac: ; only used in ATAN2?
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #$00
|
||||
lda (ptr1),y
|
||||
sta FAC_EXPONENT
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta FAC_MANTISSA0
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta FAC_MANTISSA1
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta FAC_MANTISSA2
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta FAC_MANTISSA3
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta FAC_SIGN
|
||||
ldx #$00
|
||||
stx FAC_ROUNDING
|
||||
; always load arg after fac so these can
|
||||
; be removed in funcs that only take fac
|
||||
eor ARG_SIGN
|
||||
sta FAC_SIGN_COMPARE
|
||||
rts
|
||||
|
||||
; get C-parameter (two floats), to FAC and ARG
|
||||
___float_float_to_fac_arg:
|
||||
jsr ___float_float_to_fac
|
||||
___float_float_to_arg:
|
||||
ldy #$03
|
||||
jsr ldeaxysp
|
||||
|
||||
.if BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
|
||||
sta ARG_MANTISSA1 ; 3
|
||||
stx ARG_MANTISSA0 ; 2
|
||||
ldy sreg ; 1
|
||||
sty ARG_EXPONENT
|
||||
|
||||
ldx #$00
|
||||
stx ARG_MANTISSA2
|
||||
stx ARG_MANTISSA3
|
||||
|
||||
lda sreg+1 ; 0
|
||||
sta ARG_SIGN
|
||||
eor FAC_SIGN
|
||||
sta FAC_SIGN_COMPARE ; sign compare
|
||||
.endif
|
||||
|
||||
.if BINARYFORMAT = BINARYFORMAT_CBM_PACKED
|
||||
sta ARG_MANTISSA2 ; 3
|
||||
stx ARG_MANTISSA1 ; 2
|
||||
lda sreg ; 1
|
||||
ora #$80
|
||||
sta ARG_MANTISSA0
|
||||
|
||||
; bit7=0 sign=0
|
||||
; bit7=1 sign=$ff
|
||||
ldx #0
|
||||
lda sreg ; 1
|
||||
bpl @pos
|
||||
dex
|
||||
@pos:
|
||||
stx ARG_SIGN
|
||||
|
||||
ldy sreg+1 ; 0
|
||||
sty ARG_EXPONENT
|
||||
|
||||
ldx #$00
|
||||
stx ARG_MANTISSA3
|
||||
|
||||
lda ARG_SIGN
|
||||
eor FAC_SIGN
|
||||
sta FAC_SIGN_COMPARE ; sign compare
|
||||
.endif
|
||||
|
||||
|
||||
.if BINARYFORMAT = BINARYFORMAT_IEEE754
|
||||
; ieee float in a/x/sreg/sreg+1
|
||||
sta ARG_MANTISSA2
|
||||
stx ARG_MANTISSA1
|
||||
|
||||
asl sreg ; mantissa msb
|
||||
rol sreg+1 ; exp
|
||||
|
||||
; sign is in carry
|
||||
lda #$ff
|
||||
bcs @l
|
||||
lda #0
|
||||
@l:
|
||||
sta ARG_SIGN
|
||||
|
||||
lda sreg ; mantissa msb
|
||||
lsr
|
||||
ora #$80 ; the first bit in the mantissa should always be 1
|
||||
sta ARG_MANTISSA0
|
||||
|
||||
lda sreg+1 ; exp
|
||||
clc
|
||||
adc #2
|
||||
sta ARG_EXPONENT
|
||||
|
||||
ldx #$00
|
||||
stx ARG_MANTISSA3
|
||||
|
||||
lda ARG_SIGN
|
||||
eor FAC_SIGN
|
||||
sta FAC_SIGN_COMPARE ; sign compare
|
||||
.endif
|
||||
|
||||
jmp incsp4
|
||||
|
||||
; load BASIC float into ARG
|
||||
; in: pointer (a/x) to BASIC float (not packed)
|
||||
__float_float_to_arg: ; only used in ATAN2?
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #$00
|
||||
lda (ptr1),y
|
||||
sta ARG_EXPONENT
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta ARG_MANTISSA0
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta ARG_MANTISSA1
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta ARG_MANTISSA2
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta ARG_MANTISSA3
|
||||
iny
|
||||
lda (ptr1),y
|
||||
sta ARG_SIGN
|
||||
; sign compare
|
||||
eor FAC_SIGN
|
||||
sta FAC_SIGN_COMPARE
|
||||
rts
|
||||
|
||||
; return to C, float as unsigned long
|
||||
___float_fac_to_float:
|
||||
.if BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
|
||||
lda FAC_SIGN
|
||||
sta sreg+1 ; 0
|
||||
lda FAC_EXPONENT
|
||||
sta sreg ; 1
|
||||
ldx FAC_MANTISSA0 ; 2
|
||||
lda FAC_MANTISSA1 ; 3
|
||||
.endif
|
||||
.if BINARYFORMAT = BINARYFORMAT_CBM_PACKED
|
||||
lda FAC_EXPONENT
|
||||
sta sreg+1 ; 0
|
||||
|
||||
; use the MSB of the mantissa for the sign
|
||||
lda FAC_SIGN ; either $ff or $00
|
||||
ora #$7f ; -> $ff or $7f
|
||||
and FAC_MANTISSA0 ; bit7 of mantissa is always 1
|
||||
sta sreg ; 1
|
||||
|
||||
ldx FAC_MANTISSA1 ; 2
|
||||
lda FAC_MANTISSA2 ; 3
|
||||
.endif
|
||||
.if BINARYFORMAT = BINARYFORMAT_IEEE754
|
||||
; return float in a/x/sreg/sreg+1
|
||||
lda FAC_EXPONENT
|
||||
sec
|
||||
sbc #2
|
||||
sta sreg+1 ; 0
|
||||
|
||||
lda FAC_MANTISSA0
|
||||
asl
|
||||
sta sreg ; 1
|
||||
|
||||
lda FAC_SIGN ; either $ff or $00
|
||||
asl
|
||||
ror sreg+1 ; exp
|
||||
ror sreg ; mantissa msb
|
||||
|
||||
|
||||
ldx FAC_MANTISSA1 ; 2
|
||||
lda FAC_MANTISSA2 ; 3 lsb
|
||||
|
||||
.endif
|
||||
rts
|
||||
|
||||
;; store float in memory
|
||||
;; in: dest. pointer (a/x), float in FAC
|
||||
;__float_fac_to_float: ; UNUSED
|
||||
; sta ptr1
|
||||
; stx ptr1+1
|
||||
; ldy #$00
|
||||
; lda FAC_EXPONENT
|
||||
; sta (ptr1),y
|
||||
; iny
|
||||
; lda FAC_MANTISSA0
|
||||
; sta (ptr1),y
|
||||
; iny
|
||||
; lda FAC_MANTISSA1
|
||||
; sta (ptr1),y
|
||||
; iny
|
||||
; lda FAC_MANTISSA2
|
||||
; sta (ptr1),y
|
||||
; iny
|
||||
; lda FAC_MANTISSA3
|
||||
; sta (ptr1),y
|
||||
; iny
|
||||
; lda FAC_SIGN
|
||||
; sta (ptr1),y
|
||||
; rts
|
||||
|
||||
;; store packed float in memory
|
||||
;; in: dest. pointer (a/x), float in FAC
|
||||
;__float_fac_to_float_packed: ; UNUSED
|
||||
; sta ptr1
|
||||
; stx ptr1+1
|
||||
; ldy #4
|
||||
; lda FAC_MANTISSA3
|
||||
; sta (ptr1),y
|
||||
; dey
|
||||
; lda FAC_MANTISSA2
|
||||
; sta (ptr1),y
|
||||
; dey
|
||||
; lda FAC_MANTISSA1
|
||||
; sta (ptr1),y
|
||||
; dey
|
||||
;; use the MSB of the mantissa for the sign
|
||||
; lda FAC_SIGN
|
||||
; ora #$7f
|
||||
; and FAC_MANTISSA0
|
||||
; sta (ptr1),y
|
||||
; dey
|
||||
; lda FAC_EXPONENT
|
||||
; sta (ptr1),y
|
||||
; rts
|
||||
|
||||
;; store packed float in memory
|
||||
;; in: dest. pointer (a/x), float in ARG
|
||||
__float_arg_to_float_packed:
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #4
|
||||
lda ARG_MANTISSA3
|
||||
sta (ptr1),y
|
||||
dey
|
||||
lda ARG_MANTISSA2
|
||||
sta (ptr1),y
|
||||
dey
|
||||
lda ARG_MANTISSA1
|
||||
sta (ptr1),y
|
||||
dey
|
||||
; use the MSB of the mantissa for the sign
|
||||
lda ARG_SIGN
|
||||
ora #$7f
|
||||
and ARG_MANTISSA0
|
||||
sta (ptr1),y
|
||||
dey
|
||||
lda ARG_EXPONENT
|
||||
sta (ptr1),y
|
||||
rts
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
.export __ftostr
|
||||
.importzp ptr1
|
||||
.import popax, ldeaxysp, incsp4
|
||||
|
||||
; convert float to string
|
||||
; char* __fastcall__ _ftostr(char *d, float s);
|
||||
;-> char* __fastcall__ _ftostr(char *d, unsigned long s);
|
||||
|
||||
__ftostr:
|
||||
jsr ___float_float_to_fac
|
||||
jsr __float_fac_to_str
|
||||
|
||||
___float_strbuf_to_string:
|
||||
jsr popax ; ptr to string
|
||||
__float_strbuf_to_string:
|
||||
sta ptr1
|
||||
stx ptr1+1
|
||||
ldy #$00
|
||||
@l:
|
||||
lda $0100,y
|
||||
sta (ptr1),y
|
||||
beq @s
|
||||
iny
|
||||
bne @l
|
||||
@s:
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
rts
|
||||
|
||||
.export __strtof
|
||||
|
||||
; convert a string to a float
|
||||
; float __fastcall__ _strtof(char *d);
|
||||
;-> unsigned long __fastcall__ _strtof(char *d);
|
||||
__strtof:
|
||||
jsr ___float_str_to_fac
|
||||
jmp ___float_fac_to_float
|
||||
|
||||
.export __ctof
|
||||
|
||||
; convert char to float
|
||||
; float __fastcall__ _ctof(char v);
|
||||
;-> unsigned long __fastcall__ _ctof(char v);
|
||||
__ctof:
|
||||
jsr ___float_s8_to_fac
|
||||
jmp ___float_fac_to_float
|
||||
|
||||
.export __utof
|
||||
|
||||
; convert unsigned char to float
|
||||
; float __fastcall__ _utof(unsigned char v);
|
||||
;-> unsigned long __fastcall__ _utof(unsigned char v);
|
||||
__utof:
|
||||
jsr ___float_u8_to_fac
|
||||
jmp ___float_fac_to_float
|
||||
|
||||
.export __stof
|
||||
|
||||
; convert short to float
|
||||
; float __fastcall__ _stof(unsigned short v);
|
||||
;-> unsigned long __fastcall__ _stof(unsigned short v);
|
||||
__stof:
|
||||
jsr ___float_u16_to_fac
|
||||
jmp ___float_fac_to_float
|
||||
|
||||
.export __itof
|
||||
|
||||
; convert integer to float
|
||||
; float __fastcall__ _itof(int v);
|
||||
;-> unsigned long __fastcall__ _itof(int v);
|
||||
__itof:
|
||||
;a: low x: high
|
||||
jsr ___float_s16_to_fac
|
||||
jmp ___float_fac_to_float
|
||||
|
||||
.export __ftoi
|
||||
|
||||
; convert float to integer
|
||||
; int __fastcall__ _ftoi(float f);
|
||||
;-> int __fastcall__ _ftoi(unsigned long f);
|
||||
__ftoi:
|
||||
jsr ___float_float_to_fac
|
||||
jmp __float_fac_to_u16
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; these functions take one arg (in FAC) and return result (in FAC) aswell
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
.macro __ffunc1 addr
|
||||
jsr ___float_float_to_fac
|
||||
__enable_basic_if_needed
|
||||
jsr addr
|
||||
__disable_basic_if_needed
|
||||
jmp ___float_fac_to_float
|
||||
.endmacro
|
||||
|
||||
.export __fabs, __fatn, __fcos, __fexp, __fint, __flog
|
||||
.export __frnd, __fsgn, __fsin, __fsqr, __ftan, __fnot, __fround
|
||||
|
||||
__fabs: __ffunc1 BASIC_FAC_Abs
|
||||
__fatn: __ffunc1 BASIC_FAC_Atn
|
||||
__fcos: __ffunc1 BASIC_FAC_Cos
|
||||
__fexp: __ffunc1 BASIC_FAC_Exp
|
||||
;__ffre: __ffunc1 BASIC_FAC_Fre
|
||||
__fint: __ffunc1 BASIC_FAC_Int
|
||||
__flog: __ffunc1 BASIC_FAC_Log
|
||||
;__fpos: __ffunc1 BASIC_FAC_Pos
|
||||
__frnd: __ffunc1 BASIC_FAC_Rnd
|
||||
__fsgn: __ffunc1 BASIC_FAC_Sgn
|
||||
__fsin: __ffunc1 BASIC_FAC_Sin
|
||||
__fsqr: __ffunc1 BASIC_FAC_Sqr
|
||||
__ftan: __ffunc1 BASIC_FAC_Tan
|
||||
__fnot: __ffunc1 BASIC_FAC_Not
|
||||
__fround: __ffunc1 BASIC_FAC_Round
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; these functions take two args (in FAC and ARG) and return result (in FAC)
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
__float_ret2:
|
||||
|
||||
;jsr __basicoff
|
||||
.if .defined(__C64__)
|
||||
ldx #$36
|
||||
stx $01
|
||||
cli
|
||||
.endif
|
||||
jmp ___float_fac_to_float ; also pops pointer to float
|
||||
|
||||
.macro __ffunc2a addr
|
||||
jsr ___float_float_to_fac_arg
|
||||
__enable_basic_if_needed
|
||||
lda FAC_EXPONENT
|
||||
jsr addr
|
||||
jmp __float_ret2
|
||||
.endmacro
|
||||
|
||||
.macro __ffunc2b addr
|
||||
jsr ___float_float_to_fac_arg
|
||||
__enable_basic_if_needed
|
||||
jsr addr
|
||||
jmp __float_ret2
|
||||
.endmacro
|
||||
|
||||
.export __fadd, __fsub, __fmul, __fdiv, __fpow
|
||||
|
||||
; float __fastcall__ _fadd(float f, float a);
|
||||
;-> unsigned long __fastcall__ _fadd(unsigned long f, unsigned long a);
|
||||
__fadd: __ffunc2a BASIC_ARG_FAC_Add
|
||||
__fsub: __ffunc2a BASIC_ARG_FAC_Sub
|
||||
__fmul: __ffunc2a BASIC_ARG_FAC_Mul
|
||||
__fdiv: __ffunc2a BASIC_ARG_FAC_Div
|
||||
__fpow: __ffunc2a BASIC_ARG_FAC_Pow
|
||||
|
||||
.export __fand, __for
|
||||
|
||||
__fand: __ffunc2b BASIC_ARG_FAC_And
|
||||
__for: __ffunc2b BASIC_ARG_FAC_Or
|
||||
|
||||
__float_ret3:
|
||||
;jsr __basicoff
|
||||
.if .defined(__C64__)
|
||||
ldx #$36
|
||||
stx $01
|
||||
cli
|
||||
.endif
|
||||
ldx #0
|
||||
rts
|
||||
|
||||
.bss
|
||||
|
||||
tempfloat:
|
||||
.res 5
|
||||
|
||||
.SEGMENT "LOWCODE"
|
||||
|
||||
.export __fcmp
|
||||
|
||||
__fcmp:
|
||||
jsr ___float_float_to_fac_arg
|
||||
lda #<tempfloat
|
||||
ldx #>tempfloat
|
||||
jsr __float_arg_to_float_packed
|
||||
lda #<tempfloat
|
||||
ldy #>tempfloat
|
||||
___float_cmp_fac_arg:
|
||||
__enable_basic_if_needed
|
||||
; in: FAC=(x1) a/y= ptr lo/hi to x2
|
||||
jsr BASIC_FAC_cmp
|
||||
; a=0 (==) / a=1 (>) / a=255 (<)
|
||||
jmp __float_ret3
|
||||
|
||||
.export __ftestsgn
|
||||
|
||||
__ftestsgn:
|
||||
jsr ___float_float_to_fac
|
||||
;___float_testsgn_fac:
|
||||
__enable_basic_if_needed
|
||||
; in: FAC(x1)
|
||||
jsr BASIC_FAC_testsgn
|
||||
jmp __float_ret3
|
||||
|
||||
___float_testsgn_fac:
|
||||
lda FAC_EXPONENT
|
||||
beq @s
|
||||
lda FAC_SIGN
|
||||
rol a
|
||||
lda #$ff
|
||||
bcs @s
|
||||
lda #$01
|
||||
@s:
|
||||
rts
|
||||
|
||||
___float_testsgn_arg:
|
||||
lda ARG_EXPONENT
|
||||
beq @s
|
||||
lda ARG_SIGN
|
||||
rol a
|
||||
lda #$ff
|
||||
bcs @s
|
||||
lda #$01
|
||||
@s:
|
||||
rts
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; polynom1 f(x)=a1+a2*x^2+a3*x^3+...+an*x^n
|
||||
;---------------------------------------------------------------------------------------------
|
||||
.export __fpoly1
|
||||
__fpoly1:
|
||||
jsr ___float_float_to_fac
|
||||
;jsr popya
|
||||
jsr popax
|
||||
tay
|
||||
txa
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_FAC_Poly1
|
||||
jmp __float_ret2
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; polynom2 f(x)=a1+a2*x^3+a3*x^5+...+an*x^(2n-1)
|
||||
;---------------------------------------------------------------------------------------------
|
||||
.export __fpoly2
|
||||
__fpoly2:
|
||||
jsr ___float_float_to_fac
|
||||
;jsr popya
|
||||
jsr popax
|
||||
tay
|
||||
txa
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_FAC_Poly1
|
||||
jmp __float_ret2
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
|
||||
__float_atn_fac:
|
||||
__enable_basic_if_needed
|
||||
jsr BASIC_FAC_Atn
|
||||
__return_with_cleanup
|
||||
__float_div_fac_arg:
|
||||
__enable_basic_if_needed
|
||||
lda FAC_EXPONENT
|
||||
jsr BASIC_ARG_FAC_Div
|
||||
__return_with_cleanup
|
||||
__float_add_fac_arg:
|
||||
__enable_basic_if_needed
|
||||
lda FAC_EXPONENT
|
||||
jsr BASIC_ARG_FAC_Add
|
||||
__return_with_cleanup
|
||||
|
||||
__float_swap_fac_arg: ; only used in ATAN2
|
||||
lda FAC_EXPONENT
|
||||
ldx ARG_EXPONENT
|
||||
stx FAC_EXPONENT
|
||||
sta ARG_EXPONENT
|
||||
lda FAC_MANTISSA0
|
||||
ldx ARG_MANTISSA0
|
||||
stx FAC_MANTISSA0
|
||||
sta ARG_MANTISSA0
|
||||
lda FAC_MANTISSA1
|
||||
ldx ARG_MANTISSA1
|
||||
stx FAC_MANTISSA1
|
||||
sta ARG_MANTISSA1
|
||||
lda FAC_MANTISSA2
|
||||
ldx ARG_MANTISSA2
|
||||
stx FAC_MANTISSA2
|
||||
sta ARG_MANTISSA2
|
||||
lda FAC_MANTISSA3
|
||||
ldx ARG_MANTISSA3
|
||||
stx FAC_MANTISSA3
|
||||
sta ARG_MANTISSA3
|
||||
lda FAC_SIGN
|
||||
ldx ARG_SIGN
|
||||
stx FAC_SIGN
|
||||
sta ARG_SIGN
|
||||
rts
|
||||
|
||||
.export __fneg
|
||||
__fneg:
|
||||
jsr ___float_float_to_fac
|
||||
|
||||
lda FAC_EXPONENT
|
||||
beq @sk
|
||||
lda FAC_SIGN
|
||||
eor #$FF
|
||||
sta FAC_SIGN
|
||||
@sk:
|
||||
jmp ___float_fac_to_float
|
||||
|
||||
|
||||
__f_pi2: .byte $81,$80+$49,$0f,$da,$a1,$00
|
||||
__f_pi: .byte $82,$80+$49,$0f,$da,$a1,$00
|
||||
__f_1pi2: .byte $83,$80+$16,$cb,$e3,$f9,$00
|
||||
|
||||
.export __fatan2
|
||||
|
||||
; float _fatan2(float x, float y)
|
||||
;-> unsigned long _fatan2(unsigned long x, unsigned long y)
|
||||
__fatan2:
|
||||
|
||||
jsr ___float_float_to_fac_arg
|
||||
|
||||
jsr ___float_testsgn_arg
|
||||
beq @s11 ; =0
|
||||
bpl @s12 ; <0
|
||||
; arg>0
|
||||
; a=atn(y/x)
|
||||
jsr __float_swap_fac_arg
|
||||
jsr __float_div_fac_arg
|
||||
jsr __float_atn_fac
|
||||
jmp __float_ret2
|
||||
@s12: ; arg<0
|
||||
; a=atn(y/x)+pi
|
||||
jsr __float_swap_fac_arg
|
||||
jsr __float_div_fac_arg
|
||||
jsr __float_atn_fac
|
||||
lda #<__f_pi
|
||||
ldx #>__f_pi
|
||||
jsr __float_float_to_arg
|
||||
jsr __float_add_fac_arg
|
||||
jmp __float_ret2
|
||||
|
||||
@s11: ; arg=0
|
||||
jsr ___float_testsgn_fac
|
||||
beq @s21 ; =0
|
||||
bpl @s22 ; <0
|
||||
; fac >0
|
||||
; a= 0.5*pi
|
||||
lda #<__f_pi2
|
||||
ldx #>__f_pi2
|
||||
jsr __float_float_to_fac
|
||||
jmp __float_ret2
|
||||
; fac =0
|
||||
@s21:
|
||||
; a= 0
|
||||
lda #$00
|
||||
sta FAC_MANTISSA0
|
||||
jmp __float_ret2
|
||||
; fac <0
|
||||
@s22:
|
||||
; a= 1.5*pi
|
||||
lda #<__f_1pi2
|
||||
ldx #>__f_1pi2
|
||||
jsr __float_float_to_fac
|
||||
jmp __float_ret2
|
||||
|
134
test/float/cbmkernal/ftoa.c
Normal file
134
test/float/cbmkernal/ftoa.c
Normal file
@ -0,0 +1,134 @@
|
||||
|
||||
#include <_float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <cbmfp.h>
|
||||
|
||||
// convert float into a string. this is surprisingly complex, so we just use
|
||||
// the kernal function, and then fix up the result
|
||||
|
||||
char *ftoa(char *buf, float n)
|
||||
{
|
||||
char i, ii, epos = 0, ex;
|
||||
char tempbuf[0x20];
|
||||
_ftostr(tempbuf, n);
|
||||
|
||||
// find position of the 'e'
|
||||
i=0;while(tempbuf[i]) {
|
||||
if (tempbuf[i] == 69) { /* 'e' */
|
||||
epos = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (epos == 0) {
|
||||
i = ii = 0;
|
||||
// no exponent, we can return the number as is
|
||||
if (tempbuf[i] == '-') {
|
||||
buf[ii] = tempbuf[i];
|
||||
i++;ii++;
|
||||
}
|
||||
// else {
|
||||
// buf[ii] = ' ';
|
||||
// ii++;
|
||||
// }
|
||||
|
||||
// skip space
|
||||
if (tempbuf[i] == ' ') {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (tempbuf[i] == '.') {
|
||||
i++;
|
||||
buf[ii] = '0'; ii++;
|
||||
buf[ii] = '.'; ii++;
|
||||
}
|
||||
while (tempbuf[i]) {
|
||||
buf[ii] = tempbuf[i];
|
||||
i++;ii++;
|
||||
}
|
||||
buf[ii] = 0;
|
||||
} else {
|
||||
// we have an exponent, get rid of it
|
||||
|
||||
i = ii = 0;
|
||||
if (tempbuf[i] == '-') {
|
||||
buf[ii] = tempbuf[i];
|
||||
i++;ii++;
|
||||
}
|
||||
// else {
|
||||
// buf[ii] = ' ';
|
||||
// ii++;
|
||||
// }
|
||||
// skip space
|
||||
if (tempbuf[i] == ' ') {
|
||||
i++;
|
||||
}
|
||||
|
||||
ex = ((tempbuf[epos+2] - '0') * 10) + (tempbuf[epos+3] - '0');
|
||||
|
||||
if (tempbuf[epos+1] == '+') {
|
||||
// positive exponent, move decimal point to right, add zeros to the right
|
||||
|
||||
// first copy until we see either the decimal point, or the 'e'
|
||||
while (tempbuf[i] && tempbuf[i] != '.' && tempbuf[i] != 69) {
|
||||
buf[ii] = tempbuf[i];
|
||||
i++;ii++;
|
||||
}
|
||||
|
||||
// 'e' found, add as many zeros as in the exponent
|
||||
if (tempbuf[i] == 69) {
|
||||
while(ex) {
|
||||
buf[ii] = '0';
|
||||
ii++;
|
||||
ex--;
|
||||
}
|
||||
}
|
||||
|
||||
if (tempbuf[i] == '.') {
|
||||
i++; // skip '.'
|
||||
// copy digits until 'e'
|
||||
while(ex && tempbuf[i] != 69) {
|
||||
buf[ii] = tempbuf[i];
|
||||
ii++;i++;
|
||||
ex--;
|
||||
}
|
||||
// add zeros
|
||||
while(ex) {
|
||||
buf[ii] = '0';
|
||||
ii++;
|
||||
ex--;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// negative exponent, move decimal point to left, add zeros to left
|
||||
|
||||
buf[ii] = '0'; ii++;
|
||||
buf[ii] = '.'; ii++;
|
||||
|
||||
ex--;
|
||||
|
||||
// add zeros
|
||||
while(ex) {
|
||||
buf[ii] = '0';
|
||||
ii++;
|
||||
ex--;
|
||||
}
|
||||
|
||||
while (tempbuf[i] && tempbuf[i] != 69) {
|
||||
if (tempbuf[i] == '.') {
|
||||
i++;
|
||||
}
|
||||
buf[ii] = tempbuf[i];
|
||||
i++;ii++;
|
||||
}
|
||||
|
||||
}
|
||||
buf[ii] = 0;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
161
test/float/float-basic-cmp.c
Normal file
161
test/float/float-basic-cmp.c
Normal file
@ -0,0 +1,161 @@
|
||||
|
||||
// test comparison operations
|
||||
// WIP WIP WIP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x10];
|
||||
char buf2[0x10];
|
||||
char buf3[0x10];
|
||||
|
||||
signed char var_schar;
|
||||
unsigned char var_uchar;
|
||||
signed int var_sint;
|
||||
unsigned int var_uint;
|
||||
signed long var_slong;
|
||||
unsigned long var_ulong;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-basic-cmp\n");
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// float variable vs float constant
|
||||
printf("var vs const\n");
|
||||
|
||||
//FIXME: compiles, but is wrong, the constant in the comparison becomes 0
|
||||
fp1 = 1.5f;
|
||||
printf("1.5f == 1.6f is ");
|
||||
if (fp1 == 1.6f) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
fp1 = 1.5f;
|
||||
printf("1.5f == 1.5f is ");
|
||||
if (1.5f == fp1) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
|
||||
//FIXME: compiles, but is wrong, the constant in the comparison becomes 0
|
||||
fp1 = 1.5f;
|
||||
printf("1.5f != 1.6f is ");
|
||||
if (fp1 != 1.6f) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
fp1 = 1.5f;
|
||||
printf("1.5f != 1.5f is ");
|
||||
if (1.5f != fp1) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
|
||||
//FIXME: compiles, but is wrong, the constant in the comparison becomes 0
|
||||
fp1 = 1.5f;
|
||||
printf("1.5f < 1.6f is ");
|
||||
if (fp1 < 1.6f) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
fp1 = 1.7f;
|
||||
printf("1.7f < 1.5f is ");
|
||||
if (1.7f < fp1) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// float variable vs float variable
|
||||
printf("var vs var\n");
|
||||
fp1 = 1.5f;
|
||||
fp2 = 1.6f;
|
||||
printf("1.5f == 1.6f is ");
|
||||
if (fp1 == fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.5f != 1.6f is ");
|
||||
if (fp1 != fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.5f < 1.6f is ");
|
||||
if (fp1 < fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.5f > 1.6f is ");
|
||||
if (fp1 > fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.5f <= 1.6f is ");
|
||||
if (fp1 <= fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.5f >= 1.6f is ");
|
||||
if (fp1 >= fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
|
||||
fp1 = 1.6f;
|
||||
printf("1.6f == 1.6f is ");
|
||||
if (fp1 == fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.6f != 1.6f is ");
|
||||
if (fp1 != fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.6f < 1.6f is ");
|
||||
if (fp1 < fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.6f > 1.6f is ");
|
||||
if (fp1 > fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.6f <= 1.6f is ");
|
||||
if (fp1 <= fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
printf("1.6f >= 1.6f is ");
|
||||
if (fp1 >= fp2) {
|
||||
printf("true\n");
|
||||
} else {
|
||||
printf("false\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
183
test/float/float-basic.c
Normal file
183
test/float/float-basic.c
Normal file
@ -0,0 +1,183 @@
|
||||
|
||||
// test basic arithmetic operations
|
||||
// WIP WIP WIP
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x10];
|
||||
char buf2[0x10];
|
||||
char buf3[0x10];
|
||||
|
||||
unsigned long l1,l2;
|
||||
|
||||
signed char var_schar;
|
||||
unsigned char var_uchar;
|
||||
signed int var_sint;
|
||||
unsigned int var_uint;
|
||||
signed long var_slong;
|
||||
unsigned long var_ulong;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("float-basic\n");
|
||||
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
|
||||
/* addition, variable + variable */
|
||||
printf("addition, variable + variable\n");
|
||||
fp1 = 12.34f;
|
||||
fp2 = 43.21f;
|
||||
fp3 = fp1 + fp2;
|
||||
printf("%s+%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf("fp3:0x%08lx [0x425e3333] %s (55.549999)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
|
||||
/* addition, variable + constant */
|
||||
printf("addition, variable + constant\n");
|
||||
fp3 = 55.549999f;
|
||||
fp1 = fp3 + 0.05f;
|
||||
printf("%s+%s=%s\n", _ftostr(buf, fp3), _ftostr(buf3, 0.05f), _ftostr(buf2, fp1));
|
||||
printf("fp3:0x%08lx [0x425e3333] %s\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
printf("fp1:0x%08lx [0x425e6666] %s\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
#if 1
|
||||
/* addition, constant + variable */
|
||||
printf("addition, constant + variable\n");
|
||||
fp2 = 43.21f;
|
||||
fp1 = 12.7f + fp2; // FIXME: wrong, the add is dropped?
|
||||
printf("%s+%s=%s\n", _ftostr(buf3, 12.7f), _ftostr(buf, fp2), _ftostr(buf2, fp1));
|
||||
printf("fp3:0x%08lx [0x425e3333] %s\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp1:0x%08lx [0x425e6666] %s\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
#endif
|
||||
/* addition, constant + constant (already tested by minimal) (omitted) */
|
||||
#ifdef CONIO
|
||||
cgetc();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* substraction, variable - constant */
|
||||
printf("substraction, variable - constant\n");
|
||||
fp1 = 12.34;
|
||||
fp3 = fp1 - 11.5f; // FIXME: Invalid operands for binary operator '-'
|
||||
printf("%s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 0x11.5f), _ftostr(buf3, fp3));
|
||||
printf("fp3:0x%08lx [] %s ()\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/* substraction, constant - variable */
|
||||
printf("substraction, constant - variable\n");
|
||||
fp2 = 12.34;
|
||||
fp3 = 11.5f - fp2;
|
||||
printf("%s-%s=%s\n", _ftostr(buf, 11.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf("fp3:0x%08lx [] %s ()\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/* substraction, variable - variable */
|
||||
printf("substraction, variable - variable\n");
|
||||
fp3 = fp1 - fp2;
|
||||
printf("%s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf("fp3:0x%08lx [0x41463d70] %s (12.389999)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
printf("conversions (integer variable to float)\n");
|
||||
var_schar = -12;
|
||||
fp1 = var_schar;
|
||||
var_uchar = 199;
|
||||
fp2 = var_uchar;
|
||||
printf("fp1 0x%08lx [] %s (-12)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2 0x%08lx [] %s (199)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
var_sint = -4711;
|
||||
fp1 = var_sint;
|
||||
var_uint = 42000;
|
||||
fp2 = var_uint;
|
||||
printf("fp1 0x%08lx [] %s (-4711)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2 0x%08lx [] %s (42000)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
var_slong = -4711456;
|
||||
fp1 = var_slong;
|
||||
var_ulong = 42000456;
|
||||
fp2 = var_ulong;
|
||||
printf("fp1 0x%08lx [] %s (-4711456)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2 0x%08lx [] %s (42000456)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
#ifdef CONIO
|
||||
cgetc();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
printf("conversions (float variable to integer)\n");
|
||||
fp1 = -12.3f;
|
||||
var_schar = (signed char)fp1;
|
||||
printf("fp1 0x%08lx %s (12.3) schar:%d (12)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1), (int)var_schar);
|
||||
fp2 = 19.9f;
|
||||
var_uchar = (unsigned char)fp2;
|
||||
printf("fp2 0x%08lx %s (19.9) uchar:%u (19)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2), (int)var_uchar);
|
||||
|
||||
fp1 = 1234.5f;
|
||||
var_sint = (signed short)fp1;
|
||||
printf("fp1 0x%08lx %s (1234.5) sint:%d (1234)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1), var_sint);
|
||||
fp2 = 1999.9f;
|
||||
var_uint = (unsigned short)fp2;
|
||||
printf("fp2 0x%08lx %s (1999.9) uint:%u (1999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_uint);
|
||||
|
||||
fp1 = 123456.5f;
|
||||
var_slong = (signed long)fp1;
|
||||
printf("fp1 0x%08lx %s (1234.5) slong:%ld (1234)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1), var_slong);
|
||||
fp2 = 199988.9f;
|
||||
var_ulong = (unsigned long)fp2;
|
||||
printf("fp2 0x%08lx %s (1999.9) ulong:%lu (1999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_ulong);
|
||||
|
||||
#if 1
|
||||
printf("multiplication, variable * variable\n");
|
||||
fp1 = 25.2f;
|
||||
fp2 = 2.3f;
|
||||
fp3 = fp1 * fp2;
|
||||
printf("%s*%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
printf("division, variable / variable\n");
|
||||
fp1 = 25.2f;
|
||||
fp2 = 2.3f;
|
||||
fp3 = fp1 / fp2;
|
||||
printf("%s/%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
#endif
|
||||
|
||||
// FIXME: does not compile
|
||||
#if 0
|
||||
fp1 = (fp2 == 2.5f) ? 1.5f : 0.5f;
|
||||
#endif
|
||||
|
||||
// NOT
|
||||
printf("binary negate (not)\n");
|
||||
fp1 = 12.6f;
|
||||
fp2 = !fp1;
|
||||
var_sint = !fp1;
|
||||
fp3 = !fp2;
|
||||
printf("fp2 0x%08lx [] %s () %d\n", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
|
||||
printf("fp3 0x%08lx [] %s ()\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
|
||||
fp1 = -12.6f;
|
||||
fp1 = 0.0f - fp1;
|
||||
fp2 = !fp1;
|
||||
var_sint = !fp1;
|
||||
fp3 = !fp2;
|
||||
printf("fp2 0x%08lx [] %s () %d\n", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
|
||||
printf("fp2 0x%08lx [] %s ()\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3 0x%08lx [] %s ()\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
138
test/float/float-cbm..c
Normal file
138
test/float/float-cbm..c
Normal file
@ -0,0 +1,138 @@
|
||||
|
||||
#ifdef __CC65__
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <cbmfp.h>
|
||||
|
||||
char strbuf[0x20];
|
||||
char strbuf2[0x20];
|
||||
char strbuf3[0x20];
|
||||
|
||||
|
||||
|
||||
typedef union {
|
||||
float f;
|
||||
unsigned char b[sizeof (float)];
|
||||
} U;
|
||||
|
||||
#ifdef __CC65__
|
||||
uint32_t ftobin(float f)
|
||||
#else
|
||||
unsigned long ftobin(float f)
|
||||
#endif
|
||||
{
|
||||
U u;
|
||||
u.f = f;
|
||||
#ifdef __CC65__
|
||||
return ((uint32_t)u.b[0] << 0) | ((uint32_t)u.b[1] << 8) | ((uint32_t)u.b[2] << 16) | ((uint32_t)u.b[3] << 24);
|
||||
#else
|
||||
return ((uint32_t)u.b[3] << 0) | ((uint32_t)u.b[2] << 8) | ((uint32_t)u.b[1] << 16) | ((uint32_t)u.b[0] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
float fd, fs;
|
||||
float a, b, c1;
|
||||
int c, i, t;
|
||||
int n;
|
||||
|
||||
void testconversions(void)
|
||||
{
|
||||
printf("\ntestconversions:\n\n");
|
||||
printf("ftobin(0x12345678):0x%08lx\n", ftobin((float)0x12345678));
|
||||
|
||||
/* 42 ieee754: 0x42280000 */
|
||||
b=_ctof(42);
|
||||
printf("b:0x%08lx ", ftobin(b));
|
||||
n=(int)((float)0x42280000);
|
||||
printf("n:%d\n", n);
|
||||
|
||||
b=_ctof(42);
|
||||
printf("b:0x%08lx ", ftobin(b));
|
||||
n=(int)(b);
|
||||
printf("n:%d\n", n);
|
||||
|
||||
b=_utof(42);
|
||||
printf("b:0x%08lx ", ftobin(b));
|
||||
n=(int)(b);
|
||||
printf("n:%d\n", n);
|
||||
|
||||
b=_stof(1234);
|
||||
printf("b:0x%08lx ", ftobin(b));
|
||||
n=(int)(b);
|
||||
printf("n:%d\n", n);
|
||||
|
||||
b=(float)(1234);
|
||||
printf("b:0x%08lx ", ftobin(b));
|
||||
n=(int)(b);
|
||||
printf("n:%d\n", n);
|
||||
|
||||
b=atof("1234");
|
||||
printf("b:0x%08lx ", ftobin(b));
|
||||
n=(int)(b);
|
||||
printf("n:%d\n", n);
|
||||
|
||||
_ftoa(strbuf, b);
|
||||
printf("s:%s\n", strbuf);
|
||||
|
||||
printf("a:%s\n", _ftostr(strbuf, (float)(1234)));
|
||||
|
||||
printf("a:%s b:%s c:%s\n",
|
||||
_ftostr(strbuf, (float)(1234)),
|
||||
_ftostr(strbuf2, (float)(5678)),
|
||||
_ftostr(strbuf3, (float)(9012))
|
||||
);
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
void testlogical(void)
|
||||
{
|
||||
printf("\ntestlogical:\n\n");
|
||||
a = (float)(0xffa5);
|
||||
b = (float)(0x5aff);
|
||||
printf("a:0x%08lx (0xffa5)\n", ftobin(a));
|
||||
printf("b:0x%08lx (0x5aff)\n", ftobin(b));
|
||||
c1 = _fand(a, b);
|
||||
printf("c1:0x%08lx\n", ftobin(c1));
|
||||
n=(int)(c1);
|
||||
printf("c1:%04x\n", n);
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define _fcmplt(_d, _s) (_fcmp((_d), (_s)) == 1)
|
||||
#define _fcmpgt(_d, _s) (_fcmp((_d), (_s)) == 255)
|
||||
#define _fcmpeq(_d, _s) (_fcmp((_d), (_s)) == 0)
|
||||
|
||||
void testcompare(void)
|
||||
{
|
||||
printf("\ntestcompare:\n\n");
|
||||
a=(float)(2);
|
||||
b=(float)(3);
|
||||
printf("cmp 2,3: %3d %d %d %d\n", fcmp(a, b), fcmpgt(a, b), fcmpeq(a, b), fcmplt(a, b));
|
||||
printf("cmp 3,2: %3d %d %d %d\n", fcmp(b, a), fcmpgt(b, a), fcmpeq(b, a), fcmplt(b, a));
|
||||
printf("cmp 2,2: %3d %d %d %d\n", fcmp(a, a), fcmpgt(a, a), fcmpeq(a, a), fcmplt(a, a));
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("sizeof (float): %d\n", (int)sizeof(float));
|
||||
testconversions();
|
||||
testlogical();
|
||||
testcompare();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
160
test/float/float-minimal.c
Normal file
160
test/float/float-minimal.c
Normal file
@ -0,0 +1,160 @@
|
||||
|
||||
// test minimal float support.
|
||||
// this should test everything that does NOT require linking a library
|
||||
// - float literals in code are recognized as such
|
||||
// - float variables are converted into the float binary format
|
||||
// - taking address from float and assigning via pointer works
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 42.01002f;
|
||||
float fp2; // non initialized
|
||||
float *fp_p; // non initialized
|
||||
|
||||
uintptr_t p;
|
||||
|
||||
float fp3;
|
||||
float fp4 = 23.12f;
|
||||
|
||||
char buf[0x10];
|
||||
|
||||
signed char var_schar;
|
||||
unsigned char var_uchar;
|
||||
signed int var_sint;
|
||||
unsigned int var_uint;
|
||||
signed long var_slong;
|
||||
unsigned long var_ulong;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 23.1234f;
|
||||
|
||||
printf("float-minimal\n");
|
||||
|
||||
printf("fp2:0x%08lx [0x41b8f5c3] %s (23.1234)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp4:0x%08lx [0x41b8f5c3] %s (23.12)\n", *((uint32_t*)&fp4), _ftostr(buf, fp4));
|
||||
#if 1
|
||||
printf("(global) get address, read via ptr\n");
|
||||
// get address of global (works)
|
||||
p = (uintptr_t)&fp1;
|
||||
fp_p = (float*)p;
|
||||
// read fp via pointer and assign local
|
||||
fp2 = *fp_p;
|
||||
|
||||
printf("fp1:0x%08lx [0x42280a43] %s (42.01002)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2:0x%08lx [0x42280a43] %s (42.01002)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
#endif
|
||||
#if 1
|
||||
printf("(local) get address, read via ptr\n");
|
||||
fp2 = 23.1234f;
|
||||
|
||||
// get address of local
|
||||
p = (uintptr_t)&fp2;
|
||||
fp_p = (float*)p;
|
||||
// read fp via pointer and assign global
|
||||
fp3 = *fp_p;
|
||||
|
||||
printf("fp2:0x%08lx [] %s (23.1234)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [] %s (23.1234)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
// addition
|
||||
#if 1
|
||||
printf("constant + constant\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
printf(" 0x%08lx [] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
|
||||
fp3 = 0.1f + 0.2f;
|
||||
printf("fp3:0x%08lx [] %s (0.3)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
// substraction
|
||||
#if 0
|
||||
printf("constant - constant\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f - 0.2f; //FIXME: Invalid operands for binary operator '-'
|
||||
|
||||
printf(" 0x%08lx [] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [] %s (0.3)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
// multiplication
|
||||
#if 0
|
||||
printf("constant * constant\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f * 0.2f; // FIXME: Precondition violated: IsClassInt (T), file 'cc65/datatype.c', line 1008
|
||||
|
||||
printf(" 0x%08lx [] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [] %s (0.3)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
|
||||
// division
|
||||
#if 0
|
||||
printf("constant / constant\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f / 0.2f; // FIXME: Precondition violated: IsClassInt (T), file 'cc65/datatype.c', line 1008
|
||||
|
||||
printf(" 0x%08lx [] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [] %s (0.3)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
#endif
|
||||
#ifdef CONIO
|
||||
cgetc();
|
||||
#endif
|
||||
|
||||
// comparisons
|
||||
#if 1
|
||||
/* FIXME: this does not work yet */
|
||||
printf("0.1f == 0.1f is "); if (0.1f == 0.1f) { printf("true\n"); } else { printf("false\n"); }
|
||||
printf("0.2f == 0.1f is "); if (0.2f == 0.1f) { printf("true\n"); } else { printf("false\n"); }
|
||||
printf("0.1f != 0.1f is "); if (0.1f != 0.1f) { printf("true\n"); } else { printf("false\n"); }
|
||||
printf("0.2f != 0.1f is "); if (0.2f != 0.1f) { printf("true\n"); } else { printf("false\n"); }
|
||||
#endif
|
||||
|
||||
#ifdef CONIO
|
||||
cgetc();
|
||||
#endif
|
||||
|
||||
// conversions
|
||||
#if 1
|
||||
printf("conversions (integer constant to float)\n");
|
||||
fp1 = -12;
|
||||
fp2 = 199;
|
||||
printf("fp1 0x%08lx [] %s (-12)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2 0x%08lx [] %s (199)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
fp1 = -4711;
|
||||
fp2 = 42000;
|
||||
printf("fp1 0x%08lx [] %s (-4711)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf("fp2 0x%08lx [] %s (42000)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
#endif
|
||||
#if 1
|
||||
printf("conversions (float constant to integer)\n");
|
||||
var_schar = (signed char)12.3f;
|
||||
printf("%s (12.3) schar:%d (12)\n", _ftostr(buf, 12.3f), (int)var_schar);
|
||||
var_uchar = (unsigned char)19.9f;
|
||||
printf("%s (19.9) uchar:%u (19)\n", _ftostr(buf, 19.9f), (int)var_uchar);
|
||||
|
||||
var_sint = (signed short)1234.5f;
|
||||
printf("%s (1234.5) sint:%d (1234)\n", _ftostr(buf, 1234.5f), var_sint);
|
||||
var_uint = (unsigned short)1999.9f;
|
||||
printf("%s (1999.9) uint:%u (1999)\n", _ftostr(buf, 1999.9f), var_uint);
|
||||
|
||||
var_slong = (signed long)123456.5f;
|
||||
printf("%s (123456.5f) slong:%ld (123456)\n", _ftostr(buf, 123456.5f), var_slong);
|
||||
var_ulong = (unsigned long)199988.9f;
|
||||
printf("%s (199988.9) ulong:%lu (199988)\n", _ftostr(buf, 199988.9f), var_ulong);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
350
test/float/floattest.c
Normal file
350
test/float/floattest.c
Normal file
@ -0,0 +1,350 @@
|
||||
|
||||
#ifdef __CC65__
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
#include <math.h>
|
||||
|
||||
char strbuf[0x20];
|
||||
char strbuf2[0x20];
|
||||
char strbuf3[0x20];
|
||||
|
||||
|
||||
|
||||
typedef union {
|
||||
float f;
|
||||
unsigned char b[sizeof (float)];
|
||||
} U;
|
||||
|
||||
#ifdef __CC65__
|
||||
uint32_t ftobin(float f)
|
||||
#else
|
||||
unsigned long ftobin(float f)
|
||||
#endif
|
||||
{
|
||||
U u;
|
||||
u.f = f;
|
||||
#ifdef __CC65__
|
||||
return ((uint32_t)u.b[0] << 0) | ((uint32_t)u.b[1] << 8) | ((uint32_t)u.b[2] << 16) | ((uint32_t)u.b[3] << 24);
|
||||
#else
|
||||
return ((uint32_t)u.b[3] << 0) | ((uint32_t)u.b[2] << 8) | ((uint32_t)u.b[1] << 16) | ((uint32_t)u.b[0] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
float fd, fs;
|
||||
float a, b, c1;
|
||||
int c, i, t;
|
||||
int n;
|
||||
|
||||
void csetpoint8(unsigned char x)
|
||||
{
|
||||
while(x--) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("*\n");
|
||||
}
|
||||
|
||||
#define YNUM 32
|
||||
#define YNUM2 16
|
||||
|
||||
#define XNUM 32
|
||||
#define XNUM2 16
|
||||
|
||||
void calcsin(void)
|
||||
{
|
||||
printf("sinus:\n");
|
||||
for(i = 0; i < YNUM; i++) {
|
||||
csetpoint8(XNUM2+((int)(sinf(deg2rad((float)(i),(float)(YNUM))) * (float)(YNUM2))/(YNUM/XNUM)));
|
||||
}
|
||||
}
|
||||
|
||||
void calccos(void)
|
||||
{
|
||||
printf("cosinus:\n");
|
||||
for(i = 0; i < YNUM; i++) {
|
||||
fs=deg2rad((float)(i),(float)(YNUM));
|
||||
fd=cosf(fs) * (float)(YNUM2);
|
||||
csetpoint8(XNUM2+((int)(fd)/(YNUM/XNUM)));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __CC65__
|
||||
|
||||
int fx, fy;
|
||||
|
||||
#define CYNUM 20
|
||||
#define CYNUM2 10
|
||||
|
||||
#define CXNUM 20
|
||||
#define CXNUM2 10
|
||||
|
||||
void cplot(unsigned char x, unsigned char y)
|
||||
{
|
||||
gotoxy(x,y);cputc('*');
|
||||
}
|
||||
|
||||
void testatan2(void)
|
||||
{
|
||||
for(i = 0; i < YNUM; i++) {
|
||||
fx = CXNUM2+((int)((sinf(deg2rad((float)(i),(float)(CYNUM)))*(float)(CYNUM2)))/(CYNUM/CXNUM));
|
||||
|
||||
fs = deg2rad((float)(i), (float)(CYNUM));
|
||||
fd = cosf(fs) * (float)(CYNUM2);
|
||||
fy = CXNUM2 + ((int)(fd) / (CYNUM/CXNUM));
|
||||
|
||||
cplot(fx, fy);
|
||||
fd = fatan2((float)(fx-CXNUM2), (float)(fy-CYNUM2));
|
||||
_ftostr(strbuf, fd);
|
||||
cputs(strbuf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void calcpoly1(void){
|
||||
|
||||
p=malloc(sizeof(fpoly)+((1+3)*sizeof(float)));
|
||||
p.exponent=3;
|
||||
|
||||
// _strtof(&(p->coffs[3]),"0.25");
|
||||
// _strtof(&(p->coffs[2]),"1");
|
||||
// _strtof(&(p->coffs[1]),"-0.5");
|
||||
// _strtof(&(p->coffs[0]),"0.25");
|
||||
|
||||
// _ftostr(&strbuf,&(p->coffs[3])); printf("a0:%s\n",strbuf);
|
||||
// _ftostr(&strbuf,&(p->coffs[2])); printf("a1:%s\n",strbuf);
|
||||
// _ftostr(&strbuf,&(p->coffs[1])); printf("a2:%s\n",strbuf);
|
||||
// _ftostr(&strbuf,&(p->coffs[0])); printf("a3:%s\n",strbuf);
|
||||
|
||||
// _fpoly1(&fd,&p,&_f_pi);
|
||||
// _ftostr(&strbuf,&fd); printf("x:%s\n",strbuf);
|
||||
|
||||
for(i=0;i<256;i++){
|
||||
fs=_(float)(i);
|
||||
_ftostr(&strbuf,fs); printf("%s:",strbuf);
|
||||
fd=_fpoly1(&p,&fs);
|
||||
_ftostr(&strbuf,fd); printf("%s\n",strbuf);
|
||||
// c=_(int)(&fd);
|
||||
// csetpoint8(i/(256/35),12+(c/(256/23)));
|
||||
}
|
||||
|
||||
free(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned short var_bs;
|
||||
unsigned short var_fs;
|
||||
float var_i;
|
||||
unsigned char var_w;
|
||||
unsigned char var_j;
|
||||
float var_k;
|
||||
unsigned short var_co;
|
||||
|
||||
void f1(void)
|
||||
{
|
||||
printf("i:0x%08lx\n",ftobin(_ctof(0)));
|
||||
|
||||
#if 0
|
||||
printf("exp mantissa sign\n");
|
||||
printf("%02x ",*(unsigned char*)(1024+(40*2)+0));
|
||||
printf("%02x ",*(unsigned char*)(1024+(40*2)+1));
|
||||
printf("%02x ",*(unsigned char*)(1024+(40*2)+2));
|
||||
printf("%02x ",*(unsigned char*)(1024+(40*2)+3));
|
||||
printf("%02x ",*(unsigned char*)(1024+(40*2)+4));
|
||||
printf("%02x ",*(unsigned char*)(1024+(40*2)+5));
|
||||
#endif
|
||||
|
||||
var_bs=1024;
|
||||
var_fs=55304;
|
||||
|
||||
// var_i=_(float)(var_bs);while(1)
|
||||
var_i=(float)(2);while(1)
|
||||
{
|
||||
printf("i:%d\n",(int)(var_i));
|
||||
var_bs++;if(var_bs==1030)break;
|
||||
|
||||
#if 0
|
||||
if(FCMPGT(0x00028000,U16TOF(0)))
|
||||
{
|
||||
if (FCMPGTEQ(var_i,(U16TOF(var_bs+1000)))) break;
|
||||
}
|
||||
else if(FCMPLT(0x00028000,U16TOF(0)))
|
||||
{
|
||||
if (FCMPLTEQ(var_i,(U16TOF(var_bs+1000)))) break;
|
||||
}
|
||||
#endif
|
||||
// var_i=var_i + 0x00028000;
|
||||
var_i=var_i + 0x00818000; // FIXME: float value?
|
||||
// var_i=var_i + _ctof(1);
|
||||
};
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void testbinary(void)
|
||||
{
|
||||
printf("\ntestbinary:\n\n");
|
||||
n= 5;b=(float)(n);printf("%d:0x%08lx\n", n, ftobin(b));
|
||||
n=-5;b=(float)(n);printf("%d:0x%08lx\n", n, ftobin(b));
|
||||
n= 2;b=(float)(n);printf("%d:0x%08lx\n", n, ftobin(b));
|
||||
n= 3;b=(float)(n);printf("%d:0x%08lx\n", n, ftobin(b));
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
void testbasicmath(void)
|
||||
{
|
||||
printf("\ntestbasicmath:\n\n");
|
||||
t=123;
|
||||
fd=(float)((int)t);
|
||||
fs=_fneg(fd);
|
||||
_ftostr(strbuf,fd);
|
||||
printf("123:%s\n",strbuf);
|
||||
_ftostr(strbuf,fs);
|
||||
printf("-123:%s\n",strbuf);
|
||||
|
||||
a = (float)(4321);
|
||||
b = (float)(1234);
|
||||
printf("4321:0x%08lx\n", ftobin(a));
|
||||
printf("1234:0x%08lx\n", ftobin(b));
|
||||
c1 = a + b;
|
||||
printf("4321+1234:0x%08lx\n", ftobin(c1));
|
||||
_ftoa(strbuf, c1);
|
||||
printf("4321+1234:%s\n", strbuf);
|
||||
|
||||
a = (float)(1111);
|
||||
b = (float)(2222);
|
||||
printf("1111:0x%08lx\n", ftobin(a));
|
||||
printf("2222:0x%08lx\n", ftobin(b));
|
||||
c1 = a - b;
|
||||
printf("1111-2222:0x%08lx\n", ftobin(c1));
|
||||
_ftoa(strbuf, c1);
|
||||
printf("1111-2222:%s\n", strbuf);
|
||||
|
||||
fd=(float)((int)t);
|
||||
fs=(float)((int)2);
|
||||
fd=fd / fs;
|
||||
_ftostr(strbuf,fd);
|
||||
printf("t:%s\n",strbuf);
|
||||
|
||||
// 1234 / 60 = 20,5666...
|
||||
t=1234;
|
||||
fd=(float)((int)t);
|
||||
fs=(float)((int)60);
|
||||
fd=fd / fs;
|
||||
_ftostr(strbuf,fd);
|
||||
printf("t:%s\n",strbuf);
|
||||
|
||||
// 5678 / 60 = 94,6333...
|
||||
t=5678;
|
||||
fd=(float)((int)t);
|
||||
fs=(float)((int)60);
|
||||
fd=fd / fs;
|
||||
_ftostr(strbuf,fd);
|
||||
printf("t:%s\n",strbuf);
|
||||
|
||||
// ! operator DOES work on floats!
|
||||
fd=(float)((int)4);
|
||||
fd=!fd;
|
||||
_ftostr(strbuf,!fd);
|
||||
printf("!!4:%s\n",strbuf);
|
||||
|
||||
fd=(float)((int)0);
|
||||
fd=!fd;
|
||||
_ftostr(strbuf,!fd);
|
||||
printf("!!0:%s\n",strbuf);
|
||||
|
||||
a = 10.0f;
|
||||
b = powf(a,(float)(1)); printf("0x%08lx %s\n", ftobin(b), _ftoa(strbuf,b));
|
||||
b = powf(a,(float)(2)); printf("0x%08lx %s\n", ftobin(b), _ftoa(strbuf,b));
|
||||
b = powf(a,(float)(3)); printf("0x%08lx %s\n", ftobin(b), _ftoa(strbuf,b));
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define fcmp(_d, _s) (((_d) < (_s)) ? 1 : (((_d) > (_s)) ? 255 : (0)))
|
||||
#define fcmplt(_d, _s) ((_d) < (_s))
|
||||
#define fcmpgt(_d, _s) ((_d) > (_s))
|
||||
#define fcmpeq(_d, _s) ((_d) == (_s))
|
||||
|
||||
void testcompare(void)
|
||||
{
|
||||
printf("\ntestcompare:\n\n");
|
||||
a=(float)(2);
|
||||
b=(float)(3);
|
||||
printf("cmp 2,3: %3d %d %d %d\n", fcmp(a, b), fcmpgt(a, b), fcmpeq(a, b), fcmplt(a, b));
|
||||
printf("cmp 3,2: %3d %d %d %d\n", fcmp(b, a), fcmpgt(b, a), fcmpeq(b, a), fcmplt(b, a));
|
||||
printf("cmp 2,2: %3d %d %d %d\n", fcmp(a, a), fcmpgt(a, a), fcmpeq(a, a), fcmplt(a, a));
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void testprinting(void)
|
||||
{
|
||||
printf("\ntestprinting:\n\n");
|
||||
a = 1.0f;
|
||||
b = (a / 10.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 100.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 1000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 10000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
// printf("\n");
|
||||
a = 2.0f;
|
||||
b = (a / 10.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 100.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 1000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 10000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
// printf("\n");
|
||||
a = 400000000.0f;
|
||||
b = (a * 10.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a * 100.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a * 1000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a * 10000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
// printf("\n");
|
||||
a = -2.0f;
|
||||
b = (a / 10.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 100.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 1000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a / 10000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
// printf("\n");
|
||||
a = -400000000.0f;
|
||||
b = (a * 10.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a * 100.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a * 1000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
b = (a * 10000.0f); printf("0x%08lx %s %s\n", ftobin(b), _ftostr(strbuf, b), _ftoa(strbuf2, b));
|
||||
#ifdef __CC65__
|
||||
cgetc();
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("sizeof (float): %d\n", (int)sizeof(float));
|
||||
|
||||
testbasicmath();
|
||||
// testlogical();
|
||||
testbinary();
|
||||
testcompare();
|
||||
testprinting();
|
||||
#if 0
|
||||
f1();
|
||||
|
||||
calcsin();
|
||||
calccos();
|
||||
testatan2(); // FIXME
|
||||
#endif
|
||||
#if 0
|
||||
calcpoly1();
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
49
test/float/gccstubs.c
Normal file
49
test/float/gccstubs.c
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
float _fneg(float f)
|
||||
{
|
||||
return f * -1.0f;
|
||||
}
|
||||
|
||||
float _fand(float f1, float f2)
|
||||
{
|
||||
return ((unsigned)f1) & ((unsigned)f2);
|
||||
}
|
||||
|
||||
char buffer[32];
|
||||
|
||||
char *_ftostr(char *d, float s)
|
||||
{
|
||||
if (d == NULL) {
|
||||
d = &buffer[0];
|
||||
}
|
||||
sprintf(d, "%f", (double)s);
|
||||
return d;
|
||||
}
|
||||
|
||||
char *_ftoa(char *d, float s)
|
||||
{
|
||||
if (d == NULL) {
|
||||
d = &buffer[0];
|
||||
}
|
||||
sprintf(d, "%f", (double)s);
|
||||
return d;
|
||||
}
|
||||
|
||||
float _ctof(char c)
|
||||
{
|
||||
return (float)c;
|
||||
}
|
||||
|
||||
float _utof(unsigned int c)
|
||||
{
|
||||
return (float)c;
|
||||
}
|
||||
|
||||
float _stof(signed int c)
|
||||
{
|
||||
return (float)c;
|
||||
}
|
97
test/float/ieee754/_ftostr.c
Normal file
97
test/float/ieee754/_ftostr.c
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
char buffer[32];
|
||||
|
||||
char * __fastcall__ _ftostr(char *d, float s)
|
||||
{
|
||||
float f;
|
||||
unsigned char *p;
|
||||
char *bp, *buf;
|
||||
int exp;
|
||||
unsigned long mantissa;
|
||||
unsigned long val;
|
||||
int sign;
|
||||
unsigned char n;
|
||||
static char digits[10]={0,1,2,3,4,5,6,7,8,9};
|
||||
|
||||
unsigned long mantissa_mod = 1000000000;
|
||||
unsigned long mantissa_rest;
|
||||
|
||||
if (d == NULL) {
|
||||
buf = bp = &buffer[0];
|
||||
} else {
|
||||
buf = bp = d;
|
||||
}
|
||||
|
||||
f = s;
|
||||
p = (unsigned char*)&f;
|
||||
|
||||
// printf("%02x %02x %02x %02x\n", p[3], p[2], p[1], p[0]);
|
||||
|
||||
sign = (p[3] & 0x80) ? 1 : 0;
|
||||
exp = ((p[3] << 1) & 0xfe) | ((p[2] >> 7) & 1);
|
||||
exp -= 127;
|
||||
mantissa = p[2] & 0x7f;
|
||||
mantissa <<=8;
|
||||
mantissa |= p[1];
|
||||
mantissa <<=8;
|
||||
mantissa |= p[0];
|
||||
|
||||
*bp++ = sign ? '-' : ' ';
|
||||
|
||||
*bp++ = '1';
|
||||
*bp++ = '.';
|
||||
|
||||
val = 0xff;
|
||||
// printf("mantissa: %ld\n", mantissa);
|
||||
mantissa_rest = mantissa;
|
||||
for (n = 0; n < 10; n++) {
|
||||
// printf("n:%2d rest:%ld mod:%ld\n", n, mantissa_rest, mantissa_mod);
|
||||
if ((mantissa_mod <= mantissa_rest) && (mantissa_rest > 0)) {
|
||||
val = mantissa_rest / mantissa_mod;
|
||||
// printf("n:%2d val:%ld\n", n, val);
|
||||
// *bp++ = digits[(int)val];
|
||||
*bp++ = '0' + val;
|
||||
mantissa_rest -= (val * mantissa_mod);
|
||||
}
|
||||
mantissa_mod /= 10;
|
||||
}
|
||||
if (val == 0xff) {
|
||||
*bp++ = '0';
|
||||
}
|
||||
|
||||
// *bp++ = 'e';
|
||||
// *bp++ = 0;
|
||||
*bp++ = '*';
|
||||
*bp++ = '2';
|
||||
*bp++ = '^';
|
||||
|
||||
// printf("exp: %ld\n", exp);
|
||||
mantissa_mod = 1000;
|
||||
if (exp < 0) {
|
||||
mantissa_rest = -1 * exp;
|
||||
*bp++ = '-';
|
||||
} else {
|
||||
mantissa_rest = exp;
|
||||
}
|
||||
val = 0xff;
|
||||
for (n = 0; n < 10; n++) {
|
||||
// printf("n:%2d rest:%ld mod:%ld\n", n, mantissa_rest, mantissa_mod);
|
||||
if ((mantissa_mod <= mantissa_rest) && (mantissa_rest > 0)) {
|
||||
val = mantissa_rest / mantissa_mod;
|
||||
// printf("n:%2d val:%ld\n", n, val);
|
||||
// *bp++ = digits[(int)val];
|
||||
*bp++ = '0' + val;
|
||||
mantissa_rest -= (val * mantissa_mod);
|
||||
}
|
||||
mantissa_mod /= 10;
|
||||
}
|
||||
if (val == 0xff) {
|
||||
*bp++ = '0';
|
||||
}
|
||||
*bp++ = 0;
|
||||
|
||||
return buf;
|
||||
}
|
7
test/float/ieee754/afloat.s
Normal file
7
test/float/ieee754/afloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export afloat
|
||||
afloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/ieee754/aufloat.s
Normal file
7
test/float/ieee754/aufloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export aufloat
|
||||
aufloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/ieee754/axfloat.s
Normal file
7
test/float/ieee754/axfloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export axfloat
|
||||
axfloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/ieee754/axufloat.s
Normal file
7
test/float/ieee754/axufloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export axufloat
|
||||
axufloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/ieee754/eaxfloat.s
Normal file
7
test/float/ieee754/eaxfloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export eaxfloat
|
||||
eaxfloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/ieee754/eaxufloat.s
Normal file
7
test/float/ieee754/eaxufloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export eaxufloat
|
||||
eaxufloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/ieee754/fbnegeax.s
Normal file
7
test/float/ieee754/fbnegeax.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export fbnegeax
|
||||
fbnegeax:
|
||||
; FIXME
|
||||
rts
|
8
test/float/ieee754/feaxint.s
Normal file
8
test/float/ieee754/feaxint.s
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
; float -> 16bit int
|
||||
.export feaxint
|
||||
feaxint:
|
||||
; FIXME
|
||||
rts
|
8
test/float/ieee754/feaxlong.s
Normal file
8
test/float/ieee754/feaxlong.s
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
; float -> 32bit long
|
||||
.export feaxlong
|
||||
feaxlong:
|
||||
; FIXME
|
||||
rts
|
637
test/float/ieee754/ftosaddeax.s
Normal file
637
test/float/ieee754/ftosaddeax.s
Normal file
@ -0,0 +1,637 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.importzp sp, sreg, tmp1
|
||||
.import addysp1
|
||||
.import addysp
|
||||
.import popax
|
||||
|
||||
; Primary = TOS + Primary (like tosaddeax)
|
||||
.export ftosaddeax
|
||||
;ftosaddeax:
|
||||
; FIXME
|
||||
; rts
|
||||
|
||||
; CC65 runtime: long add
|
||||
|
||||
; ; EAX = TOS + EAX
|
||||
;
|
||||
; ;tosadd0ax:
|
||||
; ldy #$00
|
||||
; sty sreg
|
||||
; sty sreg+1
|
||||
;
|
||||
; ;tosaddeax:
|
||||
; clc
|
||||
; ldy #0
|
||||
; adc (sp),y ; lo byte
|
||||
; iny
|
||||
;
|
||||
; sta tmp1 ; use as temp storage
|
||||
; txa
|
||||
; adc (sp),y ; byte 1
|
||||
; tax
|
||||
; iny
|
||||
;
|
||||
; lda sreg
|
||||
; adc (sp),y ; byte 2
|
||||
; sta sreg
|
||||
; iny
|
||||
;
|
||||
; lda sreg+1
|
||||
; adc (sp),y ; byte 3
|
||||
; sta sreg+1
|
||||
; lda tmp1 ; load byte 0
|
||||
; jmp addysp1 ; drop TOS
|
||||
|
||||
|
||||
; found at https://github.com/CrashAndSideburns/6502ieee754/blob/main/arithmetic/addition.s
|
||||
|
||||
;addition:
|
||||
ftosaddeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
|
||||
lda #0
|
||||
sta SIGN_ONE
|
||||
sta SIGN_TWO
|
||||
|
||||
; Pull 2 LSBs of second parameter off of stack.
|
||||
pha
|
||||
lda sreg+1
|
||||
ASL
|
||||
STA MANTISSA_TWO + 3
|
||||
lda sreg+0
|
||||
ROL
|
||||
STA MANTISSA_TWO + 2
|
||||
|
||||
; Pull MSB of mantissa off of stack and shift exponent LSB into carry.
|
||||
tax
|
||||
ROL
|
||||
STA MANTISSA_TWO + 1
|
||||
|
||||
; Pull MSB off of stack, shift in exponent LSB, store sign.
|
||||
PLA
|
||||
ROL
|
||||
STA EXPONENT_TWO
|
||||
ROL SIGN_TWO
|
||||
|
||||
;-----------------
|
||||
|
||||
; Pull 2 LSBs of first parameter off of stack.
|
||||
ldy #0
|
||||
lda (sp),y ; lsb
|
||||
ASL
|
||||
STA MANTISSA_ONE + 3
|
||||
iny
|
||||
lda (sp),y
|
||||
ROL
|
||||
STA MANTISSA_ONE + 2
|
||||
|
||||
; Pull MSB of mantissa off of stack and shift exponent LSB into carry.
|
||||
iny
|
||||
lda (sp),y
|
||||
ROL
|
||||
STA MANTISSA_ONE + 1
|
||||
|
||||
; Pull MSB off of stack, shift in exponent LSB, store sign.
|
||||
iny
|
||||
lda (sp),y ; msb
|
||||
ROL
|
||||
STA EXPONENT_ONE
|
||||
ROL SIGN_ONE
|
||||
|
||||
|
||||
; Add implicit 1 to mantissas if appropriate.
|
||||
@add_second_implicit_bit:
|
||||
LDA EXPONENT_TWO
|
||||
CMP #$00
|
||||
BEQ @add_first_implicit_bit
|
||||
SEC
|
||||
ROR MANTISSA_TWO + 1
|
||||
ROR MANTISSA_TWO + 2
|
||||
ROR MANTISSA_TWO + 3
|
||||
|
||||
@add_first_implicit_bit:
|
||||
LDA EXPONENT_ONE
|
||||
CMP #$00
|
||||
BEQ @manage_special_values
|
||||
SEC
|
||||
ROR MANTISSA_ONE + 1
|
||||
ROR MANTISSA_ONE + 2
|
||||
ROR MANTISSA_ONE + 3
|
||||
|
||||
@manage_special_values:
|
||||
; Check if first parameter has exponent #$ff.
|
||||
; If it does, first parameter is some special quantity.
|
||||
; If not, check if second parameter has epxonent #$ff.
|
||||
; If it does, then it is special and the first parameter is not, so propagate.
|
||||
; If neither parameter is special, move on to aligning mantissas.
|
||||
LDA EXPONENT_ONE
|
||||
CMP #$ff
|
||||
BEQ @first_parameter_special
|
||||
LDA EXPONENT_TWO
|
||||
CMP #$ff
|
||||
BEQ @propagate_second_parameter
|
||||
JMP @align_mantissas
|
||||
|
||||
@first_parameter_special:
|
||||
; Exponent is non-zero, so an implicit 1 has been added to mantissa.
|
||||
; Unless the mantissa with added implicit 1 is $800000, return first param.
|
||||
; If the mantissa is precisely $800000, first param is ±∞.
|
||||
LDA MANTISSA_ONE + 1
|
||||
CMP #$80
|
||||
BNE @propagate_first_parameter
|
||||
LDA MANTISSA_ONE + 2
|
||||
CMP #$00
|
||||
BNE @propagate_first_parameter
|
||||
LDA MANTISSA_ONE + 3
|
||||
CMP #$00
|
||||
BEQ @first_parameter_infinite
|
||||
|
||||
@propagate_first_parameter:
|
||||
; Shift out implicit bit, shift exponent and sign through.
|
||||
; Push return value onto stack.
|
||||
; Push return address onto stack.
|
||||
; Return from subroutine.
|
||||
ASL MANTISSA_ONE + 1
|
||||
LSR SIGN_ONE
|
||||
ROR EXPONENT_ONE
|
||||
ROR MANTISSA_ONE + 1
|
||||
|
||||
; LDA EXPONENT_ONE
|
||||
; PHA
|
||||
; LDA MANTISSA_ONE + 1
|
||||
; PHA
|
||||
; LDA MANTISSA_ONE + 2
|
||||
; PHA
|
||||
; LDA MANTISSA_ONE + 3
|
||||
; PHA
|
||||
|
||||
; LDA $01
|
||||
; PHA
|
||||
; LDA $00
|
||||
; PHA
|
||||
|
||||
LDA EXPONENT_ONE
|
||||
sta sreg+1
|
||||
LDA MANTISSA_ONE + 1
|
||||
sta sreg+0
|
||||
LDX MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 3
|
||||
; ldx #$43
|
||||
; lda #$21
|
||||
jmp addysp1 ; drop TOS
|
||||
|
||||
RTS
|
||||
|
||||
@first_parameter_infinite:
|
||||
; Check if second parameter is also ±∞.
|
||||
; If second param is not special, propagate infinity.
|
||||
; If second param is NaN, propagate NaN.
|
||||
LDA EXPONENT_TWO
|
||||
CMP #$ff
|
||||
BNE @propagate_first_parameter
|
||||
LDA MANTISSA_TWO + 1
|
||||
CMP #$80
|
||||
BNE @propagate_second_parameter
|
||||
LDA MANTISSA_TWO + 2
|
||||
CMP #$00
|
||||
BNE @propagate_second_parameter
|
||||
LDA MANTISSA_TWO + 3
|
||||
CMP #$00
|
||||
BNE @propagate_second_parameter
|
||||
|
||||
@adding_infinities:
|
||||
; First and second parameters are both ±∞.
|
||||
; Check if they have opposite sign.
|
||||
; (+∞)+(-∞) = (-∞)+(+∞) = NaN.
|
||||
; If they have opposite sign, return a NaN.
|
||||
; Otherwise, return the first parameter.
|
||||
LDA SIGN_ONE
|
||||
EOR SIGN_TWO
|
||||
BEQ @propagate_first_parameter
|
||||
; LDA #$ff
|
||||
; PHA
|
||||
; PHA
|
||||
; PHA
|
||||
; PHA
|
||||
|
||||
LDA #$ff
|
||||
sta sreg+1
|
||||
sta sreg
|
||||
tax
|
||||
jmp addysp1 ; drop TOS
|
||||
|
||||
; LDA $01
|
||||
; PHA
|
||||
; LDA $00
|
||||
; PHA
|
||||
|
||||
RTS
|
||||
|
||||
@propagate_second_parameter:
|
||||
; Shift out implicit bit, shift exponent and sign through.
|
||||
; Push return value onto stack.
|
||||
; Push return address onto stack.
|
||||
; Return from subroutine.
|
||||
ASL MANTISSA_TWO + 1
|
||||
LSR SIGN_TWO
|
||||
ROR EXPONENT_TWO
|
||||
ROR MANTISSA_TWO + 1
|
||||
|
||||
; LDA EXPONENT_TWO
|
||||
; PHA
|
||||
; LDA MANTISSA_TWO + 1
|
||||
; PHA
|
||||
; LDA MANTISSA_TWO + 2
|
||||
; PHA
|
||||
; LDA MANTISSA_TWO + 3
|
||||
; PHA
|
||||
|
||||
; LDA $01
|
||||
; PHA
|
||||
; LDA $00
|
||||
; PHA
|
||||
|
||||
LDA EXPONENT_TWO
|
||||
sta sreg+1
|
||||
LDA MANTISSA_TWO + 1
|
||||
sta sreg
|
||||
LDX MANTISSA_TWO + 2
|
||||
LDA MANTISSA_TWO + 3
|
||||
jmp addysp1 ; drop TOS
|
||||
|
||||
RTS
|
||||
|
||||
@align_mantissas:
|
||||
; Check if the mantissas differ by 25 or more.
|
||||
; If they do, propagate the parameter with the larger mantissa.
|
||||
; If they don't, shift the mantissa of the smaller parameter right.
|
||||
SEC
|
||||
LDA EXPONENT_TWO
|
||||
SBC EXPONENT_ONE
|
||||
BCC @first_difference_underflow
|
||||
CMP #25
|
||||
BCS @propagate_second_parameter
|
||||
@first_difference_underflow:
|
||||
SEC
|
||||
LDA EXPONENT_ONE
|
||||
SBC EXPONENT_TWO
|
||||
BCC @second_difference_underflow
|
||||
CMP #25
|
||||
BCS @propagate_first_parameter
|
||||
@second_difference_underflow:
|
||||
CMP #$00
|
||||
BEQ @apply_signs
|
||||
TAX
|
||||
BPL @shift_second_mantissa
|
||||
@shift_first_mantissa:
|
||||
LSR MANTISSA_ONE + 1
|
||||
ROR MANTISSA_ONE + 2
|
||||
ROR MANTISSA_ONE + 3
|
||||
ROR MANTISSA_ONE + 4
|
||||
ROR MANTISSA_ONE + 5
|
||||
ROR MANTISSA_ONE + 6
|
||||
INX
|
||||
CPX #$00
|
||||
BNE @shift_first_mantissa
|
||||
|
||||
LDA EXPONENT_TWO
|
||||
STA EXPONENT_ONE
|
||||
JMP @apply_signs
|
||||
@shift_second_mantissa:
|
||||
LSR MANTISSA_TWO + 1
|
||||
ROR MANTISSA_TWO + 2
|
||||
ROR MANTISSA_TWO + 3
|
||||
ROR MANTISSA_TWO + 4
|
||||
ROR MANTISSA_TWO + 5
|
||||
ROR MANTISSA_TWO + 6
|
||||
DEX
|
||||
CPX #$00
|
||||
BNE @shift_second_mantissa
|
||||
|
||||
@apply_signs:
|
||||
; Check the signs of both floats.
|
||||
; If a float has a 1 sign bit, take the 2's complement of the mantissa.
|
||||
@negate_first_mantissa:
|
||||
LDA SIGN_ONE
|
||||
CMP #$00
|
||||
BEQ @negate_second_mantissa
|
||||
LDA MANTISSA_ONE
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE
|
||||
LDA MANTISSA_ONE + 1
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 1
|
||||
LDA MANTISSA_ONE + 2
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 3
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 3
|
||||
LDA MANTISSA_ONE + 4
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 4
|
||||
LDA MANTISSA_ONE + 5
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 5
|
||||
LDA MANTISSA_ONE + 6
|
||||
EOR #$ff
|
||||
CLC
|
||||
ADC #$01
|
||||
STA MANTISSA_ONE + 6
|
||||
LDA MANTISSA_ONE + 5
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 5
|
||||
LDA MANTISSA_ONE + 4
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 4
|
||||
LDA MANTISSA_ONE + 3
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 3
|
||||
LDA MANTISSA_ONE + 2
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 1
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 1
|
||||
LDA MANTISSA_ONE
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE
|
||||
@negate_second_mantissa:
|
||||
LDA SIGN_TWO
|
||||
CMP #$00
|
||||
BEQ @sum_mantissas
|
||||
LDA MANTISSA_TWO
|
||||
EOR #$ff
|
||||
STA MANTISSA_TWO
|
||||
LDA MANTISSA_TWO + 1
|
||||
EOR #$ff
|
||||
STA MANTISSA_TWO + 1
|
||||
LDA MANTISSA_TWO + 2
|
||||
EOR #$ff
|
||||
STA MANTISSA_TWO + 2
|
||||
LDA MANTISSA_TWO + 3
|
||||
EOR #$ff
|
||||
STA MANTISSA_TWO + 3
|
||||
LDA MANTISSA_TWO + 4
|
||||
EOR #$ff
|
||||
STA MANTISSA_TWO + 4
|
||||
LDA MANTISSA_TWO + 5
|
||||
EOR #$ff
|
||||
STA MANTISSA_TWO + 5
|
||||
LDA MANTISSA_TWO + 6
|
||||
EOR #$ff
|
||||
CLC
|
||||
ADC #$01
|
||||
STA MANTISSA_TWO + 6
|
||||
LDA MANTISSA_TWO + 5
|
||||
ADC #$00
|
||||
STA MANTISSA_TWO + 5
|
||||
LDA MANTISSA_TWO + 4
|
||||
ADC #$00
|
||||
STA MANTISSA_TWO + 4
|
||||
LDA MANTISSA_TWO + 3
|
||||
ADC #$00
|
||||
STA MANTISSA_TWO + 3
|
||||
LDA MANTISSA_TWO + 2
|
||||
ADC #$00
|
||||
STA MANTISSA_TWO + 2
|
||||
LDA MANTISSA_TWO + 1
|
||||
ADC #$00
|
||||
STA MANTISSA_TWO + 1
|
||||
LDA MANTISSA_TWO
|
||||
ADC #$00
|
||||
STA MANTISSA_TWO
|
||||
|
||||
@sum_mantissas:
|
||||
; Sum the mantissas to obtain the mantissa of the return float.
|
||||
; Check if the resultant mantissa has a 1 MSB.
|
||||
; If it does, set the result sign to 1 and take the 2's complement of the mantissa.
|
||||
; If it doesn't, move on to normalising the resultant mantissa.
|
||||
CLC
|
||||
LDA MANTISSA_ONE + 6
|
||||
ADC MANTISSA_TWO + 6
|
||||
STA MANTISSA_ONE + 6
|
||||
LDA MANTISSA_ONE + 5
|
||||
ADC MANTISSA_TWO + 5
|
||||
STA MANTISSA_ONE + 5
|
||||
LDA MANTISSA_ONE + 4
|
||||
ADC MANTISSA_TWO + 4
|
||||
STA MANTISSA_ONE + 4
|
||||
LDA MANTISSA_ONE + 3
|
||||
ADC MANTISSA_TWO + 3
|
||||
STA MANTISSA_ONE + 3
|
||||
LDA MANTISSA_ONE + 2
|
||||
ADC MANTISSA_TWO + 2
|
||||
STA MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 1
|
||||
ADC MANTISSA_TWO + 1
|
||||
STA MANTISSA_ONE + 1
|
||||
LDA MANTISSA_ONE
|
||||
ADC MANTISSA_TWO
|
||||
STA MANTISSA_ONE
|
||||
|
||||
AND #$80
|
||||
CMP #$00
|
||||
BEQ @positive_sum
|
||||
|
||||
LDA MANTISSA_ONE
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE
|
||||
LDA MANTISSA_ONE + 1
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 1
|
||||
LDA MANTISSA_ONE + 2
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 3
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 3
|
||||
LDA MANTISSA_ONE + 4
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 4
|
||||
LDA MANTISSA_ONE + 5
|
||||
EOR #$ff
|
||||
STA MANTISSA_ONE + 5
|
||||
LDA MANTISSA_ONE + 6
|
||||
EOR #$ff
|
||||
CLC
|
||||
ADC #$01
|
||||
STA MANTISSA_ONE + 6
|
||||
LDA MANTISSA_ONE + 5
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 5
|
||||
LDA MANTISSA_ONE + 4
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 4
|
||||
LDA MANTISSA_ONE + 3
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 3
|
||||
LDA MANTISSA_ONE + 2
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 1
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 1
|
||||
LDA MANTISSA_ONE
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE
|
||||
LDA #$01
|
||||
STA SIGN_ONE
|
||||
JMP @normalise_mantissa
|
||||
@positive_sum:
|
||||
LDA #$00
|
||||
STA SIGN_ONE
|
||||
|
||||
@normalise_mantissa:
|
||||
; Now that the new mantissa has been computed, normalise it.
|
||||
; Check if the LSB of the byte before the MSB of the mantissa is 1.
|
||||
; If it is, shift the mantissa down and increment the mantissa.
|
||||
; If it isn't, move on to checking if we must shift left.
|
||||
LDA MANTISSA_ONE
|
||||
AND #$01
|
||||
CMP #$01
|
||||
BNE @no_overflow
|
||||
LSR MANTISSA_ONE
|
||||
ROR MANTISSA_ONE + 1
|
||||
ROR MANTISSA_ONE + 2
|
||||
ROR MANTISSA_ONE + 3
|
||||
ROR MANTISSA_ONE + 4
|
||||
ROR MANTISSA_ONE + 5
|
||||
ROR MANTISSA_ONE + 6
|
||||
INC EXPONENT_ONE
|
||||
JMP @round
|
||||
|
||||
@no_overflow:
|
||||
; Check if the MSB of the mantissa is 1.
|
||||
; If it is, move on to rounding.
|
||||
; If it isn't, shift mantissa left and decrement exponent until MSB is 1 or exponent is 0.
|
||||
LDA MANTISSA_ONE + 1
|
||||
AND #$80
|
||||
CMP #$80
|
||||
BEQ @round
|
||||
LDA EXPONENT_ONE
|
||||
CMP #$00
|
||||
BEQ @round
|
||||
ASL MANTISSA_ONE + 6
|
||||
ROL MANTISSA_ONE + 5
|
||||
ROL MANTISSA_ONE + 4
|
||||
ROL MANTISSA_ONE + 3
|
||||
ROL MANTISSA_ONE + 2
|
||||
ROL MANTISSA_ONE + 1
|
||||
ROL MANTISSA_ONE
|
||||
DEC EXPONENT_ONE
|
||||
JMP @no_overflow
|
||||
|
||||
@round:
|
||||
; Check if we have already produced ±∞ in the event that we decide not to round.
|
||||
; If we have, return ±∞.
|
||||
; If we haven't, check if the MSB of the byte after the mantissa is 0.
|
||||
; If it is, return, trucating the subsequent bits.
|
||||
; If it isn't, check if any subsequent bits are 1.
|
||||
; If any are, round up.
|
||||
; If none are, check if the LSB of the mantissa is 1.
|
||||
; If it is, round up.
|
||||
; If it isn't, return.
|
||||
LDA EXPONENT_ONE
|
||||
CMP #$ff
|
||||
BEQ @return_infinity
|
||||
LDA MANTISSA_ONE + 4
|
||||
AND #$80
|
||||
CMP #$00
|
||||
BEQ @return
|
||||
LDA MANTISSA_ONE + 4
|
||||
AND #$7f
|
||||
CMP #$00
|
||||
BNE @round_up
|
||||
LDA MANTISSA_ONE + 5
|
||||
CMP #$00
|
||||
BNE @round_up
|
||||
LDA MANTISSA_ONE + 6
|
||||
CMP #$00
|
||||
BNE @round_up
|
||||
LDA MANTISSA_ONE + 3
|
||||
AND #$01
|
||||
CMP #$00
|
||||
BEQ @return
|
||||
|
||||
@round_up:
|
||||
; Increment the mantissa by 1.
|
||||
; If the increment doesn't overflow, return.
|
||||
; If it does, shift the mantissa right and increment the exponent.
|
||||
; Check if incrementing the exponent left us with an exponent of #$ff.
|
||||
; If it did, return ±∞.
|
||||
; If it didn't, round again.
|
||||
CLC
|
||||
LDA MANTISSA_ONE + 3
|
||||
ADC #$01
|
||||
STA MANTISSA_ONE + 3
|
||||
LDA MANTISSA_ONE + 2
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 1
|
||||
ADC #$00
|
||||
STA MANTISSA_ONE + 1
|
||||
BCC @return
|
||||
ROL MANTISSA_ONE + 1
|
||||
ROL MANTISSA_ONE + 2
|
||||
ROL MANTISSA_ONE + 3
|
||||
ROL MANTISSA_ONE + 4
|
||||
ROL MANTISSA_ONE + 5
|
||||
ROL MANTISSA_ONE + 6
|
||||
INC EXPONENT_ONE
|
||||
LDA EXPONENT_ONE
|
||||
CMP #$ff
|
||||
BEQ @return_infinity
|
||||
JMP @round
|
||||
|
||||
@return_infinity:
|
||||
; If we have to return ±∞ due to an over/underflow, clear the mantissa.
|
||||
LDA #$00
|
||||
STA MANTISSA_ONE + 1
|
||||
STA MANTISSA_ONE + 2
|
||||
STA MANTISSA_ONE + 3
|
||||
@return:
|
||||
; Shift out implicit bit, shift exponent and sign through.
|
||||
; Push return value onto stack.
|
||||
; Push return address onto stack.
|
||||
; Return from subroutine.
|
||||
LDA EXPONENT_ONE
|
||||
CMP #$00
|
||||
BNE @return_normal
|
||||
LSR MANTISSA_ONE + 1
|
||||
ROR MANTISSA_ONE + 2
|
||||
ROR MANTISSA_ONE + 3
|
||||
BCS @round_up
|
||||
@return_normal:
|
||||
ASL MANTISSA_ONE + 1
|
||||
LSR SIGN_ONE
|
||||
ROR EXPONENT_ONE
|
||||
ROR MANTISSA_ONE + 1
|
||||
|
||||
; LDA EXPONENT_ONE
|
||||
; PHA
|
||||
; LDA MANTISSA_ONE + 1
|
||||
; PHA
|
||||
; LDA MANTISSA_ONE + 2
|
||||
; PHA
|
||||
; LDA MANTISSA_ONE + 3
|
||||
; PHA
|
||||
|
||||
; LDA $01
|
||||
; PHA
|
||||
; LDA $00
|
||||
; PHA
|
||||
|
||||
LDA EXPONENT_ONE
|
||||
sta sreg+1
|
||||
LDA MANTISSA_ONE + 1
|
||||
sta sreg
|
||||
LDX MANTISSA_ONE + 2
|
||||
LDA MANTISSA_ONE + 3
|
||||
jmp addysp1 ; drop TOS
|
||||
|
||||
RTS
|
||||
|
12
test/float/ieee754/ftosdiveax.s
Normal file
12
test/float/ieee754/ftosdiveax.s
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.importzp sp, sreg, tmp1
|
||||
.import addysp1
|
||||
.import addysp
|
||||
.import popax
|
||||
|
||||
.export ftosdiveax
|
||||
ftosdiveax:
|
||||
; FIXME
|
||||
rts
|
8
test/float/ieee754/ftoseqeax.s
Normal file
8
test/float/ieee754/ftoseqeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export ftoseqeax
|
||||
ftoseqeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/ieee754/ftosgeeax.s
Normal file
8
test/float/ieee754/ftosgeeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export ftosgeeax
|
||||
ftosgeeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/ieee754/ftosgteax.s
Normal file
8
test/float/ieee754/ftosgteax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export ftosgteax
|
||||
ftosgteax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/ieee754/ftosleeax.s
Normal file
8
test/float/ieee754/ftosleeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export ftosleeax
|
||||
ftosleeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/ieee754/ftoslteax.s
Normal file
8
test/float/ieee754/ftoslteax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export ftoslteax
|
||||
ftoslteax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
12
test/float/ieee754/ftosmuleax.s
Normal file
12
test/float/ieee754/ftosmuleax.s
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.importzp sp, sreg, tmp1
|
||||
.import addysp1
|
||||
.import addysp
|
||||
.import popax
|
||||
|
||||
.export ftosmuleax
|
||||
ftosmuleax:
|
||||
; FIXME
|
||||
rts
|
8
test/float/ieee754/ftosneeax.s
Normal file
8
test/float/ieee754/ftosneeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export ftosneeax
|
||||
ftosneeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
43
test/float/ieee754/ftossubeax.s
Normal file
43
test/float/ieee754/ftossubeax.s
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
.importzp sp, sreg, tmp1
|
||||
.import addysp1
|
||||
.import addysp
|
||||
.import popax
|
||||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.import ftosaddeax
|
||||
|
||||
.export ftossubeax
|
||||
ftossubeax:
|
||||
; FIXME
|
||||
rts
|
||||
|
||||
; found at https://github.com/CrashAndSideburns/6502ieee754/blob/main/arithmetic/addition.s
|
||||
; subtraction:
|
||||
|
||||
; Pull MSB of second parameter off of stack, flip sign bit, and push back to stack.
|
||||
; Proceed to addition.
|
||||
; TSX
|
||||
; TXA
|
||||
; CLC
|
||||
; ADC #$05
|
||||
; TAX
|
||||
; TXS
|
||||
; PLA
|
||||
; EOR #$80
|
||||
; PHA
|
||||
; TXA
|
||||
; SEC
|
||||
; SBC #$05
|
||||
; TAX
|
||||
; TXS
|
||||
|
||||
pha
|
||||
ldy #3
|
||||
lda (sp),y ; msb
|
||||
eor #$80
|
||||
sta (sp),y ; msb
|
||||
pla
|
||||
|
||||
jmp ftosaddeax
|
7
test/float/ieee754/ieee754.inc
Normal file
7
test/float/ieee754/ieee754.inc
Normal file
@ -0,0 +1,7 @@
|
||||
SIGN_ONE = $e2
|
||||
EXPONENT_ONE = $e3
|
||||
MANTISSA_ONE = $e4 ; e4, e5, e6, e7, e8, e9, ea (7 bytes)
|
||||
|
||||
SIGN_TWO = $eb
|
||||
EXPONENT_TWO = $ec
|
||||
MANTISSA_TWO = $ed
|
54
test/float/include/_float.h
Normal file
54
test/float/include/_float.h
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
#ifndef _FLOAT_H_
|
||||
#define _FLOAT_H_
|
||||
|
||||
/* ieee754 32bit format:
|
||||
*
|
||||
* sign
|
||||
* / /exponent/mantissa
|
||||
* 3 32222222 22211111111110000000000
|
||||
* 1 09876543 21098765432109876543210
|
||||
*
|
||||
* The sign is stored in bit 31.
|
||||
* The exponent can be computed from bits 23-30 by subtracting 127. (128 = 2^1)
|
||||
* The mantissa is stored in bits 0-22.
|
||||
* An invisible leading bit (i.e. it is not actually stored) with value 1.0
|
||||
* is placed in front, then bit 23 has a value of 1/2, bit 22 has value 1/4 etc.
|
||||
* As a result, the mantissa has a value between 1.0 and 2.
|
||||
*
|
||||
* 1.0 = exp=127, mantissa=0
|
||||
*
|
||||
* If the exponent reaches -127 (binary 00000000), the leading 1 is no longer
|
||||
* used to enable gradual underflow.
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char exponent; /* msb is the sign */
|
||||
unsigned char mantissa[3]; /* msb is lsb of exponent */
|
||||
} FLOAT754;
|
||||
|
||||
/* we dont wanna seriously use double precision eh? ;=P */
|
||||
/* #define double float */
|
||||
|
||||
/* string to/from float conversion functions */
|
||||
char *_ftoa(char *buf, float n);
|
||||
|
||||
/* string conversion functions, these use the exponential form */
|
||||
char * __fastcall__ _ftostr(char *d, float s); /* for vsprintf */
|
||||
float __fastcall__ _strtof(char *d);
|
||||
|
||||
/* beware, this is not standard */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
/* degrees to radiants */
|
||||
#define deg2rad(_fs, _n) ((_fs / _n) * (2.0f * M_PI))
|
||||
/* radiants to degrees deg = (rad / (2 * pi)) * 256 */
|
||||
#define rad2deg(_rad, _n) ((_rad / (2.0f * M_PI)) * _n)
|
||||
|
||||
/* resets fp-libs in Turbo-C and M$-C */
|
||||
#define _fpreset()
|
||||
|
||||
#endif /* _FLOAT_H_ */
|
||||
|
46
test/float/include/math.h
Normal file
46
test/float/include/math.h
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
#ifndef _MATH_H_
|
||||
#define _MATH_H_
|
||||
|
||||
#include "_float.h"
|
||||
|
||||
/* double pow(double x, double y); */
|
||||
float __fastcall__ powf(float f, float a); /* C99 */
|
||||
|
||||
/* double sin(double x); */
|
||||
float __fastcall__ sinf(float s); /* C99 */
|
||||
|
||||
/* double cos(double x); */
|
||||
float __fastcall__ cosf(float s); /* C99 */
|
||||
|
||||
/* double log(double x); */
|
||||
float __fastcall__ logf(float x); /* C99 */
|
||||
|
||||
/* double exp(double x); */
|
||||
float __fastcall__ expf(float x); /* C99 */
|
||||
|
||||
/* double sqrt(double x); */
|
||||
float __fastcall__ sqrtf(float x); /* C99 */
|
||||
|
||||
/* double tan(double x); */
|
||||
float __fastcall__ tanf(float x); /* C99 */
|
||||
|
||||
/* double atan(double x); */
|
||||
float __fastcall__ atanf(float x); /* C99 */
|
||||
|
||||
/* double fabs(double x); */
|
||||
float __fastcall__ fabsf(float x); /* C99 */
|
||||
|
||||
/* beware, this is not standard */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
/* FIXME */
|
||||
float __fastcall__ _fatan2(float x, float y);
|
||||
|
||||
|
||||
float ffloor(float x);
|
||||
|
||||
#endif /* _MATH_H_ */
|
||||
|
25
test/float/quick.c
Normal file
25
test/float/quick.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
#include <math.h>
|
||||
|
||||
unsigned char buf[32];*/
|
||||
|
||||
//unsigned char var_uchar;
|
||||
// float fp2;
|
||||
|
||||
float fp1 = 42.0f;
|
||||
float fp2 = 23;
|
||||
float fp3 = 33.0;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// fp2 = (float)((unsigned char)19);
|
||||
// var_uchar = (unsigned char)fp2;
|
||||
// var_uchar = (unsigned char)192.3f;
|
||||
// printf("fp2 0x%08lx %s (19.9) uchar:%u (19)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2), (int)var_uchar);
|
||||
|
||||
}
|
196
test/float/readme.md
Normal file
196
test/float/readme.md
Normal file
@ -0,0 +1,196 @@
|
||||
|
||||
## cc65 floating point support
|
||||
|
||||
WARNING: the following is just a brain dump after a long weekend of hacking. it
|
||||
sure needs cleanup etc :)
|
||||
|
||||
The current goal is to implement ieee754 support in the compiler, using the
|
||||
"float" datatype as the common 32bit float. ANYTHING ELSE COMES LATER
|
||||
|
||||
You can not use any of this to write software yet. Dont bother. This is for
|
||||
people who want to help pushing the floating point support further.
|
||||
|
||||
- build the compiler/toolchain/libs from this fptest branch
|
||||
- now you can build the programs in this directory
|
||||
|
||||
right now you'll have to use the cbm kernal wrapper library, as that is pretty
|
||||
much the only one that somewhat works :)
|
||||
|
||||
feel free to work on "real" ieee754 functions (see below)
|
||||
|
||||
## The Compiler
|
||||
|
||||
- for the time being i will handle and test only expressions where left and
|
||||
right side are both floats. that will enable me to fix and test a fair portion
|
||||
of what has to be done, before i will have to dive into the ugly areas of type
|
||||
conversion and casting.
|
||||
|
||||
NOT WORKING YET:
|
||||
|
||||
- float values as in "12.34f" work, but "12.34" does not - should it?
|
||||
- compare, float const vs float const
|
||||
- substraction, float variable - float constant (compile error)
|
||||
- multiplication operator, float const * float const (compile error)
|
||||
- division operator, float const / float const
|
||||
|
||||
- ternary operator (compile error)
|
||||
|
||||
- addition, float constant + float variable (compiles but does not work)
|
||||
|
||||
(and probably more :))
|
||||
|
||||
TODO (much later):
|
||||
|
||||
- add a cmdline option to the compiler to switch the float binary type (754, cbm,
|
||||
woz, ...). -> remember the code in fp.c/h
|
||||
|
||||
### Files & Functions
|
||||
|
||||
#### codegen.c
|
||||
|
||||
g_getimmed Load a constant into the primary register
|
||||
g_getstatic Fetch an static memory cell into the primary register
|
||||
g_getlocal Fetch specified local object (local var) into the primary register
|
||||
g_putstatic
|
||||
g_reglong
|
||||
g_regfloat Make sure, the value in the primary register a float. Convert if necessary
|
||||
g_typeadjust
|
||||
g_typecast Cast the value in the primary register to the operand size that is flagged by the lhs value
|
||||
oper Encode a binary operation.
|
||||
g_push
|
||||
g_push_float Push the primary register or a constant value onto the stack
|
||||
g_inc
|
||||
g_dec
|
||||
g_defdata
|
||||
g_defdata_float
|
||||
|
||||
(see below) g_add, g_sub, g_mul, g_div, g_neg, g_bneg
|
||||
(see below) g_eq, g_ne, g_lt, g_gt, g_le, g_ge
|
||||
(invalid) g_mod, g_or, g_xor, g_and, g_asr
|
||||
|
||||
#### datatype.c
|
||||
|
||||
ArithmeticConvert
|
||||
|
||||
#### expr.c
|
||||
|
||||
LimitExprValue
|
||||
parseadd
|
||||
parsesub
|
||||
|
||||
#### initdata.c
|
||||
|
||||
DefineData Output a data definition for the given expression
|
||||
|
||||
#### loadexpr.c
|
||||
|
||||
LoadExpr
|
||||
|
||||
#### locals.c
|
||||
|
||||
ParseAutoDecl
|
||||
|
||||
#### assignment.c
|
||||
|
||||
OpAssignArithmetic Parse an "=" (if 'Gen' is 0) or "op=" operation for arithmetic lhs
|
||||
|
||||
#### fp.c
|
||||
|
||||
wrapper for doing floating point operations on target floats
|
||||
|
||||
FP_D_As32bitRaw converts double into 32bit (float) and then returns its raw content as a 32bit int
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## The Library
|
||||
|
||||
cbmkernal:
|
||||
|
||||
this is a wrapper to the CBM kernal functions
|
||||
|
||||
- this one is fairly complete and should be OK to use when fixing/adding basic
|
||||
things in the compiler
|
||||
- the only missing functions are ftosrsubeax, fnegeax - which can be easily
|
||||
added once testcode is found that actually triggers it :)
|
||||
|
||||
ieee754:
|
||||
|
||||
this should become a freestanding ieee754 library
|
||||
|
||||
- basically everything missing except addition/substraction
|
||||
- compare functions are missing
|
||||
- mul, div functions are missing
|
||||
- type conversion functions are missing
|
||||
|
||||
woz:
|
||||
|
||||
historical float routines by woz :) unfortunately not ieee754
|
||||
|
||||
- (optionally) converting from/to ieee754 format is missing (compile time option)
|
||||
- compare functions are missing
|
||||
- type conversion functions are missing
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### runtime functions
|
||||
|
||||
these must be available in the runtime library
|
||||
|
||||
func description cbmfp wozfp 754 codegen.c
|
||||
|
||||
aufloat Primary 8bit unsigned -> float * - - g_regfloat
|
||||
afloat Primary 8bit signed -> float * - - g_regfloat
|
||||
axufloat Primary 16bit unsigned -> float * - - g_regfloat
|
||||
axfloat Primary 16bit signed -> float * - - g_regfloat
|
||||
eaxufloat Primary 32bit unsigned -> float * - - g_regfloat
|
||||
eaxfloat Primary 32bit signed -> float * - - g_regfloat
|
||||
|
||||
feaxint Primary float -> 16bit int * - - g_regint
|
||||
feaxlong Primary float -> 32bit long * - - g_reglong
|
||||
|
||||
ftosaddeax Primary = TOS + Primary * ? ? g_add
|
||||
ftossubeax Primary = TOS - Primary * ? ? g_sub
|
||||
ftosrsubeax Primary = Primary - TOS - - - g_rsub
|
||||
ftosmuleax Primary = TOS * Primary * ? - g_mul
|
||||
ftosdiveax Primary = TOS / Primary * ? - g_div
|
||||
|
||||
fnegeax Primary = -Primary - - - g_neg
|
||||
fbnegeax Primary = !Primary (return bool!) * - - g_bneg
|
||||
|
||||
ftosgeeax Test for greater than or equal to * - - g_ge
|
||||
ftosgteax Test for greater than * - - g_gt
|
||||
ftosleeax Test for less than or equal to * - - g_le
|
||||
ftoslteax Test for less than * - - g_lt
|
||||
ftosneeax Test for not equal * - - g_ne
|
||||
ftoseqeax Test for equal * - - g_eq
|
||||
|
||||
### extra functions
|
||||
|
||||
optional utility functions.
|
||||
|
||||
func description cbmfp wozfp 754
|
||||
|
||||
char *_ftostr(char *d, float s) * ? ? for printf family
|
||||
float _strtof(char *d) * - - for scanf family
|
||||
|
||||
### math.h functions
|
||||
|
||||
these are optional, required for standard libm
|
||||
|
||||
func description cbmfp wozfp 754
|
||||
|
||||
/* C99 */
|
||||
float powf(float f, float a); * - -
|
||||
float sinf(float s); * - -
|
||||
float cosf(float s); * - -
|
||||
float logf(float x); * * -
|
||||
float expf(float x); * - -
|
||||
float sqrtf(float x); * - -
|
||||
float tanf(float x); * - -
|
||||
float atanf(float x); * - -
|
||||
float fabsf(float x); * - -
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
https://www.geeksforgeeks.org/ieee-standard-754-floating-point-numbers/
|
||||
https://www.h-schmidt.net/FloatConverter/IEEE754.html
|
97
test/float/woz/_ftostr.c
Normal file
97
test/float/woz/_ftostr.c
Normal file
@ -0,0 +1,97 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
char buffer[32];
|
||||
|
||||
char * __fastcall__ _ftostr(char *d, float s)
|
||||
{
|
||||
float f;
|
||||
unsigned char *p;
|
||||
char *bp, *buf;
|
||||
int exp;
|
||||
unsigned long mantissa;
|
||||
unsigned long val;
|
||||
int sign;
|
||||
unsigned char n;
|
||||
static char digits[10]={0,1,2,3,4,5,6,7,8,9};
|
||||
|
||||
unsigned long mantissa_mod = 1000000000;
|
||||
unsigned long mantissa_rest;
|
||||
|
||||
if (d == NULL) {
|
||||
buf = bp = &buffer[0];
|
||||
} else {
|
||||
buf = bp = d;
|
||||
}
|
||||
|
||||
f = s;
|
||||
p = (unsigned char*)&f;
|
||||
|
||||
// printf("%02x %02x %02x %02x\n", p[3], p[2], p[1], p[0]);
|
||||
|
||||
sign = (p[3] & 0x80) ? 1 : 0;
|
||||
exp = ((p[3] << 1) & 0xfe) | ((p[2] >> 7) & 1);
|
||||
exp -= 127;
|
||||
mantissa = p[2] & 0x7f;
|
||||
mantissa <<=8;
|
||||
mantissa |= p[1];
|
||||
mantissa <<=8;
|
||||
mantissa |= p[0];
|
||||
|
||||
*bp++ = sign ? '-' : ' ';
|
||||
|
||||
*bp++ = '1';
|
||||
*bp++ = '.';
|
||||
|
||||
val = 0xff;
|
||||
// printf("mantissa: %ld\n", mantissa);
|
||||
mantissa_rest = mantissa;
|
||||
for (n = 0; n < 10; n++) {
|
||||
// printf("n:%2d rest:%ld mod:%ld\n", n, mantissa_rest, mantissa_mod);
|
||||
if ((mantissa_mod <= mantissa_rest) && (mantissa_rest > 0)) {
|
||||
val = mantissa_rest / mantissa_mod;
|
||||
// printf("n:%2d val:%ld\n", n, val);
|
||||
// *bp++ = digits[(int)val];
|
||||
*bp++ = '0' + val;
|
||||
mantissa_rest -= (val * mantissa_mod);
|
||||
}
|
||||
mantissa_mod /= 10;
|
||||
}
|
||||
if (val == 0xff) {
|
||||
*bp++ = '0';
|
||||
}
|
||||
|
||||
// *bp++ = 'e';
|
||||
// *bp++ = 0;
|
||||
*bp++ = '*';
|
||||
*bp++ = '2';
|
||||
*bp++ = '^';
|
||||
|
||||
// printf("exp: %ld\n", exp);
|
||||
mantissa_mod = 1000;
|
||||
if (exp < 0) {
|
||||
mantissa_rest = -1 * exp;
|
||||
*bp++ = '-';
|
||||
} else {
|
||||
mantissa_rest = exp;
|
||||
}
|
||||
val = 0xff;
|
||||
for (n = 0; n < 10; n++) {
|
||||
// printf("n:%2d rest:%ld mod:%ld\n", n, mantissa_rest, mantissa_mod);
|
||||
if ((mantissa_mod <= mantissa_rest) && (mantissa_rest > 0)) {
|
||||
val = mantissa_rest / mantissa_mod;
|
||||
// printf("n:%2d val:%ld\n", n, val);
|
||||
// *bp++ = digits[(int)val];
|
||||
*bp++ = '0' + val;
|
||||
mantissa_rest -= (val * mantissa_mod);
|
||||
}
|
||||
mantissa_mod /= 10;
|
||||
}
|
||||
if (val == 0xff) {
|
||||
*bp++ = '0';
|
||||
}
|
||||
*bp++ = 0;
|
||||
|
||||
return buf;
|
||||
}
|
7
test/float/woz/afloat.s
Normal file
7
test/float/woz/afloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export afloat
|
||||
afloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/woz/aufloat.s
Normal file
7
test/float/woz/aufloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export aufloat
|
||||
aufloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/woz/axfloat.s
Normal file
7
test/float/woz/axfloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export axfloat
|
||||
axfloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/woz/axufloat.s
Normal file
7
test/float/woz/axufloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export axufloat
|
||||
axufloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/woz/eaxfloat.s
Normal file
7
test/float/woz/eaxfloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export eaxfloat
|
||||
eaxfloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/woz/eaxufloat.s
Normal file
7
test/float/woz/eaxufloat.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export eaxufloat
|
||||
eaxufloat:
|
||||
; FIXME
|
||||
rts
|
7
test/float/woz/fbnegeax.s
Normal file
7
test/float/woz/fbnegeax.s
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export fbnegeax
|
||||
fbnegeax:
|
||||
; FIXME
|
||||
rts
|
8
test/float/woz/feaxint.s
Normal file
8
test/float/woz/feaxint.s
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
; float -> 16bit int
|
||||
.export feaxint
|
||||
feaxint:
|
||||
; FIXME
|
||||
rts
|
8
test/float/woz/feaxlong.s
Normal file
8
test/float/woz/feaxlong.s
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
; float -> 32bit long
|
||||
.export feaxlong
|
||||
feaxlong:
|
||||
; FIXME
|
||||
rts
|
9
test/float/woz/ftosaddeax.s
Normal file
9
test/float/woz/ftosaddeax.s
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosaddeax
|
||||
ftosaddeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
9
test/float/woz/ftosdiveax.s
Normal file
9
test/float/woz/ftosdiveax.s
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosdiveax
|
||||
ftosdiveax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftoseqeax.s
Normal file
8
test/float/woz/ftoseqeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftoseqeax
|
||||
ftoseqeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftosgeeax.s
Normal file
8
test/float/woz/ftosgeeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosgeeax
|
||||
ftosgeeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftosgteax.s
Normal file
8
test/float/woz/ftosgteax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosgteax
|
||||
ftosgteax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftosleeax.s
Normal file
8
test/float/woz/ftosleeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosleeax
|
||||
ftosleeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftoslteax.s
Normal file
8
test/float/woz/ftoslteax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftoslteax
|
||||
ftoslteax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
9
test/float/woz/ftosmuleax.s
Normal file
9
test/float/woz/ftosmuleax.s
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosmuleax
|
||||
ftosmuleax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftosneeax.s
Normal file
8
test/float/woz/ftosneeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftosneeax
|
||||
ftosneeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
test/float/woz/ftossubeax.s
Normal file
8
test/float/woz/ftossubeax.s
Normal file
@ -0,0 +1,8 @@
|
||||
.include "wozfp.inc"
|
||||
|
||||
.export ftossubeax
|
||||
ftossubeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
16
test/float/woz/wozfp.inc
Normal file
16
test/float/woz/wozfp.inc
Normal file
@ -0,0 +1,16 @@
|
||||
; .org $40 ; SET BASE PAGE ADRESSES
|
||||
; SIGN = *
|
||||
|
||||
SIGN = $40
|
||||
|
||||
X2 = SIGN+1 ; EXPONENT 2
|
||||
M2 = X2+1 ; MANTISSA 2
|
||||
X1 = M2+3 ; EXPONENT 1
|
||||
M1 = X1+1 ; MANTISSA 1
|
||||
E = M1+3 ; SCRATCH
|
||||
ZZ = E+4
|
||||
T = ZZ+4
|
||||
SEXP = T+4
|
||||
INT = SEXP+4
|
||||
;
|
||||
|
456
test/float/woz/wozfp.s
Normal file
456
test/float/woz/wozfp.s
Normal file
@ -0,0 +1,456 @@
|
||||
; JULY 5, 1976
|
||||
; BASIC FLOATING POINT ROUTINES
|
||||
; FOR 6502 MICROPROCESSOR
|
||||
; BY R. RANKIN AND S. WOZNIAK
|
||||
;
|
||||
; CONSISTING OF:
|
||||
; NATURAL LOG
|
||||
; COMMON LOG
|
||||
; EXPONENTIAL (E**X)
|
||||
; FLOAT FIX
|
||||
; FADD FSUB
|
||||
; FMUL FDIV
|
||||
;
|
||||
;
|
||||
; FLOATING POINT REPRESENTATION (4-BYTES)
|
||||
; EXPONENT BYTE 1
|
||||
; MANTISSA BYTES 2-4
|
||||
;
|
||||
; MANTISSA: TWO'S COMPLEMENT REPRESENTATION WITH SIGN IN
|
||||
; MSB OF HIGH-ORDER BYTE. MANTISSA IS NORMALIZED WITH AN
|
||||
; ASSUMED DECIMAL POINT BETWEEN BITS 5 AND 6 OF THE HIGH-ORDER
|
||||
; BYTE. THUS THE MANTISSA IS IN THE RANGE 1. TO 2. EXCEPT
|
||||
; WHEN THE NUMBER IS LESS THAN 2**(-128).
|
||||
;
|
||||
; EXPONENT: THE EXPONENT REPRESENTS POWERS OF TWO. THE
|
||||
; REPRESENTATION IS 2'S COMPLEMENT EXCEPT THAT THE SIGN
|
||||
; BIT (BIT 7) IS COMPLEMENTED. THIS ALLOWS DIRECT COMPARISON
|
||||
; OF EXPONENTS FOR SIZE SINCE THEY ARE STORED IN INCREASING
|
||||
; NUMERICAL SEQUENCE RANGING FROM $00 (-128) TO $FF (+127)
|
||||
; ($ MEANS NUMBER IS HEXADECIMAL).
|
||||
;
|
||||
; REPRESENTATION OF DECIMAL NUMBERS: THE PRESENT FLOATING
|
||||
; POINT REPRESENTATION ALLOWS DECIMAL NUMBERS IN THE APPROXIMATE
|
||||
; RANGE OF 10**(-38) THROUGH 10**(38) WITH 6 TO 7 SIGNIFICANT
|
||||
; DIGITS.
|
||||
;
|
||||
;
|
||||
|
||||
.include "wozfp.inc"
|
||||
|
||||
; .org $1D00 ; STARTING LOCATION FOR LOG
|
||||
; .export WOZFP
|
||||
;WOZFP:
|
||||
;
|
||||
;
|
||||
; NATURAL LOG OF MANT/EXP1 WITH RESULT IN MANT/EXP1
|
||||
;
|
||||
LOG: LDA M1
|
||||
BEQ ERROR
|
||||
BPL CONT ; IF ARG>0 OK
|
||||
ERROR: BRK ; ERROR ARG<=0
|
||||
;
|
||||
CONT: JSR SWAP ; MOVE ARG TO EXP/MANT2
|
||||
LDX #0 ; LOAD X FOR HIGH BYTE OF EXPONENT
|
||||
LDA X2 ; HOLD EXPONENT
|
||||
LDY #$80
|
||||
STY X2 ; SET EXPONENT 2 TO 0 ($80)
|
||||
EOR #$80 ; COMPLEMENT SIGN BIT OF ORIGINAL EXPONENT
|
||||
STA M1+1 ; SET EXPONENT INTO MANTISSA 1 FOR FLOAT
|
||||
BPL *+3 ; IS EXPONENT NEGATIVE
|
||||
DEX ; YES, SET X TO $FF
|
||||
STX M1 ; SET UPPER BYTE OF EXPONENT
|
||||
JSR FLOAT ; CONVERT TO FLOATING POINT
|
||||
LDX #3 ; 4 BYTE TRANSFERS
|
||||
SEXP1: LDA X2,X
|
||||
STA ZZ,X ; COPY MANTISSA TO Z
|
||||
LDA X1,X
|
||||
STA SEXP,X ; SAVE EXPONENT IN SEXP
|
||||
LDA R22,X ; LOAD EXP/MANT1 WITH SQRT(2)
|
||||
STA X1,X
|
||||
DEX
|
||||
BPL SEXP1
|
||||
JSR FSUB ; Z-SQRT(2)
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
SAVET: LDA X1,X ; SAVE EXP/MANT1 AS T
|
||||
STA T,X
|
||||
LDA ZZ,X ; LOAD EXP/MANT1 WITH Z
|
||||
STA X1,X
|
||||
LDA R22,X ; LOAD EXP/MANT2 WITH SQRT(2)
|
||||
STA X2,X
|
||||
DEX
|
||||
BPL SAVET
|
||||
JSR FADD ; Z+SQRT(2)
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
TM2: LDA T,X
|
||||
STA X2,X ; LOAD T INTO EXP/MANT2
|
||||
DEX
|
||||
BPL TM2
|
||||
JSR FDIV ; T=(Z-SQRT(2))/(Z+SQRT(2))
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
MIT: LDA X1,X
|
||||
STA T,X ; COPY EXP/MANT1 TO T AND
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH T
|
||||
DEX
|
||||
BPL MIT
|
||||
JSR FMUL ; T*T
|
||||
JSR SWAP ; MOVE T*T TO EXP/MANT2
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
MIC: LDA C,X
|
||||
STA X1,X ; LOAD EXP/MANT1 WITH C
|
||||
DEX
|
||||
BPL MIC
|
||||
JSR FSUB ; T*T-C
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
M2MB: LDA MB,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH MB
|
||||
DEX
|
||||
BPL M2MB
|
||||
JSR FDIV ; MB/(T*T-C)
|
||||
LDX #3
|
||||
M2A1: LDA A1,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH A1
|
||||
DEX
|
||||
BPL M2A1
|
||||
JSR FADD ; MB/(T*T-C)+A1
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
M2T: LDA T,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH T
|
||||
DEX
|
||||
BPL M2T
|
||||
JSR FMUL ; (MB/(T*T-C)+A1)*T
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
M2MHL: LDA MHLF,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH MHLF (.5)
|
||||
DEX
|
||||
BPL M2MHL
|
||||
JSR FADD ; +.5
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
LDEXP: LDA SEXP,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH ORIGINAL EXPONENT
|
||||
DEX
|
||||
BPL LDEXP
|
||||
JSR FADD ; +EXPN
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
MLE2: LDA LE2,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH LN(2)
|
||||
DEX
|
||||
BPL MLE2
|
||||
JSR FMUL ; *LN(2)
|
||||
RTS ; RETURN RESULT IN MANT/EXP1
|
||||
;
|
||||
; COMMON LOG OF MANT/EXP1 RESULT IN MANT/EXP1
|
||||
;
|
||||
LOG10: JSR LOG ; COMPUTE NATURAL LOG
|
||||
LDX #3
|
||||
L10: LDA LN10,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH 1/LN(10)
|
||||
DEX
|
||||
BPL L10
|
||||
JSR FMUL ; LOG10(X)=LN(X)/LN(10)
|
||||
RTS
|
||||
;
|
||||
LN10: .byte $7E, $6F, $2D, $ED ; 0.4342945
|
||||
|
||||
R22: .byte $80, $5A, $82, $7A ; 1.4142136 SQRT(2)
|
||||
|
||||
LE2: .byte $7F, $58, $B9, $0C ; 0.69314718 LOG BASE E OF 2
|
||||
|
||||
A1: .byte $80, $52, $B0, 40 ; 1.2920074
|
||||
|
||||
MB: .byte $81, $AB, $86, $49 ; -2.6398577
|
||||
|
||||
C: .byte $80, $6A, $08, $66 ; 1.6567626
|
||||
|
||||
MHLF: .byte $7F, $40, $00, $00 ; 0.5
|
||||
|
||||
;
|
||||
; .res $1e00-*
|
||||
; .org $1E00 ; STARTING LOCATION FOR EXP
|
||||
;
|
||||
; EXP OF MANT/EXP1 RESULT IN MANT/EXP1
|
||||
;
|
||||
EXP: LDX #3 ; 4 BYTE TRANSFER
|
||||
LDA L2E,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH LOG BASE 2 OF E
|
||||
DEX
|
||||
BPL EXP+2
|
||||
JSR FMUL ; LOG2(3)*X
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
FSA: LDA X1,X
|
||||
STA ZZ,X ; STORE EXP/MANT1 IN Z
|
||||
DEX
|
||||
BPL FSA ; SAVE Z=LN(2)*X
|
||||
JSR FIX ; CONVERT CONTENTS OF EXP/MANT1 TO AN INTEGER
|
||||
LDA M1+1
|
||||
STA INT ; SAVE RESULT AS INT
|
||||
SEC ; SET CARRY FOR SUBTRACTION
|
||||
SBC #124 ; INT-124
|
||||
LDA M1
|
||||
SBC #0
|
||||
BPL OVFLW ; OVERFLOW INT>=124
|
||||
CLC ; CLEAR CARRY FOR ADD
|
||||
LDA M1+1
|
||||
ADC #120 ; ADD 120 TO INT
|
||||
LDA M1
|
||||
ADC #0
|
||||
BPL CONTIN ; IF RESULT POSITIVE CONTINUE
|
||||
LDA #0 ; INT<-120 SET RESULT TO ZERO AND RETURN
|
||||
LDX #3 ; 4 BYTE MOVE
|
||||
ZERO: STA X1,X ; SET EXP/MANT1 TO ZERO
|
||||
DEX
|
||||
BPL ZERO
|
||||
RTS ; RETURN
|
||||
;
|
||||
OVFLW: BRK ; OVERFLOW
|
||||
;
|
||||
CONTIN: JSR FLOAT ; FLOAT INT
|
||||
LDX #3
|
||||
ENTD: LDA ZZ,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH Z
|
||||
DEX
|
||||
BPL ENTD
|
||||
JSR FSUB ; Z*Z-FLOAT(INT)
|
||||
LDX #3 ; 4 BYTE MOVE
|
||||
ZSAV: LDA X1,X
|
||||
STA ZZ,X ; SAVE EXP/MANT1 IN Z
|
||||
STA X2,X ; COPY EXP/MANT1 TO EXP/MANT2
|
||||
DEX
|
||||
BPL ZSAV
|
||||
JSR FMUL ; Z*Z
|
||||
LDX #3 ; 4 BYTE MOVE
|
||||
LA2: LDA A2,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH A2
|
||||
LDA X1,X
|
||||
STA SEXP,X ; SAVE EXP/MANT1 AS SEXP
|
||||
DEX
|
||||
BPL LA2
|
||||
JSR FADD ; Z*Z+A2
|
||||
LDX #3 ; 4 BYTE MOVE
|
||||
LB2: LDA B2,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH B2
|
||||
DEX
|
||||
BPL LB2
|
||||
JSR FDIV ; T=B/(Z*Z+A2)
|
||||
LDX #3 ; 4 BYTE MOVE
|
||||
DLOAD: LDA X1,X
|
||||
STA T,X ; SAVE EXP/MANT1 AS T
|
||||
LDA C2,X
|
||||
STA X1,X ; LOAD EXP/MANT1 WITH C2
|
||||
LDA SEXP,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH SEXP
|
||||
DEX
|
||||
BPL DLOAD
|
||||
JSR FMUL ; Z*Z*C2
|
||||
JSR SWAP ; MOVE EXP/MANT1 TO EXP/MANT2
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
LTMP: LDA T,X
|
||||
STA X1,X ; LOAD EXP/MANT1 WITH T
|
||||
DEX
|
||||
BPL LTMP
|
||||
JSR FSUB ; C2*Z*Z-B2/(Z*Z+A2)
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
LDD: LDA D,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH D
|
||||
DEX
|
||||
BPL LDD
|
||||
JSR FADD ; D+C2*Z*Z-B2/(Z*Z+A2)
|
||||
JSR SWAP ; MOVE EXP/MANT1 TO EXP/MANT2
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
LFA: LDA ZZ,X
|
||||
STA X1,X ; LOAD EXP/MANT1 WITH Z
|
||||
DEX
|
||||
BPL LFA
|
||||
JSR FSUB ; -Z+D+C2*Z*Z-B2/(Z*Z+A2)
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
LF3: LDA ZZ,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH Z
|
||||
DEX
|
||||
BPL LF3
|
||||
JSR FDIV ; Z/(**** )
|
||||
LDX #3 ; 4 BYTE TRANSFER
|
||||
LD12: LDA MHLF,X
|
||||
STA X2,X ; LOAD EXP/MANT2 WITH .5
|
||||
DEX
|
||||
BPL LD12
|
||||
JSR FADD ; +Z/(***)+.5
|
||||
SEC ; ADD INT TO EXPONENT WITH CARRY SET
|
||||
LDA INT ; TO MULTIPLY BY
|
||||
ADC X1 ; 2**(INT+1)
|
||||
STA X1 ; RETURN RESULT TO EXPONENT
|
||||
RTS ; RETURN ANS=(.5+Z/(-Z+D+C2*Z*Z-B2/(Z*Z+A2))*2**(INT+1)
|
||||
L2E: .byte $80, $5C, $55, $1E ; 1.4426950409 LOG BASE 2 OF E
|
||||
|
||||
A2: .byte $86, $57, $6A, $E1 ; 87.417497202
|
||||
|
||||
B2: .byte $89, $4D, $3F, $1D ; 617.9722695
|
||||
|
||||
C2: .byte $7B, $46, $FA, $70 ; .03465735903
|
||||
|
||||
D: .byte $83, $4F, $A3, $03 ; 9.9545957821
|
||||
|
||||
;
|
||||
;
|
||||
; BASIC FLOATING POINT ROUTINES
|
||||
;
|
||||
; .res $1F00-*
|
||||
; .org $1F00 ; START OF BASIC FLOATING POINT ROUTINES
|
||||
ADD: CLC ; CLEAR CARRY
|
||||
LDX #$02 ; INDEX FOR 3-BYTE ADD
|
||||
ADD1: LDA M1,X
|
||||
ADC M2,X ; ADD A BYTE OF MANT2 TO MANT1
|
||||
STA M1,X
|
||||
DEX ; ADVANCE INDEX TO NEXT MORE SIGNIF.BYTE
|
||||
BPL ADD1 ; LOOP UNTIL DONE.
|
||||
RTS ; RETURN
|
||||
MD1: ASL SIGN ; CLEAR LSB OF SIGN
|
||||
JSR ABSWAP ; ABS VAL OF MANT1, THEN SWAP MANT2
|
||||
ABSWAP: BIT M1 ; MANT1 NEG?
|
||||
BPL ABSWP1 ; NO,SWAP WITH MANT2 AND RETURN
|
||||
JSR FCOMPL ; YES, COMPLEMENT IT.
|
||||
INC SIGN ; INCR SIGN, COMPLEMENTING LSB
|
||||
ABSWP1: SEC ; SET CARRY FOR RETURN TO MUL/DIV
|
||||
;
|
||||
; SWAP EXP/MANT1 WITH EXP/MANT2
|
||||
;
|
||||
SWAP: LDX #$04 ; INDEX FOR 4-BYTE SWAP.
|
||||
SWAP1: STY E-1,X
|
||||
LDA X1-1,X ; SWAP A BYTE OF EXP/MANT1 WITH
|
||||
LDY X2-1,X ; EXP/MANT2 AND LEAVEA COPY OF
|
||||
STY X1-1,X ; MANT1 IN E(3BYTES). E+3 USED.
|
||||
STA X2-1,X
|
||||
DEX ; ADVANCE INDEX TO NEXT BYTE
|
||||
BNE SWAP1 ; LOOP UNTIL DONE.
|
||||
RTS
|
||||
;
|
||||
;
|
||||
;
|
||||
; CONVERT 16 BIT INTEGER IN M1(HIGH) AND M1+1(LOW) TO F.P.
|
||||
; RESULT IN EXP/MANT1. EXP/MANT2 UNEFFECTED
|
||||
;
|
||||
;
|
||||
FLOAT: LDA #$8E
|
||||
STA X1 ; SET EXPN TO 14 DEC
|
||||
LDA #0 ; CLEAR LOW ORDER BYTE
|
||||
STA M1+2
|
||||
BEQ NORML ; NORMALIZE RESULT
|
||||
NORM1: DEC X1 ; DECREMENT EXP1
|
||||
ASL M1+2
|
||||
ROL M1+1 ; SHIFT MANT1 (3 BYTES) LEFT
|
||||
ROL M1
|
||||
NORML: LDA M1 ; HIGH ORDER MANT1 BYTE
|
||||
ASL ; UPPER TWO BITS UNEQUAL?
|
||||
EOR M1
|
||||
BMI RTS1 ; YES,RETURN WITH MANT1 NORMALIZED
|
||||
LDA X1 ; EXP1 ZERO?
|
||||
BNE NORM1 ; NO, CONTINUE NORMALIZING
|
||||
RTS1: RTS ; RETURN
|
||||
;
|
||||
;
|
||||
; EXP/MANT2-EXP/MANT1 RESULT IN EXP/MANT1
|
||||
;
|
||||
FSUB: JSR FCOMPL ; CMPL MANT1 CLEARS CARRY UNLESS ZERO
|
||||
SWPALG: JSR ALGNSW ; RIGHT SHIFT MANT1 OR SWAP WITH MANT2 ON CARRY
|
||||
;
|
||||
; ADD EXP/MANT1 AND EXP/MANT2 RESULT IN EXP/MANT1
|
||||
;
|
||||
FADD: LDA X2
|
||||
CMP X1 ; COMPARE EXP1 WITH EXP2
|
||||
BNE SWPALG ; IF UNEQUAL, SWAP ADDENDS OR ALIGN MANTISSAS
|
||||
JSR ADD ; ADD ALIGNED MANTISSAS
|
||||
ADDEND: BVC NORML ; NO OVERFLOW, NORMALIZE RESULTS
|
||||
BVS RTLOG ; OV: SHIFT MANT1 RIGHT. NOTE CARRY IS CORRECT SIGN
|
||||
ALGNSW: BCC SWAP ; SWAP IF CARRY CLEAR, ELSE SHIFT RIGHT ARITH.
|
||||
RTAR: LDA M1 ; SIGN OF MANT1 INTO CARRY FOR
|
||||
ASL ; RIGHT ARITH SHIFT
|
||||
RTLOG: INC X1 ; INCR EXP1 TO COMPENSATE FOR RT SHIFT
|
||||
BEQ OVFL ; EXP1 OUT OF RANGE.
|
||||
RTLOG1: LDX #$FA ; INDEX FOR 6 BYTE RIGHT SHIFT
|
||||
ROR1: LDA #$80
|
||||
BCS ROR2
|
||||
ASL
|
||||
ROR2: LSR E+3,X ; SIMULATE ROR E+3,X
|
||||
ORA E+3,X
|
||||
STA E+3,X
|
||||
INX ; NEXT BYTE OF SHIFT
|
||||
BNE ROR1 ; LOOP UNTIL DONE
|
||||
RTS ; RETURN
|
||||
;
|
||||
;
|
||||
; EXP/MANT1 X EXP/MANT2 RESULT IN EXP/MANT1
|
||||
;
|
||||
FMUL: JSR MD1 ; ABS. VAL OF MANT1, MANT2
|
||||
ADC X1 ; ADD EXP1 TO EXP2 FOR PRODUCT EXPONENT
|
||||
JSR MD2 ; CHECK PRODUCT EXP AND PREPARE FOR MUL
|
||||
CLC ; CLEAR CARRY
|
||||
MUL1: JSR RTLOG1 ; MANT1 AND E RIGHT.(PRODUCT AND MPLIER)
|
||||
BCC MUL2 ; IF CARRY CLEAR, SKIP PARTIAL PRODUCT
|
||||
JSR ADD ; ADD MULTIPLICAN TO PRODUCT
|
||||
MUL2: DEY ; NEXT MUL ITERATION
|
||||
BPL MUL1 ; LOOP UNTIL DONE
|
||||
MDEND: LSR SIGN ; TEST SIGN (EVEN/ODD)
|
||||
NORMX: BCC NORML ; IF EXEN, NORMALIZE PRODUCT, ELSE COMPLEMENT
|
||||
FCOMPL: SEC ; SET CARRY FOR SUBTRACT
|
||||
LDX #$03 ; INDEX FOR 3 BYTE SUBTRACTION
|
||||
COMPL1: LDA #$00 ; CLEAR A
|
||||
SBC X1,X ; SUBTRACT BYTE OF EXP1
|
||||
STA X1,X ; RESTORE IT
|
||||
DEX ; NEXT MORE SIGNIFICANT BYTE
|
||||
BNE COMPL1 ; LOOP UNTIL DONE
|
||||
BEQ ADDEND ; NORMALIZE (OR SHIFT RIGHT IF OVERFLOW)
|
||||
;
|
||||
;
|
||||
; EXP/MANT2 / EXP/MANT1 RESULT IN EXP/MANT1
|
||||
;
|
||||
FDIV: JSR MD1 ; TAKE ABS VAL OF MANT1, MANT2
|
||||
SBC X1 ; SUBTRACT EXP1 FROM EXP2
|
||||
JSR MD2 ; SAVE AS QUOTIENT EXP
|
||||
DIV1: SEC ; SET CARRY FOR SUBTRACT
|
||||
LDX #$02 ; INDEX FOR 3-BYTE INSTRUCTION
|
||||
DIV2: LDA M2,X
|
||||
SBC E,X ; SUBTRACT A BYTE OF E FROM MANT2
|
||||
PHA ; SAVE ON STACK
|
||||
DEX ; NEXT MORE SIGNIF BYTE
|
||||
BPL DIV2 ; LOOP UNTIL DONE
|
||||
LDX #$FD ; INDEX FOR 3-BYTE CONDITIONAL MOVE
|
||||
DIV3: PLA ; PULL A BYTE OF DIFFERENCE OFF STACK
|
||||
BCC DIV4 ; IF MANT2<E THEN DONT RESTORE MANT2
|
||||
STA M2+3,X
|
||||
DIV4: INX ; NEXT LESS SIGNIF BYTE
|
||||
BNE DIV3 ; LOOP UNTIL DONE
|
||||
ROL M1+2
|
||||
ROL M1+1 ; ROLL QUOTIENT LEFT, CARRY INTO LSB
|
||||
ROL M1
|
||||
ASL M2+2
|
||||
ROL M2+1 ; SHIFT DIVIDEND LEFT
|
||||
ROL M2
|
||||
BCS OVFL ; OVERFLOW IS DUE TO UNNORMALIZED DIVISOR
|
||||
DEY ; NEXT DIVIDE ITERATION
|
||||
BNE DIV1 ; LOOP UNTIL DONE 23 ITERATIONS
|
||||
BEQ MDEND ; NORMALIZE QUOTIENT AND CORRECT SIGN
|
||||
MD2: STX M1+2
|
||||
STX M1+1 ; CLR MANT1 (3 BYTES) FOR MUL/DIV
|
||||
STX M1
|
||||
BCS OVCHK ; IF EXP CALC SET CARRY, CHECK FOR OVFL
|
||||
BMI MD3 ; IF NEG NO UNDERFLOW
|
||||
PLA ; POP ONE
|
||||
PLA ; RETURN LEVEL
|
||||
BCC NORMX ; CLEAR X1 AND RETURN
|
||||
MD3: EOR #$80 ; COMPLEMENT SIGN BIT OF EXP
|
||||
STA X1 ; STORE IT
|
||||
LDY #$17 ; COUNT FOR 24 MUL OR 23 DIV ITERATIONS
|
||||
RTS ; RETURN
|
||||
OVCHK: BPL MD3 ; IF POS EXP THEN NO OVERFLOW
|
||||
OVFL: BRK
|
||||
;
|
||||
;
|
||||
; CONVERT EXP/MANT1 TO INTEGER IN M1 (HIGH) AND M1+1(LOW)
|
||||
; EXP/MANT2 UNEFFECTED
|
||||
;
|
||||
JSR RTAR ; SHIFT MANT1 RT AND INCREMENT EXPNT
|
||||
FIX: LDA X1 ; CHECK EXPONENT
|
||||
CMP #$8E ; IS EXPONENT 14?
|
||||
BNE FIX-3 ; NO, SHIFT
|
||||
RTRN: RTS ; RETURN
|
||||
|
||||
; .include "util.s"
|
Loading…
x
Reference in New Issue
Block a user