1/* 2 * Copyright (c) 2015, Linaro Limited 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 .altmacro 29 30 /* 31 * This helper macro concatenates instr_prefix, instr_suffix, to 32 * create a ldp/stp instruction. It also selects register name x/w 33 * based on reg_bytes. 34 */ 35 .macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \ 36 base_offs, reg0, reg1 37 .if \reg_bytes == 8 38 \instr_prefix\instr_suffix \ 39 x\reg0, x\reg1, [\base_reg, #\base_offs] 40 .else 41 \instr_prefix\instr_suffix \ 42 w\reg0, w\reg1, [\base_reg, #\base_offs] 43 .endif 44 .endm 45 46 /* 47 * This helper macro concatenates instr_prefix, instr_suffix, to 48 * create a ldr/str instruction. It also selects register name x/w 49 * based on reg_bytes. 50 */ 51 .macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \ 52 base_offs, reg 53 .if \reg_bytes == 8 54 \instr_prefix\instr_suffix \ 55 x\reg, [\base_reg, #\base_offs] 56 .else 57 \instr_prefix\instr_suffix \ 58 w\reg, [\base_reg, #\base_offs] 59 .endif 60 .endm 61 62 /* 63 * This helper macro uses recursion to create a loop which will 64 * start with generating instructions for register pairs and if 65 * it's an odd number of registers end with a single load/store. 66 */ 67 .macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \ 68 from_regnum, to_regnum 69 .if (\to_regnum - \from_regnum + 1) >= 2 70 __do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \ 71 \base_offs, \from_regnum, %(\from_regnum + 1) 72 .else 73 __do_reg \instr_prefix, r, \reg_bytes, \base_reg, \ 74 \base_offs, \from_regnum 75 .endif 76 .if (\to_regnum - \from_regnum + 1) > 2 77 _do_regs \instr_prefix, \reg_bytes, \base_reg, \ 78 %(\base_offs + 2 * \reg_bytes), \ 79 %(\from_regnum + 2), \to_regnum 80 .endif 81 .endm 82 83 /* 84 * Stores registers x[from_regnum]..x[to_regnum] at 85 * [base_reg, #base_offs] 86 */ 87 .macro store_xregs base_reg, base_offs, from_regnum, to_regnum 88 _do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum 89 .endm 90 91 /* 92 * Stores registers w[from_regnum]..w[to_regnum] at 93 * [base_reg, #base_offs] 94 */ 95 .macro store_wregs base_reg, base_offs, from_regnum, to_regnum 96 _do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum 97 .endm 98 99 /* 100 * Loads registers x[from_regnum]..x[to_regnum] at 101 * [base_reg, #base_offs] 102 */ 103 .macro load_xregs base_reg, base_offs, from_regnum, to_regnum 104 _do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum 105 .endm 106 107 /* 108 * Loads registers w[from_regnum]..w[to_regnum] at 109 * [base_reg, #base_offs] 110 */ 111 .macro load_wregs base_reg, base_offs, from_regnum, to_regnum 112 _do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum 113 .endm 114 115 116 /* Push register pair on stack */ 117 .macro push, r1, r2 118 stp \r1, \r2, [sp, #-16]! 119 .endm 120 121 /* Pop register pair from stack */ 122 .macro pop, r1, r2 123 ldp \r1, \r2, [sp], #16 124 .endm 125 126 .macro mov_imm _reg, _val 127 .if (((\_val) >> 31) == 0 || ((\_val) >> 31) == 0x1ffffffff) 128 movz \_reg, :abs_g1_s:\_val 129 .else 130 .if (((\_val) >> 47) == 0 || ((\_val) >> 47) == 0x1ffff) 131 movz \_reg, :abs_g2_s:\_val 132 .else 133 movz \_reg, :abs_g3:\_val 134 movk \_reg, :abs_g2_nc:\_val 135 .endif 136 movk \_reg, :abs_g1_nc:\_val 137 .endif 138 movk \_reg, :abs_g0_nc:\_val 139 .endm 140