File: math.s

package info (click to toggle)
atari800 5.2.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 7,196 kB
  • sloc: ansic: 86,829; asm: 18,694; sh: 3,173; cpp: 2,798; java: 2,453; xml: 957; makefile: 727; perl: 334; pascal: 178
file content (172 lines) | stat: -rw-r--r-- 3,937 bytes parent folder | download
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