PR libstdc++/84769 qualify std::get and std::get_if to avoid ADL
[official-gcc.git] / libgcc / config / msp430 / lib2hw_mul.S
blob833edc142ab27e95e15c7a6e4a40543a40a21339
1 ;   Copyright (C) 2014-2018 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.
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/>.
23         ;;  Macro to start a multiply function.  Each function has three
24         ;; names, and hence three entry points - although they all go
25         ;; through the same code.  The first name is the version generated
26         ;; by GCC.  The second is the MSP430 EABI mandated name for the
27         ;; *software* version of the function.  The third is the EABI
28         ;; mandated name for the *hardware* version of the function.
29         ;; 
30         ;;  Since we are using the hardware and software names to point
31         ;; to the same code this effectively means that we are mapping
32         ;; the software function onto the hardware function.  Thus if
33         ;; the library containing this code is linked into an application
34         ;; (before the libgcc.a library) *all* multiply functions will
35         ;; be mapped onto the hardware versions.
36         ;;
37         ;;  We construct each function in its own section so that linker
38         ;; garbage collection can be used to delete any unused functions
39         ;; from this file.
40 .macro start_func gcc_name eabi_soft_name eabi_hard_name
41         .pushsection .text.\gcc_name,"ax",@progbits
42         .p2align 1
43         .global \eabi_hard_name
44         .type \eabi_hard_name , @function
45 \eabi_hard_name:
46         .global \eabi_soft_name
47         .type \eabi_soft_name , @function
48 \eabi_soft_name:
49         .global \gcc_name
50         .type \gcc_name , @function
51 \gcc_name:
52         PUSH.W  sr                      ; Save current interrupt state
53         DINT                            ; Disable interrupts
54         NOP                             ; Account for latency
55 .endm
58         ;; End a function started with the start_func macro.
59 .macro end_func name
60 #ifdef __MSP430X_LARGE__
61         POP.W  sr
62         RETA
63 #else
64         RETI
65 #endif
66         .size \name , . - \name
67         .popsection
68 .endm
71         ;; Like the start_func macro except that it is used to
72         ;; create a false entry point that just jumps to the
73         ;; software function (implemented elsewhere).
74 .macro fake_func gcc_name  eabi_soft_name  eabi_hard_name
75         .pushsection .text.\gcc_name,"ax",@progbits
76         .p2align 1
77         .global \eabi_hard_name
78         .type \eabi_hard_name , @function
79 \eabi_hard_name:
80         .global \gcc_name
81         .type \gcc_name , @function
82 \gcc_name:
83 #ifdef __MSP430X_LARGE__
84         BRA     \eabi_soft_name
85 #else
86         BR      \eabi_soft_name
87 #endif
88         .size \gcc_name , . - \gcc_name
89         .popsection
90 .endm
93 .macro mult16 OP1, OP2, RESULT
94 ;* * 16-bit hardware multiply:  int16 = int16 * int16
95 ;*  
96 ;*   - Operand 1 is in R12
97 ;*   - Operand 2 is in R13
98 ;*   - Result is in R12
100 ;* To ensure that the multiply is performed atomically, interrupts are
101 ;* disabled upon routine entry.  Interrupt state is restored upon exit.
103 ;*   Registers used:  R12, R13
105 ;* Macro arguments are the memory locations of the hardware registers.
106         
107         MOV.W   r12, &\OP1              ; Load operand 1 into multiplier
108         MOV.W   r13, &\OP2              ; Load operand 2 which triggers MPY
109         MOV.W   &\RESULT, r12           ; Move result into return register
110 .endm
112 .macro mult1632 OP1, OP2, RESULT_LO, RESULT_HI
113 ;* * 16-bit hardware multiply with a 32-bit result:
114 ;*      int32 = int16 * int16
115 ;*      uint32 = uint16 * uint16
116 ;*  
117 ;*   - Operand 1 is in R12
118 ;*   - Operand 2 is in R13
119 ;*   - Result is in R12, R13
121 ;* To ensure that the multiply is performed atomically, interrupts are
122 ;* disabled upon routine entry.  Interrupt state is restored upon exit.
124 ;*   Registers used:  R12, R13
126 ;* Macro arguments are the memory locations of the hardware registers.
127         
128         MOV.W   r12, &\OP1              ; Load operand 1 into multiplier
129         MOV.W   r13, &\OP2              ; Load operand 2 which triggers MPY
130         MOV.W   &\RESULT_LO, r12        ; Move low result into return register
131         MOV.W   &\RESULT_HI, r13        ; Move high result into return register
132 .endm
134 .macro mult32 OP1, OP2, MAC_OP1, MAC_OP2, RESULT_LO, RESULT_HI
135 ;* * 32-bit hardware multiply with a 32-bit result using 16 multiply and accumulate:
136 ;*      int32 = int32 * int32
137 ;*  
138 ;*   - Operand 1 is in R12, R13
139 ;*   - Operand 2 is in R14, R15
140 ;*   - Result    is in R12, R13
142 ;* To ensure that the multiply is performed atomically, interrupts are
143 ;* disabled upon routine entry.  Interrupt state is restored upon exit.
145 ;*   Registers used:  R12, R13, R14, R15
147 ;* Macro arguments are the memory locations of the hardware registers.
148         
149         MOV.W   r12, &\OP1              ; Load operand 1 Low into multiplier
150         MOV.W   r14, &\OP2              ; Load operand 2 Low which triggers MPY
151         MOV.W   r12, &\MAC_OP1          ; Load operand 1 Low into mac
152         MOV.W   &\RESULT_LO, r12        ; Low 16-bits of result ready for return
153         MOV.W   &\RESULT_HI, &\RESULT_LO; MOV intermediate mpy high into low
154         MOV.W   r15, &\MAC_OP2          ; Load operand 2 High, trigger MAC
155         MOV.W   r13, &\MAC_OP1          ; Load operand 1 High
156         MOV.W   r14, &\MAC_OP2          ; Load operand 2 Lo, trigger MAC
157         MOV.W   &\RESULT_LO, r13        ; Upper 16-bits result ready for return
158 .endm
161 .macro mult32_hw  OP1_LO  OP1_HI  OP2_LO  OP2_HI  RESULT_LO  RESULT_HI
162 ;* * 32-bit hardware multiply with a 32-bit result
163 ;*      int32 = int32 * int32
164 ;*  
165 ;*   - Operand 1 is in R12, R13
166 ;*   - Operand 2 is in R14, R15
167 ;*   - Result    is in R12, R13
169 ;* To ensure that the multiply is performed atomically, interrupts are
170 ;* disabled upon routine entry.  Interrupt state is restored upon exit.
172 ;*   Registers used:  R12, R13, R14, R15
174 ;* Macro arguments are the memory locations of the hardware registers.
175         
176         MOV.W   r12, &\OP1_LO           ; Load operand 1 Low into multiplier
177         MOV.W   r13, &\OP1_HI           ; Load operand 1 High into multiplier
178         MOV.W   r14, &\OP2_LO           ; Load operand 2 Low into multiplier
179         MOV.W   r15, &\OP2_HI           ; Load operand 2 High, trigger MPY
180         MOV.W   &\RESULT_LO, r12        ; Ready low 16-bits for return
181         MOV.W   &\RESULT_HI, r13        ; Ready high 16-bits for return
182 .endm
184 .macro mult3264_hw  OP1_LO  OP1_HI  OP2_LO  OP2_HI  RES0 RES1 RES2 RES3
185 ;* * 32-bit hardware multiply with a 64-bit result
186 ;*      int64 = int32 * int32
187 ;*      uint64 = uint32 * uint32
188 ;*  
189 ;*   - Operand 1 is in R12, R13
190 ;*   - Operand 2 is in R14, R15
191 ;*   - Result    is in R12, R13, R14, R15
193 ;* To ensure that the multiply is performed atomically, interrupts are
194 ;* disabled upon routine entry.  Interrupt state is restored upon exit.
196 ;*   Registers used:  R12, R13, R14, R15
198 ;* Macro arguments are the memory locations of the hardware registers.
199         
200         MOV.W   r12, &\OP1_LO           ; Load operand 1 Low into multiplier
201         MOV.W   r13, &\OP1_HI           ; Load operand 1 High into multiplier
202         MOV.W   r14, &\OP2_LO           ; Load operand 2 Low into multiplier
203         MOV.W   r15, &\OP2_HI           ; Load operand 2 High, trigger MPY
204         MOV.W   &\RES0, R12             ; Ready low 16-bits for return
205         MOV.W   &\RES1, R13             ; 
206         MOV.W   &\RES2, R14             ; 
207         MOV.W   &\RES3, R15             ; Ready high 16-bits for return
208 .endm
211 ;; EABI mandated names:
212 ;; 
213 ;; int16 __mspabi_mpyi (int16 x, int16 y)
214 ;;            Multiply int by int.
215 ;; int16 __mspabi_mpyi_hw (int16 x, int16 y)
216 ;;            Multiply int by int. Uses hardware MPY16 or MPY32.
217 ;; int16 __mspabi_mpyi_f5hw (int16 x, int16 y)
218 ;;            Multiply int by int. Uses hardware MPY32 (F5xx devices and up).
219 ;; 
220 ;; int32 __mspabi_mpyl (int32 x, int32 y);
221 ;;            Multiply long by long.
222 ;; int32 __mspabi_mpyl_hw (int32 x, int32 y)
223 ;;            Multiply long by long. Uses hardware MPY16.
224 ;; int32 __mspabi_mpyl_hw32 (int32 x, int32 y)
225 ;;            Multiply long by long. Uses hardware MPY32 (F4xx devices).
226 ;; int32 __mspabi_mpyl_f5hw (int32 x, int32 y)
227 ;;            Multiply long by long. Uses hardware MPY32 (F5xx devices and up).
228 ;; 
229 ;; int64 __mspabi_mpyll (int64 x, int64 y)
230 ;;            Multiply long long by long long.
231 ;; int64 __mspabi_mpyll_hw (int64 x, int64 y)
232 ;;            Multiply long long by long long. Uses hardware MPY16.
233 ;; int64 __mspabi_mpyll_hw32 (int64 x, int64 y)
234 ;;            Multiply long long by long long. Uses hardware MPY32 (F4xx devices).
235 ;; int64 __mspabi_mpyll_f5hw (int64 x, int64 y)
236 ;;            Multiply long long by long long. Uses hardware MPY32 (F5xx devices and up).
238 ;; int32 __mspabi_mpysl (int16 x, int16 y)
239 ;;            Multiply int by int; result is long.
240 ;; int32 __mspabi_mpysl_hw(int16 x, int16 y)
241 ;;            Multiply int by int; result is long. Uses hardware MPY16 or MPY32
242 ;; int32 __mspabi_mpysl_f5hw(int16 x, int16 y)
243 ;;            Multiply int by int; result is long. Uses hardware MPY32 (F5xx devices and up).
244 ;; 
245 ;; int64 __mspabi_mpysll(int32 x, int32 y)
246 ;;            Multiply long by long; result is long long.
247 ;; int64 __mspabi_mpysll_hw(int32 x, int32 y)
248 ;;            Multiply long by long; result is long long. Uses hardware MPY16.
249 ;; int64 __mspabi_mpysll_hw32(int32 x, int32 y)
250 ;;            Multiply long by long; result is long long. Uses hardware MPY32 (F4xx devices).
251 ;; int64 __mspabi_mpysll_f5hw(int32 x, int32 y)
252 ;;            Multiply long by long; result is long long. Uses hardware MPY32 (F5xx devices and up).
253 ;; 
254 ;; uint32 __mspabi_mpyul(uint16 x, uint16 y)
255 ;;            Multiply unsigned int by unsigned int; result is unsigned long.
256 ;; uint32 __mspabi_mpyul_hw(uint16 x, uint16 y)
257 ;;            Multiply unsigned int by unsigned int; result is unsigned long. Uses hardware MPY16 or MPY32
258 ;; uint32 __mspabi_mpyul_f5hw(uint16 x, uint16 y)
259 ;;            Multiply unsigned int by unsigned int; result is unsigned long. Uses hardware MPY32 (F5xx devices and up).
260 ;; 
261 ;; uint64 __mspabi_mpyull(uint32 x, uint32 y)
262 ;;            Multiply unsigned long by unsigned long; result is unsigned long long.
263 ;; uint64 __mspabi_mpyull_hw(uint32 x, uint32 y)
264 ;;            Multiply unsigned long by unsigned long; result is unsigned long long. Uses hardware MPY16
265 ;; uint64 __mspabi_mpyull_hw32(uint32 x, uint32 y)
266 ;;            Multiply unsigned long by unsigned long; result is unsigned long long. Uses hardware MPY32 (F4xx devices).
267 ;; uint64 _ _mspabi_mpyull_f5hw(uint32 x, uint32 y)
268 ;;            Multiply unsigned long by unsigned long; result is unsigned long long. Uses hardware MPY32 (F5xx devices and up)
272 .set MPY_OP1,   0x0130
273 .set MPY_OP1_S, 0x0132
274 .set MAC_OP1,   0x0134
275 .set MPY_OP2,   0x0138
276 .set MAC_OP2,   0x0138
277 .set RESULT_LO, 0x013A
278 .set RESULT_HI, 0x013C
280 #if defined MUL_16
281 ;;  First generation MSP430 hardware multiplies ...
283         start_func __mulhi2 __mspabi_mpyi  __mspabi_mpyi_hw
284         mult16 MPY_OP1, MPY_OP2, RESULT_LO
285         end_func   __mulhi2
287         start_func __mulsihi2  __mspabi_mpysl  __mspabi_mpysl_hw
288         mult1632 MPY_OP1_S, MPY_OP2, RESULT_LO, RESULT_HI
289         end_func   __mulsihi2
291         start_func __umulsihi2  __mspabi_mpyul  _mspabi_mpyul_hw
292         mult1632 MPY_OP1, MPY_OP2, RESULT_LO, RESULT_HI
293         end_func   __umulsihi2
295         start_func __mulsi2  __mspabi_mpyl  __mspabi_mpyl_hw
296         mult32 MPY_OP1, MPY_OP2, MAC_OP1, MAC_OP2, RESULT_LO, RESULT_HI
297         end_func   __mulsi2
299         ;; FIXME: We do not have hardware implementations of these
300         ;; routines, so just jump to the software versions instead.
301         fake_func __muldisi2   __mspabi_mpysll  __mspabi_mpysll_hw   
302         fake_func __umuldisi2  __mspabi_mpyull  __mspabi_mpyull_hw  
303         fake_func __muldi3     __mspabi_mpyll   __mspabi_mpyll_hw       
305 #elif defined MUL_32
306 ;;  Second generation MSP430 hardware multiplies ...
308         start_func __mulhi2  __mspabi_mpyi  __mspabi_mpyi_hw
309         mult16 MPY_OP1, MPY_OP2, RESULT_LO
310         end_func   __mulhi2
312         start_func __mulsihi2  __mspabi_mpysl  __mspabi_mpysl_hw
313         mult1632 MPY_OP1_S, MPY_OP2, RESULT_LO, RESULT_HI
314         end_func   __mulsihi2
316         start_func __umulsihi2  __mspabi_mpyul  _mspabi_mpyul_hw
317         mult1632 MPY_OP1, MPY_OP2, RESULT_LO, RESULT_HI
318         end_func   __umulsihi2
320         start_func __mulsi2_hw32  __mspabi_mpyl  __mspabi_mpyl_hw32
321         mult32_hw 0x0140, 0x0142, 0x0150, 0x0152, 0x0154, 0x0156
322         end_func   __mulsi2_hw32
324         start_func __muldisi2  __mspabi_mpysll  __mspabi_mpysll_hw32
325         mult3264_hw 0x0144, 0x146, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015A
326         end_func   __muldisi2
328         start_func __umuldisi2 __mspabi_mpyull  __mspabi_mpyull_hw32
329         mult3264_hw 0x0140, 0x142, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015A
330         end_func   __umuldisi2
332         ;; FIXME: Add a hardware version of this function.
333         fake_func __muldi3    __mspabi_mpyll  __mspabi_mpyll_hw32 
334         
335 #elif defined MUL_F5
336 /* The F5xxx series of MCUs support the same 16-bit and 32-bit multiply
337    as the second generation hardware, but they are accessed from different
338    memory registers.  */
340         start_func __mulhi2_f5 __mspabi_mpyi  __mspabi_mpyi_f5hw
341         mult16 0x04C0, 0x04C8, 0x04CA
342         end_func   __mulhi2_f5
344         start_func __mulsihi2  __mspabi_mpysl  __mspabi_mpysl_f5hw
345         mult1632 0x04C2, 0x04C8, 0x04CA, 0x04CC
346         end_func   __mulsihi2
347         
348         start_func __umulsihi2  __mspabi_mpyul  _mspabi_mpyul_f5hw
349         mult1632 0x04C0, 0x04C8, 0x04CA, 0x04CC
350         end_func   __umulsihi2
352         start_func __mulsi2_f5  __mspabi_mpyl  __mspabi_mpyl_f5hw
353         mult32_hw 0x04D0, 0x04D2, 0x04E0, 0x04E2, 0x04E4, 0x04E6
354         end_func   __mulsi2_f5
355         
356         start_func __muldisi2  __mspabi_mpysll  __mspabi_mpysll_f5hw
357         mult3264_hw 0x04D4, 0x04D6, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA
358         end_func   __muldisi2
359         
360         start_func __umuldisi2  __mspabi_mpyull  __mspabi_mpyull_f5hw
361         mult3264_hw 0x04D0, 0x04D2, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA
362         end_func   __umuldisi2
364         ;; FIXME: Add a hardware version of this function.
365         fake_func __muldi3   __mspabi_mpyll __mspabi_mpyll_f5hw 
367 #else
368 #error MUL type not defined
369 #endif