FFmpeg
intmath.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2022-2024 Rémi Denis-Courmont.
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 #ifndef AVUTIL_RISCV_INTMATH_H
22 #define AVUTIL_RISCV_INTMATH_H
23 
24 #include <stdint.h>
25 
26 #include "config.h"
27 #include "libavutil/attributes.h"
28 #include "libavutil/riscv/cpu.h"
29 
30 /*
31  * The compiler is forced to sign-extend the result anyhow, so it is faster to
32  * compute it explicitly and use it.
33  */
34 #define av_clip_int8 av_clip_int8_rvi
36 {
37  union { uint8_t u; int8_t s; } u = { .u = a };
38 
39  if (a != u.s)
40  a = ((a >> 31) ^ 0x7F);
41  return a;
42 }
43 
44 #define av_clip_int16 av_clip_int16_rvi
46 {
47  union { uint16_t u; int16_t s; } u = { .u = a };
48 
49  if (a != u.s)
50  a = ((a >> 31) ^ 0x7FFF);
51  return a;
52 }
53 
54 #define av_clipl_int32 av_clipl_int32_rvi
56 {
57  union { uint32_t u; int32_t s; } u = { .u = a };
58 
59  if (a != u.s)
60  a = ((a >> 63) ^ 0x7FFFFFFF);
61  return a;
62 }
63 
64 #define av_clip_intp2 av_clip_intp2_rvi
66 {
67  const int shift = 31 - p;
68  int b = ((int)(((unsigned)a) << shift)) >> shift;
69 
70  if (a != b)
71  b = (a >> 31) ^ ((1 << p) - 1);
72  return b;
73 }
74 
75 #if defined (__GNUC__) || defined (__clang__)
76 static inline av_const int ff_ctz_rv(int x)
77 {
78 #if HAVE_RV && !defined(__riscv_zbb)
79  if (!__builtin_constant_p(x) &&
80  __builtin_expect(ff_rv_zbb_support(), true)) {
81  int y;
82 
83  __asm__ (
84  ".option push\n"
85  ".option arch, +zbb\n"
86 #if __riscv_xlen >= 64
87  "ctzw %0, %1\n"
88 #else
89  "ctz %0, %1\n"
90 #endif
91  ".option pop" : "=r" (y) : "r" (x));
92  if (y > 32)
93  __builtin_unreachable();
94  return y;
95  }
96 #endif
97  return __builtin_ctz(x);
98 }
99 #define ff_ctz ff_ctz_rv
100 
101 static inline av_const int ff_ctzll_rv(long long x)
102 {
103 #if HAVE_RV && !defined(__riscv_zbb) && __riscv_xlen == 64
104  if (!__builtin_constant_p(x) &&
105  __builtin_expect(ff_rv_zbb_support(), true)) {
106  int y;
107 
108  __asm__ (
109  ".option push\n"
110  ".option arch, +zbb\n"
111  "ctz %0, %1\n"
112  ".option pop" : "=r" (y) : "r" (x));
113  if (y > 64)
114  __builtin_unreachable();
115  return y;
116  }
117 #endif
118  return __builtin_ctzll(x);
119 }
120 #define ff_ctzll ff_ctzll_rv
121 
122 static inline av_const int ff_clz_rv(int x)
123 {
124 #if HAVE_RV && !defined(__riscv_zbb)
125  if (!__builtin_constant_p(x) &&
126  __builtin_expect(ff_rv_zbb_support(), true)) {
127  int y;
128 
129  __asm__ (
130  ".option push\n"
131  ".option arch, +zbb\n"
132 #if __riscv_xlen >= 64
133  "clzw %0, %1\n"
134 #else
135  "clz %0, %1\n"
136 #endif
137  ".option pop" : "=r" (y) : "r" (x));
138  if (y > 32)
139  __builtin_unreachable();
140  return y;
141  }
142 #endif
143  return __builtin_clz(x);
144 }
145 #define ff_clz ff_clz_rv
146 
147 #if __riscv_xlen == 64
148 static inline av_const int ff_clzll_rv(long long x)
149 {
150 #if HAVE_RV && !defined(__riscv_zbb)
151  if (!__builtin_constant_p(x) &&
152  __builtin_expect(ff_rv_zbb_support(), true)) {
153  int y;
154 
155  __asm__ (
156  ".option push\n"
157  ".option arch, +zbb\n"
158  "clz %0, %1\n"
159  ".option pop" : "=r" (y) : "r" (x));
160  if (y > 64)
161  __builtin_unreachable();
162  return y;
163  }
164 #endif
165  return __builtin_clzll(x);
166 }
167 #define ff_clz ff_clz_rv
168 #endif
169 
170 static inline av_const int ff_log2_rv(unsigned int x)
171 {
172  return 31 - ff_clz_rv(x | 1);
173 }
174 #define ff_log2 ff_log2_rv
175 #define ff_log2_16bit ff_log2_rv
176 
177 static inline av_const int av_popcount_rv(unsigned int x)
178 {
179 #if HAVE_RV && !defined(__riscv_zbb)
180  if (!__builtin_constant_p(x) &&
181  __builtin_expect(ff_rv_zbb_support(), true)) {
182  int y;
183 
184  __asm__ (
185  ".option push\n"
186  ".option arch, +zbb\n"
187 #if __riscv_xlen >= 64
188  "cpopw %0, %1\n"
189 #else
190  "cpop %0, %1\n"
191 #endif
192  ".option pop" : "=r" (y) : "r" (x));
193  if (y > 32)
194  __builtin_unreachable();
195  return y;
196  }
197 #endif
198  return __builtin_popcount(x);
199 }
200 #define av_popcount av_popcount_rv
201 
202 static inline av_const int av_popcount64_rv(uint64_t x)
203 {
204 #if HAVE_RV && !defined(__riscv_zbb) && __riscv_xlen >= 64
205  if (!__builtin_constant_p(x) &&
206  __builtin_expect(ff_rv_zbb_support(), true)) {
207  int y;
208 
209  __asm__ (
210  ".option push\n"
211  ".option arch, +zbb\n"
212  "cpop %0, %1\n"
213  ".option pop" : "=r" (y) : "r" (x));
214  if (y > 64)
215  __builtin_unreachable();
216  return y;
217  }
218 #endif
219  return __builtin_popcountl(x);
220 }
221 #define av_popcount64 av_popcount64_rv
222 
223 static inline av_const int av_parity_rv(unsigned int x)
224 {
225 #if HAVE_RV && !defined(__riscv_zbb)
226  if (!__builtin_constant_p(x) &&
227  __builtin_expect(ff_rv_zbb_support(), true)) {
228  int y;
229 
230  __asm__ (
231  ".option push\n"
232  ".option arch, +zbb\n"
233 #if __riscv_xlen >= 64
234  "cpopw %0, %1\n"
235 #else
236  "cpop %0, %1\n"
237 #endif
238  ".option pop" : "=r" (y) : "r" (x));
239  return y & 1;
240  }
241 #endif
242  return __builtin_parity(x);
243 }
244 #define av_parity av_parity_rv
245 #endif
246 
247 #endif /* AVUTIL_RISCV_INTMATH_H */
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
av_const
#define av_const
Definition: attributes.h:84
b
#define b
Definition: input.c:41
av_clipl_int32_rvi
static av_always_inline av_const int32_t av_clipl_int32_rvi(int64_t a)
Definition: intmath.h:55
av_clip_int8_rvi
static av_always_inline av_const int8_t av_clip_int8_rvi(int a)
Definition: intmath.h:35
ff_clz_rv
static av_const int ff_clz_rv(int x)
Definition: intmath.h:122
s
#define s(width, name)
Definition: cbs_vp9.c:198
ff_rv_zbb_support
static av_const bool ff_rv_zbb_support(void)
Definition: cpu.h:34
cpu.h
ff_ctzll_rv
static av_const int ff_ctzll_rv(long long x)
Definition: intmath.h:101
av_popcount_rv
static av_const int av_popcount_rv(unsigned int x)
Definition: intmath.h:177
ff_ctz_rv
static av_const int ff_ctz_rv(int x)
Definition: intmath.h:76
shift
static int shift(int a, int b)
Definition: bonk.c:261
ff_log2_rv
static av_const int ff_log2_rv(unsigned int x)
Definition: intmath.h:170
av_clip_intp2_rvi
static av_always_inline av_const int av_clip_intp2_rvi(int a, int p)
Definition: intmath.h:65
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
attributes.h
av_always_inline
#define av_always_inline
Definition: attributes.h:49
av_parity_rv
static av_const int av_parity_rv(unsigned int x)
Definition: intmath.h:223
__asm__
__asm__(".macro parse_r var r\n\t" "\\var = -1\n\t" _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) ".iflt \\var\n\t" ".error \"Unable to parse register name \\r\"\n\t" ".endif\n\t" ".endm")
av_clip_int16_rvi
static av_always_inline av_const int16_t av_clip_int16_rvi(int a)
Definition: intmath.h:45
av_popcount64_rv
static av_const int av_popcount64_rv(uint64_t x)
Definition: intmath.h:202
int32_t
int32_t
Definition: audioconvert.c:56
int
int
Definition: ffmpeg_filter.c:424