Subversion Repositories DashDisplay

Rev

Details | Last modification | View Log | RSS feed

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