-
Notifications
You must be signed in to change notification settings - Fork 1
/
float.inc
135 lines (119 loc) · 2.74 KB
/
float.inc
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
; Rutinas del BASIC
LDFAC1 = $BBA2 ; Load FAC#1 from memory (A:L, Y:H)
LDFAC2 = $BA8C ; Load FAC#2 from memory (A:L, Y:H)
STFAC1 = $BBD4 ; Store FAC#1 in memory (X:L, Y:H)
TFAC12 = $BC0C ; Copy FAC#1 into FAC#2
TFAC21 = $BBFC ; Copy FAC#2 into FAC#1
FMUL = $BA28 ; Multiply
FMULA = $BA59 ; Multiply by A
FADDM = $B867 ; Add FAC#1 + MEM (A:L, Y:H)
FADD = $B86A ; Add FAC#1 + FAC#2
FCMP = $BC5B ; Compare FAC#1 with memory (A:L, Y:H) -> A (0, 1, -1)
FNEG = $BFB4 ; Negate FAC#1 if nonzero
float_inc .block
ldaddr .macro addr
lda #<\addr
ldy #>\addr
.endm
ldaddr_st .macro addr
ldx #<\addr
ldy #>\addr
.endm
.bend
float_t .struct exp = 0, sgn = 0, man = 0
.byte \exp
.byte ((bool(\sgn)?1:0) << 7) | ((\man >> 24) & $7f) ; La mantisa se guarda en big-endian
.byte (\man >> 16) & $ff
.byte (\man >> 8) & $ff
.byte \man & $ff
.ends
dfloat .macro val
.if type(\val) == gap
.byte ?,?,?,?,?
.else
f := float(\val)
.if f == 0.0
.dstruct float_t, 0,0,0
.else
; extraemos el signo
sgn = sign(f) < 0 ? 1 : 0
; lo forzamos a positivo
f := abs(f)
; Calculamos exponente y mantisa:
; La mantisa debe estar normalizada entre [0.5..1).
; Si f ya está en este rango, el exponente será 0.
; si f < 0.5, el exponente será negativo.
; Si f >= 1, será positivo.
ex := 0
.if f < 0.5
; multiplicamos por 2 hasta que f >= 0.5
.for ex = 0, f < 0.5, ex = ex - 1
f *= 2
.next
.elsif f >= 1
; dividimos entre 2 hasta que f < 1
.for ex = 0, f >= 1.0, ex = ex + 1
f /= 2
.next
.endif
; Sumamos 128 al exponente para convertirlo en un valor positivo de 8 bits.
.cerror ex < -127 || ex > 127, "Float constant out of bounds: " .. repr(\val)
ex += 128
; Lo que queda de f es la mantisa normalizada.
; Para convertirla a un valor de 32 bits, multiplicamos por $100000000 y truncamos.
; El bit más significativo, que siempre será 1, lo sustituiremos por el bit de signo.
m = int( trunc( f * $100000000 ) )
; ¡Hecho!
.dstruct float_t, ex, sgn, m
;.warn format("%f -> %02x%08x", \val, ex, (sgn<<31) | (m & $7fffffff))
.endif
.endif
.endm
ldfac1 .macro addr
#float_inc.ldaddr \addr
jsr LDFAC1
.endm
ldfac2 .macro addr
#float_inc.ldaddr \addr
jsr LDFAC2
.endm
stfac1 .macro addr
#float_inc.ldaddr_st \addr
jsr STFAC1
.endm
tfac12 .macro
jsr TFAC12
.endm
tfac21 .macro
js_ TFAC21
.endm
fmul .macro byte = ?
.if type(\byte) == gap
jsr FMUL
.else
lda \byte
jsr FMULA
.endif
.endm
fadd .macro addr = ?
.if type(\addr) == gap
jsr FADD
.else
#float_inc.ldaddr \addr
jsr FADDM
.endif
.endm
fcmp .macro addr
#float_inc.ldaddr \addr
jsr FCMP
.endm
fneg .macro
jsr FNEG
.endm
fmov .macro dst, src
ldy #4
_loop lda \src,y
sta \dst,y
dey
bpl _loop
.endm