1 /*
2  * Copyright (C) 2017-2019 Alibaba Group Holding Limited
3  */
4 
5 
6 /******************************************************************************
7  * @file     csi_rv64_gcc.h
8  * @brief    CSI Header File for GCC.
9  * @version  V1.0
10  * @date     01. Sep 2018
11  ******************************************************************************/
12 
13 #ifndef _CSI_RV32_GCC_H_
14 #define _CSI_RV32_GCC_H_
15 
16 #include <stdlib.h>
17 
18 #ifndef __ASM
19 #define __ASM                   __asm     /*!< asm keyword for GNU Compiler */
20 #endif
21 
22 #ifndef __INLINE
23 #define __INLINE                inline    /*!< inline keyword for GNU Compiler */
24 #endif
25 
26 #ifndef __ALWAYS_STATIC_INLINE
27 #define __ALWAYS_STATIC_INLINE  __attribute__((always_inline)) static inline
28 #endif
29 
30 #ifndef __STATIC_INLINE
31 #define __STATIC_INLINE         static inline
32 #endif
33 
34 /* ###########################  Core Function Access  ########################### */
35 /** \ingroup  CSI_Core_FunctionInterface
36     \defgroup CSI_Core_RegAccFunctions CSI Core Register Access Functions
37   @{
38  */
39 /**
40   \brief   Enable IRQ Interrupts
41   \details Enables IRQ interrupts by setting the IE-bit in the PSR.
42            Can only be executed in Privileged modes.
43  */
__enable_irq(void)44 __ALWAYS_STATIC_INLINE void __enable_irq(void)
45 {
46     __ASM volatile("csrs mstatus, 8");
47 }
48 
49 /**
50   \brief   Disable IRQ Interrupts
51   \details Disables IRQ interrupts by clearing the IE-bit in the PSR.
52   Can only be executed in Privileged modes.
53  */
__disable_irq(void)54 __ALWAYS_STATIC_INLINE void __disable_irq(void)
55 {
56     __ASM volatile("csrc mstatus, 8");
57 }
58 
59 /**
60   \brief   Get MXSTATUS
61   \details Returns the content of the MXSTATUS Register.
62   \return               MXSTATUS Register value
63  */
__get_MXSTATUS(void)64 __ALWAYS_STATIC_INLINE uint64_t __get_MXSTATUS(void)
65 {
66     uint64_t result;
67 
68     __ASM volatile("csrr %0, mxstatus" : "=r"(result));
69     return (result);
70 }
71 
72 
73 
74 /**
75   \brief   Set MEPC
76   \details Writes the given value to the MEPC Register.
77   \param [in]    mstatus  MEPC Register value to set
78  */
__set_MEPC(uint64_t mepc)79 __ALWAYS_STATIC_INLINE void __set_MEPC(uint64_t mepc)
80 {
81     __ASM volatile("csrw mepc, %0" : : "r"(mepc));
82 }
83 
84 
85 /**
86   \brief   Set MXSTATUS
87   \details Writes the given value to the MXSTATUS Register.
88   \param [in]    mxstatus  MXSTATUS Register value to set
89  */
__set_MXSTATUS(uint64_t mxstatus)90 __ALWAYS_STATIC_INLINE void __set_MXSTATUS(uint64_t mxstatus)
91 {
92     __ASM volatile("csrw mxstatus, %0" : : "r"(mxstatus));
93 }
94 
95 /**
96   \brief   Get MSTATUS
97   \details Returns the content of the MSTATUS Register.
98   \return               MSTATUS Register value
99  */
__get_MSTATUS(void)100 __ALWAYS_STATIC_INLINE uint64_t __get_MSTATUS(void)
101 {
102     uint64_t result;
103 
104     __ASM volatile("csrr %0, mstatus" : "=r"(result));
105     return (result);
106 }
107 
108 /**
109   \brief   Set MSTATUS
110   \details Writes the given value to the MSTATUS Register.
111   \param [in]    mstatus  MSTATUS Register value to set
112  */
__set_MSTATUS(uint64_t mstatus)113 __ALWAYS_STATIC_INLINE void __set_MSTATUS(uint64_t mstatus)
114 {
115     __ASM volatile("csrw mstatus, %0" : : "r"(mstatus));
116 }
117 
118 /**
119   \brief   Get MHCR
120   \details Returns the content of the MHCR Register.
121   \return               MHCR Register value
122  */
__get_MHCR(void)123 __ALWAYS_STATIC_INLINE uint64_t __get_MHCR(void)
124 {
125     uint64_t result;
126 
127     __ASM volatile("csrr %0, mhcr" : "=r"(result));
128     return (result);
129 }
130 
131 /**
132   \brief   Set MHCR
133   \details Writes the given value to the MHCR Register.
134   \param [in]    mstatus  MHCR Register value to set
135  */
__set_MHCR(uint64_t mhcr)136 __ALWAYS_STATIC_INLINE void __set_MHCR(uint64_t mhcr)
137 {
138     __ASM volatile("csrw mhcr, %0" : : "r"(mhcr));
139 }
140 
141 /**
142   \brief   Get MISA Register
143   \details Returns the content of the MISA Register.
144   \return               MISA Register value
145  */
__get_MISA(void)146 __ALWAYS_STATIC_INLINE uint64_t __get_MISA(void)
147 {
148     uint64_t result;
149 
150     __ASM volatile("csrr %0, misa" : "=r"(result));
151     return (result);
152 }
153 
154 /**
155   \brief   Set MISA
156   \details Writes the given value to the MISA Register.
157   \param [in]    misa  MISA Register value to set
158  */
__set_MISA(uint64_t misa)159 __ALWAYS_STATIC_INLINE void __set_MISA(uint64_t misa)
160 {
161     __ASM volatile("csrw misa, %0" : : "r"(misa));
162 }
163 
164 /**
165   \brief   Get MIE Register
166   \details Returns the content of the MIE Register.
167   \return               MIE Register value
168  */
__get_MIE(void)169 __ALWAYS_STATIC_INLINE uint64_t __get_MIE(void)
170 {
171     uint64_t result;
172 
173     __ASM volatile("csrr %0, mie" : "=r"(result));
174     return (result);
175 }
176 
177 /**
178   \brief   Set MIE
179   \details Writes the given value to the MIE Register.
180   \param [in]    mie  MIE Register value to set
181  */
__set_MIE(uint64_t mie)182 __ALWAYS_STATIC_INLINE void __set_MIE(uint64_t mie)
183 {
184     __ASM volatile("csrw mie, %0" : : "r"(mie));
185 }
186 
187 /**
188   \brief   Get MTVEC Register
189   \details Returns the content of the MTVEC Register.
190   \return               MTVEC Register value
191  */
__get_MTVEC(void)192 __ALWAYS_STATIC_INLINE uint64_t __get_MTVEC(void)
193 {
194     uint64_t result;
195 
196     __ASM volatile("csrr %0, mtvec" : "=r"(result));
197     return (result);
198 }
199 
200 /**
201   \brief   Set MTVEC
202   \details Writes the given value to the MTVEC Register.
203   \param [in]    mtvec  MTVEC Register value to set
204  */
__set_MTVEC(uint64_t mtvec)205 __ALWAYS_STATIC_INLINE void __set_MTVEC(uint64_t mtvec)
206 {
207     __ASM volatile("csrw mtvec, %0" : : "r"(mtvec));
208 }
209 
210 /**
211   \brief   Set MTVT
212   \details Writes the given value to the MTVT Register.
213   \param [in]    mtvt  MTVT Register value to set
214  */
__set_MTVT(uint64_t mtvt)215 __ALWAYS_STATIC_INLINE void __set_MTVT(uint64_t mtvt)
216 {
217     __ASM volatile("csrw mtvt, %0" : : "r"(mtvt));
218 }
219 
220 /**
221   \brief   Get MTVT Register
222   \details Returns the content of the MTVT Register.
223   \return               MTVT Register value
224  */
__get_MTVT(void)225 __ALWAYS_STATIC_INLINE uint64_t __get_MTVT(void)
226 {
227     uint64_t result;
228 
229     __ASM volatile("csrr %0, mtvt" : "=r"(result));
230     return (result);
231 }
232 
233 /**
234   \brief   Get SP
235   \details Returns the content of the SP Register.
236   \return               SP Register value
237  */
__get_SP(void)238 __ALWAYS_STATIC_INLINE uint64_t __get_SP(void)
239 {
240     uint64_t result;
241 
242     __ASM volatile("mv %0, sp" : "=r"(result));
243     return (result);
244 }
245 
246 /**
247   \brief   Set SP
248   \details Writes the given value to the SP Register.
249   \param [in]    sp  SP Register value to set
250  */
__set_SP(uint64_t sp)251 __ALWAYS_STATIC_INLINE void __set_SP(uint64_t sp)
252 {
253     __ASM volatile("mv sp, %0" : : "r"(sp): "sp");
254 }
255 
256 /**
257   \brief   Get MSCRATCH Register
258   \details Returns the content of the MSCRATCH Register.
259   \return               MSCRATCH Register value
260  */
__get_MSCRATCH(void)261 __ALWAYS_STATIC_INLINE uint64_t __get_MSCRATCH(void)
262 {
263     uint64_t result;
264 
265     __ASM volatile("csrr %0, mscratch" : "=r"(result));
266     return (result);
267 }
268 
269 /**
270   \brief   Set MSCRATCH
271   \details Writes the given value to the MSCRATCH Register.
272   \param [in]    mscratch  MSCRATCH Register value to set
273  */
__set_MSCRATCH(uint64_t mscratch)274 __ALWAYS_STATIC_INLINE void __set_MSCRATCH(uint64_t mscratch)
275 {
276     __ASM volatile("csrw mscratch, %0" : : "r"(mscratch));
277 }
278 
279 /**
280   \brief   Get MCAUSE Register
281   \details Returns the content of the MCAUSE Register.
282   \return               MCAUSE Register value
283  */
__get_MCAUSE(void)284 __ALWAYS_STATIC_INLINE uint64_t __get_MCAUSE(void)
285 {
286     uint64_t result;
287 
288     __ASM volatile("csrr %0, mcause" : "=r"(result));
289     return (result);
290 }
291 
292 /**
293   \brief   Get MNXTI Register
294   \details Returns the content of the MNXTI Register.
295   \return               MNXTI Register value
296  */
__get_MNXTI(void)297 __ALWAYS_STATIC_INLINE uint64_t __get_MNXTI(void)
298 {
299     uint64_t result;
300 
301     __ASM volatile("csrr %0, mnxti" : "=r"(result));
302     return (result);
303 }
304 
305 /**
306   \brief   Set MNXTI
307   \details Writes the given value to the MNXTI Register.
308   \param [in]    mnxti  MNXTI Register value to set
309  */
__set_MNXTI(uint64_t mnxti)310 __ALWAYS_STATIC_INLINE void __set_MNXTI(uint64_t mnxti)
311 {
312     __ASM volatile("csrw mnxti, %0" : : "r"(mnxti));
313 }
314 
315 /**
316   \brief   Get MINTSTATUS Register
317   \details Returns the content of the MINTSTATUS Register.
318   \return               MINTSTATUS Register value
319  */
__get_MINTSTATUS(void)320 __ALWAYS_STATIC_INLINE uint64_t __get_MINTSTATUS(void)
321 {
322     uint64_t result;
323 
324     __ASM volatile("csrr %0, mintstatus" : "=r"(result));
325     return (result);
326 }
327 
328 /**
329   \brief   Get MTVAL Register
330   \details Returns the content of the MTVAL Register.
331   \return               MTVAL Register value
332  */
__get_MTVAL(void)333 __ALWAYS_STATIC_INLINE uint64_t __get_MTVAL(void)
334 {
335     uint64_t result;
336 
337     __ASM volatile("csrr %0, mtval" : "=r"(result));
338     return (result);
339 }
340 
341 /**
342   \brief   Get MIP Register
343   \details Returns the content of the MIP Register.
344   \return               MIP Register value
345  */
__get_MIP(void)346 __ALWAYS_STATIC_INLINE uint64_t __get_MIP(void)
347 {
348     uint64_t result;
349 
350     __ASM volatile("csrr %0, mip" : "=r"(result));
351     return (result);
352 }
353 
354 /**
355   \brief   Set MIP
356   \details Writes the given value to the MIP Register.
357   \param [in]    mip  MIP Register value to set
358  */
__set_MIP(uint64_t mip)359 __ALWAYS_STATIC_INLINE void __set_MIP(uint64_t mip)
360 {
361     __ASM volatile("csrw mip, %0" : : "r"(mip));
362 }
363 
364 /**
365   \brief   Get MCYCLEL Register
366   \details Returns the content of the MCYCLEL Register.
367   \return               MCYCLE Register value
368  */
__get_MCYCLE(void)369 __ALWAYS_STATIC_INLINE uint64_t __get_MCYCLE(void)
370 {
371     uint64_t result;
372 
373     __ASM volatile("csrr %0, mcycle" : "=r"(result));
374     return (result);
375 }
376 
377 /**
378   \brief   Get MCYCLEH Register
379   \details Returns the content of the MCYCLEH Register.
380   \return               MCYCLEH Register value
381  */
__get_MCYCLEH(void)382 __ALWAYS_STATIC_INLINE uint64_t __get_MCYCLEH(void)
383 {
384     uint64_t result;
385 
386     __ASM volatile("csrr %0, mcycleh" : "=r"(result));
387     return (result);
388 }
389 
390 /**
391   \brief   Get MINSTRET Register
392   \details Returns the content of the MINSTRET Register.
393   \return               MINSTRET Register value
394  */
__get_MINSTRET(void)395 __ALWAYS_STATIC_INLINE uint64_t __get_MINSTRET(void)
396 {
397     uint64_t result;
398 
399     __ASM volatile("csrr %0, minstret" : "=r"(result));
400     return (result);
401 }
402 
403 /**
404   \brief   Get MINSTRETH Register
405   \details Returns the content of the MINSTRETH Register.
406   \return               MINSTRETH Register value
407  */
__get_MINSTRETH(void)408 __ALWAYS_STATIC_INLINE uint64_t __get_MINSTRETH(void)
409 {
410     uint64_t result;
411 
412     __ASM volatile("csrr %0, minstreth" : "=r"(result));
413     return (result);
414 }
415 
416 /**
417   \brief   Get MVENDORID Register
418   \details Returns the content of the MVENDROID Register.
419   \return               MVENDORID Register value
420  */
__get_MVENDORID(void)421 __ALWAYS_STATIC_INLINE uint64_t __get_MVENDORID(void)
422 {
423     uint64_t result;
424 
425     __ASM volatile("csrr %0, mvendorid" : "=r"(result));
426     return (result);
427 }
428 
429 /**
430   \brief   Get MARCHID Register
431   \details Returns the content of the MARCHID Register.
432   \return               MARCHID Register value
433  */
__get_MARCHID(void)434 __ALWAYS_STATIC_INLINE uint64_t __get_MARCHID(void)
435 {
436     uint64_t result;
437 
438     __ASM volatile("csrr %0, marchid" : "=r"(result));
439     return (result);
440 }
441 
442 /**
443   \brief   Get MIMPID Register
444   \details Returns the content of the MIMPID Register.
445   \return               MIMPID Register value
446  */
__get_MIMPID(void)447 __ALWAYS_STATIC_INLINE uint64_t __get_MIMPID(void)
448 {
449     uint64_t result;
450 
451     __ASM volatile("csrr %0, mimpid" : "=r"(result));
452     return (result);
453 }
454 
455 /**
456   \brief   Get MHARTID Register
457   \details Returns the content of the MHARTID Register.
458   \return               MHARTID Register value
459  */
__get_MHARTID(void)460 __ALWAYS_STATIC_INLINE uint64_t __get_MHARTID(void)
461 {
462     uint64_t result;
463 
464     __ASM volatile("csrr %0, mhartid" : "=r"(result));
465     return (result);
466 }
467 
468 /**
469   \brief   Get PMPCFGx Register
470   \details Returns the content of the PMPCFGx Register.
471   \return               PMPCFGx Register value
472  */
__get_PMPCFG0(void)473 __ALWAYS_STATIC_INLINE uint64_t __get_PMPCFG0(void)
474 {
475     uint64_t result;
476 
477     __ASM volatile("csrr %0, pmpcfg0" : "=r"(result));
478     return (result);
479 }
480 
__get_PMPCFG1(void)481 __ALWAYS_STATIC_INLINE uint64_t __get_PMPCFG1(void)
482 {
483     uint64_t result;
484 
485     __ASM volatile("csrr %0, pmpcfg1" : "=r"(result));
486     return (result);
487 }
488 
__get_PMPCFG2(void)489 __ALWAYS_STATIC_INLINE uint64_t __get_PMPCFG2(void)
490 {
491     uint64_t result;
492 
493     __ASM volatile("csrr %0, pmpcfg2" : "=r"(result));
494     return (result);
495 }
496 
__get_PMPCFG3(void)497 __ALWAYS_STATIC_INLINE uint64_t __get_PMPCFG3(void)
498 {
499     uint64_t result;
500 
501     __ASM volatile("csrr %0, pmpcfg3" : "=r"(result));
502     return (result);
503 }
504 
505 /**
506   \brief   Get PMPxCFG Register by index
507   \details Returns the content of the PMPxCFG Register.
508   \param [in]    idx    PMP region index
509   \return               PMPxCFG Register value
510  */
__get_PMPxCFG(uint64_t idx)511 __STATIC_INLINE uint8_t __get_PMPxCFG(uint64_t idx)
512 {
513     uint64_t pmpcfgx = 0;
514 
515     if (idx < 4) {
516         pmpcfgx = __get_PMPCFG0();
517     } else if (idx >=4 && idx < 8) {
518         idx -= 4;
519         pmpcfgx = __get_PMPCFG1();
520     } else if (idx >=8 && idx < 12) {
521         idx -= 8;
522         pmpcfgx = __get_PMPCFG2();
523     } else if (idx >=12 && idx < 16) {
524         idx -= 12;
525         pmpcfgx = __get_PMPCFG3();
526     } else {
527         return 0;
528     }
529 
530     return (uint8_t)((pmpcfgx & (0xFF << (idx << 3))) >> (idx << 3));
531 }
532 
533 /**
534   \brief   Set PMPCFGx
535   \details Writes the given value to the PMPCFGx Register.
536   \param [in]    pmpcfg  PMPCFGx Register value to set
537  */
__set_PMPCFG0(uint64_t pmpcfg)538 __ALWAYS_STATIC_INLINE void __set_PMPCFG0(uint64_t pmpcfg)
539 {
540     __ASM volatile("csrw pmpcfg0, %0" : : "r"(pmpcfg));
541 }
542 
__set_PMPCFG1(uint64_t pmpcfg)543 __ALWAYS_STATIC_INLINE void __set_PMPCFG1(uint64_t pmpcfg)
544 {
545     __ASM volatile("csrw pmpcfg1, %0" : : "r"(pmpcfg));
546 }
547 
__set_PMPCFG2(uint64_t pmpcfg)548 __ALWAYS_STATIC_INLINE void __set_PMPCFG2(uint64_t pmpcfg)
549 {
550     __ASM volatile("csrw pmpcfg2, %0" : : "r"(pmpcfg));
551 }
552 
__set_PMPCFG3(uint64_t pmpcfg)553 __ALWAYS_STATIC_INLINE void __set_PMPCFG3(uint64_t pmpcfg)
554 {
555     __ASM volatile("csrw pmpcfg3, %0" : : "r"(pmpcfg));
556 }
557 
558 /**
559   \brief   Set PMPxCFG by index
560   \details Writes the given value to the PMPxCFG Register.
561   \param [in]    idx      PMPx region index
562   \param [in]    pmpxcfg  PMPxCFG Register value to set
563  */
__set_PMPxCFG(uint64_t idx,uint8_t pmpxcfg)564 __STATIC_INLINE void __set_PMPxCFG(uint64_t idx, uint8_t pmpxcfg)
565 {
566     uint64_t pmpcfgx = 0;
567 
568     if (idx < 4) {
569         pmpcfgx = __get_PMPCFG0();
570         pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3));
571         __set_PMPCFG0(pmpcfgx);
572     } else if (idx >=4 && idx < 8) {
573         idx -= 4;
574         pmpcfgx = __get_PMPCFG1();
575         pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3));
576         __set_PMPCFG1(pmpcfgx);
577     } else if (idx >=8 && idx < 12) {
578         idx -= 8;
579         pmpcfgx = __get_PMPCFG2();
580         pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3));
581         __set_PMPCFG2(pmpcfgx);
582     } else if (idx >=12 && idx < 16) {
583         idx -= 12;
584         pmpcfgx = __get_PMPCFG3();
585         pmpcfgx = (pmpcfgx & ~(0xFF << (idx << 3))) | (pmpxcfg << (idx << 3));
586         __set_PMPCFG3(pmpcfgx);
587     } else {
588         return;
589     }
590 }
591 
592 /**
593   \brief   Get PMPADDRx Register
594   \details Returns the content of the PMPADDRx Register.
595   \return               PMPADDRx Register value
596  */
__get_PMPADDR0(void)597 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR0(void)
598 {
599     uint64_t result;
600 
601     __ASM volatile("csrr %0, pmpaddr0" : "=r"(result));
602     return (result);
603 }
604 
__get_PMPADDR1(void)605 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR1(void)
606 {
607     uint64_t result;
608 
609     __ASM volatile("csrr %0, pmpaddr1" : "=r"(result));
610     return (result);
611 }
612 
__get_PMPADDR2(void)613 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR2(void)
614 {
615     uint64_t result;
616 
617     __ASM volatile("csrr %0, pmpaddr2" : "=r"(result));
618     return (result);
619 }
620 
__get_PMPADDR3(void)621 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR3(void)
622 {
623     uint64_t result;
624 
625     __ASM volatile("csrr %0, pmpaddr3" : "=r"(result));
626     return (result);
627 }
628 
__get_PMPADDR4(void)629 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR4(void)
630 {
631     uint64_t result;
632 
633     __ASM volatile("csrr %0, pmpaddr4" : "=r"(result));
634     return (result);
635 }
636 
__get_PMPADDR5(void)637 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR5(void)
638 {
639     uint64_t result;
640 
641     __ASM volatile("csrr %0, pmpaddr5" : "=r"(result));
642     return (result);
643 }
644 
__get_PMPADDR6(void)645 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR6(void)
646 {
647     uint64_t result;
648 
649     __ASM volatile("csrr %0, pmpaddr6" : "=r"(result));
650     return (result);
651 }
652 
__get_PMPADDR7(void)653 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR7(void)
654 {
655     uint64_t result;
656 
657     __ASM volatile("csrr %0, pmpaddr7" : "=r"(result));
658     return (result);
659 }
660 
__get_PMPADDR8(void)661 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR8(void)
662 {
663     uint64_t result;
664 
665     __ASM volatile("csrr %0, pmpaddr8" : "=r"(result));
666     return (result);
667 }
668 
__get_PMPADDR9(void)669 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR9(void)
670 {
671     uint64_t result;
672 
673     __ASM volatile("csrr %0, pmpaddr9" : "=r"(result));
674     return (result);
675 }
676 
__get_PMPADDR10(void)677 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR10(void)
678 {
679     uint64_t result;
680 
681     __ASM volatile("csrr %0, pmpaddr10" : "=r"(result));
682     return (result);
683 }
684 
__get_PMPADDR11(void)685 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR11(void)
686 {
687     uint64_t result;
688 
689     __ASM volatile("csrr %0, pmpaddr11" : "=r"(result));
690     return (result);
691 }
692 
__get_PMPADDR12(void)693 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR12(void)
694 {
695     uint64_t result;
696 
697     __ASM volatile("csrr %0, pmpaddr12" : "=r"(result));
698     return (result);
699 }
700 
__get_PMPADDR13(void)701 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR13(void)
702 {
703     uint64_t result;
704 
705     __ASM volatile("csrr %0, pmpaddr13" : "=r"(result));
706     return (result);
707 }
708 
__get_PMPADDR14(void)709 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR14(void)
710 {
711     uint64_t result;
712 
713     __ASM volatile("csrr %0, pmpaddr14" : "=r"(result));
714     return (result);
715 }
716 
__get_PMPADDR15(void)717 __ALWAYS_STATIC_INLINE uint64_t __get_PMPADDR15(void)
718 {
719     uint64_t result;
720 
721     __ASM volatile("csrr %0, pmpaddr15" : "=r"(result));
722     return (result);
723 }
724 
725 /**
726   \brief   Get PMPADDRx Register by index
727   \details Returns the content of the PMPADDRx Register.
728   \param [in]    idx    PMP region index
729   \return               PMPADDRx Register value
730  */
__get_PMPADDRx(uint64_t idx)731 __STATIC_INLINE uint64_t __get_PMPADDRx(uint64_t idx)
732 {
733     switch (idx) {
734     case 0: return __get_PMPADDR0();
735     case 1: return __get_PMPADDR1();
736     case 2: return __get_PMPADDR2();
737     case 3: return __get_PMPADDR3();
738     case 4: return __get_PMPADDR4();
739     case 5: return __get_PMPADDR5();
740     case 6: return __get_PMPADDR6();
741     case 7: return __get_PMPADDR7();
742     case 8: return __get_PMPADDR8();
743     case 9: return __get_PMPADDR9();
744     case 10: return __get_PMPADDR10();
745     case 11: return __get_PMPADDR11();
746     case 12: return __get_PMPADDR12();
747     case 13: return __get_PMPADDR13();
748     case 14: return __get_PMPADDR14();
749     case 15: return __get_PMPADDR15();
750     default: return 0;
751     }
752 }
753 
754 /**
755   \brief   Set PMPADDRx
756   \details Writes the given value to the PMPADDRx Register.
757   \param [in]    pmpaddr  PMPADDRx Register value to set
758  */
__set_PMPADDR0(uint64_t pmpaddr)759 __ALWAYS_STATIC_INLINE void __set_PMPADDR0(uint64_t pmpaddr)
760 {
761     __ASM volatile("csrw pmpaddr0, %0" : : "r"(pmpaddr));
762 }
763 
__set_PMPADDR1(uint64_t pmpaddr)764 __ALWAYS_STATIC_INLINE void __set_PMPADDR1(uint64_t pmpaddr)
765 {
766     __ASM volatile("csrw pmpaddr1, %0" : : "r"(pmpaddr));
767 }
768 
__set_PMPADDR2(uint64_t pmpaddr)769 __ALWAYS_STATIC_INLINE void __set_PMPADDR2(uint64_t pmpaddr)
770 {
771     __ASM volatile("csrw pmpaddr2, %0" : : "r"(pmpaddr));
772 }
773 
__set_PMPADDR3(uint64_t pmpaddr)774 __ALWAYS_STATIC_INLINE void __set_PMPADDR3(uint64_t pmpaddr)
775 {
776     __ASM volatile("csrw pmpaddr3, %0" : : "r"(pmpaddr));
777 }
778 
__set_PMPADDR4(uint64_t pmpaddr)779 __ALWAYS_STATIC_INLINE void __set_PMPADDR4(uint64_t pmpaddr)
780 {
781     __ASM volatile("csrw pmpaddr4, %0" : : "r"(pmpaddr));
782 }
783 
__set_PMPADDR5(uint64_t pmpaddr)784 __ALWAYS_STATIC_INLINE void __set_PMPADDR5(uint64_t pmpaddr)
785 {
786     __ASM volatile("csrw pmpaddr5, %0" : : "r"(pmpaddr));
787 }
788 
__set_PMPADDR6(uint64_t pmpaddr)789 __ALWAYS_STATIC_INLINE void __set_PMPADDR6(uint64_t pmpaddr)
790 {
791     __ASM volatile("csrw pmpaddr6, %0" : : "r"(pmpaddr));
792 }
793 
__set_PMPADDR7(uint64_t pmpaddr)794 __ALWAYS_STATIC_INLINE void __set_PMPADDR7(uint64_t pmpaddr)
795 {
796     __ASM volatile("csrw pmpaddr7, %0" : : "r"(pmpaddr));
797 }
798 
__set_PMPADDR8(uint64_t pmpaddr)799 __ALWAYS_STATIC_INLINE void __set_PMPADDR8(uint64_t pmpaddr)
800 {
801     __ASM volatile("csrw pmpaddr8, %0" : : "r"(pmpaddr));
802 }
803 
__set_PMPADDR9(uint64_t pmpaddr)804 __ALWAYS_STATIC_INLINE void __set_PMPADDR9(uint64_t pmpaddr)
805 {
806     __ASM volatile("csrw pmpaddr9, %0" : : "r"(pmpaddr));
807 }
808 
__set_PMPADDR10(uint64_t pmpaddr)809 __ALWAYS_STATIC_INLINE void __set_PMPADDR10(uint64_t pmpaddr)
810 {
811     __ASM volatile("csrw pmpaddr10, %0" : : "r"(pmpaddr));
812 }
813 
__set_PMPADDR11(uint64_t pmpaddr)814 __ALWAYS_STATIC_INLINE void __set_PMPADDR11(uint64_t pmpaddr)
815 {
816     __ASM volatile("csrw pmpaddr11, %0" : : "r"(pmpaddr));
817 }
818 
__set_PMPADDR12(uint64_t pmpaddr)819 __ALWAYS_STATIC_INLINE void __set_PMPADDR12(uint64_t pmpaddr)
820 {
821     __ASM volatile("csrw pmpaddr12, %0" : : "r"(pmpaddr));
822 }
823 
__set_PMPADDR13(uint64_t pmpaddr)824 __ALWAYS_STATIC_INLINE void __set_PMPADDR13(uint64_t pmpaddr)
825 {
826     __ASM volatile("csrw pmpaddr13, %0" : : "r"(pmpaddr));
827 }
828 
__set_PMPADDR14(uint64_t pmpaddr)829 __ALWAYS_STATIC_INLINE void __set_PMPADDR14(uint64_t pmpaddr)
830 {
831     __ASM volatile("csrw pmpaddr14, %0" : : "r"(pmpaddr));
832 }
833 
__set_PMPADDR15(uint64_t pmpaddr)834 __ALWAYS_STATIC_INLINE void __set_PMPADDR15(uint64_t pmpaddr)
835 {
836     __ASM volatile("csrw pmpaddr15, %0" : : "r"(pmpaddr));
837 }
838 
839 /**
840   \brief   Set PMPADDRx by index
841   \details Writes the given value to the PMPADDRx Register.
842   \param [in]    idx      PMP region index
843   \param [in]    pmpaddr  PMPADDRx Register value to set
844  */
__set_PMPADDRx(uint64_t idx,uint64_t pmpaddr)845 __STATIC_INLINE void __set_PMPADDRx(uint64_t idx, uint64_t pmpaddr)
846 {
847     switch (idx) {
848     case 0: __set_PMPADDR0(pmpaddr); break;
849     case 1: __set_PMPADDR1(pmpaddr); break;
850     case 2: __set_PMPADDR2(pmpaddr); break;
851     case 3: __set_PMPADDR3(pmpaddr); break;
852     case 4: __set_PMPADDR4(pmpaddr); break;
853     case 5: __set_PMPADDR5(pmpaddr); break;
854     case 6: __set_PMPADDR6(pmpaddr); break;
855     case 7: __set_PMPADDR7(pmpaddr); break;
856     case 8: __set_PMPADDR8(pmpaddr); break;
857     case 9: __set_PMPADDR9(pmpaddr); break;
858     case 10: __set_PMPADDR10(pmpaddr); break;
859     case 11: __set_PMPADDR11(pmpaddr); break;
860     case 12: __set_PMPADDR12(pmpaddr); break;
861     case 13: __set_PMPADDR13(pmpaddr); break;
862     case 14: __set_PMPADDR14(pmpaddr); break;
863     case 15: __set_PMPADDR15(pmpaddr); break;
864     default: return;
865     }
866 }
867 
868 /**
869   \brief   Enable interrupts and exceptions
870   \details Enables interrupts and exceptions by setting the IE-bit and EE-bit in the PSR.
871            Can only be executed in Privileged modes.
872  */
__enable_excp_irq(void)873 __ALWAYS_STATIC_INLINE void __enable_excp_irq(void)
874 {
875     __enable_irq();
876 }
877 
878 
879 /**
880   \brief   Disable interrupts and exceptions
881   \details Disables interrupts and exceptions by clearing the IE-bit and EE-bit in the PSR.
882            Can only be executed in Privileged modes.
883  */
__disable_excp_irq(void)884 __ALWAYS_STATIC_INLINE void __disable_excp_irq(void)
885 {
886     __disable_irq();
887 }
888 
889 #define __CSI_GCC_OUT_REG(r) "=r" (r)
890 #define __CSI_GCC_USE_REG(r) "r" (r)
891 
892 /**
893   \brief   No Operation
894   \details No Operation does nothing. This instruction can be used for code alignment purposes.
895  */
__NOP(void)896 __ALWAYS_STATIC_INLINE void __NOP(void)
897 {
898     __ASM volatile("nop");
899 }
900 
901 
902 /**
903   \brief   return from M-MODE
904   \details return from M-MODE.
905  */
__MRET(void)906 __ALWAYS_STATIC_INLINE void __MRET(void)
907 {
908     __ASM volatile("mret");
909 }
910 
911 /**
912   \brief   Wait For Interrupt
913   \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
914  */
__WFI(void)915 __ALWAYS_STATIC_INLINE void __WFI(void)
916 {
917     __ASM volatile("wfi");
918 }
919 
920 /**
921   \brief   Wait For Interrupt
922   \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
923  */
__WAIT(void)924 __ALWAYS_STATIC_INLINE void __WAIT(void)
925 {
926     __ASM volatile("wfi");
927 }
928 
929 /**
930   \brief   Doze For Interrupt
931   \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
932  */
__DOZE(void)933 __ALWAYS_STATIC_INLINE void __DOZE(void)
934 {
935     __ASM volatile("wfi");
936 }
937 
938 /**
939   \brief   Stop For Interrupt
940   \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
941  */
__STOP(void)942 __ALWAYS_STATIC_INLINE void __STOP(void)
943 {
944     __ASM volatile("wfi");
945 }
946 
947 /**
948   \brief   Instruction Synchronization Barrier
949   \details Instruction Synchronization Barrier flushes the pipeline in the processor,
950            so that all instructions following the ISB are fetched from cache or memory,
951            after the instruction has been completed.
952  */
__ISB(void)953 __ALWAYS_STATIC_INLINE void __ISB(void)
954 {
955     __ASM volatile("fence");
956 }
957 
958 
959 /**
960   \brief   Data Synchronization Barrier
961   \details Acts as a special kind of Data Memory Barrier.
962            It completes when all explicit memory accesses before this instruction complete.
963  */
__DSB(void)964 __ALWAYS_STATIC_INLINE void __DSB(void)
965 {
966     __ASM volatile("fence");
967 }
968 
969 /**
970   \brief   Invalid all icache
971   \details invalid all icache.
972  */
__ICACHE_IALL(void)973 __ALWAYS_STATIC_INLINE void __ICACHE_IALL(void)
974 {
975     __ASM volatile("icache.iall");
976 }
977 
978 /**
979   \brief   Invalid Icache by addr
980   \details Invalid Icache by addr.
981   \param [in] addr  operate addr
982  */
__ICACHE_IPA(uint64_t addr)983 __ALWAYS_STATIC_INLINE void __ICACHE_IPA(uint64_t addr)
984 {
985     __ASM volatile("icache.ipa %0" : : "r"(addr));
986 }
987 
988 /**
989   \brief   Invalid all dcache
990   \details invalid all dcache.
991  */
__DCACHE_IALL(void)992 __ALWAYS_STATIC_INLINE void __DCACHE_IALL(void)
993 {
994     __ASM volatile("dcache.iall");
995 }
996 
997 /**
998   \brief   Clear all dcache
999   \details clear all dcache.
1000  */
__DCACHE_CALL(void)1001 __ALWAYS_STATIC_INLINE void __DCACHE_CALL(void)
1002 {
1003     __ASM volatile("dcache.call");
1004 }
1005 
1006 /**
1007   \brief   Clear&invalid all dcache
1008   \details clear & invalid all dcache.
1009  */
__DCACHE_CIALL(void)1010 __ALWAYS_STATIC_INLINE void __DCACHE_CIALL(void)
1011 {
1012     __ASM volatile("dcache.ciall");
1013 }
1014 
1015 #if (__L2CACHE_PRESENT == 1U)
1016 /**
1017   \brief   Invalid L2 cache
1018   \details invalid L2 cache.
1019  */
__L2CACHE_IALL(void)1020 __ALWAYS_STATIC_INLINE void __L2CACHE_IALL(void)
1021 {
1022     __ASM volatile("l2cache.iall");
1023 }
1024 
1025 /**
1026   \brief   Clear L2cache
1027   \details clear L2cache.
1028  */
__L2CACHE_CALL(void)1029 __ALWAYS_STATIC_INLINE void __L2CACHE_CALL(void)
1030 {
1031     __ASM volatile("l2cache.call");
1032 }
1033 
1034 /**
1035   \brief   Clear&invalid L2cache
1036   \details clear & invalid L2cache.
1037  */
__L2CACHE_CIALL(void)1038 __ALWAYS_STATIC_INLINE void __L2CACHE_CIALL(void)
1039 {
1040     __ASM volatile("l2cache.ciall");
1041 }
1042 #endif
1043 
1044 
1045 /**
1046   \brief   Invalid Dcache by addr
1047   \details Invalid Dcache by addr.
1048   \param [in] addr  operate addr
1049  */
__DCACHE_IPA(uint64_t addr)1050 __ALWAYS_STATIC_INLINE void __DCACHE_IPA(uint64_t addr)
1051 {
1052     __ASM volatile("dcache.ipa %0" : : "r"(addr));
1053 }
1054 
1055 /**
1056   \brief   Clear Dcache by addr
1057   \details Clear Dcache by addr.
1058   \param [in] addr  operate addr
1059  */
__DCACHE_CPA(uint64_t addr)1060 __ALWAYS_STATIC_INLINE void __DCACHE_CPA(uint64_t addr)
1061 {
1062     __ASM volatile("dcache.cpa %0" : : "r"(addr));
1063 }
1064 
1065 /**
1066   \brief   Clear & Invalid Dcache by addr
1067   \details Clear & Invalid Dcache by addr.
1068   \param [in] addr  operate addr
1069  */
__DCACHE_CIPA(uint64_t addr)1070 __ALWAYS_STATIC_INLINE void __DCACHE_CIPA(uint64_t addr)
1071 {
1072     __ASM volatile("dcache.cipa %0" : : "r"(addr));
1073 }
1074 
1075 
1076 /**
1077   \brief   Data Memory Barrier
1078   \details Ensures the apparent order of the explicit memory operations before
1079            and after the instruction, without ensuring their completion.
1080  */
__DMB(void)1081 __ALWAYS_STATIC_INLINE void __DMB(void)
1082 {
1083     __ASM volatile("fence");
1084 }
1085 
1086 /**
1087   \brief   Reverse byte order (32 bit)
1088   \details Reverses the byte order in integer value.
1089   \param [in]    value  Value to reverse
1090   \return               Reversed value
1091  */
__REV(uint64_t value)1092 __ALWAYS_STATIC_INLINE uint64_t __REV(uint64_t value)
1093 {
1094     return __builtin_bswap32(value);
1095 }
1096 
1097 
1098 /**
1099   \brief   Reverse byte order (16 bit)
1100   \details Reverses the byte order in two unsigned short values.
1101   \param [in]    value  Value to reverse
1102   \return               Reversed value
1103  */
__REV16(uint32_t value)1104 __ALWAYS_STATIC_INLINE uint32_t __REV16(uint32_t value)
1105 {
1106     uint32_t result;
1107 
1108     result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) |
1109              ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8);
1110 
1111     return (result);
1112 }
1113 
1114 
1115 /**
1116   \brief   Reverse byte order in signed short value
1117   \details Reverses the byte order in a signed short value with sign extension to integer.
1118   \param [in]    value  Value to reverse
1119   \return               Reversed value
1120  */
__REVSH(int32_t value)1121 __ALWAYS_STATIC_INLINE int32_t __REVSH(int32_t value)
1122 {
1123     return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8));
1124 }
1125 
1126 
1127 /**
1128   \brief   Rotate Right in unsigned value (32 bit)
1129   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
1130   \param [in]    op1  Value to rotate
1131   \param [in]    op2  Number of Bits to rotate
1132   \return               Rotated value
1133  */
__ROR(uint32_t op1,uint32_t op2)1134 __ALWAYS_STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
1135 {
1136     return (op1 >> op2) | (op1 << (32U - op2));
1137 }
1138 
1139 
1140 /**
1141   \brief   Breakpoint
1142   \details Causes the processor to enter Debug state
1143            Debug tools can use this to investigate system state when the instruction at a particular address is reached.
1144  */
__BKPT(void)1145 __ALWAYS_STATIC_INLINE void __BKPT(void)
1146 {
1147     __ASM volatile("ebreak");
1148 }
1149 
1150 /**
1151   \brief   Reverse bit order of value
1152   \details Reverses the bit order of the given value.
1153   \param [in]    value  Value to reverse
1154   \return               Reversed value
1155  */
__RBIT(uint32_t value)1156 __ALWAYS_STATIC_INLINE uint32_t __RBIT(uint32_t value)
1157 {
1158     uint32_t result;
1159 
1160     int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
1161 
1162     result = value;                      /* r will be reversed bits of v; first get LSB of v */
1163 
1164     for (value >>= 1U; value; value >>= 1U) {
1165         result <<= 1U;
1166         result |= value & 1U;
1167         s--;
1168     }
1169 
1170     result <<= s;                        /* shift when v's highest bits are zero */
1171 
1172     return (result);
1173 }
1174 
1175 
1176 /**
1177   \brief   Count leading zeros
1178   \details Counts the number of leading zeros of a data value.
1179   \param [in]  value  Value to count the leading zeros
1180   \return             number of leading zeros in value
1181  */
1182 #define __CLZ             __builtin_clz
1183 /**
1184   \details This function saturates a signed value.
1185   \param [in]    x   Value to be saturated
1186   \param [in]    y   Bit position to saturate to [1..32]
1187   \return            Saturated value.
1188  */
__SSAT(int32_t x,uint32_t y)1189 __ALWAYS_STATIC_INLINE int32_t __SSAT(int32_t x, uint32_t y)
1190 {
1191     int32_t posMax, negMin;
1192     uint32_t i;
1193 
1194     posMax = 1;
1195 
1196     for (i = 0; i < (y - 1); i++) {
1197         posMax = posMax * 2;
1198     }
1199 
1200     if (x > 0) {
1201         posMax = (posMax - 1);
1202 
1203         if (x > posMax) {
1204             x = posMax;
1205         }
1206 
1207 //    x &= (posMax * 2 + 1);
1208     } else {
1209         negMin = -posMax;
1210 
1211         if (x < negMin) {
1212             x = negMin;
1213         }
1214 
1215 //    x &= (posMax * 2 - 1);
1216     }
1217 
1218     return (x);
1219 }
1220 
1221 /**
1222   \brief   Unsigned Saturate
1223   \details Saturates an unsigned value.
1224   \param [in]  value  Value to be saturated
1225   \param [in]    sat  Bit position to saturate to (0..31)
1226   \return             Saturated value
1227  */
__USAT(uint32_t value,uint32_t sat)1228 __ALWAYS_STATIC_INLINE uint32_t __USAT(uint32_t value, uint32_t sat)
1229 {
1230     uint32_t result;
1231 
1232     if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) {
1233         result = 0xFFFFFFFF >> (32 - sat);
1234     } else {
1235         result = value;
1236     }
1237 
1238     return (result);
1239 }
1240 
1241 /**
1242   \brief   Unsigned Saturate for internal use
1243   \details Saturates an unsigned value, should not call directly.
1244   \param [in]  value  Value to be saturated
1245   \param [in]    sat  Bit position to saturate to (0..31)
1246   \return             Saturated value
1247  */
__IUSAT(uint32_t value,uint32_t sat)1248 __ALWAYS_STATIC_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat)
1249 {
1250     uint32_t result;
1251 
1252     if (value & 0x80000000) { /* only overflow set bit-31 */
1253         result = 0;
1254     } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) {
1255         result = 0xFFFFFFFF >> (32 - sat);
1256     } else {
1257         result = value;
1258     }
1259 
1260     return (result);
1261 }
1262 
1263 /**
1264   \brief   Rotate Right with Extend
1265   \details This function moves each bit of a bitstring right by one bit.
1266            The carry input is shifted in at the left end of the bitstring.
1267   \note    carry input will always 0.
1268   \param [in]    op1  Value to rotate
1269   \return               Rotated value
1270  */
__RRX(uint32_t op1)1271 __ALWAYS_STATIC_INLINE uint32_t __RRX(uint32_t op1)
1272 {
1273     return 0;
1274 }
1275 
1276 /**
1277   \brief   LDRT Unprivileged (8 bit)
1278   \details Executes a Unprivileged LDRT instruction for 8 bit value.
1279   \param [in]    addr  Pointer to location
1280   \return             value of type uint8_t at (*ptr)
1281  */
__LDRBT(volatile uint8_t * addr)1282 __ALWAYS_STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr)
1283 {
1284     uint32_t result;
1285 
1286     __ASM volatile("lb %0, 0(%1)" : "=r"(result) : "r"(addr));
1287 
1288     return ((uint8_t) result);    /* Add explicit type cast here */
1289 }
1290 
1291 
1292 /**
1293   \brief   LDRT Unprivileged (16 bit)
1294   \details Executes a Unprivileged LDRT instruction for 16 bit values.
1295   \param [in]    addr  Pointer to location
1296   \return        value of type uint16_t at (*ptr)
1297  */
__LDRHT(volatile uint16_t * addr)1298 __ALWAYS_STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr)
1299 {
1300     uint32_t result;
1301 
1302     __ASM volatile("lh %0, 0(%1)" : "=r"(result) : "r"(addr));
1303 
1304     return ((uint16_t) result);    /* Add explicit type cast here */
1305 }
1306 
1307 
1308 /**
1309   \brief   LDRT Unprivileged (32 bit)
1310   \details Executes a Unprivileged LDRT instruction for 32 bit values.
1311   \param [in]    addr  Pointer to location
1312   \return        value of type uint32_t at (*ptr)
1313  */
__LDRT(volatile uint32_t * addr)1314 __ALWAYS_STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr)
1315 {
1316     uint32_t result;
1317 
1318     __ASM volatile("lw %0, 0(%1)" : "=r"(result) : "r"(addr));
1319 
1320     return (result);
1321 }
1322 
1323 
1324 /**
1325   \brief   STRT Unprivileged (8 bit)
1326   \details Executes a Unprivileged STRT instruction for 8 bit values.
1327   \param [in]  value  Value to store
1328   \param [in]    addr  Pointer to location
1329  */
__STRBT(uint8_t value,volatile uint8_t * addr)1330 __ALWAYS_STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr)
1331 {
1332     __ASM volatile("sb %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
1333 }
1334 
1335 
1336 /**
1337   \brief   STRT Unprivileged (16 bit)
1338   \details Executes a Unprivileged STRT instruction for 16 bit values.
1339   \param [in]  value  Value to store
1340   \param [in]    addr  Pointer to location
1341  */
__STRHT(uint16_t value,volatile uint16_t * addr)1342 __ALWAYS_STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr)
1343 {
1344     __ASM volatile("sh %1, 0(%0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
1345 }
1346 
1347 
1348 /**
1349   \brief   STRT Unprivileged (32 bit)
1350   \details Executes a Unprivileged STRT instruction for 32 bit values.
1351   \param [in]  value  Value to store
1352   \param [in]    addr  Pointer to location
1353  */
__STRT(uint32_t value,volatile uint32_t * addr)1354 __ALWAYS_STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr)
1355 {
1356     __ASM volatile("sw %1, 0(%0)" :: "r"(addr), "r"(value) : "memory");
1357 }
1358 
1359 /*@}*/ /* end of group CSI_Core_InstructionInterface */
1360 
1361 /* ###################  Compiler specific Intrinsics  ########################### */
1362 /** \defgroup CSI_SIMD_intrinsics CSI SIMD Intrinsics
1363   Access to dedicated SIMD instructions \n
1364   Single Instruction Multiple Data (SIMD) extensions are provided to simplify development of application software. SIMD extensions increase the processing capability without materially increasing the power consumption. The SIMD extensions are completely transparent to the operating system (OS), allowing existing OS ports to be used.
1365 
1366   @{
1367 */
1368 
1369 /**
1370   \brief   Halfword packing instruction. Combines bits[15:0] of val1 with bits[31:16]
1371            of val2 levitated with the val3.
1372   \details Combine a halfword from one register with a halfword from another register.
1373            The second argument can be left-shifted before extraction of the halfword.
1374   \param [in]    val1   first 16-bit operands
1375   \param [in]    val2   second 16-bit operands
1376   \param [in]    val3   value for left-shifting val2. Value range [0..31].
1377   \return               the combination of halfwords.
1378   \remark
1379                  res[15:0]  = val1[15:0]              \n
1380                  res[31:16] = val2[31:16] << val3
1381  */
__PKHBT(uint32_t val1,uint32_t val2,uint32_t val3)1382 __ALWAYS_STATIC_INLINE uint32_t __PKHBT(uint32_t val1, uint32_t val2, uint32_t val3)
1383 {
1384     return ((((int32_t)(val1) << 0) & (int32_t)0x0000FFFF) | (((int32_t)(val2) << val3) & (int32_t)0xFFFF0000));
1385 }
1386 
1387 /**
1388   \brief   Halfword packing instruction. Combines bits[31:16] of val1 with bits[15:0]
1389            of val2 right-shifted with the val3.
1390   \details Combine a halfword from one register with a halfword from another register.
1391            The second argument can be right-shifted before extraction of the halfword.
1392   \param [in]    val1   first 16-bit operands
1393   \param [in]    val2   second 16-bit operands
1394   \param [in]    val3   value for right-shifting val2. Value range [1..32].
1395   \return               the combination of halfwords.
1396   \remark
1397                  res[15:0]  = val2[15:0] >> val3        \n
1398                  res[31:16] = val1[31:16]
1399  */
__PKHTB(uint32_t val1,uint32_t val2,uint32_t val3)1400 __ALWAYS_STATIC_INLINE uint32_t __PKHTB(uint32_t val1, uint32_t val2, uint32_t val3)
1401 {
1402     return ((((int32_t)(val1) << 0) & (int32_t)0xFFFF0000) | (((int32_t)(val2) >> val3) & (int32_t)0x0000FFFF));
1403 }
1404 
1405 /**
1406   \brief   Dual 16-bit signed saturate.
1407   \details This function saturates a signed value.
1408   \param [in]    x   two signed 16-bit values to be saturated.
1409   \param [in]    y   bit position for saturation, an integral constant expression in the range 1 to 16.
1410   \return        the sum of the absolute differences of the following bytes, added to the accumulation value:\n
1411                  the signed saturation of the low halfword in val1, saturated to the bit position specified in
1412                  val2 and returned in the low halfword of the return value.\n
1413                  the signed saturation of the high halfword in val1, saturated to the bit position specified in
1414                  val2 and returned in the high halfword of the return value.
1415  */
__SSAT16(int32_t x,const uint32_t y)1416 __ALWAYS_STATIC_INLINE uint32_t __SSAT16(int32_t x, const uint32_t y)
1417 {
1418     int32_t r = 0, s = 0;
1419 
1420     r = __SSAT((((int32_t)x << 16) >> 16), y) & (int32_t)0x0000FFFF;
1421     s = __SSAT((((int32_t)x) >> 16), y) & (int32_t)0x0000FFFF;
1422 
1423     return ((uint32_t)((s << 16) | (r)));
1424 }
1425 
1426 /**
1427   \brief   Dual 16-bit unsigned saturate.
1428   \details This function enables you to saturate two signed 16-bit values to a selected unsigned range.
1429   \param [in]    x   two signed 16-bit values to be saturated.
1430   \param [in]    y   bit position for saturation, an integral constant expression in the range 1 to 16.
1431   \return        the saturation of the two signed 16-bit values, as non-negative values:
1432                  the saturation of the low halfword in val1, saturated to the bit position specified in
1433                  val2 and returned in the low halfword of the return value.\n
1434                  the saturation of the high halfword in val1, saturated to the bit position specified in
1435                  val2 and returned in the high halfword of the return value.
1436  */
__USAT16(uint32_t x,const uint32_t y)1437 __ALWAYS_STATIC_INLINE uint32_t __USAT16(uint32_t x, const uint32_t y)
1438 {
1439     int32_t r = 0, s = 0;
1440 
1441     r = __IUSAT(((x << 16) >> 16), y) & 0x0000FFFF;
1442     s = __IUSAT(((x) >> 16), y) & 0x0000FFFF;
1443 
1444     return ((s << 16) | (r));
1445 }
1446 
1447 /**
1448   \brief   Quad 8-bit saturating addition.
1449   \details This function enables you to perform four 8-bit integer additions,
1450            saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1.
1451   \param [in]    x   first four 8-bit summands.
1452   \param [in]    y   second four 8-bit summands.
1453   \return        the saturated addition of the first byte of each operand in the first byte of the return value.\n
1454                  the saturated addition of the second byte of each operand in the second byte of the return value.\n
1455                  the saturated addition of the third byte of each operand in the third byte of the return value.\n
1456                  the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n
1457                  The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1.
1458   \remark
1459                  res[7:0]   = val1[7:0]   + val2[7:0]        \n
1460                  res[15:8]  = val1[15:8]  + val2[15:8]       \n
1461                  res[23:16] = val1[23:16] + val2[23:16]      \n
1462                  res[31:24] = val1[31:24] + val2[31:24]
1463  */
__QADD8(uint32_t x,uint32_t y)1464 __ALWAYS_STATIC_INLINE uint32_t __QADD8(uint32_t x, uint32_t y)
1465 {
1466     int32_t r, s, t, u;
1467 
1468     r = __SSAT(((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF;
1469     s = __SSAT(((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF;
1470     t = __SSAT(((((int32_t)x <<  8) >> 24) + (((int32_t)y <<  8) >> 24)), 8) & (int32_t)0x000000FF;
1471     u = __SSAT(((((int32_t)x) >> 24) + (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF;
1472 
1473     return ((uint32_t)((u << 24) | (t << 16) | (s <<  8) | (r)));
1474 }
1475 
1476 /**
1477   \brief   Quad 8-bit unsigned saturating addition.
1478   \details This function enables you to perform four unsigned 8-bit integer additions,
1479            saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1.
1480   \param [in]    x   first four 8-bit summands.
1481   \param [in]    y   second four 8-bit summands.
1482   \return        the saturated addition of the first byte of each operand in the first byte of the return value.\n
1483                  the saturated addition of the second byte of each operand in the second byte of the return value.\n
1484                  the saturated addition of the third byte of each operand in the third byte of the return value.\n
1485                  the saturated addition of the fourth byte of each operand in the fourth byte of the return value.\n
1486                  The returned results are saturated to the 8-bit signed integer range 0 <= x <= 2^8 - 1.
1487   \remark
1488                  res[7:0]   = val1[7:0]   + val2[7:0]        \n
1489                  res[15:8]  = val1[15:8]  + val2[15:8]       \n
1490                  res[23:16] = val1[23:16] + val2[23:16]      \n
1491                  res[31:24] = val1[31:24] + val2[31:24]
1492  */
__UQADD8(uint32_t x,uint32_t y)1493 __ALWAYS_STATIC_INLINE uint32_t __UQADD8(uint32_t x, uint32_t y)
1494 {
1495     int32_t r, s, t, u;
1496 
1497     r = __IUSAT((((x << 24) >> 24) + ((y << 24) >> 24)), 8) & 0x000000FF;
1498     s = __IUSAT((((x << 16) >> 24) + ((y << 16) >> 24)), 8) & 0x000000FF;
1499     t = __IUSAT((((x <<  8) >> 24) + ((y <<  8) >> 24)), 8) & 0x000000FF;
1500     u = __IUSAT((((x) >> 24) + ((y) >> 24)), 8) & 0x000000FF;
1501 
1502     return ((u << 24) | (t << 16) | (s <<  8) | (r));
1503 }
1504 
1505 /**
1506   \brief   Quad 8-bit signed addition.
1507   \details This function performs four 8-bit signed integer additions.
1508   \param [in]    x  first four 8-bit summands.
1509   \param [in]    y  second four 8-bit summands.
1510   \return        the addition of the first bytes from each operand, in the first byte of the return value.\n
1511                  the addition of the second bytes of each operand, in the second byte of the return value.\n
1512                  the addition of the third bytes of each operand, in the third byte of the return value.\n
1513                  the addition of the fourth bytes of each operand, in the fourth byte of the return value.
1514   \remark
1515                  res[7:0]   = val1[7:0]   + val2[7:0]        \n
1516                  res[15:8]  = val1[15:8]  + val2[15:8]       \n
1517                  res[23:16] = val1[23:16] + val2[23:16]      \n
1518                  res[31:24] = val1[31:24] + val2[31:24]
1519  */
__SADD8(uint32_t x,uint32_t y)1520 __ALWAYS_STATIC_INLINE uint32_t __SADD8(uint32_t x, uint32_t y)
1521 {
1522     int32_t r, s, t, u;
1523 
1524     r = ((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF;
1525     s = ((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF;
1526     t = ((((int32_t)x <<  8) >> 24) + (((int32_t)y <<  8) >> 24)) & (int32_t)0x000000FF;
1527     u = ((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) & (int32_t)0x000000FF;
1528 
1529     return ((uint32_t)((u << 24) | (t << 16) | (s <<  8) | (r)));
1530 }
1531 
1532 /**
1533   \brief   Quad 8-bit unsigned addition.
1534   \details This function performs four unsigned 8-bit integer additions.
1535   \param [in]    x  first four 8-bit summands.
1536   \param [in]    y  second four 8-bit summands.
1537   \return        the addition of the first bytes from each operand, in the first byte of the return value.\n
1538                  the addition of the second bytes of each operand, in the second byte of the return value.\n
1539                  the addition of the third bytes of each operand, in the third byte of the return value.\n
1540                  the addition of the fourth bytes of each operand, in the fourth byte of the return value.
1541   \remark
1542                  res[7:0]   = val1[7:0]   + val2[7:0]        \n
1543                  res[15:8]  = val1[15:8]  + val2[15:8]       \n
1544                  res[23:16] = val1[23:16] + val2[23:16]      \n
1545                  res[31:24] = val1[31:24] + val2[31:24]
1546  */
__UADD8(uint32_t x,uint32_t y)1547 __ALWAYS_STATIC_INLINE uint32_t __UADD8(uint32_t x, uint32_t y)
1548 {
1549     int32_t r, s, t, u;
1550 
1551     r = (((x << 24) >> 24) + ((y << 24) >> 24)) & 0x000000FF;
1552     s = (((x << 16) >> 24) + ((y << 16) >> 24)) & 0x000000FF;
1553     t = (((x <<  8) >> 24) + ((y <<  8) >> 24)) & 0x000000FF;
1554     u = (((x) >> 24) + ((y) >> 24)) & 0x000000FF;
1555 
1556     return ((u << 24) | (t << 16) | (s <<  8) | (r));
1557 }
1558 
1559 /**
1560   \brief   Quad 8-bit saturating subtract.
1561   \details This function enables you to perform four 8-bit integer subtractions,
1562            saturating the results to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1.
1563   \param [in]    x   first four 8-bit summands.
1564   \param [in]    y   second four 8-bit summands.
1565   \return        the subtraction of the first byte of each operand in the first byte of the return value.\n
1566                  the subtraction of the second byte of each operand in the second byte of the return value.\n
1567                  the subtraction of the third byte of each operand in the third byte of the return value.\n
1568                  the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n
1569                  The returned results are saturated to the 8-bit signed integer range -2^7 <= x <= 2^7 - 1.
1570   \remark
1571                  res[7:0]   = val1[7:0]   - val2[7:0]        \n
1572                  res[15:8]  = val1[15:8]  - val2[15:8]       \n
1573                  res[23:16] = val1[23:16] - val2[23:16]      \n
1574                  res[31:24] = val1[31:24] - val2[31:24]
1575  */
__QSUB8(uint32_t x,uint32_t y)1576 __ALWAYS_STATIC_INLINE uint32_t __QSUB8(uint32_t x, uint32_t y)
1577 {
1578     int32_t r, s, t, u;
1579 
1580     r = __SSAT(((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF;
1581     s = __SSAT(((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF;
1582     t = __SSAT(((((int32_t)x <<  8) >> 24) - (((int32_t)y <<  8) >> 24)), 8) & (int32_t)0x000000FF;
1583     u = __SSAT(((((int32_t)x) >> 24) - (((int32_t)y) >> 24)), 8) & (int32_t)0x000000FF;
1584 
1585     return ((uint32_t)((u << 24) | (t << 16) | (s <<  8) | (r)));
1586 }
1587 
1588 /**
1589   \brief   Quad 8-bit unsigned saturating subtraction.
1590   \details This function enables you to perform four unsigned 8-bit integer subtractions,
1591            saturating the results to the 8-bit unsigned integer range 0 < x < 2^8 - 1.
1592   \param [in]    x   first four 8-bit summands.
1593   \param [in]    y   second four 8-bit summands.
1594   \return        the subtraction of the first byte of each operand in the first byte of the return value.\n
1595                  the subtraction of the second byte of each operand in the second byte of the return value.\n
1596                  the subtraction of the third byte of each operand in the third byte of the return value.\n
1597                  the subtraction of the fourth byte of each operand in the fourth byte of the return value.\n
1598                  The returned results are saturated to the 8-bit unsigned integer range 0 <= x <= 2^8 - 1.
1599   \remark
1600                  res[7:0]   = val1[7:0]   - val2[7:0]        \n
1601                  res[15:8]  = val1[15:8]  - val2[15:8]       \n
1602                  res[23:16] = val1[23:16] - val2[23:16]      \n
1603                  res[31:24] = val1[31:24] - val2[31:24]
1604  */
__UQSUB8(uint32_t x,uint32_t y)1605 __ALWAYS_STATIC_INLINE uint32_t __UQSUB8(uint32_t x, uint32_t y)
1606 {
1607     int32_t r, s, t, u;
1608 
1609     r = __IUSAT((((x << 24) >> 24) - ((y << 24) >> 24)), 8) & 0x000000FF;
1610     s = __IUSAT((((x << 16) >> 24) - ((y << 16) >> 24)), 8) & 0x000000FF;
1611     t = __IUSAT((((x <<  8) >> 24) - ((y <<  8) >> 24)), 8) & 0x000000FF;
1612     u = __IUSAT((((x) >> 24) - ((y) >> 24)), 8) & 0x000000FF;
1613 
1614     return ((u << 24) | (t << 16) | (s <<  8) | (r));
1615 }
1616 
1617 /**
1618   \brief   Quad 8-bit signed subtraction.
1619   \details This function enables you to perform four 8-bit signed integer subtractions.
1620   \param [in]    x  first four 8-bit operands of each subtraction.
1621   \param [in]    y  second four 8-bit operands of each subtraction.
1622   \return        the subtraction of the first bytes from each operand, in the first byte of the return value.\n
1623                  the subtraction of the second bytes of each operand, in the second byte of the return value.\n
1624                  the subtraction of the third bytes of each operand, in the third byte of the return value.\n
1625                  the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.
1626   \remark
1627                  res[7:0]   = val1[7:0]   - val2[7:0]        \n
1628                  res[15:8]  = val1[15:8]  - val2[15:8]       \n
1629                  res[23:16] = val1[23:16] - val2[23:16]      \n
1630                  res[31:24] = val1[31:24] - val2[31:24]
1631  */
__SSUB8(uint32_t x,uint32_t y)1632 __ALWAYS_STATIC_INLINE uint32_t __SSUB8(uint32_t x, uint32_t y)
1633 {
1634     int32_t r, s, t, u;
1635 
1636     r = ((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) & (int32_t)0x000000FF;
1637     s = ((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) & (int32_t)0x000000FF;
1638     t = ((((int32_t)x <<  8) >> 24) - (((int32_t)y <<  8) >> 24)) & (int32_t)0x000000FF;
1639     u = ((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) & (int32_t)0x000000FF;
1640 
1641     return ((uint32_t)((u << 24) | (t << 16) | (s <<  8) | (r)));
1642 }
1643 
1644 /**
1645   \brief   Quad 8-bit unsigned subtract.
1646   \details This function enables you to perform four 8-bit unsigned integer subtractions.
1647   \param [in]    x  first four 8-bit operands of each subtraction.
1648   \param [in]    y  second four 8-bit operands of each subtraction.
1649   \return        the subtraction of the first bytes from each operand, in the first byte of the return value.\n
1650                  the subtraction of the second bytes of each operand, in the second byte of the return value.\n
1651                  the subtraction of the third bytes of each operand, in the third byte of the return value.\n
1652                  the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.
1653   \remark
1654                  res[7:0]   = val1[7:0]   - val2[7:0]        \n
1655                  res[15:8]  = val1[15:8]  - val2[15:8]       \n
1656                  res[23:16] = val1[23:16] - val2[23:16]      \n
1657                  res[31:24] = val1[31:24] - val2[31:24]
1658  */
__USUB8(uint32_t x,uint32_t y)1659 __ALWAYS_STATIC_INLINE uint32_t __USUB8(uint32_t x, uint32_t y)
1660 {
1661     int32_t r, s, t, u;
1662 
1663     r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF;
1664     s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF;
1665     t = (((x <<  8) >> 24) - ((y <<  8) >> 24)) & 0x000000FF;
1666     u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF;
1667 
1668     return ((u << 24) | (t << 16) | (s <<  8) | (r));
1669 }
1670 
1671 /**
1672   \brief   Unsigned sum of quad 8-bit unsigned absolute difference.
1673   \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values
1674            of the differences together, returning the result as a single unsigned integer.
1675   \param [in]    x  first four 8-bit operands of each subtraction.
1676   \param [in]    y  second four 8-bit operands of each subtraction.
1677   \return        the subtraction of the first bytes from each operand, in the first byte of the return value.\n
1678                  the subtraction of the second bytes of each operand, in the second byte of the return value.\n
1679                  the subtraction of the third bytes of each operand, in the third byte of the return value.\n
1680                  the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.\n
1681                  The sum is returned as a single unsigned integer.
1682   \remark
1683                  absdiff1   = val1[7:0]   - val2[7:0]        \n
1684                  absdiff2   = val1[15:8]  - val2[15:8]       \n
1685                  absdiff3   = val1[23:16] - val2[23:16]      \n
1686                  absdiff4   = val1[31:24] - val2[31:24]      \n
1687                  res[31:0]  = absdiff1 + absdiff2 + absdiff3 + absdiff4
1688  */
__USAD8(uint32_t x,uint32_t y)1689 __ALWAYS_STATIC_INLINE uint32_t __USAD8(uint32_t x, uint32_t y)
1690 {
1691     int32_t r, s, t, u;
1692 
1693     r = (((x << 24) >> 24) - ((y << 24) >> 24)) & 0x000000FF;
1694     s = (((x << 16) >> 24) - ((y << 16) >> 24)) & 0x000000FF;
1695     t = (((x <<  8) >> 24) - ((y <<  8) >> 24)) & 0x000000FF;
1696     u = (((x) >> 24) - ((y) >> 24)) & 0x000000FF;
1697 
1698     return (u + t + s + r);
1699 }
1700 
1701 /**
1702   \brief   Unsigned sum of quad 8-bit unsigned absolute difference with 32-bit accumulate.
1703   \details This function enables you to perform four unsigned 8-bit subtractions, and add the absolute values
1704            of the differences to a 32-bit accumulate operand.
1705   \param [in]    x  first four 8-bit operands of each subtraction.
1706   \param [in]    y  second four 8-bit operands of each subtraction.
1707   \param [in]  sum  accumulation value.
1708   \return        the sum of the absolute differences of the following bytes, added to the accumulation value:
1709                  the subtraction of the first bytes from each operand, in the first byte of the return value.\n
1710                  the subtraction of the second bytes of each operand, in the second byte of the return value.\n
1711                  the subtraction of the third bytes of each operand, in the third byte of the return value.\n
1712                  the subtraction of the fourth bytes of each operand, in the fourth byte of the return value.
1713   \remark
1714                  absdiff1 = val1[7:0]   - val2[7:0]        \n
1715                  absdiff2 = val1[15:8]  - val2[15:8]       \n
1716                  absdiff3 = val1[23:16] - val2[23:16]      \n
1717                  absdiff4 = val1[31:24] - val2[31:24]      \n
1718                  sum = absdiff1 + absdiff2 + absdiff3 + absdiff4 \n
1719                  res[31:0] = sum[31:0] + val3[31:0]
1720  */
__USADA8(uint32_t x,uint32_t y,uint32_t sum)1721 __ALWAYS_STATIC_INLINE uint32_t __USADA8(uint32_t x, uint32_t y, uint32_t sum)
1722 {
1723     int32_t r, s, t, u;
1724 
1725 #ifdef __cplusplus
1726     r = (abs((long long)((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF;
1727     s = (abs((long long)((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF;
1728     t = (abs((long long)((x <<  8) >> 24) - ((y <<  8) >> 24))) & 0x000000FF;
1729     u = (abs((long long)((x) >> 24) - ((y) >> 24))) & 0x000000FF;
1730 #else
1731     r = (abs(((x << 24) >> 24) - ((y << 24) >> 24))) & 0x000000FF;
1732     s = (abs(((x << 16) >> 24) - ((y << 16) >> 24))) & 0x000000FF;
1733     t = (abs(((x <<  8) >> 24) - ((y <<  8) >> 24))) & 0x000000FF;
1734     u = (abs(((x) >> 24) - ((y) >> 24))) & 0x000000FF;
1735 #endif
1736     return (u + t + s + r + sum);
1737 }
1738 
1739 /**
1740   \brief   Dual 16-bit saturating addition.
1741   \details This function enables you to perform two 16-bit integer arithmetic additions in parallel,
1742            saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
1743   \param [in]    x   first two 16-bit summands.
1744   \param [in]    y   second two 16-bit summands.
1745   \return        the saturated addition of the low halfwords, in the low halfword of the return value.\n
1746                  the saturated addition of the high halfwords, in the high halfword of the return value.\n
1747                  The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
1748   \remark
1749                  res[15:0]  = val1[15:0]  + val2[15:0]        \n
1750                  res[31:16] = val1[31:16] + val2[31:16]
1751  */
__QADD16(uint32_t x,uint32_t y)1752 __ALWAYS_STATIC_INLINE uint32_t __QADD16(uint32_t x, uint32_t y)
1753 {
1754     int32_t r = 0, s = 0;
1755 
1756     r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF;
1757     s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF;
1758 
1759     return ((uint32_t)((s << 16) | (r)));
1760 }
1761 
1762 /**
1763   \brief   Dual 16-bit unsigned saturating addition.
1764   \details This function enables you to perform two unsigned 16-bit integer additions, saturating
1765            the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1.
1766   \param [in]    x   first two 16-bit summands.
1767   \param [in]    y   second two 16-bit summands.
1768   \return        the saturated addition of the low halfwords, in the low halfword of the return value.\n
1769                  the saturated addition of the high halfwords, in the high halfword of the return value.\n
1770                  The results are saturated to the 16-bit unsigned integer range 0 < x < 2^16 - 1.
1771   \remark
1772                  res[15:0]  = val1[15:0]  + val2[15:0]        \n
1773                  res[31:16] = val1[31:16] + val2[31:16]
1774  */
__UQADD16(uint32_t x,uint32_t y)1775 __ALWAYS_STATIC_INLINE uint32_t __UQADD16(uint32_t x, uint32_t y)
1776 {
1777     int32_t r = 0, s = 0;
1778 
1779     r = __IUSAT((((x << 16) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF;
1780     s = __IUSAT((((x) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF;
1781 
1782     return ((s << 16) | (r));
1783 }
1784 
1785 /**
1786   \brief   Dual 16-bit signed addition.
1787   \details This function enables you to perform two 16-bit signed integer additions.
1788   \param [in]    x   first two 16-bit summands.
1789   \param [in]    y   second two 16-bit summands.
1790   \return        the addition of the low halfwords in the low halfword of the return value.\n
1791                  the addition of the high halfwords in the high halfword of the return value.
1792   \remark
1793                  res[15:0]  = val1[15:0]  + val2[15:0]        \n
1794                  res[31:16] = val1[31:16] + val2[31:16]
1795  */
__SADD16(uint32_t x,uint32_t y)1796 __ALWAYS_STATIC_INLINE uint32_t __SADD16(uint32_t x, uint32_t y)
1797 {
1798     int32_t r = 0, s = 0;
1799 
1800     r = ((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF;
1801     s = ((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF;
1802 
1803     return ((uint32_t)((s << 16) | (r)));
1804 }
1805 
1806 /**
1807   \brief   Dual 16-bit unsigned addition
1808   \details This function enables you to perform two 16-bit unsigned integer additions.
1809   \param [in]    x   first two 16-bit summands for each addition.
1810   \param [in]    y   second two 16-bit summands for each addition.
1811   \return        the addition of the low halfwords in the low halfword of the return value.\n
1812                  the addition of the high halfwords in the high halfword of the return value.
1813   \remark
1814                  res[15:0]  = val1[15:0]  + val2[15:0]        \n
1815                  res[31:16] = val1[31:16] + val2[31:16]
1816  */
__UADD16(uint32_t x,uint32_t y)1817 __ALWAYS_STATIC_INLINE uint32_t __UADD16(uint32_t x, uint32_t y)
1818 {
1819     int32_t r = 0, s = 0;
1820 
1821     r = (((x << 16) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF;
1822     s = (((x) >> 16) + ((y) >> 16)) & 0x0000FFFF;
1823 
1824     return ((s << 16) | (r));
1825 }
1826 
1827 
1828 /**
1829   \brief   Dual 16-bit signed addition with halved results.
1830   \details This function enables you to perform two signed 16-bit integer additions, halving the results.
1831   \param [in]    x   first two 16-bit summands.
1832   \param [in]    y   second two 16-bit summands.
1833   \return        the halved addition of the low halfwords, in the low halfword of the return value.\n
1834                  the halved addition of the high halfwords, in the high halfword of the return value.
1835   \remark
1836                  res[15:0]  = (val1[15:0]  + val2[15:0]) >> 1        \n
1837                  res[31:16] = (val1[31:16] + val2[31:16]) >> 1
1838  */
__SHADD16(uint32_t x,uint32_t y)1839 __ALWAYS_STATIC_INLINE uint32_t __SHADD16(uint32_t x, uint32_t y)
1840 {
1841     int32_t r, s;
1842 
1843     r = (((((int32_t)x << 16) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF;
1844     s = (((((int32_t)x) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF;
1845 
1846     return ((uint32_t)((s << 16) | (r)));
1847 }
1848 
1849 /**
1850   \brief   Dual 16-bit unsigned addition with halved results.
1851   \details This function enables you to perform two unsigned 16-bit integer additions, halving the results.
1852   \param [in]    x   first two 16-bit summands.
1853   \param [in]    y   second two 16-bit summands.
1854   \return        the halved addition of the low halfwords, in the low halfword of the return value.\n
1855                  the halved addition of the high halfwords, in the high halfword of the return value.
1856   \remark
1857                  res[15:0]  = (val1[15:0]  + val2[15:0]) >> 1        \n
1858                  res[31:16] = (val1[31:16] + val2[31:16]) >> 1
1859  */
__UHADD16(uint32_t x,uint32_t y)1860 __ALWAYS_STATIC_INLINE uint32_t __UHADD16(uint32_t x, uint32_t y)
1861 {
1862     int32_t r, s;
1863 
1864     r = ((((x << 16) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF;
1865     s = ((((x) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF;
1866 
1867     return ((s << 16) | (r));
1868 }
1869 
1870 /**
1871   \brief   Quad 8-bit signed addition with halved results.
1872   \details This function enables you to perform four signed 8-bit integer additions, halving the results.
1873   \param [in]    x   first four 8-bit summands.
1874   \param [in]    y   second four 8-bit summands.
1875   \return        the halved addition of the first bytes from each operand, in the first byte of the return value.\n
1876                  the halved addition of the second bytes from each operand, in the second byte of the return value.\n
1877                  the halved addition of the third bytes from each operand, in the third byte of the return value.\n
1878                  the halved addition of the fourth bytes from each operand, in the fourth byte of the return value.
1879   \remark
1880                  res[7:0]   = (val1[7:0]   + val2[7:0]  ) >> 1    \n
1881                  res[15:8]  = (val1[15:8]  + val2[15:8] ) >> 1    \n
1882                  res[23:16] = (val1[23:16] + val2[23:16]) >> 1    \n
1883                  res[31:24] = (val1[31:24] + val2[31:24]) >> 1
1884  */
__SHADD8(uint32_t x,uint32_t y)1885 __ALWAYS_STATIC_INLINE uint32_t __SHADD8(uint32_t x, uint32_t y)
1886 {
1887     int32_t r, s, t, u;
1888 
1889     r = (((((int32_t)x << 24) >> 24) + (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF;
1890     s = (((((int32_t)x << 16) >> 24) + (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF;
1891     t = (((((int32_t)x <<  8) >> 24) + (((int32_t)y <<  8) >> 24)) >> 1) & (int32_t)0x000000FF;
1892     u = (((((int32_t)x) >> 24) + (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF;
1893 
1894     return ((uint32_t)((u << 24) | (t << 16) | (s <<  8) | (r)));
1895 }
1896 
1897 /**
1898   \brief   Quad 8-bit unsigned addition with halved results.
1899   \details This function enables you to perform four unsigned 8-bit integer additions, halving the results.
1900   \param [in]    x   first four 8-bit summands.
1901   \param [in]    y   second four 8-bit summands.
1902   \return        the halved addition of the first bytes from each operand, in the first byte of the return value.\n
1903                  the halved addition of the second bytes from each operand, in the second byte of the return value.\n
1904                  the halved addition of the third bytes from each operand, in the third byte of the return value.\n
1905                  the halved addition of the fourth bytes from each operand, in the fourth byte of the return value.
1906   \remark
1907                  res[7:0]   = (val1[7:0]   + val2[7:0]  ) >> 1    \n
1908                  res[15:8]  = (val1[15:8]  + val2[15:8] ) >> 1    \n
1909                  res[23:16] = (val1[23:16] + val2[23:16]) >> 1    \n
1910                  res[31:24] = (val1[31:24] + val2[31:24]) >> 1
1911  */
__UHADD8(uint32_t x,uint32_t y)1912 __ALWAYS_STATIC_INLINE uint32_t __UHADD8(uint32_t x, uint32_t y)
1913 {
1914     int32_t r, s, t, u;
1915 
1916     r = ((((x << 24) >> 24) + ((y << 24) >> 24)) >> 1) & 0x000000FF;
1917     s = ((((x << 16) >> 24) + ((y << 16) >> 24)) >> 1) & 0x000000FF;
1918     t = ((((x <<  8) >> 24) + ((y <<  8) >> 24)) >> 1) & 0x000000FF;
1919     u = ((((x) >> 24) + ((y) >> 24)) >> 1) & 0x000000FF;
1920 
1921     return ((u << 24) | (t << 16) | (s <<  8) | (r));
1922 }
1923 
1924 /**
1925   \brief   Dual 16-bit saturating subtract.
1926   \details This function enables you to perform two 16-bit integer subtractions in parallel,
1927            saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
1928   \param [in]    x   first two 16-bit summands.
1929   \param [in]    y   second two 16-bit summands.
1930   \return        the saturated subtraction of the low halfwords, in the low halfword of the return value.\n
1931                  the saturated subtraction of the high halfwords, in the high halfword of the return value.\n
1932                  The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
1933   \remark
1934                  res[15:0]  = val1[15:0]  - val2[15:0]        \n
1935                  res[31:16] = val1[31:16] - val2[31:16]
1936  */
__QSUB16(uint32_t x,uint32_t y)1937 __ALWAYS_STATIC_INLINE uint32_t __QSUB16(uint32_t x, uint32_t y)
1938 {
1939     int32_t r, s;
1940 
1941     r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF;
1942     s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF;
1943 
1944     return ((uint32_t)((s << 16) | (r)));
1945 }
1946 
1947 /**
1948   \brief   Dual 16-bit unsigned saturating subtraction.
1949   \details This function enables you to perform two unsigned 16-bit integer subtractions,
1950            saturating the results to the 16-bit unsigned integer range 0 < x < 2^16 - 1.
1951   \param [in]    x   first two 16-bit operands for each subtraction.
1952   \param [in]    y   second two 16-bit operands for each subtraction.
1953   \return        the saturated subtraction of the low halfwords, in the low halfword of the return value.\n
1954                  the saturated subtraction of the high halfwords, in the high halfword of the return value.\n
1955                  The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
1956   \remark
1957                  res[15:0]  = val1[15:0]  - val2[15:0]        \n
1958                  res[31:16] = val1[31:16] - val2[31:16]
1959  */
__UQSUB16(uint32_t x,uint32_t y)1960 __ALWAYS_STATIC_INLINE uint32_t __UQSUB16(uint32_t x, uint32_t y)
1961 {
1962     int32_t r, s;
1963 
1964     r = __IUSAT((((x << 16) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF;
1965     s = __IUSAT((((x) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF;
1966 
1967     return ((s << 16) | (r));
1968 }
1969 
1970 /**
1971   \brief   Dual 16-bit signed subtraction.
1972   \details This function enables you to perform two 16-bit signed integer subtractions.
1973   \param [in]    x   first two 16-bit operands of each subtraction.
1974   \param [in]    y   second two 16-bit operands of each subtraction.
1975   \return        the subtraction of the low halfword in the second operand from the low
1976                  halfword in the first operand, in the low halfword of the return value. \n
1977                  the subtraction of the high halfword in the second operand from the high
1978                  halfword in the first operand, in the high halfword of the return value.
1979   \remark
1980                  res[15:0]  = val1[15:0]  - val2[15:0]        \n
1981                  res[31:16] = val1[31:16] - val2[31:16]
1982  */
__SSUB16(uint32_t x,uint32_t y)1983 __ALWAYS_STATIC_INLINE uint32_t __SSUB16(uint32_t x, uint32_t y)
1984 {
1985     int32_t r, s;
1986 
1987     r = ((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF;
1988     s = ((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF;
1989 
1990     return ((uint32_t)((s << 16) | (r)));
1991 }
1992 
1993 /**
1994   \brief   Dual 16-bit unsigned subtract.
1995   \details This function enables you to perform two 16-bit unsigned integer subtractions.
1996   \param [in]    x   first two 16-bit operands of each subtraction.
1997   \param [in]    y   second two 16-bit operands of each subtraction.
1998   \return        the subtraction of the low halfword in the second operand from the low
1999                  halfword in the first operand, in the low halfword of the return value. \n
2000                  the subtraction of the high halfword in the second operand from the high
2001                  halfword in the first operand, in the high halfword of the return value.
2002   \remark
2003                  res[15:0]  = val1[15:0]  - val2[15:0]        \n
2004                  res[31:16] = val1[31:16] - val2[31:16]
2005  */
__USUB16(uint32_t x,uint32_t y)2006 __ALWAYS_STATIC_INLINE uint32_t __USUB16(uint32_t x, uint32_t y)
2007 {
2008     int32_t r, s;
2009 
2010     r = (((x << 16) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF;
2011     s = (((x) >> 16) - ((y) >> 16)) & 0x0000FFFF;
2012 
2013     return ((s << 16) | (r));
2014 }
2015 
2016 /**
2017   \brief   Dual 16-bit signed subtraction with halved results.
2018   \details This function enables you to perform two signed 16-bit integer subtractions, halving the results.
2019   \param [in]    x   first two 16-bit summands.
2020   \param [in]    y   second two 16-bit summands.
2021   \return        the halved subtraction of the low halfwords, in the low halfword of the return value.\n
2022                  the halved subtraction of the high halfwords, in the high halfword of the return value.
2023   \remark
2024                  res[15:0]  = (val1[15:0]  - val2[15:0]) >> 1        \n
2025                  res[31:16] = (val1[31:16] - val2[31:16]) >> 1
2026  */
__SHSUB16(uint32_t x,uint32_t y)2027 __ALWAYS_STATIC_INLINE uint32_t __SHSUB16(uint32_t x, uint32_t y)
2028 {
2029     int32_t r, s;
2030 
2031     r = (((((int32_t)x << 16) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF;
2032     s = (((((int32_t)x) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF;
2033 
2034     return ((uint32_t)((s << 16) | (r)));
2035 }
2036 
2037 /**
2038   \brief   Dual 16-bit unsigned subtraction with halved results.
2039   \details This function enables you to perform two unsigned 16-bit integer subtractions, halving the results.
2040   \param [in]    x   first two 16-bit summands.
2041   \param [in]    y   second two 16-bit summands.
2042   \return        the halved subtraction of the low halfwords, in the low halfword of the return value.\n
2043                  the halved subtraction of the high halfwords, in the high halfword of the return value.
2044   \remark
2045                  res[15:0]  = (val1[15:0]  - val2[15:0]) >> 1        \n
2046                  res[31:16] = (val1[31:16] - val2[31:16]) >> 1
2047  */
__UHSUB16(uint32_t x,uint32_t y)2048 __ALWAYS_STATIC_INLINE uint32_t __UHSUB16(uint32_t x, uint32_t y)
2049 {
2050     int32_t r, s;
2051 
2052     r = ((((x << 16) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF;
2053     s = ((((x) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF;
2054 
2055     return ((s << 16) | (r));
2056 }
2057 
2058 /**
2059   \brief   Quad 8-bit signed addition with halved results.
2060   \details This function enables you to perform four signed 8-bit integer subtractions, halving the results.
2061   \param [in]    x   first four 8-bit summands.
2062   \param [in]    y   second four 8-bit summands.
2063   \return        the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n
2064                  the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n
2065                  the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n
2066                  the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value.
2067   \remark
2068                  res[7:0]   = (val1[7:0]   - val2[7:0]  ) >> 1    \n
2069                  res[15:8]  = (val1[15:8]  - val2[15:8] ) >> 1    \n
2070                  res[23:16] = (val1[23:16] - val2[23:16]) >> 1    \n
2071                  res[31:24] = (val1[31:24] - val2[31:24]) >> 1
2072  */
__SHSUB8(uint32_t x,uint32_t y)2073 __ALWAYS_STATIC_INLINE uint32_t __SHSUB8(uint32_t x, uint32_t y)
2074 {
2075     int32_t r, s, t, u;
2076 
2077     r = (((((int32_t)x << 24) >> 24) - (((int32_t)y << 24) >> 24)) >> 1) & (int32_t)0x000000FF;
2078     s = (((((int32_t)x << 16) >> 24) - (((int32_t)y << 16) >> 24)) >> 1) & (int32_t)0x000000FF;
2079     t = (((((int32_t)x <<  8) >> 24) - (((int32_t)y <<  8) >> 24)) >> 1) & (int32_t)0x000000FF;
2080     u = (((((int32_t)x) >> 24) - (((int32_t)y) >> 24)) >> 1) & (int32_t)0x000000FF;
2081 
2082     return ((uint32_t)((u << 24) | (t << 16) | (s <<  8) | (r)));
2083 }
2084 
2085 /**
2086   \brief   Quad 8-bit unsigned subtraction with halved results.
2087   \details This function enables you to perform four unsigned 8-bit integer subtractions, halving the results.
2088   \param [in]    x   first four 8-bit summands.
2089   \param [in]    y   second four 8-bit summands.
2090   \return        the halved subtraction of the first bytes from each operand, in the first byte of the return value.\n
2091                  the halved subtraction of the second bytes from each operand, in the second byte of the return value.\n
2092                  the halved subtraction of the third bytes from each operand, in the third byte of the return value.\n
2093                  the halved subtraction of the fourth bytes from each operand, in the fourth byte of the return value.
2094   \remark
2095                  res[7:0]   = (val1[7:0]   - val2[7:0]  ) >> 1    \n
2096                  res[15:8]  = (val1[15:8]  - val2[15:8] ) >> 1    \n
2097                  res[23:16] = (val1[23:16] - val2[23:16]) >> 1    \n
2098                  res[31:24] = (val1[31:24] - val2[31:24]) >> 1
2099  */
__UHSUB8(uint32_t x,uint32_t y)2100 __ALWAYS_STATIC_INLINE uint32_t __UHSUB8(uint32_t x, uint32_t y)
2101 {
2102     int32_t r, s, t, u;
2103 
2104     r = ((((x << 24) >> 24) - ((y << 24) >> 24)) >> 1) & 0x000000FF;
2105     s = ((((x << 16) >> 24) - ((y << 16) >> 24)) >> 1) & 0x000000FF;
2106     t = ((((x <<  8) >> 24) - ((y <<  8) >> 24)) >> 1) & 0x000000FF;
2107     u = ((((x) >> 24) - ((y) >> 24)) >> 1) & 0x000000FF;
2108 
2109     return ((u << 24) | (t << 16) | (s <<  8) | (r));
2110 }
2111 
2112 /**
2113   \brief   Dual 16-bit add and subtract with exchange.
2114   \details This function enables you to exchange the halfwords of the one operand,
2115            then add the high halfwords and subtract the low halfwords,
2116            saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
2117   \param [in]    x   first operand for the subtraction in the low halfword,
2118                      and the first operand for the addition in the high halfword.
2119   \param [in]    y   second operand for the subtraction in the high halfword,
2120                      and the second operand for the addition in the low halfword.
2121   \return        the saturated subtraction of the high halfword in the second operand from the
2122                  low halfword in the first operand, in the low halfword of the return value.\n
2123                  the saturated addition of the high halfword in the first operand and the
2124                  low halfword in the second operand, in the high halfword of the return value.\n
2125                  The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
2126   \remark
2127                  res[15:0]  = val1[15:0]  - val2[31:16]        \n
2128                  res[31:16] = val1[31:16] + val2[15:0]
2129  */
__QASX(uint32_t x,uint32_t y)2130 __ALWAYS_STATIC_INLINE uint32_t __QASX(uint32_t x, uint32_t y)
2131 {
2132     int32_t r, s;
2133 
2134     r = __SSAT(((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF;
2135     s = __SSAT(((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF;
2136 
2137     return ((uint32_t)((s << 16) | (r)));
2138 }
2139 
2140 /**
2141   \brief   Dual 16-bit unsigned saturating addition and subtraction with exchange.
2142   \details This function enables you to exchange the halfwords of the second operand and
2143            perform one unsigned 16-bit integer addition and one unsigned 16-bit subtraction,
2144            saturating the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1.
2145   \param [in]    x   first operand for the subtraction in the low halfword,
2146                      and the first operand for the addition in the high halfword.
2147   \param [in]    y   second operand for the subtraction in the high halfword,
2148                      and the second operand for the addition in the low halfword.
2149   \return        the saturated subtraction of the high halfword in the second operand from the
2150                  low halfword in the first operand, in the low halfword of the return value.\n
2151                  the saturated addition of the high halfword in the first operand and the
2152                  low halfword in the second operand, in the high halfword of the return value.\n
2153                  The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1.
2154   \remark
2155                  res[15:0]  = val1[15:0]  - val2[31:16]        \n
2156                  res[31:16] = val1[31:16] + val2[15:0]
2157  */
__UQASX(uint32_t x,uint32_t y)2158 __ALWAYS_STATIC_INLINE uint32_t __UQASX(uint32_t x, uint32_t y)
2159 {
2160     int32_t r, s;
2161 
2162     r = __IUSAT((((x << 16) >> 16) - ((y) >> 16)), 16) & 0x0000FFFF;
2163     s = __IUSAT((((x) >> 16) + ((y << 16) >> 16)), 16) & 0x0000FFFF;
2164 
2165     return ((s << 16) | (r));
2166 }
2167 
2168 /**
2169   \brief   Dual 16-bit addition and subtraction with exchange.
2170   \details It enables you to exchange the halfwords of the second operand, add the high halfwords
2171            and subtract the low halfwords.
2172   \param [in]    x   first operand for the subtraction in the low halfword,
2173                      and the first operand for the addition in the high halfword.
2174   \param [in]    y   second operand for the subtraction in the high halfword,
2175                      and the second operand for the addition in the low halfword.
2176   \return        the subtraction of the high halfword in the second operand from the
2177                  low halfword in the first operand, in the low halfword of the return value.\n
2178                  the addition of the high halfword in the first operand and the
2179                  low halfword in the second operand, in the high halfword of the return value.
2180   \remark
2181                  res[15:0]  = val1[15:0]  - val2[31:16]        \n
2182                  res[31:16] = val1[31:16] + val2[15:0]
2183  */
__SASX(uint32_t x,uint32_t y)2184 __ALWAYS_STATIC_INLINE uint32_t __SASX(uint32_t x, uint32_t y)
2185 {
2186     int32_t r, s;
2187 
2188     r = ((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF;
2189     s = ((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF;
2190 
2191     return ((uint32_t)((s << 16) | (r)));
2192 }
2193 
2194 /**
2195   \brief   Dual 16-bit unsigned addition and subtraction with exchange.
2196   \details This function enables you to exchange the two halfwords of the second operand,
2197            add the high halfwords and subtract the low halfwords.
2198   \param [in]    x   first operand for the subtraction in the low halfword,
2199                      and the first operand for the addition in the high halfword.
2200   \param [in]    y   second operand for the subtraction in the high halfword,
2201                      and the second operand for the addition in the low halfword.
2202   \return        the subtraction of the high halfword in the second operand from the
2203                  low halfword in the first operand, in the low halfword of the return value.\n
2204                  the addition of the high halfword in the first operand and the
2205                  low halfword in the second operand, in the high halfword of the return value.
2206   \remark
2207                  res[15:0]  = val1[15:0]  - val2[31:16]        \n
2208                  res[31:16] = val1[31:16] + val2[15:0]
2209  */
__UASX(uint32_t x,uint32_t y)2210 __ALWAYS_STATIC_INLINE uint32_t __UASX(uint32_t x, uint32_t y)
2211 {
2212     int32_t r, s;
2213 
2214     r = (((x << 16) >> 16) - ((y) >> 16)) & 0x0000FFFF;
2215     s = (((x) >> 16) + ((y << 16) >> 16)) & 0x0000FFFF;
2216 
2217     return ((s << 16) | (r));
2218 }
2219 
2220 /**
2221   \brief   Dual 16-bit signed addition and subtraction with halved results.
2222   \details This function enables you to exchange the two halfwords of one operand, perform one
2223            signed 16-bit integer addition and one signed 16-bit subtraction, and halve the results.
2224   \param [in]    x   first 16-bit operands.
2225   \param [in]    y   second 16-bit operands.
2226   \return        the halved subtraction of the high halfword in the second operand from the
2227                  low halfword in the first operand, in the low halfword of the return value.\n
2228                  the halved addition of the low halfword in the second operand from the high
2229                  halfword in the first operand, in the high halfword of the return value.
2230   \remark
2231                  res[15:0]  = (val1[15:0]  - val2[31:16]) >> 1        \n
2232                  res[31:16] = (val1[31:16] + val2[15:0]) >> 1
2233  */
__SHASX(uint32_t x,uint32_t y)2234 __ALWAYS_STATIC_INLINE uint32_t __SHASX(uint32_t x, uint32_t y)
2235 {
2236     int32_t r, s;
2237 
2238     r = (((((int32_t)x << 16) >> 16) - (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF;
2239     s = (((((int32_t)x) >> 16) + (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF;
2240 
2241     return ((uint32_t)((s << 16) | (r)));
2242 }
2243 
2244 /**
2245   \brief   Dual 16-bit unsigned addition and subtraction with halved results and exchange.
2246   \details This function enables you to exchange the halfwords of the second operand,
2247            add the high halfwords and subtract the low halfwords, halving the results.
2248   \param [in]    x   first operand for the subtraction in the low halfword, and
2249                      the first operand for the addition in the high halfword.
2250   \param [in]    y   second operand for the subtraction in the high halfword, and
2251                      the second operand for the addition in the low halfword.
2252   \return        the halved subtraction of the high halfword in the second operand from the
2253                  low halfword in the first operand, in the low halfword of the return value.\n
2254                  the halved addition of the low halfword in the second operand from the high
2255                  halfword in the first operand, in the high halfword of the return value.
2256   \remark
2257                  res[15:0]  = (val1[15:0]  - val2[31:16]) >> 1        \n
2258                  res[31:16] = (val1[31:16] + val2[15:0]) >> 1
2259  */
__UHASX(uint32_t x,uint32_t y)2260 __ALWAYS_STATIC_INLINE uint32_t __UHASX(uint32_t x, uint32_t y)
2261 {
2262     int32_t r, s;
2263 
2264     r = ((((x << 16) >> 16) - ((y) >> 16)) >> 1) & 0x0000FFFF;
2265     s = ((((x) >> 16) + ((y << 16) >> 16)) >> 1) & 0x0000FFFF;
2266 
2267     return ((s << 16) | (r));
2268 }
2269 
2270 /**
2271   \brief   Dual 16-bit subtract and add with exchange.
2272   \details This function enables you to exchange the halfwords of one operand,
2273            then subtract the high halfwords and add the low halfwords,
2274            saturating the results to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
2275   \param [in]    x   first operand for the addition in the low halfword,
2276                      and the first operand for the subtraction in the high halfword.
2277   \param [in]    y   second operand for the addition in the high halfword,
2278                      and the second operand for the subtraction in the low halfword.
2279   \return        the saturated addition of the low halfword of the first operand and the high
2280                  halfword of the second operand, in the low halfword of the return value.\n
2281                  the saturated subtraction of the low halfword of the second operand from the
2282                  high halfword of the first operand, in the high halfword of the return value.\n
2283                  The returned results are saturated to the 16-bit signed integer range -2^15 <= x <= 2^15 - 1.
2284   \remark
2285                  res[15:0]  = val1[15:0]  + val2[31:16]        \n
2286                  res[31:16] = val1[31:16] - val2[15:0]
2287  */
__QSAX(uint32_t x,uint32_t y)2288 __ALWAYS_STATIC_INLINE uint32_t __QSAX(uint32_t x, uint32_t y)
2289 {
2290     int32_t r, s;
2291 
2292     r = __SSAT(((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)), 16) & (int32_t)0x0000FFFF;
2293     s = __SSAT(((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF;
2294 
2295     return ((uint32_t)((s << 16) | (r)));
2296 }
2297 
2298 /**
2299   \brief   Dual 16-bit unsigned saturating subtraction and addition with exchange.
2300   \details This function enables you to exchange the halfwords of the second operand and perform
2301            one unsigned 16-bit integer subtraction and one unsigned 16-bit addition, saturating
2302            the results to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1.
2303   \param [in]    x   first operand for the addition in the low halfword,
2304                      and the first operand for the subtraction in the high halfword.
2305   \param [in]    y   second operand for the addition in the high halfword,
2306                      and the second operand for the subtraction in the low halfword.
2307   \return        the saturated addition of the low halfword of the first operand and the high
2308                  halfword of the second operand, in the low halfword of the return value.\n
2309                  the saturated subtraction of the low halfword of the second operand from the
2310                  high halfword of the first operand, in the high halfword of the return value.\n
2311                  The returned results are saturated to the 16-bit unsigned integer range 0 <= x <= 2^16 - 1.
2312   \remark
2313                  res[15:0]  = val1[15:0]  + val2[31:16]        \n
2314                  res[31:16] = val1[31:16] - val2[15:0]
2315  */
__UQSAX(uint32_t x,uint32_t y)2316 __ALWAYS_STATIC_INLINE uint32_t __UQSAX(uint32_t x, uint32_t y)
2317 {
2318     int32_t r, s;
2319 
2320     r = __IUSAT((((x << 16) >> 16) + ((y) >> 16)), 16) & 0x0000FFFF;
2321     s = __IUSAT((((x) >> 16) - ((y << 16) >> 16)), 16) & 0x0000FFFF;
2322 
2323     return ((s << 16) | (r));
2324 }
2325 
2326 /**
2327   \brief   Dual 16-bit unsigned subtract and add with exchange.
2328   \details This function enables you to exchange the halfwords of the second operand,
2329            subtract the high halfwords and add the low halfwords.
2330   \param [in]    x   first operand for the addition in the low halfword,
2331                      and the first operand for the subtraction in the high halfword.
2332   \param [in]    y   second operand for the addition in the high halfword,
2333                      and the second operand for the subtraction in the low halfword.
2334   \return        the addition of the low halfword of the first operand and the high
2335                  halfword of the second operand, in the low halfword of the return value.\n
2336                  the subtraction of the low halfword of the second operand from the
2337                  high halfword of the first operand, in the high halfword of the return value.\n
2338   \remark
2339                  res[15:0]  = val1[15:0]  + val2[31:16]        \n
2340                  res[31:16] = val1[31:16] - val2[15:0]
2341  */
__USAX(uint32_t x,uint32_t y)2342 __ALWAYS_STATIC_INLINE uint32_t __USAX(uint32_t x, uint32_t y)
2343 {
2344     int32_t r, s;
2345 
2346     r = (((x << 16) >> 16) + ((y) >> 16)) & 0x0000FFFF;
2347     s = (((x) >> 16) - ((y << 16) >> 16)) & 0x0000FFFF;
2348 
2349     return ((s << 16) | (r));
2350 }
2351 
2352 /**
2353   \brief   Dual 16-bit signed subtraction and addition with exchange.
2354   \details This function enables you to exchange the two halfwords of one operand and perform one
2355            16-bit integer subtraction and one 16-bit addition.
2356   \param [in]    x   first operand for the addition in the low halfword, and the first operand
2357                      for the subtraction in the high halfword.
2358   \param [in]    y   second operand for the addition in the high halfword, and the second
2359                      operand for the subtraction in the low halfword.
2360   \return        the addition of the low halfword of the first operand and the high
2361                  halfword of the second operand, in the low halfword of the return value.\n
2362                  the subtraction of the low halfword of the second operand from the
2363                  high halfword of the first operand, in the high halfword of the return value.\n
2364   \remark
2365                  res[15:0]  = val1[15:0]  + val2[31:16]        \n
2366                  res[31:16] = val1[31:16] - val2[15:0]
2367  */
__SSAX(uint32_t x,uint32_t y)2368 __ALWAYS_STATIC_INLINE uint32_t __SSAX(uint32_t x, uint32_t y)
2369 {
2370     int32_t r, s;
2371 
2372     r = ((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) & (int32_t)0x0000FFFF;
2373     s = ((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) & (int32_t)0x0000FFFF;
2374 
2375     return ((uint32_t)((s << 16) | (r)));
2376 }
2377 
2378 
2379 /**
2380   \brief   Dual 16-bit signed subtraction and addition with halved results.
2381   \details This function enables you to exchange the two halfwords of one operand, perform one signed
2382            16-bit integer subtraction and one signed 16-bit addition, and halve the results.
2383   \param [in]    x   first 16-bit operands.
2384   \param [in]    y   second 16-bit operands.
2385   \return        the halved addition of the low halfword in the first operand and the
2386                  high halfword in the second operand, in the low halfword of the return value.\n
2387                  the halved subtraction of the low halfword in the second operand from the
2388                  high halfword in the first operand, in the high halfword of the return value.
2389   \remark
2390                  res[15:0]  = (val1[15:0]  + val2[31:16]) >> 1        \n
2391                  res[31:16] = (val1[31:16] - val2[15:0]) >> 1
2392  */
__SHSAX(uint32_t x,uint32_t y)2393 __ALWAYS_STATIC_INLINE uint32_t __SHSAX(uint32_t x, uint32_t y)
2394 {
2395     int32_t r, s;
2396 
2397     r = (((((int32_t)x << 16) >> 16) + (((int32_t)y) >> 16)) >> 1) & (int32_t)0x0000FFFF;
2398     s = (((((int32_t)x) >> 16) - (((int32_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF;
2399 
2400     return ((uint32_t)((s << 16) | (r)));
2401 }
2402 
2403 /**
2404   \brief   Dual 16-bit unsigned subtraction and addition with halved results and exchange.
2405   \details This function enables you to exchange the halfwords of the second operand,
2406            subtract the high halfwords and add the low halfwords, halving the results.
2407   \param [in]    x   first operand for the addition in the low halfword, and
2408                      the first operand for the subtraction in the high halfword.
2409   \param [in]    y   second operand for the addition in the high halfword, and
2410                      the second operand for the subtraction in the low halfword.
2411   \return        the halved addition of the low halfword in the first operand and the
2412                  high halfword in the second operand, in the low halfword of the return value.\n
2413                  the halved subtraction of the low halfword in the second operand from the
2414                  high halfword in the first operand, in the high halfword of the return value.
2415   \remark
2416                  res[15:0]  = (val1[15:0]  + val2[31:16]) >> 1        \n
2417                  res[31:16] = (val1[31:16] - val2[15:0]) >> 1
2418  */
__UHSAX(uint32_t x,uint32_t y)2419 __ALWAYS_STATIC_INLINE uint32_t __UHSAX(uint32_t x, uint32_t y)
2420 {
2421     int32_t r, s;
2422 
2423     r = ((((x << 16) >> 16) + ((y) >> 16)) >> 1) & 0x0000FFFF;
2424     s = ((((x) >> 16) - ((y << 16) >> 16)) >> 1) & 0x0000FFFF;
2425 
2426     return ((s << 16) | (r));
2427 }
2428 
2429 /**
2430   \brief   Dual 16-bit signed multiply with exchange returning difference.
2431   \details This function enables you to perform two 16-bit signed multiplications, subtracting
2432            one of the products from the other. The halfwords of the second operand are exchanged
2433            before performing the arithmetic. This produces top * bottom and bottom * top multiplication.
2434   \param [in]    x   first 16-bit operands for each multiplication.
2435   \param [in]    y   second 16-bit operands for each multiplication.
2436   \return        the difference of the products of the two 16-bit signed multiplications.
2437   \remark
2438                  p1 = val1[15:0]  * val2[31:16]       \n
2439                  p2 = val1[31:16] * val2[15:0]        \n
2440                  res[31:0] = p1 - p2
2441  */
__SMUSDX(uint32_t x,uint32_t y)2442 __ALWAYS_STATIC_INLINE uint32_t __SMUSDX(uint32_t x, uint32_t y)
2443 {
2444     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) -
2445                        ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16))));
2446 }
2447 
2448 /**
2449   \brief   Sum of dual 16-bit signed multiply with exchange.
2450   \details This function enables you to perform two 16-bit signed multiplications with exchanged
2451            halfwords of the second operand, adding the products together.
2452   \param [in]    x   first 16-bit operands for each multiplication.
2453   \param [in]    y   second 16-bit operands for each multiplication.
2454   \return        the sum of the products of the two 16-bit signed multiplications with exchanged halfwords of the second operand.
2455   \remark
2456                  p1 = val1[15:0]  * val2[31:16]       \n
2457                  p2 = val1[31:16] * val2[15:0]        \n
2458                  res[31:0] = p1 + p2
2459  */
__SMUADX(uint32_t x,uint32_t y)2460 __ALWAYS_STATIC_INLINE uint32_t __SMUADX(uint32_t x, uint32_t y)
2461 {
2462     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) +
2463                        ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16))));
2464 }
2465 
2466 
2467 /**
2468   \brief   Saturating add.
2469   \details This function enables you to obtain the saturating add of two integers.
2470   \param [in]    x   first summand of the saturating add operation.
2471   \param [in]    y   second summand of the saturating add operation.
2472   \return        the saturating addition of val1 and val2.
2473   \remark
2474                  res[31:0] = SAT(val1 + SAT(val2))
2475  */
__QADD(int32_t x,int32_t y)2476 __ALWAYS_STATIC_INLINE int32_t __QADD(int32_t x, int32_t y)
2477 {
2478     int32_t result;
2479 
2480     if (y >= 0) {
2481         if ((int32_t)((uint32_t)x + (uint32_t)y) >= x) {
2482             result = x + y;
2483         } else {
2484             result = 0x7FFFFFFF;
2485         }
2486     } else {
2487         if ((int32_t)((uint32_t)x + (uint32_t)y) < x) {
2488             result = x + y;
2489         } else {
2490             result = 0x80000000;
2491         }
2492     }
2493 
2494     return result;
2495 }
2496 
2497 /**
2498   \brief   Saturating subtract.
2499   \details This function enables you to obtain the saturating add of two integers.
2500   \param [in]    x   first summand of the saturating add operation.
2501   \param [in]    y   second summand of the saturating add operation.
2502   \return        the saturating addition of val1 and val2.
2503   \remark
2504                  res[31:0] = SAT(val1 - SAT(val2))
2505  */
__QSUB(int32_t x,int32_t y)2506 __ALWAYS_STATIC_INLINE int32_t __QSUB(int32_t x, int32_t y)
2507 {
2508     int64_t tmp;
2509     int32_t result;
2510 
2511     tmp = (int64_t)x - (int64_t)y;
2512 
2513     if (tmp > 0x7fffffff) {
2514         tmp = 0x7fffffff;
2515     } else if (tmp < (-2147483647 - 1)) {
2516         tmp = -2147483647 - 1;
2517     }
2518 
2519     result = tmp;
2520     return result;
2521 }
2522 
2523 /**
2524   \brief   Dual 16-bit signed multiply with single 32-bit accumulator.
2525   \details This function enables you to perform two signed 16-bit multiplications,
2526            adding both results to a 32-bit accumulate operand.
2527   \param [in]    x   first 16-bit operands for each multiplication.
2528   \param [in]    y   second 16-bit operands for each multiplication.
2529   \param [in]  sum   accumulate value.
2530   \return        the product of each multiplication added to the accumulate value, as a 32-bit integer.
2531   \remark
2532                  p1 = val1[15:0]  * val2[15:0]      \n
2533                  p2 = val1[31:16] * val2[31:16]     \n
2534                  res[31:0] = p1 + p2 + val3[31:0]
2535  */
__SMLAD(uint32_t x,uint32_t y,uint32_t sum)2536 __ALWAYS_STATIC_INLINE uint32_t __SMLAD(uint32_t x, uint32_t y, uint32_t sum)
2537 {
2538     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) +
2539                        ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) +
2540                        (((int32_t)sum))));
2541 }
2542 
2543 /**
2544   \brief   Pre-exchanged dual 16-bit signed multiply with single 32-bit accumulator.
2545   \details This function enables you to perform two signed 16-bit multiplications with exchanged
2546            halfwords of the second operand, adding both results to a 32-bit accumulate operand.
2547   \param [in]    x   first 16-bit operands for each multiplication.
2548   \param [in]    y   second 16-bit operands for each multiplication.
2549   \param [in]  sum   accumulate value.
2550   \return        the product of each multiplication with exchanged halfwords of the second
2551                  operand added to the accumulate value, as a 32-bit integer.
2552   \remark
2553                  p1 = val1[15:0]  * val2[31:16]     \n
2554                  p2 = val1[31:16] * val2[15:0]      \n
2555                  res[31:0] = p1 + p2 + val3[31:0]
2556  */
__SMLADX(uint32_t x,uint32_t y,uint32_t sum)2557 __ALWAYS_STATIC_INLINE uint32_t __SMLADX(uint32_t x, uint32_t y, uint32_t sum)
2558 {
2559     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) +
2560                        ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) +
2561                        (((int32_t)sum))));
2562 }
2563 
2564 /**
2565   \brief   Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate.
2566   \details This function enables you to perform two 16-bit signed multiplications, take the
2567            difference of the products, subtracting the high halfword product from the low
2568            halfword product, and add the difference to a 32-bit accumulate operand.
2569   \param [in]    x   first 16-bit operands for each multiplication.
2570   \param [in]    y   second 16-bit operands for each multiplication.
2571   \param [in]  sum   accumulate value.
2572   \return        the difference of the product of each multiplication, added to the accumulate value.
2573   \remark
2574                  p1 = val1[15:0]  * val2[15:0]       \n
2575                  p2 = val1[31:16] * val2[31:16]      \n
2576                  res[31:0] = p1 - p2 + val3[31:0]
2577  */
__SMLSD(uint32_t x,uint32_t y,uint32_t sum)2578 __ALWAYS_STATIC_INLINE uint32_t __SMLSD(uint32_t x, uint32_t y, uint32_t sum)
2579 {
2580     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) -
2581                        ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) +
2582                        (((int32_t)sum))));
2583 }
2584 
2585 /**
2586   \brief   Dual 16-bit signed multiply with exchange subtract with 32-bit accumulate.
2587   \details This function enables you to exchange the halfwords in the second operand, then perform two 16-bit
2588            signed multiplications. The difference of the products is added to a 32-bit accumulate operand.
2589   \param [in]    x   first 16-bit operands for each multiplication.
2590   \param [in]    y   second 16-bit operands for each multiplication.
2591   \param [in]  sum   accumulate value.
2592   \return        the difference of the product of each multiplication, added to the accumulate value.
2593   \remark
2594                  p1 = val1[15:0]  * val2[31:16]     \n
2595                  p2 = val1[31:16] * val2[15:0]      \n
2596                  res[31:0] = p1 - p2 + val3[31:0]
2597  */
__SMLSDX(uint32_t x,uint32_t y,uint32_t sum)2598 __ALWAYS_STATIC_INLINE uint32_t __SMLSDX(uint32_t x, uint32_t y, uint32_t sum)
2599 {
2600     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) -
2601                        ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) +
2602                        (((int32_t)sum))));
2603 }
2604 
2605 /**
2606   \brief   Dual 16-bit signed multiply with single 64-bit accumulator.
2607   \details This function enables you to perform two signed 16-bit multiplications, adding both results
2608            to a 64-bit accumulate operand. Overflow is only possible as a result of the 64-bit addition.
2609            This overflow is not detected if it occurs. Instead, the result wraps around modulo2^64.
2610   \param [in]    x   first 16-bit operands for each multiplication.
2611   \param [in]    y   second 16-bit operands for each multiplication.
2612   \param [in]  sum   accumulate value.
2613   \return        the product of each multiplication added to the accumulate value.
2614   \remark
2615                  p1 = val1[15:0]  * val2[15:0]      \n
2616                  p2 = val1[31:16] * val2[31:16]     \n
2617                  sum = p1 + p2 + val3[63:32][31:0]  \n
2618                  res[63:32] = sum[63:32]            \n
2619                  res[31:0]  = sum[31:0]
2620  */
__SMLALD(uint32_t x,uint32_t y,uint64_t sum)2621 __ALWAYS_STATIC_INLINE uint64_t __SMLALD(uint32_t x, uint32_t y, uint64_t sum)
2622 {
2623     return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) +
2624                        ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) +
2625                        (((uint64_t)sum))));
2626 }
2627 
2628 /**
2629   \brief   Dual 16-bit signed multiply with exchange with single 64-bit accumulator.
2630   \details This function enables you to exchange the halfwords of the second operand, and perform two
2631            signed 16-bit multiplications, adding both results to a 64-bit accumulate operand. Overflow
2632            is only possible as a result of the 64-bit addition. This overflow is not detected if it occurs.
2633            Instead, the result wraps around modulo2^64.
2634   \param [in]    x   first 16-bit operands for each multiplication.
2635   \param [in]    y   second 16-bit operands for each multiplication.
2636   \param [in]  sum   accumulate value.
2637   \return        the product of each multiplication added to the accumulate value.
2638   \remark
2639                  p1 = val1[15:0]  * val2[31:16]     \n
2640                  p2 = val1[31:16] * val2[15:0]      \n
2641                  sum = p1 + p2 + val3[63:32][31:0]  \n
2642                  res[63:32] = sum[63:32]            \n
2643                  res[31:0]  = sum[31:0]
2644  */
__SMLALDX(uint32_t x,uint32_t y,uint64_t sum)2645 __ALWAYS_STATIC_INLINE uint64_t __SMLALDX(uint32_t x, uint32_t y, uint64_t sum)
2646 {
2647     return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) +
2648                        ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) +
2649                        (((uint64_t)sum))));
2650 }
2651 
2652 /**
2653   \brief   dual 16-bit signed multiply subtract with 64-bit accumulate.
2654   \details This function It enables you to perform two 16-bit signed multiplications, take the difference
2655            of the products, subtracting the high halfword product from the low halfword product, and add the
2656            difference to a 64-bit accumulate operand. Overflow cannot occur during the multiplications or the
2657            subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow is not
2658            detected. Instead, the result wraps round to modulo2^64.
2659   \param [in]    x   first 16-bit operands for each multiplication.
2660   \param [in]    y   second 16-bit operands for each multiplication.
2661   \param [in]  sum   accumulate value.
2662   \return        the difference of the product of each multiplication, added to the accumulate value.
2663   \remark
2664                  p1 = val1[15:0]  * val2[15:0]      \n
2665                  p2 = val1[31:16] * val2[31:16]     \n
2666                  res[63:32][31:0] = p1 - p2 + val3[63:32][31:0]
2667  */
__SMLSLD(uint32_t x,uint32_t y,uint64_t sum)2668 __ALWAYS_STATIC_INLINE uint64_t __SMLSLD(uint32_t x, uint32_t y, uint64_t sum)
2669 {
2670     return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) -
2671                        ((((int32_t)x) >> 16) * (((int32_t)y) >> 16)) +
2672                        (((uint64_t)sum))));
2673 }
2674 
2675 /**
2676   \brief   Dual 16-bit signed multiply with exchange subtract with 64-bit accumulate.
2677   \details This function enables you to exchange the halfwords of the second operand, perform two 16-bit multiplications,
2678            adding the difference of the products to a 64-bit accumulate operand. Overflow cannot occur during the
2679            multiplications or the subtraction. Overflow can occur as a result of the 64-bit addition, and this overflow
2680            is not detected. Instead, the result wraps round to modulo2^64.
2681   \param [in]    x   first 16-bit operands for each multiplication.
2682   \param [in]    y   second 16-bit operands for each multiplication.
2683   \param [in]  sum   accumulate value.
2684   \return        the difference of the product of each multiplication, added to the accumulate value.
2685   \remark
2686                  p1 = val1[15:0]  * val2[31:16]      \n
2687                  p2 = val1[31:16] * val2[15:0]       \n
2688                  res[63:32][31:0] = p1 - p2 + val3[63:32][31:0]
2689  */
__SMLSLDX(uint32_t x,uint32_t y,uint64_t sum)2690 __ALWAYS_STATIC_INLINE uint64_t __SMLSLDX(uint32_t x, uint32_t y, uint64_t sum)
2691 {
2692     return ((uint64_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y) >> 16)) -
2693                        ((((int32_t)x) >> 16) * (((int32_t)y << 16) >> 16)) +
2694                        (((uint64_t)sum))));
2695 }
2696 
2697 /**
2698   \brief   32-bit signed multiply with 32-bit truncated accumulator.
2699   \details This function enables you to perform a signed 32-bit multiplications, adding the most
2700            significant 32 bits of the 64-bit result to a 32-bit accumulate operand.
2701   \param [in]    x   first operand for multiplication.
2702   \param [in]    y   second operand for multiplication.
2703   \param [in]  sum   accumulate value.
2704   \return        the product of multiplication (most significant 32 bits) is added to the accumulate value, as a 32-bit integer.
2705   \remark
2706                  p = val1 * val2      \n
2707                  res[31:0] = p[63:32] + val3[31:0]
2708  */
__SMMLA(int32_t x,int32_t y,int32_t sum)2709 __ALWAYS_STATIC_INLINE uint32_t __SMMLA(int32_t x, int32_t y, int32_t sum)
2710 {
2711     return (uint32_t)((int32_t)((int64_t)((int64_t)x * (int64_t)y) >> 32) + sum);
2712 }
2713 
2714 /**
2715   \brief   Sum of dual 16-bit signed multiply.
2716   \details This function enables you to perform two 16-bit signed multiplications, adding the products together.
2717   \param [in]    x   first 16-bit operands for each multiplication.
2718   \param [in]    y   second 16-bit operands for each multiplication.
2719   \return        the sum of the products of the two 16-bit signed multiplications.
2720   \remark
2721                  p1 = val1[15:0]  * val2[15:0]      \n
2722                  p2 = val1[31:16] * val2[31:16]     \n
2723                  res[31:0] = p1 + p2
2724  */
__SMUAD(uint32_t x,uint32_t y)2725 __ALWAYS_STATIC_INLINE uint32_t __SMUAD(uint32_t x, uint32_t y)
2726 {
2727     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) +
2728                        ((((int32_t)x) >> 16) * (((int32_t)y) >> 16))));
2729 }
2730 
2731 /**
2732   \brief   Dual 16-bit signed multiply returning difference.
2733   \details This function enables you to perform two 16-bit signed multiplications, taking the difference
2734            of the products by subtracting the high halfword product from the low halfword product.
2735   \param [in]    x   first 16-bit operands for each multiplication.
2736   \param [in]    y   second 16-bit operands for each multiplication.
2737   \return        the difference of the products of the two 16-bit signed multiplications.
2738   \remark
2739                  p1 = val1[15:0]  * val2[15:0]      \n
2740                  p2 = val1[31:16] * val2[31:16]     \n
2741                  res[31:0] = p1 - p2
2742  */
__SMUSD(uint32_t x,uint32_t y)2743 __ALWAYS_STATIC_INLINE uint32_t __SMUSD(uint32_t x, uint32_t y)
2744 {
2745     return ((uint32_t)(((((int32_t)x << 16) >> 16) * (((int32_t)y << 16) >> 16)) -
2746                        ((((int32_t)x) >> 16) * (((int32_t)y) >> 16))));
2747 }
2748 
2749 /**
2750   \brief   Dual extracted 8-bit to 16-bit signed addition.
2751   \details This function enables you to extract two 8-bit values from the second operand (at bit positions
2752            [7:0] and [23:16]), sign-extend them to 16-bits each, and add the results to the first operand.
2753   \param [in]    x   values added to the sign-extended to 16-bit values.
2754   \param [in]    y   two 8-bit values to be extracted and sign-extended.
2755   \return        the addition of val1 and val2, where the 8-bit values in val2[7:0] and
2756                  val2[23:16] have been extracted and sign-extended prior to the addition.
2757   \remark
2758                  res[15:0]  = val1[15:0] + SignExtended(val2[7:0])      \n
2759                  res[31:16] = val1[31:16] + SignExtended(val2[23:16])
2760  */
__SXTAB16(uint32_t x,uint32_t y)2761 __ALWAYS_STATIC_INLINE uint32_t __SXTAB16(uint32_t x, uint32_t y)
2762 {
2763     return ((uint32_t)((((((int32_t)y << 24) >> 24) + (((int32_t)x << 16) >> 16)) & (int32_t)0x0000FFFF) |
2764                        (((((int32_t)y <<  8) >>  8)  + (((int32_t)x >> 16) << 16)) & (int32_t)0xFFFF0000)));
2765 }
2766 
2767 /**
2768   \brief   Extracted 16-bit to 32-bit unsigned addition.
2769   \details This function enables you to extract two 8-bit values from one operand, zero-extend
2770            them to 16 bits each, and add the results to two 16-bit values from another operand.
2771   \param [in]    x   values added to the zero-extended to 16-bit values.
2772   \param [in]    y   two 8-bit values to be extracted and zero-extended.
2773   \return        the addition of val1 and val2, where the 8-bit values in val2[7:0] and
2774                  val2[23:16] have been extracted and zero-extended prior to the addition.
2775   \remark
2776                  res[15:0]  = ZeroExt(val2[7:0]   to 16 bits) + val1[15:0]      \n
2777                  res[31:16] = ZeroExt(val2[31:16] to 16 bits) + val1[31:16]
2778  */
__UXTAB16(uint32_t x,uint32_t y)2779 __ALWAYS_STATIC_INLINE uint32_t __UXTAB16(uint32_t x, uint32_t y)
2780 {
2781     return ((uint32_t)(((((y << 24) >> 24) + ((x << 16) >> 16)) & 0x0000FFFF) |
2782                        ((((y <<  8) >>  8) + ((x >> 16) << 16)) & 0xFFFF0000)));
2783 }
2784 
2785 /**
2786   \brief   Dual extract 8-bits and sign extend each to 16-bits.
2787   \details This function enables you to extract two 8-bit values from an operand and sign-extend them to 16 bits each.
2788   \param [in]    x   two 8-bit values in val[7:0] and val[23:16] to be sign-extended.
2789   \return        the 8-bit values sign-extended to 16-bit values.\n
2790                  sign-extended value of val[7:0] in the low halfword of the return value.\n
2791                  sign-extended value of val[23:16] in the high halfword of the return value.
2792   \remark
2793                  res[15:0]  = SignExtended(val[7:0])       \n
2794                  res[31:16] = SignExtended(val[23:16])
2795  */
__SXTB16(uint32_t x)2796 __ALWAYS_STATIC_INLINE uint32_t __SXTB16(uint32_t x)
2797 {
2798     return ((uint32_t)(((((int32_t)x << 24) >> 24) & (int32_t)0x0000FFFF) |
2799                        ((((int32_t)x <<  8) >>  8) & (int32_t)0xFFFF0000)));
2800 }
2801 
2802 /**
2803   \brief   Dual extract 8-bits and zero-extend to 16-bits.
2804   \details This function enables you to extract two 8-bit values from an operand and zero-extend them to 16 bits each.
2805   \param [in]    x   two 8-bit values in val[7:0] and val[23:16] to be zero-extended.
2806   \return        the 8-bit values sign-extended to 16-bit values.\n
2807                  sign-extended value of val[7:0] in the low halfword of the return value.\n
2808                  sign-extended value of val[23:16] in the high halfword of the return value.
2809   \remark
2810                  res[15:0]  = SignExtended(val[7:0])       \n
2811                  res[31:16] = SignExtended(val[23:16])
2812  */
__UXTB16(uint32_t x)2813 __ALWAYS_STATIC_INLINE uint32_t __UXTB16(uint32_t x)
2814 {
2815     return ((uint32_t)((((x << 24) >> 24) & 0x0000FFFF) |
2816                        (((x <<  8) >>  8) & 0xFFFF0000)));
2817 }
2818 
2819 #endif /* _CSI_RV32_GCC_H_ */
2820