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) \
14 asm 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) \
43 asm 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) \
73 asm 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) \
104 asm 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) \
133 asm 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) \
161 asm 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) \
188 asm 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) \
217 asm 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 )
244