summaryrefslogtreecommitdiff
path: root/libs/ffvpx/libavutil/x86/asm.h
blob: 9bff42d6288d4e2051424e40a125fec9d60f252e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef AVUTIL_X86_ASM_H
#define AVUTIL_X86_ASM_H

#include <stdint.h>
#include "config.h"

typedef struct xmm_reg { uint64_t a, b; } xmm_reg;
typedef struct ymm_reg { uint64_t a, b, c, d; } ymm_reg;

#if ARCH_X86_64
#    define FF_OPSIZE "q"
#    define FF_REG_a "rax"
#    define FF_REG_b "rbx"
#    define FF_REG_c "rcx"
#    define FF_REG_d "rdx"
#    define FF_REG_D "rdi"
#    define FF_REG_S "rsi"
#    define FF_PTR_SIZE "8"
typedef int64_t x86_reg;

/* FF_REG_SP is defined in Solaris sys headers, so use FF_REG_sp */
#    define FF_REG_sp "rsp"
#    define FF_REG_BP "rbp"
#    define FF_REGBP   rbp
#    define FF_REGa    rax
#    define FF_REGb    rbx
#    define FF_REGc    rcx
#    define FF_REGd    rdx
#    define FF_REGSP   rsp

#elif ARCH_X86_32

#    define FF_OPSIZE "l"
#    define FF_REG_a "eax"
#    define FF_REG_b "ebx"
#    define FF_REG_c "ecx"
#    define FF_REG_d "edx"
#    define FF_REG_D "edi"
#    define FF_REG_S "esi"
#    define FF_PTR_SIZE "4"
typedef int32_t x86_reg;

#    define FF_REG_sp "esp"
#    define FF_REG_BP "ebp"
#    define FF_REGBP   ebp
#    define FF_REGa    eax
#    define FF_REGb    ebx
#    define FF_REGc    ecx
#    define FF_REGd    edx
#    define FF_REGSP   esp
#else
typedef int x86_reg;
#endif

#define HAVE_7REGS (ARCH_X86_64 || (HAVE_EBX_AVAILABLE && HAVE_EBP_AVAILABLE))
#define HAVE_6REGS (ARCH_X86_64 || (HAVE_EBX_AVAILABLE || HAVE_EBP_AVAILABLE))

#if ARCH_X86_64 && defined(PIC)
#    define BROKEN_RELOCATIONS 1
#endif

/*
 * If gcc is not set to support sse (-msse) it will not accept xmm registers
 * in the clobber list for inline asm. XMM_CLOBBERS takes a list of xmm
 * registers to be marked as clobbered and evaluates to nothing if they are
 * not supported, or to the list itself if they are supported. Since a clobber
 * list may not be empty, XMM_CLOBBERS_ONLY should be used if the xmm
 * registers are the only in the clobber list.
 * For example a list with "eax" and "xmm0" as clobbers should become:
 * : XMM_CLOBBERS("xmm0",) "eax"
 * and a list with only "xmm0" should become:
 * XMM_CLOBBERS_ONLY("xmm0")
 */
#if HAVE_XMM_CLOBBERS
#    define XMM_CLOBBERS(...)        __VA_ARGS__
#    define XMM_CLOBBERS_ONLY(...) : __VA_ARGS__
#else
#    define XMM_CLOBBERS(...)
#    define XMM_CLOBBERS_ONLY(...)
#endif

/* Use to export labels from asm. */
#define LABEL_MANGLE(a) EXTERN_PREFIX #a

// Use rip-relative addressing if compiling PIC code on x86-64.
#if ARCH_X86_64 && defined(PIC)
#    define LOCAL_MANGLE(a) #a "(%%rip)"
#else
#    define LOCAL_MANGLE(a) #a
#endif

#if HAVE_INLINE_ASM_DIRECT_SYMBOL_REFS
#   define MANGLE(a) EXTERN_PREFIX LOCAL_MANGLE(a)
#   define NAMED_CONSTRAINTS_ADD(...)
#   define NAMED_CONSTRAINTS(...)
#   define NAMED_CONSTRAINTS_ARRAY_ADD(...)
#   define NAMED_CONSTRAINTS_ARRAY(...)
#else
    /* When direct symbol references are used in code passed to a compiler that does not support them
     *  then these references need to be converted to named asm constraints instead.
     * Instead of returning a direct symbol MANGLE now returns a named constraint for that specific symbol.
     * In order for this to work there must also be a corresponding entry in the asm-interface. To add this
     *  entry use the macro NAMED_CONSTRAINTS() and pass in a list of each symbol reference used in the
     *  corresponding block of code. (e.g. NAMED_CONSTRAINTS(var1,var2,var3) where var1 is the first symbol etc. ).
     * If there are already existing constraints then use NAMED_CONSTRAINTS_ADD to add to the existing constraint list.
     */
#   define MANGLE(a) "%["#a"]"
    // Intel/MSVC does not correctly expand va-args so we need a rather ugly hack in order to get it to work
#   define FE_0(P,X) P(X)
#   define FE_1(P,X,X1) P(X), FE_0(P,X1)
#   define FE_2(P,X,X1,X2) P(X), FE_1(P,X1,X2)
#   define FE_3(P,X,X1,X2,X3) P(X), FE_2(P,X1,X2,X3)
#   define FE_4(P,X,X1,X2,X3,X4) P(X), FE_3(P,X1,X2,X3,X4)
#   define FE_5(P,X,X1,X2,X3,X4,X5) P(X), FE_4(P,X1,X2,X3,X4,X5)
#   define FE_6(P,X,X1,X2,X3,X4,X5,X6) P(X), FE_5(P,X1,X2,X3,X4,X5,X6)
#   define FE_7(P,X,X1,X2,X3,X4,X5,X6,X7) P(X), FE_6(P,X1,X2,X3,X4,X5,X6,X7)
#   define FE_8(P,X,X1,X2,X3,X4,X5,X6,X7,X8) P(X), FE_7(P,X1,X2,X3,X4,X5,X6,X7,X8)
#   define FE_9(P,X,X1,X2,X3,X4,X5,X6,X7,X8,X9) P(X), FE_8(P,X1,X2,X3,X4,X5,X6,X7,X8,X9)
#   define GET_FE_IMPL(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME
#   define GET_FE(A) GET_FE_IMPL A
#   define GET_FE_GLUE(x, y) x y
#   define FOR_EACH_VA(P,...) GET_FE_GLUE(GET_FE((__VA_ARGS__,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)), (P,__VA_ARGS__))
#   define NAME_CONSTRAINT(x) [x] "m"(x)
    // Parameters are a list of each symbol reference required
#   define NAMED_CONSTRAINTS_ADD(...) , FOR_EACH_VA(NAME_CONSTRAINT,__VA_ARGS__)
    // Same but without comma for when there are no previously defined constraints
#   define NAMED_CONSTRAINTS(...) FOR_EACH_VA(NAME_CONSTRAINT,__VA_ARGS__)
    // Same as above NAMED_CONSTRAINTS except used for passing arrays/pointers instead of normal variables
#   define NAME_CONSTRAINT_ARRAY(x) [x] "m"(*x)
#   define NAMED_CONSTRAINTS_ARRAY_ADD(...) , FOR_EACH_VA(NAME_CONSTRAINT_ARRAY,__VA_ARGS__)
#   define NAMED_CONSTRAINTS_ARRAY(...) FOR_EACH_VA(NAME_CONSTRAINT_ARRAY,__VA_ARGS__)
#endif

#endif /* AVUTIL_X86_ASM_H */