iLLD_TC27xC  1.0
IfxCpu_IntrinsicsDcc.h
Go to the documentation of this file.
1 /**
2  * \file IfxCpu_IntrinsicsDcc.h
3  * \version iLLD_0_1_0_10
4  * \copyright Copyright (c) 2012 Infineon Technologies AG. All rights reserved.
5  *
6  *
7  *
8  * IMPORTANT NOTICE
9  *
10  *
11  * Infineon Technologies AG (Infineon) is supplying this file for use
12  * exclusively with Infineon's microcontroller products. This file can be freely
13  * distributed within development tools that are supporting such microcontroller
14  * products.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
17  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
19  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
20  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
21  *
22  * \defgroup IfxLld_Cpu_Intrinsics_Dcc intrinsics for DCC compiler
23  * \ingroup IfxLld_Cpu_Intrinsics
24  *
25  */
26 #ifndef IFXCPU_INTRINSICSDCC_H
27 #define IFXCPU_INTRINSICSDCC_H
28 /******************************************************************************/
29 #include "Ifx_Types.h"
30 
31 /******************************************************************************/
32 /* *INDENT-OFF* */
33 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_min_smax Minimum and Maximum of (Short) Integers
34  These intrinsic functions return the minimum or maximum of a signed integer, unsigned integer or short integer.
35  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
36  * \{
37  */
38 
39 /** Function call without return
40  */
41 asm volatile void __non_return_call(void (*fun)(void))
42 {
43 % reg fun
44  ji fun
45 }
46 
47 /** Jump and link
48  */
49 asm volatile void __jump_and_link(void (*fun)(void))
50 {
51 % reg fun
52  jli fun
53 }
54 
55 /** \} */
56 
57 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_any_type Cross type arithmetic operation
58  *
59  * Macro compatible with float, fix point, signed integer and unsigned integer
60  *
61  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
62  * \{
63  */
64 #define __minX(X,Y) ( ((X) < (Y)) ? (X) : (Y) )
65 #define __maxX(X,Y) ( ((X) > (Y)) ? (X) : (Y) )
66 #define __saturateX(X,Min,Max) ( __minX(__maxX(X, Min), Max) )
67 #define __checkrangeX(X,Min,Max) (((X) >= (Min)) && ((X) <= (Max)))
68 
69 
70 /** Return minimum of two integers
71  */
72 extern sint32 __min( sint32, sint32) __attribute__((intrinsic_pseudo(3, "min") ));
73 
74 /** Return minimum of two short integers
75  */
76 extern sint32 __mins( sint32, sint32) __attribute__((intrinsic_function(0x10b, 0, "min.h") ));
77 
78 /** Return minimum of two unsigned integers
79  */
80 extern uint32 __minu( uint32, uint32) __attribute__((intrinsic_pseudo(3, "min.u") ));
81 
82 /** Return maximum of two integers
83  */
84 extern sint32 __max( sint32, sint32) __attribute__((intrinsic_pseudo(3, "max") ));
85 
86 /** Return maximum of two short integers
87  */
88 extern uint32 __maxs( uint32, uint32) __attribute__((intrinsic_function(0x10b, 0, "max.h") ));
89 
90 /** Return maximum of two unsigned integers
91  */
92 extern uint32 __maxu( uint32, uint32) __attribute__((intrinsic_pseudo(3, "max.u") ));
93 
94 /** \} */
95 
96 /** \defgroup intrinsicstasking_float Floating point operation
97  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
98  * \{
99  */
100 #define __saturate(X,Min,Max) ( __minf(__maxf(X, Min), Max) )
101 
102 #define __sqrf(X) ((X) * (X))
103 #define __sqrtf(X) sqrtf(X)
104 #define __checkrange(X,Min,Max) (((X) >= (Min)) && ((X) <= (Max)))
105 
106 #define __roundf(X) ((((X) - (sint32)(X)) > 0.5) ? (1 + (sint32)(X)) : ((sint32)(X)))
107 #define __absf(X) ( ((X) < 0.0) ? -(X) : (X) )
108 #define __minf(X,Y) ( ((X) < (Y)) ? (X) : (Y) )
109 #define __maxf(X,Y) ( ((X) > (Y)) ? (X) : (Y) )
110 #define __saturatef(X,Min,Max) ( __minf(__maxf(X, Min), Max) )
111 #define __checkrangef(X,Min,Max) (((X) >= (Min)) && ((X) <= (Max)))
112 
113 #define __abs_stdreal(X) ( ((X) > 0.0) ? (X) : -(X) )
114 #define __min_stdreal(X,Y) ( ((X) < (Y)) ? (X) : (Y) )
115 #define __max_stdreal(X,Y) ( ((X) > (Y)) ? (X) : (Y) )
116 #define __saturate_stdreal(X,Min,Max) ( __min_stdreal(__max_stdreal(X, Min), Max) )
117 
118 #define __neqf(X,Y) ( ((X) > (Y)) || ((X) < (Y)) ) /**< X != Y */
119 #define __leqf(X,Y) ( !((X) > (Y)) ) /**< X <= Y */
120 #define __geqf(X,Y) ( !((X) < (Y)) ) /**< X >= Y */
121 /** \} */
122 
123 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_fractional Fractional Arithmetic Support
124  The next table provides an overview of intrinsic functions to convert fractional values. Note that the
125  TASKING VX-toolset C compiler for TriCore fully supports the fractional type so normally you should not
126  need these intrinsic functions (except for __mulfractlong). For compatibility reasons the TASKING C
127  compiler does support these functions.
128  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
129  * \{
130  */
131 
132 /** Count the consecutive number of bits that have the same value as bit 15 of an sfract
133  */
134 asm short __clssf(sfract a)
135 {
136 % reg a
137 ! "%d2"
138  cls %d2, a
139 }
140 
141 /** Convert float to fract
142  */
144 {
145 % reg a
146 ! "%d2"
147  ftoq31 %d2, a, 0
148 }
149 
150 /** \brief Convert fract to float
151  */
153 {
154 % reg a
155 ! "%d2", "%d3"
156  mov %d3, 0
157  q31tof %d2, a, %d3
158 }
159 
160 /** Convert __laccum to fract
161  */
163 {
164 % reg a
165 ! "%d2"
166  dextr %d2, a!H, a!L, 17
167 }
168 
169 /** Multiply-add with rounding. Returns the rounded result of ( a + b * c )
170  */
171 #ifdef INTRINSIC_WORKAROUND
172 extern sfract __mac_r_sf(sfract a, sfract b, sfract c);
173 #else
175 {
176 % reg a, b, c
177 ! "%d2"
178  maddrs.q %d2, a, bU, cU, 1
179 }
180 #endif
181 
182 /** Multiply-add sfract. Returns ( a + b * c )
183  */
184 #ifdef INTRINSIC_WORKAROUND
185 extern sfract __mac_sf(sfract a, sfract b, sfract c);
186 #else
188 {
189 % reg a, b, c
190 ! "%d2"
191  madds.q %d2, a, bU, cU, 1
192 }
193 #endif
194 
195 /** Integer part of the multiplication of a fract and a fract
196  */
198 {
199 % reg a, b
200 ! "%d2"
201  mul.q %d2, a, b, 1
202 }
203 
204 /** Integer part of the multiplication of a fract and a long
205  */
206 asm long __mulfractlong(fract a, long b)
207 {
208 % reg a, b
209 ! "%d2"
210  mul.q %d2, a, b, 1
211 }
212 
213 /** Convert fract to sfract
214  */
216 {
217 % reg a
218 ! "%d2"
219  mov.u %d2, 0x8000
220  adds %d2, a
221  insert %d2, %d0, 0, 0, 0x10
222 }
223 
224 /** Convert signed short to sfract
225  */
227 {
228 % reg a
229 ! "%d2"
230  sh %d2, a, 16
231 }
232 
233 /** Convert sfract to signed short
234  */
236 {
237 % reg a
238  sh %d2, a, -16
239 }
240 
241 /** Convert sfract to uint16
242  */
244 {
245 % reg a
246 ! "%d2"
247  sh %d2, a, -16
248 }
249 
250 /** Left/right shift of an __laccum
251  */
252 asm laccum __shaaccum(laccum a, sint32 b)
253 {
254 % lab L0, L1; reg a, b
255 ! "%d2", "%d3"
256  jge b, 0, L0
257  sha %d3, a!L, b
258  rsub b, b, 0
259  dextr %d2, a!H, a!L, b
260  j L1
261 L0:
262  dextr %d2, a!H, a!L, b
263  sha %d2, a!L, b
264 L1:
265 }
266 
267 /** Left/right shift of an fract
268  */
269 #ifdef INTRINSIC_WORKAROUND
270 extern fract __shafracts(fract a, sint32 b);
271 #else
272 asm fract __shafracts(fract a, sint32 b)
273 {
274 % reg a, b
275 ! "%d2"
276  shas %d2, a, b
277 }
278 #endif
279 
280 /** Left/right shift of an sfract
281  */
282 #ifdef INTRINSIC_WORKAROUND
283 extern sfract __shasfracts(sfract a, sint32 b);
284 #else
285 asm sfract __shasfracts(sfract a, sint32 b)
286 {
287 % reg a, b
288 ! "%d2"
289  shas %d2, a, b
290 }
291 #endif
292 
293 /** Convert uint16 to sfract
294  */
296 {
297 % reg a
298 ! "%d2"
299  sh %d2, a, 16
300 }
301 
302 /** \} */
303 
304 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_insert Insert / Extract Bit-fields and Bits
305  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
306  * \{
307  */
308 
309 /** Extract a bit-field (bit pos to bit pos+width) from value
310  */
311 extern sint32 __extr( sint32, uint32, const uint32) __attribute__((intrinsic_function(0x108, 0, "extr") ));
312 
313 /** Same as __extr() but return bit-field as unsigned integer
314  */
315 extern uint32 __extru( uint32, uint32, const uint32) __attribute__((intrinsic_function(0x108, 0, "extr.u") ));
316 
317 /** Load a single bit.
318  */
319 #define __getbit( address, bitoffset ) __extru( *(address), bitoffset, 1 )
320 
321 /** Return trg but replace trgbit by srcbit in src.
322  */
323 extern uint32 __ins( uint32, const uint32, uint32, const uint32) __attribute__((intrinsic_function(0x121, 0, "ins.t") ));
324 
325 /** Extract bit-field (width w bits starting at bit 0) from a and insert it in
326  * b at position p.
327  */
328 extern uint32 __insert( uint32, uint32, uint32, const uint32) __attribute__((intrinsic_function(0x109, 0, "insert") ));
329 
330 /** Return trg but replace trgbit by inverse of srcbit in src.
331  */
332 extern uint32 __insn( uint32, const uint32, uint32, const uint32) __attribute__((intrinsic_function(0x121, 0, "insn.t") ));
333 
334 /** Atomic load-modify-store.
335  */
336 #ifdef INTRINSIC_WORKAROUND
337 extern void __imaskldmst(uint32* a, sint32 b, sint32 p, const sint32 w);
338 #else
339 asm volatile void __imaskldmst(uint32* a, sint32 b, sint32 p, const sint32 w)
340 {
341 % reg a, b, p; con w
342 ! "%d2", "%d3"
343  imask %e2, b, p, w
344  ldmst [a]0, %e2
345 }
346 #endif
347 
348 /** Store a single bit.
349  */
350 #define __putbit(value,address,bitoffset) __imaskldmst(address,value,bitoffset,1)
351 
352 /** \} */
353 
354 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_interrupt_handling Interrupt Handling
355  The next table provides an overview of the intrinsic functions to read or set interrupt handling.
356  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
357  * \{
358  */
359 
360 /** Set CPU priority number [0..255] (or [0..1023] for TriCore 1.6.x) and enable interrupts immediately at function entry
361  */
362 extern void __bisr( const uint32) __attribute__((intrinsic_function(0x100, 0, "bisr") ));
363 
364 /** Disable interrupts. Only supported for TriCore1
365  */
366 extern void __disable( void) __attribute__((intrinsic_function(0x103, 0, "disable") ));
367 
368 /** Disable interrupts and return previous interrupt state (enabled or disabled). Direct supported for TriCore1.6. Emulated on TC1.3.1
369  */
370 #if defined INTRINSIC_WORKAROUND
371 extern sint32 __disable_and_save(void);
372 #endif
373 
374 /** Enable interrupts immediately at function entry
375  */
376 extern void __enable( void) __attribute__((intrinsic_function(0x103, 0, "enable") ));
377 
378 /** Restore interrupt state. Direct supported for TriCore1.6. Emulated on TC1.3.1
379  */
380 extern void __restore( sint32) __attribute__((intrinsic_function(0x104, 0, "restore") ));
381 
382 /** Call a system call function number
383  */
384 extern void __syscall( const uint32) __attribute__((intrinsic_function(0x100, 0, "syscall") ));
385 
386 /** \} */
387 
388 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_miscellaneous Miscellaneous Intrinsic Functions
389  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
390  * \{
391  */
392 
393 /** Write back and invalidate cache address "p". Generates CACHEA.WI [Ab].
394  */
395 extern void __cacheawi( void*) __attribute__((intrinsic_function(0x110, 0, "cachea.wi") ));
396 
397 /** Write back and invalidate cache address \"p\" and return post incremented
398  * value of \"p\". Generates CACHEA.WI [Ab+].
399  */
401 {
402 % reg p
403 !
404  cachea.wi [p + ]0
405  mov.aa %a2, p
406 }
407 
408 /** Write back and invalidate cache index "p". Generates CACHEI.WI [Ab].
409  */
410 asm volatile void __cacheiwi(uint8* p)
411 {
412 % reg p
413 !
414  cachei.wi [p]
415 }
416 
417 /** Initialize a circular pointer with a dynamically allocated buffer at run-time.
418  */
419 asm circ_t __initcirc(void* buf, uint16 bufsize, uint16 byteindex)
420 {
421 % reg buf, bufsize, byteindex
422 ! "%a2", "%a3"
423  lea %a2, [buf]0
424  extr.u bufsize, bufsize, 0, 16
425  insert bufsize, byteindex, bufsize, 16, 16
426  mov.a %a3, bufsize
427 }
428 
429 /** Multiply two 32-bit numbers to an intermediate 64-bit result, and scale
430  * back the result to 32 bits. To scale back the result, 32 bits are extracted
431  * from the intermediate 64-bit result: bit 63-offset to bit 31-offset.
432  */
433 asm volatile sint32 __mulsc(sint32 a, sint32 b, sint32 offset)
434 {
435 % reg a, b, offset
436 ! "%d2", "%d3"
437  mul %e2, a, b
438  dextr %d2, %d3, %d2, offset
439 }
440 
441 /** Rotate operand left count times. The bits that are shifted out are inserted at the right side (bit 31 is shifted to bit 0).
442  */
443 asm volatile uint32 __rol(uint32 operand, uint32 count)
444 {
445 % reg operand, count
446 ! "%d2"
447  dextr %d2, operand, operand, count
448 }
449 
450 /** Rotate operand right count times. The bits that are shifted out are inserted at the left side (bit 0 is shifted to bit 31).
451  */
452 asm volatile uint32 __ror(uint32 operand, uint32 count)
453 {
454 % reg operand, count
455 ! "%d2"
456  rsub count, count, 0
457  dextr %d2, operand, operand, count
458 }
459 
460 /** \} */
461 
462 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_packed Packed Data Type Support
463  The next table provides an overview of the intrinsic functions for initialization of packed data type.
464  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
465  * \{
466  */
467 
468 /** Absolute value of __packb
469 */
471 {
472 % reg a
473 ! "%d2"
474  abs.b %d2, a
475 }
476 
477 /** Absolute value of __packhw
478  */
480 {
481 % reg a
482 ! "%d2"
483  abs.h %d2, a
484 }
485 
486 /** Absolute value of __packhw using saturation
487  */
489 {
490 % reg a
491 ! "%d2"
492  abss.h %d2, a
493 }
494 
495 /** \brief Extract first byte from a __packb
496  */
498 {
499 % reg a
500 ! "%d2"
501  extr %d2, a, 0, 8
502 }
503 
504 /** \brief Extract second byte from a __packb
505  */
507 {
508 % reg a
509 ! "%d2"
510  extr %d2, a, 8, 8
511 }
512 
513 /** \brief Extract third byte from a __packb
514  */
516 {
517 % reg a
518 ! "%d2"
519  extr %d2, a, 16, 8
520 }
521 
522 /** \brief Extract fourth byte from a __packb
523  */
525 {
526 % reg a
527 ! "%d2"
528  extr %d2, a, 24, 8
529 }
530 
531 /** \brief Extract first short from a __packhw
532  */
534 {
535 % reg a
536 ! "%d2"
537  extr %d2, a, 0, 16
538 }
539 
540 /** \brief Extract second short from a __packhw
541  */
543 {
544 % reg a
545 ! "%d2"
546  extr %d2, a, 16, 16
547 }
548 
549 /** Extract first unsigned byte from a __packb
550  */
552 {
553 % reg a
554 ! "%d2"
555  extr %d2, a, 0, 8
556 }
557 
558 /** Extract second unsigned byte from a __packb
559  */
561 {
562 % reg a
563 ! "%d2"
564  extr %d2, a, 8, 8
565 }
566 
567 /** Extract third unsigned byte from a __packb
568  */
570 {
571 % reg a
572 ! "%d2"
573  extr %d2, a, 16, 8
574 }
575 
576 /** Extract fourth unsigned byte from a __packb
577  */
579 {
580 % reg a
581 ! "%d2"
582  extr %d2, a, 24, 8
583 }
584 
585 /** Extract first uint16 from a __packhw
586  */
588 {
589 % reg a
590 ! "%d2"
591  extr %d2, a, 0, 16
592 }
593 
594 /** Extract second uint16 from a __packhw
595  */
597 {
598 % reg a
599 ! "%d2"
600  extr %d2, a, 16, 16
601 }
602 
603 /** Extract first byte from a __packb
604  */
606 {
607 % reg a
608 ! "%d2"
609  ld.w %d2, [a]
610  extr %d2, %d2, 0, 8
611 }
612 
613 /** Extract second byte from a __packb
614  */
616 {
617 % reg a
618 ! "%d2"
619  ld.w %d2, [a]
620  extr %d2, %d2, 8, 8
621 }
622 
623 /** Extract third byte from a __packb
624  */
626 {
627 % reg a
628 ! "%d2"
629  ld.w %d2, [a]
630  extr %d2, %d2, 16, 8
631 }
632 
633 /** Extract fourth byte from a __packb
634  */
636 {
637 % reg a
638 ! "%d2"
639  ld.w %d2, [a]
640  extr %d2, %d2, 24, 8
641 }
642 
643 /** Extract first short from a __packhw
644  */
645 asm short __gethw1(__packhw* a)
646 {
647 % reg a
648 ! "%d2"
649  ld.w %d2, [a]
650  extr %d2, %d2, 0, 16
651 }
652 
653 /** Extract second short from a __packhw
654  */
655 asm short __gethw2(__packhw* a)
656 {
657 % reg a
658 ! "%d2"
659  ld.w %d2, [a]
660  extr %d2, %d2, 16, 16
661 }
662 
663 /** Extract first unsigned byte from a __packb
664  */
665 asm volatile uint8 __getubyte1(__upackb* a)
666 {
667 % reg a
668 ! "%d2"
669  ld.w %d2, [a]
670  extr %d2, %d2, 0, 8
671 }
672 
673 /** Extract second unsigned byte from a __packb
674  */
675 asm volatile uint8 __getubyte2(__upackb* a)
676 {
677 % reg a
678 ! "%d2"
679  ld.w %d2, [a]
680  extr %d2, %d2, 8, 8
681 }
682 
683 /** Extract third unsigned byte from a __packb
684  */
685 asm volatile uint8 __getubyte3(__upackb* a)
686 {
687 % reg a
688 ! "%d2"
689  ld.w %d2, [a]
690  extr %d2, %d2, 16, 8
691 }
692 
693 /** Extract fourth unsigned byte from a __packb
694  */
695 asm volatile uint8 __getubyte4(__upackb* a)
696 {
697 % reg a
698 ! "%d2"
699  ld.w %d2, [a]
700  extr %d2, %d2, 24, 8
701 }
702 
703 /** Extract first uint16 from a __packhw
704  */
705 asm volatile uint16 __getuhw1(__upackhw* a)
706 {
707 % reg a
708 ! "%d2"
709  ld.w %d2, [a]
710  extr %d2, %d2, 0, 16
711 }
712 
713 /** Extract second uint16 from a __packhw
714  */
715 asm volatile uint16 __getuhw2(__upackhw* a)
716 {
717 % reg a
718 ! "%d2"
719  ld.w %d2, [a]
720  extr %d2, %d2, 16, 16
721 }
722 
723 /** Initialize __packb with four integers
724  */
725 asm __packb __initpackb(sint32 a, sint32 b, sint32 c, sint32 d)
726 {
727 % reg a, b, c, d
728 ! "%d2"
729  insert c, c, d, 8, 8
730  insert d, a, b, 8, 8
731  insert %d2, d, c, 16, 16
732 }
733 
734 /** Initialize __packb with a long integer
735  */
737 {
738 % reg a
739 ! "%d2"
740  mov %d2, a
741 }
742 
743 /** \brief Initialize __packhw with two integers
744  */
745 asm __packhw __initpackhw(short a, short b)
746 {
747 % reg a, b
748 ! "%d2"
749  insert %d2, a, b, 16, 16
750 }
751 
752 /** Initialize __packhw with a long integer
753  */
755 {
756 % reg a
757 ! "%d2"
758  mov %d2, a
759 }
760 
761 /** Initialize __packb with four unsigned integers
762  */
763 asm __upackb __initupackb( uint32 a, uint32 b, uint32 c, uint32 d)
764 {
765 % reg a, b, c, d
766 ! "%d2"
767  insert c, c, d, 8, 8
768  insert a, a, b, 8, 8
769  insert %d2, a, c, 16, 16
770 }
771 
772 /** Initialize __packhw with two unsigned integers
773  */
775 {
776 % reg a, b
777 ! "%d2"
778  insert %d2, a, b, 16, 16
779 }
780 
781 /** \brief Insert sint8 into first byte of a __packb
782  */
784 {
785 % reg a, b
786 ! "%d2"
787  insert %d2, a, b, 0, 8
788 }
789 
790 /** \brief Insert sint8 into second byte of a __packb
791  */
793 {
794 % reg a, b
795 ! "%d2"
796  insert %d2, a, b, 8, 8
797 }
798 
799 /** \brief Insert sint8 into third byte of a __packb
800  */
802 {
803 % reg a, b
804 ! "%d2"
805  insert %d2, a, b, 16, 8
806 }
807 
808 /** \brief Insert sint8 into fourth byte of a __packb
809  */
811 {
812 % reg a, b
813 ! "%d2"
814  insert %d2, a, b, 24, 8
815 }
816 
817 /** Insert short into first halfword of a __packhw
818  */
820 {
821 % reg a, b
822 ! "%d2"
823  insert %d2, a, b, 0, 16
824 }
825 
826 /** Insert short into second halfword of a __packhw
827  */
829 {
830 % reg a, b
831 ! "%d2"
832  insert %d2, a, b, 16, 16
833 }
834 
835 /** \brief Insert uint8 into first unsigned byte of a __packb
836  */
838 {
839 % reg a, b
840 ! "%d2"
841  insert %d2, a, b, 0, 8
842 }
843 
844 /** \brief Insert uint8 into second unsigned byte of a __packb
845  */
847 {
848 % reg a, b
849 ! "%d2"
850  insert %d2, a, b, 8, 8
851 }
852 
853 /** \brief Insert uint8 into third unsigned byte of a __packb
854  */
856 {
857 % reg a, b
858 ! "%d2"
859  insert %d2, a, b, 16, 8
860 }
861 
862 /** \brief Insert uint8 into fourth unsigned byte of a __packb
863  */
865 {
866 % reg a, b
867 ! "%d2"
868  insert %d2, a, b, 24, 8
869 }
870 
871 /** Insert uint16 into first halfword of a __upackhw
872  */
874 {
875 % reg a, b
876 ! "%d2"
877  insert %d2, a, b, 0, 16
878 }
879 
880 /** Insert uint16 into second halfword of a __upackhw
881  */
883 {
884 % reg a, b
885 ! "%d2"
886  insert %d2, a, b, 16, 16
887 }
888 
889 /** Minimum of two __packb values
890  */
891 #ifdef INTRINSIC_WORKAROUND
892 extern __packb __minb(__packb a, __packb b);
893 #else
895 {
896 % reg a, b
897 ! "%d2"
898  min.b %d2, a, b
899 }
900 #endif
901 
902 /** Minimum of two __upackb values
903  */
905 {
906 % reg a, b
907 ! "%d2"
908  min.bu %d2, a, b
909 }
910 
911 /** Minimum of two __packhw values
912  */
914 {
915 % reg a, b
916 ! "%d2"
917  min.h %d2, a, b
918 }
919 
920 /** Minimum of two __upackhw values
921  */
923 {
924 % reg a, b
925 ! "%d2"
926  min.hu %d2, a, b
927 }
928 
929 /** Insert sint8 into first byte of a __packb
930  */
931 asm volatile void __setbyte1(__packb* a, sint8 b)
932 {
933 % reg a, b
934 ! "%d2"
935  ld.w %d2, [a]
936  insert %d2, %d2, b, 0, 8
937  st.w [a], %d2
938 }
939 
940 /** Insert sint8 into second byte of a __packb
941  */
942 asm volatile void __setbyte2(__packb* a, sint8 b)
943 {
944 % reg a, b
945 ! "%d2"
946  ld.w %d2, [a]
947  insert %d2, %d2, b, 8, 8
948  st.w [a], %d2
949 }
950 
951 /** Insert sint8 into third byte of a __packb
952  */
953 asm volatile void __setbyte3(__packb* a, sint8 b)
954 {
955 % reg a, b
956 ! "%d2"
957  ld.w %d2, [a]
958  insert %d2, %d2, b, 16, 8
959  st.w [a], %d2
960 }
961 
962 /** Insert sint8 into fourth byte of a __packb
963  */
964 asm volatile void __setbyte4(__packb* a, sint8 b)
965 {
966 % reg a, b
967 ! "%d2"
968  ld.w %d2, [a]
969  insert %d2, %d2, b, 24, 8
970  st.w [a], %d2
971 }
972 
973 /** Insert short into first halfword of a __packhw
974  */
975 asm volatile void __sethw1(__packhw* a, short b)
976 {
977 % reg a, b
978 ! "%d2"
979  ld.w %d2, [a]
980  insert %d2, %d2, b, 0, 16
981  st.w [a], %d2
982 }
983 
984 /** Insert short into second halfword of a __packhw
985  */
986 asm volatile void __sethw2(__packhw* a, short b)
987 {
988 % reg a, b
989 ! "%d2"
990  ld.w %d2, [a]
991  insert %d2, %d2, b, 16, 16
992  st.w [a], %d2
993 }
994 
995 /** Insert uint8 into first byte of a __upackb
996  */
997 asm volatile void __setubyte1(__upackb* a, uint8 b)
998 {
999 % reg a, b
1000 ! "%d2"
1001  ld.w %d2, [a]
1002  insert %d2, %d2, b, 0, 8
1003  st.w [a], %d2
1004 }
1005 
1006 /** Insert uint8 into second byte of a __upackb
1007  */
1008 asm volatile void __setubyte2(__upackb* a, uint8 b)
1009 {
1010 % reg a, b
1011 ! "%d2"
1012  ld.w %d2, [a]
1013  insert %d2, %d2, b, 8, 8
1014  st.w [a], %d2
1015 }
1016 
1017 /** Insert uint8 into third byte of a __upackb
1018  */
1019 asm volatile void __setubyte3(__upackb* a, uint8 b)
1020 {
1021 % reg a, b
1022 ! "%d2"
1023  ld.w %d2, [a]
1024  insert %d2, %d2, b, 16, 8
1025  st.w [a], %d2
1026 }
1027 
1028 /** Insert uint8 into fourth byte of a __upackb
1029  */
1030 asm volatile void __setubyte4(__upackb* a, uint8 b)
1031 {
1032 % reg a, b
1033 ! "%d2"
1034  ld.w %d2, [a]
1035  insert %d2, %d2, b, 24, 8
1036  st.w [a], %d2
1037 }
1038 
1039 /** Insert uint16 into first halfword of a __upackhw
1040  */
1041 asm volatile void __setuhw1(__upackhw* a, uint16 b)
1042 {
1043 % reg a, b
1044 ! "%d2"
1045  ld.w %d2, [a]
1046  insert %d2, %d2, b, 0, 16
1047  st.w [a], %d2
1048 }
1049 
1050 /** Insert uint16 into second halfword of a __upackhw
1051  */
1052 asm volatile void __setuhw2(__upackhw* a, uint16 b)
1053 {
1054 % reg a, b
1055 ! "%d2"
1056  ld.w %d2, [a]
1057  insert %d2, %d2, b, 16, 16
1058  st.w [a], %d2
1059 }
1060 
1061 /** \} */
1062 
1063 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_register Register Handling
1064  The next table provides an overview of the intrinsic functions that you can use to access control registers.
1065  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
1066  * \{
1067  */
1068 
1069 /** Return absolute value
1070  */
1071 extern sint32 __abs( sint32) __attribute__((intrinsic_pseudo(1, "abs") ));
1072 
1073 /** Return absolue difference of two integers
1074  */
1075 extern sint32 __absdif( sint32, sint32) __attribute__((intrinsic_pseudo(1, "absdif") ));
1076 
1077 /** Return absolute value with saturation
1078  */
1079 extern sint32 __abss( sint32) __attribute__((intrinsic_pseudo(1, "abss") ));
1080 
1081 /** Count leading ones in int
1082  */
1083 extern sint32 __clo( sint32) __attribute__((intrinsic_pseudo(1, "clo") ));
1084 
1085 /** Count number of redundant sign bits (all consecutive bits with the same value as bit 31
1086  */
1087 extern sint32 __cls( sint32) __attribute__((intrinsic_pseudo(1, "cls") ));
1088 
1089 /** Count leading zeros in int
1090  */
1091 extern sint32 __clz( sint32) __attribute__((intrinsic_pseudo(1, "clz") ));
1092 
1093 /** Return absolute double precision floating-point value
1094  */
1095 asm double __fabs(double d)
1096 {
1097 % reg d
1098 ! "%d2"
1099  insert %d2, d, 0, 31, 1
1100 }
1101 
1102 /** Return absolute floating-point value
1103  */
1104 asm float __fabsf(float f)
1105 {
1106 % reg f
1107 ! "%d2"
1108  insert %d2, f, 0, 31, 1
1109 }
1110 
1111 /** Move contents of the addressed core SFR into a data register
1112  */
1113 extern sint32 __mfcr( const uint32) __attribute__((intrinsic_function(0x101, 0, "mfcr") ));
1114 
1115 /** Move contents of a data register (second sint32) to the addressed core SFR (first sint32)
1116  */
1117 extern void __mtcr( const uint32, sint32) __attribute__((intrinsic_function(0x102, 0, "mtcr") ));
1118 
1119 /** Return parity
1120  */
1121 asm volatile sint32 __parity(sint32 a)
1122 {
1123 % reg a
1124 ! "%d2"
1125  parity %d2, a
1126 }
1127 
1128 /** Return saturated byte
1129  */
1130 asm sint8 __satb(sint32 a)
1131 {
1132 % reg a
1133 ! "%d2"
1134  sat.b %d2, a
1135 }
1136 
1137 /** Return saturated unsigned byte
1138  */
1139 asm volatile uint8 __satbu(sint32 a)
1140 {
1141 % reg a
1142 ! "%d2"
1143  sat.bu %d2, a
1144 }
1145 
1146 /** Return saturated halfword
1147  */
1148 asm short __sath(sint32 a)
1149 {
1150 % reg a
1151 ! "%d2"
1152  sat.h %d2, a
1153 }
1154 
1155 /** Return saturated unsignedhalfword
1156  */
1157 asm volatile uint16 __sathu(sint32 a)
1158 {
1159 % reg a
1160 ! "%d2"
1161  sat.hu %d2, a
1162 }
1163 
1164 /** \} */
1165 
1166 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_saturation Saturation Arithmetic Support
1167  These intrinsics support saturation arithmetic
1168  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
1169  * \{
1170  */
1171 /** add signed with saturation
1172  */
1173 extern sint32 __adds( sint32, sint32) __attribute__((intrinsic_pseudo(1, "adds") ));
1174 
1175 /** add unsigned with saturation
1176  */
1177 asm volatile uint32 __addsu(uint32 a, uint32 b)
1178 {
1179 % reg a, b
1180 ! "%d2"
1181  adds.u %d2, a, b
1182 }
1183 
1184 /** substract signed with saturation
1185  */
1186 asm volatile sint32 __subs(sint32 a, sint32 b)
1187 {
1188 % reg a, b
1189 ! "%d2"
1190  subs %d2, a, b
1191 }
1192 
1193 /** substract unsigned with saturation
1194  */
1195 asm volatile uint32 __subsu(uint32 a, uint32 b)
1196 {
1197 % reg a, b
1198 ! "%d2"
1199  subs.u %d2, a, b
1200 }
1201 
1202 /** \} */
1203 
1204 /** \defgroup IfxLld_Cpu_Intrinsics_Dcc_single_assembly Insert Single Assembly Instruction
1205  The next table provides an overview of the intrinsic functions that you can use to insert a single assembly
1206  instruction.You can also use inline assembly but these intrinsics provide a shorthand for frequently used
1207  assembly instructions.
1208  * \ingroup IfxLld_Cpu_Intrinsics_Dcc
1209  * \{
1210  */
1211 
1212 /** Insert DEBUG instruction
1213  */
1214 extern void __debug( void) __attribute__((intrinsic_function(0x103, 0, "debug") ));
1215 
1216 /** Insert DSYNC instruction
1217  */
1218 extern void __dsync( void) __attribute__((intrinsic_function(0x103, 0, "dsync") ));
1219 
1220 /** Insert ISYNC instruction
1221  */
1222 extern void __isync( void) __attribute__((intrinsic_function(0x103, 0, "isync") ));
1223 
1224 /** Insert LDMST instruction. Note that all operands must be word-aligned.
1225  */
1226 #ifdef INTRINSIC_WORKAROUND
1227 #define __ldmst __ldmst_c
1228 #else
1229 asm volatile void __ldmst(volatile void *address, uint32 mask, uint32 value)
1230 {
1231 %reg address, mask, value;
1232 !"%d2", "%d3"
1233  mov %d3, mask
1234  mov %d2, value
1235  ldmst [address],%e2
1236 }
1237 
1238 #endif
1239 
1240 /** Insert NOP instruction
1241  */
1242 extern void __nop( void) __attribute__((intrinsic_function(0x103, 0, "nop") ));
1243 
1244 /** Insert a loop over n NOP instruction
1245  */
1246 asm volatile void __nops(void* cnt)
1247 {
1248 % lab L0;
1249  reg cnt
1250  add.a cnt, -1
1251 L0:
1252  nop
1253  loop cnt, L0
1254 }
1255 
1256 /** Insert a loop over n times 1000 NOP instruction
1257  */
1258 asm volatile void __nops1000(uint32 x)
1259 {
1260 % reg x;
1261  lab L0, L1
1262 ! "%a2", "%a3"
1263  mov.a %a2, x
1264 L1:
1265  lea %a3, 999
1266 L0:
1267  nop
1268  nop
1269  loop %a3, L0
1270  loop %a2, L1
1271 }
1272 
1273 /** Insert RSLCX instruction
1274  */
1275 extern void __rslcx( void) __attribute__((intrinsic_function(0x103, 0, "rslcx") ));
1276 
1277 /** Insert SVLCX instruction
1278  */
1279 extern void __svlcx( void) __attribute__((intrinsic_function(0x103, 0, "svlcx") ));
1280 
1281 /** Insert SWAP instruction. Note that all operands must be word-aligned.
1282  */
1283 #ifdef INTRINSIC_WORKAROUND
1284 extern uint32 __swap(void* place, uint32 value);
1285 #else
1286 asm volatile uint32 __swap(void* place, uint32 value)
1287 {
1288 % reg place, value
1289 ! "%d2"
1290  mov %d2, value
1291  swap.w [place], %d2
1292 }
1293 #endif
1294 
1295 // FIXME
1296 asm volatile unsigned int __cmpAndSwap(unsigned int *address, unsigned long value, unsigned long CmpVal)
1297 {
1298 %reg value, address, CmpVal
1299 ! "%d0", "%d1"
1300  mov %d0,value
1301  mov %d1,CmpVal
1302  cmpswap.w %e0, [address]
1303 }
1304 /** \} */
1305 
1306 /** Insert n NOP instruction
1307  */
1308 //#info "NOP: Feature not yet implemented."
1309 
1310 #define __setareg(areg,val) ___setareg(areg,val)
1311 /* we need to use a15 for the address register and not direct that the compiler this will not remove */
1312 #define ___setareg(areg,val) \
1313  { __asm ("#$$bp"); \
1314  __asm (" movh.a\t %a15,"#val"@ha\n"); \
1315  __asm (" lea\t %a15,[%a15]"#val"@l\n"); \
1316  __asm (" mov.aa %"#areg", %a15\n"); \
1317  __asm ("#$$ep"); }
1318 
1319 /* FIXME check that the compiler take in account that d0 is used by the inline function */
1320 asm volatile void __stopPerfCounters(void)
1321 {
1322 ! "%d0"
1323  mov %d0,0
1324  mtcr 0xFC00,%d0
1325  isync
1326 }
1327 
1328 /* *INDENT-ON* */
1329 
1330 /******************************************************************************/
1331 #endif /* IFXCPU_INTRINSICSDCC_H */