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