32 |
POSSIBILITY OF SUCH DAMAGE. |
POSSIBILITY OF SUCH DAMAGE. |
33 |
*/ |
*/ |
34 |
|
|
35 |
|
/* $Id$ */ |
36 |
|
|
37 |
/* |
/* |
38 |
mulsf3x.S is part of FPlib V 0.3.0 ported to avr-as |
mulsf3x.S is part of FPlib V 0.3.0 ported to avr-as |
39 |
for details see readme.fplib |
for details see readme.fplib |
59 |
|
|
60 |
GLOBAL(__mulsf3x) |
GLOBAL(__mulsf3x) |
61 |
TST rA3 |
TST rA3 |
62 |
BREQ ___mulsf3x_ZERO |
BREQ 2f |
63 |
___mulsf3_10: |
|
64 |
TST rB3 |
TST rB3 |
65 |
BREQ ___mulsf3x_ZERO |
BREQ 2f |
66 |
|
|
|
___mulsf3x_00: |
|
67 |
SUBI rA3,0x7F ; exp(A) now signed char |
SUBI rA3,0x7F ; exp(A) now signed char |
68 |
SUBI rB3,0x7F ; exp(B) now signed char |
SUBI rB3,0x7F ; exp(B) now signed char |
69 |
|
|
70 |
ADD rA3,rB3 ; add two signed registers |
ADD rA3,rB3 ; add two signed registers |
71 |
BRVC ___mulsf3x_20 ; no signed overflow |
BRVC 1f ; no signed overflow |
72 |
BRMI ___mulsf3x_INF ; signed overflow : if now negative -> positive overflow |
BRMI 100f ; signed overflow : if now negative -> positive overflow |
73 |
___mulsf3x_ZERO: |
2: |
74 |
RJMP _U(__fp_zerox) |
RJMP _U(__fp_zerox) |
75 |
|
|
76 |
___mulsf3x_20: |
1: |
77 |
SUBI rA3,0x81 ; = ADI,0x7F |
SUBI rA3,0x81 ; = ADI,0x7F |
78 |
CPI rA3,0xFF |
CPI rA3,0xFF |
79 |
BREQ ___mulsf3x_ZERO ; no (unsigned overflow) -> signed underflow |
BREQ 2b ; no (unsigned overflow) -> signed underflow |
80 |
|
|
81 |
|
#ifdef __AVR_ENHANCED__ |
82 |
|
|
83 |
|
; this section of code is used by processors which have MUL instruction |
84 |
|
|
85 |
|
; now multiply mantissa A[rA2:rA1:rA0] * B[rB2:rB1:rB0] |
86 |
|
; result : [rr5:rr4:rr3:rr2:rr1:rr0] |
87 |
|
|
88 |
|
; definitions used by calculation |
89 |
|
#define rr2 rAE |
90 |
|
#define rr3 rTI1 |
91 |
|
#define rr4 rBE |
92 |
|
#define rr5 rB3 |
93 |
|
#define rmh r1 ; the multiply result high register |
94 |
|
#define rml r0 ; the multiply result low register |
95 |
|
|
96 |
|
MUL rA0, rB0 ; 0+0 = 0,1 |
97 |
|
MOV rr4, rmh ; rr1 == rr4 |
98 |
|
PUSH rml ; rr0 finished |
99 |
|
|
100 |
|
CLR rr2 |
101 |
|
MUL rA0, rB1 ; 0+1 = 1,2 |
102 |
|
ADD rr4, rml |
103 |
|
ADC rr2, rmh |
104 |
|
CLR rr3 |
105 |
|
MUL rA1, rB0 ; 1+0 = 1,2,3 |
106 |
|
ADD rr4, rml |
107 |
|
ADC rr2, rmh |
108 |
|
ADC rr3, rr3 |
109 |
|
PUSH rr4 ; rr1 finished |
110 |
|
|
111 |
|
CLR rr4 |
112 |
|
MUL rA0, rB2 ; 0+2 = 2,3 |
113 |
|
ADD rr2, rml |
114 |
|
ADC rr3, rmh |
115 |
|
MUL rA1, rB1 ; 1+1 = 2,3,4 |
116 |
|
ADD rr2, rml |
117 |
|
ADC rr3, rmh |
118 |
|
ADC rr4, rr4 |
119 |
|
CLR rA0 |
120 |
|
MUL rA2, rB0 ; 2+0 = 2,3,4 |
121 |
|
ADD rr2, rml |
122 |
|
ADC rr3, rmh |
123 |
|
ADC rr4, rA0 |
124 |
|
|
125 |
|
CLR rr5 |
126 |
|
MUL rA1, rB2 ; 1+2 = 3,4,5 |
127 |
|
ADD rr3, rml |
128 |
|
ADC rr4, rmh |
129 |
|
ADC rr5, rr5 |
130 |
|
MUL rA2, rB1 ; 2+1 = 3,4,5 |
131 |
|
ADD rr3, rml |
132 |
|
ADC rr4, rmh |
133 |
|
ADC rr5, rA0 |
134 |
|
|
135 |
|
MUL rA2, rB2 ; 2+2 = 4,5 |
136 |
|
ADD rr4, rml |
137 |
|
ADC rr5, rmh |
138 |
|
|
139 |
|
; converting result to original format |
140 |
|
MOV rA2, rr5 |
141 |
|
MOV rA1, rr4 |
142 |
|
MOV rA0, rr3 |
143 |
|
; rr2 is the right one, no need to move |
144 |
|
|
145 |
|
#undef rr5 |
146 |
|
#undef rr4 |
147 |
|
#undef rr3 |
148 |
|
; definitions used by result |
149 |
|
#define rr5 rA2 |
150 |
|
#define rr4 rA1 |
151 |
|
#define rr3 rA0 |
152 |
|
// #define rr2 rAE |
153 |
|
#define rr1 rT1c |
154 |
|
#define rr0 rT0 |
155 |
|
#define rb5 rTI1 |
156 |
|
#define rb4 rBE |
157 |
|
#define rb3 rB3 |
158 |
|
|
159 |
|
; take out the lowest bytes from stack |
160 |
|
POP rr1 |
161 |
|
POP rr0 |
162 |
|
; +++ 44 instructions +++ |
163 |
|
|
164 |
|
#else // __AVR_ENHANCED__ |
165 |
|
|
166 |
|
; this section of code is used by processors which have not MUL instruction |
167 |
|
|
168 |
; now multiply mantissa A[rA2:rA1:rA0] * B[rb5:rb4:rb3:rB2:rB1:rB0] |
; now multiply mantissa A[rA2:rA1:rA0] * B[rb5:rb4:rb3:rB2:rB1:rB0] |
169 |
; result : [rr5:rr4:rr3:rr2:rr1:rr0] |
; result : [rr5:rr4:rr3:rr2:rr1:rr0] |
186 |
CLR rb3 |
CLR rb3 |
187 |
|
|
188 |
LDI loop,8 ; loop counter |
LDI loop,8 ; loop counter |
189 |
___mulsf3x_100: |
1: |
190 |
LSR rb4 |
LSR rb4 |
191 |
BRCC ___mulsf3x_101 |
BRCC 2f |
192 |
ADD rr0,rB0 |
ADD rr0,rB0 |
193 |
adc rr1,rB1 |
adc rr1,rB1 |
194 |
adc rr2,rB2 |
adc rr2,rB2 |
195 |
adc rr3,rb3 |
adc rr3,rb3 |
196 |
___mulsf3x_101: |
2: |
197 |
ADD rB0,rB0 |
ADD rB0,rB0 |
198 |
adc rB1,rB1 |
adc rB1,rB1 |
199 |
adc rB2,rB2 |
adc rB2,rB2 |
200 |
adc rb3,rb3 |
adc rb3,rb3 |
201 |
DEC loop |
DEC loop |
202 |
BRNE ___mulsf3x_100 ; |
BRNE 1b |
203 |
LDI loop,8 ; loop counter |
LDI loop,8 ; loop counter |
204 |
|
|
205 |
MOV rb5,rA1 ; rb5 not yet needed |
MOV rb5,rA1 ; rb5 not yet needed |
206 |
CLR rr4 ; rb4 is allready clear |
CLR rr4 ; rb4 is allready clear |
207 |
LDI loop,8 ; loop counter |
LDI loop,8 ; loop counter |
208 |
___mulsf3x_200: |
1: |
209 |
LSR rb5 |
LSR rb5 |
210 |
BRCC ___mulsf3x_201 |
BRCC 2f |
211 |
ADD rr1,rB1 |
ADD rr1,rB1 |
212 |
adc rr2,rB2 |
adc rr2,rB2 |
213 |
adc rr3,rb3 |
adc rr3,rb3 |
214 |
adc rr4,rb4 |
adc rr4,rb4 |
215 |
___mulsf3x_201: |
2: |
216 |
ADD rB1,rB1 |
ADD rB1,rB1 |
217 |
adc rB2,rB2 |
adc rB2,rB2 |
218 |
adc rb3,rb3 |
adc rb3,rb3 |
219 |
adc rb4,rb4 |
adc rb4,rb4 |
220 |
DEC loop |
DEC loop |
221 |
BRNE ___mulsf3x_200 ; |
BRNE 1b |
222 |
|
|
223 |
MOV loop,rA2 ; loop no longer needed, check |
MOV loop,rA2 ; loop no longer needed, check |
224 |
CLR rr5 ; rb5 is allready clear |
CLR rr5 ; rb5 is allready clear |
225 |
___mulsf3x_300: |
1: |
226 |
LSR loop |
LSR loop |
227 |
BRCC ___mulsf3x_301 |
BRCC 2f |
228 |
ADD rr2,rB2 |
ADD rr2,rB2 |
229 |
adc rr3,rb3 |
adc rr3,rb3 |
230 |
adc rr4,rb4 |
adc rr4,rb4 |
231 |
adc rr5,rb5 |
adc rr5,rb5 |
232 |
___mulsf3x_301: |
2: |
233 |
ADD rB2,rB2 |
ADD rB2,rB2 |
234 |
adc rb3,rb3 |
adc rb3,rb3 |
235 |
adc rb4,rb4 |
adc rb4,rb4 |
236 |
adc rb5,rb5 |
adc rb5,rb5 |
237 |
TST loop |
TST loop |
238 |
BRNE ___mulsf3x_300 ; |
BRNE 1b |
239 |
|
; +++ 49 instructions +++ |
240 |
|
|
241 |
|
#endif // __AVR_ENHANCED__ |
242 |
|
|
243 |
|
|
244 |
; multiplication done : result in rr5:rr4:rr3:rr2:rr1:rr0 |
; multiplication done : result in rr5:rr4:rr3:rr2:rr1:rr0 |
245 |
; = rA2:rA1:rA0:rAE:rr1:rr0 |
; = rA2:rA1:rA0:rAE:rr1:rr0 |
246 |
___mulsf3x_400: ; normalize 1.0 * 1.0 = 1.0 |
; normalize 1.0 * 1.0 = 1.0 |
247 |
; 0x800000 * 0x800000 = 0x40 00 00 00 00 00 |
; 0x800000 * 0x800000 = 0x40 00 00 00 00 00 |
248 |
; 1.999999 * 1.999999 = 3.99999 ~ 4.0 |
; 1.999999 * 1.999999 = 3.99999 ~ 4.0 |
249 |
; 0xFFFFFF * 0xFFFFFF = 0xFF FF FE 00 00 01 |
; 0xFFFFFF * 0xFFFFFF = 0xFF FF FE 00 00 01 |
250 |
|
|
251 |
TST rA2 |
TST rA2 |
252 |
BRPL ___mulsf3x_405 ; if MSB erg is clr |
BRPL 1f ; if MSB erg is clr |
253 |
INC rA3 ; |
INC rA3 ; |
254 |
BRNE ___mulsf3x_420 |
BRNE 2f |
255 |
___mulsf3x_INF: |
100: |
256 |
RJMP _U(__fp_nanx) ; returns to ___mulsf3 or a high level function : rT1c ok |
RJMP _U(__fp_nanx) ; returns to ___mulsf3 or a high level function : rT1c ok |
257 |
___mulsf3x_405: |
1: |
258 |
ADD rr0,rr0 |
ADD rr0,rr0 |
259 |
adc rr1,rr1 |
adc rr1,rr1 |
260 |
adc rAE,rAE |
adc rAE,rAE |
262 |
adc rA1,rA1 |
adc rA1,rA1 |
263 |
adc rA2,rA2 |
adc rA2,rA2 |
264 |
|
|
265 |
___mulsf3x_420: |
2: |
266 |
OR rr0,rr1 ; rr0 = rT0 which holds the mantissae extension beyond rAE |
OR rr0,rr1 ; rr0 = rT0 which holds the mantissae extension beyond rAE |
267 |
RET |
RET |
268 |
|
|