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