1 /**************************************************************************//** 2 * @file cmsis_gcc.h 3 * @brief CMSIS Cortex-M Core Function/Instruction Header File 4 * @version V4.20 5 * @date 18. August 2015 6 ******************************************************************************/ 7 /* Copyright (c) 2009 - 2015 ARM LIMITED 8 9 All rights reserved. 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions are met: 12 - Redistributions of source code must retain the above copyright 13 notice, this list of conditions and the following disclaimer. 14 - Redistributions in binary form must reproduce the above copyright 15 notice, this list of conditions and the following disclaimer in the 16 documentation and/or other materials provided with the distribution. 17 - Neither the name of ARM nor the names of its contributors may be used 18 to endorse or promote products derived from this software without 19 specific prior written permission. 20 * 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 POSSIBILITY OF SUCH DAMAGE. 32 ---------------------------------------------------------------------------*/ 33 34 35 #ifndef __CMSIS_GCC_H 36 #define __CMSIS_GCC_H 37 38 39 /* ########################### Core Function Access ########################### */ 40 /** \ingroup CMSIS_Core_FunctionInterface 41 \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 42 @{ 43 */ 44 45 /** \brief Enable IRQ Interrupts 46 47 This function enables IRQ interrupts by clearing the I-bit in the CPSR. 48 Can only be executed in Privileged modes. 49 */ 50 __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) 51 { 52 __ASM volatile ("cpsie i" : : : "memory"); 53 } 54 55 56 /** \brief Disable IRQ Interrupts 57 58 This function disables IRQ interrupts by setting the I-bit in the CPSR. 59 Can only be executed in Privileged modes. 60 */ 61 __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) 62 { 63 __ASM volatile ("cpsid i" : : : "memory"); 64 } 65 66 67 /** \brief Get Control Register 68 69 This function returns the content of the Control Register. 70 71 \return Control Register value 72 */ 73 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) 74 { 75 uint32_t result; 76 77 __ASM volatile ("MRS %0, control" : "=r" (result) ); 78 return(result); 79 } 80 81 82 /** \brief Set Control Register 83 84 This function writes the given value to the Control Register. 85 86 \param [in] control Control Register value to set 87 */ 88 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) 89 { 90 __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); 91 } 92 93 94 /** \brief Get IPSR Register 95 96 This function returns the content of the IPSR Register. 97 98 \return IPSR Register value 99 */ 100 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) 101 { 102 uint32_t result; 103 104 __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); 105 return(result); 106 } 107 108 109 /** \brief Get APSR Register 110 111 This function returns the content of the APSR Register. 112 113 \return APSR Register value 114 */ 115 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) 116 { 117 uint32_t result; 118 119 __ASM volatile ("MRS %0, apsr" : "=r" (result) ); 120 return(result); 121 } 122 123 124 /** \brief Get xPSR Register 125 126 This function returns the content of the xPSR Register. 127 128 \return xPSR Register value 129 */ 130 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) 131 { 132 uint32_t result; 133 134 __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); 135 return(result); 136 } 137 138 139 /** \brief Get Process Stack Pointer 140 141 This function returns the current value of the Process Stack Pointer (PSP). 142 143 \return PSP Register value 144 */ 145 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) 146 { 147 register uint32_t result; 148 149 __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); 150 return(result); 151 } 152 153 154 /** \brief Set Process Stack Pointer 155 156 This function assigns the given value to the Process Stack Pointer (PSP). 157 158 \param [in] topOfProcStack Process Stack Pointer value to set 159 */ 160 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) 161 { 162 __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); 163 } 164 165 166 /** \brief Get Main Stack Pointer 167 168 This function returns the current value of the Main Stack Pointer (MSP). 169 170 \return MSP Register value 171 */ 172 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) 173 { 174 register uint32_t result; 175 176 __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); 177 return(result); 178 } 179 180 181 /** \brief Set Main Stack Pointer 182 183 This function assigns the given value to the Main Stack Pointer (MSP). 184 185 \param [in] topOfMainStack Main Stack Pointer value to set 186 */ 187 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) 188 { 189 __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); 190 } 191 192 193 /** \brief Get Priority Mask 194 195 This function returns the current state of the priority mask bit from the Priority Mask Register. 196 197 \return Priority Mask value 198 */ 199 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) 200 { 201 uint32_t result; 202 203 __ASM volatile ("MRS %0, primask" : "=r" (result) ); 204 return(result); 205 } 206 207 208 /** \brief Set Priority Mask 209 210 This function assigns the given value to the Priority Mask Register. 211 212 \param [in] priMask Priority Mask 213 */ 214 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) 215 { 216 __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); 217 } 218 219 220 #if (__CORTEX_M >= 0x03U) 221 222 /** \brief Enable FIQ 223 224 This function enables FIQ interrupts by clearing the F-bit in the CPSR. 225 Can only be executed in Privileged modes. 226 */ 227 __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) 228 { 229 __ASM volatile ("cpsie f" : : : "memory"); 230 } 231 232 233 /** \brief Disable FIQ 234 235 This function disables FIQ interrupts by setting the F-bit in the CPSR. 236 Can only be executed in Privileged modes. 237 */ 238 __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) 239 { 240 __ASM volatile ("cpsid f" : : : "memory"); 241 } 242 243 244 /** \brief Get Base Priority 245 246 This function returns the current value of the Base Priority register. 247 248 \return Base Priority register value 249 */ 250 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) 251 { 252 uint32_t result; 253 254 __ASM volatile ("MRS %0, basepri" : "=r" (result) ); 255 return(result); 256 } 257 258 259 /** \brief Set Base Priority 260 261 This function assigns the given value to the Base Priority register. 262 263 \param [in] basePri Base Priority value to set 264 */ 265 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) 266 { 267 __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); 268 } 269 270 271 /** \brief Set Base Priority with condition 272 273 This function assigns the given value to the Base Priority register only if BASEPRI masking is disabled, 274 or the new value increases the BASEPRI priority level. 275 276 \param [in] basePri Base Priority value to set 277 */ 278 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) 279 { 280 __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); 281 } 282 283 284 /** \brief Get Fault Mask 285 286 This function returns the current value of the Fault Mask register. 287 288 \return Fault Mask register value 289 */ 290 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) 291 { 292 uint32_t result; 293 294 __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); 295 return(result); 296 } 297 298 299 /** \brief Set Fault Mask 300 301 This function assigns the given value to the Fault Mask register. 302 303 \param [in] faultMask Fault Mask value to set 304 */ 305 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) 306 { 307 __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); 308 } 309 310 #endif /* (__CORTEX_M >= 0x03U) */ 311 312 313 #if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) 314 315 /** \brief Get FPSCR 316 317 This function returns the current value of the Floating Point Status/Control register. 318 319 \return Floating Point Status/Control register value 320 */ 321 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) 322 { 323 #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) 324 uint32_t result; 325 326 /* Empty asm statement works as a scheduling barrier */ 327 __ASM volatile (""); 328 __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); 329 __ASM volatile (""); 330 return(result); 331 #else 332 return(0); 333 #endif 334 } 335 336 337 /** \brief Set FPSCR 338 339 This function assigns the given value to the Floating Point Status/Control register. 340 341 \param [in] fpscr Floating Point Status/Control value to set 342 */ 343 __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) 344 { 345 #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) 346 /* Empty asm statement works as a scheduling barrier */ 347 __ASM volatile (""); 348 // __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); // ARMCC_V6: needs to be checked 349 __ASM volatile (""); 350 #endif 351 } 352 353 #endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ 354 355 356 357 /*@} end of CMSIS_Core_RegAccFunctions */ 358 359 360 /* ########################## Core Instruction Access ######################### */ 361 /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 362 Access to dedicated instructions 363 @{ 364 */ 365 366 /* Define macros for porting to both thumb1 and thumb2. 367 * For thumb1, use low register (r0-r7), specified by constrant "l" 368 * Otherwise, use general registers, specified by constrant "r" */ 369 #if defined (__thumb__) && !defined (__thumb2__) 370 #define __CMSIS_GCC_OUT_REG(r) "=l" (r) 371 #define __CMSIS_GCC_USE_REG(r) "l" (r) 372 #else 373 #define __CMSIS_GCC_OUT_REG(r) "=r" (r) 374 #define __CMSIS_GCC_USE_REG(r) "r" (r) 375 #endif 376 377 /** \brief No Operation 378 379 No Operation does nothing. This instruction can be used for code alignment purposes. 380 */ 381 __attribute__((always_inline)) __STATIC_INLINE void __NOP(void) 382 { 383 __ASM volatile ("nop"); 384 } 385 386 387 /** \brief Wait For Interrupt 388 389 Wait For Interrupt is a hint instruction that suspends execution 390 until one of a number of events occurs. 391 */ 392 __attribute__((always_inline)) __STATIC_INLINE void __WFI(void) 393 { 394 __ASM volatile ("wfi"); 395 } 396 397 398 /** \brief Wait For Event 399 400 Wait For Event is a hint instruction that permits the processor to enter 401 a low-power state until one of a number of events occurs. 402 */ 403 __attribute__((always_inline)) __STATIC_INLINE void __WFE(void) 404 { 405 __ASM volatile ("wfe"); 406 } 407 408 409 /** \brief Send Event 410 411 Send Event is a hint instruction. It causes an event to be signaled to the CPU. 412 */ 413 __attribute__((always_inline)) __STATIC_INLINE void __SEV(void) 414 { 415 __ASM volatile ("sev"); 416 } 417 418 419 /** \brief Instruction Synchronization Barrier 420 421 Instruction Synchronization Barrier flushes the pipeline in the processor, 422 so that all instructions following the ISB are fetched from cache or 423 memory, after the instruction has been completed. 424 */ 425 __attribute__((always_inline)) __STATIC_INLINE void __ISB(void) 426 { 427 __ASM volatile ("isb 0xF":::"memory"); 428 } 429 430 431 /** \brief Data Synchronization Barrier 432 433 This function acts as a special kind of Data Memory Barrier. 434 It completes when all explicit memory accesses before this instruction complete. 435 */ 436 __attribute__((always_inline)) __STATIC_INLINE void __DSB(void) 437 { 438 __ASM volatile ("dsb 0xF":::"memory"); 439 } 440 441 442 /** \brief Data Memory Barrier 443 444 This function ensures the apparent order of the explicit memory operations before 445 and after the instruction, without ensuring their completion. 446 */ 447 __attribute__((always_inline)) __STATIC_INLINE void __DMB(void) 448 { 449 __ASM volatile ("dmb 0xF":::"memory"); 450 } 451 452 453 /** \brief Reverse byte order (32 bit) 454 455 This function reverses the byte order in integer value. 456 457 \param [in] value Value to reverse 458 \return Reversed value 459 */ 460 __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) 461 { 462 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 463 return __builtin_bswap32(value); 464 #else 465 uint32_t result; 466 467 __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 468 return(result); 469 #endif 470 } 471 472 473 /** \brief Reverse byte order (16 bit) 474 475 This function reverses the byte order in two unsigned short values. 476 477 \param [in] value Value to reverse 478 \return Reversed value 479 */ 480 __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) 481 { 482 uint32_t result; 483 484 __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 485 return(result); 486 } 487 488 489 /** \brief Reverse byte order in signed short value 490 491 This function reverses the byte order in a signed short value with sign extension to integer. 492 493 \param [in] value Value to reverse 494 \return Reversed value 495 */ 496 __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) 497 { 498 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 499 return (short)__builtin_bswap16(value); 500 #else 501 int32_t result; 502 503 __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 504 return(result); 505 #endif 506 } 507 508 509 /** \brief Rotate Right in unsigned value (32 bit) 510 511 This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 512 513 \param [in] value Value to rotate 514 \param [in] value Number of Bits to rotate 515 \return Rotated value 516 */ 517 __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) 518 { 519 return (op1 >> op2) | (op1 << (32U - op2)); 520 } 521 522 523 /** \brief Breakpoint 524 525 This function causes the processor to enter Debug state. 526 Debug tools can use this to investigate system state when the instruction at a particular address is reached. 527 528 \param [in] value is ignored by the processor. 529 If required, a debugger can use it to store additional information about the breakpoint. 530 */ 531 #define __BKPT(value) __ASM volatile ("bkpt "#value) 532 533 534 /** \brief Reverse bit order of value 535 536 This function reverses the bit order of the given value. 537 538 \param [in] value Value to reverse 539 \return Reversed value 540 */ 541 __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) 542 { 543 uint32_t result; 544 545 #if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) 546 __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); 547 #else 548 int32_t s = 4 /*sizeof(v)*/ * 8 - 1; // extra shift needed at end 549 550 result = value; // r will be reversed bits of v; first get LSB of v 551 for (value >>= 1U; value; value >>= 1U) 552 { 553 result <<= 1U; 554 result |= value & 1U; 555 s--; 556 } 557 result <<= s; // shift when v's highest bits are zero 558 #endif 559 return(result); 560 } 561 562 563 /** \brief Count leading zeros 564 565 This function counts the number of leading zeros of a data value. 566 567 \param [in] value Value to count the leading zeros 568 \return number of leading zeros in value 569 */ 570 #define __CLZ __builtin_clz 571 572 573 #if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) 574 575 /** \brief LDR Exclusive (8 bit) 576 577 This function executes a exclusive LDR instruction for 8 bit value. 578 579 \param [in] ptr Pointer to data 580 \return value of type uint8_t at (*ptr) 581 */ 582 __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) 583 { 584 uint32_t result; 585 586 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 587 __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); 588 #else 589 /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 590 accepted by assembler. So has to use following less efficient pattern. 591 */ 592 __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 593 #endif 594 return ((uint8_t) result); /* Add explicit type cast here */ 595 } 596 597 598 /** \brief LDR Exclusive (16 bit) 599 600 This function executes a exclusive LDR instruction for 16 bit values. 601 602 \param [in] ptr Pointer to data 603 \return value of type uint16_t at (*ptr) 604 */ 605 __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) 606 { 607 uint32_t result; 608 609 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 610 __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); 611 #else 612 /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 613 accepted by assembler. So has to use following less efficient pattern. 614 */ 615 __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 616 #endif 617 return ((uint16_t) result); /* Add explicit type cast here */ 618 } 619 620 621 /** \brief LDR Exclusive (32 bit) 622 623 This function executes a exclusive LDR instruction for 32 bit values. 624 625 \param [in] ptr Pointer to data 626 \return value of type uint32_t at (*ptr) 627 */ 628 __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) 629 { 630 uint32_t result; 631 632 __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); 633 return(result); 634 } 635 636 637 /** \brief STR Exclusive (8 bit) 638 639 This function executes a exclusive STR instruction for 8 bit values. 640 641 \param [in] value Value to store 642 \param [in] ptr Pointer to location 643 \return 0 Function succeeded 644 \return 1 Function failed 645 */ 646 __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) 647 { 648 uint32_t result; 649 650 __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 651 return(result); 652 } 653 654 655 /** \brief STR Exclusive (16 bit) 656 657 This function executes a exclusive STR instruction for 16 bit values. 658 659 \param [in] value Value to store 660 \param [in] ptr Pointer to location 661 \return 0 Function succeeded 662 \return 1 Function failed 663 */ 664 __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) 665 { 666 uint32_t result; 667 668 __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); 669 return(result); 670 } 671 672 673 /** \brief STR Exclusive (32 bit) 674 675 This function executes a exclusive STR instruction for 32 bit values. 676 677 \param [in] value Value to store 678 \param [in] ptr Pointer to location 679 \return 0 Function succeeded 680 \return 1 Function failed 681 */ 682 __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) 683 { 684 uint32_t result; 685 686 __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); 687 return(result); 688 } 689 690 691 /** \brief Remove the exclusive lock 692 693 This function removes the exclusive lock which is created by LDREX. 694 695 */ 696 __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) 697 { 698 __ASM volatile ("clrex" ::: "memory"); 699 } 700 701 702 /** \brief Signed Saturate 703 704 This function saturates a signed value. 705 706 \param [in] value Value to be saturated 707 \param [in] sat Bit position to saturate to (1..32) 708 \return Saturated value 709 */ 710 #define __SSAT(ARG1,ARG2) \ 711 ({ \ 712 uint32_t __RES, __ARG1 = (ARG1); \ 713 __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 714 __RES; \ 715 }) 716 717 718 /** \brief Unsigned Saturate 719 720 This function saturates an unsigned value. 721 722 \param [in] value Value to be saturated 723 \param [in] sat Bit position to saturate to (0..31) 724 \return Saturated value 725 */ 726 #define __USAT(ARG1,ARG2) \ 727 ({ \ 728 uint32_t __RES, __ARG1 = (ARG1); \ 729 __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 730 __RES; \ 731 }) 732 733 734 /** \brief Rotate Right with Extend (32 bit) 735 736 This function moves each bit of a bitstring right by one bit. 737 The carry input is shifted in at the left end of the bitstring. 738 739 \param [in] value Value to rotate 740 \return Rotated value 741 */ 742 __attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) 743 { 744 uint32_t result; 745 746 __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); 747 return(result); 748 } 749 750 751 /** \brief LDRT Unprivileged (8 bit) 752 753 This function executes a Unprivileged LDRT instruction for 8 bit value. 754 755 \param [in] ptr Pointer to data 756 \return value of type uint8_t at (*ptr) 757 */ 758 __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) 759 { 760 uint32_t result; 761 762 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 763 __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); 764 #else 765 /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 766 accepted by assembler. So has to use following less efficient pattern. 767 */ 768 __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 769 #endif 770 return ((uint8_t) result); /* Add explicit type cast here */ 771 } 772 773 774 /** \brief LDRT Unprivileged (16 bit) 775 776 This function executes a Unprivileged LDRT instruction for 16 bit values. 777 778 \param [in] ptr Pointer to data 779 \return value of type uint16_t at (*ptr) 780 */ 781 __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) 782 { 783 uint32_t result; 784 785 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) 786 __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); 787 #else 788 /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not 789 accepted by assembler. So has to use following less efficient pattern. 790 */ 791 __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); 792 #endif 793 return ((uint16_t) result); /* Add explicit type cast here */ 794 } 795 796 797 /** \brief LDRT Unprivileged (32 bit) 798 799 This function executes a Unprivileged LDRT instruction for 32 bit values. 800 801 \param [in] ptr Pointer to data 802 \return value of type uint32_t at (*ptr) 803 */ 804 __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) 805 { 806 uint32_t result; 807 808 __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); 809 return(result); 810 } 811 812 813 /** \brief STRT Unprivileged (8 bit) 814 815 This function executes a Unprivileged STRT instruction for 8 bit values. 816 817 \param [in] value Value to store 818 \param [in] ptr Pointer to location 819 */ 820 __attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) 821 { 822 __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); 823 } 824 825 826 /** \brief STRT Unprivileged (16 bit) 827 828 This function executes a Unprivileged STRT instruction for 16 bit values. 829 830 \param [in] value Value to store 831 \param [in] ptr Pointer to location 832 */ 833 __attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) 834 { 835 __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); 836 } 837 838 839 /** \brief STRT Unprivileged (32 bit) 840 841 This function executes a Unprivileged STRT instruction for 32 bit values. 842 843 \param [in] value Value to store 844 \param [in] ptr Pointer to location 845 */ 846 __attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) 847 { 848 __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); 849 } 850 851 #endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ 852 853 /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 854 855 856 /* ################### Compiler specific Intrinsics ########################### */ 857 /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics 858 Access to dedicated SIMD instructions 859 @{ 860 */ 861 862 #if (__CORTEX_M >= 0x04) /* only for Cortex-M4 and above */ 863 864 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) 865 { 866 uint32_t result; 867 868 __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 869 return(result); 870 } 871 872 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) 873 { 874 uint32_t result; 875 876 __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 877 return(result); 878 } 879 880 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) 881 { 882 uint32_t result; 883 884 __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 885 return(result); 886 } 887 888 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) 889 { 890 uint32_t result; 891 892 __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 893 return(result); 894 } 895 896 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) 897 { 898 uint32_t result; 899 900 __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 901 return(result); 902 } 903 904 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) 905 { 906 uint32_t result; 907 908 __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 909 return(result); 910 } 911 912 913 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) 914 { 915 uint32_t result; 916 917 __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 918 return(result); 919 } 920 921 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) 922 { 923 uint32_t result; 924 925 __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 926 return(result); 927 } 928 929 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) 930 { 931 uint32_t result; 932 933 __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 934 return(result); 935 } 936 937 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) 938 { 939 uint32_t result; 940 941 __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 942 return(result); 943 } 944 945 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) 946 { 947 uint32_t result; 948 949 __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 950 return(result); 951 } 952 953 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) 954 { 955 uint32_t result; 956 957 __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 958 return(result); 959 } 960 961 962 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) 963 { 964 uint32_t result; 965 966 __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 967 return(result); 968 } 969 970 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) 971 { 972 uint32_t result; 973 974 __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 975 return(result); 976 } 977 978 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) 979 { 980 uint32_t result; 981 982 __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 983 return(result); 984 } 985 986 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) 987 { 988 uint32_t result; 989 990 __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 991 return(result); 992 } 993 994 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) 995 { 996 uint32_t result; 997 998 __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 999 return(result); 1000 } 1001 1002 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) 1003 { 1004 uint32_t result; 1005 1006 __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1007 return(result); 1008 } 1009 1010 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) 1011 { 1012 uint32_t result; 1013 1014 __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1015 return(result); 1016 } 1017 1018 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) 1019 { 1020 uint32_t result; 1021 1022 __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1023 return(result); 1024 } 1025 1026 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) 1027 { 1028 uint32_t result; 1029 1030 __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1031 return(result); 1032 } 1033 1034 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) 1035 { 1036 uint32_t result; 1037 1038 __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1039 return(result); 1040 } 1041 1042 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) 1043 { 1044 uint32_t result; 1045 1046 __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1047 return(result); 1048 } 1049 1050 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) 1051 { 1052 uint32_t result; 1053 1054 __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1055 return(result); 1056 } 1057 1058 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) 1059 { 1060 uint32_t result; 1061 1062 __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1063 return(result); 1064 } 1065 1066 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) 1067 { 1068 uint32_t result; 1069 1070 __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1071 return(result); 1072 } 1073 1074 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) 1075 { 1076 uint32_t result; 1077 1078 __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1079 return(result); 1080 } 1081 1082 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) 1083 { 1084 uint32_t result; 1085 1086 __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1087 return(result); 1088 } 1089 1090 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) 1091 { 1092 uint32_t result; 1093 1094 __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1095 return(result); 1096 } 1097 1098 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) 1099 { 1100 uint32_t result; 1101 1102 __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1103 return(result); 1104 } 1105 1106 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) 1107 { 1108 uint32_t result; 1109 1110 __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1111 return(result); 1112 } 1113 1114 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) 1115 { 1116 uint32_t result; 1117 1118 __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1119 return(result); 1120 } 1121 1122 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) 1123 { 1124 uint32_t result; 1125 1126 __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1127 return(result); 1128 } 1129 1130 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) 1131 { 1132 uint32_t result; 1133 1134 __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1135 return(result); 1136 } 1137 1138 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) 1139 { 1140 uint32_t result; 1141 1142 __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1143 return(result); 1144 } 1145 1146 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) 1147 { 1148 uint32_t result; 1149 1150 __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1151 return(result); 1152 } 1153 1154 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) 1155 { 1156 uint32_t result; 1157 1158 __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1159 return(result); 1160 } 1161 1162 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) 1163 { 1164 uint32_t result; 1165 1166 __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1167 return(result); 1168 } 1169 1170 #define __SSAT16(ARG1,ARG2) \ 1171 ({ \ 1172 uint32_t __RES, __ARG1 = (ARG1); \ 1173 __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1174 __RES; \ 1175 }) 1176 1177 #define __USAT16(ARG1,ARG2) \ 1178 ({ \ 1179 uint32_t __RES, __ARG1 = (ARG1); \ 1180 __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 1181 __RES; \ 1182 }) 1183 1184 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) 1185 { 1186 uint32_t result; 1187 1188 __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1189 return(result); 1190 } 1191 1192 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) 1193 { 1194 uint32_t result; 1195 1196 __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1197 return(result); 1198 } 1199 1200 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) 1201 { 1202 uint32_t result; 1203 1204 __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); 1205 return(result); 1206 } 1207 1208 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) 1209 { 1210 uint32_t result; 1211 1212 __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1213 return(result); 1214 } 1215 1216 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) 1217 { 1218 uint32_t result; 1219 1220 __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1221 return(result); 1222 } 1223 1224 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) 1225 { 1226 uint32_t result; 1227 1228 __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1229 return(result); 1230 } 1231 1232 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) 1233 { 1234 uint32_t result; 1235 1236 __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1237 return(result); 1238 } 1239 1240 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) 1241 { 1242 uint32_t result; 1243 1244 __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1245 return(result); 1246 } 1247 1248 __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) 1249 { 1250 union llreg_u{ 1251 uint32_t w32[2]; 1252 uint64_t w64; 1253 } llr; 1254 llr.w64 = acc; 1255 1256 #ifndef __ARMEB__ // Little endian 1257 __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1258 #else // Big endian 1259 __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 1260 #endif 1261 1262 return(llr.w64); 1263 } 1264 1265 __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) 1266 { 1267 union llreg_u{ 1268 uint32_t w32[2]; 1269 uint64_t w64; 1270 } llr; 1271 llr.w64 = acc; 1272 1273 #ifndef __ARMEB__ // Little endian 1274 __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1275 #else // Big endian 1276 __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 1277 #endif 1278 1279 return(llr.w64); 1280 } 1281 1282 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) 1283 { 1284 uint32_t result; 1285 1286 __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1287 return(result); 1288 } 1289 1290 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) 1291 { 1292 uint32_t result; 1293 1294 __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1295 return(result); 1296 } 1297 1298 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) 1299 { 1300 uint32_t result; 1301 1302 __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1303 return(result); 1304 } 1305 1306 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) 1307 { 1308 uint32_t result; 1309 1310 __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); 1311 return(result); 1312 } 1313 1314 __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) 1315 { 1316 union llreg_u{ 1317 uint32_t w32[2]; 1318 uint64_t w64; 1319 } llr; 1320 llr.w64 = acc; 1321 1322 #ifndef __ARMEB__ // Little endian 1323 __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1324 #else // Big endian 1325 __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 1326 #endif 1327 1328 return(llr.w64); 1329 } 1330 1331 __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) 1332 { 1333 union llreg_u{ 1334 uint32_t w32[2]; 1335 uint64_t w64; 1336 } llr; 1337 llr.w64 = acc; 1338 1339 #ifndef __ARMEB__ // Little endian 1340 __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); 1341 #else // Big endian 1342 __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); 1343 #endif 1344 1345 return(llr.w64); 1346 } 1347 1348 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) 1349 { 1350 uint32_t result; 1351 1352 __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1353 return(result); 1354 } 1355 1356 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) 1357 { 1358 uint32_t result; 1359 1360 __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1361 return(result); 1362 } 1363 1364 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) 1365 { 1366 uint32_t result; 1367 1368 __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); 1369 return(result); 1370 } 1371 1372 #define __PKHBT(ARG1,ARG2,ARG3) \ 1373 ({ \ 1374 uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 1375 __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 1376 __RES; \ 1377 }) 1378 1379 #define __PKHTB(ARG1,ARG2,ARG3) \ 1380 ({ \ 1381 uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ 1382 if (ARG3 == 0) \ 1383 __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ 1384 else \ 1385 __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ 1386 __RES; \ 1387 }) 1388 1389 __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) 1390 { 1391 int32_t result; 1392 1393 __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); 1394 return(result); 1395 } 1396 1397 #endif /* (__CORTEX_M >= 0x04) */ 1398 /*@} end of group CMSIS_SIMD_intrinsics */ 1399 1400 1401 #endif /* __CMSIS_GCC_H */ 1402