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