1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
; Altirra BASIC - Misc math module
; Copyright (C) 2014 Avery Lee, All Rights Reserved.
;
; Copying and distribution of this file, with or without modification,
; are permitted in any medium without royalty provided the copyright
; notice and this notice are preserved. This file is offered as-is,
; without any warranty.
;===========================================================================
;FCOMP Floating point compare routine.
;
; Inputs:
; FR0
; FR1
;
; Outputs:
; Z, C set for comparison result like SBC
;
.proc fcomp
;check for sign difference
lda fr1
eor fr0
bpl signs_same
;Signs are different. If FR0 is positive, then we need to
;exit Z=0, C=1; if FR0 is negative, then Z=0, C=0.
;
;We're using a dirty trick here by skipping the ROR below.
;A=FR0^FR1, so after the EOR FR0, A=FR1. This causes us to
;set C=0 for -FR0,+FR1 and C=1 for +FR0,-FR1, which is what
;we want.
;
dta {bit $00}
;okay, we've confirmed that the numbers are different, but the
;carry flag may be going the wrong way if the numbers are
;negative... so let's fix that.
diff:
ror ;!! - skipped for differing sign path
eor fr0
sec
rol
xit:
rts
signs_same:
;Check for both values being zero, as only signexp and first
;mantissa byte are guaranteed to be $00 in that case.
;
;We are using another trick here by testing:
;
; (x ^ y) | x == 0
;
;in lieu of x|y. This works out at the boolean level.
;
ora fr0
beq xit
;compare signexp and mantissa bytes in order
ldx #<-6
loop:
lda fr0+6,x
cmp fr1+6,x
bne diff
inx
bne loop
rts ;!! - Z=1, C=1
.endp
;===========================================================================
.proc MathFloor
;These are the digits we need to check+zero by exponent:
;
; $3F 00 00 00 00 00 -> always fraction
; $40 xx 00 00 00 00
; $41 xx xx 00 00 00
; $42 xx xx xx 00 00
; $43 xx xx xx xx 00
; $44 xx xx xx xx xx -> always integer, take no action
;
lda fr0
asl
;if exponent is < $40 then we have zero or -1
bmi not_tiny
php
jsr zfr0
plp
bcs round_down
done:
rts
not_tiny:
;ok... using the exponent, compute the first digit offset we should
;check
lsr
adc #$bc ;!! - C=0
bcs done ;exit if exp too large and we can't have decimals
tax
;check digit pairs until we find a non-zero fractional digit pair,
;zeroing as we go
lda #0
tay
zero_loop:
ora fr0+6,x
sty fr0+6,x
inx
bne zero_loop
;skip rounding if it was already integral
tay
beq done
;check if we have a negative number; if so, we need to subtract one
lda fr0
bpl done
round_down:
;subtract one to round down
jsr MathLoadOneFR1
jmp fsub
.endp
;===========================================================================
; Extract sign from FR0 into funScratch1 and take abs(FR0).
;
.proc MathSplitSign
lda fr0
sta funScratch1
and #$7f
sta fr0
xit:
rts
.endp
;===========================================================================
.proc MathByteToFP
ldx #0
.def :MathWordToFP = *
stx fr0+1
.def :MathWordToFP_FR0Hi_A = *
sta fr0
jmp ifp
.endp
;===========================================================================
.proc MathLoadOneFR1
ldx #<const_one
.def :MathLoadConstFR1 = *
ldy #>const_one
bne MathLoadFR1_FPSCR.fld1r_trampoline
.endp
;===========================================================================
.proc MathStoreFR0_FPSCR
ldx #<fpscr
.def :MathStoreFR0_Page5 = *
ldy #>fpscr
jmp fst0r
.endp
;===========================================================================
.proc MathLoadFR1_FPSCR
ldx #<fpscr
.def :MathLoadFR1_Page5 = *
ldy #>fpscr
fld1r_trampoline:
jmp fld1r
.endp
|