1cabdff1aSopenharmony_ci/****************************************************************************
2cabdff1aSopenharmony_ci * Assembly testing and benchmarking tool
3cabdff1aSopenharmony_ci * Copyright (c) 2015 Martin Storsjo
4cabdff1aSopenharmony_ci * Copyright (c) 2015 Janne Grunau
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or modify
9cabdff1aSopenharmony_ci * it under the terms of the GNU General Public License as published by
10cabdff1aSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or
11cabdff1aSopenharmony_ci * (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16cabdff1aSopenharmony_ci * GNU General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU General Public License
19cabdff1aSopenharmony_ci * along with this program; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
21cabdff1aSopenharmony_ci *****************************************************************************/
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "libavutil/aarch64/asm.S"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ciconst register_init, align=4
26cabdff1aSopenharmony_ci        .quad 0x21f86d66c8ca00ce
27cabdff1aSopenharmony_ci        .quad 0x75b6ba21077c48ad
28cabdff1aSopenharmony_ci        .quad 0xed56bb2dcb3c7736
29cabdff1aSopenharmony_ci        .quad 0x8bda43d3fd1a7e06
30cabdff1aSopenharmony_ci        .quad 0xb64a9c9e5d318408
31cabdff1aSopenharmony_ci        .quad 0xdf9a54b303f1d3a3
32cabdff1aSopenharmony_ci        .quad 0x4a75479abd64e097
33cabdff1aSopenharmony_ci        .quad 0x249214109d5d1c88
34cabdff1aSopenharmony_ci        .quad 0x1a1b2550a612b48c
35cabdff1aSopenharmony_ci        .quad 0x79445c159ce79064
36cabdff1aSopenharmony_ci        .quad 0x2eed899d5a28ddcd
37cabdff1aSopenharmony_ci        .quad 0x86b2536fcd8cf636
38cabdff1aSopenharmony_ci        .quad 0xb0856806085e7943
39cabdff1aSopenharmony_ci        .quad 0x3f2bf84fc0fcca4e
40cabdff1aSopenharmony_ci        .quad 0xacbd382dcf5b8de2
41cabdff1aSopenharmony_ci        .quad 0xd229e1f5b281303f
42cabdff1aSopenharmony_ci        .quad 0x71aeaff20b095fd9
43cabdff1aSopenharmony_ci        .quad 0xab63e2e11fa38ed9
44cabdff1aSopenharmony_ciendconst
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ciconst error_message_register
48cabdff1aSopenharmony_ci        .asciz "failed to preserve register"
49cabdff1aSopenharmony_cierror_message_stack:
50cabdff1aSopenharmony_ci        .asciz "stack clobbered"
51cabdff1aSopenharmony_ciendconst
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci// max number of args used by any asm function.
55cabdff1aSopenharmony_ci#define MAX_ARGS 15
56cabdff1aSopenharmony_ci
57cabdff1aSopenharmony_ci#define CLOBBER_STACK ((8*MAX_ARGS + 15) & ~15)
58cabdff1aSopenharmony_ci
59cabdff1aSopenharmony_cifunction checkasm_stack_clobber, export=1
60cabdff1aSopenharmony_ci        mov             x3,  sp
61cabdff1aSopenharmony_ci        mov             x2,  #CLOBBER_STACK
62cabdff1aSopenharmony_ci1:
63cabdff1aSopenharmony_ci        stp             x0,  x1,  [sp, #-16]!
64cabdff1aSopenharmony_ci        subs            x2,  x2,  #16
65cabdff1aSopenharmony_ci        b.gt            1b
66cabdff1aSopenharmony_ci        mov             sp,  x3
67cabdff1aSopenharmony_ci        ret
68cabdff1aSopenharmony_ciendfunc
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci// + 16 for stack canary reference
71cabdff1aSopenharmony_ci#define ARG_STACK ((8*(MAX_ARGS - 8) + 15) & ~15 + 16)
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_cifunction checkasm_checked_call, export=1
74cabdff1aSopenharmony_ci        stp             x29, x30, [sp, #-16]!
75cabdff1aSopenharmony_ci        mov             x29, sp
76cabdff1aSopenharmony_ci        stp             x19, x20, [sp, #-16]!
77cabdff1aSopenharmony_ci        stp             x21, x22, [sp, #-16]!
78cabdff1aSopenharmony_ci        stp             x23, x24, [sp, #-16]!
79cabdff1aSopenharmony_ci        stp             x25, x26, [sp, #-16]!
80cabdff1aSopenharmony_ci        stp             x27, x28, [sp, #-16]!
81cabdff1aSopenharmony_ci        stp             d8,  d9,  [sp, #-16]!
82cabdff1aSopenharmony_ci        stp             d10, d11, [sp, #-16]!
83cabdff1aSopenharmony_ci        stp             d12, d13, [sp, #-16]!
84cabdff1aSopenharmony_ci        stp             d14, d15, [sp, #-16]!
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci        movrel          x9, register_init
87cabdff1aSopenharmony_ci        ldp             d8,  d9,  [x9], #16
88cabdff1aSopenharmony_ci        ldp             d10, d11, [x9], #16
89cabdff1aSopenharmony_ci        ldp             d12, d13, [x9], #16
90cabdff1aSopenharmony_ci        ldp             d14, d15, [x9], #16
91cabdff1aSopenharmony_ci        ldp             x19, x20, [x9], #16
92cabdff1aSopenharmony_ci        ldp             x21, x22, [x9], #16
93cabdff1aSopenharmony_ci        ldp             x23, x24, [x9], #16
94cabdff1aSopenharmony_ci        ldp             x25, x26, [x9], #16
95cabdff1aSopenharmony_ci        ldp             x27, x28, [x9], #16
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_ci        sub             sp,  sp,  #ARG_STACK
98cabdff1aSopenharmony_ci.equ pos, 0
99cabdff1aSopenharmony_ci.rept MAX_ARGS-8
100cabdff1aSopenharmony_ci        // Skip the first 8 args, that are loaded into registers
101cabdff1aSopenharmony_ci        ldr             x9, [x29, #16 + 8*8 + pos]
102cabdff1aSopenharmony_ci        str             x9, [sp, #pos]
103cabdff1aSopenharmony_ci.equ pos, pos + 8
104cabdff1aSopenharmony_ci.endr
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci        // Fill x8-x17 with garbage. This doesn't have to be preserved,
107cabdff1aSopenharmony_ci        // but avoids relying on them having any particular value.
108cabdff1aSopenharmony_ci        movrel          x9, register_init
109cabdff1aSopenharmony_ci        ldp             x10, x11, [x9], #32
110cabdff1aSopenharmony_ci        ldp             x12, x13, [x9], #32
111cabdff1aSopenharmony_ci        ldp             x14, x15, [x9], #32
112cabdff1aSopenharmony_ci        ldp             x16, x17, [x9], #32
113cabdff1aSopenharmony_ci        ldp             x8,  x9,  [x9]
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci        // For stack overflows, the callee is free to overwrite the parameters
116cabdff1aSopenharmony_ci        // that were passed on the stack (if any), so we can only check after
117cabdff1aSopenharmony_ci        // that point. First figure out how many parameters the function
118cabdff1aSopenharmony_ci        // really took on the stack:
119cabdff1aSopenharmony_ci        ldr             w2,  [x29, #16 + 8*8 + (MAX_ARGS-8)*8]
120cabdff1aSopenharmony_ci        // Load the first non-parameter value from the stack, that should be
121cabdff1aSopenharmony_ci        // left untouched by the function. Store a copy of it inverted, so that
122cabdff1aSopenharmony_ci        // e.g. overwriting everything with zero would be noticed.
123cabdff1aSopenharmony_ci        ldr             x2,  [sp, x2, lsl #3]
124cabdff1aSopenharmony_ci        mvn             x2,  x2
125cabdff1aSopenharmony_ci        str             x2,  [sp, #ARG_STACK-8]
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci        // Load the in-register arguments
128cabdff1aSopenharmony_ci        mov             x12, x0
129cabdff1aSopenharmony_ci        ldp             x0,  x1,  [x29, #16]
130cabdff1aSopenharmony_ci        ldp             x2,  x3,  [x29, #32]
131cabdff1aSopenharmony_ci        ldp             x4,  x5,  [x29, #48]
132cabdff1aSopenharmony_ci        ldp             x6,  x7,  [x29, #64]
133cabdff1aSopenharmony_ci        // Call the target function
134cabdff1aSopenharmony_ci        blr             x12
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci        // Load the number of stack parameters, stack canary and its reference
137cabdff1aSopenharmony_ci        ldr             w2,  [x29, #16 + 8*8 + (MAX_ARGS-8)*8]
138cabdff1aSopenharmony_ci        ldr             x2,  [sp, x2, lsl #3]
139cabdff1aSopenharmony_ci        ldr             x3,  [sp, #ARG_STACK-8]
140cabdff1aSopenharmony_ci
141cabdff1aSopenharmony_ci        add             sp,  sp,  #ARG_STACK
142cabdff1aSopenharmony_ci        stp             x0,  x1,  [sp, #-16]!
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci        mvn             x3,  x3
145cabdff1aSopenharmony_ci        cmp             x2,  x3
146cabdff1aSopenharmony_ci        b.ne            2f
147cabdff1aSopenharmony_ci
148cabdff1aSopenharmony_ci        movrel          x9, register_init
149cabdff1aSopenharmony_ci        movi            v3.8h,  #0
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci.macro check_reg_neon reg1, reg2
152cabdff1aSopenharmony_ci        ldr             q1,  [x9], #16
153cabdff1aSopenharmony_ci        uzp1            v2.2d,  v\reg1\().2d, v\reg2\().2d
154cabdff1aSopenharmony_ci        eor             v1.16b, v1.16b, v2.16b
155cabdff1aSopenharmony_ci        orr             v3.16b, v3.16b, v1.16b
156cabdff1aSopenharmony_ci.endm
157cabdff1aSopenharmony_ci        check_reg_neon  8,  9
158cabdff1aSopenharmony_ci        check_reg_neon  10, 11
159cabdff1aSopenharmony_ci        check_reg_neon  12, 13
160cabdff1aSopenharmony_ci        check_reg_neon  14, 15
161cabdff1aSopenharmony_ci        uqxtn           v3.8b,  v3.8h
162cabdff1aSopenharmony_ci        umov            x3,  v3.d[0]
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_ci.macro check_reg reg1, reg2
165cabdff1aSopenharmony_ci        ldp             x0,  x1,  [x9], #16
166cabdff1aSopenharmony_ci        eor             x0,  x0,  \reg1
167cabdff1aSopenharmony_ci        eor             x1,  x1,  \reg2
168cabdff1aSopenharmony_ci        orr             x3,  x3,  x0
169cabdff1aSopenharmony_ci        orr             x3,  x3,  x1
170cabdff1aSopenharmony_ci.endm
171cabdff1aSopenharmony_ci        check_reg       x19, x20
172cabdff1aSopenharmony_ci        check_reg       x21, x22
173cabdff1aSopenharmony_ci        check_reg       x23, x24
174cabdff1aSopenharmony_ci        check_reg       x25, x26
175cabdff1aSopenharmony_ci        check_reg       x27, x28
176cabdff1aSopenharmony_ci
177cabdff1aSopenharmony_ci        cbz             x3,  0f
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci        movrel          x0, error_message_register
180cabdff1aSopenharmony_ci        b               1f
181cabdff1aSopenharmony_ci2:
182cabdff1aSopenharmony_ci        movrel          x0, error_message_stack
183cabdff1aSopenharmony_ci1:
184cabdff1aSopenharmony_ci        bl              X(checkasm_fail_func)
185cabdff1aSopenharmony_ci0:
186cabdff1aSopenharmony_ci        ldp             x0,  x1,  [sp], #16
187cabdff1aSopenharmony_ci        ldp             d14, d15, [sp], #16
188cabdff1aSopenharmony_ci        ldp             d12, d13, [sp], #16
189cabdff1aSopenharmony_ci        ldp             d10, d11, [sp], #16
190cabdff1aSopenharmony_ci        ldp             d8,  d9,  [sp], #16
191cabdff1aSopenharmony_ci        ldp             x27, x28, [sp], #16
192cabdff1aSopenharmony_ci        ldp             x25, x26, [sp], #16
193cabdff1aSopenharmony_ci        ldp             x23, x24, [sp], #16
194cabdff1aSopenharmony_ci        ldp             x21, x22, [sp], #16
195cabdff1aSopenharmony_ci        ldp             x19, x20, [sp], #16
196cabdff1aSopenharmony_ci        ldp             x29, x30, [sp], #16
197cabdff1aSopenharmony_ci        ret
198cabdff1aSopenharmony_ciendfunc
199