]>
Commit | Line | Data |
---|---|---|
1 | ; Copyright (C) 2014-2015 Free Software Foundation, Inc. | |
2 | ; Contributed by Red Hat. | |
3 | ; | |
4 | ; This file is free software; you can redistribute it and/or modify it | |
5 | ; under the terms of the GNU General Public License as published by the | |
6 | ; Free Software Foundation; either version 3, or (at your option) any | |
7 | ; later version. | |
8 | ; | |
9 | ; This file is distributed in the hope that it will be useful, but | |
10 | ; WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | ; General Public License for more details. | |
13 | ; | |
14 | ; Under Section 7 of GPL version 3, you are granted additional | |
15 | ; permissions described in the GCC Runtime Library Exception, version | |
16 | ; 3.1, as published by the Free Software Foundation. | |
17 | ; | |
18 | ; You should have received a copy of the GNU General Public License and | |
19 | ; a copy of the GCC Runtime Library Exception along with this program; | |
20 | ; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
21 | ; <http://www.gnu.org/licenses/>. | |
22 | ||
23 | .macro start_func name | |
24 | .pushsection .text.\name,"ax",@progbits | |
25 | .align 2 | |
26 | .global \name | |
27 | .type \name , @function | |
28 | \name: | |
29 | PUSH.W sr ; Save current interrupt state | |
30 | DINT ; Disable interrupts | |
31 | NOP ; Account for latency | |
32 | .endm | |
33 | ||
34 | .macro end_func name | |
35 | #ifdef __MSP430X_LARGE__ | |
36 | POP.W sr | |
37 | RETA | |
38 | #else | |
39 | RETI | |
40 | #endif | |
41 | .size \name , . - \name | |
42 | .popsection | |
43 | .endm | |
44 | ||
45 | .macro mult16 OP1, OP2, RESULT | |
46 | ;* * 16-bit hardware multiply: int16 = int16 * int16 | |
47 | ;* | |
48 | ;* - Operand 1 is in R12 | |
49 | ;* - Operand 2 is in R13 | |
50 | ;* - Result is in R12 | |
51 | ;* | |
52 | ;* To ensure that the multiply is performed atomically, interrupts are | |
53 | ;* disabled upon routine entry. Interrupt state is restored upon exit. | |
54 | ;* | |
55 | ;* Registers used: R12, R13 | |
56 | ;* | |
57 | ;* Macro arguments are the memory locations of the hardware registers. | |
58 | ||
59 | MOV.W r12, &\OP1 ; Load operand 1 into multiplier | |
60 | MOV.W r13, &\OP2 ; Load operand 2 which triggers MPY | |
61 | MOV.W &\RESULT, r12 ; Move result into return register | |
62 | .endm | |
63 | ||
64 | .macro mult1632 OP1, OP2, RESULT_LO, RESULT_HI | |
65 | ;* * 16-bit hardware multiply with a 32-bit result: | |
66 | ;* int32 = int16 * int16 | |
67 | ;* uint32 = uint16 * uint16 | |
68 | ;* | |
69 | ;* - Operand 1 is in R12 | |
70 | ;* - Operand 2 is in R13 | |
71 | ;* - Result is in R12, R13 | |
72 | ;* | |
73 | ;* To ensure that the multiply is performed atomically, interrupts are | |
74 | ;* disabled upon routine entry. Interrupt state is restored upon exit. | |
75 | ;* | |
76 | ;* Registers used: R12, R13 | |
77 | ;* | |
78 | ;* Macro arguments are the memory locations of the hardware registers. | |
79 | ||
80 | MOV.W r12, &\OP1 ; Load operand 1 into multiplier | |
81 | MOV.W r13, &\OP2 ; Load operand 2 which triggers MPY | |
82 | MOV.W &\RESULT_LO, r12 ; Move low result into return register | |
83 | MOV.W &\RESULT_HI, r13 ; Move high result into return register | |
84 | .endm | |
85 | ||
86 | .macro mult32 OP1, OP2, MAC_OP1, MAC_OP2, RESULT_LO, RESULT_HI | |
87 | ;* * 32-bit hardware multiply with a 32-bit result using 16 multiply and accumulate: | |
88 | ;* int32 = int32 * int32 | |
89 | ;* | |
90 | ;* - Operand 1 is in R12, R13 | |
91 | ;* - Operand 2 is in R14, R15 | |
92 | ;* - Result is in R12, R13 | |
93 | ;* | |
94 | ;* To ensure that the multiply is performed atomically, interrupts are | |
95 | ;* disabled upon routine entry. Interrupt state is restored upon exit. | |
96 | ;* | |
97 | ;* Registers used: R12, R13, R14, R15 | |
98 | ;* | |
99 | ;* Macro arguments are the memory locations of the hardware registers. | |
100 | ||
101 | MOV.W r12, &\OP1 ; Load operand 1 Low into multiplier | |
102 | MOV.W r14, &\OP2 ; Load operand 2 Low which triggers MPY | |
103 | MOV.W r12, &\MAC_OP1 ; Load operand 1 Low into mac | |
104 | MOV.W &\RESULT_LO, r12 ; Low 16-bits of result ready for return | |
105 | MOV.W &\RESULT_HI, &\RESULT_LO; MOV intermediate mpy high into low | |
106 | MOV.W r15, &\MAC_OP2 ; Load operand 2 High, trigger MAC | |
107 | MOV.W r13, &\MAC_OP1 ; Load operand 1 High | |
108 | MOV.W r14, &\MAC_OP2 ; Load operand 2 Lo, trigger MAC | |
109 | MOV.W &\RESULT_LO, r13 ; Upper 16-bits result ready for return | |
110 | .endm | |
111 | ||
112 | ||
113 | .macro mult32_hw OP1_LO OP1_HI OP2_LO OP2_HI RESULT_LO RESULT_HI | |
114 | ;* * 32-bit hardware multiply with a 32-bit result | |
115 | ;* int32 = int32 * int32 | |
116 | ;* | |
117 | ;* - Operand 1 is in R12, R13 | |
118 | ;* - Operand 2 is in R14, R15 | |
119 | ;* - Result is in R12, R13 | |
120 | ;* | |
121 | ;* To ensure that the multiply is performed atomically, interrupts are | |
122 | ;* disabled upon routine entry. Interrupt state is restored upon exit. | |
123 | ;* | |
124 | ;* Registers used: R12, R13, R14, R15 | |
125 | ;* | |
126 | ;* Macro arguments are the memory locations of the hardware registers. | |
127 | ||
128 | MOV.W r12, &\OP1_LO ; Load operand 1 Low into multiplier | |
129 | MOV.W r13, &\OP1_HI ; Load operand 1 High into multiplier | |
130 | MOV.W r14, &\OP2_LO ; Load operand 2 Low into multiplier | |
131 | MOV.W r15, &\OP2_HI ; Load operand 2 High, trigger MPY | |
132 | MOV.W &\RESULT_LO, r12 ; Ready low 16-bits for return | |
133 | MOV.W &\RESULT_HI, r13 ; Ready high 16-bits for return | |
134 | .endm | |
135 | ||
136 | .macro mult3264_hw OP1_LO OP1_HI OP2_LO OP2_HI RES0 RES1 RES2 RES3 | |
137 | ;* * 32-bit hardware multiply with a 64-bit result | |
138 | ;* int64 = int32 * int32 | |
139 | ;* uint64 = uint32 * uint32 | |
140 | ;* | |
141 | ;* - Operand 1 is in R12, R13 | |
142 | ;* - Operand 2 is in R14, R15 | |
143 | ;* - Result is in R12, R13, R14, R15 | |
144 | ;* | |
145 | ;* To ensure that the multiply is performed atomically, interrupts are | |
146 | ;* disabled upon routine entry. Interrupt state is restored upon exit. | |
147 | ;* | |
148 | ;* Registers used: R12, R13, R14, R15 | |
149 | ;* | |
150 | ;* Macro arguments are the memory locations of the hardware registers. | |
151 | ||
152 | MOV.W r12, &\OP1_LO ; Load operand 1 Low into multiplier | |
153 | MOV.W r13, &\OP1_HI ; Load operand 1 High into multiplier | |
154 | MOV.W r14, &\OP2_LO ; Load operand 2 Low into multiplier | |
155 | MOV.W r15, &\OP2_HI ; Load operand 2 High, trigger MPY | |
156 | MOV.W &\RES0, R12 ; Ready low 16-bits for return | |
157 | MOV.W &\RES1, R13 ; | |
158 | MOV.W &\RES2, R14 ; | |
159 | MOV.W &\RES3, R15 ; Ready high 16-bits for return | |
160 | .endm | |
161 | ||
162 | ||
163 | ;; First generation MSP430 hardware multiplies .... | |
164 | ||
165 | .set MPY_OP1, 0x0130 | |
166 | .set MPY_OP1_S, 0x0132 | |
167 | .set MAC_OP1, 0x0134 | |
168 | .set MPY_OP2, 0x0138 | |
169 | .set MAC_OP2, 0x0138 | |
170 | .set RESULT_LO, 0x013A | |
171 | .set RESULT_HI, 0x013C | |
172 | ||
173 | start_func __mulhi2 | |
174 | mult16 MPY_OP1, MPY_OP2, RESULT_LO | |
175 | end_func __mulhi2 | |
176 | ||
177 | start_func __mulsihi2 | |
178 | mult1632 MPY_OP1_S, MPY_OP2, RESULT_LO, RESULT_HI | |
179 | end_func __mulsihi2 | |
180 | ||
181 | start_func __umulsihi2 | |
182 | mult1632 MPY_OP1, MPY_OP2, RESULT_LO, RESULT_HI | |
183 | end_func __umulsihi2 | |
184 | ||
185 | start_func __mulsi2 | |
186 | mult32 MPY_OP1, MPY_OP2, MAC_OP1, MAC_OP2, RESULT_LO, RESULT_HI | |
187 | end_func __mulsi2 | |
188 | ||
189 | start_func __mulsi2_hw32 | |
190 | mult32_hw 0x0140, 0x0142, 0x0150, 0x0152, 0x0154, 0x0156 | |
191 | end_func __mulsi2_hw32 | |
192 | ||
193 | start_func __muldisi2_hw32 | |
194 | mult3264_hw 0x0144, 0x146, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015A | |
195 | end_func __muldisi2_hw32 | |
196 | ||
197 | start_func __umuldisi2_hw32 | |
198 | mult3264_hw 0x0140, 0x142, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015A | |
199 | end_func __umuldisi2_hw32 | |
200 | ||
201 | /* The F5xxx series of MCUs support the same 16-bit hardware | |
202 | multiply, but it is accessed from different memory registers. */ | |
203 | ||
204 | start_func __mulhi2_f5 | |
205 | mult16 0x04C0, 0x04C8, 0x04CA | |
206 | end_func __mulhi2_f5 | |
207 | ||
208 | start_func __mulsihi2_f5 | |
209 | mult1632 0x04C2, 0x04C8, 0x04CA, 0x04CC | |
210 | end_func __mulsihi2_f5 | |
211 | ||
212 | start_func __umulsihi2_f5 | |
213 | mult1632 0x04C0, 0x04C8, 0x04CA, 0x04CC | |
214 | end_func __umulsihi2_f5 | |
215 | ||
216 | start_func __mulsi2_f5 | |
217 | mult32_hw 0x04D0, 0x04D2, 0x04E0, 0x04E2, 0x04E4, 0x04E6 | |
218 | end_func __mulsi2_f5 | |
219 | ||
220 | start_func __muldisi2_f5 | |
221 | mult3264_hw 0x04D4, 0x04D6, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA | |
222 | end_func __muldisi2_f5 | |
223 | ||
224 | start_func __umuldisi2_f5 | |
225 | mult3264_hw 0x04D0, 0x04D2, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA | |
226 | end_func __umuldisi2_f5 |