1;//
2;//
3;// File Name:  armCOMM_s.h
4;// OpenMAX DL: v1.0.2
5;// Revision:   12290
6;// Date:       Wednesday, April 9, 2008
7;//
8;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
9;//
10;//
11;//
12;// ARM optimized OpenMAX common header file
13;//
14
15;// Protect against multiple inclusion
16 IF :LNOT::DEF:ARMCOMM_S_H
17 GBLL ARMCOMM_S_H
18
19        REQUIRE8            ;// Requires 8-byte stack alignment
20        PRESERVE8           ;// Preserves 8-byte stack alignment
21
22        GBLL    ARM_ERRORCHECK
23ARM_ERRORCHECK  SETL {FALSE}
24
25;// Globals
26
27        GBLS    _RRegList   ;// R saved register list
28        GBLS    _DRegList   ;// D saved register list
29        GBLS    _Variant    ;// Selected processor variant
30        GBLS    _CPU        ;// CPU name
31        GBLS    _Struct     ;// Structure name
32
33        GBLL    _InFunc     ;// Inside function assembly flag
34        GBLL    _SwLong     ;// Long switch flag
35
36        GBLA    _RBytes     ;// Number of register bytes on stack
37        GBLA    _SBytes     ;// Number of scratch bytes on stack
38        GBLA    _ABytes     ;// Stack offset of next argument
39        GBLA    _Workspace  ;// Stack offset of scratch workspace
40        GBLA    _F          ;// Function number
41        GBLA    _StOff      ;// Struct offset
42        GBLA    _SwNum      ;// Switch number
43        GBLS    _32         ;// Suffix for 32 byte alignmnet
44        GBLS    _16         ;// Suffix for 16 byte alignmnet
45
46_InFunc         SETL    {FALSE}
47_SBytes         SETA    0
48_F              SETA    0
49_SwNum          SETA    0
50_32             SETS    "ALIGN32"
51_16             SETS    "ALIGN16"
52
53;/////////////////////////////////////////////////////////
54;// Override the tools settings of the CPU if the #define
55;// USECPU is set, otherwise use the CPU defined by the
56;// assembler settings.
57;/////////////////////////////////////////////////////////
58
59       IF :DEF: OVERRIDECPU
60_CPU       SETS  OVERRIDECPU
61       ELSE
62_CPU       SETS    {CPU}
63       ENDIF
64
65
66
67;/////////////////////////////////////////////////////////
68;// Work out which code to build
69;/////////////////////////////////////////////////////////
70
71        IF :DEF:ARM1136JS:LOR::DEF:CortexA8:LOR::DEF:ARM_GENERIC
72            INFO 1,"Please switch to using M_VARIANTS"
73        ENDIF
74
75        ;// Define and reset all officially recongnised variants
76        MACRO
77        _M_DEF_VARIANTS
78        _M_DEF_VARIANT ARM926EJS
79        _M_DEF_VARIANT ARM1136JS
80        _M_DEF_VARIANT ARM1136JS_U
81        _M_DEF_VARIANT CortexA8
82        _M_DEF_VARIANT ARM7TDMI
83        MEND
84
85        MACRO
86        _M_DEF_VARIANT $var
87        GBLL $var
88        GBLL _ok$var
89$var    SETL {FALSE}
90        MEND
91
92
93        ;// Variant declaration
94        ;//
95        ;// Define a list of code variants supported by this
96        ;// source file. This macro then chooses the most
97        ;// appropriate variant to build for the currently configured
98        ;// core.
99        ;//
100        MACRO
101        M_VARIANTS $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7
102        ;// Set to TRUE variants that are supported
103        _M_DEF_VARIANTS
104        _M_VARIANT $v0
105        _M_VARIANT $v1
106        _M_VARIANT $v2
107        _M_VARIANT $v3
108        _M_VARIANT $v4
109        _M_VARIANT $v5
110        _M_VARIANT $v6
111        _M_VARIANT $v7
112
113        ;// Look for first available variant to match a CPU
114        ;// _M_TRY cpu, variant fall back list
115_Variant SETS ""
116        _M_TRY ARM926EJ-S,   ARM926EJS
117        _M_TRY ARM1176JZ-S,  ARM1136JS
118        _M_TRY ARM1176JZF-S, ARM1136JS
119        _M_TRY ARM1156T2-S,  ARM1136JS
120        _M_TRY ARM1156T2F-S, ARM1136JS
121        _M_TRY ARM1136J-S,   ARM1136JS
122        _M_TRY ARM1136JF-S,  ARM1136JS
123        _M_TRY MPCore,       ARM1136JS
124        _M_TRY falcon-vfp, ARM1136JS
125        _M_TRY falcon-full-neon, CortexA8
126        _M_TRY Cortex-A8NoNeon, ARM1136JS
127        _M_TRY Cortex-A8,    CortexA8, ARM1136JS
128        _M_TRY Cortex-R4,    ARM1136JS
129        _M_TRY ARM7TDMI
130
131        ;// Select the correct variant
132        _M_DEF_VARIANTS
133        IF _Variant=""
134            INFO 1, "No match found for CPU '$_CPU'"
135        ELSE
136$_Variant   SETL {TRUE}
137        ENDIF
138        MEND
139
140        ;// Register a variant as available
141        MACRO
142        _M_VARIANT $var
143        IF "$var"=""
144            MEXIT
145        ENDIF
146        IF :LNOT::DEF:_ok$var
147            INFO 1, "Unrecognized variant '$var'"
148        ENDIF
149$var    SETL {TRUE}
150        MEND
151
152        ;// For a given CPU, see if any of the variants supporting
153        ;// this CPU are available. The first available variant is
154        ;// chosen
155        MACRO
156        _M_TRY $cpu, $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7
157        IF "$cpu"<>_CPU
158            MEXIT
159        ENDIF
160        _M_TRY1 $v0
161        _M_TRY1 $v1
162        _M_TRY1 $v2
163        _M_TRY1 $v3
164        _M_TRY1 $v4
165        _M_TRY1 $v5
166        _M_TRY1 $v6
167        _M_TRY1 $v7
168        ;// Check a match was found
169        IF _Variant=""
170            INFO 1, "No variant match found for CPU '$_CPU'"
171        ENDIF
172        MEND
173
174        MACRO
175        _M_TRY1 $var
176        IF "$var"=""
177            MEXIT
178        ENDIF
179        IF (_Variant=""):LAND:$var
180_Variant SETS "$var"
181        ENDIF
182        MEND
183
184;////////////////////////////////////////////////////////
185;// Structure definition
186;////////////////////////////////////////////////////////
187
188        ;// Declare a structure of given name
189        MACRO
190        M_STRUCT $sname
191_Struct SETS "$sname"
192_StOff  SETA 0
193        MEND
194
195        ;// Declare a structure field
196        ;// The field is called $sname_$fname
197        ;// $size   = the size of each entry, must be power of 2
198        ;// $number = (if provided) the number of entries for an array
199        MACRO
200        M_FIELD $fname, $size, $number
201        IF (_StOff:AND:($size-1))!=0
202_StOff      SETA _StOff + ($size - (_StOff:AND:($size-1)))
203        ENDIF
204$_Struct._$fname EQU _StOff
205        IF "$number"<>""
206_StOff      SETA _StOff + $size*$number
207        ELSE
208_StOff      SETA _StOff + $size
209        ENDIF
210        MEND
211
212
213        MACRO
214        M_ENDSTRUCT
215sizeof_$_Struct EQU _StOff
216_Struct SETS ""
217        MEND
218
219;//////////////////////////////////////////////////////////
220;// Switch and table macros
221;//////////////////////////////////////////////////////////
222
223        ;// Start a relative switch table with register to switch on
224        ;//
225        ;// $v = the register to switch on
226        ;// $s = if specified must be "L" to indicate long
227        ;//      this allows a greater range to the case code
228        MACRO
229        M_SWITCH $v, $s
230        ASSERT "$s"="":LOR:"$s"="L"
231_SwLong SETL {FALSE}
232        IF "$s"="L"
233_SwLong     SETL {TRUE}
234        ENDIF
235_SwNum  SETA _SwNum+1
236        IF {CONFIG}=16
237            ;// Thumb
238            IF _SwLong
239                TBH [pc, $v, LSL#1]
240            ELSE
241                TBB [pc, $v]
242            ENDIF
243_Switch$_SwNum
244        ELSE
245            ;// ARM
246            ADD pc, pc, $v, LSL #2
247            NOP
248        ENDIF
249        MEND
250
251        ;// Add a case to the switch statement
252        MACRO
253        M_CASE  $label
254        IF {CONFIG}=16
255            ;// Thumb
256            IF _SwLong
257                DCW ($label - _Switch$_SwNum)/2
258            ELSE
259                DCB ($label - _Switch$_SwNum)/2
260            ENDIF
261        ELSE
262            ;// ARM
263            B   $label
264        ENDIF
265        MEND
266
267        ;// End of switch statement
268        MACRO
269        M_ENDSWITCH
270        ALIGN 2
271        MEND
272
273
274;////////////////////////////////////////////////////////
275;// Data area allocation
276;////////////////////////////////////////////////////////
277
278        ;// Constant table allocator macro
279        ;//
280        ;// Creates a new section for each constant table
281        ;// $name is symbol through which the table can be accessed.
282        ;// $align is the optional alignment of the table, log2 of
283        ;//  the byte alignment - $align=4 is 16 byte aligned
284        MACRO
285        M_TABLE  $name, $align
286        ASSERT :LNOT:_InFunc
287        IF "$align"=""
288            AREA |.constdata|, READONLY, DATA
289        ELSE
290            ;// AREAs inherit the alignment of the first declaration.
291            ;// Therefore for each alignment size we must have an area
292            ;// of a different name.
293            AREA constdata_a$align, READONLY, DATA, ALIGN=$align
294
295            ;// We also force alignment incase we are tagging onto
296            ;// an already started area.
297            ALIGN (1<<$align)
298        ENDIF
299$name
300        MEND
301
302;/////////////////////////////////////////////////////
303;// Macros to allocate space on the stack
304;//
305;// These all assume that the stack is 8-byte aligned
306;// at entry to the function, which means that the
307;// 32-byte alignment macro needs to work in a
308;// bit more of a special way...
309;/////////////////////////////////////////////////////
310
311
312
313
314        ;// Allocate 1-byte aligned area of name
315        ;// $name size $size bytes.
316        MACRO
317        M_ALLOC1  $name, $size
318        ASSERT :LNOT:_InFunc
319$name$_F   EQU _SBytes
320_SBytes SETA _SBytes + ($size)
321        MEND
322
323        ;// Allocate 2-byte aligned area of name
324        ;// $name size $size bytes.
325        MACRO
326        M_ALLOC2  $name, $size
327        ASSERT :LNOT:_InFunc
328        IF (_SBytes:AND:1)!=0
329_SBytes     SETA _SBytes + (2 - (_SBytes:AND:1))
330        ENDIF
331$name$_F   EQU _SBytes
332_SBytes SETA _SBytes + ($size)
333        MEND
334
335        ;// Allocate 4-byte aligned area of name
336        ;// $name size $size bytes.
337        MACRO
338        M_ALLOC4  $name, $size
339        ASSERT :LNOT:_InFunc
340        IF (_SBytes:AND:3)!=0
341_SBytes     SETA _SBytes + (4 - (_SBytes:AND:3))
342        ENDIF
343$name$_F   EQU _SBytes
344_SBytes SETA _SBytes + ($size)
345        MEND
346
347        ;// Allocate 8-byte aligned area of name
348        ;// $name size $size bytes.
349        MACRO
350        M_ALLOC8  $name, $size
351        ASSERT :LNOT:_InFunc
352        IF (_SBytes:AND:7)!=0
353_SBytes     SETA _SBytes + (8 - (_SBytes:AND:7))
354        ENDIF
355$name$_F   EQU _SBytes
356_SBytes SETA _SBytes + ($size)
357        MEND
358
359
360        ;// Allocate 8-byte aligned area of name
361        ;// $name size ($size+16) bytes.
362        ;// The extra 16 bytes are later used to align the pointer to 16 bytes
363
364        MACRO
365        M_ALLOC16  $name, $size
366        ASSERT :LNOT:_InFunc
367        IF (_SBytes:AND:7)!=0
368_SBytes     SETA _SBytes + (8 - (_SBytes:AND:7))
369        ENDIF
370$name$_F$_16   EQU (_SBytes + 8)
371_SBytes SETA _SBytes + ($size) + 8
372        MEND
373
374        ;// Allocate 8-byte aligned area of name
375        ;// $name size ($size+32) bytes.
376        ;// The extra 32 bytes are later used to align the pointer to 32 bytes
377
378        MACRO
379        M_ALLOC32  $name, $size
380        ASSERT :LNOT:_InFunc
381        IF (_SBytes:AND:7)!=0
382_SBytes     SETA _SBytes + (8 - (_SBytes:AND:7))
383        ENDIF
384$name$_F$_32   EQU (_SBytes + 24)
385_SBytes SETA _SBytes + ($size) + 24
386        MEND
387
388
389
390
391        ;// Argument Declaration Macro
392        ;//
393        ;// Allocate an argument name $name
394        ;// size $size bytes
395        MACRO
396        M_ARG     $name, $size
397        ASSERT _InFunc
398$name$_F    EQU _ABytes
399_ABytes SETA _ABytes + ($size)
400        MEND
401
402;///////////////////////////////////////////////
403;// Macros to access stacked variables
404;///////////////////////////////////////////////
405
406        ;// Macro to perform a data processing operation
407        ;// with a constant second operand
408        MACRO
409        _M_OPC $op,$rd,$rn,$const
410        LCLA    _sh
411        LCLA    _cst
412_sh     SETA    0
413_cst    SETA    $const
414        IF _cst=0
415        $op $rd, $rn, #_cst
416            MEXIT
417        ENDIF
418        WHILE (_cst:AND:3)=0
419_cst        SETA _cst>>2
420_sh         SETA _sh+2
421        WEND
422        $op $rd, $rn, #(_cst:AND:0x000000FF)<<_sh
423        IF _cst>=256
424            $op $rd, $rd, #(_cst:AND:0xFFFFFF00)<<_sh
425        ENDIF
426        MEND
427
428        ;// Macro to perform a data access operation
429        ;// Such as LDR or STR
430        ;// The addressing mode is modified such that
431        ;// 1. If no address is given then the name is taken
432        ;//    as a stack offset
433        ;// 2. If the addressing mode is not available for the
434        ;//    state being assembled for (eg Thumb) then a suitable
435        ;//    addressing mode is substituted.
436        ;//
437        ;// On Entry:
438        ;// $i = Instruction to perform (eg "LDRB")
439        ;// $a = Required byte alignment
440        ;// $r = Register(s) to transfer (eg "r1")
441        ;// $a0,$a1,$a2. Addressing mode and condition. One of:
442        ;//     label {,cc}
443        ;//     [base]                    {,,,cc}
444        ;//     [base, offset]{!}         {,,cc}
445        ;//     [base, offset, shift]{!}  {,cc}
446        ;//     [base], offset            {,,cc}
447        ;//     [base], offset, shift     {,cc}
448        MACRO
449        _M_DATA $i,$a,$r,$a0,$a1,$a2,$a3
450        IF "$a0":LEFT:1="["
451            IF "$a1"=""
452                $i$a3   $r, $a0
453            ELSE
454                IF "$a0":RIGHT:1="]"
455                    IF "$a2"=""
456                        _M_POSTIND $i$a3, "$r", $a0, $a1
457                    ELSE
458                        _M_POSTIND $i$a3, "$r", $a0, "$a1,$a2"
459                    ENDIF
460                ELSE
461                    IF "$a2"=""
462                        _M_PREIND  $i$a3, "$r", $a0, $a1
463                    ELSE
464                        _M_PREIND  $i$a3, "$r", $a0, "$a1,$a2"
465                    ENDIF
466                ENDIF
467            ENDIF
468        ELSE
469            LCLA    _Offset
470_Offset     SETA    _Workspace + $a0$_F
471            ASSERT  (_Offset:AND:($a-1))=0
472            $i$a1   $r, [sp, #_Offset]
473        ENDIF
474        MEND
475
476        ;// Handle post indexed load/stores
477        ;// op  reg, [base], offset
478        MACRO
479        _M_POSTIND $i,$r,$a0,$a1
480        LCLS _base
481        LCLS _offset
482        IF {CONFIG}=16 ;// Thumb
483_base       SETS ("$a0":LEFT:(:LEN:"$a0"-1)):RIGHT:(:LEN:"$a0"-2)   ;// remove []
484_offset     SETS "$a1"
485            IF _offset:LEFT:1="+"
486_offset         SETS _offset:RIGHT:(:LEN:_offset-1)
487            ENDIF
488            $i  $r, $a0
489            IF _offset:LEFT:1="-"
490_offset         SETS _offset:RIGHT:(:LEN:_offset-1)
491                SUB $_base, $_base, $_offset
492            ELSE
493                ADD $_base, $_base, $_offset
494            ENDIF
495        ELSE ;// ARM
496            $i  $r, $a0, $a1
497        ENDIF
498        MEND
499
500        ;// Handle pre indexed load/store
501        ;// op  reg, [base, offset]{!}
502        MACRO
503        _M_PREIND $i,$r,$a0,$a1
504        LCLS _base
505        LCLS _offset
506        IF ({CONFIG}=16):LAND:(("$a1":RIGHT:2)="]!")
507_base       SETS "$a0":RIGHT:(:LEN:("$a0")-1)
508_offset     SETS "$a1":LEFT:(:LEN:("$a1")-2)
509            $i $r, [$_base, $_offset]
510            ADD $_base, $_base, $_offset
511        ELSE
512            $i  $r, $a0, $a1
513        ENDIF
514        MEND
515
516        ;// Load unsigned byte from stack
517        MACRO
518        M_LDRB  $r,$a0,$a1,$a2,$a3
519        _M_DATA "LDRB",1,$r,$a0,$a1,$a2,$a3
520        MEND
521
522        ;// Load signed byte from stack
523        MACRO
524        M_LDRSB $r,$a0,$a1,$a2,$a3
525        _M_DATA "LDRSB",1,$r,$a0,$a1,$a2,$a3
526        MEND
527
528        ;// Store byte to stack
529        MACRO
530        M_STRB  $r,$a0,$a1,$a2,$a3
531        _M_DATA "STRB",1,$r,$a0,$a1,$a2,$a3
532        MEND
533
534        ;// Load unsigned half word from stack
535        MACRO
536        M_LDRH  $r,$a0,$a1,$a2,$a3
537        _M_DATA "LDRH",2,$r,$a0,$a1,$a2,$a3
538        MEND
539
540        ;// Load signed half word from stack
541        MACRO
542        M_LDRSH $r,$a0,$a1,$a2,$a3
543        _M_DATA "LDRSH",2,$r,$a0,$a1,$a2,$a3
544        MEND
545
546        ;// Store half word to stack
547        MACRO
548        M_STRH  $r,$a0,$a1,$a2,$a3
549        _M_DATA "STRH",2,$r,$a0,$a1,$a2,$a3
550        MEND
551
552        ;// Load word from stack
553        MACRO
554        M_LDR   $r,$a0,$a1,$a2,$a3
555        _M_DATA "LDR",4,$r,$a0,$a1,$a2,$a3
556        MEND
557
558        ;// Store word to stack
559        MACRO
560        M_STR   $r,$a0,$a1,$a2,$a3
561        _M_DATA "STR",4,$r,$a0,$a1,$a2,$a3
562        MEND
563
564        ;// Load double word from stack
565        MACRO
566        M_LDRD  $r0,$r1,$a0,$a1,$a2,$a3
567        _M_DATA "LDRD",8,"$r0,$r1",$a0,$a1,$a2,$a3
568        MEND
569
570        ;// Store double word to stack
571        MACRO
572        M_STRD  $r0,$r1,$a0,$a1,$a2,$a3
573        _M_DATA "STRD",8,"$r0,$r1",$a0,$a1,$a2,$a3
574        MEND
575
576        ;// Get absolute address of stack allocated location
577        MACRO
578        M_ADR   $a, $b, $cc
579        _M_OPC  ADD$cc, $a, sp, (_Workspace + $b$_F)
580        MEND
581
582        ;// Get absolute address of stack allocated location and align the address to 16 bytes
583        MACRO
584        M_ADR16 $a, $b, $cc
585            _M_OPC  ADD$cc, $a, sp, (_Workspace + $b$_F$_16)
586
587            ;// Now align $a to 16 bytes
588            BIC$cc  $a,$a,#0x0F
589        MEND
590
591        ;// Get absolute address of stack allocated location and align the address to 32 bytes
592        MACRO
593        M_ADR32 $a, $b, $cc
594            _M_OPC  ADD$cc, $a, sp, (_Workspace + $b$_F$_32)
595
596            ;// Now align $a to 32 bytes
597            BIC$cc  $a,$a,#0x1F
598        MEND
599
600;//////////////////////////////////////////////////////////
601;// Function header and footer macros
602;//////////////////////////////////////////////////////////
603
604        ;// Function Header Macro
605        ;// Generates the function prologue
606        ;// Note that functions should all be "stack-moves-once"
607        ;// The FNSTART and FNEND macros should be the only places
608        ;// where the stack moves.
609        ;//
610        ;// $name  = function name
611        ;// $rreg  = ""   don't stack any registers
612        ;//          "lr" stack "lr" only
613        ;//          "rN" stack registers "r4-rN,lr"
614        ;// $dreg  = ""   don't stack any D registers
615        ;//          "dN" stack registers "d8-dN"
616        ;//
617        ;// Note: ARM Archicture procedure call standard AAPCS
618        ;// states that r4-r11, sp, d8-d15 must be preserved by
619        ;// a compliant function.
620        MACRO
621        M_START $name, $rreg, $dreg
622        ASSERT :LNOT:_InFunc
623        ASSERT "$name"!=""
624_InFunc SETL {TRUE}
625_RBytes SETA 0
626_Workspace SETA 0
627
628        ;// Create an area for the function
629        AREA    |.text|, CODE
630        EXPORT  $name
631$name   FUNCTION
632
633        ;// Save R registers
634        _M_GETRREGLIST $rreg
635        IF _RRegList<>""
636            STMFD   sp!, {$_RRegList, lr}
637        ENDIF
638
639        ;// Save D registers
640        _M_GETDREGLIST  $dreg
641        IF _DRegList<>""
642            VSTMFD  sp!, {$_DRegList}
643        ENDIF
644
645
646        ;// Ensure size claimed on stack is 8-byte aligned
647        IF ((_SBytes:AND:7)!=0)
648_SBytes     SETA _SBytes + (8 - (_SBytes:AND:7))
649        ENDIF
650
651        IF (_SBytes!=0)
652            _M_OPC SUB, sp, sp, _SBytes
653        ENDIF
654
655
656_ABytes SETA _SBytes + _RBytes - _Workspace
657
658
659        ;// Print function name if debug enabled
660        M_PRINTF "$name\n",
661        MEND
662
663        ;// Work out a list of R saved registers
664        MACRO
665        _M_GETRREGLIST $rreg
666        IF "$rreg"=""
667_RRegList   SETS ""
668            MEXIT
669        ENDIF
670        IF "$rreg"="lr":LOR:"$rreg"="r4"
671_RRegList   SETS "r4"
672_RBytes     SETA _RBytes+8
673            MEXIT
674        ENDIF
675        IF "$rreg"="r5":LOR:"$rreg"="r6"
676_RRegList   SETS "r4-r6"
677_RBytes     SETA _RBytes+16
678            MEXIT
679        ENDIF
680        IF "$rreg"="r7":LOR:"$rreg"="r8"
681_RRegList   SETS "r4-r8"
682_RBytes     SETA _RBytes+24
683            MEXIT
684        ENDIF
685        IF "$rreg"="r9":LOR:"$rreg"="r10"
686_RRegList   SETS "r4-r10"
687_RBytes     SETA _RBytes+32
688            MEXIT
689        ENDIF
690        IF "$rreg"="r11":LOR:"$rreg"="r12"
691_RRegList   SETS "r4-r12"
692_RBytes     SETA _RBytes+40
693            MEXIT
694        ENDIF
695        INFO 1, "Unrecognized saved r register limit '$rreg'"
696        MEND
697
698        ;// Work out a list of D saved registers
699        MACRO
700        _M_GETDREGLIST $dreg
701        IF "$dreg"=""
702_DRegList   SETS ""
703            MEXIT
704        ENDIF
705        IF "$dreg"="d8"
706_DRegList   SETS "d8"
707_RBytes     SETA _RBytes+8
708            MEXIT
709        ENDIF
710        IF "$dreg"="d9"
711_DRegList   SETS "d8-d9"
712_RBytes     SETA _RBytes+16
713            MEXIT
714        ENDIF
715        IF "$dreg"="d10"
716_DRegList   SETS "d8-d10"
717_RBytes     SETA _RBytes+24
718            MEXIT
719        ENDIF
720        IF "$dreg"="d11"
721_DRegList   SETS "d8-d11"
722_RBytes     SETA _RBytes+32
723            MEXIT
724        ENDIF
725        IF "$dreg"="d12"
726_DRegList   SETS "d8-d12"
727_RBytes     SETA _RBytes+40
728            MEXIT
729        ENDIF
730        IF "$dreg"="d13"
731_DRegList   SETS "d8-d13"
732_RBytes     SETA _RBytes+48
733            MEXIT
734        ENDIF
735        IF "$dreg"="d14"
736_DRegList   SETS "d8-d14"
737_RBytes     SETA _RBytes+56
738            MEXIT
739        ENDIF
740        IF "$dreg"="d15"
741_DRegList   SETS "d8-d15"
742_RBytes     SETA _RBytes+64
743            MEXIT
744        ENDIF
745        INFO 1, "Unrecognized saved d register limit '$dreg'"
746        MEND
747
748        ;// Produce function return instructions
749        MACRO
750        _M_RET $cc
751        IF _DRegList<>""
752            VPOP$cc {$_DRegList}
753        ENDIF
754        IF _RRegList=""
755            BX$cc lr
756        ELSE
757            LDM$cc.FD sp!, {$_RRegList, pc}
758        ENDIF
759        MEND
760
761        ;// Early Function Exit Macro
762        ;// $cc = condition to exit with
763        ;// (Example: M_EXIT EQ)
764        MACRO
765        M_EXIT  $cc
766        ASSERT  _InFunc
767        IF  _SBytes!=0
768            ;// Restore stack frame and exit
769            B$cc  _End$_F
770        ELSE
771            ;// Can return directly
772            _M_RET $cc
773        ENDIF
774        MEND
775
776        ;// Function Footer Macro
777        ;// Generates the function epilogue
778        MACRO
779        M_END
780        ASSERT _InFunc
781_InFunc SETL {FALSE}
782_End$_F
783
784        ;// Restore the stack pointer to its original value on function entry
785        IF _SBytes!=0
786            _M_OPC ADD, sp, sp, _SBytes
787        ENDIF
788        _M_RET
789        ENDFUNC
790
791        ;// Reset the global stack tracking variables back to their
792        ;// initial values, and increment the function count
793_SBytes        SETA 0
794_F             SETA _F+1
795        MEND
796
797
798;//==========================================================================
799;// Debug Macros
800;//==========================================================================
801
802        GBLL    DEBUG_ON
803DEBUG_ON SETL   {FALSE}
804        GBLL    DEBUG_STALLS_ON
805DEBUG_STALLS_ON SETL {FALSE}
806
807        ;//==========================================================================
808        ;// Debug call to printf
809        ;//  M_PRINTF $format, $val0, $val1, $val2
810        ;//
811        ;// Examples:
812        ;//  M_PRINTF "x=%08x\n", r0
813        ;//
814        ;// This macro preserves the value of all registers including the
815        ;// flags.
816        ;//==========================================================================
817
818        MACRO
819        M_PRINTF  $format, $val0, $val1, $val2
820        IF DEBUG_ON
821
822        IMPORT  printf
823        LCLA    nArgs
824nArgs	SETA    0
825
826        ;// save registers so we don't corrupt them
827        STMFD   sp!, {r0-r12, lr}
828
829        ;// Drop stack to give us some workspace
830        SUB     sp, sp, #16
831
832        ;// Save registers we need to print to the stack
833        IF "$val2" <> ""
834            ASSERT "$val1" <> ""
835            STR    $val2, [sp, #8]
836nArgs       SETA   nArgs+1
837        ENDIF
838        IF "$val1" <> ""
839            ASSERT "$val0" <> ""
840            STR    $val1, [sp, #4]
841nArgs	    SETA   nArgs+1
842        ENDIF
843        IF "$val0"<>""
844            STR    $val0, [sp]
845nArgs	    SETA   nArgs+1
846        ENDIF
847
848        ;// Now we are safe to corrupt registers
849        ADR     r0, %FT00
850        IF nArgs=1
851          LDR   r1, [sp]
852        ENDIF
853        IF nArgs=2
854          LDMIA sp, {r1,r2}
855        ENDIF
856        IF nArgs=3
857          LDMIA sp, {r1,r2,r3}
858        ENDIF
859
860        ;// print the values
861        MRS     r4, cpsr        ;// preserve flags
862        BL      printf
863        MSR     cpsr_f, r4      ;// restore flags
864        B       %FT01
86500      ;// string to print
866        DCB     "$format", 0
867        ALIGN
86801      ;// Finished
869        ADD     sp, sp, #16
870        ;// Restore registers
871        LDMFD	sp!, {r0-r12,lr}
872
873        ENDIF   ;// DEBUG_ON
874        MEND
875
876
877        ;// Stall Simulation Macro
878        ;// Inserts a given number of NOPs for the currently
879        ;//  defined platform
880        MACRO
881        M_STALL $plat1stall, $plat2stall, $plat3stall, $plat4stall, $plat5stall, $plat6stall
882        IF DEBUG_STALLS_ON
883            _M_STALL_SUB $plat1stall
884            _M_STALL_SUB $plat2stall
885            _M_STALL_SUB $plat3stall
886            _M_STALL_SUB $plat4stall
887            _M_STALL_SUB $plat5stall
888            _M_STALL_SUB $plat6stall
889        ENDIF
890        MEND
891
892        MACRO
893        _M_STALL_SUB $platstall
894        IF "$platstall"!=""
895            LCLA _pllen
896            LCLS _pl
897            LCLL _pllog
898_pllen      SETA :LEN:"$platstall"
899_pl         SETS "$platstall":LEFT:(_pllen - 2)
900            IF :DEF:$_pl
901                IF $_pl
902                    LCLS _st
903                    LCLA _stnum
904_st                 SETS "$platstall":RIGHT:1
905_stnum              SETA $_st
906                    WHILE _stnum>0
907			MOV sp, sp
908_stnum                  SETA _stnum - 1
909                    WEND
910                ENDIF
911            ENDIF
912        ENDIF
913        MEND
914
915
916
917;//==========================================================================
918;// Endian Invarience Macros
919;//
920;// The idea behind these macros is that if an array is
921;// loaded as words then the SMUL00 macro will multiply
922;// array elements 0 regardless of the endianess of the
923;// system. For little endian SMUL00=SMULBB, for big
924;// endian SMUL00=SMULTT and similarly for other packed operations.
925;//
926;//==========================================================================
927
928        MACRO
929        LIBI4   $comli, $combi, $a, $b, $c, $d, $cc
930        IF {ENDIAN}="big"
931        $combi.$cc $a, $b, $c, $d
932        ELSE
933        $comli.$cc $a, $b, $c, $d
934        ENDIF
935        MEND
936
937        MACRO
938        LIBI3   $comli, $combi, $a, $b, $c, $cc
939        IF {ENDIAN}="big"
940        $combi.$cc $a, $b, $c
941        ELSE
942        $comli.$cc $a, $b, $c
943        ENDIF
944        MEND
945
946        ;// SMLAxy macros
947
948        MACRO
949        SMLA00  $a, $b, $c, $d, $cc
950        LIBI4 SMLABB, SMLATT, $a, $b, $c, $d, $cc
951        MEND
952
953        MACRO
954        SMLA01  $a, $b, $c, $d, $cc
955        LIBI4 SMLABT, SMLATB, $a, $b, $c, $d, $cc
956        MEND
957
958        MACRO
959        SMLA0B  $a, $b, $c, $d, $cc
960        LIBI4 SMLABB, SMLATB, $a, $b, $c, $d, $cc
961        MEND
962
963        MACRO
964        SMLA0T  $a, $b, $c, $d, $cc
965        LIBI4 SMLABT, SMLATT, $a, $b, $c, $d, $cc
966        MEND
967
968        MACRO
969        SMLA10  $a, $b, $c, $d, $cc
970        LIBI4 SMLATB, SMLABT, $a, $b, $c, $d, $cc
971        MEND
972
973        MACRO
974        SMLA11  $a, $b, $c, $d, $cc
975        LIBI4 SMLATT, SMLABB, $a, $b, $c, $d, $cc
976        MEND
977
978        MACRO
979        SMLA1B  $a, $b, $c, $d, $cc
980        LIBI4 SMLATB, SMLABB, $a, $b, $c, $d, $cc
981        MEND
982
983        MACRO
984        SMLA1T  $a, $b, $c, $d, $cc
985        LIBI4 SMLATT, SMLABT, $a, $b, $c, $d, $cc
986        MEND
987
988        MACRO
989        SMLAB0  $a, $b, $c, $d, $cc
990        LIBI4 SMLABB, SMLABT, $a, $b, $c, $d, $cc
991        MEND
992
993        MACRO
994        SMLAB1  $a, $b, $c, $d, $cc
995        LIBI4 SMLABT, SMLABB, $a, $b, $c, $d, $cc
996        MEND
997
998        MACRO
999        SMLAT0  $a, $b, $c, $d, $cc
1000        LIBI4 SMLATB, SMLATT, $a, $b, $c, $d, $cc
1001        MEND
1002
1003        MACRO
1004        SMLAT1  $a, $b, $c, $d, $cc
1005        LIBI4 SMLATT, SMLATB, $a, $b, $c, $d, $cc
1006        MEND
1007
1008        ;// SMULxy macros
1009
1010        MACRO
1011        SMUL00  $a, $b, $c, $cc
1012        LIBI3 SMULBB, SMULTT, $a, $b, $c, $cc
1013        MEND
1014
1015        MACRO
1016        SMUL01  $a, $b, $c, $cc
1017        LIBI3 SMULBT, SMULTB, $a, $b, $c, $cc
1018        MEND
1019
1020        MACRO
1021        SMUL0B  $a, $b, $c, $cc
1022        LIBI3 SMULBB, SMULTB, $a, $b, $c, $cc
1023        MEND
1024
1025        MACRO
1026        SMUL0T  $a, $b, $c, $cc
1027        LIBI3 SMULBT, SMULTT, $a, $b, $c, $cc
1028        MEND
1029
1030        MACRO
1031        SMUL10  $a, $b, $c, $cc
1032        LIBI3 SMULTB, SMULBT, $a, $b, $c, $cc
1033        MEND
1034
1035        MACRO
1036        SMUL11  $a, $b, $c, $cc
1037        LIBI3 SMULTT, SMULBB, $a, $b, $c, $cc
1038        MEND
1039
1040        MACRO
1041        SMUL1B  $a, $b, $c, $cc
1042        LIBI3 SMULTB, SMULBB, $a, $b, $c, $cc
1043        MEND
1044
1045        MACRO
1046        SMUL1T  $a, $b, $c, $cc
1047        LIBI3 SMULTT, SMULBT, $a, $b, $c, $cc
1048        MEND
1049
1050        MACRO
1051        SMULB0  $a, $b, $c, $cc
1052        LIBI3 SMULBB, SMULBT, $a, $b, $c, $cc
1053        MEND
1054
1055        MACRO
1056        SMULB1  $a, $b, $c, $cc
1057        LIBI3 SMULBT, SMULBB, $a, $b, $c, $cc
1058        MEND
1059
1060        MACRO
1061        SMULT0  $a, $b, $c, $cc
1062        LIBI3 SMULTB, SMULTT, $a, $b, $c, $cc
1063        MEND
1064
1065        MACRO
1066        SMULT1  $a, $b, $c, $cc
1067        LIBI3 SMULTT, SMULTB, $a, $b, $c, $cc
1068        MEND
1069
1070        ;// SMLAWx, SMULWx macros
1071
1072        MACRO
1073        SMLAW0  $a, $b, $c, $d, $cc
1074        LIBI4 SMLAWB, SMLAWT, $a, $b, $c, $d, $cc
1075        MEND
1076
1077        MACRO
1078        SMLAW1  $a, $b, $c, $d, $cc
1079        LIBI4 SMLAWT, SMLAWB, $a, $b, $c, $d, $cc
1080        MEND
1081
1082        MACRO
1083        SMULW0  $a, $b, $c, $cc
1084        LIBI3 SMULWB, SMULWT, $a, $b, $c, $cc
1085        MEND
1086
1087        MACRO
1088        SMULW1  $a, $b, $c, $cc
1089        LIBI3 SMULWT, SMULWB, $a, $b, $c, $cc
1090        MEND
1091
1092        ;// SMLALxy macros
1093
1094
1095        MACRO
1096        SMLAL00  $a, $b, $c, $d, $cc
1097        LIBI4 SMLALBB, SMLALTT, $a, $b, $c, $d, $cc
1098        MEND
1099
1100        MACRO
1101        SMLAL01  $a, $b, $c, $d, $cc
1102        LIBI4 SMLALBT, SMLALTB, $a, $b, $c, $d, $cc
1103        MEND
1104
1105        MACRO
1106        SMLAL0B  $a, $b, $c, $d, $cc
1107        LIBI4 SMLALBB, SMLALTB, $a, $b, $c, $d, $cc
1108        MEND
1109
1110        MACRO
1111        SMLAL0T  $a, $b, $c, $d, $cc
1112        LIBI4 SMLALBT, SMLALTT, $a, $b, $c, $d, $cc
1113        MEND
1114
1115        MACRO
1116        SMLAL10  $a, $b, $c, $d, $cc
1117        LIBI4 SMLALTB, SMLALBT, $a, $b, $c, $d, $cc
1118        MEND
1119
1120        MACRO
1121        SMLAL11  $a, $b, $c, $d, $cc
1122        LIBI4 SMLALTT, SMLALBB, $a, $b, $c, $d, $cc
1123        MEND
1124
1125        MACRO
1126        SMLAL1B  $a, $b, $c, $d, $cc
1127        LIBI4 SMLALTB, SMLALBB, $a, $b, $c, $d, $cc
1128        MEND
1129
1130        MACRO
1131        SMLAL1T  $a, $b, $c, $d, $cc
1132        LIBI4 SMLALTT, SMLALBT, $a, $b, $c, $d, $cc
1133        MEND
1134
1135        MACRO
1136        SMLALB0  $a, $b, $c, $d, $cc
1137        LIBI4 SMLALBB, SMLALBT, $a, $b, $c, $d, $cc
1138        MEND
1139
1140        MACRO
1141        SMLALB1  $a, $b, $c, $d, $cc
1142        LIBI4 SMLALBT, SMLALBB, $a, $b, $c, $d, $cc
1143        MEND
1144
1145        MACRO
1146        SMLALT0  $a, $b, $c, $d, $cc
1147        LIBI4 SMLALTB, SMLALTT, $a, $b, $c, $d, $cc
1148        MEND
1149
1150        MACRO
1151        SMLALT1  $a, $b, $c, $d, $cc
1152        LIBI4 SMLALTT, SMLALTB, $a, $b, $c, $d, $cc
1153        MEND
1154
1155  ENDIF ;// ARMCOMM_S_H
1156
1157  END
1158