; float-ecb.inc - Part of Standard CMOC library under Extended Color Basic.
;
; This file contains code that calls Color Basic and Extended Color
; Basic routines.

FP0ADDR	EQU	$004F
FP1ADDR	EQU	$005C

; Fields of Color Basic's first two (unpacked) float point accumulators.
FP0EXP	EQU	FP0ADDR
FP0MAN	EQU	FP0ADDR+1
FP0SGN	EQU	FP0ADDR+5
FP1EXP	EQU	FP1ADDR
FP1MAN	EQU	FP1ADDR+1
FP1SGN	EQU	FP1ADDR+5

VALTYP	EQU	$0006		; variable type (0 = numeric)
FPCARY  EQU     $005B           ; floating point carry byte
RESSGN	EQU	$0062		; sign of result of operation
FPSBYT  EQU     $0063           ; floating point sub byte

GETCCH	EQU	$00A5
CHARAD	EQU	$00A6		; interpreter's input pointer
COEFCT	EQU	$0055		; polynomial coefficient counter


#if defined(_CMOC_NEED_initSingleFromSignedWord_)

; Initializes the single-precision float at X with the signed word in D.
;
initSingleFromSignedWord
	pshs	u,y,x
	jsr	$B4F4			; load D (signed) into FPA0
	puls	x
	jsr	$BC35			; pack FPA0 into X
	puls	y,u,pc			; not implemented

#endif  /* defined(initSingleFromSignedWord_) */


#if defined(_CMOC_NEED_initSingleFromUnsignedWord_)

; Initializes the single-precision float at X with the unsigned word in D.
;
initSingleFromUnsignedWord
	pshs	u,y,x
	lbsr	loadUnsignedDInFPA0	; load D (unsigned) into FPA0
	puls	x
	jsr	$BC35			; pack FPA0 into X
	puls	y,u,pc			; not implemented

#endif  /* defined(_CMOC_NEED_initSingleFromUnsignedWord_) */


#if defined(_CMOC_NEED_negateSingle_)

; Negates the packed single-precision float at X.
; Preserves X.
;
negateSingle
	ldb	1,x
	eorb	#$80
	stb	1,x
	rts

#endif  /* defined(_CMOC_NEED_negateSingle_) */


#if defined(_CMOC_NEED_isSingleZero_)

; Sets the Z flag to 1 if the packed single-precision float at X is zero.
; Sets the Z flag to 0 otherwise.
; Preserves X.
;
isSingleZero
	tst	,x		; null exponent byte means number is zero
	rts

#endif  /* defined(_CMOC_NEED_isSingleZero_) */


#if defined(_CMOC_NEED_incrementSingle_)

; Adds one 1 to the packed single-precision float at X.
; Preserves X.
;
incrementSingle
	pshs	u,y,x
	jsr	$BC14		; unpack into Basic's FPA0 (preserves X)
	leax	packed1,DAT
	jsr	$B9C2		; add number at X to FPA0 (trashes X)
	ldx	,s		; retrieve original number address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc
packed1
	fcb	$81		; packed 1.0
	fdb	0
	fdb	0

#endif  /* defined(_CMOC_NEED_incrementSingle_) */


#if defined(_CMOC_NEED_decrementSingle_)

; Subtracts one 1 from the packed single-precision float at X.
; Preserves X.
;
decrementSingle
	pshs	u,y,x
	jsr	$BC14		; unpack into Basic's FPA0 (preserves X)
	leax	packedMinus1,DAT
	jsr	$B9C2		; add number at X to FPA0 (trashes X)
	ldx	,s		; retrieve original number address
	jsr	$BC35		; pack FPA0 at X
	puls	x,y,u,pc
packedMinus1
	fcb	$81		; packed -1.0
	fdb	$8000
	fdb	0

#endif  /* defined(_CMOC_NEED_decrementSingle_) */


#if defined(_CMOC_NEED_copySingle_)

; Copies a packed single-precision number.
; Input: Address in stack = address of source number.
;        X = address of destination number.
; Preserves X.
;
copySingle
	pshs	u
	ldu	4,s	; address of source number
	ldd	,u
	std	,x
	ldd	2,u
	std	2,x
	ldb	4,u
	stb	4,x
	puls	u,pc

