mirror of
https://github.com/cc65/cc65.git
synced 2024-06-17 00:29:31 +00:00
Merge e3dd2e6523
into b1e1c13d4b
This commit is contained in:
commit
9c03dc621e
54
include/_float.h
Normal file
54
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_ */
|
||||
|
58
include/math.h
Normal file
58
include/math.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
#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 */
|
||||
|
||||
/* double round(double x); */ /* C99 */
|
||||
float __fastcall__ roundf(float x); /* C99 */
|
||||
|
||||
/* double trunc(double x); */ /* C99 */
|
||||
float __fastcall__ truncf(float x); /* C99 */
|
||||
|
||||
/* double ceil(double x) */
|
||||
float __fastcall__ ceilf(float x); /* C99 */
|
||||
|
||||
/* double fmod(double x, double y); */
|
||||
float __fastcall__ fmodf(float x, float y);
|
||||
|
||||
/* double floor(double x); */
|
||||
float __fastcall__ floorf(float x);
|
||||
|
||||
/* beware, this is not standard */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
/* FIXME */
|
||||
float __fastcall__ _fatan2(float x, float y);
|
||||
|
||||
#endif /* _MATH_H_ */
|
||||
|
|
@ -177,8 +177,12 @@ endif
|
|||
|
||||
SRCDIRS = $(SRCDIR)
|
||||
|
||||
SRCDIRS += float/softfloat \
|
||||
float/softmath
|
||||
|
||||
ifeq ($(TARGET),$(filter $(TARGET),$(CBMS)))
|
||||
SRCDIRS += cbm
|
||||
SRCDIRS += float/cbmkernal
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),$(filter $(TARGET),$(GEOS)))
|
||||
|
|
70
libsrc/c64/extra/fp754kernal.s
Normal file
70
libsrc/c64/extra/fp754kernal.s
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
; import/overload stubs for the C64 kernal floating point implementation
|
||||
|
||||
.import ___cbmkernal_afloat
|
||||
.import ___cbmkernal_aufloat
|
||||
.import ___cbmkernal_axfloat
|
||||
.import ___cbmkernal_axufloat
|
||||
.import ___cbmkernal_eaxfloat
|
||||
.import ___cbmkernal_eaxufloat
|
||||
.import ___cbmkernal_feaxint
|
||||
.import ___cbmkernal_feaxlong
|
||||
.import ___cbmkernal_fbnegeax
|
||||
.import ___cbmkernal_fnegeax
|
||||
.import ___cbmkernal_ftosaddeax
|
||||
.import ___cbmkernal_ftossubeax
|
||||
.import ___cbmkernal_ftosrsubeax
|
||||
.import ___cbmkernal_ftosdiveax
|
||||
.import ___cbmkernal_ftosmuleax
|
||||
.import ___cbmkernal_ftoseqeax
|
||||
.import ___cbmkernal_ftosneeax
|
||||
.import ___cbmkernal_ftosgteax
|
||||
.import ___cbmkernal_ftoslteax
|
||||
.import ___cbmkernal_ftosgeeax
|
||||
.import ___cbmkernal_ftosleeax
|
||||
|
||||
.export afloat := ___cbmkernal_afloat
|
||||
.export aufloat := ___cbmkernal_aufloat
|
||||
.export axfloat := ___cbmkernal_axfloat
|
||||
.export axufloat := ___cbmkernal_axufloat
|
||||
.export eaxfloat := ___cbmkernal_eaxfloat
|
||||
.export eaxufloat := ___cbmkernal_eaxufloat
|
||||
.export feaxint := ___cbmkernal_feaxint
|
||||
.export feaxlong := ___cbmkernal_feaxlong
|
||||
.export fbnegeax := ___cbmkernal_fbnegeax
|
||||
.export fnegeax := ___cbmkernal_fnegeax
|
||||
.export ftosaddeax := ___cbmkernal_ftosaddeax
|
||||
.export ftossubeax := ___cbmkernal_ftossubeax
|
||||
.export ftosrsubeax := ___cbmkernal_ftosrsubeax
|
||||
.export ftosdiveax := ___cbmkernal_ftosdiveax
|
||||
.export ftosmuleax := ___cbmkernal_ftosmuleax
|
||||
.export ftoseqeax := ___cbmkernal_ftoseqeax
|
||||
.export ftosneeax := ___cbmkernal_ftosneeax
|
||||
.export ftosgteax := ___cbmkernal_ftosgteax
|
||||
.export ftoslteax := ___cbmkernal_ftoslteax
|
||||
.export ftosgeeax := ___cbmkernal_ftosgeeax
|
||||
.export ftosleeax := ___cbmkernal_ftosleeax
|
||||
|
||||
.import ___cbmkernal_powf
|
||||
.import ___cbmkernal_sinf
|
||||
.import ___cbmkernal_cosf
|
||||
.import ___cbmkernal_logf
|
||||
.import ___cbmkernal_expf
|
||||
.import ___cbmkernal_sqrtf
|
||||
.import ___cbmkernal_tanf
|
||||
.import ___cbmkernal_atanf
|
||||
.import ___cbmkernal_fabsf
|
||||
.import ___cbmkernal_roundf
|
||||
.import ___cbmkernal_truncf
|
||||
|
||||
.export _powf := ___cbmkernal_powf
|
||||
.export _sinf := ___cbmkernal_sinf
|
||||
.export _cosf := ___cbmkernal_cosf
|
||||
.export _logf := ___cbmkernal_logf
|
||||
.export _expf := ___cbmkernal_expf
|
||||
.export _sqrtf := ___cbmkernal_sqrtf
|
||||
.export _tanf := ___cbmkernal_tanf
|
||||
.export _atanf := ___cbmkernal_atanf
|
||||
.export _fabsf := ___cbmkernal_fabsf
|
||||
.export _roundf := ___cbmkernal_roundf
|
||||
.export _truncf := ___cbmkernal_truncf
|
63
libsrc/float/cbmkernal/cbmfp-vic20.inc
Normal file
63
libsrc/float/cbmkernal/cbmfp-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)
|
446
libsrc/float/cbmkernal/cbmfp-wrapper.s
Normal file
446
libsrc/float/cbmkernal/cbmfp-wrapper.s
Normal file
|
@ -0,0 +1,446 @@
|
|||
|
||||
.import __ctof
|
||||
.import __utof
|
||||
.import __itof
|
||||
.import __stof
|
||||
|
||||
; 8bit signed -> float
|
||||
.export ___cbmkernal_afloat
|
||||
___cbmkernal_afloat:
|
||||
jmp __ctof
|
||||
|
||||
; 8bit unsigned -> float
|
||||
.export ___cbmkernal_aufloat
|
||||
___cbmkernal_aufloat:
|
||||
jmp __utof
|
||||
|
||||
; 16bit signed -> float
|
||||
.export ___cbmkernal_axfloat
|
||||
___cbmkernal_axfloat:
|
||||
jmp __itof
|
||||
|
||||
; 16bit unsigned -> float
|
||||
.export ___cbmkernal_axufloat
|
||||
___cbmkernal_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 ___cbmkernal_eaxfloat
|
||||
___cbmkernal_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 ___cbmkernal_eaxufloat
|
||||
___cbmkernal_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 ___cbmkernal_feaxint
|
||||
___cbmkernal_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 ___cbmkernal_feaxlong
|
||||
___cbmkernal_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 ___cbmkernal_fbnegeax
|
||||
.import bnegax
|
||||
___cbmkernal_fbnegeax:
|
||||
; FIXME: why does this not work with __fnot?
|
||||
jsr __ftoi
|
||||
jmp bnegax
|
||||
|
||||
.export ___cbmkernal_fnegeax
|
||||
___cbmkernal_fnegeax:
|
||||
jmp __fneg
|
||||
|
||||
;--------------------------------------------------------------
|
||||
; math ops
|
||||
|
||||
.import __fadd
|
||||
.import __fsub
|
||||
.import __fdiv
|
||||
.import __fmul
|
||||
|
||||
; Primary = TOS + Primary (like tosaddeax)
|
||||
.export ___cbmkernal_ftosaddeax
|
||||
___cbmkernal_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 ___cbmkernal_ftossubeax
|
||||
___cbmkernal_ftossubeax:
|
||||
jmp __fsub
|
||||
.export ___cbmkernal_ftosdiveax
|
||||
___cbmkernal_ftosdiveax:
|
||||
jmp __fdiv
|
||||
.export ___cbmkernal_ftosmuleax
|
||||
___cbmkernal_ftosmuleax:
|
||||
jmp __fmul
|
||||
|
||||
.import __frsub
|
||||
; Primary = Primary - TOS
|
||||
.export ___cbmkernal_ftosrsubeax
|
||||
___cbmkernal_ftosrsubeax:
|
||||
jmp __frsub
|
||||
|
||||
;--------------------------------------------------------------
|
||||
|
||||
.import __fcmp
|
||||
|
||||
; test for equal
|
||||
.export ___cbmkernal_ftoseqeax
|
||||
___cbmkernal_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 ___cbmkernal_ftosneeax
|
||||
___cbmkernal_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 ___cbmkernal_ftosgteax
|
||||
___cbmkernal_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 ___cbmkernal_ftoslteax
|
||||
___cbmkernal_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 ___cbmkernal_ftosgeeax
|
||||
___cbmkernal_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 ___cbmkernal_ftosleeax
|
||||
___cbmkernal_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
|
||||
.import __fround
|
||||
.import __fint
|
||||
|
||||
.export ___cbmkernal_powf
|
||||
___cbmkernal_powf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp __fpow
|
||||
|
||||
.export ___cbmkernal_sinf
|
||||
___cbmkernal_sinf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fsin
|
||||
|
||||
.export ___cbmkernal_cosf
|
||||
___cbmkernal_cosf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fcos
|
||||
|
||||
.export ___cbmkernal_logf
|
||||
___cbmkernal_logf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __flog
|
||||
|
||||
.export ___cbmkernal_expf
|
||||
___cbmkernal_expf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fexp
|
||||
|
||||
.export ___cbmkernal_sqrtf
|
||||
___cbmkernal_sqrtf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fsqr
|
||||
|
||||
.export ___cbmkernal_tanf
|
||||
___cbmkernal_tanf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __ftan
|
||||
|
||||
.export ___cbmkernal_atanf
|
||||
___cbmkernal_atanf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fatn
|
||||
|
||||
.export ___cbmkernal_fabsf
|
||||
___cbmkernal_fabsf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fabs
|
||||
|
||||
; roundf rounds to the "nearest integer", "away from zero". that means
|
||||
; For example, round(0.5) is 1.0, and round(-0.5) is -1.0.
|
||||
.export ___cbmkernal_roundf
|
||||
___cbmkernal_roundf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; jmp __fround
|
||||
|
||||
; primary = primary + 0.5
|
||||
jsr pusheax ; push eax to stack
|
||||
|
||||
; ldy #$00
|
||||
; sty sreg
|
||||
; lda #$00
|
||||
; sta sreg
|
||||
; ldx #0
|
||||
|
||||
bit sreg+1
|
||||
bpl @plus
|
||||
|
||||
; $3effffff
|
||||
lda #$3e
|
||||
sta sreg+1
|
||||
ldx #$ff
|
||||
txa
|
||||
sta sreg
|
||||
|
||||
jsr __fadd
|
||||
jmp __fint
|
||||
@plus:
|
||||
|
||||
; $3fffffff
|
||||
lda #$3f
|
||||
sta sreg+1
|
||||
ldx #0
|
||||
txa
|
||||
sta sreg
|
||||
|
||||
jsr __fadd
|
||||
jmp __fint
|
||||
|
||||
.export ___cbmkernal_truncf
|
||||
___cbmkernal_truncf:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
jmp __fint
|
124
libsrc/float/cbmkernal/cbmfp.h
Normal file
124
libsrc/float/cbmkernal/cbmfp.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
|
||||
#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 above seems to match wozniacs format)
|
||||
|
||||
* 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); /* afloat */
|
||||
float __fastcall__ _utof(unsigned char v); /* aufloat */
|
||||
float __fastcall__ _itof(int v); /* axfloat */
|
||||
float __fastcall__ _stof(unsigned short v); /* axufloat */
|
||||
|
||||
int __fastcall__ _ftoi(float f); /* feaxint */
|
||||
|
||||
/* compare two floats, returns 0 if f = a, 1 if f < a, 255 if f > a */
|
||||
unsigned char __fastcall__ _fcmp(float f, float a); /* ftos..eax */
|
||||
|
||||
/* 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 */
|
||||
|
||||
float __fastcall__ _fint(float s); /* math.h truncf */ /* truncate decimal fraction */
|
||||
float __fastcall__ _fround(float s); /* math.h roundf */ /* rounding */
|
||||
|
||||
/* 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); /* random number */
|
||||
float __fastcall__ _fsgn(float s); /* "signum" returns 1 if positive, 0 if 0, -1 if negative */
|
||||
|
||||
float __fastcall__ _fneg(float f); /* negate (flip sign) FIXME: fnegeax */
|
||||
|
||||
unsigned char __fastcall__ _ftestsgn(float f); /* FIXME */
|
||||
|
||||
#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
|
64
libsrc/float/cbmkernal/cbmfp.inc
Normal file
64
libsrc/float/cbmkernal/cbmfp.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 "signum" returns 1 if positive, 0 if 0, -1 if negative
|
||||
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)
|
||||
|
896
libsrc/float/cbmkernal/cbmfp.s
Normal file
896
libsrc/float/cbmkernal/cbmfp.s
Normal file
|
@ -0,0 +1,896 @@
|
|||
|
||||
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 "cbmfp-vic20.inc"
|
||||
.else
|
||||
.include "cbmfp.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
|
||||
|
||||
.import ldeaxysp
|
||||
|
||||
; 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
|
||||
.import incsp4
|
||||
|
||||
; 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
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
.if 1 = 1
|
||||
.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
|
||||
ldx #$00
|
||||
|
||||
; if next char is a minus, copy it
|
||||
lda $0100,x
|
||||
cmp #'-'
|
||||
bne @s0
|
||||
sta (ptr1),y
|
||||
iny
|
||||
inx
|
||||
@s0:
|
||||
|
||||
; if next char is a space, skip it
|
||||
lda $0100,x
|
||||
cmp #' '
|
||||
bne @s1
|
||||
inx
|
||||
@s1:
|
||||
|
||||
; if next char is a dot, copy a '0' to buffer
|
||||
lda $0100,x
|
||||
cmp #'.'
|
||||
bne @s2
|
||||
lda #'0'
|
||||
sta (ptr1),y
|
||||
iny
|
||||
@s2:
|
||||
; FIXME: we should handle the scientific notation somehow
|
||||
; FIXME: we should handle very small numbers somehow (display 0)
|
||||
@l:
|
||||
lda $0100,x
|
||||
sta (ptr1),y
|
||||
beq @s
|
||||
inx
|
||||
iny
|
||||
bne @l
|
||||
@s:
|
||||
lda ptr1
|
||||
ldx ptr1+1
|
||||
rts
|
||||
.endif
|
||||
.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 ; truncate fractions
|
||||
__flog: __ffunc1 BASIC_FAC_Log
|
||||
;__fpos: __ffunc1 BASIC_FAC_Pos
|
||||
__frnd: __ffunc1 BASIC_FAC_Rnd ; random numbers
|
||||
__fsgn: __ffunc1 BASIC_FAC_Sgn ;"signum" returns 1 if positive, 0 if 0, -1 if negative
|
||||
__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 ; rounding
|
||||
|
||||
;---------------------------------------------------------------------------------------------
|
||||
; 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
|
||||
|
||||
.macro __ffunc2c addr
|
||||
jsr ___float_float_to_fac_arg
|
||||
jsr __float_swap_fac_arg
|
||||
__enable_basic_if_needed
|
||||
lda FAC_EXPONENT
|
||||
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
|
||||
|
||||
.export __frsub
|
||||
__frsub: __ffunc2c BASIC_ARG_FAC_Sub
|
||||
|
||||
__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
|
||||
.import popax
|
||||
__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
|
||||
.import popax
|
||||
__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
|
||||
|
97
libsrc/float/ieee754/_ftostr.c
Normal file
97
libsrc/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
libsrc/float/ieee754/afloat.s
Normal file
7
libsrc/float/ieee754/afloat.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export afloat
|
||||
afloat:
|
||||
; FIXME
|
||||
rts
|
7
libsrc/float/ieee754/aufloat.s
Normal file
7
libsrc/float/ieee754/aufloat.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export aufloat
|
||||
aufloat:
|
||||
; FIXME
|
||||
rts
|
7
libsrc/float/ieee754/axfloat.s
Normal file
7
libsrc/float/ieee754/axfloat.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export axfloat
|
||||
axfloat:
|
||||
; FIXME
|
||||
rts
|
7
libsrc/float/ieee754/axufloat.s
Normal file
7
libsrc/float/ieee754/axufloat.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export axufloat
|
||||
axufloat:
|
||||
; FIXME
|
||||
rts
|
7
libsrc/float/ieee754/eaxfloat.s
Normal file
7
libsrc/float/ieee754/eaxfloat.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export eaxfloat
|
||||
eaxfloat:
|
||||
; FIXME
|
||||
rts
|
7
libsrc/float/ieee754/eaxufloat.s
Normal file
7
libsrc/float/ieee754/eaxufloat.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export eaxufloat
|
||||
eaxufloat:
|
||||
; FIXME
|
||||
rts
|
7
libsrc/float/ieee754/fbnegeax.s
Normal file
7
libsrc/float/ieee754/fbnegeax.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
.export fbnegeax
|
||||
fbnegeax:
|
||||
; FIXME
|
||||
rts
|
8
libsrc/float/ieee754/feaxint.s
Normal file
8
libsrc/float/ieee754/feaxint.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
; float -> 16bit int
|
||||
.export feaxint
|
||||
feaxint:
|
||||
; FIXME
|
||||
rts
|
8
libsrc/float/ieee754/feaxlong.s
Normal file
8
libsrc/float/ieee754/feaxlong.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
.include "ieee754.inc"
|
||||
|
||||
; float -> 32bit long
|
||||
.export feaxlong
|
||||
feaxlong:
|
||||
; FIXME
|
||||
rts
|
637
libsrc/float/ieee754/ftosaddeax.s
Normal file
637
libsrc/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
libsrc/float/ieee754/ftosdiveax.s
Normal file
12
libsrc/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
libsrc/float/ieee754/ftoseqeax.s
Normal file
8
libsrc/float/ieee754/ftoseqeax.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.include "ieee754.inc"
|
||||
|
||||
.export ftoseqeax
|
||||
ftoseqeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
libsrc/float/ieee754/ftosgeeax.s
Normal file
8
libsrc/float/ieee754/ftosgeeax.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.include "ieee754.inc"
|
||||
|
||||
.export ftosgeeax
|
||||
ftosgeeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
libsrc/float/ieee754/ftosgteax.s
Normal file
8
libsrc/float/ieee754/ftosgteax.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.include "ieee754.inc"
|
||||
|
||||
.export ftosgteax
|
||||
ftosgteax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
libsrc/float/ieee754/ftosleeax.s
Normal file
8
libsrc/float/ieee754/ftosleeax.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.include "ieee754.inc"
|
||||
|
||||
.export ftosleeax
|
||||
ftosleeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
8
libsrc/float/ieee754/ftoslteax.s
Normal file
8
libsrc/float/ieee754/ftoslteax.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.include "ieee754.inc"
|
||||
|
||||
.export ftoslteax
|
||||
ftoslteax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
12
libsrc/float/ieee754/ftosmuleax.s
Normal file
12
libsrc/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
libsrc/float/ieee754/ftosneeax.s
Normal file
8
libsrc/float/ieee754/ftosneeax.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.include "ieee754.inc"
|
||||
|
||||
.export ftosneeax
|
||||
ftosneeax:
|
||||
; FIXME
|
||||
lda #0
|
||||
tax
|
||||
rts
|
43
libsrc/float/ieee754/ftossubeax.s
Normal file
43
libsrc/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
libsrc/float/ieee754/ieee754.inc
Normal file
7
libsrc/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
|
324
libsrc/float/readme.md
Normal file
324
libsrc/float/readme.md
Normal file
|
@ -0,0 +1,324 @@
|
|||
|
||||
## cc65 floating point support
|
||||
|
||||
The current main 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. Don't bother. This is for
|
||||
people who want to help pushing the floating point support further.
|
||||
|
||||
You can however try the current state of development. You should be able to
|
||||
build small (and slow...) programs that use floats on any supported target.
|
||||
|
||||
- Build the compiler/toolchain/libs from this fptest branch.
|
||||
- Now you can build and run the samples and/or tests.
|
||||
```
|
||||
samples/floattest.c
|
||||
samples/mandelfloat.c
|
||||
samples/mathtest.c
|
||||
samples/tgisincos.c
|
||||
```
|
||||
full math.h is available for C64 when linking agains fp754kernal.o (see below)
|
||||
|
||||
### Further info
|
||||
|
||||
- Right now by default all targets will use the Berkeley Softfloat Library. This
|
||||
solves the annoying "chicken and egg" problem of having to implement the float
|
||||
support both in the compiler and in the target library at the same time, before
|
||||
anything can be tested properly. Fortunately that also means we can use the
|
||||
simulator for running test programs, and test changes in the compiler using
|
||||
our test bench, and that against a library that is known to somewhat work
|
||||
correctly :)
|
||||
- The default library also contains a collection of math functions (which i
|
||||
dubbed "softmath"), which may fill the gap until more targets have specific
|
||||
wrappers and/or a generic math library (in assembly) was written.
|
||||
- The default library can be overridden by linking an override file, similar to
|
||||
how you can use the soft80 implementation for conio. Right now such override
|
||||
files are provided for the C64 (c64-fp754kernal.o) and VIC20
|
||||
(vic20-fp754kernal.o). The samples will automatically use the overrides.
|
||||
|
||||
### WANTED
|
||||
|
||||
- For the time being, i will not look at writing IEEE754 functions in assembly.
|
||||
Please see below for more info on what is needed to do this, should you be
|
||||
interested in doing this. Please contact me before you are putting work into
|
||||
this, so we can discuss some things and prevent anyone wasting time :)
|
||||
|
||||
- It might be possible to produce a similar kernal- or OS- wrapper override file
|
||||
as the C64 one for other targets (or port the C64 one to other CBM targets).
|
||||
- If you create a new one, keep in mind that the compiler *right now* will
|
||||
currently work with IEEE754 floats, which your library calls must also work
|
||||
with (which will involve converting forth and back to whatever other format
|
||||
at runtime), and there is no easy way tp change that.
|
||||
|
||||
### Roadmap
|
||||
|
||||
- Test/Fix using the Softfloat lib some more, fix as much tests as possible
|
||||
- When all obvious tests have been created and work OK, we can merge
|
||||
- for the failing tests, create "negative" cases
|
||||
|
||||
After the merge, the following things can be done more or less independent from
|
||||
each other (not necessarily by me :)):
|
||||
|
||||
- implement IEEE754 library
|
||||
- for generic support this will be the best compromise for standard compliance
|
||||
and speed, but will take more RAM than alternatives.
|
||||
- Once implemented, it will work for all targets.
|
||||
|
||||
- implement support for native FP routines
|
||||
- Some targets have FP routines in ROM (or OS) that can be used instead of
|
||||
providing our own in the library. This may or may not save RAM, and may or
|
||||
may not be faster than the default library.
|
||||
- The wrapper library must implement conversion from/to 32bit IEEE754
|
||||
|
||||
- implement support for native FP formats
|
||||
- for this the wrappers in fp.c must be used in the compiler at all places.
|
||||
- also we must *implement* the native format on the host in fp.c
|
||||
- if the native format uses a different number of bytes than 4 for its native
|
||||
format, we must add support for this in the compiler at various places
|
||||
- last not least a wrapper library that uses the native format must be created
|
||||
- it is not unlikely that we will need extra tests for the native format
|
||||
|
||||
## The Compiler
|
||||
|
||||
NOT WORKING YET:
|
||||
|
||||
/test/val/float-basic-var-var.c +=, -=
|
||||
|
||||
/test/val/float-basic-var-intvar.c +=, -=
|
||||
/test/val/float-basic-var-intconst.c *, /, +=, -=, *=, /=
|
||||
|
||||
/test/val/float-basic-intvar-const.c +=, -=, *=, /=
|
||||
/test/val/float-basic-intvar-var.c +=, /=
|
||||
/test/val/float-basic-intconst-var.c *, /
|
||||
|
||||
/test/val/float-cmp-const-intvar.c
|
||||
/test/val/float-cmp-intvar-const.c
|
||||
/test/val/float-cmp-var-intvar.c
|
||||
|
||||
- float values written as "12.34f" work, but "12.34" does not - should it?
|
||||
|
||||
TODO:
|
||||
|
||||
- more tests are needed
|
||||
- warnings
|
||||
- errors
|
||||
- register variables
|
||||
- more/all tests should check local/global/register variables
|
||||
|
||||
### Files & Functions
|
||||
|
||||
#### assignment.c
|
||||
|
||||
src/cc65/assignment.c
|
||||
|
||||
```
|
||||
OpAssignArithmetic Parse an "=" or "op=" operation for arithmetic lhs
|
||||
OpAddSubAssign Parse a "+=" or "-=" operation
|
||||
```
|
||||
|
||||
#### codegen.c
|
||||
|
||||
src/cc65/codegen.c
|
||||
src/cc65/codegen.h
|
||||
|
||||
```
|
||||
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, g_asl
|
||||
```
|
||||
#### datatype.c
|
||||
|
||||
src/cc65/datatype.c
|
||||
|
||||
```
|
||||
ArithmeticConvert Perform the usual arithmetic conversions for binary operators.
|
||||
```
|
||||
|
||||
#### expr.c
|
||||
|
||||
src/cc65/expr.c
|
||||
|
||||
```
|
||||
LimitExprValue
|
||||
parseadd
|
||||
parsesub
|
||||
```
|
||||
|
||||
#### fp.c
|
||||
|
||||
src/common/fp.c (OK)
|
||||
src/common/fp.h (OK)
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
#### initdata.c
|
||||
|
||||
src/cc65/initdata.c
|
||||
|
||||
```
|
||||
DefineData Output a data definition for the given expression
|
||||
```
|
||||
|
||||
#### loadexpr.c
|
||||
|
||||
src/cc65/loadexpr.c
|
||||
|
||||
```
|
||||
LoadExpr Load an expression into the primary register if it is not already there.
|
||||
```
|
||||
|
||||
#### locals.c
|
||||
|
||||
src/cc65/locals.c (OK?)
|
||||
|
||||
```
|
||||
ParseAutoDecl Parse the declarator of an auto variable.
|
||||
```
|
||||
|
||||
#### scanner.c
|
||||
|
||||
src/cc65/scanner.c (OK?)
|
||||
|
||||
```
|
||||
NumericConst Parse a numeric constant
|
||||
```
|
||||
|
||||
Note: Scanner fixes should be directly promoted to upstream. Any differences in
|
||||
this branch should be related to debugging/logging.
|
||||
|
||||
#### typeconv.c
|
||||
|
||||
src/cc65/typeconv.c (OK?)
|
||||
|
||||
```
|
||||
DoConversion Emit code to convert the given expression to a new type
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## The Library
|
||||
|
||||
### variants
|
||||
|
||||
The floating point support calls library functions for any operations on non
|
||||
constant values.
|
||||
|
||||
#### softfloat
|
||||
|
||||
This is a Port of "Berkeley SoftFloat Release 2c". It is currently used by
|
||||
default for all targets.
|
||||
|
||||
#### softmath
|
||||
|
||||
Contains a collection of math functions, (hopefully) enough to completely
|
||||
implement math.h in C. This is currently used by default for all targets.
|
||||
|
||||
#### cbmkernal
|
||||
|
||||
This is a wrapper to the CBM kernal functions. This is fairly complete,
|
||||
including math functions. To use this, link against c64-fp754kernal.o. The c64
|
||||
samples will do this by default.
|
||||
|
||||
#### ieee754
|
||||
|
||||
This should become a freestanding IEEE754 library, which can completely replace
|
||||
the softfloat (and softmath) library.
|
||||
|
||||
- basically everything missing except addition/substraction
|
||||
- compare functions are missing
|
||||
- mul, div functions are missing
|
||||
- type conversion functions are missing
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
### runtime functions
|
||||
|
||||
These must be available in the runtime library.
|
||||
```
|
||||
func description softfloat cbmfp 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
|
||||
```
|
||||
### math.h functions
|
||||
|
||||
These are optional, required for standard libm.
|
||||
```
|
||||
func description softmath cbmfp 754
|
||||
|
||||
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) * * -
|
||||
float roundf(float x) * * -
|
||||
float truncf(float x) * * -
|
||||
float ceilf(float x) * - -
|
||||
float floorf(float x) * - -
|
||||
float fmodf(float x, float y) * - -
|
||||
```
|
||||
|
||||
### extra functions
|
||||
|
||||
Optional utility functions.
|
||||
```
|
||||
func description softfloat cbmfp 754
|
||||
|
||||
char *_ftostr(char *d, float s) * * ? for printf family
|
||||
float _strtof(char *d) - * - for scanf family
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- https://www.geeksforgeeks.org/ieee-standard-754-floating-point-numbers/
|
||||
- https://www.h-schmidt.net/FloatConverter/IEEE754.html
|
70
libsrc/float/softfloat/6502-CC65.h
Normal file
70
libsrc/float/softfloat/6502-CC65.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
#undef DOUBLES // implement double precision floats
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define LITTLEENDIAN
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The macro `BITS64' can be defined to indicate that 64-bit integer types are
|
||||
| supported by the compiler.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#undef BITS64
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Each of the following `typedef's defines the most convenient type that holds
|
||||
| integers of at least as many bits as specified. For example, `uint8' should
|
||||
| be the most convenient type that can hold unsigned integers of as many as
|
||||
| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most
|
||||
| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
|
||||
| to the same as `int'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef unsigned char flag;
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed short int16;
|
||||
typedef unsigned long uint32;
|
||||
typedef signed long int32;
|
||||
#ifdef BITS64
|
||||
typedef unsigned long long int uint64;
|
||||
typedef signed long long int int64;
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Each of the following `typedef's defines a type that holds integers
|
||||
| of _exactly_ the number of bits specified. For instance, for most
|
||||
| implementation of C, `bits16' and `sbits16' should be `typedef'ed to
|
||||
| `unsigned short int' and `signed short int' (or `short int'), respectively.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef unsigned char bits8;
|
||||
typedef signed char sbits8;
|
||||
typedef unsigned short bits16;
|
||||
typedef signed short sbits16;
|
||||
typedef unsigned long bits32;
|
||||
typedef signed long sbits32;
|
||||
#ifdef BITS64
|
||||
typedef unsigned long long int bits64;
|
||||
typedef signed long long int sbits64;
|
||||
#endif
|
||||
|
||||
#ifdef BITS64
|
||||
/*----------------------------------------------------------------------------
|
||||
| The `LIT64' macro takes as its argument a textual integer literal and
|
||||
| if necessary ``marks'' the literal as having a 64-bit integer type.
|
||||
| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
|
||||
| appended with the letters `LL' standing for `long long', which is `gcc's
|
||||
| name for the 64-bit integer type. Some compilers may allow `LIT64' to be
|
||||
| defined as the identity macro: `#define LIT64( a ) a'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define LIT64( a ) a##LL
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The macro `INLINE' can be used before functions that should be inlined. If
|
||||
| a compiler does not support explicit inlining, this macro should be defined
|
||||
| to be `static'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define INLINE static
|
||||
|
83
libsrc/float/softfloat/README.txt
Normal file
83
libsrc/float/softfloat/README.txt
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
Package Overview for Berkeley SoftFloat Release 2c
|
||||
|
||||
John R. Hauser
|
||||
2015 January 30
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Overview
|
||||
|
||||
Berkeley SoftFloat is a software implementation of binary floating-point
|
||||
that conforms to the IEEE Standard for Floating-Point Arithmetic.
|
||||
Release 2c updates an older version of SoftFloat that has for most purposes
|
||||
been supplanted by Release 3 or later. For the latest version of SoftFloat,
|
||||
see Web page `http://www.jhauser.us/arithmetic/SoftFloat.html'.
|
||||
|
||||
SoftFloat is distributed in the form of C source code. For Release 2c,
|
||||
compiling the SoftFloat sources generates two things:
|
||||
|
||||
-- A SoftFloat object file (typically `softfloat.o') containing the complete
|
||||
set of IEC/IEEE floating-point routines.
|
||||
|
||||
-- A `timesoftfloat' program for evaluating the speed of the SoftFloat
|
||||
routines. (The SoftFloat module is linked into this program.)
|
||||
|
||||
This version of the SoftFloat package is documented in four text files:
|
||||
|
||||
SoftFloat.txt Documentation for using the SoftFloat functions.
|
||||
SoftFloat-source.txt Documentation for compiling SoftFloat.
|
||||
SoftFloat-history.txt History of major changes to SoftFloat.
|
||||
timesoftfloat.txt Documentation for using `timesoftfloat'.
|
||||
|
||||
Other files in the package comprise the source code for SoftFloat.
|
||||
|
||||
Please be aware that some work is involved in porting this software to other
|
||||
targets. It is not just a matter of getting `make' to complete without
|
||||
error messages. You should not attempt to compile this release of SoftFloat
|
||||
without first reading both `SoftFloat.txt' and `SoftFloat-source.txt'.
|
||||
Depending on your needs, you may find that newer versions of SoftFloat are
|
||||
less work to port.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Legal Notice
|
||||
|
||||
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made
|
||||
possible in part by the International Computer Science Institute, located
|
||||
at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding
|
||||
was partially provided by the National Science Foundation under grant
|
||||
MIP-9311980. The original version of this code was written as part of a
|
||||
project to build a fixed-point vector processor in collaboration with the
|
||||
University of California at Berkeley, overseen by Profs. Nelson Morgan and
|
||||
John Wawrzynek.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN
|
||||
HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
|
||||
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
|
||||
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE,
|
||||
OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF
|
||||
THE SOFTWARE.
|
||||
|
||||
The following are expressly permitted, even for commercial purposes:
|
||||
(1) distribution of SoftFloat in whole or in part, as long as this and
|
||||
other legal notices remain and are prominent, and provided also that, for a
|
||||
partial distribution, prominent notice is given that it is a subset of the
|
||||
original; and
|
||||
(2) inclusion or use of SoftFloat in whole or in part in a derivative
|
||||
work, provided that the use restrictions above are met and the minimal
|
||||
documentation requirements stated in the source code are satisfied.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Contact Information
|
||||
|
||||
At the time of this writing, the most up-to-date information about SoftFloat
|
||||
and the latest release can be found at the Web page `http://www.jhauser.us/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
389
libsrc/float/softfloat/SoftFloat.txt
Normal file
389
libsrc/float/softfloat/SoftFloat.txt
Normal file
|
@ -0,0 +1,389 @@
|
|||
|
||||
Berkeley SoftFloat Release 2c General Documentation
|
||||
|
||||
John R. Hauser
|
||||
2015 January 30
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Introduction
|
||||
|
||||
Berkeley SoftFloat is a software implementation of binary floating-point
|
||||
that conforms to the IEEE Standard for Floating-Point Arithmetic. For
|
||||
Release 2c of SoftFloat, as many as four formats are supported: 32-bit
|
||||
single-precision, 64-bit double-precision, 80-bit double-extended-precision,
|
||||
and 128-bit quadruple-precision. All operations required by the older 1985
|
||||
version of the IEEE Standard are implemented, except for conversions to and
|
||||
from decimal.
|
||||
|
||||
This document gives information about the types defined and the routines
|
||||
implemented by this release of SoftFloat. It does not attempt to define or
|
||||
explain the IEEE Floating-Point Standard. Details about the standard are
|
||||
available elsewhere.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Limitations
|
||||
|
||||
SoftFloat is written in C and is designed to work with other C code. The
|
||||
SoftFloat header files assume an ISO/ANSI-style C compiler. No attempt
|
||||
has been made to accomodate compilers that are not ISO-conformant. In
|
||||
particular, the distributed header files will not be acceptable to any
|
||||
compiler that does not recognize function prototypes.
|
||||
|
||||
Support for the 80-bit double-extended-precision and 128-bit quadruple-
|
||||
precision formats depends on a C compiler that implements 64-bit integer
|
||||
arithmetic. If the largest integer format supported by the C compiler is
|
||||
32 bits, SoftFloat is limited to only 32-bit single-precision and 64-bit
|
||||
double-precision. When that is the case, all references in this document
|
||||
to 80-bit double-extended-precision, 128-bit quadruple-precision, and 64-bit
|
||||
integers should be ignored.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Contents
|
||||
|
||||
Introduction
|
||||
Limitations
|
||||
Contents
|
||||
Legal Notice
|
||||
Types and Functions
|
||||
Rounding Modes
|
||||
Double-Extended-Precision Rounding Precision
|
||||
Exceptions and Exception Flags
|
||||
Function Details
|
||||
Conversion Functions
|
||||
Basic Arithmetic Functions
|
||||
Remainder Functions
|
||||
Round-to-Integer Functions
|
||||
Comparison Functions
|
||||
Signaling NaN Test Functions
|
||||
Raise-Exception Function
|
||||
Contact Information
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Legal Notice
|
||||
|
||||
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made
|
||||
possible in part by the International Computer Science Institute, located
|
||||
at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding
|
||||
was partially provided by the National Science Foundation under grant
|
||||
MIP-9311980. The original version of this code was written as part of a
|
||||
project to build a fixed-point vector processor in collaboration with the
|
||||
University of California at Berkeley, overseen by Profs. Nelson Morgan and
|
||||
John Wawrzynek.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN
|
||||
HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
|
||||
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
|
||||
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE,
|
||||
OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF
|
||||
THE SOFTWARE.
|
||||
|
||||
The following are expressly permitted, even for commercial purposes:
|
||||
(1) distribution of SoftFloat in whole or in part, as long as this and
|
||||
other legal notices remain and are prominent, and provided also that, for a
|
||||
partial distribution, prominent notice is given that it is a subset of the
|
||||
original; and
|
||||
(2) inclusion or use of SoftFloat in whole or in part in a derivative
|
||||
work, provided that the use restrictions above are met and the minimal
|
||||
documentation requirements stated in the source code are satisfied.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Types and Functions
|
||||
|
||||
When 64-bit integers are supported by the compiler, the `softfloat.h' header
|
||||
file defines four types: `float32' (32-bit single-precision), `float64'
|
||||
(64-bit double-precision), `floatx80' (80-bit double-extended-precision),
|
||||
and `float128' (128-bit quadruple-precision). The `float32' and `float64'
|
||||
types are defined in terms of 32-bit and 64-bit integer types, respectively,
|
||||
while the `float128' type is defined as a structure of two 64-bit integers,
|
||||
taking into account the byte order of the particular machine being used.
|
||||
The `floatx80' type is defined as a structure containing one 16-bit and one
|
||||
64-bit integer, with the machine's byte order again determining the order
|
||||
within the structure.
|
||||
|
||||
When 64-bit integers are _not_ supported by the compiler, the `softfloat.h'
|
||||
header file defines only two types: `float32' and `float64'. Because
|
||||
the ISO/ANSI C Standard guarantees at least one built-in integer type of
|
||||
32 bits, the `float32' type is identified with an appropriate integer type.
|
||||
The `float64' type is defined as a structure of two 32-bit integers, with
|
||||
the machine's byte order determining the order of the fields.
|
||||
|
||||
In either case, the types in `softfloat.h' are defined such that if a system
|
||||
implements the usual C `float' and `double' types according to the IEEE
|
||||
Standard, then the `float32' and `float64' types should be indistinguishable
|
||||
in memory from the native `float' and `double' types. (On the other hand,
|
||||
when `float32' or `float64' values are placed in processor registers by
|
||||
the compiler, the type of registers used may differ from those used for the
|
||||
native `float' and `double' types.)
|
||||
|
||||
SoftFloat implements the following arithmetic operations:
|
||||
|
||||
-- Conversions among all the floating-point formats, and also between
|
||||
integers (32-bit and 64-bit) and any of the floating-point formats.
|
||||
|
||||
-- The usual add, subtract, multiply, divide, and square root operations for
|
||||
all floating-point formats.
|
||||
|
||||
-- For each format, the floating-point remainder operation defined by the
|
||||
IEEE Standard.
|
||||
|
||||
-- For each floating-point format, a "round to integer" operation that
|
||||
rounds to the nearest integer value in the same format. (The floating-
|
||||
point formats can hold integer values, of course.)
|
||||
|
||||
-- Comparisons between two values in the same floating-point format.
|
||||
|
||||
The only functions required by the 1985 IEEE Standard that are not provided
|
||||
are conversions to and from decimal.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Rounding Modes
|
||||
|
||||
All four rounding modes prescribed by the 1985 IEEE Standard are implemented
|
||||
for all operations that require rounding. The rounding mode is selected
|
||||
by the global variable `float_rounding_mode'. This variable may be set
|
||||
to one of the values `float_round_nearest_even', `float_round_to_zero',
|
||||
`float_round_down', or `float_round_up'. The rounding mode is initialized
|
||||
to nearest/even.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Double-Extended-Precision Rounding Precision
|
||||
|
||||
For 80-bit double-extended-precision (`floatx80') only, the rounding
|
||||
precision of the basic arithmetic operations is controlled by the global
|
||||
variable `floatx80_rounding_precision'. The operations affected are:
|
||||
|
||||
floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt
|
||||
|
||||
When `floatx80_rounding_precision' is set to its default value of 80,
|
||||
these operations are rounded (as usual) to the full precision of the 80-bit
|
||||
double-extended-precision format. Setting `floatx80_rounding_precision' to
|
||||
32 or to 64 causes the operations listed to be rounded to reduced precision
|
||||
equivalent to 32-bit single-precision (`float32') or to 64-bit double-
|
||||
precision (`float64'), respectively. When rounding to reduced precision,
|
||||
additional bits in the result significand beyond the rounding point are set
|
||||
to zero. The consequences of setting `floatx80_rounding_precision' to a
|
||||
value other than 32, 64, or 80 is not specified. Operations other than the
|
||||
ones listed above are not affected by `floatx80_rounding_precision'.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Exceptions and Exception Flags
|
||||
|
||||
All five exception flags required by the IEEE Standard are implemented.
|
||||
Each flag is stored as a separate bit in the global variable
|
||||
`float_exception_flags'. The positions of the exception flag bits within
|
||||
this variable are determined by the bit masks `float_flag_inexact',
|
||||
`float_flag_underflow', `float_flag_overflow', `float_flag_divbyzero', and
|
||||
`float_flag_invalid'. The exception flags variable is initialized to all 0,
|
||||
meaning no exceptions.
|
||||
|
||||
An individual exception flag can be cleared with the statement
|
||||
|
||||
float_exception_flags &= ~ float_flag_<exception>;
|
||||
|
||||
where `<exception>' is the appropriate name. To raise a floating-point
|
||||
exception, the SoftFloat function `float_raise' should be used (see below).
|
||||
|
||||
In the terminology of the IEEE Standard, SoftFloat can detect tininess
|
||||
for underflow either before or after rounding. The choice is made by
|
||||
the global variable `float_detect_tininess', which can be set to either
|
||||
`float_tininess_before_rounding' or `float_tininess_after_rounding'.
|
||||
Detecting tininess after rounding is better because it results in fewer
|
||||
spurious underflow signals. The other option is provided for compatibility
|
||||
with some systems. Like most systems, SoftFloat always detects loss of
|
||||
accuracy for underflow as an inexact result.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Function Details
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Conversion Functions
|
||||
|
||||
All conversions among the floating-point formats are supported, as are all
|
||||
conversions between a floating-point format and 32-bit and 64-bit signed
|
||||
integers. The complete set of conversion functions is:
|
||||
|
||||
int32_to_float32 int64_to_float32
|
||||
int32_to_float64 int64_to_float64
|
||||
int32_to_floatx80 int64_to_floatx80
|
||||
int32_to_float128 int64_to_float128
|
||||
|
||||
float32_to_int32 float32_to_int64
|
||||
float64_to_int32 float64_to_int64
|
||||
floatx80_to_int32 floatx80_to_int64
|
||||
float128_to_int32 float128_to_int64
|
||||
|
||||
float32_to_float64 float32_to_floatx80 float32_to_float128
|
||||
float64_to_float32 float64_to_floatx80 float64_to_float128
|
||||
floatx80_to_float32 floatx80_to_float64 floatx80_to_float128
|
||||
float128_to_float32 float128_to_float64 float128_to_floatx80
|
||||
|
||||
Each conversion function takes one operand of the appropriate type and
|
||||
returns one result. Conversions from a smaller to a larger floating-point
|
||||
format are always exact and so require no rounding. Conversions from 32-bit
|
||||
integers to 64-bit double-precision and larger formats are also exact, and
|
||||
likewise for conversions from 64-bit integers to 80-bit double-extended-
|
||||
precision and 128-bit quadruple-precision.
|
||||
|
||||
Conversions from floating-point to integer raise the invalid exception if
|
||||
the source value cannot be rounded to a representable integer of the desired
|
||||
size (32 or 64 bits). If the floating-point operand is a NaN, the largest
|
||||
positive integer is returned. Otherwise, if the conversion overflows, the
|
||||
largest integer with the same sign as the operand is returned.
|
||||
|
||||
On conversions to integer, if the floating-point operand is not already
|
||||
an integer value, the operand is rounded according to the current rounding
|
||||
mode as specified by `float_rounding_mode'. Because C (and perhaps other
|
||||
languages) require that conversions to integers be rounded toward zero, the
|
||||
following functions are provided for improved speed and convenience:
|
||||
|
||||
float32_to_int32_round_to_zero float32_to_int64_round_to_zero
|
||||
float64_to_int32_round_to_zero float64_to_int64_round_to_zero
|
||||
floatx80_to_int32_round_to_zero floatx80_to_int64_round_to_zero
|
||||
float128_to_int32_round_to_zero float128_to_int64_round_to_zero
|
||||
|
||||
These variant functions ignore `float_rounding_mode' and always round toward
|
||||
zero.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Basic Arithmetic Functions
|
||||
|
||||
The following basic arithmetic functions are provided:
|
||||
|
||||
float32_add float32_sub float32_mul float32_div float32_sqrt
|
||||
float64_add float64_sub float64_mul float64_div float64_sqrt
|
||||
floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt
|
||||
float128_add float128_sub float128_mul float128_div float128_sqrt
|
||||
|
||||
Each function takes two operands, except for `sqrt' which takes only one.
|
||||
The operands and result are all of the same type.
|
||||
|
||||
Rounding of the 80-bit double-extended-precision (`floatx80') functions is
|
||||
affected by the `floatx80_rounding_precision' variable, as explained above
|
||||
in the section _Double-Extended-Precision Rounding Precision_.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Remainder Functions
|
||||
|
||||
For each format, SoftFloat implements the remainder function according to
|
||||
the IEEE Standard. The remainder functions are:
|
||||
|
||||
float32_rem
|
||||
float64_rem
|
||||
floatx80_rem
|
||||
float128_rem
|
||||
|
||||
Each remainder function takes two operands. The operands and result are all
|
||||
of the same type. Given operands x and y, the remainder functions return
|
||||
the value x - n*y, where n is the integer closest to x/y. If x/y is exactly
|
||||
halfway between two integers, n is the even integer closest to x/y. The
|
||||
remainder functions are always exact and so require no rounding.
|
||||
|
||||
Depending on the relative magnitudes of the operands, the remainder
|
||||
functions can take considerably longer to execute than the other SoftFloat
|
||||
functions. This is inherent in the remainder operation itself and is not a
|
||||
flaw in the SoftFloat implementation.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Round-to-Integer Functions
|
||||
|
||||
For each format, SoftFloat implements the round-to-integer function
|
||||
specified by the IEEE Standard. The functions are:
|
||||
|
||||
float32_round_to_int
|
||||
float64_round_to_int
|
||||
floatx80_round_to_int
|
||||
float128_round_to_int
|
||||
|
||||
Each function takes a single floating-point operand and returns a result of
|
||||
the same type. (Note that the result is not an integer type.) The operand
|
||||
is rounded to an exact integer according to the current rounding mode, and
|
||||
the resulting integer value is returned in the same floating-point format.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Comparison Functions
|
||||
|
||||
The following floating-point comparison functions are provided:
|
||||
|
||||
float32_eq float32_le float32_lt
|
||||
float64_eq float64_le float64_lt
|
||||
floatx80_eq floatx80_le floatx80_lt
|
||||
float128_eq float128_le float128_lt
|
||||
|
||||
Each function takes two operands of the same type and returns a 1 or 0
|
||||
representing either _true_ or _false_. The abbreviation `eq' stands for
|
||||
"equal" (=); `le' stands for "less than or equal" (<=); and `lt' stands for
|
||||
"less than" (<).
|
||||
|
||||
The usual greater-than (>), greater-than-or-equal (>=), and not-equal (!=)
|
||||
functions are easily obtained using the functions provided. The not-equal
|
||||
function is just the logical complement of the equal function. The greater-
|
||||
than-or-equal function is identical to the less-than-or-equal function with
|
||||
the operands reversed, and the greater-than function is identical to the
|
||||
less-than function with the operands reversed.
|
||||
|
||||
The IEEE Standard specifies that the less-than-or-equal and less-than
|
||||
functions raise the invalid exception if either input is any kind of NaN.
|
||||
The equal functions, on the other hand, are defined not to raise the invalid
|
||||
exception on quiet NaNs. For completeness, SoftFloat provides the following
|
||||
additional functions:
|
||||
|
||||
float32_eq_signaling float32_le_quiet float32_lt_quiet
|
||||
float64_eq_signaling float64_le_quiet float64_lt_quiet
|
||||
floatx80_eq_signaling floatx80_le_quiet floatx80_lt_quiet
|
||||
float128_eq_signaling float128_le_quiet float128_lt_quiet
|
||||
|
||||
The `signaling' equal functions are identical to the standard functions
|
||||
except that the invalid exception is raised for any NaN input. Likewise,
|
||||
the `quiet' comparison functions are identical to their counterparts except
|
||||
that the invalid exception is not raised for quiet NaNs.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Signaling NaN Test Functions
|
||||
|
||||
The following functions test whether a floating-point value is a signaling
|
||||
NaN:
|
||||
|
||||
float32_is_signaling_nan
|
||||
float64_is_signaling_nan
|
||||
floatx80_is_signaling_nan
|
||||
float128_is_signaling_nan
|
||||
|
||||
The functions take one operand and return 1 if the operand is a signaling
|
||||
NaN and 0 otherwise.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Raise-Exception Function
|
||||
|
||||
SoftFloat provides a function for raising floating-point exceptions:
|
||||
|
||||
float_raise
|
||||
|
||||
The function takes a mask indicating the set of exceptions to raise. No
|
||||
result is returned. In addition to setting the specified exception flags,
|
||||
this function may cause a trap or abort appropriate for the current system.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Contact Information
|
||||
|
||||
At the time of this writing, the most up-to-date information about SoftFloat
|
||||
and the latest release can be found at the Web page `http://www.jhauser.us/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
65
libsrc/float/softfloat/history.txt
Normal file
65
libsrc/float/softfloat/history.txt
Normal file
|
@ -0,0 +1,65 @@
|
|||
|
||||
History of Major Changes to Berkeley SoftFloat, up to Release 2c
|
||||
|
||||
John R. Hauser
|
||||
2015 January 31
|
||||
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Release 2c (2015 January)
|
||||
|
||||
-- Fixed mistakes affecting some 64-bit processors.
|
||||
|
||||
-- Further improved the documentation and the wording for the legal
|
||||
restrictions on using SoftFloat.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Release 2b (2002 May)
|
||||
|
||||
-- Made minor updates to the documentation, including improved wording for
|
||||
the legal restrictions on using SoftFloat.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Release 2a (1998 December)
|
||||
|
||||
-- Added functions to convert between 64-bit integers (int64) and all
|
||||
supported floating-point formats.
|
||||
|
||||
-- Fixed a bug in all 64-bit-version square root functions except
|
||||
`float32_sqrt' that caused the result sometimes to be off by 1 unit in
|
||||
the last place (1 ulp) from what it should be. (Bug discovered by Paul
|
||||
Donahue.)
|
||||
|
||||
-- Improved the Makefiles.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Release 2 (1997 June)
|
||||
|
||||
-- Created the 64-bit (bits64) version, adding the floatx80 and float128
|
||||
formats.
|
||||
|
||||
-- Changed the source directory structure, splitting the sources into a
|
||||
`bits32' and a `bits64' version. Renamed `environment.h' to `milieu.h'
|
||||
to avoid confusion with environment variables.
|
||||
|
||||
-- Fixed a small error that caused `float64_round_to_int' often to round the
|
||||
wrong way in nearest/even mode when the operand was between 2^20 and 2^21
|
||||
and halfway between two integers.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Release 1a (1996 July)
|
||||
|
||||
-- Corrected a mistake that caused borderline underflow cases not to raise
|
||||
the underflow flag when they should have. (Problem reported by Doug
|
||||
Priest.)
|
||||
|
||||
-- Added the `float_detect_tininess' variable to control whether tininess is
|
||||
detected before or after rounding.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Release 1 (1996 July)
|
||||
|
||||
-- Original release.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
644
libsrc/float/softfloat/macros.h
Normal file
644
libsrc/float/softfloat/macros.h
Normal file
|
@ -0,0 +1,644 @@
|
|||
|
||||
/*============================================================================
|
||||
|
||||
This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
|
||||
Arithmetic Package, Release 2c, by John R. Hauser.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
|
||||
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
|
||||
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
|
||||
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
|
||||
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
|
||||
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
|
||||
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
|
||||
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
|
||||
SOFTWARE.
|
||||
|
||||
Derivative works require also that (1) the source code for the derivative work
|
||||
includes prominent notice that the work is derivative, and (2) the source code
|
||||
includes prominent notice of these three paragraphs for those parts of this
|
||||
code that are retained.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts `a' right by the number of bits given in `count'. If any nonzero
|
||||
| bits are shifted off, they are "jammed" into the least significant bit of
|
||||
| the result by setting the least significant bit to 1. The value of `count'
|
||||
| can be arbitrarily large; in particular, if `count' is greater than 32, the
|
||||
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
|
||||
| The result is stored in the location pointed to by `zPtr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
|
||||
{
|
||||
bits32 z;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z = a;
|
||||
}
|
||||
else if ( count < 32 ) {
|
||||
z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
|
||||
}
|
||||
else {
|
||||
z = ( a != 0 );
|
||||
}
|
||||
*zPtr = z;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
|
||||
| number of bits given in `count'. Any bits shifted off are lost. The value
|
||||
| of `count' can be arbitrarily large; in particular, if `count' is greater
|
||||
| than 64, the result will be 0. The result is broken into two 32-bit pieces
|
||||
| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
shift64Right(
|
||||
bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
|
||||
{
|
||||
bits32 z0, z1;
|
||||
int8 negCount = ( - count ) & 31;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else if ( count < 32 ) {
|
||||
z1 = ( a0<<negCount ) | ( a1>>count );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
z1 = ( count < 64 ) ? ( a0>>( count & 31 ) ) : 0;
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
|
||||
| number of bits given in `count'. If any nonzero bits are shifted off, they
|
||||
| are "jammed" into the least significant bit of the result by setting the
|
||||
| least significant bit to 1. The value of `count' can be arbitrarily large;
|
||||
| in particular, if `count' is greater than 64, the result will be either 0
|
||||
| or 1, depending on whether the concatenation of `a0' and `a1' is zero or
|
||||
| nonzero. The result is broken into two 32-bit pieces which are stored at
|
||||
| the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
shift64RightJamming(
|
||||
bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
|
||||
{
|
||||
bits32 z0, z1;
|
||||
int8 negCount = ( - count ) & 31;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else if ( count < 32 ) {
|
||||
z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if ( count == 32 ) {
|
||||
z1 = a0 | ( a1 != 0 );
|
||||
}
|
||||
else if ( count < 64 ) {
|
||||
z1 = ( a0>>( count & 31 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
|
||||
}
|
||||
else {
|
||||
z1 = ( ( a0 | a1 ) != 0 );
|
||||
}
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
|
||||
| by 32 _plus_ the number of bits given in `count'. The shifted result is
|
||||
| at most 64 nonzero bits; these are broken into two 32-bit pieces which are
|
||||
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
|
||||
| off form a third 32-bit result as follows: The _last_ bit shifted off is
|
||||
| the most-significant bit of the extra result, and the other 31 bits of the
|
||||
| extra result are all zero if and only if _all_but_the_last_ bits shifted off
|
||||
| were all zero. This extra result is stored in the location pointed to by
|
||||
| `z2Ptr'. The value of `count' can be arbitrarily large.
|
||||
| (This routine makes more sense if `a0', `a1', and `a2' are considered
|
||||
| to form a fixed-point value with binary point between `a1' and `a2'. This
|
||||
| fixed-point value is shifted right by the number of bits given in `count',
|
||||
| and the integer part of the result is returned at the locations pointed to
|
||||
| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
|
||||
| corrupted as described above, and is returned at the location pointed to by
|
||||
| `z2Ptr'.)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
shift64ExtraRightJamming(
|
||||
bits32 a0,
|
||||
bits32 a1,
|
||||
bits32 a2,
|
||||
int16 count,
|
||||
bits32 *z0Ptr,
|
||||
bits32 *z1Ptr,
|
||||
bits32 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits32 z0, z1, z2;
|
||||
int8 negCount = ( - count ) & 31;
|
||||
|
||||
if ( count == 0 ) {
|
||||
z2 = a2;
|
||||
z1 = a1;
|
||||
z0 = a0;
|
||||
}
|
||||
else {
|
||||
if ( count < 32 ) {
|
||||
z2 = a1<<negCount;
|
||||
z1 = ( a0<<negCount ) | ( a1>>count );
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if ( count == 32 ) {
|
||||
z2 = a1;
|
||||
z1 = a0;
|
||||
}
|
||||
else {
|
||||
a2 |= a1;
|
||||
if ( count < 64 ) {
|
||||
z2 = a0<<negCount;
|
||||
z1 = a0>>( count & 31 );
|
||||
}
|
||||
else {
|
||||
z2 = ( count == 64 ) ? a0 : ( a0 != 0 );
|
||||
z1 = 0;
|
||||
}
|
||||
}
|
||||
z0 = 0;
|
||||
}
|
||||
z2 |= ( a2 != 0 );
|
||||
}
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
|
||||
| number of bits given in `count'. Any bits shifted off are lost. The value
|
||||
| of `count' must be less than 32. The result is broken into two 32-bit
|
||||
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
shortShift64Left(
|
||||
bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
|
||||
{
|
||||
|
||||
*z1Ptr = a1<<count;
|
||||
*z0Ptr =
|
||||
( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 31 ) );
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
|
||||
| by the number of bits given in `count'. Any bits shifted off are lost.
|
||||
| The value of `count' must be less than 32. The result is broken into three
|
||||
| 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
|
||||
| `z1Ptr', and `z2Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
shortShift96Left(
|
||||
bits32 a0,
|
||||
bits32 a1,
|
||||
bits32 a2,
|
||||
int16 count,
|
||||
bits32 *z0Ptr,
|
||||
bits32 *z1Ptr,
|
||||
bits32 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits32 z0, z1, z2;
|
||||
int8 negCount;
|
||||
|
||||
z2 = a2<<count;
|
||||
z1 = a1<<count;
|
||||
z0 = a0<<count;
|
||||
if ( 0 < count ) {
|
||||
negCount = ( ( - count ) & 31 );
|
||||
z1 |= a2>>negCount;
|
||||
z0 |= a1>>negCount;
|
||||
}
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
|
||||
| value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
|
||||
| any carry out is lost. The result is broken into two 32-bit pieces which
|
||||
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
add64(
|
||||
bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
|
||||
{
|
||||
bits32 z1;
|
||||
|
||||
z1 = a1 + b1;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = a0 + b0 + ( z1 < a1 );
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
|
||||
| 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
|
||||
| modulo 2^96, so any carry out is lost. The result is broken into three
|
||||
| 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
|
||||
| `z1Ptr', and `z2Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
add96(
|
||||
bits32 a0,
|
||||
bits32 a1,
|
||||
bits32 a2,
|
||||
bits32 b0,
|
||||
bits32 b1,
|
||||
bits32 b2,
|
||||
bits32 *z0Ptr,
|
||||
bits32 *z1Ptr,
|
||||
bits32 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits32 z0, z1, z2;
|
||||
int8 carry0, carry1;
|
||||
|
||||
z2 = a2 + b2;
|
||||
carry1 = ( z2 < a2 );
|
||||
z1 = a1 + b1;
|
||||
carry0 = ( z1 < a1 );
|
||||
z0 = a0 + b0;
|
||||
z1 += carry1;
|
||||
z0 += ( z1 < carry1 );
|
||||
z0 += carry0;
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
|
||||
| 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
|
||||
| 2^64, so any borrow out (carry out) is lost. The result is broken into two
|
||||
| 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
|
||||
| `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
sub64(
|
||||
bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
|
||||
{
|
||||
|
||||
*z1Ptr = a1 - b1;
|
||||
*z0Ptr = a0 - b0 - ( a1 < b1 );
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
|
||||
| the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
|
||||
| is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
|
||||
| into three 32-bit pieces which are stored at the locations pointed to by
|
||||
| `z0Ptr', `z1Ptr', and `z2Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
sub96(
|
||||
bits32 a0,
|
||||
bits32 a1,
|
||||
bits32 a2,
|
||||
bits32 b0,
|
||||
bits32 b1,
|
||||
bits32 b2,
|
||||
bits32 *z0Ptr,
|
||||
bits32 *z1Ptr,
|
||||
bits32 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits32 z0, z1, z2;
|
||||
int8 borrow0, borrow1;
|
||||
|
||||
z2 = a2 - b2;
|
||||
borrow1 = ( a2 < b2 );
|
||||
z1 = a1 - b1;
|
||||
borrow0 = ( a1 < b1 );
|
||||
z0 = a0 - b0;
|
||||
z0 -= ( z1 < borrow1 );
|
||||
z1 -= borrow1;
|
||||
z0 -= borrow0;
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
|
||||
| into two 32-bit pieces which are stored at the locations pointed to by
|
||||
| `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void mul32To64( bits32 a, bits32 b, bits32 *z0Ptr, bits32 *z1Ptr )
|
||||
{
|
||||
bits16 aHigh, aLow, bHigh, bLow;
|
||||
bits32 z0, zMiddleA, zMiddleB, z1;
|
||||
|
||||
aLow = a;
|
||||
aHigh = a>>16;
|
||||
bLow = b;
|
||||
bHigh = b>>16;
|
||||
z1 = ( (bits32) aLow ) * bLow;
|
||||
zMiddleA = ( (bits32) aLow ) * bHigh;
|
||||
zMiddleB = ( (bits32) aHigh ) * bLow;
|
||||
z0 = ( (bits32) aHigh ) * bHigh;
|
||||
zMiddleA += zMiddleB;
|
||||
z0 += ( ( (bits32) ( zMiddleA < zMiddleB ) )<<16 ) + ( zMiddleA>>16 );
|
||||
zMiddleA <<= 16;
|
||||
z1 += zMiddleA;
|
||||
z0 += ( z1 < zMiddleA );
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
|
||||
| to obtain a 96-bit product. The product is broken into three 32-bit pieces
|
||||
| which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
|
||||
| `z2Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
mul64By32To96(
|
||||
bits32 a0,
|
||||
bits32 a1,
|
||||
bits32 b,
|
||||
bits32 *z0Ptr,
|
||||
bits32 *z1Ptr,
|
||||
bits32 *z2Ptr
|
||||
)
|
||||
{
|
||||
bits32 z0, z1, z2, more1;
|
||||
|
||||
mul32To64( a1, b, &z1, &z2 );
|
||||
mul32To64( a0, b, &z0, &more1 );
|
||||
add64( z0, more1, 0, z1, &z0, &z1 );
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
|
||||
| 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
|
||||
| product. The product is broken into four 32-bit pieces which are stored at
|
||||
| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE void
|
||||
mul64To128(
|
||||
bits32 a0,
|
||||
bits32 a1,
|
||||
bits32 b0,
|
||||
bits32 b1,
|
||||
bits32 *z0Ptr,
|
||||
bits32 *z1Ptr,
|
||||
bits32 *z2Ptr,
|
||||
bits32 *z3Ptr
|
||||
)
|
||||
{
|
||||
bits32 z0, z1, z2, z3;
|
||||
bits32 more1, more2;
|
||||
|
||||
mul32To64( a1, b1, &z2, &z3 );
|
||||
mul32To64( a1, b0, &z1, &more2 );
|
||||
add64( z1, more2, 0, z2, &z1, &z2 );
|
||||
mul32To64( a0, b0, &z0, &more1 );
|
||||
add64( z0, more1, 0, z1, &z0, &z1 );
|
||||
mul32To64( a0, b1, &more1, &more2 );
|
||||
add64( more1, more2, 0, z2, &more1, &z2 );
|
||||
add64( z0, z1, 0, more1, &z0, &z1 );
|
||||
*z3Ptr = z3;
|
||||
*z2Ptr = z2;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns an approximation to the 32-bit integer quotient obtained by dividing
|
||||
| `b' into the 64-bit value formed by concatenating `a0' and `a1'. The
|
||||
| divisor `b' must be at least 2^31. If q is the exact quotient truncated
|
||||
| toward zero, the approximation returned lies between q and q + 2 inclusive.
|
||||
| If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
|
||||
| unsigned integer is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static bits32 estimateDiv64To32( bits32 a0, bits32 a1, bits32 b )
|
||||
{
|
||||
bits32 b0, b1;
|
||||
bits32 rem0, rem1, term0, term1;
|
||||
bits32 z;
|
||||
|
||||
if ( b <= a0 ) return 0xFFFFFFFF;
|
||||
b0 = b>>16;
|
||||
z = ( b0<<16 <= a0 ) ? 0xFFFF0000 : ( a0 / b0 )<<16;
|
||||
mul32To64( b, z, &term0, &term1 );
|
||||
sub64( a0, a1, term0, term1, &rem0, &rem1 );
|
||||
while ( ( (sbits32) rem0 ) < 0 ) {
|
||||
z -= 0x10000;
|
||||
b1 = b<<16;
|
||||
add64( rem0, rem1, b0, b1, &rem0, &rem1 );
|
||||
}
|
||||
rem0 = ( rem0<<16 ) | ( rem1>>16 );
|
||||
z |= ( b0<<16 <= rem0 ) ? 0xFFFF : rem0 / b0;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns an approximation to the square root of the 32-bit significand given
|
||||
| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
|
||||
| `aExp' (the least significant bit) is 1, the integer returned approximates
|
||||
| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
|
||||
| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
|
||||
| case, the approximation returned lies strictly within +/-2 of the exact
|
||||
| value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static bits32 estimateSqrt32( int16 aExp, bits32 a )
|
||||
{
|
||||
static const bits16 sqrtOddAdjustments[] = {
|
||||
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
|
||||
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
|
||||
};
|
||||
static const bits16 sqrtEvenAdjustments[] = {
|
||||
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
|
||||
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
|
||||
};
|
||||
int8 index;
|
||||
bits32 z;
|
||||
|
||||
index = ( a>>27 ) & 15;
|
||||
if ( aExp & 1 ) {
|
||||
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
|
||||
z = ( ( a / z )<<14 ) + ( z<<15 );
|
||||
a >>= 1;
|
||||
}
|
||||
else {
|
||||
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
|
||||
z = a / z + z;
|
||||
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
|
||||
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
|
||||
}
|
||||
return ( ( estimateDiv64To32( a, 0, z ) )>>1 ) + ( z>>1 );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the number of leading 0 bits before the most-significant 1 bit of
|
||||
| `a'. If `a' is zero, 32 is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static int8 countLeadingZeros32( bits32 a )
|
||||
{
|
||||
static const int8 countLeadingZerosHigh[] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
int8 shiftCount;
|
||||
|
||||
shiftCount = 0;
|
||||
if ( a < 0x10000 ) {
|
||||
shiftCount += 16;
|
||||
a <<= 16;
|
||||
}
|
||||
if ( a < 0x1000000 ) {
|
||||
shiftCount += 8;
|
||||
a <<= 8;
|
||||
}
|
||||
shiftCount += countLeadingZerosHigh[ a>>24 ];
|
||||
return shiftCount;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
|
||||
| equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
|
||||
| returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE flag eq64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
|
||||
{
|
||||
|
||||
return ( a0 == b0 ) && ( a1 == b1 );
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
|
||||
| than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
|
||||
| Otherwise, returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE flag le64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
|
||||
{
|
||||
|
||||
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
|
||||
| than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
|
||||
| returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE flag lt64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
|
||||
{
|
||||
|
||||
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
|
||||
| equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
|
||||
| returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
INLINE flag ne64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
|
||||
{
|
||||
|
||||
return ( a0 != b0 ) || ( a1 != b1 );
|
||||
|
||||
}
|
||||
#endif
|
||||
|
38
libsrc/float/softfloat/milieu.h
Normal file
38
libsrc/float/softfloat/milieu.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
|
||||
/*============================================================================
|
||||
|
||||
This C header file template is part of the Berkeley SoftFloat IEEE Floating-
|
||||
Point Arithmetic Package, Release 2c, by John R. Hauser.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
|
||||
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
|
||||
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
|
||||
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
|
||||
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
|
||||
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
|
||||
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
|
||||
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
|
||||
SOFTWARE.
|
||||
|
||||
Derivative works require also that (1) the source code for the derivative work
|
||||
includes prominent notice that the work is derivative, and (2) the source code
|
||||
includes prominent notice of these three paragraphs for those parts of this
|
||||
code that are retained.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Include common integer types and flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "6502-CC65.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Symbolic Boolean literals.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
FALSE = 0,
|
||||
TRUE = 1
|
||||
};
|
||||
|
179
libsrc/float/softfloat/softfloat-wrapper.s
Normal file
179
libsrc/float/softfloat/softfloat-wrapper.s
Normal file
|
@ -0,0 +1,179 @@
|
|||
|
||||
.importzp sreg, tmp1
|
||||
|
||||
.import _int32_to_float32
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; conversions: to float
|
||||
|
||||
; 16bit signed -> float
|
||||
.export axfloat
|
||||
axfloat:
|
||||
; FIXME
|
||||
; sign extend to 32bit
|
||||
ldy #$ff
|
||||
cpx #$80
|
||||
bcs @sk
|
||||
ldy #$00
|
||||
@sk:
|
||||
sty sreg
|
||||
sty sreg+1
|
||||
jmp _int32_to_float32
|
||||
|
||||
; 16bit unsigned -> float
|
||||
.export axufloat
|
||||
axufloat:
|
||||
; FIXME
|
||||
ldy #0
|
||||
sty sreg
|
||||
sty sreg+1
|
||||
jmp _int32_to_float32
|
||||
|
||||
; 32bit signed -> float
|
||||
.export eaxfloat
|
||||
eaxfloat:
|
||||
; FIXME
|
||||
jmp _int32_to_float32
|
||||
|
||||
; 32bit unsigned -> float
|
||||
.export eaxufloat
|
||||
eaxufloat:
|
||||
; FIXME
|
||||
jmp _int32_to_float32
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; conversions: from float
|
||||
|
||||
.import _float32_to_int32
|
||||
.import _float32_to_int32_round_to_zero
|
||||
|
||||
; float -> 16bit int
|
||||
.export feaxint
|
||||
feaxint:
|
||||
; FIXME
|
||||
jmp _float32_to_int32_round_to_zero
|
||||
; jmp _float32_to_int32
|
||||
; float -> 32bit int
|
||||
.export feaxlong
|
||||
feaxlong:
|
||||
jmp _float32_to_int32_round_to_zero
|
||||
; jmp _float32_to_int32
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; the ! operator, returns a bool (int)
|
||||
.export fbnegeax
|
||||
fbnegeax:
|
||||
stx tmp1
|
||||
ora tmp1
|
||||
ora sreg
|
||||
ora sreg+1
|
||||
beq @ret1 ; is = 0
|
||||
; return 0
|
||||
lda #0
|
||||
tax
|
||||
rts
|
||||
@ret1:
|
||||
lda #1
|
||||
ldx #0
|
||||
rts
|
||||
|
||||
.import _float32_mul
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
.export fnegeax
|
||||
fnegeax:
|
||||
pha
|
||||
; txa
|
||||
; pha
|
||||
lda sreg+1
|
||||
eor #$80 ; sign bit
|
||||
sta sreg+1
|
||||
; lda sreg+0
|
||||
; eor #$ff ; sign bit
|
||||
; sta sreg+0
|
||||
; txa
|
||||
; eor #$ff ; sign bit
|
||||
; tax
|
||||
; pla
|
||||
; tax
|
||||
pla
|
||||
; eor #$ff ; sign bit
|
||||
rts
|
||||
|
||||
|
||||
.import _float32_add
|
||||
.import _float32_sub
|
||||
.import _float32_mul
|
||||
.import _float32_div
|
||||
|
||||
.export ftosaddeax
|
||||
ftosaddeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp _float32_add
|
||||
.export ftossubeax
|
||||
ftossubeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp _float32_sub
|
||||
.export ftosmuleax
|
||||
ftosmuleax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp _float32_mul
|
||||
.export ftosdiveax
|
||||
ftosdiveax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp _float32_div
|
||||
|
||||
.import _float32_rsub
|
||||
.export ftosrsubeax
|
||||
ftosrsubeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp _float32_rsub
|
||||
|
||||
.import _float32_eq
|
||||
.import _float32_le
|
||||
.import _float32_lt
|
||||
|
||||
; test for equal
|
||||
.export ftoseqeax
|
||||
ftoseqeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jmp _float32_eq
|
||||
|
||||
; test for not equal
|
||||
.export ftosneeax
|
||||
ftosneeax:
|
||||
; arg0: a/x/sreg/sreg+1
|
||||
; arg1: (sp),y (y=0..3)
|
||||
jsr _float32_eq
|
||||
eor #1
|
||||
rts
|
||||
|
||||
|
||||
; Test for less than or equal to
|
||||
.export ftosleeax
|
||||
ftosleeax:
|
||||
jmp _float32_le
|
||||
|
||||
.export ftosgteax
|
||||
ftosgteax:
|
||||
jsr _float32_le
|
||||
eor #1
|
||||
rts
|
||||
|
||||
; Test for less than
|
||||
.export ftoslteax
|
||||
ftoslteax:
|
||||
jmp _float32_lt
|
||||
|
||||
; Test for "not less than" -> "equal or greater than"
|
||||
; Test for greater than or equal to
|
||||
.export ftosgeeax
|
||||
ftosgeeax:
|
||||
jsr _float32_lt
|
||||
eor #1
|
||||
rts
|
2295
libsrc/float/softfloat/softfloat.c
Normal file
2295
libsrc/float/softfloat/softfloat.c
Normal file
File diff suppressed because it is too large
Load Diff
134
libsrc/float/softfloat/softfloat.h
Normal file
134
libsrc/float/softfloat/softfloat.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
|
||||
#ifndef SOFTFLOAT_H_
|
||||
#define SOFTFLOAT_H_
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C header file template is part of the Berkeley SoftFloat IEEE Floating-
|
||||
Point Arithmetic Package, Release 2c, by John R. Hauser.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
|
||||
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
|
||||
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
|
||||
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
|
||||
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
|
||||
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
|
||||
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
|
||||
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
|
||||
SOFTWARE.
|
||||
|
||||
Derivative works require also that (1) the source code for the derivative work
|
||||
includes prominent notice that the work is derivative, and (2) the source code
|
||||
includes prominent notice of these three paragraphs for those parts of this
|
||||
code that are retained.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE floating-point types.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef unsigned long float32;
|
||||
typedef struct {
|
||||
unsigned long high, low;
|
||||
} float64;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE floating-point underflow tininess-detection mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern signed char float_detect_tininess;
|
||||
enum {
|
||||
float_tininess_after_rounding = 0,
|
||||
float_tininess_before_rounding = 1
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE floating-point rounding mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern signed char float_rounding_mode;
|
||||
enum {
|
||||
float_round_nearest_even = 0,
|
||||
float_round_to_zero = 1,
|
||||
float_round_down = 2,
|
||||
float_round_up = 3
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE floating-point exception flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern signed char float_exception_flags;
|
||||
enum {
|
||||
float_flag_inexact = 1,
|
||||
float_flag_underflow = 2,
|
||||
float_flag_overflow = 4,
|
||||
float_flag_divbyzero = 8,
|
||||
float_flag_invalid = 16
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Routine to raise any or all of the software IEEE floating-point exception
|
||||
| flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void float_raise( signed char );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE integer-to-floating-point conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 int32_to_float32( int32 );
|
||||
float64 int32_to_float64( int32 );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE single-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 float32_to_int32( float32 );
|
||||
int32 float32_to_int32_round_to_zero( float32 );
|
||||
float64 float32_to_float64( float32 );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE single-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 __fastcall__ float32_round_to_int( float32 );
|
||||
float32 __fastcall__ float32_add( float32, float32 );
|
||||
float32 __fastcall__ float32_sub( float32, float32 );
|
||||
float32 __fastcall__ float32_rsub( float32, float32 );
|
||||
float32 __fastcall__ float32_mul( float32, float32 );
|
||||
float32 __fastcall__ float32_div( float32, float32 );
|
||||
float32 __fastcall__ float32_rem( float32, float32 );
|
||||
float32 __fastcall__ float32_sqrt( float32 );
|
||||
unsigned char __fastcall__ float32_eq( float32, float32 );
|
||||
unsigned char __fastcall__ float32_le( float32, float32 );
|
||||
unsigned char __fastcall__ float32_lt( float32, float32 );
|
||||
unsigned char __fastcall__ float32_eq_signaling( float32, float32 );
|
||||
unsigned char __fastcall__ float32_le_quiet( float32, float32 );
|
||||
unsigned char __fastcall__ float32_lt_quiet( float32, float32 );
|
||||
unsigned char __fastcall__ float32_is_signaling_nan( float32 );
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE double-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
signed short float64_to_int32( float64 );
|
||||
signed short float64_to_int32_round_to_zero( float64 );
|
||||
float32 float64_to_float32( float64 );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEEE double-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float64 float64_round_to_int( float64 );
|
||||
float64 float64_add( float64, float64 );
|
||||
float64 float64_sub( float64, float64 );
|
||||
float64 float64_mul( float64, float64 );
|
||||
float64 float64_div( float64, float64 );
|
||||
float64 float64_rem( float64, float64 );
|
||||
float64 float64_sqrt( float64 );
|
||||
unsigned char float64_eq( float64, float64 );
|
||||
unsigned char float64_le( float64, float64 );
|
||||
unsigned char float64_lt( float64, float64 );
|
||||
unsigned char float64_eq_signaling( float64, float64 );
|
||||
unsigned char float64_le_quiet( float64, float64 );
|
||||
unsigned char float64_lt_quiet( float64, float64 );
|
||||
unsigned char float64_is_signaling_nan( float64 );
|
||||
#endif
|
||||
|
||||
#endif /* SOFTFLOAT_H_ */
|
98
libsrc/float/softfloat/softloat-ftostr.c
Normal file
98
libsrc/float/softfloat/softloat-ftostr.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//#define DEBUG_VALUE
|
||||
|
||||
// This is really a terrible function that should get completely rewritten and
|
||||
// tested by someone who knows what he is doing =P
|
||||
char *_ftostr(char *buffer, float f) {
|
||||
signed long intpart;
|
||||
float fracpart;
|
||||
float f1, f2;
|
||||
signed long n0;
|
||||
int is_negative;
|
||||
unsigned long raw_value = *((unsigned long*)(&f));
|
||||
|
||||
is_negative = (raw_value & 0x80000000) ? 1 : 0; // very hacky indeed
|
||||
|
||||
if (!is_negative) {
|
||||
intpart = (signed long)(f);
|
||||
} else {
|
||||
intpart = (signed long)(f);
|
||||
intpart = -intpart;
|
||||
}
|
||||
|
||||
f2 = intpart;
|
||||
#if 0
|
||||
if (!is_negative) {
|
||||
if (f2 > f) {
|
||||
if (intpart > 0) {
|
||||
--intpart;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (f2 > f) {
|
||||
if (intpart > 0) {
|
||||
--intpart;
|
||||
}
|
||||
}
|
||||
// ++intpart;
|
||||
}
|
||||
|
||||
if (!is_negative) {
|
||||
if (intpart < 0) {
|
||||
intpart *= -1;
|
||||
}
|
||||
} else {
|
||||
if (intpart < 0) {
|
||||
intpart *= -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
f2 = intpart;
|
||||
if (!is_negative) {
|
||||
fracpart = f - f2;
|
||||
} else {
|
||||
fracpart = (-f) - f2;
|
||||
}
|
||||
|
||||
f1 = 10000.0f;
|
||||
|
||||
f1 = f1 * fracpart;
|
||||
|
||||
n0 = (signed long)f1;
|
||||
#if 0
|
||||
// caution: make sure fracpart can never be negative
|
||||
if (n0 < 0) {
|
||||
n0 *= -1;
|
||||
}
|
||||
#endif
|
||||
// printf("n0:%ld\n",n0);
|
||||
#ifdef DEBUG_VALUE
|
||||
if (n0 >= 1000) {
|
||||
sprintf(buffer, "<0x%08lx:%s%ld.%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
|
||||
} else if (n0 >= 100) {
|
||||
sprintf(buffer, "<0x%08lx:%s%ld.0%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
|
||||
} else if (n0 >= 10) {
|
||||
sprintf(buffer, "<0x%08lx:%s%ld.00%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
|
||||
} else if (n0 >= 1) {
|
||||
sprintf(buffer, "<0x%08lx:%s%ld.000%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
|
||||
} else {
|
||||
sprintf(buffer, "<0x%08lx:%s%ld.0000>", raw_value, is_negative ? "-" : "", intpart);
|
||||
}
|
||||
#else
|
||||
if (n0 >= 1000) {
|
||||
sprintf(buffer, "%s%ld.%ld", is_negative ? "-" : "", intpart, n0);
|
||||
} else if (n0 >= 100) {
|
||||
sprintf(buffer, "%s%ld.0%ld", is_negative ? "-" : "", intpart, n0);
|
||||
} else if (n0 >= 10) {
|
||||
sprintf(buffer, "%s%ld.00%ld", is_negative ? "-" : "", intpart, n0);
|
||||
} else if (n0 >= 1) {
|
||||
sprintf(buffer, "%s%ld.000%ld", is_negative ? "-" : "", intpart, n0);
|
||||
} else {
|
||||
sprintf(buffer, "%s%ld.0000", is_negative ? "-" : "", intpart);
|
||||
}
|
||||
#endif
|
||||
return &buffer[0];
|
||||
}
|
400
libsrc/float/softfloat/source.txt
Normal file
400
libsrc/float/softfloat/source.txt
Normal file
|
@ -0,0 +1,400 @@
|
|||
|
||||
Berkeley SoftFloat Release 2c Source Documentation
|
||||
|
||||
John R. Hauser
|
||||
2015 January 30
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Introduction
|
||||
|
||||
Berkeley SoftFloat is a software implementation of binary floating-point
|
||||
that conforms to the IEEE Standard for Floating-Point Arithmetic.
|
||||
Release 2c of SoftFloat can support four floating-point formats: 32-bit
|
||||
single-precision, 64-bit double-precision, 80-bit double-extended-precision,
|
||||
and 128-bit quadruple-precision. All operations required by the older 1985
|
||||
version of the IEEE Standard are implemented, except for conversions to and
|
||||
from decimal. SoftFloat is distributed in the form of C source code, so a
|
||||
C compiler is needed to compile the code. Support for the 80-bit double-
|
||||
extended-precision and 128-bit quadruple-precision formats is dependent on
|
||||
the C compiler implementing a 64-bit integer type.
|
||||
|
||||
This document gives information needed for compiling and/or porting this
|
||||
SoftFloat release.
|
||||
|
||||
The source code for SoftFloat is intended to be relatively machine-
|
||||
independent and should be compilable using most any ISO/ANSI C compiler. At
|
||||
the time of this writing, SoftFloat has been successfully compiled with the
|
||||
GNU C Compiler (`gcc') for several platforms.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Limitations
|
||||
|
||||
As supplied, SoftFloat requires an ISO/ANSI-style C compiler. No attempt
|
||||
has been made to accomodate compilers that are not ISO-conformant. Older
|
||||
"K&R-style" compilers are not adequate for compiling SoftFloat. All testing
|
||||
I have done so far has been with the GNU C Compiler. Compilation with other
|
||||
compilers should be possible but has not been tested by me.
|
||||
|
||||
The SoftFloat sources assume that source code file names can be longer than
|
||||
8 characters. In order to compile under an MS-DOS-type system, many of the
|
||||
source files will need to be renamed, and the source and Makefiles edited
|
||||
appropriately. Once compiled, the SoftFloat binary does not depend on the
|
||||
existence of long file names.
|
||||
|
||||
The underlying machine is assumed to be binary with a word size that is a
|
||||
power of 2. Bytes are 8 bits. Arithmetic on signed integers must modularly
|
||||
wrap around on overflows (as is already required for unsigned integers
|
||||
in C).
|
||||
|
||||
Support for the 80-bit double-extended-precision and 128-bit quadruple-
|
||||
precision formats depends on the C compiler implementing a 64-bit integer
|
||||
type. If the largest integer type supported by the C compiler is 32 bits,
|
||||
SoftFloat is limited to the 32-bit single-precision and 64-bit double-
|
||||
precision formats.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Contents
|
||||
|
||||
Introduction
|
||||
Limitations
|
||||
Contents
|
||||
Legal Notice
|
||||
SoftFloat Source Directory Structure
|
||||
SoftFloat Source Files
|
||||
processors/*.h
|
||||
softfloat/bits*/*/softfloat.h
|
||||
softfloat/bits*/*/milieu.h
|
||||
softfloat/bits*/*/softfloat-specialize
|
||||
softfloat/bits*/softfloat-macros
|
||||
softfloat/bits*/softfloat.c
|
||||
Steps to Creating a `softfloat.o'
|
||||
Making `softfloat.o' a Library
|
||||
Testing SoftFloat
|
||||
Timing SoftFloat
|
||||
Compiler Options and Efficiency
|
||||
Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'
|
||||
Contact Information
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Legal Notice
|
||||
|
||||
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made
|
||||
possible in part by the International Computer Science Institute, located
|
||||
at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding
|
||||
was partially provided by the National Science Foundation under grant
|
||||
MIP-9311980. The original version of this code was written as part of a
|
||||
project to build a fixed-point vector processor in collaboration with the
|
||||
University of California at Berkeley, overseen by Profs. Nelson Morgan and
|
||||
John Wawrzynek.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
|
||||
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
|
||||
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
|
||||
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN
|
||||
HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
|
||||
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
|
||||
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE,
|
||||
OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF
|
||||
THE SOFTWARE.
|
||||
|
||||
The following are expressly permitted, even for commercial purposes:
|
||||
(1) distribution of SoftFloat in whole or in part, as long as this and
|
||||
other legal notices remain and are prominent, and provided also that, for a
|
||||
partial distribution, prominent notice is given that it is a subset of the
|
||||
original; and
|
||||
(2) inclusion or use of SoftFloat in whole or in part in a derivative
|
||||
work, provided that the use restrictions above are met and the minimal
|
||||
documentation requirements stated in the source code are satisfied.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
SoftFloat Source Directory Structure
|
||||
|
||||
Because SoftFloat is targeted to multiple platforms, its source code
|
||||
is slightly scattered between target-specific and target-independent
|
||||
directories and files. The directory structure is as follows:
|
||||
|
||||
processors
|
||||
softfloat
|
||||
bits64
|
||||
templates
|
||||
386-Win32-GCC
|
||||
SPARC-Solaris-GCC
|
||||
bits32
|
||||
templates
|
||||
386-Win32-GCC
|
||||
SPARC-Solaris-GCC
|
||||
|
||||
The two topmost directories and their contents are:
|
||||
|
||||
softfloat - Most of the source code needed for SoftFloat.
|
||||
processors - Target-specific header files that are not specific to
|
||||
SoftFloat.
|
||||
|
||||
The `softfloat' directory is further split into two parts:
|
||||
|
||||
bits64 - SoftFloat implementation using 64-bit integers.
|
||||
bits32 - SoftFloat implementation using only 32-bit integers.
|
||||
|
||||
Within these directories are subdirectories for each of the targeted
|
||||
platforms. The SoftFloat source code is distributed with targets
|
||||
`386-Win32-GCC' and `SPARC-Solaris-GCC' (and perhaps others) already
|
||||
prepared for both the 32-bit and 64-bit implementations. Source files
|
||||
that are not within these target-specific subdirectories are intended to be
|
||||
target-independent.
|
||||
|
||||
The naming convention used for the target-specific directories is
|
||||
`<processor>-<executable-type>-<compiler>'. The names of the supplied
|
||||
target directories should be interpreted as follows:
|
||||
|
||||
<processor>:
|
||||
386 - Intel 386-compatible processor.
|
||||
SPARC - SPARC processor (as used by Sun computers).
|
||||
<executable-type>:
|
||||
Win32 - Microsoft Win32 executable.
|
||||
Solaris - Sun Solaris executable.
|
||||
<compiler>:
|
||||
GCC - GNU C Compiler.
|
||||
|
||||
You do not need to maintain this convention if you do not want to.
|
||||
|
||||
Alongside the supplied target-specific directories is a `templates'
|
||||
directory containing a set of "generic" target-specific source files. A
|
||||
new target directory can be created by copying the `templates' directory and
|
||||
editing the files inside. (Complete instructions for porting SoftFloat to
|
||||
a new target are in the section _Steps to Creating a `softfloat.o'_.) Note
|
||||
that the `templates' directory will not work as a target directory without
|
||||
some editing. To avoid confusion, it would be wise to refrain from editing
|
||||
the files inside `templates' directly.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
SoftFloat Source Files
|
||||
|
||||
The purpose of each source file is described below. In the following,
|
||||
the `*' symbol is used in place of the name of a specific target, such as
|
||||
`386-Win32-GCC' or `SPARC-Solaris-GCC', or in place of some other text, as
|
||||
in `bits*' for either `bits32' or `bits64'.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
processors/*.h
|
||||
|
||||
The target-specific `processors' header file defines integer types
|
||||
of various sizes, and also defines certain C preprocessor macros that
|
||||
characterize the target. The two examples supplied are `386-GCC.h' and
|
||||
`SPARC-GCC.h'. The naming convention used for processor header files is
|
||||
`<processor>-<compiler>.h'.
|
||||
|
||||
If 64-bit integers are supported by the compiler, the macro name `BITS64'
|
||||
should be defined here along with the corresponding 64-bit integer
|
||||
types. In addition, the function-like macro `LIT64' must be defined for
|
||||
constructing 64-bit integer literals (constants). The `LIT64' macro is used
|
||||
consistently in the SoftFloat code to annotate 64-bit literals.
|
||||
|
||||
If `BITS64' is not defined, only the 32-bit version of SoftFloat can be
|
||||
compiled. If `BITS64' _is_ defined, either can be compiled.
|
||||
|
||||
If an inlining attribute (such as an `inline' keyword) is provided by the
|
||||
compiler, the macro `INLINE' should be defined to the appropriate keyword.
|
||||
If not, `INLINE' can be set to the keyword `static'. The `INLINE' macro
|
||||
appears in the SoftFloat source code before every function that should
|
||||
be inlined by the compiler. SoftFloat depends on inlining to obtain
|
||||
good speed. Even if inlining cannot be forced with a language keyword,
|
||||
the compiler may still be able to perform inlining on its own as an
|
||||
optimization. If a command-line option is needed to convince the compiler
|
||||
to perform this optimization, this should be assured in the Makefile. (See
|
||||
the section _Compiler Options and Efficiency_ below.)
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
softfloat/bits*/*/softfloat.h
|
||||
|
||||
The target-specific `softfloat.h' header file defines the SoftFloat
|
||||
interface as seen by clients.
|
||||
|
||||
Unlike the actual function definitions in `softfloat.c', the declarations
|
||||
in `softfloat.h' do not use any of the types defined by the `processors'
|
||||
header file. This is done so that clients will not have to include the
|
||||
`processors' header file in order to use SoftFloat. Nevertheless, the
|
||||
target-specific declarations in `softfloat.h' must match what `softfloat.c'
|
||||
expects. For example, if `int32' is defined as `int' in the `processors'
|
||||
header file, then in `softfloat.h' the output of `float32_to_int32' should
|
||||
be stated as `int', although in `softfloat.c' it is given in target-
|
||||
independent form as `int32'.
|
||||
|
||||
For the `bits64' implementation of SoftFloat, the macro names `FLOATX80'
|
||||
and `FLOAT128' must be defined in order for the 80-bit double-extended-
|
||||
precision and 128-bit quadruple-precision formats to be enabled in the
|
||||
code. Conversely, either or both of these larger formats can be disabled by
|
||||
simply removing the `#define' of the respective macro. When a format is not
|
||||
enabled, none of the functions that either input or output the format are
|
||||
defined, and no space is taken up in `softfloat.o' by such functions. There
|
||||
is no provision for disabling the usual 32-bit single-precision and 64-bit
|
||||
double-precision formats.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
softfloat/bits*/*/milieu.h
|
||||
|
||||
The target-specific `milieu.h' header file provides declarations that are
|
||||
needed to compile SoftFloat. In addition, deviations from ISO/ANSI C by
|
||||
the compiler (such as names not properly declared in system header files)
|
||||
are corrected in this header if possible.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
softfloat/bits*/*/softfloat-specialize
|
||||
|
||||
This target-specific C source fragment defines:
|
||||
|
||||
-- whether tininess for underflow is detected before or after rounding by
|
||||
default;
|
||||
-- what (if anything) special happens when exceptions are raised;
|
||||
-- how signaling NaNs are distinguished from quiet NaNs;
|
||||
-- the default generated quiet NaNs; and
|
||||
-- how NaNs are propagated from function inputs to output.
|
||||
|
||||
These details are not decided by the IEEE Standard. This fragment is
|
||||
included verbatim within `softfloat.c' when SoftFloat is compiled.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
softfloat/bits*/softfloat-macros
|
||||
|
||||
This target-independent C source fragment defines a number of arithmetic
|
||||
functions used as primitives within the `softfloat.c' source. Most of
|
||||
the functions defined here are intended to be inlined for efficiency.
|
||||
This fragment is included verbatim within `softfloat.c' when SoftFloat is
|
||||
compiled.
|
||||
|
||||
Target-specific variations on this file are possible. See the section
|
||||
_Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'_
|
||||
below.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
softfloat/bits*/softfloat.c
|
||||
|
||||
The target-independent `softfloat.c' source file contains the body of the
|
||||
SoftFloat implementation.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
The inclusion of the files above within each other (using `#include') can be
|
||||
shown graphically as follows:
|
||||
|
||||
softfloat/bits*/softfloat.c
|
||||
softfloat/bits*/*/milieu.h
|
||||
processors/*.h
|
||||
softfloat/bits*/*/softfloat.h
|
||||
softfloat/bits*/*/softfloat-specialize
|
||||
softfloat/bits*/softfloat-macros
|
||||
|
||||
Note in particular that `softfloat.c' does not include the `processors'
|
||||
header file directly. Rather, `softfloat.c' includes the target-specific
|
||||
`milieu.h' header file, which in turn includes the appropriate processor
|
||||
header file.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Steps to Creating a `softfloat.o'
|
||||
|
||||
Porting and/or compiling SoftFloat involves the following steps:
|
||||
|
||||
1. If one does not already exist, create an appropriate `.h' file in the
|
||||
`processors' directory.
|
||||
|
||||
2. If `BITS64' is defined in the `processors' header file, choose whether
|
||||
to compile the 32-bit or 64-bit implementation of SoftFloat. If
|
||||
`BITS64' is not defined, your only choice is the 32-bit implementation.
|
||||
The remaining steps occur within either the `bits32' or `bits64'
|
||||
subdirectories.
|
||||
|
||||
3. If one does not already exist, create an appropriate target-specific
|
||||
subdirectory by copying the given `templates' directory.
|
||||
|
||||
4. In the target-specific subdirectory, edit the files `softfloat-specialize'
|
||||
and `softfloat.h' to define the desired exception handling functions
|
||||
and mode control values. In the `softfloat.h' header file, ensure also
|
||||
that all declarations give the proper target-specific type (such as
|
||||
`int' or `long') corresponding to the target-independent type used in
|
||||
`softfloat.c' (such as `int32'). None of the type names declared in the
|
||||
`processors' header file should appear in `softfloat.h'.
|
||||
|
||||
5. In the target-specific subdirectory, edit the files `milieu.h' and
|
||||
`Makefile' to reflect the current environment.
|
||||
|
||||
6. In the target-specific subdirectory, execute `make'.
|
||||
|
||||
For the targets that are supplied, if the expected compiler is available
|
||||
(usually `gcc'), it should only be necessary to execute `make' in the
|
||||
target-specific subdirectory.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Making `softfloat.o' a Library
|
||||
|
||||
SoftFloat is not made into a software library by the supplied Makefile.
|
||||
If desired, `softfloat.o' can easily be put into its own library (typically
|
||||
`softfloat.a' or `libsoftfloat.a') using the usual system tool (in UNIX,
|
||||
`ar').
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Testing SoftFloat
|
||||
|
||||
SoftFloat can be tested using the `testsoftfloat' program by the same
|
||||
author. The `testsoftfloat' program is part of the TestFloat package
|
||||
available at the Web page `http://www.jhauser.us/arithmetic/TestFloat.html'.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Timing SoftFloat
|
||||
|
||||
A program called `timesoftfloat' for timing the SoftFloat functions is
|
||||
included with the SoftFloat source code. Compiling `timesoftfloat' should
|
||||
pose no difficulties once `softfloat.o' exists. The supplied Makefile
|
||||
will create a `timesoftfloat' executable by default after generating
|
||||
`softfloat.o'. See `timesoftfloat.txt' for documentation about using
|
||||
`timesoftfloat'.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Compiler Options and Efficiency
|
||||
|
||||
In order to get good speed with SoftFloat, it is important that the compiler
|
||||
inline the routines that have been marked `INLINE' in the code. Even if
|
||||
inlining cannot be forced by an appropriate definition of the `INLINE'
|
||||
macro, the compiler may still be able to perform inlining on its own as
|
||||
an optimization. In that case, the Makefile should be edited to give the
|
||||
compiler whatever option is required to cause it to inline small functions.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'
|
||||
|
||||
The `softfloat-macros' source fragment defines arithmetic functions used
|
||||
as primitives by `softfloat.c'. This file has been written in a target-
|
||||
independent form. For a given target, it may be possible to improve on
|
||||
these functions using target-specific and/or non-ISO-C features (such
|
||||
as `asm' statements). For example, one of the "macro" functions takes
|
||||
two word-size integers and returns their full product in two words.
|
||||
This operation can be done directly in hardware on many processors; but
|
||||
because it is not available through standard C, the function defined in
|
||||
`softfloat-macros' uses four multiplications to achieve the same result.
|
||||
|
||||
To address these shortcomings, a customized version of `softfloat-macros'
|
||||
can be created in any of the target-specific subdirectories. A simple
|
||||
modification to the target's Makefile should be sufficient to ensure that
|
||||
the custom version is used instead of the generic one.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Contact Information
|
||||
|
||||
At the time of this writing, the most up-to-date information about SoftFloat
|
||||
and the latest release can be found at the Web page `http://www.jhauser.us/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
241
libsrc/float/softfloat/specialize.h
Normal file
241
libsrc/float/softfloat/specialize.h
Normal file
|
@ -0,0 +1,241 @@
|
|||
|
||||
/*============================================================================
|
||||
|
||||
This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
|
||||
Arithmetic Package, Release 2c, by John R. Hauser.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
|
||||
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
|
||||
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
|
||||
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
|
||||
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
|
||||
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
|
||||
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
|
||||
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
|
||||
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
|
||||
SOFTWARE.
|
||||
|
||||
Derivative works require also that (1) the source code for the derivative work
|
||||
includes prominent notice that the work is derivative, and (2) the source code
|
||||
includes prominent notice of these three paragraphs for those parts of this
|
||||
code that are retained.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Underflow tininess-detection mode, statically initialized to default value.
|
||||
| (The declaration in `softfloat.h' must match the `int8' type here.)
|
||||
*----------------------------------------------------------------------------*/
|
||||
int8 float_detect_tininess = float_tininess_after_rounding;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Raises the exceptions specified by `flags'. Floating-point traps can be
|
||||
| defined here if desired. It is currently not possible for such a trap
|
||||
| to substitute a result value. If traps are not implemented, this routine
|
||||
| should be simply `float_exception_flags |= flags;'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void float_raise( int8 flags )
|
||||
{
|
||||
|
||||
float_exception_flags |= flags;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Internal canonical NaN format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
flag sign;
|
||||
bits32 high, low;
|
||||
} commonNaNT;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated single-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float32_default_nan = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the single-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float32_is_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( 0xFF000000 < (bits32) ( a<<1 ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the single-precision floating-point value `a' is a signaling
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float32_is_signaling_nan( float32 a )
|
||||
{
|
||||
|
||||
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the single-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static commonNaNT *float32ToCommonNaN( float32 a )
|
||||
{
|
||||
static commonNaNT z;
|
||||
|
||||
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a>>31;
|
||||
z.low = 0;
|
||||
z.high = a<<9;
|
||||
return &z;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the single-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float32 commonNaNToFloat32( commonNaNT *a )
|
||||
{
|
||||
|
||||
return ( ( (bits32) a->sign )<<31 ) | 0x7FC00000 | ( a->high>>9 );
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two single-precision floating-point values `a' and `b', one of which
|
||||
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float32 propagateFloat32NaN( float32 a, float32 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float32_is_nan( a );
|
||||
aIsSignalingNaN = float32_is_signaling_nan( a );
|
||||
bIsNaN = float32_is_nan( b );
|
||||
bIsSignalingNaN = float32_is_signaling_nan( b );
|
||||
a |= 0x00400000;
|
||||
b |= 0x00400000;
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef DOUBLES
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated double-precision NaN. The `high' and
|
||||
| `low' values hold the most- and least-significant bits, respectively.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float64_default_nan_high = 0xFFFFFFFF,
|
||||
float64_default_nan_low = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the double-precision floating-point value `a' is a NaN;
|
||||
| otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float64_is_nan( float64 a )
|
||||
{
|
||||
|
||||
return
|
||||
( 0xFFE00000 <= (bits32) ( a.high<<1 ) )
|
||||
&& ( a.low || ( a.high & 0x000FFFFF ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns 1 if the double-precision floating-point value `a' is a signaling
|
||||
| NaN; otherwise returns 0.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
flag float64_is_signaling_nan( float64 a )
|
||||
{
|
||||
|
||||
return
|
||||
( ( ( a.high>>19 ) & 0xFFF ) == 0xFFE )
|
||||
&& ( a.low || ( a.high & 0x0007FFFF ) );
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the double-precision floating-point NaN
|
||||
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
|
||||
| exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static commonNaNT float64ToCommonNaN( float64 a )
|
||||
{
|
||||
commonNaNT z;
|
||||
|
||||
if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
|
||||
z.sign = a.high>>31;
|
||||
shortShift64Left( a.high, a.low, 12, &z.high, &z.low );
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns the result of converting the canonical NaN `a' to the double-
|
||||
| precision floating-point format.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float64 commonNaNToFloat64( commonNaNT a )
|
||||
{
|
||||
float64 z;
|
||||
|
||||
shift64Right( a.high, a.low, 12, &z.high, &z.low );
|
||||
z.high |= ( ( (bits32) a.sign )<<31 ) | 0x7FF80000;
|
||||
return z;
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes two double-precision floating-point values `a' and `b', one of which
|
||||
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
|
||||
| signaling NaN, the invalid exception is raised.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static float64 propagateFloat64NaN( float64 a, float64 b )
|
||||
{
|
||||
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
|
||||
|
||||
aIsNaN = float64_is_nan( a );
|
||||
aIsSignalingNaN = float64_is_signaling_nan( a );
|
||||
bIsNaN = float64_is_nan( b );
|
||||
bIsSignalingNaN = float64_is_signaling_nan( b );
|
||||
a.high |= 0x00080000;
|
||||
b.high |= 0x00080000;
|
||||
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
|
||||
if ( aIsNaN ) {
|
||||
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
4
libsrc/float/softmath/readme.txt
Normal file
4
libsrc/float/softmath/readme.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
This is a collection of various math related functions found in math.h. All
|
||||
functions are single precision (only), and are rather selected for their
|
||||
compactness than speed.
|
72
libsrc/float/softmath/softmath-atanf.c
Normal file
72
libsrc/float/softmath/softmath-atanf.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#if 1
|
||||
/* atan(x)= x(c1 + c2*x**2 + c3*x**4)/(c4 + c5*x**2 + c6*x**4 + x**6)
|
||||
|
||||
Accurate to about 13.7 decimal digits over the range [0, pi/12]. */
|
||||
float _atan(float x)
|
||||
{
|
||||
const float c1= 48.70107004404898384f;
|
||||
const float c2= 49.5326263772254345f;
|
||||
const float c3= 9.40604244231624f;
|
||||
const float c4= 48.70107004404996166f;
|
||||
const float c5= 65.7663163908956299f;
|
||||
const float c6= 21.587934067020262f;
|
||||
|
||||
float x2;
|
||||
x2 = x * x;
|
||||
return (x * (c1 + x2 * (c2 + x2 * c3)) / (c4 + x2 * (c5 + x2 * (c6 + x2))));
|
||||
}
|
||||
|
||||
#define TAN_SIXTHPI 0.009138776996f
|
||||
#define TAN_TWELFTHPI 0.004569293096f
|
||||
|
||||
float atanf(float x)
|
||||
{
|
||||
float y;
|
||||
int complement= 0; // true if arg was >1
|
||||
int region= 0; // true depending on region arg is in
|
||||
int sign= 0; // true if arg was < 0
|
||||
|
||||
if (x < 0.0f ) {
|
||||
// x = -x;
|
||||
// x = x * -1.0f;
|
||||
x = -1.0f * x;
|
||||
sign = 1; // arctan(-x)=-arctan(x)
|
||||
}
|
||||
if (x > 1.0f) {
|
||||
x = 1.0f / x; // keep arg between 0 and 1
|
||||
complement = 1;
|
||||
}
|
||||
if (x > TAN_TWELFTHPI) {
|
||||
/* FIXME: reduce arg to under tan(pi/12) */
|
||||
#if 1
|
||||
float n, m;
|
||||
n = (TAN_SIXTHPI * x) + 1.0f;
|
||||
m = (x - TAN_SIXTHPI);
|
||||
// x = (x - TAN_SIXTHPI) / (1.0f + (TAN_SIXTHPI * x));
|
||||
x = m / n;
|
||||
#else
|
||||
x = fmodf(x, TAN_SIXTHPI);
|
||||
#endif
|
||||
region = 1;
|
||||
}
|
||||
|
||||
y = _atan(x);
|
||||
|
||||
if (region) { y += (M_PI / 6.0f); } /* correct for region we're in */
|
||||
if (complement) { y= (M_PI / 2.0f) - y; } /* correct for 1/x */
|
||||
if (sign) { y =- y; } /* correct for negative arg */
|
||||
return y;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
float atanf(float x)
|
||||
{
|
||||
x = x;
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
|
14
libsrc/float/softmath/softmath-ceilf.c
Normal file
14
libsrc/float/softmath/softmath-ceilf.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
/* FIXME: this is really too simple */
|
||||
float ceilf(float x)
|
||||
{
|
||||
int n = (int) x;
|
||||
|
||||
if (n >= x) {
|
||||
return n;
|
||||
}
|
||||
|
||||
return n + 1;
|
||||
}
|
67
libsrc/float/softmath/softmath-cosf.c
Normal file
67
libsrc/float/softmath/softmath-cosf.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
|
||||
/* nicked from https://github.com/AZHenley/cosine/blob/master/cosine.c */
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Austin Henley
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define RUNTERMS 8
|
||||
float cosf(float x)
|
||||
{
|
||||
int i;
|
||||
int div;
|
||||
float num;
|
||||
float result = 1.0f;
|
||||
float inter = 1.0f;
|
||||
float comp;
|
||||
float den;
|
||||
|
||||
div = (int)(x / M_PI);
|
||||
|
||||
x = x - (div * M_PI);
|
||||
|
||||
num = x * x;
|
||||
for (i = 1; i <= RUNTERMS; i++) {
|
||||
comp = 2.0f * i;
|
||||
den = comp * (comp - 1.0f);
|
||||
inter *= num / den;
|
||||
if (i % 2 == 0) {
|
||||
result += inter;
|
||||
} else {
|
||||
result -= inter;
|
||||
}
|
||||
}
|
||||
|
||||
if (div % 2 != 0) {
|
||||
return result * -1.0f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
float cosf(float x) {
|
||||
return sinf(x + (M_PI / 2.0));
|
||||
}
|
||||
#endif
|
73
libsrc/float/softmath/softmath-expf.c
Normal file
73
libsrc/float/softmath/softmath-expf.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#if 1
|
||||
|
||||
/* natural logarithm of 2 */
|
||||
#define LN2 0.693147180559945309417f
|
||||
|
||||
// #include <stdio.h>
|
||||
// char abuf[100];
|
||||
// char abuf2[100];
|
||||
// char abuf3[100];
|
||||
|
||||
float expf(float x)
|
||||
{
|
||||
float p;
|
||||
int i;
|
||||
int k;
|
||||
// float i;
|
||||
// float k;
|
||||
|
||||
float r;
|
||||
float tn;
|
||||
float x0 = fabsf(x); // FIXME: somehow this doesnt work!
|
||||
|
||||
if (x == 0) {
|
||||
return 1;
|
||||
}
|
||||
x0 = fabsf(x);
|
||||
// printf("x:%s x0:%s\n", _ftostr(abuf3, x), _ftostr(abuf, x0));
|
||||
|
||||
k = ceilf((x0 / LN2) - 0.5f);
|
||||
p = (float)(1 << (int)k);
|
||||
r = x0 - (LN2 * (float)k); // internal error
|
||||
tn = 1.0f;
|
||||
// printf("k:%s tn:%s r:%s\n", _ftostr(abuf3, k), _ftostr(abuf, tn), _ftostr(abuf2, r ));
|
||||
|
||||
for (i = 14; i > 0; --i) {
|
||||
//tn = tn * (r / (float)i) + 1.0f;
|
||||
float tmp;
|
||||
tmp = (r / (float)i);
|
||||
tn = tn * tmp;
|
||||
tn = tn + 1.0f;
|
||||
// printf("i:%d tn:%s tmp:%s\n", i, _ftostr(abuf, tn), _ftostr(abuf2, tmp ));
|
||||
}
|
||||
|
||||
p *= tn;
|
||||
|
||||
if (x < 0) {
|
||||
return 1.0f / p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static float expf(float n) {
|
||||
int a = 0, b = n > 0;
|
||||
float c = 1, d = 1, e = 1;
|
||||
for (b || (n = -n); e + .00001 < (e += (d *= n) / (c *= ++a));); // "Floating point type is currently unsupported"
|
||||
// for (b || (n = -n); e + .00001 < (e = e + (d *= n) / (c *= ++a));); // "Floating point type is currently unsupported"
|
||||
// approximately 15 iterations
|
||||
return b ? e : 1 / e;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
float expf(float x)
|
||||
{
|
||||
x = x;
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
6
libsrc/float/softmath/softmath-fabsf.c
Normal file
6
libsrc/float/softmath/softmath-fabsf.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
float fabsf(float x) {
|
||||
return x < 0.0f ? -x : x;
|
||||
}
|
17
libsrc/float/softmath/softmath-floorf.c
Normal file
17
libsrc/float/softmath/softmath-floorf.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
/* FIXME: this is really too simple */
|
||||
float ffloor(float x)
|
||||
{
|
||||
signed long n;
|
||||
float d;
|
||||
|
||||
n = (signed long)x;
|
||||
d = (float)n;
|
||||
|
||||
if (x >= 0) {
|
||||
return d;
|
||||
}
|
||||
return d - 1;
|
||||
}
|
9
libsrc/float/softmath/softmath-fmodf.c
Normal file
9
libsrc/float/softmath/softmath-fmodf.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
float fmodf(float x, float y)
|
||||
{
|
||||
float res;
|
||||
res = x / y;
|
||||
return x - (truncf(res) * y);
|
||||
}
|
130
libsrc/float/softmath/softmath-logf.c
Normal file
130
libsrc/float/softmath/softmath-logf.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include <math.h>
|
||||
|
||||
/* natural logarithm */
|
||||
|
||||
#if 1
|
||||
/*#define LOGBASE 10*/
|
||||
#define LOGBASE 2 /* e=2.7182818... */
|
||||
float logf(float x)
|
||||
{
|
||||
int i;
|
||||
float alpha;
|
||||
float save;
|
||||
float ans;
|
||||
|
||||
alpha = (x-1)/(x+1);
|
||||
ans = alpha;
|
||||
save = ans * alpha * alpha;
|
||||
|
||||
for (i = 2 ; i <= LOGBASE ; i++) {
|
||||
ans += (1.0/(float)(2*i-1)) * save;
|
||||
save = save * alpha * alpha;
|
||||
}
|
||||
|
||||
return 2.0*ans;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static int msb(int a)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
while(a >>= 1) {
|
||||
r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
float logf(float y)
|
||||
{
|
||||
float result;
|
||||
int log2;
|
||||
float divisor, x;
|
||||
|
||||
log2 = msb((int)y);
|
||||
divisor = (float)(1 << log2);
|
||||
x = y / divisor;
|
||||
|
||||
result = -1.7417939f + (2.8212026f + (-1.4699568f + (0.44717955f - 0.056570851f * x) * x) * x) * x;
|
||||
result += ((float)log2) * 0.69314718f; // ln(2) = 0.69314718
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
float logf(float x)
|
||||
{
|
||||
|
||||
// ASSUMING:
|
||||
// - non-denormalized numbers i.e. x > 2^−126
|
||||
// - integer is 32 bit. float is IEEE 32 bit.
|
||||
|
||||
// INSPIRED BY:
|
||||
// - https://stackoverflow.com/a/44232045
|
||||
// - http://mathonweb.com/help_ebook/html/algorithms.htm#ln
|
||||
// - https://en.wikipedia.org/wiki/Fast_inverse_square_root
|
||||
|
||||
// FORMULA:
|
||||
// x = m * 2^p =>
|
||||
// ln(x) = ln(m) + ln(2)p,
|
||||
|
||||
// first normalize the value to between 1.0 and 2.0
|
||||
// assuming normalized IEEE float
|
||||
// sign exp frac
|
||||
// 0b 0 [00000000] 00000000000000000000000
|
||||
// value = (-1)^s * M * 2 ^ (exp-127)
|
||||
//
|
||||
// exp = 127 for x = 1,
|
||||
// so 2^(exp-127) is the multiplier
|
||||
|
||||
// evil floating point bit level hacking
|
||||
unsigned long bx = * (unsigned long *) (&x);
|
||||
|
||||
// extract exp, since x>0, sign bit must be 0
|
||||
unsigned long ex = bx >> 23;
|
||||
signed long t = (signed long)ex-(signed long)127;
|
||||
unsigned long s = (t < 0) ? (-t) : t;
|
||||
|
||||
// reinterpret back to float
|
||||
// 127 << 23 = 1065353216
|
||||
// 0b11111111111111111111111 = 8388607
|
||||
bx = 1065353216 | (bx & 8388607);
|
||||
x = * (float *) (&bx);
|
||||
|
||||
|
||||
// use remez algorithm to find approximation between [1,2]
|
||||
// - see this answer https://stackoverflow.com/a/44232045
|
||||
// - or this usage of C++/boost's remez implementation
|
||||
// https://computingandrecording.wordpress.com/2017/04/24/
|
||||
// e.g.
|
||||
// boost::math::tools::remez_minimax<double> approx(
|
||||
// [](const double& x) { return log(x); },
|
||||
// 4, 0, 1, 2, false, 0, 0, 64);
|
||||
//
|
||||
// 4th order is:
|
||||
// { -1.74178, 2.82117, -1.46994, 0.447178, -0.0565717 }
|
||||
//
|
||||
// 3rd order is:
|
||||
// { -1.49278, 2.11263, -0.729104, 0.10969 }
|
||||
|
||||
return
|
||||
|
||||
/* less accurate */
|
||||
-1.49278+(2.11263+(-0.729104+0.10969*x)*x)*x
|
||||
|
||||
/* OR more accurate */
|
||||
// -1.7417939+(2.8212026+(-1.4699568+(0.44717955-0.056570851*x)*x)*x)*x
|
||||
|
||||
/* compensate for the ln(2)s. ln(2)=0.6931471806 */
|
||||
+ 0.6931471806*t;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
float logf(float y)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
7
libsrc/float/softmath/softmath-powf.c
Normal file
7
libsrc/float/softmath/softmath-powf.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
float powf(float x, float y)
|
||||
{
|
||||
return expf(x * logf(y));
|
||||
}
|
11
libsrc/float/softmath/softmath-roundf.c
Normal file
11
libsrc/float/softmath/softmath-roundf.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
/* FIXME: this is really too simple */
|
||||
float roundf(float x)
|
||||
{
|
||||
if (x > 0.0f) {
|
||||
return (float)((signed long)(x + 0.5f));
|
||||
}
|
||||
return (float)((signed long)(x - 0.5f));
|
||||
}
|
6
libsrc/float/softmath/softmath-sinf.c
Normal file
6
libsrc/float/softmath/softmath-sinf.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
float sinf(float x) {
|
||||
return cosf(x - (M_PI / 2.0));
|
||||
}
|
90
libsrc/float/softmath/softmath-sqrtf.c
Normal file
90
libsrc/float/softmath/softmath-sqrtf.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#if 1
|
||||
static float powerOfTen(int num)
|
||||
{
|
||||
int i;
|
||||
// float rst = 1.0f;
|
||||
float rst;
|
||||
rst = 1.0f;
|
||||
if(num >= 0) {
|
||||
for(i = 0; i < num ; ++i) {
|
||||
// rst *= 10.0;
|
||||
rst = rst * 10.0f;
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < (0 - num); ++i) {
|
||||
// rst *= 0.1;
|
||||
rst = rst * 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
return rst;
|
||||
}
|
||||
|
||||
#define MAXDIGITS 8
|
||||
float sqrtf(float a)
|
||||
{
|
||||
// float rst = 0.0f;
|
||||
float rst;
|
||||
// float z = a;
|
||||
float z;
|
||||
signed int i;
|
||||
// float j = 1.0f;
|
||||
float j;
|
||||
float power;
|
||||
rst = 0.0f;
|
||||
z = a;
|
||||
j = 1.0f;
|
||||
for(i = MAXDIGITS ; i > 0 ; i--) {
|
||||
power = powerOfTen(i);
|
||||
// value must be bigger then 0
|
||||
if(z - (( 2.0f * rst ) + ( j * power)) * ( j * power) >= 0) {
|
||||
while( z - (( 2.0f * rst ) + ( j * power)) * ( j * power) >= 0) {
|
||||
//j++;
|
||||
j = j + 1.0f;
|
||||
if(j >= 10.0f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//j--; //correct the extra value by minus one to j
|
||||
j = j - 1.0f;
|
||||
//z -= (( 2.0f * rst ) + ( j * power)) * ( j * power); //find value of z
|
||||
z = z - (( 2.0f * rst ) + ( j * power)) * ( j * power); //find value of z
|
||||
|
||||
//rst += j * power; // find sum of a
|
||||
rst = rst + (j * power); // find sum of a
|
||||
j = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0 ; i >= 0 - MAXDIGITS ; i--) {
|
||||
power = powerOfTen(i);
|
||||
if(z - (( 2.0f * rst ) + ( j * power))*( j * power) >= 0) {
|
||||
while( z - (( 2.0f * rst ) + ( j * power))*( j * power) >= 0) {
|
||||
//j++;
|
||||
j = j + 1.0f;
|
||||
if(j >= 10.0f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//j--; //correct the extra value by minus one to j
|
||||
j = j - 1.0f;
|
||||
//z -= (( 2.0f * rst ) + ( j * power))*( j * power); //find value of z
|
||||
z = z - (( 2.0f * rst ) + ( j * power)) * ( j * power); //find value of z
|
||||
//rst += j * power; // find sum of a
|
||||
rst = rst + (j * power); // find sum of a
|
||||
j = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// find the number on each digit
|
||||
return rst;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
float sqrtf(float a)
|
||||
{
|
||||
a = a;
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
52
libsrc/float/softmath/softmath-tanf.c
Normal file
52
libsrc/float/softmath/softmath-tanf.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#if 1
|
||||
/* The input argument is in radians. Note that the function
|
||||
computes tan(pi*x/4), NOT tan(x); it's up to the range
|
||||
reduction algorithm that calls this to scale things properly.
|
||||
|
||||
Algorithm:
|
||||
tan(x)= x(c1 + c2*x**2 + c3*x**4)/(c4 + c5*x**2 + c6*x**4 + x**6)
|
||||
|
||||
Accurate to about 14 decimal digits over the range [0, pi/4]. */
|
||||
static float _tan(float x)
|
||||
{
|
||||
const float c1=-34287.4662577359568109624f;
|
||||
const float c2= 2566.7175462315050423295f;
|
||||
const float c3=- 26.5366371951731325438f;
|
||||
const float c4=-43656.1579281292375769579f;
|
||||
const float c5= 12244.4839556747426927793f;
|
||||
const float c6=- 336.611376245464339493f;
|
||||
|
||||
float x2;
|
||||
|
||||
x2 = x * x;
|
||||
return (x * (c1 + x2 * (c2 + x2 * c3)) / (c4 + x2 * (c5 + x2 * (c6 + x2))));
|
||||
}
|
||||
|
||||
float tanf(float x){
|
||||
int octant;
|
||||
|
||||
x = fmodf(x, (2.0f * M_PI));
|
||||
octant=(int)(x * (4.0f / M_PI));
|
||||
switch (octant){
|
||||
case 0: return _tan(x * (4.0f / M_PI));
|
||||
case 1: return 1.0f / _tan(((M_PI / 2.0f) - x) * (4.0f / M_PI));
|
||||
case 2: return -1.0f / _tan((x - (M_PI / 2.0f)) * (4.0f / M_PI));
|
||||
case 3: return - _tan((M_PI - x) * (4.0f / M_PI));
|
||||
case 4: return _tan((x - M_PI) * (4.0f / M_PI));
|
||||
case 5: return 1.0f / _tan(((3.0f * M_PI / 2.0f) - x) * (4.0f / M_PI));
|
||||
case 6: return -1.0f / _tan((x - (3.0f * M_PI / 2.0f)) * (4.0f / M_PI));
|
||||
case 7: return - _tan(((2.0f * M_PI)-x) * (4.0f / M_PI));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
float tanf(float x)
|
||||
{
|
||||
x = x;
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
8
libsrc/float/softmath/softmath-truncf.c
Normal file
8
libsrc/float/softmath/softmath-truncf.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
/* FIXME: this is really too simple */
|
||||
float truncf(float x)
|
||||
{
|
||||
return (float)((signed long)x);
|
||||
}
|
66
libsrc/vic20/extra/fp754kernal.s
Normal file
66
libsrc/vic20/extra/fp754kernal.s
Normal file
|
@ -0,0 +1,66 @@
|
|||
|
||||
; import/overload stubs for the VIC20 kernal floating point implementation
|
||||
|
||||
.import ___cbmkernal_afloat
|
||||
.import ___cbmkernal_aufloat
|
||||
.import ___cbmkernal_axfloat
|
||||
.import ___cbmkernal_axufloat
|
||||
.import ___cbmkernal_eaxfloat
|
||||
.import ___cbmkernal_eaxufloat
|
||||
.import ___cbmkernal_feaxint
|
||||
.import ___cbmkernal_feaxlong
|
||||
.import ___cbmkernal_fbnegeax
|
||||
.import ___cbmkernal_ftosaddeax
|
||||
.import ___cbmkernal_ftossubeax
|
||||
.import ___cbmkernal_ftosdiveax
|
||||
.import ___cbmkernal_ftosmuleax
|
||||
.import ___cbmkernal_ftoseqeax
|
||||
.import ___cbmkernal_ftosneeax
|
||||
.import ___cbmkernal_ftosgteax
|
||||
.import ___cbmkernal_ftoslteax
|
||||
.import ___cbmkernal_ftosgeeax
|
||||
.import ___cbmkernal_ftosleeax
|
||||
|
||||
.export afloat := ___cbmkernal_afloat
|
||||
.export aufloat := ___cbmkernal_aufloat
|
||||
.export axfloat := ___cbmkernal_axfloat
|
||||
.export axufloat := ___cbmkernal_axufloat
|
||||
.export eaxfloat := ___cbmkernal_eaxfloat
|
||||
.export eaxufloat := ___cbmkernal_eaxufloat
|
||||
.export feaxint := ___cbmkernal_feaxint
|
||||
.export feaxlong := ___cbmkernal_feaxlong
|
||||
.export fbnegeax := ___cbmkernal_fbnegeax
|
||||
.export ftosaddeax := ___cbmkernal_ftosaddeax
|
||||
.export ftossubeax := ___cbmkernal_ftossubeax
|
||||
.export ftosdiveax := ___cbmkernal_ftosdiveax
|
||||
.export ftosmuleax := ___cbmkernal_ftosmuleax
|
||||
.export ftoseqeax := ___cbmkernal_ftoseqeax
|
||||
.export ftosneeax := ___cbmkernal_ftosneeax
|
||||
.export ftosgteax := ___cbmkernal_ftosgteax
|
||||
.export ftoslteax := ___cbmkernal_ftoslteax
|
||||
.export ftosgeeax := ___cbmkernal_ftosgeeax
|
||||
.export ftosleeax := ___cbmkernal_ftosleeax
|
||||
|
||||
.import ___cbmkernal_powf
|
||||
.import ___cbmkernal_sinf
|
||||
.import ___cbmkernal_cosf
|
||||
.import ___cbmkernal_logf
|
||||
.import ___cbmkernal_expf
|
||||
.import ___cbmkernal_sqrtf
|
||||
.import ___cbmkernal_tanf
|
||||
.import ___cbmkernal_atanf
|
||||
.import ___cbmkernal_fabsf
|
||||
.import ___cbmkernal_roundf
|
||||
.import ___cbmkernal_truncf
|
||||
|
||||
.export _powf := ___cbmkernal_powf
|
||||
.export _sinf := ___cbmkernal_sinf
|
||||
.export _cosf := ___cbmkernal_cosf
|
||||
.export _logf := ___cbmkernal_logf
|
||||
.export _expf := ___cbmkernal_expf
|
||||
.export _sqrtf := ___cbmkernal_sqrtf
|
||||
.export _tanf := ___cbmkernal_tanf
|
||||
.export _atanf := ___cbmkernal_atanf
|
||||
.export _fabsf := ___cbmkernal_fabsf
|
||||
.export _roundf := ___cbmkernal_roundf
|
||||
.export _truncf := ___cbmkernal_truncf
|
|
@ -164,9 +164,11 @@ EXELIST_apple2 = \
|
|||
checkversion \
|
||||
diodemo \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
mousedemo \
|
||||
multdemo \
|
||||
ovrldemo \
|
||||
|
@ -180,9 +182,11 @@ EXELIST_apple2enh = $(EXELIST_apple2)
|
|||
EXELIST_atari = \
|
||||
ascii \
|
||||
checkversion \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
mousedemo \
|
||||
multdemo \
|
||||
ovrldemo \
|
||||
|
@ -202,8 +206,10 @@ EXELIST_atari5200 = \
|
|||
EXELIST_atmos = \
|
||||
ascii \
|
||||
checkversion \
|
||||
floattest \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
sieve \
|
||||
terminal \
|
||||
tgidemo
|
||||
|
@ -215,24 +221,30 @@ EXELIST_c64 = \
|
|||
ascii \
|
||||
checkversion \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
mathtest \
|
||||
mousedemo \
|
||||
multdemo \
|
||||
ovrldemo \
|
||||
sieve \
|
||||
terminal \
|
||||
tinyshell \
|
||||
tgidemo
|
||||
tgidemo \
|
||||
tgisincos
|
||||
|
||||
EXELIST_c128 = \
|
||||
ascii \
|
||||
checkversion \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
mousedemo \
|
||||
sieve \
|
||||
terminal \
|
||||
|
@ -249,8 +261,10 @@ EXELIST_c16 = \
|
|||
EXELIST_cbm510 = \
|
||||
ascii \
|
||||
checkversion \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelfloat \
|
||||
mousedemo \
|
||||
terminal \
|
||||
tinyshell \
|
||||
|
@ -259,8 +273,10 @@ EXELIST_cbm510 = \
|
|||
EXELIST_cbm610 = \
|
||||
ascii \
|
||||
checkversion \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelfloat \
|
||||
terminal \
|
||||
tinyshell \
|
||||
sieve
|
||||
|
@ -273,9 +289,11 @@ EXELIST_cx16 = \
|
|||
ascii \
|
||||
checkversion \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
mousedemo \
|
||||
sieve \
|
||||
tinyshell \
|
||||
|
@ -311,7 +329,9 @@ EXELIST_pet = \
|
|||
ascii \
|
||||
checkversion \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
hello \
|
||||
mandelfloat \
|
||||
tinyshell \
|
||||
sieve
|
||||
|
||||
|
@ -319,8 +339,10 @@ EXELIST_plus4 = \
|
|||
ascii \
|
||||
checkversion \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelfloat \
|
||||
terminal \
|
||||
tinyshell \
|
||||
sieve
|
||||
|
@ -343,9 +365,11 @@ EXELIST_kim1 = \
|
|||
EXELIST_telestrat = \
|
||||
ascii \
|
||||
checkversion \
|
||||
floattest \
|
||||
gunzip65 \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
sieve \
|
||||
tgidemo
|
||||
|
||||
|
@ -353,8 +377,10 @@ EXELIST_vic20 = \
|
|||
ascii \
|
||||
checkversion \
|
||||
enumdevdir \
|
||||
floattest \
|
||||
hello \
|
||||
mandelbrot \
|
||||
mandelfloat \
|
||||
sieve \
|
||||
tgidemo
|
||||
|
||||
|
@ -447,6 +473,22 @@ ovrldemo: overlaydemo.o
|
|||
|
||||
OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I)
|
||||
|
||||
# link float examples against the (much faster) kernal lib, if available
|
||||
ifeq ($(SYS),c64)
|
||||
floattest: override CFLAGS += -D DYN_DRV=0
|
||||
floattest: floattest.o
|
||||
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
|
||||
mandelfloat.o: override CFLAGS += -D DYN_DRV=0
|
||||
mandelfloat: mandelfloat.o
|
||||
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
|
||||
mathtest.o: override CFLAGS += -D DYN_DRV=0
|
||||
mathtest: mathtest.o
|
||||
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
|
||||
tgisincos.o: override CFLAGS += -D DYN_DRV=0
|
||||
tgisincos: tgisincos.o
|
||||
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
|
||||
endif
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# TGI programs on the VIC-20 need a special ld65 configuration file.
|
||||
|
||||
|
|
36
samples/floattest.c
Normal file
36
samples/floattest.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
char buf[100];
|
||||
|
||||
// quick check to see if printing float value works
|
||||
void constants(void)
|
||||
{
|
||||
printf("-100.0 %15s\n", _ftostr(buf, -100.0f));
|
||||
printf(" -10.0 %15s\n", _ftostr(buf, -10.0f));
|
||||
printf(" -1.0 %15s\n", _ftostr(buf, -1.0f));
|
||||
printf(" -0.1 %15s\n", _ftostr(buf, -0.1f));
|
||||
printf(" -0.01 %15s\n", _ftostr(buf, -0.01f));
|
||||
printf(" -0.001 %15s\n", _ftostr(buf, -0.001f));
|
||||
printf(" -0.0001 %15s\n", _ftostr(buf, -0.0001f));
|
||||
printf(" -0.00001 %15s\n", _ftostr(buf, -0.00001f));
|
||||
printf(" 0.0 %15s\n", _ftostr(buf, 0.0f));
|
||||
printf(" 0.1 %15s\n", _ftostr(buf, 0.1f));
|
||||
printf(" 0.01 %15s\n", _ftostr(buf, 0.01f));
|
||||
printf(" 0.001 %15s\n", _ftostr(buf, 0.001f));
|
||||
printf(" 0.0001 %15s\n", _ftostr(buf, 0.0001f));
|
||||
printf(" 0.00001 %15s\n", _ftostr(buf, 0.00001f));
|
||||
printf(" 1.0 %15s\n", _ftostr(buf, 1.0f));
|
||||
printf(" 10.0 %15s\n", _ftostr(buf, 10.0f));
|
||||
printf(" 100.0 %15s\n", _ftostr(buf, 100.0f));
|
||||
printf("<key>\n");
|
||||
// cgetc();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
constants();
|
||||
return 0;
|
||||
}
|
74
samples/mandelfloat.c
Normal file
74
samples/mandelfloat.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
/*
|
||||
* $ cl65 -o mandelfloat.prg mandelfloat.c
|
||||
*
|
||||
* use the CBM kernal fp routines like this:
|
||||
*
|
||||
* $ cl65 -o mandelfloat.prg mandelfloat.c c64-fp488kernal.o
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_ITER 40
|
||||
|
||||
#define XRES 20
|
||||
#define YRES 20
|
||||
|
||||
#define XMIN -2.25f
|
||||
#define XMAX 2.25f
|
||||
#define YMIN -2.25f
|
||||
#define YMAX 2.25f
|
||||
|
||||
// FIXME: Invalid operands for binary operator '-'
|
||||
// #define XRANGE (XMAX - XMIN)
|
||||
// #define YRANGE (YMAX - YMIN)
|
||||
#define XRANGE 4.5f
|
||||
#define YRANGE 4.5f
|
||||
|
||||
#define XSTEP (XRANGE / XRES)
|
||||
#define YSTEP (YRANGE / YRES)
|
||||
|
||||
char *colortab = ".+*#%$=-";
|
||||
|
||||
void color(int iterations) {
|
||||
if (iterations >= MAX_ITER) {
|
||||
putchar(' ');
|
||||
} else {
|
||||
putchar(colortab[iterations & 7]);
|
||||
}
|
||||
}
|
||||
|
||||
float x, y; /* Coordinates of the current point in the complex plane. */
|
||||
float u, v; /* Coordinates of the iterated point. */
|
||||
unsigned char i, j; /* Pixel counters */
|
||||
unsigned char k; /* Iteration counter */
|
||||
|
||||
float u, v;
|
||||
float u2, v2;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
for (j = 0; j < YRES; j++) {
|
||||
y = YMIN + j * YSTEP;
|
||||
for(i = 0; i < XRES; i++) {
|
||||
|
||||
u = 0.0f;
|
||||
v = 0.0f;
|
||||
u2 = 0.0f;
|
||||
v2 = 0.0f;
|
||||
x = i * XSTEP + XMIN;
|
||||
/* iterate the point */
|
||||
for (k = 1; (k < MAX_ITER) && ((u2 + v2) < 4.0f); ++k) {
|
||||
v = 2.0f * u * v + y;
|
||||
u = u2 - v2 + x;
|
||||
u2 = u * u;
|
||||
v2 = v * v;
|
||||
};
|
||||
color(k);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
218
samples/mathtest.c
Normal file
218
samples/mathtest.c
Normal file
|
@ -0,0 +1,218 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __CC65__
|
||||
#include <conio.h> // for cgetc
|
||||
#else
|
||||
#define cgetc()
|
||||
char *_ftostr(char *d, float s);
|
||||
#endif
|
||||
|
||||
#ifdef __SIM6502__
|
||||
#define cgetc()
|
||||
#endif
|
||||
|
||||
char buf[100];
|
||||
|
||||
/*
|
||||
float __fastcall__ sinf(float s);
|
||||
float __fastcall__ cosf(float s);
|
||||
float __fastcall__ tanf(float x);
|
||||
float __fastcall__ atanf(float x);
|
||||
*/
|
||||
|
||||
float atanvalues[8]= {
|
||||
0.50f, // 0.46
|
||||
-1.50f, // -0.98
|
||||
};
|
||||
|
||||
void sincostanatan(void)
|
||||
{
|
||||
int n;
|
||||
float angle = 0.0;
|
||||
// float angle = -M_PI;
|
||||
printf("sinus:\n");
|
||||
angle = 0.0;
|
||||
for (n = 0; n < 18; n++) {
|
||||
printf("%15s ", _ftostr(buf, angle));
|
||||
printf("%15s", _ftostr(buf, sinf(angle)));
|
||||
printf("\n");
|
||||
// angle += (M_PI / 8); Error: Invalid left operand for binary operator '+='
|
||||
angle = angle + ((M_PI * 2.0f) / 16);
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
printf("cosinus:\n");
|
||||
angle = 0.0;
|
||||
for (n = 0; n < 18; n++) {
|
||||
printf("%15s ", _ftostr(buf, angle));
|
||||
printf("%15s", _ftostr(buf, cosf(angle)));
|
||||
printf("\n");
|
||||
// angle += (M_PI / 8); Error: Invalid left operand for binary operator '+='
|
||||
angle = angle + ((M_PI * 2.0f) / 16);
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
printf("tangens:\n");
|
||||
angle = 0.0;
|
||||
for (n = 0; n < 18; n++) {
|
||||
printf("%15s ", _ftostr(buf, angle));
|
||||
printf("%15s", _ftostr(buf, tanf(angle)));
|
||||
printf("\n");
|
||||
// angle += (M_PI / 8); Error: Invalid left operand for binary operator '+='
|
||||
angle = angle + ((M_PI * 2.0f) / 16);
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
printf("atan:\n");
|
||||
angle = 0.0;
|
||||
for (n = 0; n < 2; n++) {
|
||||
printf("%15s ", _ftostr(buf, atanvalues[n]));
|
||||
printf("%15s", _ftostr(buf, atanf(atanvalues[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
}
|
||||
|
||||
/*
|
||||
float __fastcall__ roundf(float x);
|
||||
float __fastcall__ truncf(float x);
|
||||
float __fastcall__ fabsf(float x);
|
||||
*/
|
||||
|
||||
float roundtruncvals[22] = {
|
||||
2.0f,
|
||||
1.9f,
|
||||
1.5f,
|
||||
1.4f,
|
||||
1.1f,
|
||||
1.0f,
|
||||
0.9f,
|
||||
0.5f, // 1.0
|
||||
0.4f,
|
||||
0.1f,
|
||||
0.0f,
|
||||
-0.1f,
|
||||
-0.4f,
|
||||
-0.5f, // -1.0
|
||||
-0.501f, // -1.0
|
||||
-0.9f,
|
||||
-1.0f,
|
||||
-1.1f,
|
||||
-1.4f,
|
||||
-1.5f,
|
||||
-1.5001f,
|
||||
-1.9f,
|
||||
// -2.0f,
|
||||
// -2.1f,
|
||||
};
|
||||
|
||||
void roundtruncabs(void)
|
||||
{
|
||||
int n;
|
||||
printf("round/trunc:\n");
|
||||
for (n = 0; n < 21; n++) {
|
||||
printf("%12s", _ftostr(buf, roundtruncvals[n]));
|
||||
printf("%12s", _ftostr(buf, roundf(roundtruncvals[n])));
|
||||
printf("%12s", _ftostr(buf, truncf(roundtruncvals[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
printf("abs/ceil:\n");
|
||||
for (n = 0; n < 21; n++) {
|
||||
printf("%12s", _ftostr(buf, roundtruncvals[n]));
|
||||
printf("%12s", _ftostr(buf, fabsf(roundtruncvals[n])));
|
||||
printf("%12s", _ftostr(buf, ceilf(roundtruncvals[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
}
|
||||
|
||||
/*
|
||||
float __fastcall__ powf(float f, float a);
|
||||
float __fastcall__ sqrtf(float x);
|
||||
*/
|
||||
float powvals0[8] = {
|
||||
2,
|
||||
10,
|
||||
2,
|
||||
10
|
||||
};
|
||||
|
||||
float powvals1[8] = {
|
||||
3,
|
||||
3,
|
||||
4,
|
||||
4
|
||||
};
|
||||
|
||||
float sqrtvals[8] = {
|
||||
9,
|
||||
2,
|
||||
1,
|
||||
16,
|
||||
0,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
};
|
||||
|
||||
void powersqrt(void)
|
||||
{
|
||||
int n;
|
||||
printf("pow:\n");
|
||||
for (n = 0; n < 4; n++) {
|
||||
printf("%12s", _ftostr(buf, powvals0[n]));
|
||||
printf("%12s", _ftostr(buf, powvals1[n]));
|
||||
printf("%12s", _ftostr(buf, powf(powvals0[n], powvals1[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("sqrt:\n");
|
||||
for (n = 0; n < 8; n++) {
|
||||
printf("%12s", _ftostr(buf, sqrtvals[n]));
|
||||
printf("%12s", _ftostr(buf, sqrtf(sqrtvals[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
}
|
||||
|
||||
/*
|
||||
float __fastcall__ logf(float x);
|
||||
float __fastcall__ expf(float x);
|
||||
*/
|
||||
float logvals[8] = {
|
||||
1.0f, // 0
|
||||
5.6f, // 1.72
|
||||
10.0f, // 2.302585
|
||||
};
|
||||
|
||||
float expvals[8] = {
|
||||
12.0f, // 162754.79
|
||||
5.0f, // 148.413159
|
||||
4.0f, // 54.598150
|
||||
3.0f, // 20.085537
|
||||
};
|
||||
|
||||
void logexp(void)
|
||||
{
|
||||
int n;
|
||||
printf("log:\n");
|
||||
for (n = 0; n < 3; n++) {
|
||||
printf("%12s", _ftostr(buf, logvals[n]));
|
||||
printf("%12s", _ftostr(buf, logf(logvals[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("exp:\n");
|
||||
for (n = 0; n < 4; n++) {
|
||||
printf("%12s", _ftostr(buf, expvals[n]));
|
||||
printf("%12s", _ftostr(buf, expf(expvals[n])));
|
||||
printf("\n");
|
||||
}
|
||||
printf("<key>\n"); cgetc();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
roundtruncabs();
|
||||
sincostanatan();
|
||||
logexp();
|
||||
powersqrt();
|
||||
}
|
|
@ -81,6 +81,18 @@ Platforms: Runs on all platforms that have TGI support:
|
|||
Apple ][, Atari, C64, C128, Oric Atmos and Telestrat, GEOS,
|
||||
and NES.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Name: mandelfloat
|
||||
Description: A very simple mandelbrot calculator, which uses floats and out-
|
||||
puts the result to console.
|
||||
Platforms: Runs on all platforms that have putchar();
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Name: mathtest
|
||||
Description: Uses the floating point math.h functions to plot some more or
|
||||
less interesting pattern
|
||||
Platforms: Runs on all platforms that have putchar();
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Name: mousedemo
|
||||
Description: Shows how to use the mouse.
|
||||
|
|
362
samples/tgisincos.c
Normal file
362
samples/tgisincos.c
Normal file
|
@ -0,0 +1,362 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <cc65.h>
|
||||
#include <conio.h>
|
||||
#include <ctype.h>
|
||||
#include <modload.h>
|
||||
#include <tgi.h>
|
||||
|
||||
char buf[100]; // for ftostr
|
||||
char buf2[100]; // for ftostr
|
||||
char buf3[100]; // for ftostr
|
||||
|
||||
|
||||
#ifndef DYN_DRV
|
||||
# define DYN_DRV 1
|
||||
#endif
|
||||
|
||||
#define COLOR_BACK TGI_COLOR_BLACK
|
||||
#define COLOR_FORE TGI_COLOR_WHITE
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Driver stuff */
|
||||
static unsigned MaxX;
|
||||
static unsigned MaxY;
|
||||
static unsigned AspectRatio;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
static void CheckError (const char* S)
|
||||
{
|
||||
unsigned char Error = tgi_geterror ();
|
||||
|
||||
if (Error != TGI_ERR_OK) {
|
||||
printf ("%s: %u\n", S, Error);
|
||||
if (doesclrscrafterexit ()) {
|
||||
cgetc ();
|
||||
}
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
#if DYN_DRV
|
||||
static void DoWarning (void)
|
||||
/* Warn the user that the dynamic TGI driver is needed for this program */
|
||||
{
|
||||
printf ("Warning: This program needs the TGI\n"
|
||||
"driver on disk! Press 'y' if you have\n"
|
||||
"it - any other key exits.\n");
|
||||
if (tolower (cgetc ()) != 'y') {
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
printf ("OK. Please wait patiently...\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLUE };
|
||||
|
||||
#if 1
|
||||
int XRes, YRes;
|
||||
float xf, xfMin, xfMax, xfDelta, yf, yfMin, yfMax, yfDelta;
|
||||
float radiusf, zf, zScale;
|
||||
int x,y;
|
||||
// unsigned char YMax;
|
||||
int YMax;
|
||||
unsigned int XResHalf;
|
||||
float yfMinSquare;
|
||||
|
||||
float yfD;
|
||||
float a;
|
||||
float b;
|
||||
float yfSquare;
|
||||
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
|
||||
void Dosincos(void) {
|
||||
#if 1
|
||||
tgi_setpalette (Palette);
|
||||
tgi_setcolor (COLOR_FORE);
|
||||
tgi_clear ();
|
||||
#endif
|
||||
/* Get stuff from the graph lib */
|
||||
XRes = tgi_getmaxx() + 1;
|
||||
// XRes = 320;
|
||||
YRes = tgi_getmaxy() + 1;
|
||||
// YRes = 200;
|
||||
YMax = YRes - 1;
|
||||
|
||||
|
||||
|
||||
/* Compute and draw a 3d function. */
|
||||
yfMin = -144.0f;
|
||||
yfMax = 144.0f;
|
||||
yf = 0;
|
||||
// printf("yf:%s\n", _ftostr(buf, yf));
|
||||
// printf("min:%s\n", _ftostr(buf, yfMin));
|
||||
// printf("max:%s\n", _ftostr(buf, yfMax));
|
||||
|
||||
yfDelta = 2.25f;
|
||||
zScale = -10.0f;
|
||||
|
||||
XResHalf = XRes * 0.5f;
|
||||
yfMinSquare = yfMin * yfMin;
|
||||
|
||||
yoff = 20;
|
||||
xoff = 0;
|
||||
|
||||
// for( yf = yfMin; yf < yfMax; yf += yfDelta) { // FIXME
|
||||
// for( yf = yfMin; yf < yfMax; yf = yf + yfDelta) { // FIXME
|
||||
for( yf = yfMin; yf < yfMax; yf = yfDelta + yf ) { // FIXME
|
||||
// printf("yf:%s min:%s max:%s\n", _ftostr(buf, yf), _ftostr(buf2, yfMin), _ftostr(buf3, yfMax));
|
||||
#if 0
|
||||
float yfD;
|
||||
float a;
|
||||
float b;
|
||||
float yfSquare;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* add some very fake perspective */
|
||||
yoff++;
|
||||
xoff--;
|
||||
#endif
|
||||
// xfMax = sqrtf( yfMinSquare - yf * yf);
|
||||
xfMax = sqrtf( yfMinSquare - (yf * yf));
|
||||
xfMin = -xfMax; // trigger fnegeax
|
||||
xfDelta = 1.0f;
|
||||
|
||||
// Constant terms from the inner loop
|
||||
yfD = yf / yfDelta;
|
||||
a = XResHalf + yfD;
|
||||
// b= YMax + yfD - 90;
|
||||
b= YMax + yfD - 90.0f;
|
||||
|
||||
yfSquare = yf * yf;
|
||||
|
||||
// for( xf = xfMin; xf < xfMax; xf += xfDelta) {
|
||||
for( xf = xfMin; xf < xfMax; xf = xf + xfDelta) {
|
||||
// printf("xf:%s xfmax:%s\n", _ftostr(buf2, xf), _ftostr(buf3, xfMax));
|
||||
|
||||
radiusf = .0327f * sqrtf( (xf * xf) + yfSquare);
|
||||
|
||||
zf = zScale * (cosf(7.7f * radiusf) +
|
||||
cosf(8.5f * radiusf) +
|
||||
cosf(9.3f * radiusf));
|
||||
|
||||
|
||||
/* Scale to screen coordinates */
|
||||
x = 1.0f * ( xf + a);
|
||||
x += xoff;
|
||||
|
||||
y = 0.8f * ( b - zf);
|
||||
y += yoff;
|
||||
//printf("x: %d y: %d\n", x, y);
|
||||
if( y > 0 && y < YRes) {
|
||||
|
||||
tgi_setpixel( x, y);
|
||||
|
||||
/* Clear horizon under y. */
|
||||
if( y < YMax) {
|
||||
tgi_setcolor (COLOR_BACK);
|
||||
tgi_line( x, y + 1, x, YMax);
|
||||
tgi_setcolor (COLOR_FORE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cgetc();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
5 dim xp, yp, r, fl, xr, yr, x, y, f
|
||||
6 dim ad, yq, xl, q
|
||||
7 m7 = 504
|
||||
e4 = 40
|
||||
8 yl = 200
|
||||
n1 = -1
|
||||
n5 = 0.5
|
||||
nh = 900
|
||||
eh = 100
|
||||
hs = 160
|
||||
sf = 3136
|
||||
vz = 196
|
||||
s = 1
|
||||
a = 7872
|
||||
10 dim bi(7), mi(319), ma(319), l(3000), p(30,120)
|
||||
|
||||
11 for t = 0 to 7
|
||||
bi(7-t) = s
|
||||
s = s + s
|
||||
next : rem bit table
|
||||
13 for t = 0 to yl
|
||||
if (7 and t) = 0 then a = a + 320
|
||||
14 l(t) = a
|
||||
next : rem line addr table
|
||||
15 for x = 0 to 319
|
||||
mi(x) = yl
|
||||
ma(x) = n1
|
||||
next : rem min/max buffer
|
||||
|
||||
19 for y = 30 to 0 step n1
|
||||
yq = y * y
|
||||
xp = int(4 * sqr(nh - yq) + n5)
|
||||
20 for x= 0 to xp
|
||||
r = sqr(x * x / sf + yq /vz)
|
||||
21 f = cos(r) - cos(3 * r) / 3 + cos(5 * r) / 5 - cos(7 * r) / 7
|
||||
p(y, x) = int(e4 * f + n5)
|
||||
22 fl = 0
|
||||
xp = hs + x - y
|
||||
yp = eh + y + y - p(y, x)
|
||||
23 if mi(xp) > yp then mi(xp) = yp: fl = 1
|
||||
24 if ma(xp) < yp then ma(xp) = yp: fl = 1
|
||||
25 if fl = 0 or yp < z or yp >= yl then 27
|
||||
26 ad = l(yp) + (xp and m7) + (yp and 7)
|
||||
poke ad, peek(ad) or bi(xp and 7)
|
||||
27 fl = 0
|
||||
xp = hs - x - y
|
||||
28 if mi(xp) > yp then mi(xp) = yp: fl = 1
|
||||
29 if ma(xp) < yp then ma(xp) = yp: fl = 1
|
||||
30 if fl = 0 or yp < z or yp >= yl then 32
|
||||
31 ad = l(yp) + (xp and m7) + (yp and 7)
|
||||
poke ad, peek(ad) or bi(xp and 7)
|
||||
32 next
|
||||
next
|
||||
|
||||
33 for y = -1 to -30 step n1
|
||||
yq = y * y
|
||||
xp = int(4 * sqr(nh - yq) + n5)
|
||||
35 for x = 0 to xp
|
||||
36 fl = 0
|
||||
xp = hs + x - y
|
||||
yp = eh + y + y - p(-y,x)
|
||||
37 if mi(xp) > yp then mi(xp) = yp: fl = 1
|
||||
38 if ma(xp) < yp then ma(xp) = yp: fl = 1
|
||||
39 if fl = 0 or yp < z or yp >= yl then 41
|
||||
40 ad = l(yp) + (xp and m7) + (yp and 7)
|
||||
poke ad, peek(ad) or bi(xp and 7)
|
||||
41 fl = 0
|
||||
xp = hs - x - y
|
||||
42 if mi(xp) > yp then mi(xp) = yp: fl = 1
|
||||
43 if ma(xp) < yp then ma(xp) = yp: fl = 1
|
||||
44 if fl = 0 or yp < z or yp >= yl then 46
|
||||
45 ad = l(yp) + (xp and m7) + (yp and 7)
|
||||
poke ad, peek(ad) or bi(xp and 7)
|
||||
46 next
|
||||
next
|
||||
*/
|
||||
|
||||
int mi[320];
|
||||
int ma[320];
|
||||
|
||||
int x, y;
|
||||
int xp, yp;
|
||||
int yq;
|
||||
float r;
|
||||
float f;
|
||||
int p[30][120];
|
||||
unsigned char fl;
|
||||
|
||||
void DoHat(void) {
|
||||
|
||||
tgi_setpalette (Palette);
|
||||
tgi_setcolor (COLOR_FORE);
|
||||
tgi_clear ();
|
||||
|
||||
for (x = 0; x < 320; x++) {
|
||||
mi[x] = 200;
|
||||
ma[x] = -1;
|
||||
}
|
||||
|
||||
for (y = 30; y >= 0; y--) {
|
||||
yq = y * y;
|
||||
// xp = (int) (4.0f * sqrtf(900.0f - yq) + 0.5f); // Error: Invalid operands for binary operator '-'
|
||||
xp = (int) (4.0f * sqrtf((float)(900 - yq)) + 0.5f);
|
||||
|
||||
for (x = 0; x < xp; x++) {
|
||||
r = sqrtf((float)x * (float)x / 3136.0f + (float)yq / 196.0f);
|
||||
f = cosf(r) - cosf(3.0f * r) / 3.0f + cosf(5.0f * r) / 5.0f - cosf(7.0f * r) / 7.0f;
|
||||
p[y][x] = (int)((40.0f * f) + 0.5f);
|
||||
fl = 0;
|
||||
xp = 160 + x - y;
|
||||
yp = 100 + y + y - p[y][x];
|
||||
if (mi[xp] > yp) { mi[xp] = yp; fl = 1; }
|
||||
if (ma[xp] < yp) { ma[xp] = yp; fl = 1; }
|
||||
if (!((fl == 0) || (yp < 0) || (yp >= 200))) {
|
||||
tgi_setpixel( xp, yp);
|
||||
}
|
||||
fl = 0;
|
||||
xp = 160 - x - y;
|
||||
|
||||
if (mi[xp] > yp) { mi[xp] = yp; fl = 1; }
|
||||
if (ma[xp] < yp) { ma[xp] = yp; fl = 1; }
|
||||
if (!((fl == 0) || (yp < 0) || (yp >= 200))) {
|
||||
tgi_setpixel( xp, yp);
|
||||
}
|
||||
}
|
||||
}
|
||||
cgetc();
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
unsigned char Border;
|
||||
|
||||
#if 1
|
||||
|
||||
#if DYN_DRV
|
||||
/* Warn the user that the tgi driver is needed */
|
||||
DoWarning ();
|
||||
|
||||
/* Load and initialize the driver */
|
||||
tgi_load_driver (tgi_stddrv);
|
||||
CheckError ("tgi_load_driver");
|
||||
#else
|
||||
/* Install the driver */
|
||||
tgi_install (tgi_static_stddrv);
|
||||
CheckError ("tgi_install");
|
||||
#endif
|
||||
|
||||
tgi_init ();
|
||||
CheckError ("tgi_init");
|
||||
|
||||
/* Get stuff from the driver */
|
||||
MaxX = tgi_getmaxx ();
|
||||
MaxY = tgi_getmaxy ();
|
||||
AspectRatio = tgi_getaspectratio ();
|
||||
|
||||
/* Set the palette, set the border color */
|
||||
Border = bordercolor (COLOR_BLACK);
|
||||
#endif
|
||||
/* Do graphics stuff */
|
||||
Dosincos();
|
||||
// DoHat();
|
||||
|
||||
#if DYN_DRV
|
||||
/* Unload the driver */
|
||||
tgi_unload ();
|
||||
#else
|
||||
/* Uninstall the driver */
|
||||
tgi_uninstall ();
|
||||
#endif
|
||||
|
||||
/* Reset the border */
|
||||
(void) bordercolor (Border);
|
||||
|
||||
/* Done */
|
||||
printf ("Done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -31,7 +31,7 @@
|
|||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
/* cc65 */
|
||||
#include "asmcode.h"
|
||||
|
@ -48,7 +48,13 @@
|
|||
#include "typecmp.h"
|
||||
#include "typeconv.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x) printf x
|
||||
#define FIXME(x) printf x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
|
@ -451,6 +457,8 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
|
|||
unsigned Flags;
|
||||
int MustScale;
|
||||
|
||||
LOG(("OpAssignArithmetic '%s' (Gen=%p)\n", Op, Gen));
|
||||
|
||||
ED_Init (&Expr2);
|
||||
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
||||
|
||||
|
@ -465,7 +473,9 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
|
|||
PushAddr (Expr);
|
||||
|
||||
if (Gen == 0) {
|
||||
|
||||
// printf("OpAssignArithmetic (gen=0) 1 lhs: %s rhs: %s\n",
|
||||
// (TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "int",
|
||||
// (TypeOf (Expr2.Type) == CF_FLOAT) ? "float" : "int");
|
||||
/* Read the expression on the right side of the '=' */
|
||||
MarkedExprWithCheck (hie1, &Expr2);
|
||||
|
||||
|
@ -477,8 +487,11 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
|
|||
/* If necessary, load the value into the primary register */
|
||||
LoadExpr (CF_NONE, &Expr2);
|
||||
|
||||
LOG(("OpAssignArithmetic '%s' (0) 2 lhs: %s rhs: %s\n",
|
||||
Op,
|
||||
(TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "int",
|
||||
(TypeOf (Expr2.Type) == CF_FLOAT) ? "float" : "int"));
|
||||
} else {
|
||||
|
||||
/* Load the original value if necessary */
|
||||
LoadExpr (CF_NONE, Expr);
|
||||
|
||||
|
@ -489,8 +502,14 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
|
|||
/* Read the expression on the right side of the '=' or 'op=' */
|
||||
MarkedExprWithCheck (hie1, &Expr2);
|
||||
|
||||
/* The rhs must be an integer (or a float, but we don't support that yet */
|
||||
if (!IsClassInt (Expr2.Type)) {
|
||||
LOG(("OpAssignArithmetic '%s' (!=0) 2 lhs: %s rhs: %s\n",
|
||||
Op,
|
||||
(TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "int",
|
||||
(TypeOf (Expr2.Type) == CF_FLOAT) ? "float" : "int"));
|
||||
|
||||
|
||||
/* The rhs must be an integer or a float */
|
||||
if (!IsClassInt (Expr2.Type) && !IsClassFloat (Expr2.Type)) {
|
||||
Error ("Invalid right operand for binary operator '%s'", Op);
|
||||
/* Continue. Wrong code will be generated, but the compiler won't
|
||||
** break, so this is the best error recovery.
|
||||
|
@ -523,9 +542,19 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
|
|||
|
||||
/* Special handling for add and sub - some sort of a hack, but short code */
|
||||
if (Gen->Func == g_add) {
|
||||
g_inc (Flags | CF_CONST, Expr2.IVal);
|
||||
LOG(("OpAssignArithmetic '%s' gen g_add\n", Op));
|
||||
if (IsClassFloat (Expr2.Type)) {
|
||||
g_inc (Flags | CF_CONST, FP_D_As32bitRaw(Expr2.V.FVal));
|
||||
} else {
|
||||
g_inc (Flags | CF_CONST, Expr2.IVal);
|
||||
}
|
||||
} else if (Gen->Func == g_sub) {
|
||||
g_dec (Flags | CF_CONST, Expr2.IVal);
|
||||
LOG(("OpAssignArithmetic '%s' gen g_sub\n", Op));
|
||||
if (IsClassFloat (Expr2.Type)) {
|
||||
g_dec (Flags | CF_CONST, FP_D_As32bitRaw(Expr2.V.FVal));
|
||||
} else {
|
||||
g_dec (Flags | CF_CONST, Expr2.IVal);
|
||||
}
|
||||
} else {
|
||||
if (!ED_IsUneval (Expr)) {
|
||||
if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) {
|
||||
|
@ -605,6 +634,8 @@ void OpAssign (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
|
|||
{
|
||||
const Type* ltype = Expr->Type;
|
||||
|
||||
LOG(("OpAssign\n"));
|
||||
|
||||
ExprDesc Expr2;
|
||||
ED_Init (&Expr2);
|
||||
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
||||
|
@ -677,8 +708,9 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
|||
return;
|
||||
}
|
||||
|
||||
/* There must be an integer or pointer on the left side */
|
||||
if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) {
|
||||
LOG(("OpAddSubAssign '%s'\n", Op));
|
||||
/* There must be an integer, pointer or float on the left side */
|
||||
if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type) && !IsTypeFloat (Expr->Type)) {
|
||||
Error ("Invalid left operand for binary operator '%s'", Op);
|
||||
/* Continue. Wrong code will be generated, but the compiler won't
|
||||
** break, so this is the best error recovery.
|
||||
|
@ -706,11 +738,9 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
|||
ED_Init (&Expr2);
|
||||
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
|
||||
|
||||
/* Evaluate the rhs. We expect an integer here, since float is not
|
||||
** supported
|
||||
*/
|
||||
/* Evaluate the rhs. We expect an integer or float here */
|
||||
hie1 (&Expr2);
|
||||
if (!IsClassInt (Expr2.Type)) {
|
||||
if (!IsClassInt (Expr2.Type) && !IsClassFloat (Expr2.Type)) {
|
||||
Error ("Invalid right operand for binary operator '%s'", Op);
|
||||
/* Continue. Wrong code will be generated, but the compiler won't
|
||||
** break, so this is the best error recovery.
|
||||
|
@ -721,7 +751,10 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
|||
lflags |= CG_TypeOf (Expr->Type) | CG_AddrModeFlags (Expr) | CF_FORCECHAR;
|
||||
rflags |= CG_TypeOf (Expr2.Type) | CF_FORCECHAR;
|
||||
|
||||
LOG(("OpAddSubAssign '%s' lflags:%04x rflags:%04x\n", Op, lflags, rflags));
|
||||
|
||||
if (ED_IsConstAbs (&Expr2)) {
|
||||
LOG(("OpAddSubAssign '%s' result is constant\n", Op));
|
||||
/* The resulting value is a constant */
|
||||
rflags |= CF_CONST;
|
||||
lflags |= CF_CONST;
|
||||
|
@ -731,6 +764,7 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
|||
Expr2.IVal *= CheckedSizeOf (Indirect (Expr->Type));
|
||||
}
|
||||
} else {
|
||||
LOG(("OpAddSubAssign '%s' result is not constant\n", Op));
|
||||
/* Not constant, load into the primary */
|
||||
LoadExpr (CF_NONE, &Expr2);
|
||||
|
||||
|
@ -756,19 +790,40 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
|||
** static variable, register variable, pooled literal or code
|
||||
** label location.
|
||||
*/
|
||||
if (Gen->Tok == TOK_PLUS_ASSIGN) {
|
||||
g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
|
||||
if (IsClassFloat (Expr->Type)) {
|
||||
LOG(("OpAddSubAssign '%s' abs, float %08x (IVal:%08lx)\n", Op, FP_D_As32bitRaw(Expr2.V.FVal), Expr2.IVal));
|
||||
/* FIXME: what about the case when expr2 is NOT float? */
|
||||
if (Gen->Tok == TOK_PLUS_ASSIGN) {
|
||||
g_addeqstatic (lflags, Expr->Name, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
|
||||
} else {
|
||||
g_subeqstatic (lflags, Expr->Name, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
|
||||
}
|
||||
} else {
|
||||
g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
|
||||
LOG(("OpAddSubAssign '%s' abs, int\n", Op));
|
||||
if (Gen->Tok == TOK_PLUS_ASSIGN) {
|
||||
g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
|
||||
} else {
|
||||
g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case E_LOC_STACK:
|
||||
/* Value on the stack */
|
||||
if (Gen->Tok == TOK_PLUS_ASSIGN) {
|
||||
g_addeqlocal (lflags, Expr->IVal, Expr2.IVal);
|
||||
if (IsClassFloat (Expr->Type)) {
|
||||
LOG(("OpAddSubAssign '%s' stack, float\n", Op));
|
||||
if (Gen->Tok == TOK_PLUS_ASSIGN) {
|
||||
g_addeqlocal (lflags, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
|
||||
} else {
|
||||
g_subeqlocal (lflags, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
|
||||
}
|
||||
} else {
|
||||
g_subeqlocal (lflags, Expr->IVal, Expr2.IVal);
|
||||
LOG(("OpAddSubAssign '%s' stack, int\n", Op));
|
||||
if (Gen->Tok == TOK_PLUS_ASSIGN) {
|
||||
g_addeqlocal (lflags, Expr->IVal, Expr2.IVal);
|
||||
} else {
|
||||
g_subeqlocal (lflags, Expr->IVal, Expr2.IVal);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -218,6 +218,10 @@ void g_reglong (unsigned from);
|
|||
** is irrelevent of signedness).
|
||||
*/
|
||||
|
||||
void g_regfloat (unsigned from);
|
||||
/* Convert the value in the primary register to a float
|
||||
*/
|
||||
|
||||
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
|
||||
/* Adjust the integer operands before doing a binary operation. lhs is a flags
|
||||
** value, that corresponds to the value on TOS, rhs corresponds to the value
|
||||
|
@ -274,8 +278,15 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes);
|
|||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void g_getimmed (unsigned Flags, uintptr_t Val, long Offs);
|
||||
#ifdef DEBUG
|
||||
// #define g_getimmed(a,b,c) _g_getimmed((a),(b),(c),(__FILE__),(__FUNCTION__),(__LINE__))
|
||||
// void _g_getimmed(unsigned Flags, uintptr_t Val, long Offs, char *file, const char *func, int line);
|
||||
#define g_getimmed(a,b,c) _g_getimmed((a),(b),(c))
|
||||
void _g_getimmed (unsigned Flags, uintptr_t Val, long Offs);
|
||||
#else
|
||||
#define g_getimmed(a,b,c) _g_getimmed((a),(b),(c))
|
||||
void _g_getimmed (unsigned Flags, uintptr_t Val, long Offs);
|
||||
#endif
|
||||
/* Load a constant into the primary register */
|
||||
|
||||
void g_getstatic (unsigned Flags, uintptr_t Label, long Offs);
|
||||
|
@ -396,6 +407,8 @@ void g_test (unsigned flags);
|
|||
|
||||
void g_push (unsigned flags, unsigned long val);
|
||||
/* Push the primary register or a constant value onto the stack */
|
||||
void g_push_float (unsigned flags, double val);
|
||||
/* Push the primary register or a constant value onto the stack */
|
||||
|
||||
void g_swap (unsigned flags);
|
||||
/* Swap the primary register and the top of the stack. flags give the type
|
||||
|
@ -467,6 +480,8 @@ void g_res (unsigned n);
|
|||
|
||||
void g_defdata (unsigned flags, uintptr_t val, long offs);
|
||||
/* Define data with the size given in flags */
|
||||
void g_defdata_float (unsigned flags, uintptr_t val, long offs);
|
||||
/* Define data with the size given in flags */
|
||||
|
||||
void g_defbytes (const void* bytes, unsigned count);
|
||||
/* Output a row of bytes as a constant */
|
||||
|
|
|
@ -668,14 +668,23 @@ const Type* ArithmeticConvert (const Type* lhst, const Type* rhst)
|
|||
** of the result. This pattern is called the usual arithmetic conversions.
|
||||
*/
|
||||
|
||||
if (IsTypeFloat (lhst) && IsTypeFloat (rhst)) {
|
||||
/* FIXME: float - this needs much more special handling */
|
||||
return type_float;
|
||||
}
|
||||
if (IsTypeFloat (lhst)) {
|
||||
/* FIXME: float - this needs much more special handling */
|
||||
return type_float;
|
||||
}
|
||||
if (IsTypeFloat (rhst)) {
|
||||
/* FIXME: float - this needs much more special handling */
|
||||
return type_float;
|
||||
}
|
||||
|
||||
/* There are additional rules for floating point types that we don't bother with, since
|
||||
** floating point types are not (yet) supported.
|
||||
** The integral promotions are performed on both operands.
|
||||
*/
|
||||
if (IsClassFloat(lhst) || IsClassFloat(rhst)) {
|
||||
Error ("Floating point arithmetic not supported.");
|
||||
return type_long;
|
||||
}
|
||||
lhst = IntPromotion (lhst);
|
||||
rhst = IntPromotion (rhst);
|
||||
|
||||
|
|
1089
src/cc65/expr.c
1089
src/cc65/expr.c
File diff suppressed because it is too large
Load Diff
|
@ -31,10 +31,11 @@
|
|||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -66,7 +67,13 @@
|
|||
#include "typeconv.h"
|
||||
#include "initdata.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x) printf x
|
||||
#define FIXME(x) printf x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
|
@ -165,34 +172,48 @@ static void ClosingCurlyBraces (unsigned BracesExpected)
|
|||
static void DefineData (ExprDesc* Expr)
|
||||
/* Output a data definition for the given expression */
|
||||
{
|
||||
int isfloat = (CG_TypeOf (Expr->Type) == CF_FLOAT);
|
||||
|
||||
LOG(("%s:%d DefineData IVal: %ld V.FVal: %f isfloat:%d %d\n", __FILE__, __LINE__,
|
||||
Expr->IVal, (double)(Expr->V.FVal.V), isfloat, ED_GetLoc (Expr)));
|
||||
switch (ED_GetLoc (Expr)) {
|
||||
|
||||
case E_LOC_NONE:
|
||||
/* Immediate numeric value with no storage */
|
||||
g_defdata (CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
|
||||
/* FIXME: float */
|
||||
if (isfloat) {
|
||||
g_defdata_float (CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal), 0);
|
||||
} else {
|
||||
g_defdata (CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
/* FIXME: float - other cases */
|
||||
case E_LOC_ABS:
|
||||
if (isfloat) { printf("%s:%d FIXME: E_LOC_ABS\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Absolute numeric address */
|
||||
g_defdata (CF_ABSOLUTE | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
|
||||
break;
|
||||
|
||||
case E_LOC_GLOBAL:
|
||||
if (isfloat) { printf("%s:%d FIXME: E_LOC_GLOBAL\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Global variable */
|
||||
g_defdata (CF_EXTERNAL, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_STATIC:
|
||||
if (isfloat) { printf("%s:%d FIXME: E_LOC_STATIC\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Static variable */
|
||||
g_defdata (CF_STATIC, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_LITERAL:
|
||||
if (isfloat) { printf("%s:%d FIXME: E_LOC_LITERAL\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Literal in the literal pool */
|
||||
g_defdata (CF_LITERAL, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_REGISTER:
|
||||
if (isfloat) { printf("%s:%d FIXME: E_LOC_REGISTER\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Register variable. Taking the address is usually not
|
||||
** allowed.
|
||||
*/
|
||||
|
@ -203,6 +224,7 @@ static void DefineData (ExprDesc* Expr)
|
|||
break;
|
||||
|
||||
case E_LOC_CODE:
|
||||
if (isfloat) { printf("%s:%d FIXME: E_LOC_CODE\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Code label location */
|
||||
g_defdata (CF_CODE, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* cc65 */
|
||||
#include "codegen.h"
|
||||
|
@ -41,7 +43,13 @@
|
|||
#include "global.h"
|
||||
#include "loadexpr.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x) printf x
|
||||
#define FIXME(x) printf x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
|
@ -52,6 +60,7 @@
|
|||
static void LoadAddress (unsigned Flags, ExprDesc* Expr)
|
||||
/* Load the primary register with some address value. */
|
||||
{
|
||||
LOG(("LoadAddress flags:%04x\n", Flags));
|
||||
switch (ED_GetLoc (Expr)) {
|
||||
|
||||
case E_LOC_ABS:
|
||||
|
@ -119,6 +128,7 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
|
|||
** unfortunately.
|
||||
*/
|
||||
{
|
||||
/*LOG(("LoadExpr flags:%4x\n", Flags));*/
|
||||
if (!ED_IsAddrExpr (Expr)) {
|
||||
|
||||
/* Lvalue. If this is a bit field its type is unsigned. But if the
|
||||
|
@ -171,57 +181,88 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
|
|||
}
|
||||
|
||||
/* Load the content of Expr */
|
||||
/*LOG(("LoadExpr ED_GetLoc:%04x\n", ED_GetLoc (Expr)));*/
|
||||
switch (ED_GetLoc (Expr)) {
|
||||
|
||||
case E_LOC_NONE:
|
||||
/* FIXME: float */
|
||||
/*LOG(("LoadExpr E_LOC_NONE (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));*/
|
||||
/* Immediate number constant */
|
||||
g_getimmed (Flags | CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
|
||||
if (CG_TypeOf (Expr->Type) == CF_FLOAT) {
|
||||
g_getimmed (Flags | CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal), 0);
|
||||
} else {
|
||||
g_getimmed (Flags | CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case E_LOC_ABS:
|
||||
LOG(("LoadExpr E_LOC_ABS (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));
|
||||
if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_ABS\n", __FILE__, __LINE__); exit(-1); }
|
||||
/* Absolute numeric addressed variable */
|
||||
g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0);
|
||||
break;
|
||||
|
||||
case E_LOC_GLOBAL:
|
||||
/* Global variable */
|
||||
/* LOG(("LoadExpr E_LOC_GLOBAL (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
|
||||
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_GLOBAL\n", __FILE__, __LINE__); exit(-1); } */
|
||||
/* Global variable, offset in IVal */
|
||||
g_getstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_STATIC:
|
||||
/* Static variable */
|
||||
/* LOG(("LoadExpr E_LOC_STATIC (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
|
||||
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_STATIC\n", __FILE__, __LINE__); exit(-1); } */
|
||||
/* Static variable, offset in IVal */
|
||||
g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_LITERAL:
|
||||
/* Literal in the literal pool */
|
||||
/* LOG(("LoadExpr E_LOC_LITERAL (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
|
||||
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_LITERAL\n", __FILE__, __LINE__); exit(-1); } */
|
||||
/* Literal in the literal pool, offset in IVal */
|
||||
g_getstatic (Flags | CF_LITERAL, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_REGISTER:
|
||||
/* Register variable */
|
||||
/* LOG(("LoadExpr E_LOC_REGISTER (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
|
||||
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_REGISTER\n", __FILE__, __LINE__); exit(-1); } */
|
||||
/* Register variable, offset in IVal */
|
||||
g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_CODE:
|
||||
/* Code label location */
|
||||
/* LOG(("LoadExpr E_LOC_CODE (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
|
||||
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_CODE\n", __FILE__, __LINE__); exit(-1); } */
|
||||
/* Code label location, offset in IVal */
|
||||
g_getstatic (Flags | CF_CODE, Expr->Name, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_STACK:
|
||||
/* Value on the stack */
|
||||
/* LOG(("LoadExpr E_LOC_STACK (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
|
||||
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_STACK\n", __FILE__, __LINE__); exit(-1); } */
|
||||
/* Fetch value on the stack (with offset in IVal) */
|
||||
g_getlocal (Flags, Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_PRIMARY:
|
||||
/*LOG(("LoadExpr E_LOC_PRIMARY (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));*/
|
||||
/*if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_PRIMARY\n", __FILE__, __LINE__); exit(-1); }*/
|
||||
/* The primary register */
|
||||
if (Expr->IVal != 0) {
|
||||
/* We have an expression in the primary plus a constant
|
||||
** offset. Adjust the value in the primary accordingly.
|
||||
*/
|
||||
g_inc (Flags | CF_CONST, Expr->IVal);
|
||||
if (CG_TypeOf (Expr->Type) == CF_FLOAT) {
|
||||
/* FIXME: float */
|
||||
Flags |= CF_FLOAT;
|
||||
if (Expr->V.FVal.V != 0.0f) {
|
||||
g_inc (Flags | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal));
|
||||
}
|
||||
} else {
|
||||
if (Expr->IVal != 0) {
|
||||
/* We have an expression in the primary plus a constant
|
||||
** offset. Adjust the value in the primary accordingly.
|
||||
*/
|
||||
g_inc (Flags | CF_CONST, Expr->IVal);
|
||||
|
||||
/* We might want to clear the offset, but we can't */
|
||||
/* We might want to clear the offset, but we can't */
|
||||
}
|
||||
}
|
||||
if (Flags & CF_TEST) {
|
||||
g_test (Flags);
|
||||
|
@ -229,7 +270,9 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
|
|||
break;
|
||||
|
||||
case E_LOC_EXPR:
|
||||
/* Reference to address in primary with offset in Expr */
|
||||
/*LOG(("LoadExpr E_LOC_EXPR (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));*/
|
||||
/*if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_EXPR\n", __FILE__, __LINE__); exit(-1); }*/
|
||||
/* Reference to address in primary with offset in IVal */
|
||||
g_getind (Flags, Expr->IVal);
|
||||
|
||||
/* Since the content in primary is now overwritten with the
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
@ -57,7 +57,13 @@
|
|||
#include "typeconv.h"
|
||||
#include "input.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x) printf x
|
||||
#define FIXME(x) printf x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
|
@ -199,6 +205,8 @@ static void ParseAutoDecl (Declarator* Decl)
|
|||
/* Get the size of the variable */
|
||||
unsigned Size = SizeOf (Decl->Type);
|
||||
|
||||
LOG(("ParseAutoDecl SIze:%d IsCompound:%d\n", Size, IsCompound));
|
||||
|
||||
/* Check if this is a variable on the stack or in static memory */
|
||||
if (IS_Get (&StaticLocals) == 0) {
|
||||
|
||||
|
@ -275,7 +283,20 @@ static void ParseAutoDecl (Declarator* Decl)
|
|||
}
|
||||
|
||||
/* Push the value */
|
||||
g_push (Flags | CG_TypeOf (Sym->Type), Expr.IVal);
|
||||
if (CG_TypeOf (Sym->Type) == CF_FLOAT) {
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4244 ) // conversion from double to float
|
||||
#endif
|
||||
/* FIXME: float */
|
||||
LOG(("ParseAutoDecl Expr.V.FVal.V: %f\n", Expr.V.FVal.V));
|
||||
g_push_float (Flags | CG_TypeOf (Sym->Type), Expr.V.FVal.V);
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
} else {
|
||||
g_push (Flags | CG_TypeOf (Sym->Type), Expr.IVal);
|
||||
}
|
||||
|
||||
/* This has to be done at sequence point */
|
||||
DoDeferred (SQP_KEEP_NONE, &Expr);
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -62,7 +62,13 @@
|
|||
#include "standard.h"
|
||||
#include "symtab.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x) printf x
|
||||
#define FIXME(x) printf x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
|
@ -696,6 +702,8 @@ static void NumericConst (void)
|
|||
/* Float constant */
|
||||
Double FVal = FP_D_FromInt (IVal); /* Convert to double */
|
||||
|
||||
LOG(("NumericConst start IVal:%ld FVal: %f\n", IVal, FVal.V));
|
||||
|
||||
/* Check for a fractional part and read it */
|
||||
if (SB_Peek (&Src) == '.') {
|
||||
|
||||
|
@ -771,6 +779,8 @@ static void NumericConst (void)
|
|||
}
|
||||
}
|
||||
|
||||
LOG(("NumericConst end FVal: %f\n", FVal.V));
|
||||
|
||||
/* Check for a suffix and determine the type of the constant */
|
||||
if (toupper (SB_Peek (&Src)) == 'F') {
|
||||
SB_Skip (&Src);
|
||||
|
@ -788,7 +798,7 @@ static void NumericConst (void)
|
|||
NextTok.Tok = TOK_FCONST;
|
||||
|
||||
}
|
||||
|
||||
LOG(("NumericConst exit IsFloat:%d IVal: %ld FVal: %f\n", IsFloat, NextTok.IVal, NextTok.FVal.V));
|
||||
/* We don't need the string buffer any longer */
|
||||
SB_Done (&Src);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
/* common */
|
||||
#include "shift.h"
|
||||
|
@ -47,7 +47,13 @@
|
|||
#include "typecmp.h"
|
||||
#include "typeconv.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x) printf x
|
||||
#define FIXME(x) printf x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
|
@ -97,7 +103,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
|
|||
|
||||
/* lvalue? */
|
||||
if (ED_IsLVal (Expr)) {
|
||||
|
||||
LOG(("DoConversion 1 Old: %s New: %s\n",
|
||||
(IsTypeFloat (OldType)) ? "float" : "int",
|
||||
(IsTypeFloat (NewType)) ? "float" : "int"
|
||||
));
|
||||
/* We have an lvalue. If the new size is smaller than the old one,
|
||||
** we don't need to do anything. The compiler will generate code
|
||||
** to load only the portion of the value that is actually needed.
|
||||
|
@ -106,7 +115,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
|
|||
** If both sizes are equal, do also leave the value alone.
|
||||
** If the new size is larger, we must convert the value.
|
||||
*/
|
||||
if (NewBits > OldBits) {
|
||||
if ((NewBits > OldBits) ||
|
||||
/* FIXME: float */
|
||||
/* when either side is float, emit the call to the conversion code */
|
||||
(IsTypeFloat (OldType) || IsTypeFloat (NewType))) {
|
||||
/* Load the value into the primary */
|
||||
LoadExpr (CF_NONE, Expr);
|
||||
|
||||
|
@ -116,12 +128,27 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
|
|||
/* Value is now in primary and an rvalue */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
}
|
||||
|
||||
LOG(("DoConversion 1 done\n"));
|
||||
} else if (ED_IsConstAbs (Expr)) {
|
||||
LOG(("DoConversion 2 Old: %s New: %s\n",
|
||||
(IsTypeFloat (OldType)) ? "float" : "int",
|
||||
(IsTypeFloat (NewType)) ? "float" : "int"
|
||||
));
|
||||
|
||||
/* A cast of a constant numeric value to another type. Be sure
|
||||
** to handle sign extension correctly.
|
||||
*/
|
||||
/* FIXME: float --- start of new code */
|
||||
/* convert from float to (signed) long first */
|
||||
if (IsTypeFloat (OldType) && !IsTypeFloat (NewType)) {
|
||||
OldBits = 32;
|
||||
Expr->IVal = FP_D_ToLong(Expr->V.FVal);
|
||||
LOG(("DoConversion 2 new ival: %ld\n", Expr->IVal));
|
||||
} else if (!IsTypeFloat (OldType) && IsTypeFloat (NewType)) {
|
||||
OldBits = 0;
|
||||
Expr->V.FVal = FP_D_FromInt(Expr->IVal);
|
||||
LOG(("DoConversion 2 new fval: %f\n", Expr->V.FVal.V));
|
||||
}
|
||||
|
||||
/* If this is a floating point constant, convert to integer,
|
||||
** and warn if precision is discarded.
|
||||
|
@ -133,11 +160,13 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
|
|||
}
|
||||
Expr->IVal = IVal;
|
||||
}
|
||||
/* FIXME: float --- end of new code */
|
||||
|
||||
/* Check if the new datatype will have a smaller range. If it
|
||||
** has a larger range, things are OK, since the value is
|
||||
** internally already represented by a long.
|
||||
*/
|
||||
LOG(("DoConversion 2 NewBits: %d OldBits: %d\n", NewBits, OldBits));
|
||||
if (NewBits <= OldBits) {
|
||||
long OldVal = Expr->IVal;
|
||||
|
||||
|
@ -157,6 +186,12 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
|
|||
}
|
||||
}
|
||||
|
||||
if (IsTypeFloat (NewType)) {
|
||||
LOG(("DoConversion 2 new fval: %f\n", Expr->V.FVal.V));
|
||||
} else {
|
||||
LOG(("DoConversion 2 new ival: %ld\n", Expr->IVal));
|
||||
}
|
||||
|
||||
/* Do the integer constant <-> absolute address conversion if necessary */
|
||||
if (IsClassPtr (NewType)) {
|
||||
Expr->Flags &= ~E_MASK_LOC;
|
||||
|
@ -167,12 +202,19 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
|
|||
}
|
||||
|
||||
} else {
|
||||
LOG(("DoConversion 3 Old: %s New: %s\n",
|
||||
(IsTypeFloat (OldType)) ? "float" : "int",
|
||||
(IsTypeFloat (NewType)) ? "float" : "int"
|
||||
));
|
||||
|
||||
/* The value is not a constant. If the sizes of the types are
|
||||
** not equal, add conversion code. Be sure to convert chars
|
||||
** correctly.
|
||||
*/
|
||||
if (OldBits != NewBits) {
|
||||
if ((OldBits != NewBits) ||
|
||||
/* FIXME: float */
|
||||
/* when either side is float, emit the call to the conversion code */
|
||||
(IsTypeFloat (OldType) || IsTypeFloat (NewType))) {
|
||||
|
||||
/* Load the value into the primary */
|
||||
LoadExpr (CF_NONE, Expr);
|
||||
|
@ -198,14 +240,17 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
|
|||
** impossible.
|
||||
*/
|
||||
{
|
||||
LOG(("TypeConversion\n"));
|
||||
#if 0
|
||||
/* Debugging */
|
||||
printf ("Expr:\n=======================================\n");
|
||||
LOG(("=======================================\n"));
|
||||
LOG(("Expr:\n---------------------------------------\n"));
|
||||
PrintExprDesc (stdout, Expr);
|
||||
printf ("Type:\n=======================================\n");
|
||||
LOG(("\nType:\n---------------------------------------\n"));
|
||||
PrintType (stdout, NewType);
|
||||
printf ("\n");
|
||||
LOG(("\n");
|
||||
PrintRawType (stdout, NewType);
|
||||
LOG(("=======================================\n"));
|
||||
#endif
|
||||
/* First, do some type checking */
|
||||
typecmp_t Result = TYPECMP_INITIALIZER;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* common */
|
||||
#include "fp.h"
|
||||
|
@ -189,7 +190,11 @@ Double FP_D_FromInt (long Val)
|
|||
return D;
|
||||
}
|
||||
|
||||
|
||||
long FP_D_ToLong (Double Val)
|
||||
/* Convert a floating point variable into a long */
|
||||
{
|
||||
return (long)Val.V;
|
||||
}
|
||||
|
||||
double FP_D_ToFloat (Double Val)
|
||||
/* Convert a Double into a native double */
|
||||
|
@ -236,3 +241,22 @@ Double FP_D_Div (Double Left, Double Right)
|
|||
D.V = Left.V / Right.V;
|
||||
return D;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4244 ) // conversion from double to float
|
||||
#endif
|
||||
uint32_t FP_D_As32bitRaw(Double Val)
|
||||
/* converts double into 32bit (float) and then returns its raw content as a 32bit int */
|
||||
{
|
||||
static float f;
|
||||
uint32_t *lptr;
|
||||
uint32_t lval;
|
||||
f = Val.V;
|
||||
lptr = (uint32_t *)&f;
|
||||
lval = *lptr;
|
||||
return lval;
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
|
@ -92,7 +93,7 @@ Float FP_F_Make (float Val);
|
|||
Float FP_F_FromInt (long Val);
|
||||
/* Convert an integer into a floating point variable */
|
||||
|
||||
float FP_F_ToFloat (Float Val);
|
||||
float FP_F_ToFloat (Float Val); /* FIXME: better name */
|
||||
/* Convert a Float into a native float */
|
||||
|
||||
Float FP_F_Add (Float Left, Float Right);
|
||||
|
@ -118,8 +119,9 @@ Double FP_D_Make (double Val);
|
|||
|
||||
Double FP_D_FromInt (long Val);
|
||||
/* Convert an integer into a floating point variable */
|
||||
long FP_D_ToLong (Double Val);
|
||||
|
||||
double FP_D_ToFloat (Double Val);
|
||||
double FP_D_ToFloat (Double Val); /* FIXME: better name */
|
||||
/* Convert a Double into a native double */
|
||||
|
||||
Double FP_D_Add (Double Left, Double Right);
|
||||
|
@ -134,7 +136,8 @@ Double FP_D_Mul (Double Left, Double Right);
|
|||
Double FP_D_Div (Double Left, Double Right);
|
||||
/* Divide two floats */
|
||||
|
||||
|
||||
uint32_t FP_D_As32bitRaw(Double Val);
|
||||
/* converts double into 32bit (float) and then returns its raw content as a 32bit int */
|
||||
|
||||
/* End of fp.h */
|
||||
|
||||
|
|
|
@ -50,13 +50,28 @@ define PRG_template
|
|||
|
||||
$(WORKDIR)/%.$1.$2.prg: %.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo todo/$$*.$1.$2.prg)
|
||||
$(CC65) -t sim$2 $$(CC65FLAGS) -$1 -o $$(@:.prg=.s) $$< $(NULLERR)
|
||||
$(CC65) -t sim$2 $$(CC65FLAGS) --add-source -$1 -o $$(@:.prg=.s) $$< $(NULLERR)
|
||||
$(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR)
|
||||
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
|
||||
$(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT)
|
||||
|
||||
endef # PRG_template
|
||||
|
||||
# HACK! for some reason the test does NOT fail in this particular config
|
||||
$(WORKDIR)/inline-asm-1489.Osr.65c02.prg: inline-asm-1489.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo todo/inline-asm-1489.Osr.65c02.prg)
|
||||
$(CC65) -t sim65c02 $$(CC65FLAGS) --add-source -Osr -o $(@:.prg=.s) $< $(NULLERR)
|
||||
$(CA65) -t sim65c02 -o $(@:.prg=.o) $(@:.prg=.s) $(NULLERR)
|
||||
$(LD65) -t sim65c02 -o $@ $(@:.prg=.o) sim65c02.lib $(NULLERR)
|
||||
$(SIM65) $(SIM65FLAGS) $@ $(NULLOUT)
|
||||
|
||||
$(WORKDIR)/inline-asm-1489.Os.65c02.prg: inline-asm-1489.c | $(WORKDIR)
|
||||
$(if $(QUIET),echo todo/inline-asm-1489.Os.65c02.prg)
|
||||
$(CC65) -t sim65c02 $$(CC65FLAGS) --add-source -Os -o $(@:.prg=.s) $< $(NULLERR)
|
||||
$(CA65) -t sim65c02 -o $(@:.prg=.o) $(@:.prg=.s) $(NULLERR)
|
||||
$(LD65) -t sim65c02 -o $@ $(@:.prg=.o) sim65c02.lib $(NULLERR)
|
||||
$(SIM65) $(SIM65FLAGS) $@ $(NULLOUT)
|
||||
|
||||
$(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),6502)))
|
||||
$(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),65c02)))
|
||||
|
||||
|
|
126
test/val/float-basic-const-const.c
Normal file
126
test/val/float-basic-const-const.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
void constconst(void)
|
||||
{
|
||||
printf("\n*** constant vs constant\n\n");
|
||||
|
||||
// addition
|
||||
printf("\nconstant + constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f + 0.2f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x3e99999a] %s (0.3)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3e99999a");
|
||||
|
||||
// substraction
|
||||
printf("\nconstant - constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f - 0.2f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0xbdcccccd] %s (-0.1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "bdcccccd");
|
||||
|
||||
fp3 = 0.3f - 0.1f;
|
||||
printf("fp3:0x%08lx [0x3e4ccccd] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3e4ccccd");
|
||||
fp3 = 0.1f - 0.3f;
|
||||
printf("fp3:0x%08lx [0xbe4ccccd] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "be4ccccd");
|
||||
|
||||
// multiplication
|
||||
printf("\nconstant * constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f * 5.0f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x3f000000] %s (0.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3f000000");
|
||||
|
||||
// division
|
||||
printf("\nconstant / constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f / 0.2f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x3f000000] %s (0.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3f000000");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-const-const ***\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));
|
||||
|
||||
constconst();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-const-const (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
131
test/val/float-basic-const-intconst.c
Normal file
131
test/val/float-basic-const-intconst.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#if 1
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
void constintconst(void)
|
||||
{
|
||||
printf("\n*** float constant vs int constant\n\n");
|
||||
|
||||
// addition
|
||||
printf("\nconstant + constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.2f + 2;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x400ccccd] %s (2.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "400ccccd");
|
||||
|
||||
// substraction
|
||||
printf("\nconstant - constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f - 2;
|
||||
|
||||
printf("fp3:0x%08lx [0xbff33333] %s (-1.9)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "bff33333");
|
||||
|
||||
fp3 = 0.3f - 1;
|
||||
printf("fp3:0x%08lx [0xbf333333] %s (-0.7)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "bf333333");
|
||||
|
||||
// multiplication
|
||||
printf("\nconstant * constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f * 5;
|
||||
|
||||
printf("fp3:0x%08lx [0x3f000000] %s (0.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3f000000");
|
||||
|
||||
// division
|
||||
printf("\nconstant / constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f / 2;
|
||||
|
||||
printf("fp3:0x%08lx [0x3d4ccccd] %s (0.05)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3d4ccccd");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-const-intconst ***\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));
|
||||
|
||||
constintconst();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-const-intconst (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.2f;
|
||||
fp3 = 0.1f - 2; // 2.1
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [?] %s (2.1)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
return result;
|
||||
}
|
||||
#endif
|
109
test/val/float-basic-const-intvar.c
Normal file
109
test/val/float-basic-const-intvar.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
void constintvar(void)
|
||||
{
|
||||
printf("\nfloat constant vs int variable\n\n");
|
||||
|
||||
var_sint = 64;
|
||||
fp3 = 16.75f + var_sint;
|
||||
printf("addition: %s+%d=%s\n", _ftostr(buf, 16.75f), var_sint, _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x42a18000] %s (80.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42a18000");
|
||||
|
||||
var_sint = 16;
|
||||
fp3 = 18.5f - var_sint;
|
||||
printf("substraction: %s-%d=%s\n", _ftostr(buf, 8.5f), var_sint, _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x40200000] %s (2.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "40200000");
|
||||
var_sint = 13;
|
||||
fp3 = 20.6f - var_sint;
|
||||
printf("fp3:0x%08lx [0x40f33334] %s (7.6)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "40f33334");
|
||||
var_sint = 13;
|
||||
fp3 = 10.2f - var_sint;
|
||||
printf("fp3:0x%08lx [0xc0333334] %s (-2.8)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "c0333334");
|
||||
|
||||
|
||||
var_sint = 2;
|
||||
fp3 = 16.25f * var_sint;
|
||||
printf("multiplication: %s*%d=%s\n", _ftostr(buf, 16.25f), var_sint, _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x42020000] %s (32.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42020000");
|
||||
|
||||
|
||||
var_sint = 2;
|
||||
fp3 = 16.2f / var_sint;
|
||||
printf("division: %s/%d=%s\n", _ftostr(buf, 16.2f), var_sint, _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x4101999a] %s (8.1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "4101999a");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("float-basic-const-intvar\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));
|
||||
|
||||
constintvar();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-const-intvar (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
111
test/val/float-basic-const-var.c
Normal file
111
test/val/float-basic-const-var.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
// when making sub tests work, remove them here and uncomment them in val/float-basic.c
|
||||
void constvar(void)
|
||||
{
|
||||
printf("\nconstant vs variable\n\n");
|
||||
|
||||
fp2 = 64.25f;
|
||||
fp3 = 16.75f + fp2;
|
||||
printf("addition: %s+%s=%s\n", _ftostr(buf, 16.75f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x42a20000] %s (81.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42a20000");
|
||||
|
||||
fp2 = 16.25f;
|
||||
fp3 = 8.5f - fp2;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, 8.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0xc0f80000] %s (-7.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "c0f80000");
|
||||
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.3f;
|
||||
fp3 = 0.3f - fp1;
|
||||
printf("fp3:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3e4cccce");
|
||||
fp3 = 0.1f - fp2;
|
||||
printf("fp3:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "be4cccce");
|
||||
|
||||
fp2 = 2.25f;
|
||||
fp3 = 16.25f * fp2;
|
||||
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x42124000] %s (36.5625)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42124000");
|
||||
|
||||
fp2 = 2.5f;
|
||||
fp3 = 16.2f / fp2;
|
||||
printf("division: %s/%s=%s\n", _ftostr(buf, 16.2f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x40cf5c2a] %s (6.48)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "40cf5c2a");
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("float-basic-const-var\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));
|
||||
|
||||
constvar();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-const-var (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
126
test/val/float-basic-intconst-const.c
Normal file
126
test/val/float-basic-intconst-const.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
void intconstconst(void)
|
||||
{
|
||||
printf("\n*** int constant vs constant\n\n");
|
||||
|
||||
// addition
|
||||
printf("\nconstant + constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 5;
|
||||
fp3 = 5 + 0.5f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x40b00000] %s (5.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "40b00000");
|
||||
|
||||
// substraction
|
||||
printf("\nconstant - constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 5;
|
||||
fp3 = 5 - 0.2f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x4099999a] %s (4.8)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "4099999a");
|
||||
|
||||
fp3 = 5 - 1.1f;
|
||||
printf("fp3:0x%08lx [0x4079999a] %s (3.9)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "4079999a");
|
||||
fp3 = 5 - 2.3f;
|
||||
printf("fp3:0x%08lx [0x402ccccd] %s (2.7)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "402ccccd");
|
||||
|
||||
// multiplication
|
||||
printf("\nconstant * constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 5;
|
||||
fp3 = 5 * 5.0f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x41c80000] %s (25.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "41c80000");
|
||||
|
||||
// division
|
||||
printf("\nconstant / constant\n\n");
|
||||
fp1 = 0.1f;
|
||||
fp2 = 5;
|
||||
fp3 = 5 / 0.2f;
|
||||
|
||||
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
|
||||
printf("fp3:0x%08lx [0x41c80000] %s (25.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "41c80000");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-intconst-const ***\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));
|
||||
|
||||
intconstconst();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-intconst-const (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
128
test/val/float-basic-intconst-var.c
Normal file
128
test/val/float-basic-intconst-var.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
int i;
|
||||
|
||||
unsigned char var_char;
|
||||
unsigned int var_int;
|
||||
float var_float;
|
||||
|
||||
#if 1
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf("[%s:%s]", temp, str);
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void SKIPPEDtest1(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf(" (SKIPPED:%s:%s)\n", temp, str);
|
||||
}
|
||||
|
||||
void intconstvar(void)
|
||||
{
|
||||
|
||||
var_float = 11.123f;
|
||||
#if 1
|
||||
fp1 = 47;
|
||||
printf("fp1:0x%08lx [?] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float;
|
||||
printf("fp1:0x%08lx [?] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
/* addition */
|
||||
fp1 = 47 + var_float;
|
||||
printf("fp1:0x%08lx [?] %s (58.123)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
|
||||
|
||||
fp1 = 47 - var_float;
|
||||
printf("fp1:0x%08lx [?] %s (35.877)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "420f820c");
|
||||
#endif
|
||||
#if 0 // compiles, but wrong result
|
||||
fp1 = 47 * var_float;
|
||||
printf("fp1:0x%08lx [?] %s (522.781)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
#if 0 // Internal compiler error
|
||||
fp1 = 47 / var_float;
|
||||
printf("fp1:0x%08lx [?] %s (58.123)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-intconst-var ***\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));
|
||||
|
||||
intconstvar();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-intconst-var (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
// fp1 = 47 * var_float;
|
||||
// printf("fp1:0x%08lx [?] %s (522.781)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
fp1 = 47 / var_float;
|
||||
printf("fp1:0x%08lx [?] %s (58.123)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
177
test/val/float-basic-intvar-const.c
Normal file
177
test/val/float-basic-intvar-const.c
Normal file
|
@ -0,0 +1,177 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
int i;
|
||||
|
||||
unsigned char var_char;
|
||||
unsigned int var_int;
|
||||
float var_float;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf("[%s:%s]", temp, str);
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void test2(unsigned int i, unsigned int exp)
|
||||
{
|
||||
if (i == exp) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void SKIPPEDtest1(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf(" (SKIPPED:%s:%s)\n", temp, str);
|
||||
}
|
||||
|
||||
void intvarconst(void)
|
||||
{
|
||||
var_int = 47;
|
||||
#if 1
|
||||
fp1 = var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = 11.123f;
|
||||
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
printf("int var + float const\n");
|
||||
|
||||
/* addition */
|
||||
var_char = 42;
|
||||
fp1 = var_char + 23.123f;
|
||||
printf("fp1:0x%08lx [0x42823efa] %s (65.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42823efa");
|
||||
|
||||
fp1 = var_int + 11.123f;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
/* subtraction */
|
||||
#if 1 // gives wrong result
|
||||
fp1 = var_int - 11.123f;
|
||||
printf("fp1:0x%08lx [420f820c] %s (35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "420f820c");
|
||||
#endif
|
||||
#if 1
|
||||
/* multiplication */
|
||||
fp1 = var_int * 11.123f;
|
||||
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "4402b1fc");
|
||||
|
||||
/* division */
|
||||
fp1 = var_int / 11.123f;
|
||||
printf("fp1:0x%08lx [4087371f] %s (4.2254)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "4087371f");
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int i1;
|
||||
|
||||
void intvarconst2(void)
|
||||
{
|
||||
var_int = 47;
|
||||
#if 1
|
||||
i1 = var_int;
|
||||
printf("i1: %d (47)\n", i1);
|
||||
#endif
|
||||
|
||||
printf("int var X= float const\n");
|
||||
|
||||
/* addition */
|
||||
#if 0 // gives wrong result
|
||||
i1 = var_int;
|
||||
i1 += 11.123f;
|
||||
printf("i1: %d (58)\n", i1);
|
||||
test2(i1, 58);
|
||||
#endif
|
||||
/* subtraction */
|
||||
#if 0 // gives wrong result
|
||||
i1 = var_int;
|
||||
i1 -= 11.123f;
|
||||
printf("i1: %d (35)\n", i1);
|
||||
test2(i1, 35);
|
||||
#endif
|
||||
#if 0 // internal compiler error
|
||||
/* multiplication */
|
||||
i1 = var_int;
|
||||
i1 *= 11.123f;
|
||||
printf("i1: %d (522)\n", i1);
|
||||
test2(i1, 522);
|
||||
#endif
|
||||
#if 0 // internal compiler error
|
||||
/* division */
|
||||
i1 = var_int;
|
||||
i1 /= 11.123f;
|
||||
printf("i1: %d (4)\n", i1);
|
||||
test2(i1, 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-intvar-const ***\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));
|
||||
|
||||
intvarconst();
|
||||
intvarconst2();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-intvar-const (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
175
test/val/float-basic-intvar-var.c
Normal file
175
test/val/float-basic-intvar-var.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
int i;
|
||||
|
||||
unsigned char var_char;
|
||||
unsigned int var_int;
|
||||
float var_float;
|
||||
|
||||
#if 1
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf("[%s:%s]", temp, str);
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void test2(unsigned int i, unsigned int exp)
|
||||
{
|
||||
if (i == exp) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void SKIPPEDtest1(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf(" (SKIPPED:%s:%s)\n", temp, str);
|
||||
}
|
||||
|
||||
void intfloat(void)
|
||||
{
|
||||
var_int = 47;
|
||||
var_float = 11.123f;
|
||||
#if 1
|
||||
fp1 = var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
/* addition */
|
||||
fp1 = var_int + var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
|
||||
fp1 = var_int - var_float;
|
||||
printf("fp1:0x%08lx [420f820c] %s (35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "420f820c");
|
||||
#endif
|
||||
#if 1
|
||||
fp1 = var_int * var_float;
|
||||
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "4402b1fc");
|
||||
#endif
|
||||
#if 1
|
||||
fp1 = var_int / var_float;
|
||||
printf("fp1:0x%08lx [4087371f] %s (4.225)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "4087371f");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
unsigned int i1;
|
||||
|
||||
void intfloat2(void)
|
||||
{
|
||||
printf("int X= float var\n");
|
||||
var_int = 47;
|
||||
var_float = 11.123f;
|
||||
|
||||
i1 = var_int;
|
||||
printf("i1: %d (47)\n", i1);
|
||||
|
||||
/* addition */
|
||||
i1 = var_int;
|
||||
i1 += var_float;
|
||||
printf("i1: %d (58)\n", i1);
|
||||
test2(i1, 58);
|
||||
#if 1
|
||||
i1 = var_int;
|
||||
i1 -= var_float;
|
||||
printf("i1: %d (36)\n", i1);
|
||||
test2(i1, 36);
|
||||
#endif
|
||||
#if 0 // internal compiler error
|
||||
i1 = var_int;
|
||||
i1 *= var_float;
|
||||
printf("i1: %d (522)\n", i1);
|
||||
test2(i1, 522);
|
||||
#endif
|
||||
#if 0 // internal compiler error
|
||||
i1 = var_int;
|
||||
i1 /= var_float;
|
||||
printf("i1: %d (4)\n", i1);
|
||||
test2(i1, 4);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-intvar-var ***\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));
|
||||
|
||||
intfloat();
|
||||
intfloat2();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-intvar-var (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
var_int = 47;
|
||||
var_float = 11.123f;
|
||||
fp1 = var_int * var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
return result;
|
||||
}
|
||||
#endif
|
222
test/val/float-basic-var-const.c
Normal file
222
test/val/float-basic-var-const.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#if 1
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf("[%s:%s]",temp,str);
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
void varconst(void)
|
||||
{
|
||||
printf("\n*** variable vs constant\n\n");
|
||||
/* addition, variable + constant */
|
||||
fp1 = 64.75f;
|
||||
fp3 = fp1 + 2.25f;
|
||||
printf("addition: %s+%s=%s\n", _ftostr(buf, fp3), _ftostr(buf3, 0.05f), _ftostr(buf2, fp1));
|
||||
printf(" fp3:0x%08lx [0x42860000] %s (exp:67.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42860000");
|
||||
|
||||
/* subtraction, variable - constant */
|
||||
fp1 = 16.25f;
|
||||
fp3 = fp1 - 8.5f;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 8.5f), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "40f80000");
|
||||
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.3f;
|
||||
fp3 = fp2 - 0.1f;
|
||||
printf("fp3:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3e4cccce");
|
||||
fp3 = fp1 - 0.3f;
|
||||
printf("fp3:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "be4cccce");
|
||||
|
||||
/* multiplication, variable * constant */
|
||||
fp1 = 16.25f;
|
||||
fp3 = fp1 * 2.5f;
|
||||
printf("multiplication: %s*%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 2.3f), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x42228000] %s (exp:40.625)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42228000");
|
||||
|
||||
/* division, variable / constant */
|
||||
fp1 = 32.5f;
|
||||
fp3 = fp1 / 2.5f;
|
||||
printf("division: %s/%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 2.3f), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x41500000] %s (exp:13.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "41500000");
|
||||
}
|
||||
|
||||
void varconst2(void)
|
||||
{
|
||||
printf("\n*** variable vs constant\n\n");
|
||||
|
||||
/* addition, variable + constant */
|
||||
fp1 = 64.75f;
|
||||
fp1 += 2.25f;
|
||||
printf("addition: %s+%s=%s\n", _ftostr(buf, 64.75f), _ftostr(buf3, 2.25f), _ftostr(buf2, fp1));
|
||||
printf(" fp1:0x%08lx [0x42860000] %s (exp:67.0)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42860000");
|
||||
|
||||
/* subtraction, variable - constant */
|
||||
fp1 = 16.25f;
|
||||
fp1 -= 8.5f;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 8.5f), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "40f80000");
|
||||
|
||||
fp1 = 0.3f;
|
||||
fp1 -= 0.1f;
|
||||
printf("fp1:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "3e4cccce");
|
||||
|
||||
fp1 = 0.1f;
|
||||
fp1 -= 0.3f;
|
||||
printf("fp1:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "be4cccce");
|
||||
|
||||
/* multiplication, variable * constant */
|
||||
fp1 = 16.25f;
|
||||
fp1 *= 2.5f;
|
||||
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 2.5f), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x42228000] %s (exp:40.625)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42228000");
|
||||
|
||||
/* division, variable / constant */
|
||||
fp1 = 32.5f;
|
||||
fp1 /= 2.5f;
|
||||
printf("division: %s/%s=%s\n", _ftostr(buf, 32.5f), _ftostr(buf2, 2.5f), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x41500000] %s (exp:13.0)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "41500000");
|
||||
}
|
||||
#endif
|
||||
|
||||
void varconst3(void)
|
||||
{
|
||||
float localfp3;
|
||||
float localfp2;
|
||||
float localfp1;
|
||||
float localfp4;
|
||||
float localfp5;
|
||||
printf("\n*** local variable vs constant\n\n");
|
||||
#if 1 // compiles, wrong result
|
||||
/* addition, variable + constant */
|
||||
localfp1 = 64.75f;
|
||||
localfp1 += 2.25f;
|
||||
printf("addition: %s+%s=%s\n", _ftostr(buf, 64.75f), _ftostr(buf3, 2.25f), _ftostr(buf2, localfp1));
|
||||
printf(" localfp1:0x%08lx [0x42860000] %s (exp:67.0)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
|
||||
test1(localfp1, "42860000");
|
||||
#endif
|
||||
#if 1 // compiles, wrong result
|
||||
/* subtraction, variable - constant */
|
||||
localfp1 = 16.25f;
|
||||
localfp1 -= 8.5f;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 8.5f), _ftostr(buf3, localfp1));
|
||||
printf(" localfp1:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
|
||||
test1(localfp1, "40f80000");
|
||||
|
||||
localfp1 = 0.3f;
|
||||
localfp1 -= 0.1f;
|
||||
printf("localfp1:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
|
||||
test1(localfp1, "3e4cccce");
|
||||
|
||||
localfp1 = 0.1f;
|
||||
localfp1 -= 0.3f;
|
||||
printf("localfp1:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
|
||||
test1(localfp1, "be4cccce");
|
||||
#endif
|
||||
#if 1
|
||||
/* multiplication, variable * constant */
|
||||
localfp1 = 16.25f;
|
||||
localfp1 *= 2.5f;
|
||||
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 2.5f), _ftostr(buf3, localfp1));
|
||||
printf(" localfp1:0x%08lx [0x42228000] %s (exp:40.625)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
|
||||
test1(localfp1, "42228000");
|
||||
|
||||
/* division, variable / constant */
|
||||
localfp1 = 32.5f;
|
||||
localfp1 /= 2.5f;
|
||||
printf("division: %s/%s=%s\n", _ftostr(buf, 32.5f), _ftostr(buf2, 2.5f), _ftostr(buf3, localfp1));
|
||||
printf(" localfp1:0x%08lx [0x41500000] %s (exp:13.0)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
|
||||
test1(localfp1, "41500000");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("float-basic-var-const\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));
|
||||
|
||||
varconst();
|
||||
varconst2();
|
||||
varconst3();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-var-const (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
fp1 = 16.25f;
|
||||
fp3 = fp1 - 8.5f;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 8.5f), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
return result;
|
||||
}
|
||||
#endif
|
167
test/val/float-basic-var-intconst.c
Normal file
167
test/val/float-basic-var-intconst.c
Normal file
|
@ -0,0 +1,167 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
int i;
|
||||
|
||||
unsigned char var_char;
|
||||
unsigned int var_int;
|
||||
float var_float;
|
||||
|
||||
#if 1
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf("[%s:%s]", temp, str);
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void SKIPPEDtest1(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf(" (SKIPPED:%s:%s)\n", temp, str);
|
||||
}
|
||||
|
||||
void varintconst(void)
|
||||
{
|
||||
|
||||
var_float = 11.123f;
|
||||
|
||||
fp1 = 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
/* addition */
|
||||
fp1 = var_float + 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#if 1
|
||||
fp1 = var_float - 47;
|
||||
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "c20f820c");
|
||||
#endif
|
||||
#if 0 // works but gives wrong result
|
||||
fp1 = var_float * 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
#if 0 // works but gives wrong result
|
||||
fp1 = var_float / 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void varintconst2(void)
|
||||
{
|
||||
|
||||
var_float = 11.123f;
|
||||
|
||||
printf("float *= int const\n");
|
||||
|
||||
fp1 = 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
#if 0 // works but gives wrong result
|
||||
/* addition */
|
||||
fp1 = var_float;
|
||||
fp1 += 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
#if 0 // works but gives wrong result
|
||||
fp1 = var_float;
|
||||
fp1 -= 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
#if 0 // works but gives wrong result
|
||||
fp1 = var_float;
|
||||
fp1 *= 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
#if 0 // works but gives wrong result
|
||||
fp1 = var_float;
|
||||
fp1 /= 47;
|
||||
printf("fp1:0x%08lx [42687df4] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-var-intconst ***\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));
|
||||
|
||||
varintconst();
|
||||
varintconst2();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-var-intconst (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
fp1 = var_float - 47;
|
||||
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float - 47.0f;
|
||||
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
return result;
|
||||
}
|
||||
#endif
|
152
test/val/float-basic-var-intvar.c
Normal file
152
test/val/float-basic-var-intvar.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
int i;
|
||||
|
||||
unsigned char var_char;
|
||||
unsigned int var_int;
|
||||
float var_float;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf("[%s:%s]", temp, str);
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
} else {
|
||||
printf(" (failed) !!! ");
|
||||
result++;
|
||||
}
|
||||
printf("result:%d\n", result);
|
||||
}
|
||||
|
||||
void SKIPPEDtest1(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
printf(" (SKIPPED:%s:%s)\n", temp, str);
|
||||
}
|
||||
|
||||
void intvar(void)
|
||||
{
|
||||
|
||||
var_int = 47;
|
||||
var_float = 11.123f;
|
||||
fp1 = var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
/* addition */
|
||||
fp1 = var_float + var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
|
||||
fp1 = var_float - var_int;
|
||||
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "c20f820c");
|
||||
|
||||
fp1 = var_float * var_int;
|
||||
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "4402b1fc");
|
||||
|
||||
fp1 = var_float / var_int;
|
||||
printf("fp1:0x%08lx [3e7256e3] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "3e7256e3");
|
||||
}
|
||||
|
||||
void intvar2(void)
|
||||
{
|
||||
|
||||
var_int = 47;
|
||||
var_float = 11.123f;
|
||||
|
||||
printf("float var *= int var\n");
|
||||
|
||||
fp1 = var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
fp1 = var_float;
|
||||
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
|
||||
#if 0 // compiles, but wrong result
|
||||
/* addition */
|
||||
fp1 = var_float;
|
||||
fp1 += var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
#if 0 // compiles, but wrong result
|
||||
/* subtraction */
|
||||
fp1 = var_float;
|
||||
fp1 -= var_int;
|
||||
printf("fp1:0x%08lx [42687df4] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42687df4");
|
||||
#endif
|
||||
/* multiplication */
|
||||
fp1 = var_float;
|
||||
fp1 *= var_int;
|
||||
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "4402b1fc");
|
||||
|
||||
/* division */
|
||||
fp1 = var_float;
|
||||
fp1 /= var_int;
|
||||
printf("fp1:0x%08lx [3e7256e3] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "3e7256e3");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("*** float-basic-var-intvar ***\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));
|
||||
|
||||
intvar();
|
||||
intvar2();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-var-intvar (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
179
test/val/float-basic-var-var.c
Normal file
179
test/val/float-basic-var-var.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#if 1
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf(" (ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed) !!!\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
void varvar(void)
|
||||
{
|
||||
printf("\nvariable vs variable\n\n");
|
||||
|
||||
/* addition, variable + variable */
|
||||
fp1 = 16.5f;
|
||||
fp2 = 64.25f;
|
||||
fp3 = fp1 + fp2; // = 80.75f
|
||||
printf("addition: %s+%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x42a18000] %s (exp:80.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "42a18000");
|
||||
|
||||
/* subtraction, variable - variable */
|
||||
fp1 = 64.25f;
|
||||
fp2 = 16.5f;
|
||||
fp3 = fp1 - fp2;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x423f0000] %s (exp:47.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "423f0000");
|
||||
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.3f;
|
||||
|
||||
fp3 = fp2 - fp1;
|
||||
printf("fp3:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3e4cccce");
|
||||
fp3 = fp1 - fp2;
|
||||
printf("fp3:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "be4cccce");
|
||||
|
||||
/* multiplication, variable * variable */
|
||||
fp1 = 8.5f;
|
||||
fp2 = 2.25f;
|
||||
fp3 = fp1 * fp2;
|
||||
printf("multiplication: %s*%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x41990000] %s (exp:19.125)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "41990000");
|
||||
|
||||
/* division, variable / variable */
|
||||
fp1 = 16.25f;
|
||||
fp2 = 2.5f;
|
||||
fp3 = fp1 / fp2;
|
||||
printf("division: %s/%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
|
||||
printf(" fp3:0x%08lx [0x40d00000] %s (exp:6.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "40d00000");
|
||||
}
|
||||
|
||||
void varvar2(void)
|
||||
{
|
||||
printf("\nvariable vs variable\n\n");
|
||||
|
||||
#if 0 // compiles, but wrong result
|
||||
/* addition, variable + variable */
|
||||
fp1 = 16.5f;
|
||||
fp2 = 64.25f;
|
||||
fp1 += fp2; // = 80.75f
|
||||
printf("addition: %s+%s=%s\n", _ftostr(buf, 16.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x42a18000] %s (exp:80.75)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "42a18000");
|
||||
#endif
|
||||
#if 0 // compiles, but wrong result
|
||||
/* subtraction, variable - variable */
|
||||
fp1 = 64.25f;
|
||||
fp2 = 16.5f;
|
||||
fp1 -= fp2;
|
||||
printf("substraction: %s-%s=%s\n", _ftostr(buf, 64.25f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x423f0000] %s (exp:47.75)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "423f0000");
|
||||
|
||||
fp1 = 0.3f;
|
||||
fp2 = 0.1f;
|
||||
fp1 -= fp2;
|
||||
printf("fp1:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "3e4cccce");
|
||||
|
||||
fp1 = 0.1f;
|
||||
fp2 = 0.1f;
|
||||
fp1 -= fp2;
|
||||
printf("fp1:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "be4cccce");
|
||||
#endif
|
||||
/* multiplication, variable * variable */
|
||||
fp1 = 8.5f;
|
||||
fp2 = 2.25f;
|
||||
fp1 *= fp2;
|
||||
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 8.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x41990000] %s (exp:19.125)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "41990000");
|
||||
|
||||
/* division, variable / variable */
|
||||
fp1 = 16.25f;
|
||||
fp2 = 2.5f;
|
||||
fp1 /= fp2;
|
||||
printf("division: %s/%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
|
||||
printf(" fp1:0x%08lx [0x40d00000] %s (exp:6.5)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
|
||||
test1(fp1, "40d00000");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("float-basic-var-var\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));
|
||||
|
||||
varvar();
|
||||
varvar2();
|
||||
WAIT();
|
||||
|
||||
printf("\nfloat-basic-var-var (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
int main(void)
|
||||
{
|
||||
fp1 = 16.5f;
|
||||
fp2 = 64.25f;
|
||||
fp1 += fp2; // = 80.75f
|
||||
return result;
|
||||
}
|
||||
#endif
|
105
test/val/float-bnegate.c
Normal file
105
test/val/float-bnegate.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
|
||||
// test basic arithmetic operations
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
float fp1 = 12.34f;
|
||||
float fp2; // non initialized
|
||||
float fp3, fp4 = 55.55f;
|
||||
|
||||
char buf[0x20];
|
||||
char buf2[0x20];
|
||||
char buf3[0x20];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
// returns 1 if value in f matches the string
|
||||
// the string is a hex value without leading "0x"
|
||||
int compare(float f, char *str)
|
||||
{
|
||||
char temp[12];
|
||||
sprintf(temp, "%08lx", *((uint32_t*)&f));
|
||||
return (strcmp(temp, str) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void test1(float f, char *str)
|
||||
{
|
||||
if (compare(f, str)) {
|
||||
// printf("(ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed)\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
void test2(long n, long val)
|
||||
{
|
||||
if (n == val) {
|
||||
// printf("(ok)");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" (failed)\n");
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float fp2 = 43.21f;
|
||||
|
||||
printf("float-binary negate (not)\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));
|
||||
|
||||
fp1 = 0.0f;
|
||||
fp2 = !fp1;
|
||||
var_sint = !fp1;
|
||||
fp3 = !fp2;
|
||||
printf("fp2 0x%08lx [0x3f800000] %s (!0=1) %d", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
|
||||
test1(fp2, "3f800000");
|
||||
printf("fp3 0x%08lx [0x00000000] %s (!1=0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "00000000");
|
||||
|
||||
fp1 = 12.6f;
|
||||
fp2 = !fp1;
|
||||
var_sint = !fp1;
|
||||
fp3 = !fp2;
|
||||
printf("fp2 0x%08lx [0x00000000] %s (!12.6f=0) %d", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
|
||||
test1(fp2, "00000000");
|
||||
printf("fp3 0x%08lx [0x3f800000] %s (!0=1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3f800000");
|
||||
|
||||
fp1 = -12.6f;
|
||||
fp2 = !fp1;
|
||||
var_sint = !fp1;
|
||||
fp3 = !fp2;
|
||||
printf("fp2 0x%08lx [0x00000000] %s (!-12.6f=0) %d", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
|
||||
test1(fp2, "00000000");
|
||||
printf("fp3 0x%08lx [0x3f800000] %s (!0=1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
|
||||
test1(fp3, "3f800000");
|
||||
|
||||
printf("float-binary negate (res:%d)\n", result);
|
||||
return result;
|
||||
}
|
80
test/val/float-cmp-const-const.c
Normal file
80
test/val/float-cmp-const-const.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : ""); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
void constconst(void)
|
||||
{
|
||||
printf("const vs const\n");
|
||||
|
||||
expect("1.5f == 1.6f is", 0, (1.5f == 1.6f));
|
||||
expect("1.6f == 1.5f is", 0, (1.6f == 1.5f));
|
||||
expect("1.6f == 1.6f is", 1, (1.6f == 1.6f));
|
||||
|
||||
expect("1.5f != 1.6f is", 1, (1.5f != 1.6f));
|
||||
expect("1.6f != 1.5f is", 1, (1.6f != 1.5f));
|
||||
expect("1.6f != 1.6f is", 0, (1.6f != 1.6f));
|
||||
|
||||
expect("1.5f < 1.6f is", 1, (1.5f < 1.6f));
|
||||
expect("1.6f < 1.5f is", 0, (1.6f < 1.5f));
|
||||
expect("1.6f < 1.6f is", 0, (1.6f < 1.6f));
|
||||
|
||||
expect("1.5f > 1.6f is", 0, (1.5f > 1.6f));
|
||||
expect("1.6f > 1.5f is", 1, (1.6f > 1.5f));
|
||||
expect("1.6f > 1.6f is", 0, (1.6f > 1.6f));
|
||||
|
||||
expect("1.5f <= 1.6f is", 1, (1.5f <= 1.6f));
|
||||
expect("1.6f <= 1.5f is", 0, (1.6f <= 1.5f));
|
||||
expect("1.6f <= 1.6f is", 1, (1.6f <= 1.6f));
|
||||
|
||||
expect("1.5f >= 1.6f is", 0, (1.5f >= 1.6f));
|
||||
expect("1.6f >= 1.5f is", 1, (1.6f >= 1.5f));
|
||||
expect("1.6f >= 1.6f is", 1, (1.6f >= 1.6f));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-const-const\n");
|
||||
|
||||
constconst();
|
||||
|
||||
printf("float-cmp-const-const (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
80
test/val/float-cmp-const-intconst.c
Normal file
80
test/val/float-cmp-const-intconst.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : ""); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
void constintconst(void)
|
||||
{
|
||||
printf("const vs int const\n");
|
||||
|
||||
expect("10.0f == 20 is", 0, (10.0f == 20));
|
||||
expect("20.0f == 10 is", 0, (20.0f == 10));
|
||||
expect("20.0f == 20 is", 1, (20.0f == 20));
|
||||
|
||||
expect("10.0f != 20 is", 1, (10.0f != 20));
|
||||
expect("20.0f != 10 is", 1, (20.0f != 10));
|
||||
expect("20.0f != 20 is", 0, (20.0f != 20));
|
||||
|
||||
expect("10.0f < 20 is", 1, (10.0f < 20));
|
||||
expect("20.0f < 10 is", 0, (20.0f < 10));
|
||||
expect("20.0f < 20 is", 0, (20.0f < 20));
|
||||
|
||||
expect("10.0f > 20 is", 0, (10.0f > 20));
|
||||
expect("20.0f > 10 is", 1, (20.0f > 10));
|
||||
expect("20.0f > 20 is", 0, (20.0f > 20));
|
||||
|
||||
expect("10.0f <= 20 is", 1, (10.0f <= 20));
|
||||
expect("20.0f <= 10 is", 0, (20.0f <= 10));
|
||||
expect("20.0f <= 20 is", 1, (20.0f <= 20));
|
||||
|
||||
expect("10.0f >= 20 is", 0, (10.0f >= 20));
|
||||
expect("20.0f >= 10 is", 1, (20.0f >= 10));
|
||||
expect("20.0f >= 20 is", 1, (20.0f >= 20));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-const-intconst\n");
|
||||
|
||||
constintconst();
|
||||
|
||||
printf("float-cmp-const-intconst (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
85
test/val/float-cmp-const-intvar.c
Normal file
85
test/val/float-cmp-const-intvar.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : ""); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
int i1 = 10;
|
||||
int i2 = 20;
|
||||
|
||||
void constintvar(void)
|
||||
{
|
||||
printf("const vs int var\n");
|
||||
|
||||
#if 0 // compiles but produces wrong results
|
||||
expect("10.0f == 20 is", 0, (10.0f == i2));
|
||||
expect("20.0f == 10 is", 0, (20.0f == i1));
|
||||
expect("20.0f == 20 is", 1, (20.0f == i2));
|
||||
|
||||
expect("10.0f != 20 is", 1, (10.0f != i2));
|
||||
expect("20.0f != 10 is", 1, (20.0f != i1));
|
||||
expect("20.0f != 20 is", 0, (20.0f != i2));
|
||||
|
||||
expect("10.0f < 20 is", 1, (10.0f < i2));
|
||||
expect("20.0f < 10 is", 0, (20.0f < i1));
|
||||
expect("20.0f < 20 is", 0, (20.0f < i2));
|
||||
|
||||
expect("10.0f > 20 is", 0, (10.0f > i2));
|
||||
expect("20.0f > 10 is", 1, (20.0f > i1));
|
||||
expect("20.0f > 20 is", 0, (20.0f > i2));
|
||||
|
||||
expect("10.0f <= 20 is", 1, (10.0f <= i2));
|
||||
expect("20.0f <= 10 is", 0, (20.0f <= i1));
|
||||
expect("20.0f <= 20 is", 1, (20.0f <= i2));
|
||||
|
||||
expect("10.0f >= 20 is", 0, (10.0f >= i2));
|
||||
expect("20.0f >= 10 is", 1, (20.0f >= i1));
|
||||
expect("20.0f >= 20 is", 1, (20.0f >= i2));
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-const-intvar\n");
|
||||
|
||||
constintvar();
|
||||
|
||||
printf("float-cmp-const-intvar (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
83
test/val/float-cmp-const-var.c
Normal file
83
test/val/float-cmp-const-var.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : ""); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
void constvar(void)
|
||||
{
|
||||
printf("const vs var\n");
|
||||
|
||||
expect("1.5f == 1.6f is", 0, (1.5f == fp1));
|
||||
expect("1.6f == 1.5f is", 0, (1.6f == fp2));
|
||||
expect("1.6f == 1.6f is", 1, (1.6f == fp1));
|
||||
|
||||
expect("1.5f != 1.6f is", 1, (1.5f != fp1));
|
||||
expect("1.6f != 1.5f is", 1, (1.6f != fp2));
|
||||
expect("1.6f != 1.6f is", 0, (1.6f != fp1));
|
||||
|
||||
expect("1.5f < 1.6f is", 1, (1.5f < fp1));
|
||||
expect("1.6f < 1.5f is", 0, (1.6f < fp2));
|
||||
expect("1.6f < 1.6f is", 0, (1.6f < fp1));
|
||||
|
||||
expect("1.5f > 1.6f is", 0, (1.5f > fp1));
|
||||
expect("1.6f > 1.5f is", 1, (1.6f > fp2));
|
||||
expect("1.6f > 1.6f is", 0, (1.6f > fp1));
|
||||
|
||||
expect("1.5f <= 1.6f is", 1, (1.5f <= fp1));
|
||||
expect("1.6f <= 1.5f is", 0, (1.6f <= fp2));
|
||||
expect("1.6f <= 1.6f is", 1, (1.6f <= fp1));
|
||||
|
||||
expect("1.5f >= 1.6f is", 0, (1.5f >= fp1));
|
||||
expect("1.6f >= 1.5f is", 1, (1.6f >= fp2));
|
||||
expect("1.6f >= 1.6f is", 1, (1.6f >= fp1));
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-const-var\n");
|
||||
|
||||
fp1 = 1.6f;
|
||||
fp2 = 1.5f;
|
||||
constvar();
|
||||
|
||||
printf("float-cmp-const-var (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
81
test/val/float-cmp-intconst-const.c
Normal file
81
test/val/float-cmp-intconst-const.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : ""); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
|
||||
void intconstconst(void)
|
||||
{
|
||||
printf("int const vs const\n");
|
||||
|
||||
expect("10 == 20.0f is", 0, (10 == 20.0f));
|
||||
expect("20 == 10.0f is", 0, (20 == 10.0f));
|
||||
expect("20 == 20.0f is", 1, (20 == 20.0f));
|
||||
|
||||
expect("10 != 20.0f is", 1, (10 != 20.0f));
|
||||
expect("20 != 10.0f is", 1, (20 != 10.0f));
|
||||
expect("20 != 20.0f is", 0, (20 != 20.0f));
|
||||
|
||||
expect("10 < 20.0f is", 1, (10 < 20.0f));
|
||||
expect("20 < 10.0f is", 0, (20 < 10.0f));
|
||||
expect("20 < 20.0f is", 0, (20 < 20.0f));
|
||||
|
||||
expect("10 > 20.0f is", 0, (10 > 20.0f));
|
||||
expect("20 > 10.0f is", 1, (20 > 10.0f));
|
||||
expect("20 > 20.0f is", 0, (20 > 20.0f));
|
||||
|
||||
expect("10 <= 20.0f is", 1, (10 <= 20.0f));
|
||||
expect("20 <= 10.0f is", 0, (20 <= 10.0f));
|
||||
expect("20 <= 20.0f is", 1, (20 <= 20.0f));
|
||||
|
||||
expect("10 >= 20.0f is", 0, (10 >= 20.0f));
|
||||
expect("20 >= 10.0f is", 1, (20 >= 10.0f));
|
||||
expect("20 >= 20.0f is", 1, (20 >= 20.0f));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-intconst-const\n");
|
||||
|
||||
intconstconst();
|
||||
|
||||
printf("float-cmp-intconst-const (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
99
test/val/float-cmp-intconst-var.c
Normal file
99
test/val/float-cmp-intconst-var.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val, fval) \
|
||||
printf("%s %d:%d:%s%s (is:%d want:%d fval:%s)\n", \
|
||||
msg, val, exp, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : "", \
|
||||
val, exp, _ftostr(buf, fval) \
|
||||
); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void seperate(void)
|
||||
{
|
||||
int res;
|
||||
fp1 = 10.0f;
|
||||
fp2 = 20.0f;
|
||||
// res = (20.0f == fp2); // works
|
||||
res = (20 == fp2); // fails
|
||||
printf("res:%d\n", res);
|
||||
}
|
||||
|
||||
void intconstvar(void)
|
||||
{
|
||||
printf("int const vs var\n");
|
||||
|
||||
fp1 = 10.0f;
|
||||
fp2 = 20.0f;
|
||||
|
||||
#if 1
|
||||
expect("10 == 20 is", 0, (10 == fp2), fp2);
|
||||
expect("20 == 10 is", 0, (20 == fp1), fp1);
|
||||
expect("20 == 20 is", 1, (20 == fp2), fp2);
|
||||
|
||||
expect("10 != 20 is", 1, (10 != fp2), fp2);
|
||||
expect("20 != 10 is", 1, (20 != fp1), fp1);
|
||||
expect("20 != 20 is", 0, (20 != fp2), fp2);
|
||||
|
||||
expect("10 < 20 is", 1, (10 < fp2), fp2);
|
||||
expect("20 < 10 is", 0, (20 < fp1), fp1);
|
||||
expect("20 < 20 is", 0, (20 < fp2), fp2);
|
||||
|
||||
expect("10 > 20 is", 0, (10 > fp2), fp2);
|
||||
expect("20 > 10 is", 1, (20 > fp1), fp1);
|
||||
expect("20 > 20 is", 0, (20 > fp2), fp2);
|
||||
|
||||
expect("10 <= 20 is", 1, (10 <= fp2), fp2);
|
||||
expect("20 <= 10 is", 0, (20 <= fp1), fp1);
|
||||
expect("20 <= 20 is", 1, (20 <= fp2), fp2);
|
||||
|
||||
expect("10 >= 20 is", 0, (10 >= fp2), fp2);
|
||||
expect("20 >= 10 is", 1, (20 >= fp1), fp1);
|
||||
expect("20 >= 20 is", 1, (20 >= fp2), fp2);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-intconst-var\n");
|
||||
|
||||
seperate();
|
||||
intconstvar();
|
||||
|
||||
printf("float-cmp-intconst-var (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
85
test/val/float-cmp-intvar-const.c
Normal file
85
test/val/float-cmp-intvar-const.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : ""); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
int i1 = 10;
|
||||
int i2 = 20;
|
||||
|
||||
void intvarconst(void)
|
||||
{
|
||||
printf("int var vs const\n");
|
||||
|
||||
#if 0 // internal compiler error
|
||||
expect("10 == 20.0f is", 0, (i1 == 20.0f));
|
||||
expect("20 == 10.0f is", 0, (i2 == 10.0f));
|
||||
expect("20 == 20.0f is", 1, (i2 == 20.0f));
|
||||
|
||||
expect("10 != 20.0f is", 1, (i1 != 20.0f));
|
||||
expect("20 != 10.0f is", 1, (i2 != 10.0f));
|
||||
expect("20 != 20.0f is", 0, (i2 != 20.0f));
|
||||
|
||||
expect("10 < 20.0f is", 1, (i1 < 20.0f));
|
||||
expect("20 < 10.0f is", 0, (i2 < 10.0f));
|
||||
expect("20 < 20.0f is", 0, (i2 < 20.0f));
|
||||
|
||||
expect("10 > 20.0f is", 0, (i1 > 20.0f));
|
||||
expect("20 > 10.0f is", 1, (i2 > 10.0f));
|
||||
expect("20 > 20.0f is", 0, (i2 > 20.0f));
|
||||
|
||||
expect("10 <= 20.0f is", 1, (i1 <= 20.0f));
|
||||
expect("20 <= 10.0f is", 0, (i2 <= 10.0f));
|
||||
expect("20 <= 20.0f is", 1, (i2 <= 20.0f));
|
||||
|
||||
expect("10 >= 20.0f is", 0, (i1 >= 20.0f));
|
||||
expect("20 >= 10.0f is", 1, (i2 >= 10.0f));
|
||||
expect("20 >= 20.0f is", 1, (i2 >= 20.0f));
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-intvar-const\n");
|
||||
|
||||
intvarconst();
|
||||
|
||||
printf("float-cmp-intvar-const (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
102
test/val/float-cmp-intvar-var.c
Normal file
102
test/val/float-cmp-intvar-var.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val, fval) \
|
||||
printf("%s %d:%d:%s%s (is:%d want:%d fval:%s)\n", \
|
||||
msg, val, exp, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : "", \
|
||||
val, exp, _ftostr(buf, fval) \
|
||||
); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void seperate(void)
|
||||
{
|
||||
int res;
|
||||
fp1 = 10.0f;
|
||||
fp2 = 20.0f;
|
||||
// res = (20.0f == fp2); // works
|
||||
res = (20 == fp2); // fails
|
||||
printf("res:%d\n", res);
|
||||
}
|
||||
|
||||
int i1 = 10;
|
||||
int i2 = 20;
|
||||
|
||||
void intvarvar(void)
|
||||
{
|
||||
printf("int const vs var\n");
|
||||
|
||||
fp1 = 10.0f;
|
||||
fp2 = 20.0f;
|
||||
|
||||
#if 1
|
||||
expect("10 == 20 is", 0, (i1 == fp2), fp2);
|
||||
expect("20 == 10 is", 0, (i2 == fp1), fp1);
|
||||
expect("20 == 20 is", 1, (i2 == fp2), fp2);
|
||||
|
||||
expect("10 != 20 is", 1, (i1 != fp2), fp2);
|
||||
expect("20 != 10 is", 1, (i2 != fp1), fp1);
|
||||
expect("20 != 20 is", 0, (i2 != fp2), fp2);
|
||||
|
||||
expect("10 < 20 is", 1, (i1 < fp2), fp2);
|
||||
expect("20 < 10 is", 0, (i2 < fp1), fp1);
|
||||
expect("20 < 20 is", 0, (i2 < fp2), fp2);
|
||||
|
||||
expect("10 > 20 is", 0, (i1 > fp2), fp2);
|
||||
expect("20 > 10 is", 1, (i2 > fp1), fp1);
|
||||
expect("20 > 20 is", 0, (i2 > fp2), fp2);
|
||||
|
||||
expect("10 <= 20 is", 1, (i1 <= fp2), fp2);
|
||||
expect("20 <= 10 is", 0, (i2 <= fp1), fp1);
|
||||
expect("20 <= 20 is", 1, (i2 <= fp2), fp2);
|
||||
|
||||
expect("10 >= 20 is", 0, (i1 >= fp2), fp2);
|
||||
expect("20 >= 10 is", 1, (i2 >= fp1), fp1);
|
||||
expect("20 >= 20 is", 1, (i2 >= fp2), fp2);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-intvar-var\n");
|
||||
|
||||
seperate();
|
||||
intvarvar();
|
||||
|
||||
printf("float-cmp-intvar-var (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
87
test/val/float-cmp-var-const.c
Normal file
87
test/val/float-cmp-var-const.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
|
||||
// test comparison operations
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <_float.h>
|
||||
|
||||
#ifdef CONIO
|
||||
#include <conio.h>
|
||||
#define WAIT() cgetc()
|
||||
#else
|
||||
#define WAIT()
|
||||
#endif
|
||||
|
||||
float fp1, fp2, fp3, fp4;
|
||||
|
||||
char buf[0x30];
|
||||
char buf2[0x30];
|
||||
char buf3[0x30];
|
||||
|
||||
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 result = 0;
|
||||
|
||||
#define expect(msg, exp, val) \
|
||||
printf("%s %s%s (is:%d want:%d)\n", \
|
||||
msg, \
|
||||
val ? "true" : "false", \
|
||||
(exp != val) ? " (failed)" : "", \
|
||||
exp, val \
|
||||
); \
|
||||
if (exp != val) { \
|
||||
result++; \
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// float variable vs float constant
|
||||
|
||||
void varconst(void)
|
||||
{
|
||||
printf("var vs const\n");
|
||||
|
||||
fp1 = 1.6f;
|
||||
fp2 = 1.5f;
|
||||
|
||||
expect("1.5f == 1.6f is", 0, (fp2 == 1.6f));
|
||||
expect("1.6f == 1.5f is", 0, (fp1 == 1.5f));
|
||||
expect("1.6f == 1.6f is", 1, (fp1 == 1.6f));
|
||||
|
||||
expect("1.5f != 1.6f is", 1, (fp2 != 1.6f));
|
||||
expect("1.6f != 1.5f is", 1, (fp1 != 1.5f));
|
||||
expect("1.6f != 1.6f is", 0, (fp1 != 1.6f));
|
||||
|
||||
expect("1.5f < 1.6f is", 1, (fp2 < 1.6f));
|
||||
expect("1.6f < 1.5f is", 0, (fp1 < 1.5f));
|
||||
expect("1.6f < 1.6f is", 0, (fp1 < 1.6f));
|
||||
|
||||
expect("1.5f > 1.6f is", 0, (fp2 > 1.6f));
|
||||
expect("1.6f > 1.5f is", 1, (fp1 > 1.5f));
|
||||
expect("1.6f > 1.6f is", 0, (fp1 > 1.6f));
|
||||
|
||||
expect("1.5f <= 1.6f is", 1, (fp2 <= 1.6f));
|
||||
expect("1.6f <= 1.5f is", 0, (fp1 <= 1.5f));
|
||||
expect("1.6f <= 1.6f is", 1, (fp1 <= 1.6f));
|
||||
|
||||
expect("1.5f >= 1.6f is", 0, (fp2 >= 1.6f));
|
||||
expect("1.6f >= 1.5f is", 1, (fp1 >= 1.5f));
|
||||
expect("1.6f >= 1.6f is", 1, (fp1 >= 1.6f));
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("float-cmp-var-const\n");
|
||||
|
||||
varconst();
|
||||
|
||||
printf("float-cmp-var-const (res: %d)\n", result);
|
||||
return result;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user