Home | History | Annotate | Download | only in api
      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
     37 ARM_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
    229 sizeof_$_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
    817 DEBUG_ON SETL   {FALSE}
    818         GBLL    DEBUG_STALLS_ON
    819 DEBUG_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
    838 nArgs	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]
    850 nArgs       SETA   nArgs+1
    851         ENDIF
    852         IF "$val1" <> ""
    853             ASSERT "$val0" <> ""
    854             STR    $val1, [sp, #4]
    855 nArgs	    SETA   nArgs+1
    856         ENDIF
    857         IF "$val0"<>""
    858             STR    $val0, [sp]
    859 nArgs	    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
    879 00      ;// string to print
    880         DCB     "$format", 0
    881         ALIGN
    882 01      ;// 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