#endif  /* defined(_CMOC_NEED_copySingle_) */


#if defined(_CMOC_NEED_addSingleSingle_) || defined(_CMOC_NEED_subSingleSingle_) \
    || defined(_CMOC_NEED_mulSingleSingle_) || defined(_CMOC_NEED_divSingleSingle_)

; Does a binary operation on two numbers and writes the result at a third location.
; Synopsis:
;	pshs	rightOpAddr
;	pshs	leftOpAddr
;	leax	result,PCR
;	lbsr	addSingleSingle		; for example
;	leas	4,s
;   [...]
; addSingleSingle
;	pshs	u,y,x
;	ldu	#colorBasicRoutine	; routine uses FPA0 & FPA1, result in FPA0
;	bsr	binOpSingleSingle
;	puls	u,x,y,pc
; Preserves X.
;
binOpSingleSingle
	ldx	12,s		; rightOpAddr
	jsr	$BC14		; unpack from X to FPA0
	ldx	10,s		; leftOpAddr
	jsr	,u		; unpack from X to FPA1; FPA0 = op(FPA0, FPA1)
	ldx	2,s		; result address
	jmp	$BC35		; pack FPA0 into X

#endif  /* defined(_CMOC_NEED_addSingleSingle_) */


#ifdef _CMOC_NEED_addSingleSingle_

; Adds two numbers and writes the result at a third location.
; Synopsis:
;	pshs	rightOpAddr
;	pshs	leftOpAddr
;	leax	result,PCR
;	lbsr	addSingleSingle
;	leas	4,s
; Preserves X.
;
addSingleSingle
	pshs	u,y,x
	ldu	#$B9C2		; unpack from X to FPA1; FPA0 += FPA1
	bsr	binOpSingleSingle
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_addSingleSingle_) */


#ifdef _CMOC_NEED_subSingleSingle_

; Subtracts two numbers and writes the result at a third location.
; Synopsis:
;	pshs	rightOpAddr
;	pshs	leftOpAddr
;	leax	result,PCR
;	lbsr	subSingleSingle
;	leas	4,s
; Preserves X.
;
subSingleSingle
	pshs	u,y,x
	ldu	#$B9B9		; unpack from X to FPA1; FPA0 = FPA1 - FPA0
	bsr	binOpSingleSingle
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_subSingleSingle_) */


#ifdef _CMOC_NEED_addSingleInt_

addSingleInt
	pshs	u,y,x
	ldd	10,s		; right (signed int)
	jsr	$B4F4		; load D (signed) into FPA0
	ldx	8,s		; left (single)
	jsr	$BB2F		; unpack from X to FPA1
	bra	addFPA0FPA1

#endif  /* _CMOC_NEED_addSingleInt_ */


#if defined(_CMOC_NEED_addSingleInt_) || defined(_CMOC_NEED_addIntSingle_) \
	|| defined(_CMOC_NEED_addSingleUnsignedInt_) || defined(_CMOC_NEED_addUnsignedIntSingle_)

* Input: FPA1 = number to add to D.
*        Pushed argument = address of resulting packed float.
* Output: Sum (packed single) stored at X.
* Trashes FPA0.
* Preserves X.
*
addFPA0FPA1
	lda     FP1EXP		; load exponent of FPA1
	ldb     FP0EXP		; load exponent of FPA0
	jsr     $B9C5		; FPA0 += FPA1

	ldx	,s		; result
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif


#if defined(_CMOC_NEED_addSingleUnsignedInt_) || defined(_CMOC_NEED_addUnsignedIntSingle_) \
    || defined(_CMOC_NEED_mulSingleUnsignedInt_) || defined(_CMOC_NEED_mulUnsignedIntSingle_) \
    || defined(_CMOC_NEED_initSingleFromUnsignedWord_)

loadUnsignedDInFPA0
	clr	VALTYP		; set variable type (VALTYP) to numeric
	std	FP0MAN		; store in upper mantissa of FPA0
	ldb	#128+16 	; 16 = exponent required
	orcc	#1		; set carry so value seen as non-negative (see $BA18)
	jmp	$BC86		; continue with rest of routine started at $B4F4

#endif


#ifdef _CMOC_NEED_addIntSingle_

