1/*
2 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22
23#ifdef __ELF__
24#   define ELF
25#else
26#   define ELF @
27#endif
28
29#if CONFIG_THUMB
30#   define A @
31#   define T
32#else
33#   define A
34#   define T @
35#endif
36
37#if HAVE_AS_FUNC
38#   define FUNC
39#else
40#   define FUNC @
41#endif
42
43#if HAVE_AS_FPU_DIRECTIVE
44#   define FPU
45#else
46#   define FPU @
47#endif
48
49#if   HAVE_NEON
50        .arch           armv7-a
51#elif HAVE_ARMV6T2
52        .arch           armv6t2
53#elif HAVE_ARMV6
54        .arch           armv6
55#elif HAVE_ARMV5TE
56        .arch           armv5te
57#endif
58#if   HAVE_AS_OBJECT_ARCH
59ELF     .object_arch    armv4
60#endif
61
62#if   HAVE_NEON
63FPU     .fpu            neon
64ELF     .eabi_attribute 10, 0           @ suppress Tag_FP_arch
65ELF     .eabi_attribute 12, 0           @ suppress Tag_Advanced_SIMD_arch
66#elif HAVE_VFP
67FPU     .fpu            vfp
68ELF     .eabi_attribute 10, 0           @ suppress Tag_FP_arch
69#endif
70
71        .syntax unified
72T       .thumb
73ELF     .eabi_attribute 25, 1           @ Tag_ABI_align_preserved
74ELF     .section .note.GNU-stack,"",%progbits @ Mark stack as non-executable
75
76.macro  function name, export=0, align=2
77        .set            .Lpic_idx, 0
78        .set            .Lpic_gp, 0
79    .macro endfunc
80      .if .Lpic_idx
81        .align          2
82        .altmacro
83        put_pic         %(.Lpic_idx - 1)
84        .noaltmacro
85      .endif
86      .if .Lpic_gp
87        .unreq          gp
88      .endif
89ELF     .size   \name, . - \name
90FUNC    .endfunc
91        .purgem endfunc
92    .endm
93        .text
94        .align          \align
95    .if \export
96        .global EXTERN_ASM\name
97ELF     .type   EXTERN_ASM\name, %function
98FUNC    .func   EXTERN_ASM\name
99EXTERN_ASM\name:
100    .else
101ELF     .type   \name, %function
102FUNC    .func   \name
103\name:
104    .endif
105.endm
106
107.macro  const   name, align=2, relocate=0
108    .macro endconst
109ELF     .size   \name, . - \name
110        .purgem endconst
111    .endm
112.if HAVE_SECTION_DATA_REL_RO && \relocate
113        .section        .data.rel.ro
114.else
115        .section        .rodata
116.endif
117        .align          \align
118\name:
119.endm
120
121#if !HAVE_ARMV6T2_EXTERNAL
122.macro  movw    rd, val
123        mov     \rd, \val &  255
124        orr     \rd, \val & ~255
125.endm
126#endif
127
128.macro  mov32   rd, val
129#if HAVE_ARMV6T2_EXTERNAL
130        movw            \rd, #(\val) & 0xffff
131    .if (\val) >> 16
132        movt            \rd, #(\val) >> 16
133    .endif
134#else
135        ldr             \rd, =\val
136#endif
137.endm
138
139.macro  put_pic         num
140        put_pic_\num
141.endm
142
143.macro  do_def_pic      num, val, label
144    .macro put_pic_\num
145      .if \num
146        .altmacro
147        put_pic         %(\num - 1)
148        .noaltmacro
149      .endif
150\label: .word           \val
151        .purgem         put_pic_\num
152    .endm
153.endm
154
155.macro  def_pic         val, label
156        .altmacro
157        do_def_pic      %.Lpic_idx, \val, \label
158        .noaltmacro
159        .set            .Lpic_idx, .Lpic_idx + 1
160.endm
161
162.macro  ldpic           rd,  val, indir=0
163        ldr             \rd, .Lpicoff\@
164.Lpic\@:
165    .if \indir
166A       ldr             \rd, [pc, \rd]
167T       add             \rd, pc
168T       ldr             \rd, [\rd]
169    .else
170        add             \rd, pc
171    .endif
172        def_pic         \val - (.Lpic\@ + (8 >> CONFIG_THUMB)), .Lpicoff\@
173.endm
174
175.macro  movrel rd, val
176#if CONFIG_PIC
177        ldpic           \rd, \val
178#elif HAVE_ARMV6T2_EXTERNAL && !defined(__APPLE__)
179        movw            \rd, #:lower16:\val
180        movt            \rd, #:upper16:\val
181#else
182        ldr             \rd, =\val
183#endif
184.endm
185
186.macro  movrelx         rd,  val, gp
187    .ifc \rd,\gp
188        .error      "movrelx needs two distinct registers"
189    .endif
190    .ifc \rd\()_\gp,r12_
191        .warning    "movrelx rd=\rd without explicit set gp"
192    .endif
193    .ifc \rd\()_\gp,ip_
194        .warning    "movrelx rd=\rd without explicit set gp"
195    .endif
196#if CONFIG_PIC && defined(__ELF__)
197    .ifnb \gp
198      .if .Lpic_gp
199        .unreq          gp
200      .endif
201        gp      .req    \gp
202        ldpic           gp,  _GLOBAL_OFFSET_TABLE_
203    .elseif !.Lpic_gp
204        gp      .req    r12
205        ldpic           gp,  _GLOBAL_OFFSET_TABLE_
206    .endif
207        .set            .Lpic_gp, 1
208        ldr             \rd, .Lpicoff\@
209        ldr             \rd, [gp, \rd]
210        def_pic         \val(GOT), .Lpicoff\@
211#elif CONFIG_PIC && defined(__APPLE__)
212        ldpic           \rd, .Lpic\@, indir=1
213        .non_lazy_symbol_pointer
214.Lpic\@:
215        .indirect_symbol \val
216        .word           0
217        .text
218#else
219        movrel          \rd, \val
220#endif
221.endm
222
223.macro  add_sh          rd,  rn,  rm,  sh:vararg
224A       add             \rd, \rn, \rm, \sh
225T       mov             \rm, \rm, \sh
226T       add             \rd, \rn, \rm
227.endm
228
229.macro  ldr_pre         rt,  rn,  rm:vararg
230A       ldr             \rt, [\rn, \rm]!
231T       add             \rn, \rn, \rm
232T       ldr             \rt, [\rn]
233.endm
234
235.macro  ldr_dpre        rt,  rn,  rm:vararg
236A       ldr             \rt, [\rn, -\rm]!
237T       sub             \rn, \rn, \rm
238T       ldr             \rt, [\rn]
239.endm
240
241.macro  ldr_nreg        rt,  rn,  rm:vararg
242A       ldr             \rt, [\rn, -\rm]
243T       sub             \rt, \rn, \rm
244T       ldr             \rt, [\rt]
245.endm
246
247.macro  ldr_post        rt,  rn,  rm:vararg
248A       ldr             \rt, [\rn], \rm
249T       ldr             \rt, [\rn]
250T       add             \rn, \rn, \rm
251.endm
252
253.macro  ldrc_pre        cc,  rt,  rn,  rm:vararg
254A       ldr\cc          \rt, [\rn, \rm]!
255T       itt             \cc
256T       add\cc          \rn, \rn, \rm
257T       ldr\cc          \rt, [\rn]
258.endm
259
260.macro  ldrd_reg        rt,  rt2, rn,  rm
261A       ldrd            \rt, \rt2, [\rn, \rm]
262T       add             \rt, \rn, \rm
263T       ldrd            \rt, \rt2, [\rt]
264.endm
265
266.macro  ldrd_post       rt,  rt2, rn,  rm
267A       ldrd            \rt, \rt2, [\rn], \rm
268T       ldrd            \rt, \rt2, [\rn]
269T       add             \rn, \rn, \rm
270.endm
271
272.macro  ldrh_pre        rt,  rn,  rm
273A       ldrh            \rt, [\rn, \rm]!
274T       add             \rn, \rn, \rm
275T       ldrh            \rt, [\rn]
276.endm
277
278.macro  ldrh_dpre       rt,  rn,  rm
279A       ldrh            \rt, [\rn, -\rm]!
280T       sub             \rn, \rn, \rm
281T       ldrh            \rt, [\rn]
282.endm
283
284.macro  ldrh_post       rt,  rn,  rm
285A       ldrh            \rt, [\rn], \rm
286T       ldrh            \rt, [\rn]
287T       add             \rn, \rn, \rm
288.endm
289
290.macro  ldrb_post       rt,  rn,  rm
291A       ldrb            \rt, [\rn], \rm
292T       ldrb            \rt, [\rn]
293T       add             \rn, \rn, \rm
294.endm
295
296.macro  str_post       rt,  rn,  rm:vararg
297A       str             \rt, [\rn], \rm
298T       str             \rt, [\rn]
299T       add             \rn, \rn, \rm
300.endm
301
302.macro  strb_post       rt,  rn,  rm:vararg
303A       strb            \rt, [\rn], \rm
304T       strb            \rt, [\rn]
305T       add             \rn, \rn, \rm
306.endm
307
308.macro  strd_post       rt,  rt2, rn,  rm
309A       strd            \rt, \rt2, [\rn], \rm
310T       strd            \rt, \rt2, [\rn]
311T       add             \rn, \rn, \rm
312.endm
313
314.macro  strh_pre        rt,  rn,  rm
315A       strh            \rt, [\rn, \rm]!
316T       add             \rn, \rn, \rm
317T       strh            \rt, [\rn]
318.endm
319
320.macro  strh_dpre       rt,  rn,  rm
321A       strh            \rt, [\rn, -\rm]!
322T       sub             \rn, \rn, \rm
323T       strh            \rt, [\rn]
324.endm
325
326.macro  strh_post       rt,  rn,  rm
327A       strh            \rt, [\rn], \rm
328T       strh            \rt, [\rn]
329T       add             \rn, \rn, \rm
330.endm
331
332.macro  strh_dpost       rt,  rn,  rm
333A       strh            \rt, [\rn], -\rm
334T       strh            \rt, [\rn]
335T       sub             \rn, \rn, \rm
336.endm
337
338#if HAVE_VFP_ARGS
339ELF     .eabi_attribute 28, 1
340#   define VFP
341#   define NOVFP @
342#else
343#   define VFP   @
344#   define NOVFP
345#endif
346
347#define GLUE(a, b) a ## b
348#define JOIN(a, b) GLUE(a, b)
349#define X(s) JOIN(EXTERN_ASM, s)
350