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
Generated automatically using Doxygen. If info on this page is outdated, incomplete, or wrong, please open an issue at https://github.com/sensorium/Mozzi/issues