addIntSingle
	pshs	u,y,x
	ldd	8,s		; right (signed int)
	jsr	$B4F4		; load D (signed) into FPA0
	ldx	10,s		; left (single)
	jsr	$BB2F		; unpack from X to FPA1
	bra	addFPA0FPA1

#endif  /* _CMOC_NEED_addIntSingle_ */


#ifdef _CMOC_NEED_addSingleUnsignedInt_

addSingleUnsignedInt
	pshs	u,y,x
	ldd	10,s		; right (unsigned int)
	bsr	loadUnsignedDInFPA0
	ldx	8,s		; left (single)
	jsr	$BB2F		; unpack from X to FPA1
	bra	addFPA0FPA1

#endif  /* _CMOC_NEED_addSingleUnsignedInt_ */


#ifdef _CMOC_NEED_addUnsignedIntSingle_

addUnsignedIntSingle
	pshs	u,y,x
	ldd	8,s		; left (unsigned int)
	bsr	loadUnsignedDInFPA0
	ldx	10,s		; right (single)
	jsr	$BB2F		; unpack from X to FPA1
	bra	addFPA0FPA1

#endif  /* _CMOC_NEED_addUnsignedIntSingle_ */


#ifdef _CMOC_NEED_subSingleInt_

subSingleInt
	pshs	u,y,x

	clra
	clrb
	subd	10,s		; load right operand, negated
	jsr	$B4F4		; load D (signed) into FPA0

	; The left operand must be loaded second because $B4F4
	; appears to trash FPA1.

	ldx	8,s		; left (single)
	jsr	$BB2F		; unpack from X to FPA1

	bra	subSingle_common_add

#endif  /* _CMOC_NEED_subSingleInt_ */


#ifdef _CMOC_NEED_subSingleUnsignedInt_

subSingleUnsignedInt
	pshs	u,y,x

	ldd	10,s		; load right operand
	bsr	loadUnsignedDInFPA0
	com	FP0SGN		; negate FPA0

	; The left operand must be loaded second because $B4F4
	; appears to trash FPA1.

	ldx	8,s		; left (single)
	jsr	$BB2F		; unpack from X to FPA1

	bra	subSingle_common_add

#endif  /* _CMOC_NEED_subSingleUnsignedInt_ */


#if defined(_CMOC_NEED_subSingleInt_) || defined(_CMOC_NEED_subSingleUnsignedInt_) \
    || defined(_CMOC_NEED_subIntSingle_) || defined(_CMOC_NEED_subUnsignedIntSingle_)

subSingle_common
	ldx	10,s		; right (single)
	jsr	$BB2F		; unpack from X to FPA1
	com	$61		; invert sign of FPA1

        ; Compute sign of result.
        ldb     FP0SGN
        eorb    FP1SGN
        stb     RESSGN

subSingle_common_add
	lda     FP1EXP		; load exponent of FPA1
	ldb     FP0EXP		; load exponent of FPA0
	jsr     $B9C5		; FPA0 += FPA1

	ldx	,s		; result
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif


#ifdef _CMOC_NEED_subIntSingle_

subIntSingle
	pshs	u,y,x
	ldd	8,s		; load left operand
	jsr	$B4F4		; load D (signed) into FPA0
	bra	subSingle_common

#endif  /* _CMOC_NEED_subIntSingle_ */


#ifdef _CMOC_NEED_subUnsignedIntSingle_

subUnsignedIntSingle
	pshs	u,y,x
	ldd	8,s		; load left operand
	bsr	loadUnsignedDInFPA0
	bra	subSingle_common

#endif  /* _CMOC_NEED_subUnsignedIntSingle_ */


#ifdef _CMOC_NEED_mulSingleSingle_

; Multiplies two numbers and writes the result at a third location.
; Synopsis:
;	pshs	rightOpAddr
;	pshs	leftOpAddr
;	leax	result,PCR
;	lbsr	mulSingleSingle
;	leas	4,s
; Preserves X.
;
mulSingleSingle
	pshs	u,y,x
	leau	unpackXToFPA1AndMul,pcr
	lbsr	binOpSingleSingle
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_mulSingleSingle_) */


