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