summaryrefslogtreecommitdiff
path: root/n/avr/modules/math/fixed/fixed_div_f824.avr.S
blob: 43f4e0c35ebfdec33c8469cc09b35ca0efc65f1c (plain)
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
; fixed_div_f824.avr.S
; avr.math.fixed - Fixed point math module. {{{
;
; Copyright (C) 2005 Nicolas Schodet
;
; Robot APB Team/Efrei 2006.
;        Web: http:		;assos.efrei.fr/robot/
;      Email: robot AT efrei DOT fr
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
; 
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;
; }}}

; Perfs:
;  1186 cycles in worse case
;  843 per second, per MHz

#define dd3 r25
#define dd2 r24
#define dd1 r23
#define dd0 r22

#define dv3 r21
#define dv2 r20
#define dv1 r19
#define dv0 r18

; r28-r29 are avoided because they should be saved.
#define rem3 r31
#define rem2 r30
#define rem1 r27
#define rem0 r26

#define __tmp_reg__ r0
#define __zero_reg__ r1

#define cnt r16

	.text
	.global fixed_div_f824
	.func fixed_div_f824
fixed_div_f824:
	push cnt
; Store sign.
	mov __tmp_reg__, dd3
	eor __tmp_reg__, dv3
; Change sign.
	sbrs dd3, 7
	rjmp 1f
	com dd3
	com dd2
	com dd1
	neg dd0
	sbci dd1, 0xff
	sbci dd2, 0xff
	sbci dd3, 0xff
1:	sbrs dv3, 7
	rjmp 2f
	com dv3
	com dv2
	com dv1
	neg dv0
	sbci dv1, 0xff
	sbci dv2, 0xff
	sbci dv3, 0xff
; Clear rem.
2:	clr rem0
	clr rem1
	movw rem2, rem0
; First loop, dropped bits.
	ldi cnt, 24
1:	;lsl dd0		; shift out dd
	lsl dd1			; do not touch dd0
	rol dd2
	rol dd3
	rol rem0		; shift in rem
	rol rem1		; 24 bits only
	rol rem2
	;rol rem3
	sub rem0, dv0		; rem -= dv
	sbc rem1, dv1
	sbc rem2, dv2
	sbc rem3, dv3
	brcc 2f			; if negative, restore rem
	add rem0, dv0
	adc rem1, dv1
	adc rem2, dv2
	adc rem3, dv3
2:	dec cnt			; test for loop
	brne 1b
; Second loop, stored bits.
	ldi cnt, 8
1:	rol dd0			; shift out dd, shift in result
	rol rem0		; shift in rem
	rol rem1
	rol rem2
	rol rem3
	sub rem0, dv0		; rem -= dv
	sbc rem1, dv1
	sbc rem2, dv2
	sbc rem3, dv3
	brcc 2f			; if negative, restore rem
	add rem0, dv0
	adc rem1, dv1
	adc rem2, dv2
	adc rem3, dv3
	clc			; result bit 0
	rjmp 3f
2:	sec			; result bit 1
3:	dec cnt			; test for loop
	brne 1b
; Last loop, stored bits, dd padding bits.
	ldi cnt, 24
1:	rol dd0			; shift out dd, shift in result
	rol dd1			; 0s come from the first loop
	rol dd2
	rol dd3
	rol rem0		; shift in rem
	rol rem1
	rol rem2
	rol rem3
	sub rem0, dv0		; rem -= dv
	sbc rem1, dv1
	sbc rem2, dv2
	sbc rem3, dv3
	brcc 2f			; if negative, restore rem
	add rem0, dv0
	adc rem1, dv1
	adc rem2, dv2
	adc rem3, dv3
	clc			; result bit 0
	rjmp 3f
2:	sec			; result bit 1
3:	dec cnt			; test for loop
	brne 1b
; Store last bit.
	rol dd0			; shift in result
	rol dd1
	rol dd2
	rol dd3
; Restore sign.
	sbrs __tmp_reg__, 7
	rjmp 1f
	com dd3
	com dd2
	com dd1
	neg dd0
	sbci dd1, 0xff
	sbci dd2, 0xff
	sbci dd3, 0xff
; Return.
1:	pop r16
	ret
	.endfunc