blob: 98fff3f27dffe6f63b719df3e091ac2566822176 [file] [log] [blame]
@// -*- Mode: asm; -*-
@//
@// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
@//
@// Use of this source code is governed by a BSD-style license
@// that can be found in the LICENSE file in the root of the source
@// tree. An additional intellectual property rights grant can be found
@// in the file PATENTS. All contributing project authors may
@// be found in the AUTHORS file in the root of the source tree.
@//
@// This file was originally licensed as follows. It has been
@// relicensed with permission from the copyright holders.
@//
@//
@// File Name: armCOMM_s.h
@// OpenMAX DL: v1.0.2
@// Last Modified Revision: 13871
@// Last Modified Date: Fri, 09 May 2008
@//
@// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
@//
@//
@//
@// ARM optimized OpenMAX common header file
@//
.set _SBytes, 0 @ Number of scratch bytes on stack
.set _Workspace, 0 @ Stack offset of scratch workspace
.set _RRegList, 0 @ R saved register list (last register number)
.set _DRegList, 0 @ D saved register list (last register number)
@// Work out a list of R saved registers, and how much stack space is needed.
@// gas doesn't support setting a variable to a string, so we set _RRegList to
@// the register number.
.macro _M_GETRREGLIST rreg
.ifeqs "\rreg", ""
@ Nothing needs to be saved
.exitm
.endif
@ If rreg is lr or r4, save lr and r4
.ifeqs "\rreg", "lr"
.set _RRegList, 4
.exitm
.endif
.ifeqs "\rreg", "r4"
.set _RRegList, 4
.exitm
.endif
@ If rreg = r5 or r6, save up to register r6
.ifeqs "\rreg", "r5"
.set _RRegList, 6
.exitm
.endif
.ifeqs "\rreg", "r6"
.set _RRegList, 6
.exitm
.endif
@ If rreg = r7 or r8, save up to register r8
.ifeqs "\rreg", "r7"
.set _RRegList, 8
.exitm
.endif
.ifeqs "\rreg", "r8"
.set _RRegList, 8
.exitm
.endif
@ If rreg = r9 or r10, save up to register r10
.ifeqs "\rreg", "r9"
.set _RRegList, 10
.exitm
.endif
.ifeqs "\rreg", "r10"
.set _RRegList, 10
.exitm
.endif
@ If rreg = r11 or r12, save up to register r12
.ifeqs "\rreg", "r11"
.set _RRegList, 12
.exitm
.endif
.ifeqs "\rreg", "r12"
.set _RRegList, 12
.exitm
.endif
.warning "Unrecognized saved r register limit: \rreg"
.endm
@ Work out list of D saved registers, like for R registers.
.macro _M_GETDREGLIST dreg
.ifeqs "\dreg", ""
.set _DRegList, 0
.exitm
.endif
.ifeqs "\dreg", "d8"
.set _DRegList, 8
.exitm
.endif
.ifeqs "\dreg", "d9"
.set _DRegList, 9
.exitm
.endif
.ifeqs "\dreg", "d10"
.set _DRegList, 10
.exitm
.endif
.ifeqs "\dreg", "d11"
.set _DRegList, 11
.exitm
.endif
.ifeqs "\dreg", "d12"
.set _DRegList, 12
.exitm
.endif
.ifeqs "\dreg", "d13"
.set _DRegList, 13
.exitm
.endif
.ifeqs "\dreg", "d14"
.set _DRegList, 14
.exitm
.endif
.ifeqs "\dreg", "d15"
.set _DRegList, 15
.exitm
.endif
.warning "Unrecognized saved d register limit: \rreg"
.endm
@//////////////////////////////////////////////////////////
@// Function header and footer macros
@//////////////////////////////////////////////////////////
@ Function Header Macro
@ Generates the function prologue
@ Note that functions should all be "stack-moves-once"
@ The FNSTART and FNEND macros should be the only places
@ where the stack moves.
@
@ name = function name
@ rreg = "" don't stack any registers
@ "lr" stack "lr" only
@ "rN" stack registers "r4-rN,lr"
@ dreg = "" don't stack any D registers
@ "dN" stack registers "d8-dN"
@
@ Note: ARM Archicture procedure call standard AAPCS
@ states that r4-r11, sp, d8-d15 must be preserved by
@ a compliant function.
.macro M_START name, rreg, dreg
.set _Workspace, 0
@ Define the function and make it external.
.arm
.global \name
.hidden \name
.section .text.\name,"ax",%progbits
.align 2
\name :
.fnstart
@ Save specified R registers
_M_GETRREGLIST \rreg
_M_PUSH_RREG
@ Save specified D registers
_M_GETDREGLIST \dreg
_M_PUSH_DREG
@ Ensure size claimed on stack is 8-byte aligned
.if (_SBytes & 7) != 0
.set _SBytes, _SBytes + (8 - (_SBytes & 7))
.endif
.if _SBytes != 0
sub sp, sp, #_SBytes
.endif
.endm
@ Function Footer Macro
@ Generates the function epilogue
.macro M_END
@ Restore the stack pointer to its original value on function entry
.if _SBytes != 0
add sp, sp, #_SBytes
.endif
@ Restore any saved R or D registers.
_M_RET
.fnend
@ Reset the global stack tracking variables back to their
@ initial values.
.set _SBytes, 0
.endm
@// Based on the value of _DRegList, push the specified set of registers
@// to the stack. Is there a better way?
.macro _M_PUSH_DREG
.if _DRegList == 8
vpush {d8}
.exitm
.endif
.if _DRegList == 9
vpush {d8-d9}
.exitm
.endif
.if _DRegList == 10
vpush {d8-d10}
.exitm
.endif
.if _DRegList == 11
vpush {d8-d11}
.exitm
.endif
.if _DRegList == 12
vpush {d8-d12}
.exitm
.endif
.if _DRegList == 13
vpush {d8-d13}
.exitm
.endif
.if _DRegList == 14
vpush {d8-d14}
.exitm
.endif
.if _DRegList == 15
vpush {d8-d15}
.exitm
.endif
.endm
@// Based on the value of _RRegList, push the specified set of registers
@// to the stack. Is there a better way?
.macro _M_PUSH_RREG
.if _RRegList == 4
stmfd sp!, {r4, lr}
.exitm
.endif
.if _RRegList == 6
stmfd sp!, {r4-r6, lr}
.exitm
.endif
.if _RRegList == 8
stmfd sp!, {r4-r8, lr}
.exitm
.endif
.if _RRegList == 10
stmfd sp!, {r4-r10, lr}
.exitm
.endif
.if _RRegList == 12
stmfd sp!, {r4-r12, lr}
.exitm
.endif
.endm
@// The opposite of _M_PUSH_DREG
.macro _M_POP_DREG
.if _DRegList == 8
vpop {d8}
.exitm
.endif
.if _DRegList == 9
vpop {d8-d9}
.exitm
.endif
.if _DRegList == 10
vpop {d8-d10}
.exitm
.endif
.if _DRegList == 11
vpop {d8-d11}
.exitm
.endif
.if _DRegList == 12
vpop {d8-d12}
.exitm
.endif
.if _DRegList == 13
vpop {d8-d13}
.exitm
.endif
.if _DRegList == 14
vpop {d8-d14}
.exitm
.endif
.if _DRegList == 15
vpop {d8-d15}
.exitm
.endif
.endm
@// The opposite of _M_PUSH_RREG
.macro _M_POP_RREG cc
.if _RRegList == 0
bx\cc lr
.exitm
.endif
.if _RRegList == 4
ldm\cc\()fd sp!, {r4, pc}
.exitm
.endif
.if _RRegList == 6
ldm\cc\()fd sp!, {r4-r6, pc}
.exitm
.endif
.if _RRegList == 8
ldm\cc\()fd sp!, {r4-r8, pc}
.exitm
.endif
.if _RRegList == 10
ldm\cc\()fd sp!, {r4-r10, pc}
.exitm
.endif
.if _RRegList == 12
ldm\cc\()fd sp!, {r4-r12, pc}
.exitm
.endif
.endm
@ Produce function return instructions
.macro _M_RET cc
_M_POP_DREG \cc
_M_POP_RREG \cc
.endm
@// Allocate 4-byte aligned area of name
@// |name| and size |size| bytes.
.macro M_ALLOC4 name, size
.if (_SBytes & 3) != 0
.set _SBytes, _SBytes + (4 - (_SBytes & 3))
.endif
.set \name\()_F, _SBytes
.set _SBytes, _SBytes + \size
.endm
@// Allocate 8-byte aligned area of name
@// |name| and size |size| bytes.
.macro M_ALLOC8 name, size
.if (_SBytes & 7) != 0
.set _SBytes, _SBytes + (8 - (_SBytes & 7))
.endif
.set \name\()_F, _SBytes
.set _SBytes, _SBytes + \size
.endm
@ Load word from stack
.macro M_LDR r, a0, a1, a2, a3
_M_DATA "ldr", 4, \r, \a0, \a1, \a2, \a3
.endm
@ Store word to stack
.macro M_STR r, a0, a1, a2, a3
_M_DATA "str", 4, \r, \a0, \a1, \a2, \a3
.endm
@ Load double word from stack
.macro M_LDRD r0, r1, a0, a1, a2, a3
_M_DATA2 "ldrd", 8, \r0, \r1, \a0, \a1, \a2, \a3
.endm
@ Store double word to stack
.macro M_STRD r0, r1, a0, a1, a2, a3
_M_DATA2 "strd", 8, \r0, \r1, \a0, \a1, \a2, \a3
.endm
@ Macro to perform a data access operation
@ Such as LDR or STR
@ The addressing mode is modified such that
@ 1. If no address is given then the name is taken
@ as a stack offset
@ 2. If the addressing mode is not available for the
@ state being assembled for (eg Thumb) then a suitable
@ addressing mode is substituted.
@
@ On Entry:
@ $i = Instruction to perform (eg "LDRB")
@ $a = Required byte alignment
@ $r = Register(s) to transfer (eg "r1")
@ $a0,$a1,$a2. Addressing mode and condition. One of:
@ label {,cc}
@ [base] {,,,cc}
@ [base, offset]{!} {,,cc}
@ [base, offset, shift]{!} {,cc}
@ [base], offset {,,cc}
@ [base], offset, shift {,cc}
@
@ WARNING: Most of the above are not supported, except the first case.
.macro _M_DATA i, a, r, a0, a1, a2, a3
.set _Offset, _Workspace + \a0\()_F
\i\a1 \r, [sp, #_Offset]
.endm
@ Macro to perform a data access operation
@ Such as LDR or STR
@ The addressing mode is modified such that
@ 1. If no address is given then the name is taken
@ as a stack offset
@ 2. If the addressing mode is not available for the
@ state being assembled for (eg Thumb) then a suitable
@ addressing mode is substituted.
@
@ On Entry:
@ $i = Instruction to perform (eg "LDRB")
@ $a = Required byte alignment
@ $r = Register(s) to transfer (eg "r1")
@ $a0,$a1,$a2. Addressing mode and condition. One of:
@ label {,cc}
@ [base] {,,,cc}
@ [base, offset]{!} {,,cc}
@ [base, offset, shift]{!} {,cc}
@ [base], offset {,,cc}
@ [base], offset, shift {,cc}
@
@ WARNING: Most of the above are not supported, except the first case.
.macro _M_DATA2 i, a, r0, r1, a0, a1, a2, a3
.set _Offset, _Workspace + \a0\()_F
\i\a1 \r0, \r1, [sp, #_Offset]
.endm