1/* SPDX-License-Identifier: BSD-2-Clause */ 2/* 3 * Copyright (c) 2015, Linaro Limited 4 * All rights reserved. 5 */ 6 7 .altmacro 8 9 /* 10 * This helper macro concatenates instr_prefix, instr_suffix, to 11 * create a ldp/stp instruction. It also selects register name x/w 12 * based on reg_bytes. 13 */ 14 .macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \ 15 base_offs, reg0, reg1 16 .if \reg_bytes == 8 17 \instr_prefix\instr_suffix \ 18 x\reg0, x\reg1, [\base_reg, #\base_offs] 19 .else 20 \instr_prefix\instr_suffix \ 21 w\reg0, w\reg1, [\base_reg, #\base_offs] 22 .endif 23 .endm 24 25 /* 26 * This helper macro concatenates instr_prefix, instr_suffix, to 27 * create a ldr/str instruction. It also selects register name x/w 28 * based on reg_bytes. 29 */ 30 .macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \ 31 base_offs, reg 32 .if \reg_bytes == 8 33 \instr_prefix\instr_suffix \ 34 x\reg, [\base_reg, #\base_offs] 35 .else 36 \instr_prefix\instr_suffix \ 37 w\reg, [\base_reg, #\base_offs] 38 .endif 39 .endm 40 41 /* 42 * This helper macro uses recursion to create a loop which will 43 * start with generating instructions for register pairs and if 44 * it's an odd number of registers end with a single load/store. 45 */ 46 .macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \ 47 from_regnum, to_regnum 48 .if (\to_regnum - \from_regnum + 1) >= 2 49 __do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \ 50 \base_offs, \from_regnum, %(\from_regnum + 1) 51 .else 52 __do_reg \instr_prefix, r, \reg_bytes, \base_reg, \ 53 \base_offs, \from_regnum 54 .endif 55 .if (\to_regnum - \from_regnum + 1) > 2 56 _do_regs \instr_prefix, \reg_bytes, \base_reg, \ 57 %(\base_offs + 2 * \reg_bytes), \ 58 %(\from_regnum + 2), \to_regnum 59 .endif 60 .endm 61 62 /* 63 * Stores registers x[from_regnum]..x[to_regnum] at 64 * [base_reg, #base_offs] 65 */ 66 .macro store_xregs base_reg, base_offs, from_regnum, to_regnum 67 _do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum 68 .endm 69 70 /* 71 * Stores registers w[from_regnum]..w[to_regnum] at 72 * [base_reg, #base_offs] 73 */ 74 .macro store_wregs base_reg, base_offs, from_regnum, to_regnum 75 _do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum 76 .endm 77 78 /* 79 * Loads registers x[from_regnum]..x[to_regnum] at 80 * [base_reg, #base_offs] 81 */ 82 .macro load_xregs base_reg, base_offs, from_regnum, to_regnum 83 _do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum 84 .endm 85 86 /* 87 * Loads registers w[from_regnum]..w[to_regnum] at 88 * [base_reg, #base_offs] 89 */ 90 .macro load_wregs base_reg, base_offs, from_regnum, to_regnum 91 _do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum 92 .endm 93 94 95 /* Push register pair on stack */ 96 .macro push, r1, r2 97 stp \r1, \r2, [sp, #-16]! 98 .endm 99 100 /* Pop register pair from stack */ 101 .macro pop, r1, r2 102 ldp \r1, \r2, [sp], #16 103 .endm 104 105 .macro mov_imm _reg, _val 106 .if (((\_val) >> 31) == 0 || ((\_val) >> 31) == 0x1ffffffff) 107 movz \_reg, :abs_g1_s:\_val 108 .else 109 .if (((\_val) >> 47) == 0 || ((\_val) >> 47) == 0x1ffff) 110 movz \_reg, :abs_g2_s:\_val 111 .else 112 movz \_reg, :abs_g3:\_val 113 movk \_reg, :abs_g2_nc:\_val 114 .endif 115 movk \_reg, :abs_g1_nc:\_val 116 .endif 117 movk \_reg, :abs_g0_nc:\_val 118 .endm 119