t-msp430 (LIB2ADD): Add lib2hw_mul.S
authorNick Clifton <nickc@redhat.com>
Thu, 6 Mar 2014 08:35:40 +0000 (08:35 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Thu, 6 Mar 2014 08:35:40 +0000 (08:35 +0000)
* config/msp430/t-msp430 (LIB2ADD): Add lib2hw_mul.S
* config/msp430/lib2hw_mul.S: New: Hardware multiply routines.

From-SVN: r208374

libgcc/ChangeLog
libgcc/config/msp430/lib2hw_mul.S [new file with mode: 0644]
libgcc/config/msp430/t-msp430

index 2fe114e4a941a6afd10abab6be2b3d4ff0b041da..0b908d9be783f38513241929583360b16d10a5cd 100644 (file)
@@ -1,3 +1,8 @@
+2014-03-06  Nick Clifton  <nickc@redhat.com>
+
+       * config/msp430/t-msp430 (LIB2ADD): Add lib2hw_mul.S
+       * config/msp430/lib2hw_mul.S: New: Hardware multiply routines.
+
 2014-02-28  Joey Ye  <joey.ye@arm.com>
 
        PR libgcc/60166
diff --git a/libgcc/config/msp430/lib2hw_mul.S b/libgcc/config/msp430/lib2hw_mul.S
new file mode 100644 (file)
index 0000000..7c83323
--- /dev/null
@@ -0,0 +1,226 @@
+;   Copyright (C) 2014 Free Software Foundation, Inc.
+;   Contributed by Red Hat.
+; 
+; This file is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published by the
+; Free Software Foundation; either version 3, or (at your option) any
+; later version.
+; 
+; This file is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+; General Public License for more details.
+; 
+; Under Section 7 of GPL version 3, you are granted additional
+; permissions described in the GCC Runtime Library Exception, version
+; 3.1, as published by the Free Software Foundation.
+;
+; You should have received a copy of the GNU General Public License and
+; a copy of the GCC Runtime Library Exception along with this program;
+; see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+; <http://www.gnu.org/licenses/>.
+
+.macro start_func name
+       .pushsection .text.\name,"ax",@progbits
+       .align 2
+       .global \name
+       .type \name , @function
+\name:
+       PUSH.W  sr                      ; Save current interrupt state
+       DINT                            ; Disable interrupts
+       NOP                             ; Account for latency
+.endm
+
+.macro end_func name
+#ifdef __MSP430X_LARGE__
+       POP.W  sr
+        RETA
+#else
+       RETI
+#endif
+       .size \name , . - \name
+       .popsection
+.endm
+
+.macro mult16 OP1, OP2, RESULT
+;* * 16-bit hardware multiply:  int16 = int16 * int16
+;*  
+;*   - Operand 1 is in R12
+;*   - Operand 2 is in R13
+;*   - Result is in R12
+;*
+;* To ensure that the multiply is performed atomically, interrupts are
+;* disabled upon routine entry.  Interrupt state is restored upon exit.
+;*
+;*   Registers used:  R12, R13
+;*
+;* Macro arguments are the memory locations of the hardware registers.
+       
+       MOV.W   r12, &\OP1              ; Load operand 1 into multiplier
+       MOV.W   r13, &\OP2              ; Load operand 2 which triggers MPY
+       MOV.W   &\RESULT, r12           ; Move result into return register
+.endm
+
+.macro mult1632 OP1, OP2, RESULT_LO, RESULT_HI
+;* * 16-bit hardware multiply with a 32-bit result:
+;*     int32 = int16 * int16
+;*     uint32 = uint16 * uint16
+;*  
+;*   - Operand 1 is in R12
+;*   - Operand 2 is in R13
+;*   - Result is in R12, R13
+;*
+;* To ensure that the multiply is performed atomically, interrupts are
+;* disabled upon routine entry.  Interrupt state is restored upon exit.
+;*
+;*   Registers used:  R12, R13
+;*
+;* Macro arguments are the memory locations of the hardware registers.
+       
+       MOV.W   r12, &\OP1              ; Load operand 1 into multiplier
+       MOV.W   r13, &\OP2              ; Load operand 2 which triggers MPY
+       MOV.W   &\RESULT_LO, r12        ; Move low result into return register
+       MOV.W   &\RESULT_HI, r13        ; Move high result into return register
+.endm
+
+.macro mult32 OP1, OP2, MAC_OP1, MAC_OP2, RESULT_LO, RESULT_HI
+;* * 32-bit hardware multiply with a 32-bit result using 16 multiply and accumulate:
+;*     int32 = int32 * int32
+;*  
+;*   - Operand 1 is in R12, R13
+;*   - Operand 2 is in R14, R15
+;*   - Result    is in R12, R13
+;*
+;* To ensure that the multiply is performed atomically, interrupts are
+;* disabled upon routine entry.  Interrupt state is restored upon exit.
+;*
+;*   Registers used:  R12, R13, R14, R15
+;*
+;* Macro arguments are the memory locations of the hardware registers.
+       
+       MOV.W   r12, &\OP1              ; Load operand 1 Low into multiplier
+       MOV.W   r14, &\OP2              ; Load operand 2 Low which triggers MPY
+       MOV.W   r12, &\MAC_OP1          ; Load operand 1 Low into mac
+       MOV.W   &\RESULT_LO, r12        ; Low 16-bits of result ready for return
+       MOV.W   &\RESULT_HI, &\RESULT_LO; MOV intermediate mpy high into low
+       MOV.W   r15, &\MAC_OP2          ; Load operand 2 High, trigger MAC
+       MOV.W   r13, &\MAC_OP1          ; Load operand 1 High
+       MOV.W   r14, &\MAC_OP2          ; Load operand 2 Lo, trigger MAC
+       MOV.W   &\RESULT_LO, r13        ; Upper 16-bits result ready for return
+.endm
+
+
+.macro mult32_hw  OP1_LO  OP1_HI  OP2_LO  OP2_HI  RESULT_LO  RESULT_HI
+;* * 32-bit hardware multiply with a 32-bit result
+;*     int32 = int32 * int32
+;*  
+;*   - Operand 1 is in R12, R13
+;*   - Operand 2 is in R14, R15
+;*   - Result    is in R12, R13
+;*
+;* To ensure that the multiply is performed atomically, interrupts are
+;* disabled upon routine entry.  Interrupt state is restored upon exit.
+;*
+;*   Registers used:  R12, R13, R14, R15
+;*
+;* Macro arguments are the memory locations of the hardware registers.
+       
+       MOV.W   r12, &\OP1_LO           ; Load operand 1 Low into multiplier
+       MOV.W   r13, &\OP1_HI           ; Load operand 1 High into multiplier
+       MOV.W   r14, &\OP2_LO           ; Load operand 2 Low into multiplier
+       MOV.W   r15, &\OP2_HI           ; Load operand 2 High, trigger MPY
+       MOV.W   &\RESULT_LO, r12        ; Ready low 16-bits for return
+       MOV.W   &\RESULT_HI, r13        ; Ready high 16-bits for return
+.endm
+
+.macro mult3264_hw  OP1_LO  OP1_HI  OP2_LO  OP2_HI  RES0 RES1 RES2 RES3
+;* * 32-bit hardware multiply with a 64-bit result
+;*     int64 = int32 * int32
+;*     uint64 = uint32 * uint32
+;*  
+;*   - Operand 1 is in R12, R13
+;*   - Operand 2 is in R14, R15
+;*   - Result    is in R12, R13, R14, R15
+;*
+;* To ensure that the multiply is performed atomically, interrupts are
+;* disabled upon routine entry.  Interrupt state is restored upon exit.
+;*
+;*   Registers used:  R12, R13, R14, R15
+;*
+;* Macro arguments are the memory locations of the hardware registers.
+       
+       MOV.W   r12, &\OP1_LO           ; Load operand 1 Low into multiplier
+       MOV.W   r13, &\OP1_HI           ; Load operand 1 High into multiplier
+       MOV.W   r14, &\OP2_LO           ; Load operand 2 Low into multiplier
+       MOV.W   r15, &\OP2_HI           ; Load operand 2 High, trigger MPY
+       MOV.W   &\RES0, R12             ; Ready low 16-bits for return
+       MOV.W   &\RES1, R13             ; 
+       MOV.W   &\RES2, R14             ; 
+       MOV.W   &\RES3, R15             ; Ready high 16-bits for return
+.endm
+
+
+;;  First generation MSP430 hardware multiplies ....
+
+.set MPY_OP1,   0x0130
+.set MPY_OP1_S, 0x0132
+.set MAC_OP1,  0x0134
+.set MPY_OP2,  0x0138
+.set MAC_OP2,  0x0138
+.set RESULT_LO, 0x013A
+.set RESULT_HI, 0x013C
+       
+       start_func __mulhi2
+       mult16 MPY_OP1, MPY_OP2, RESULT_LO
+       end_func __mulhi2
+
+       start_func __mulsihi2
+       mult1632 MPY_OP1_S, MPY_OP2, RESULT_LO, RESULT_HI
+       end_func __mulsihi2
+
+       start_func __umulsihi2
+       mult1632 MPY_OP1, MPY_OP2, RESULT_LO, RESULT_HI
+       end_func __umulsihi2
+
+       start_func __mulsi2
+       mult32 MPY_OP1, MPY_OP2, MAC_OP1, MAC_OP2, RESULT_LO, RESULT_HI
+       end_func __mulsi2
+
+       start_func __mulsi2_hw32
+       mult32_hw 0x0140, 0x0142, 0x0150, 0x0152, 0x0154, 0x0156
+       end_func __mulsi2_hw32
+
+       start_func __muldisi2_hw32
+       mult3264_hw 0x0144, 0x146, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015A
+       end_func __muldisi2_hw32
+
+       start_func __umuldisi2_hw32
+       mult3264_hw 0x0140, 0x142, 0x0150, 0x0152, 0x0154, 0x0156, 0x0158, 0x015A
+       end_func __umuldisi2_hw32
+       
+/* The F5xxx series of MCUs support the same 16-bit hardware
+   multiply, but it is accessed from different memory registers.  */
+       
+       start_func __mulhi2_f5
+       mult16 0x04C0, 0x04C8, 0x04CA
+       end_func __mulhi2_f5
+
+       start_func __mulsihi2_f5
+       mult1632 0x04C2, 0x04C8, 0x04CA, 0x04CC
+       end_func __mulsihi2_f5
+       
+       start_func __umulsihi2_f5
+       mult1632 0x04C0, 0x04C8, 0x04CA, 0x04CC
+       end_func __umulsihi2_f5
+
+       start_func __mulsi2_f5
+       mult32_hw 0x04D0, 0x04D2, 0x04E0, 0x04E2, 0x04E4, 0x04E6
+       end_func __mulsi2_f5
+       
+       start_func __muldisi2_f5
+       mult3264_hw 0x04D4, 0x04D6, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA
+       end_func __muldisi2_f5
+       
+       start_func __umuldisi2_f5
+       mult3264_hw 0x04D0, 0x04D2, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, 0x04EA
+       end_func __umuldisi2_f5
index 0ef3c62a4bb1479bf4fd25d49be6bcb8df76bf40..7a7b68007a51172315f8c8333858433427840d16 100644 (file)
@@ -35,6 +35,7 @@ LIB2ADD = \
        $(srcdir)/config/msp430/srai.S \
        $(srcdir)/config/msp430/srli.S \
        $(srcdir)/config/msp430/cmpsi2.S \
+       $(srcdir)/config/msp430/lib2hw_mul.S \
        $(srcdir)/config/msp430/floatunhisf.c \
        $(srcdir)/config/msp430/floatunhidf.c \
        $(srcdir)/config/msp430/floathidf.c \