Home | History | Annotate | Download | only in api
      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
     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 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
    212 sizeof_$_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
    800 DEBUG_ON SETL   {FALSE}
    801         GBLL    DEBUG_STALLS_ON
    802 DEBUG_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
    821 nArgs	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]
    833 nArgs       SETA   nArgs+1
    834         ENDIF
    835         IF "$val1" <> ""
    836             ASSERT "$val0" <> ""
    837             STR    $val1, [sp, #4]
    838 nArgs	    SETA   nArgs+1
    839         ENDIF
    840         IF "$val0"<>""
    841             STR    $val0, [sp]
    842 nArgs	    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
    862 00      ;// string to print
    863         DCB     "$format", 0
    864         ALIGN
    865 01      ;// 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