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