Mozzi  version v2.0
sound synthesis library for Arduino
mult16x16.h
1 
2 /*
3 Norbert Pozar 2009
4 http://mekonik.wordpress.com/2009/03/18/arduino-avr-gcc-multiplication/
5 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
7 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
8 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
9 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
10 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/
11 
12 // longRes = intIn1 * intIn2
13 #define MultiU16X16to32(longRes, intIn1, intIn2) asm
14  volatile ( \
15 "clr r26 \n\t"\
16 "mul %A1, %A2 \n\t"\
17 "movw %A0, r0 \n\t"\
18 "mul %B1, %B2 \n\t"\
19 "movw %C0, r0 \n\t"\
20 "mul %B2, %A1 \n\t"\
21 "add %B0, r0 \n\t"\
22 "adc %C0, r1 \n\t"\
23 "adc %D0, r26 \n\t"\
24 "mul %B1, %A2 \n\t"\
25 "add %B0, r0 \n\t"\
26 "adc %C0, r1 \n\t"\
27 "adc %D0, r26 \n\t"\
28 "clr r1 \n\t"\
29 :\
30 "=&r"(longRes) \
31 :\
32 "a"(intIn1), \
33 "a"(intIn2) \
34 :\
35 "r26"\
36 )
37 
38 // intRes = intIn1 * intIn2 >> 16
39 // uses:
40 // r26 to store 0
41 // r27 to store the uint8_t 1 of the 32bit result
42 #define MultiU16X16toH16(intRes, intIn1, intIn2) asm
43  volatile ( \
44 "clr r26 \n\t"\
45 "mul %A1, %A2 \n\t"\
46 "mov r27, r1 \n\t"\
47 "mul %B1, %B2 \n\t"\
48 "movw %A0, r0 \n\t"\
49 "mul %B2, %A1 \n\t"\
50 "add r27, r0 \n\t"\
51 "adc %A0, r1 \n\t"\
52 "adc %B0, r26 \n\t"\
53 "mul %B1, %A2 \n\t"\
54 "add r27, r0 \n\t"\
55 "adc %A0, r1 \n\t"\
56 "adc %B0, r26 \n\t"\
57 "clr r1 \n\t"\
58 :\
59 "=&r"(intRes) \
60 :\
61 "a"(intIn1), \
62 "a"(intIn2) \
63 :\
64 "r26", "r27" \
65 )
66 
67 // intRes = intIn1 * intIn2 >> 16 + round
68 // uses:
69 // r26 to store 0
70 // r27 to store the uint8_t 1 of the 32bit result
71 // 21 cycles
72 #define MultiU16X16toH16Round(intRes, intIn1, intIn2) asm
73  volatile ( \
74 "clr r26 \n\t"\
75 "mul %A1, %A2 \n\t"\
76 "mov r27, r1 \n\t"\
77 "mul %B1, %B2 \n\t"\
78 "movw %A0, r0 \n\t"\
79 "mul %B2, %A1 \n\t"\
80 "add r27, r0 \n\t"\
81 "adc %A0, r1 \n\t"\
82 "adc %B0, r26 \n\t"\
83 "mul %B1, %A2 \n\t"\
84 "add r27, r0 \n\t"\
85 "adc %A0, r1 \n\t"\
86 "adc %B0, r26 \n\t"\
87 "lsl r27 \n\t"\
88 "adc %A0, r26 \n\t"\
89 "adc %B0, r26 \n\t"\
90 "clr r1 \n\t"\
91 :\
92 "=&r"(intRes) \
93 :\
94 "a"(intIn1), \
95 "a"(intIn2) \
96 :\
97 "r26", "r27" \
98 )
99 
100 
101 // signed16 * signed16
102 // 22 cycles
103 #define MultiS16X16to32(longRes, intIn1, intIn2) asm
104  volatile ( \
105 "clr r26 \n\t"\
106 "mul %A1, %A2 \n\t"\
107 "movw %A0, r0 \n\t"\
108 "muls %B1, %B2 \n\t"\
109 "movw %C0, r0 \n\t"\
110 "mulsu %B2, %A1 \n\t"\
111 "sbc %D0, r26 \n\t"\
112 "add %B0, r0 \n\t"\
113 "adc %C0, r1 \n\t"\
114 "adc %D0, r26 \n\t"\
115 "mulsu %B1, %A2 \n\t"\
116 "sbc %D0, r26 \n\t"\
117 "add %B0, r0 \n\t"\
118 "adc %C0, r1 \n\t"\
119 "adc %D0, r26 \n\t"\
120 "clr r1 \n\t"\
121 :\
122 "=&r"(longRes) \
123 :\
124 "a"(intIn1), \
125 "a"(intIn2) \
126 :\
127 "r26"\
128 )
129 
130 
131 // signed16 * signed 16 >> 16
132 #define MultiS16X16toH16(intRes, intIn1, intIn2) asm
133  volatile ( \
134 "clr r26 \n\t"\
135 "mul %A1, %A2 \n\t"\
136 "mov r27, r1 \n\t"\
137 "muls %B1, %B2 \n\t"\
138 "movw %A0, r0 \n\t"\
139 "mulsu %B2, %A1 \n\t"\
140 "sbc %B0, r26 \n\t"\
141 "add r27, r0 \n\t"\
142 "adc %A0, r1 \n\t"\
143 "adc %B0, r26 \n\t"\
144 "mulsu %B1, %A2 \n\t"\
145 "sbc %B0, r26 \n\t"\
146 "add r27, r0 \n\t"\
147 "adc %A0, r1 \n\t"\
148 "adc %B0, r26 \n\t"\
149 "clr r1 \n\t"\
150 :\
151 "=&r"(intRes) \
152 :\
153 "a"(intIn1), \
154 "a"(intIn2) \
155 :\
156 "r26","r27" \
157 )
158 
159 // multiplies a signed and unsigned 16 bit ints with a 32 bit result
160 #define MultiSU16X16to32(longRes, intIn1, intIn2) asm
161  volatile ( \
162 "clr r26 \n\t"\
163 "mul %A1, %A2 \n\t"\
164 "movw %A0, r0 \n\t"\
165 "mulsu %B1, %B2 \n\t"\
166 "movw %C0, r0 \n\t"\
167 "mul %B2, %A1 \n\t"\
168 "add %B0, r0 \n\t"\
169 "adc %C0, r1 \n\t"\
170 "adc %D0, r26 \n\t"\
171 "mulsu %B1, %A2 \n\t"\
172 "sbc %D0, r26 \n\t"\
173 "add %B0, r0 \n\t"\
174 "adc %C0, r1 \n\t"\
175 "adc %D0, r26 \n\t"\
176 "clr r1 \n\t"\
177 :\
178 "=&r"(longRes) \
179 :\
180 "a"(intIn1), \
181 "a"(intIn2) \
182 :\
183 "r26"\
184 )
185 
186 // multiplies signed x unsigned int and returns the highest 16 bits of the result
187 #define MultiSU16X16toH16(intRes, intIn1, intIn2) asm
188  volatile ( \
189 "clr r26 \n\t"\
190 "mul %A1, %A2 \n\t"\
191 "mov r27, r1 \n\t"\
192 "mulsu %B1, %B2 \n\t"\
193 "movw %A0, r0 \n\t"\
194 "mul %B2, %A1 \n\t"\
195 "add r27, r0 \n\t"\
196 "adc %A0, r1 \n\t"\
197 "adc %B0, r26 \n\t"\
198 "mulsu %B1, %A2 \n\t"\
199 "sbc %B0, r26 \n\t"\
200 "add r27, r0 \n\t"\
201 "adc %A0, r1 \n\t"\
202 "adc %B0, r26 \n\t"\
203 "clr r1 \n\t"\
204 :\
205 "=&r"(intRes) \
206 :\
207 "a"(intIn1), \
208 "a"(intIn2) \
209 :\
210 "r26","r27" \
211 )
212 
213 // multiplies signed x unsigned int and returns the highest 16 bits of the result
214 // rounds the result based on the MSB of the lower 16 bits
215 // 22 cycles
216 #define MultiSU16X16toH16Round(intRes, intIn1, intIn2) asm
217  volatile ( \
218 "clr r26 \n\t"\
219 "mul %A1, %A2 \n\t"\
220 "mov r27, r1 \n\t"\
221 "mulsu %B1, %B2 \n\t"\
222 "movw %A0, r0 \n\t"\
223 "mul %A1, %B2 \n\t"\
224 "add r27, r0 \n\t"\
225 "adc %A0, r1 \n\t"\
226 "adc %B0, r26 \n\t"\
227 "mulsu %B1, %A2 \n\t"\
228 "sbc %B0, r26 \n\t"\
229 "add r27, r0 \n\t"\
230 "adc %A0, r1 \n\t"\
231 "adc %B0, r26 \n\t"\
232 "lsl r27 \n\t"\
233 "adc %A0, r26 \n\t"\
234 "adc %B0, r26 \n\t"\
235 "clr r1 \n\t"\
236 :\
237 "=&r"(intRes) \
238 :\
239 "a"(intIn1), \
240 "a"(intIn2) \
241 :\
242 "r26","r27" \
243 )