1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
; Copyright (C) 2014-2015 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
|