#if defined(_CMOC_NEED_mulSingleSingle_) \
    || defined(_CMOC_NEED_mulSingleUnsignedInt_) || defined(_CMOC_NEED_mulUnsignedIntSingle_) \
    || defined(_CMOC_NEED_mulSingleInt_)  || defined(_CMOC_NEED_mulIntSingle_) \
    || defined(_CMOC_NEED_divSingleSingle_) \
    || defined(_CMOC_NEED_divSingleUnsignedInt_) || defined(_CMOC_NEED_divUnsignedIntSingle_) \
    || defined(_CMOC_NEED_divSingleInt_) || defined(_CMOC_NEED_divIntSingle_)

unpackXtoFPA0AndPrep
	jsr	$BC14		; unpack from X to FPA0
	bra	prepBinFloatOp

unpackXtoFPA1AndPrep
	jsr	$BB2F		; unpack from X to FPA1

prepBinFloatOp
        ; Compute sign of result, as in $BB2F.
        ldb     FP0SGN
        eorb    FP1SGN
        stb     RESSGN

        lda     FP1EXP
        ldb     FP0EXP          ; as in $BB2F; sets N and Z
	rts

#endif


#if defined(_CMOC_NEED_mulSingleSingle_) \
    || defined(_CMOC_NEED_mulSingleUnsignedInt_) || defined(_CMOC_NEED_mulUnsignedIntSingle_) \
    || defined(_CMOC_NEED_mulSingleInt_)  || defined(_CMOC_NEED_mulIntSingle_)

; To be called by binOpSingleSingle.
; Input: X => packed single to be unpacked to FPA1.
;        FPA0 => factor of the multiplication to be done.
; Output: FPA0 = FPA0 * single at X.
;
unpackXToFPA1AndMul
	bsr	unpackXtoFPA1AndPrep
        jmp     $BACC           ; starts with BEQ instruction

#endif


#if defined(_CMOC_NEED_divSingleSingle_) \
    || defined(_CMOC_NEED_divSingleUnsignedInt_) || defined(_CMOC_NEED_divUnsignedIntSingle_) \
    || defined(_CMOC_NEED_divSingleInt_)  || defined(_CMOC_NEED_divIntSingle_)

; To be called by binOpSingleSingle.
; Input: X => packed single to be unpacked to FPA1.
;        FPA0 => factor of the division to be done.
; Output: FPA0 = FPA0 / single at X.
;
unpackXToFPA0AndDiv
	bsr	unpackXtoFPA0AndPrep
        jmp     $BB91           ; starts with BEQ instruction

unpackXToFPA1AndDiv
	bsr	unpackXtoFPA1AndPrep
        jmp     $BB91           ; starts with BEQ instruction

#endif


#ifdef _CMOC_NEED_mulSingleUnsignedInt_

mulSingleUnsignedInt
	pshs	u,y,x
	ldd	10,s		; right (unsigned int)
	lbsr	loadUnsignedDInFPA0
	ldx	8,s		; left (single)
	bsr	unpackXToFPA1AndMul
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_mulSingleUnsignedInt_) */


#ifdef _CMOC_NEED_mulUnsignedIntSingle_

mulUnsignedIntSingle
	pshs	u,y,x
	ldd	8,s		; left (unsigned int)
	lbsr	loadUnsignedDInFPA0
	ldx	10,s		; right (single)
	bsr	unpackXToFPA1AndMul
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_mulUnsignedIntSingle_) */


#ifdef _CMOC_NEED_mulSingleInt_

mulSingleInt
	pshs	u,y,x
	ldd	10,s		; right (unsigned int)
	jsr	$B4F4		; load D (signed) into FPA0
	ldx	8,s		; left (single)
	bsr	unpackXToFPA1AndMul
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_mulSingleInt_) */


#ifdef _CMOC_NEED_mulIntSingle_

mulIntSingle
	pshs	u,y,x
	ldd	8,s		; right (unsigned int)
	jsr	$B4F4		; load D (signed) into FPA0
	ldx	10,s		; left (single)
	bsr	unpackXToFPA1AndMul
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_mulIntSingle_) */


#ifdef _CMOC_NEED_divSingleSingle_

