]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/msp430/lib2hw_mul.S
MSP430: Define function to check 16-bit hwmult support
[thirdparty/gcc.git] / libgcc / config / msp430 / lib2hw_mul.S
CommitLineData
8d9254fc 1; Copyright (C) 2014-2020 Free Software Foundation, Inc.
df2b279c
NC
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
04a9ae28
NC
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
9afebea2 42 .p2align 1
04a9ae28
NC
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:
df2b279c
NC
52 PUSH.W sr ; Save current interrupt state
53 DINT ; Disable interrupts
54 NOP ; Account for latency
55.endm
56
04a9ae28
NC
57
58 ;; End a function started with the start_func macro.
df2b279c
NC
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
69
04a9ae28
NC
70
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__
91c64455 84 BRA #\eabi_soft_name
04a9ae28 85#else
91c64455 86 BR #\eabi_soft_name
04a9ae28
NC
87#endif
88 .size \gcc_name , . - \gcc_name
89 .popsection
90.endm
91
92
df2b279c
NC
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
99;*
100;* To ensure that the multiply is performed atomically, interrupts are
101;* disabled upon routine entry. Interrupt state is restored upon exit.
102;*
103;* Registers used: R12, R13
104;*
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
111
91c64455 112.macro mult1632 OP1, OP2, RESLO, RESHI
df2b279c
NC
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
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
125;*
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
91c64455
JL
130 MOV.W &\RESLO, r12 ; Move low result into return register
131 MOV.W &\RESHI, r13 ; Move high result into return register
df2b279c
NC
132.endm
133
91c64455 134.macro mult32 OP1, OP2, MAC_OP1, MAC_OP2, RESLO, RESHI
df2b279c
NC
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
141;*
142;* To ensure that the multiply is performed atomically, interrupts are
143;* disabled upon routine entry. Interrupt state is restored upon exit.
144;*
145;* Registers used: R12, R13, R14, R15
146;*
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
91c64455
JL
152 MOV.W &\RESLO, r12 ; Low 16-bits of result ready for return
153 MOV.W &\RESHI, &\RESLO ; MOV intermediate mpy high into low
df2b279c
NC
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
91c64455 157 MOV.W &\RESLO, r13 ; Upper 16-bits result ready for return
df2b279c
NC
158.endm
159
160
91c64455 161.macro mult32_hw OP1_LO OP1_HI OP2_LO OP2_HI RESLO RESHI
df2b279c
NC
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
168;*
169;* To ensure that the multiply is performed atomically, interrupts are
170;* disabled upon routine entry. Interrupt state is restored upon exit.
171;*
172;* Registers used: R12, R13, R14, R15
173;*
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
91c64455
JL
180 MOV.W &\RESLO, r12 ; Ready low 16-bits for return
181 MOV.W &\RESHI, r13 ; Ready high 16-bits for return
df2b279c
NC
182.endm
183
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
192;*
193;* To ensure that the multiply is performed atomically, interrupts are
194;* disabled upon routine entry. Interrupt state is restored upon exit.
195;*
196;* Registers used: R12, R13, R14, R15
197;*
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
209
210
04a9ae28
NC
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).
237;;
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).
91c64455 267;; uint64 __mspabi_mpyull_f5hw(uint32 x, uint32 y)
04a9ae28
NC
268;; Multiply unsigned long by unsigned long; result is unsigned long long. Uses hardware MPY32 (F5xx devices and up)
269
91c64455
JL
270;;;; The register names below are the standardised versions used across TI
271;;;; literature.
272
273;; Hardware multiply register addresses for devices with 16-bit hardware
274;; multiply.
275.set MPY, 0x0130
276.set MPYS, 0x0132
277.set MAC, 0x0134
278.set OP2, 0x0138
279.set RESLO, 0x013A
280.set RESHI, 0x013C
281;; Hardware multiply register addresses for devices with 32-bit (non-f5)
282;; hardware multiply.
283.set MPY32L, 0x0140
284.set MPY32H, 0x0142
285.set MPYS32L, 0x0144
286.set MPYS32H, 0x0146
287.set OP2L, 0x0150
288.set OP2H, 0x0152
289.set RES0, 0x0154
290.set RES1, 0x0156
291.set RES2, 0x0158
292.set RES3, 0x015A
293;; Hardware multiply register addresses for devices with f5series hardware
294;; multiply.
295;; The F5xxx series of MCUs support the same 16-bit and 32-bit multiply
296;; as the second generation hardware, but they are accessed from different
297;; memory registers.
298;; These names AREN'T standard. We've appended _F5 to the standard names.
299.set MPY_F5, 0x04C0
300.set MPYS_F5, 0x04C2
301.set MAC_F5, 0x04C4
302.set OP2_F5, 0x04C8
303.set RESLO_F5, 0x04CA
304.set RESHI_F5, 0x04CC
305.set MPY32L_F5, 0x04D0
306.set MPY32H_F5, 0x04D2
307.set MPYS32L_F5, 0x04D4
308.set MPYS32H_F5, 0x04D6
309.set OP2L_F5, 0x04E0
310.set OP2H_F5, 0x04E2
311.set RES0_F5, 0x04E4
312.set RES1_F5, 0x04E6
313.set RES2_F5, 0x04E8
314.set RES3_F5, 0x04EA
04a9ae28
NC
315
316#if defined MUL_16
317;; First generation MSP430 hardware multiplies ...
318
319 start_func __mulhi2 __mspabi_mpyi __mspabi_mpyi_hw
91c64455 320 mult16 MPY, OP2, RESLO
04a9ae28 321 end_func __mulhi2
df2b279c 322
91c64455
JL
323 start_func __mulhisi2 __mspabi_mpysl __mspabi_mpysl_hw
324 mult1632 MPYS, OP2, RESLO, RESHI
325 end_func __mulhisi2
df2b279c 326
91c64455
JL
327 start_func __umulhisi2 __mspabi_mpyul __mspabi_mpyul_hw
328 mult1632 MPY, OP2, RESLO, RESHI
329 end_func __umulhisi2
df2b279c 330
04a9ae28 331 start_func __mulsi2 __mspabi_mpyl __mspabi_mpyl_hw
91c64455 332 mult32 MPY, OP2, MAC, OP2, RESLO, RESHI
04a9ae28 333 end_func __mulsi2
df2b279c 334
04a9ae28
NC
335 ;; FIXME: We do not have hardware implementations of these
336 ;; routines, so just jump to the software versions instead.
91c64455
JL
337 fake_func __mulsidi2 __mspabi_mpysll __mspabi_mpysll_hw
338 fake_func __umulsidi2 __mspabi_mpyull __mspabi_mpyull_hw
339 fake_func __muldi3 __mspabi_mpyll __mspabi_mpyll_hw
04a9ae28
NC
340
341#elif defined MUL_32
342;; Second generation MSP430 hardware multiplies ...
343
344 start_func __mulhi2 __mspabi_mpyi __mspabi_mpyi_hw
91c64455 345 mult16 MPY, OP2, RESLO
04a9ae28
NC
346 end_func __mulhi2
347
91c64455
JL
348 start_func __mulhisi2 __mspabi_mpysl __mspabi_mpysl_hw
349 mult1632 MPYS, OP2, RESLO, RESHI
350 end_func __mulhisi2
04a9ae28 351
91c64455
JL
352 start_func __umulhisi2 __mspabi_mpyul __mspabi_mpyul_hw
353 mult1632 MPY, OP2, RESLO, RESHI
354 end_func __umulhisi2
04a9ae28
NC
355
356 start_func __mulsi2_hw32 __mspabi_mpyl __mspabi_mpyl_hw32
91c64455 357 mult32_hw MPY32L, MPY32H, OP2L, OP2H, RES0, RES1
04a9ae28 358 end_func __mulsi2_hw32
df2b279c 359
91c64455
JL
360 start_func __mulsidi2 __mspabi_mpysll __mspabi_mpysll_hw32
361 mult3264_hw MPYS32L, MPYS32H, OP2L, OP2H, RES0, RES1, RES2, RES3
362 end_func __mulsidi2
df2b279c 363
91c64455
JL
364 start_func __umulsidi2 __mspabi_mpyull __mspabi_mpyull_hw32
365 mult3264_hw MPY32L, MPY32H, OP2L, OP2H, RES0, RES1, RES2, RES3
366 end_func __umulsidi2
04a9ae28
NC
367
368 ;; FIXME: Add a hardware version of this function.
91c64455
JL
369 fake_func __muldi3 __mspabi_mpyll __mspabi_mpyll_hw32
370
04a9ae28
NC
371#elif defined MUL_F5
372/* The F5xxx series of MCUs support the same 16-bit and 32-bit multiply
373 as the second generation hardware, but they are accessed from different
374 memory registers. */
375
376 start_func __mulhi2_f5 __mspabi_mpyi __mspabi_mpyi_f5hw
91c64455 377 mult16 MPY_F5, OP2_F5, RESLO_F5
04a9ae28 378 end_func __mulhi2_f5
df2b279c 379
91c64455
JL
380 start_func __mulhisi2 __mspabi_mpysl __mspabi_mpysl_f5hw
381 mult1632 MPYS_F5, OP2_F5, RESLO_F5, RESHI_F5
382 end_func __mulhisi2
383
384 start_func __umulhisi2 __mspabi_mpyul __mspabi_mpyul_f5hw
385 mult1632 MPY_F5, OP2_F5, RESLO_F5, RESHI_F5
386 end_func __umulhisi2
df2b279c 387
04a9ae28 388 start_func __mulsi2_f5 __mspabi_mpyl __mspabi_mpyl_f5hw
91c64455 389 mult32_hw MPY32L_F5, MPY32H_F5, OP2L_F5, OP2H_F5, RES0_F5, RES1_F5
04a9ae28 390 end_func __mulsi2_f5
91c64455
JL
391
392 start_func __mulsidi2 __mspabi_mpysll __mspabi_mpysll_f5hw
393 mult3264_hw MPYS32L_F5, MPYS32H_F5, OP2L_F5, OP2H_F5, RES0_F5, RES1_F5, RES2_F5, RES3_F5
394 end_func __mulsidi2
395
396 start_func __umulsidi2 __mspabi_mpyull __mspabi_mpyull_f5hw
397 mult3264_hw MPY32L_F5, MPY32H_F5, OP2L_F5, OP2H_F5, RES0_F5, RES1_F5, RES2_F5, RES3_F5
398 end_func __umulsidi2
04a9ae28
NC
399
400 ;; FIXME: Add a hardware version of this function.
91c64455 401 fake_func __muldi3 __mspabi_mpyll __mspabi_mpyll_f5hw
04a9ae28
NC
402
403#else
404#error MUL type not defined
405#endif