Home | History | Annotate | Download | only in arm
      1 @// -*- Mode: asm; -*-
      2 @//
      3 @//  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      4 @//
      5 @//  Use of this source code is governed by a BSD-style license
      6 @//  that can be found in the LICENSE file in the root of the source
      7 @//  tree. An additional intellectual property rights grant can be found
      8 @//  in the file PATENTS.  All contributing project authors may
      9 @//  be found in the AUTHORS file in the root of the source tree.
     10 @//
     11 @//  This file was originally licensed as follows. It has been
     12 @//  relicensed with permission from the copyright holders.
     13 @//
     14 
     15 @//
     16 @// File Name:  armCOMM_s.h
     17 @// OpenMAX DL: v1.0.2
     18 @// Last Modified Revision:   13871
     19 @// Last Modified Date:       Fri, 09 May 2008
     20 @//
     21 @// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
     22 @//
     23 @//
     24 @//
     25 @// ARM optimized OpenMAX common header file
     26 @//
     27 
     28 	.set	_SBytes, 0	@ Number of scratch bytes on stack
     29 	.set	_Workspace, 0	@ Stack offset of scratch workspace
     30 
     31 	.set	_RRegList, 0	@ R saved register list (last register number)
     32 	.set	_DRegList, 0	@ D saved register list (last register number)
     33 
     34         @// Work out a list of R saved registers, and how much stack space is needed.
     35 	@// gas doesn't support setting a variable to a string, so we set _RRegList to
     36 	@// the register number.
     37 	.macro	_M_GETRREGLIST	rreg
     38 	.ifeqs "\rreg", ""
     39 	@ Nothing needs to be saved
     40 	.exitm
     41 	.endif
     42 	@ If rreg is lr or r4, save lr and r4
     43 	.ifeqs "\rreg", "lr"
     44 	.set	_RRegList, 4
     45 	.exitm
     46 	.endif
     47 
     48 	.ifeqs "\rreg", "r4"
     49 	.set	_RRegList, 4
     50 	.exitm
     51 	.endif
     52 
     53 	@ If rreg = r5 or r6, save up to register r6
     54 	.ifeqs "\rreg", "r5"
     55 	.set	_RRegList, 6
     56 	.exitm
     57 	.endif
     58 	.ifeqs "\rreg", "r6"
     59 	.set	_RRegList, 6
     60 	.exitm
     61 	.endif
     62 
     63 	@ If rreg = r7 or r8, save up to register r8
     64 	.ifeqs "\rreg", "r7"
     65 	.set	_RRegList, 8
     66 	.exitm
     67 	.endif
     68 	.ifeqs "\rreg", "r8"
     69 	.set	_RRegList, 8
     70 	.exitm
     71 	.endif
     72 
     73 	@ If rreg = r9 or r10, save up to register r10
     74 	.ifeqs "\rreg", "r9"
     75 	.set	_RRegList, 10
     76 	.exitm
     77 	.endif
     78 	.ifeqs "\rreg", "r10"
     79 	.set	_RRegList, 10
     80 	.exitm
     81 	.endif
     82 
     83 	@ If rreg = r11 or r12, save up to register r12
     84 	.ifeqs "\rreg", "r11"
     85 	.set	_RRegList, 12
     86 	.exitm
     87 	.endif
     88 	.ifeqs "\rreg", "r12"
     89 	.set	_RRegList, 12
     90 	.exitm
     91 	.endif
     92 
     93 	.warning "Unrecognized saved r register limit: \rreg"
     94 	.endm
     95 
     96 	@ Work out list of D saved registers, like for R registers.
     97 	.macro	_M_GETDREGLIST dreg
     98 	.ifeqs "\dreg", ""
     99 	.set	_DRegList, 0
    100 	.exitm
    101 	.endif
    102 
    103 	.ifeqs "\dreg", "d8"
    104 	.set	_DRegList, 8
    105 	.exitm
    106 	.endif
    107 
    108 	.ifeqs "\dreg", "d9"
    109 	.set	_DRegList, 9
    110 	.exitm
    111 	.endif
    112 
    113 	.ifeqs "\dreg", "d10"
    114 	.set	_DRegList, 10
    115 	.exitm
    116 	.endif
    117 
    118 	.ifeqs "\dreg", "d11"
    119 	.set	_DRegList, 11
    120 	.exitm
    121 	.endif
    122 
    123 	.ifeqs "\dreg", "d12"
    124 	.set	_DRegList, 12
    125 	.exitm
    126 	.endif
    127 
    128 	.ifeqs "\dreg", "d13"
    129 	.set	_DRegList, 13
    130 	.exitm
    131 	.endif
    132 
    133 	.ifeqs "\dreg", "d14"
    134 	.set	_DRegList, 14
    135 	.exitm
    136 	.endif
    137 
    138 	.ifeqs "\dreg", "d15"
    139 	.set	_DRegList, 15
    140 	.exitm
    141 	.endif
    142 
    143 	.warning "Unrecognized saved d register limit: \rreg"
    144 	.endm
    145 
    146 @//////////////////////////////////////////////////////////
    147 @// Function header and footer macros
    148 @//////////////////////////////////////////////////////////
    149 
    150         @ Function Header Macro
    151         @ Generates the function prologue
    152         @ Note that functions should all be "stack-moves-once"
    153         @ The FNSTART and FNEND macros should be the only places
    154         @ where the stack moves.
    155         @
    156         @  name  = function name
    157         @  rreg  = ""   don't stack any registers
    158         @          "lr" stack "lr" only
    159         @          "rN" stack registers "r4-rN,lr"
    160         @  dreg  = ""   don't stack any D registers
    161         @          "dN" stack registers "d8-dN"
    162         @
    163         @ Note: ARM Archicture procedure call standard AAPCS
    164         @ states that r4-r11, sp, d8-d15 must be preserved by
    165         @ a compliant function.
    166 	.macro	M_START name, rreg, dreg
    167 	.set	_Workspace, 0
    168 
    169 	@ Define the function and make it external.
    170 	.arm
    171 	.global	\name
    172 	.section	.text.\name,"ax",%progbits
    173 	.align	2
    174 \name :
    175 .fnstart
    176 	@ Save specified R registers
    177 	_M_GETRREGLIST	\rreg
    178 	_M_PUSH_RREG
    179 
    180 	@ Save specified D registers
    181         _M_GETDREGLIST  \dreg
    182 	_M_PUSH_DREG
    183 
    184 	@ Ensure size claimed on stack is 8-byte aligned
    185 	.if (_SBytes & 7) != 0
    186 	.set	_SBytes, _SBytes + (8 - (_SBytes & 7))
    187 	.endif
    188 	.if _SBytes != 0
    189 		sub	sp, sp, #_SBytes
    190 	.endif
    191 	.endm
    192 
    193         @ Function Footer Macro
    194         @ Generates the function epilogue
    195 	.macro M_END
    196 	@ Restore the stack pointer to its original value on function entry
    197 	.if _SBytes != 0
    198 		add	sp, sp, #_SBytes
    199 	.endif
    200 	@ Restore any saved R or D registers.
    201 	_M_RET
    202 	.fnend
    203         @ Reset the global stack tracking variables back to their
    204 	@ initial values.
    205 	.set _SBytes, 0
    206 	.endm
    207 
    208 	@// Based on the value of _DRegList, push the specified set of registers
    209 	@// to the stack.  Is there a better way?
    210 	.macro _M_PUSH_DREG
    211 	.if _DRegList == 8
    212 		vpush	{d8}
    213 	.exitm
    214 	.endif
    215 
    216 	.if _DRegList == 9
    217 		vpush	{d8-d9}
    218 	.exitm
    219 	.endif
    220 
    221 	.if _DRegList == 10
    222 		vpush	{d8-d10}
    223 	.exitm
    224 	.endif
    225 
    226 	.if _DRegList == 11
    227 		vpush	{d8-d11}
    228 	.exitm
    229 	.endif
    230 
    231 	.if _DRegList == 12
    232 		vpush	{d8-d12}
    233 	.exitm
    234 	.endif
    235 
    236 	.if _DRegList == 13
    237 		vpush	{d8-d13}
    238 	.exitm
    239 	.endif
    240 
    241 	.if _DRegList == 14
    242 		vpush	{d8-d14}
    243 	.exitm
    244 	.endif
    245 
    246 	.if _DRegList == 15
    247 		vpush	{d8-d15}
    248 	.exitm
    249 	.endif
    250 	.endm
    251 
    252 	@// Based on the value of _RRegList, push the specified set of registers
    253 	@// to the stack.  Is there a better way?
    254 	.macro _M_PUSH_RREG
    255 	.if _RRegList == 4
    256 		stmfd	sp!, {r4, lr}
    257 	.exitm
    258 	.endif
    259 
    260 	.if _RRegList == 6
    261 		stmfd	sp!, {r4-r6, lr}
    262 	.exitm
    263 	.endif
    264 
    265 	.if _RRegList == 8
    266 		stmfd	sp!, {r4-r8, lr}
    267 	.exitm
    268 	.endif
    269 
    270 	.if _RRegList == 10
    271 		stmfd	sp!, {r4-r10, lr}
    272 	.exitm
    273 	.endif
    274 
    275 	.if _RRegList == 12
    276 		stmfd	sp!, {r4-r12, lr}
    277 	.exitm
    278 	.endif
    279 	.endm
    280 
    281 	@// The opposite of _M_PUSH_DREG
    282 	.macro  _M_POP_DREG
    283 	.if _DRegList == 8
    284 		vpop	{d8}
    285 	.exitm
    286 	.endif
    287 
    288 	.if _DRegList == 9
    289 		vpop	{d8-d9}
    290 	.exitm
    291 	.endif
    292 
    293 	.if _DRegList == 10
    294 		vpop	{d8-d10}
    295 	.exitm
    296 	.endif
    297 
    298 	.if _DRegList == 11
    299 		vpop	{d8-d11}
    300 	.exitm
    301 	.endif
    302 
    303 	.if _DRegList == 12
    304 		vpop	{d8-d12}
    305 	.exitm
    306 	.endif
    307 
    308 	.if _DRegList == 13
    309 		vpop	{d8-d13}
    310 	.exitm
    311 	.endif
    312 
    313 	.if _DRegList == 14
    314 		vpop	{d8-d14}
    315 	.exitm
    316 	.endif
    317 
    318 	.if _DRegList == 15
    319 		vpop	{d8-d15}
    320 	.exitm
    321 	.endif
    322 	.endm
    323 
    324 	@// The opposite of _M_PUSH_RREG
    325 	.macro _M_POP_RREG cc
    326 	.if _RRegList == 0
    327 		bx\cc lr
    328 	.exitm
    329 	.endif
    330 	.if _RRegList == 4
    331 		ldm\cc\()fd	sp!, {r4, pc}
    332 	.exitm
    333 	.endif
    334 
    335 	.if _RRegList == 6
    336 		ldm\cc\()fd	sp!, {r4-r6, pc}
    337 	.exitm
    338 	.endif
    339 
    340 	.if _RRegList == 8
    341 		ldm\cc\()fd	sp!, {r4-r8, pc}
    342 	.exitm
    343 	.endif
    344 
    345 	.if _RRegList == 10
    346 		ldm\cc\()fd	sp!, {r4-r10, pc}
    347 	.exitm
    348 	.endif
    349 
    350 	.if _RRegList == 12
    351 		ldm\cc\()fd	sp!, {r4-r12, pc}
    352 	.exitm
    353 	.endif
    354 	.endm
    355 
    356         @ Produce function return instructions
    357 	.macro	_M_RET cc
    358 	_M_POP_DREG \cc
    359 	_M_POP_RREG \cc
    360 	.endm
    361 
    362         @// Allocate 4-byte aligned area of name
    363         @// |name| and size |size| bytes.
    364 	.macro	M_ALLOC4 name, size
    365 	.if	(_SBytes & 3) != 0
    366 	.set	_SBytes, _SBytes + (4 - (_SBytes & 3))
    367 	.endif
    368 	.set	\name\()_F, _SBytes
    369 	.set	_SBytes, _SBytes + \size
    370 
    371 	.endm
    372 
    373         @// Allocate 8-byte aligned area of name
    374         @// |name| and size |size| bytes.
    375 	.macro	M_ALLOC8 name, size
    376 	.if	(_SBytes & 7) != 0
    377 	.set	_SBytes, _SBytes + (8 - (_SBytes & 7))
    378 	.endif
    379 	.set	\name\()_F, _SBytes
    380 	.set	_SBytes, _SBytes + \size
    381 
    382 	.endm
    383 
    384         @ Load word from stack
    385 	.macro M_LDR r, a0, a1, a2, a3
    386 	_M_DATA "ldr", 4, \r, \a0, \a1, \a2, \a3
    387 	.endm
    388 
    389         @ Store word to stack
    390 	.macro M_STR r, a0, a1, a2, a3
    391 	_M_DATA "str", 4, \r, \a0, \a1, \a2, \a3
    392 	.endm
    393 
    394         @ Load double word from stack
    395 	.macro M_LDRD r0, r1, a0, a1, a2, a3
    396 	_M_DATA2 "ldrd", 8, \r0, \r1, \a0, \a1, \a2, \a3
    397 	.endm
    398 
    399         @ Store double word to stack
    400 	.macro M_STRD r0, r1, a0, a1, a2, a3
    401 	_M_DATA2 "strd", 8, \r0, \r1, \a0, \a1, \a2, \a3
    402 	.endm
    403 
    404         @ Macro to perform a data access operation
    405         @ Such as LDR or STR
    406         @ The addressing mode is modified such that
    407         @ 1. If no address is given then the name is taken
    408         @    as a stack offset
    409         @ 2. If the addressing mode is not available for the
    410         @    state being assembled for (eg Thumb) then a suitable
    411         @    addressing mode is substituted.
    412         @
    413         @ On Entry:
    414         @ $i = Instruction to perform (eg "LDRB")
    415         @ $a = Required byte alignment
    416         @ $r = Register(s) to transfer (eg "r1")
    417         @ $a0,$a1,$a2. Addressing mode and condition. One of:
    418         @     label {,cc}
    419         @     [base]                    {,,,cc}
    420         @     [base, offset]{!}         {,,cc}
    421         @     [base, offset, shift]{!}  {,cc}
    422         @     [base], offset            {,,cc}
    423         @     [base], offset, shift     {,cc}
    424 	@
    425 	@ WARNING: Most of the above are not supported, except the first case.
    426 	.macro _M_DATA i, a, r, a0, a1, a2, a3
    427 	.set	_Offset, _Workspace + \a0\()_F
    428 	\i\a1	\r, [sp, #_Offset]
    429 	.endm
    430 
    431         @ Macro to perform a data access operation
    432         @ Such as LDR or STR
    433         @ The addressing mode is modified such that
    434         @ 1. If no address is given then the name is taken
    435         @    as a stack offset
    436         @ 2. If the addressing mode is not available for the
    437         @    state being assembled for (eg Thumb) then a suitable
    438         @    addressing mode is substituted.
    439         @
    440         @ On Entry:
    441         @ $i = Instruction to perform (eg "LDRB")
    442         @ $a = Required byte alignment
    443         @ $r = Register(s) to transfer (eg "r1")
    444         @ $a0,$a1,$a2. Addressing mode and condition. One of:
    445         @     label {,cc}
    446         @     [base]                    {,,,cc}
    447         @     [base, offset]{!}         {,,cc}
    448         @     [base, offset, shift]{!}  {,cc}
    449         @     [base], offset            {,,cc}
    450         @     [base], offset, shift     {,cc}
    451 	@
    452 	@ WARNING: Most of the above are not supported, except the first case.
    453 	.macro _M_DATA2 i, a, r0, r1, a0, a1, a2, a3
    454 	.set	_Offset, _Workspace + \a0\()_F
    455 	\i\a1	\r0, \r1, [sp, #_Offset]
    456 	.endm
    457