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