; Divides two numbers and writes the result at a third location.
; Synopsis:
;	pshs	rightOpAddr
;	pshs	leftOpAddr
;	leax	result,PCR
;	lbsr	divSingleSingle
;	leas	4,s
; Preserves X.
;
divSingleSingle
	tst	[4,s]		; check exponent of right operand (divisor)
	beq	divByZeroSingle
	pshs	u,y,x
	ldu	#$BB8F		; unpack from X to FPA1; FP0 = FPA1 / FPA0
	lbsr	binOpSingleSingle
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_divSingleSingle_) */


#ifdef _CMOC_NEED_divSingleUnsignedInt_

divSingleUnsignedInt
	ldd	4,s		; check right operand (divisor)
	beq	divByZeroSingle
	pshs	u,y,x
	ldd	10,s		; left (unsigned int)
	lbsr	loadUnsignedDInFPA0
	ldx	8,s		; right (single)
	bsr	unpackXToFPA1AndDiv
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_divSingleUnsignedInt_) */


#if    defined(_CMOC_NEED_divSingleSingle_) \
    || defined(_CMOC_NEED_divSingleUnsignedInt_) \
    || defined(_CMOC_NEED_divUnsignedIntSingle_) \
    || defined(_CMOC_NEED_divSingleInt_) \
    || defined(_CMOC_NEED_divIntSingle_)

; Input: X => Result of division (packed single).
;
divByZeroSingle
	clr	,x		; store 0.0f in result
	rts


#endif


#ifdef _CMOC_NEED_divUnsignedIntSingle_

divUnsignedIntSingle
	tst	[4,s]		; check exponent of right operand (divisor)
	beq	divByZeroSingle
	pshs	u,y,x
	ldd	8,s		; left (unsigned int)
	bsr	loadUnsignedDInFPA1
	ldx	10,s		; right (single)
	lbsr	unpackXToFPA0AndDiv
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

* Trashes FPA0.
loadUnsignedDInFPA1
	lbsr	loadUnsignedDInFPA0
	ldd	FP0ADDR
	std	FP1ADDR
	ldd	FP0ADDR+2
	std	FP1ADDR+2
	ldd	FP0ADDR+4
	std	FP1ADDR+4
	rts

#endif  /* defined(_CMOC_NEED_divUnsignedIntSingle_) */


#ifdef _CMOC_NEED_divSingleInt_

divSingleInt
	ldd	4,s		; check right operand (divisor)
	beq	divByZeroSingle
	pshs	u,y,x
	ldd	10,s		; right (unsigned int)
	jsr	$B4F4		; load D (signed) into FPA0
	ldx	8,s		; left (single)
	lbsr	unpackXToFPA1AndDiv
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

#endif  /* defined(_CMOC_NEED_divSingleInt_) */


#ifdef _CMOC_NEED_divIntSingle_

divIntSingle
	tst	[4,s]		; check exponent of right operand (divisor)
	beq	divByZeroSingle
	pshs	u,y,x
	ldd	8,s		; left (signed int)
	bsr	loadSignedDInFPA1
	ldx	10,s		; left (single)
	lbsr	unpackXToFPA0AndDiv
	ldx	,s		; result address
	jsr	$BC35		; pack FPA0 into X
	puls	x,y,u,pc

* Trashes FPA0.
loadSignedDInFPA1
	lbsr	$B4F4		; load D (signed) into FPA0
	ldd	FP0ADDR
	std	FP1ADDR
	ldd	FP0ADDR+2
	std	FP1ADDR+2
	ldd	FP0ADDR+4
	std	FP1ADDR+4
	rts

#endif  /* defined(_CMOC_NEED_divIntSingle_) */


#if defined(_CMOC_NEED_cmpSingleSingle_)

* Input: Stacked arguments: address of left packaged single, address of right.
* Output: B = -1, 0 or +1. CC reflects signed comparison of B with 0.
* Preserves X.
*
cmpSingleSingle
	pshs	u,y,x

	ldx	8,s		; point to left operand (single)
	jsr	$BC14		; unpack from X to FPA0

	ldx	10,s		; point to right operand (single)
	jsr	$BC96		; compare FPA0 to X: puts -1, 0 or +1 in B, sets CC

	puls	x,y,u,pc

#endif  /* _CMOC_NEED_cmpSingleSingle_ */


#if defined(_CMOC_NEED_cmpSingleSignedInt_)

* Input: Stacked arguments: address of left packaged single, right signed int.
* Output: B = -1, 0 or +1. CC reflects signed comparison of B with 0.
* Preserves X.
*
cmpSingleSignedInt
	pshs	u,y,x

	ldd	10,s		; right operand (signed int)
	jsr	$B4F4		; load D (signed) into FPA0

	ldx	8,s		; point to left operand (single)
	jsr	$BC96		; compare FPA0 to X: puts -1, 0 or +1 in B, sets CC

	negb			; invert result because comparison was inverted
	cmpb	#0		; signed comparison, so no TSTB
	puls	x,y,u,pc

#endif  /* _CMOC_NEED_cmpSingleSignedInt_ */


#if defined(_CMOC_NEED_cmpSignedIntSingle_)

cmpSignedIntSingle
	pshs	u,y,x

	ldd	8,s		; left operand (signed int)
	jsr	$B4F4		; load D (signed) into FPA0

	ldx	10,s		; point to right operand (single)
	jsr	$BC96		; compare FPA0 to X: puts -1, 0 or +1 in B, sets CC

	puls	x,y,u,pc

#endif  /* _CMOC_NEED_cmpSignedIntSingle_ */


#if defined(_CMOC_NEED_cmpSingleUnsignedInt_)

cmpSingleUnsignedInt
	pshs	u,y,x

	ldd	10,s		        ; right operand (unsigned int)
	jsr	loadUnsignedDInFPA0	; load D (unsigned) into FPA0

	ldx	8,s		; point to left operand (single)
	jsr	$BC96		; compare FPA0 to X: puts -1, 0 or +1 in B, sets CC

	negb			; invert result because comparison was inverted
	cmpb	#0		; signed comparison, so no TSTB
	puls	x,y,u,pc

#endif  /* _CMOC_NEED_cmpSingleUnsignedInt_ */


#if defined(_CMOC_NEED_cmpUnsignedIntSingle_)

cmpUnsignedIntSingle
	pshs	u,y,x

	ldd	8,s		        ; left operand (unsigned int)
	jsr	loadUnsignedDInFPA0	; load D (unsigned) into FPA0

	ldx	10,s		; point to right operand (single)
	jsr	$BC96		; compare FPA0 to X: puts -1, 0 or +1 in B, sets CC

	puls	x,y,u,pc

#endif  /* _CMOC_NEED_cmpUnsignedIntSingle_ */

#if defined(_CMOC_NEED_strtof_)

; float strtof(char *nptr, char **endptr);
;
; The string must have at most 255 characters (before the null terminator).
; Caution: Passing a excessive value will make Basic fail with an OV ERROR.
;
_strtof

	pshs	u,y

	ldd	CHARAD		; save interpreter's input pointer
	pshs	b,a
	ldx	10,s		; nptr: string to parse
	stx	CHARAD		; point interpreter to caller's string

	jsr	GETCCH		; get current char
	jsr	$BD12		; result in FPA0; trashes FPA1

	ldx	8,s		; address of returned float (hidden parameter)
	jsr	$BC35		; pack FPA0 into X

	ldd	CHARAD		; get address in nptr where parsing stopped
	std	[12,s]		; store at *endptr

	puls	a,b
	std	CHARAD		; restore interpreter's input pointer

	puls	y,u,pc

#endif  /* _CMOC_NEED_strtof_ */


#if defined(_CMOC_NEED_ftoa_)

; char *ftoa(char out[38], float f);
;
; Writes 'f' in ASCII decimal to 'out'.
; Does not precede the string with a space if 'f' is positive or zero.
;
_ftoa
	pshs	u,y		; protect against Basic

	leax	8,s		; f: number to convert to string
	jsr	$BC14		; load FPA0 from X

	ldu	6,s		; out: where to write string

	ldb	FP0SGN		; get sign of 'f'
	bpl	@positive
	lda	#'-'
	sta	,u+		; output minus sign
	bra	@signDone
@positive
	lda	#' '
@signDone
	jsr	$BDE6		; let Basic do rest of conversion

	ldd	6,s		; success: return 'out'
	puls	y,u,pc

#endif  /* _CMOC_NEED_ftoa_ */
