1*538b764dSPeter Maydell /*
2*538b764dSPeter Maydell * ARM generic helpers for various arithmetical operations.
3*538b764dSPeter Maydell *
4*538b764dSPeter Maydell * This code is licensed under the GNU GPL v2 or later.
5*538b764dSPeter Maydell *
6*538b764dSPeter Maydell * SPDX-License-Identifier: GPL-2.0-or-later
7*538b764dSPeter Maydell */
8*538b764dSPeter Maydell #include "qemu/osdep.h"
9*538b764dSPeter Maydell #include "cpu.h"
10*538b764dSPeter Maydell #include "exec/helper-proto.h"
11*538b764dSPeter Maydell #include "qemu/crc32c.h"
12*538b764dSPeter Maydell #include <zlib.h> /* for crc32 */
13*538b764dSPeter Maydell
14*538b764dSPeter Maydell /*
15*538b764dSPeter Maydell * Note that signed overflow is undefined in C. The following routines are
16*538b764dSPeter Maydell * careful to use unsigned types where modulo arithmetic is required.
17*538b764dSPeter Maydell * Failure to do so _will_ break on newer gcc.
18*538b764dSPeter Maydell */
19*538b764dSPeter Maydell
20*538b764dSPeter Maydell /* Signed saturating arithmetic. */
21*538b764dSPeter Maydell
22*538b764dSPeter Maydell /* Perform 16-bit signed saturating addition. */
add16_sat(uint16_t a,uint16_t b)23*538b764dSPeter Maydell static inline uint16_t add16_sat(uint16_t a, uint16_t b)
24*538b764dSPeter Maydell {
25*538b764dSPeter Maydell uint16_t res;
26*538b764dSPeter Maydell
27*538b764dSPeter Maydell res = a + b;
28*538b764dSPeter Maydell if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
29*538b764dSPeter Maydell if (a & 0x8000) {
30*538b764dSPeter Maydell res = 0x8000;
31*538b764dSPeter Maydell } else {
32*538b764dSPeter Maydell res = 0x7fff;
33*538b764dSPeter Maydell }
34*538b764dSPeter Maydell }
35*538b764dSPeter Maydell return res;
36*538b764dSPeter Maydell }
37*538b764dSPeter Maydell
38*538b764dSPeter Maydell /* Perform 8-bit signed saturating addition. */
add8_sat(uint8_t a,uint8_t b)39*538b764dSPeter Maydell static inline uint8_t add8_sat(uint8_t a, uint8_t b)
40*538b764dSPeter Maydell {
41*538b764dSPeter Maydell uint8_t res;
42*538b764dSPeter Maydell
43*538b764dSPeter Maydell res = a + b;
44*538b764dSPeter Maydell if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
45*538b764dSPeter Maydell if (a & 0x80) {
46*538b764dSPeter Maydell res = 0x80;
47*538b764dSPeter Maydell } else {
48*538b764dSPeter Maydell res = 0x7f;
49*538b764dSPeter Maydell }
50*538b764dSPeter Maydell }
51*538b764dSPeter Maydell return res;
52*538b764dSPeter Maydell }
53*538b764dSPeter Maydell
54*538b764dSPeter Maydell /* Perform 16-bit signed saturating subtraction. */
sub16_sat(uint16_t a,uint16_t b)55*538b764dSPeter Maydell static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
56*538b764dSPeter Maydell {
57*538b764dSPeter Maydell uint16_t res;
58*538b764dSPeter Maydell
59*538b764dSPeter Maydell res = a - b;
60*538b764dSPeter Maydell if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
61*538b764dSPeter Maydell if (a & 0x8000) {
62*538b764dSPeter Maydell res = 0x8000;
63*538b764dSPeter Maydell } else {
64*538b764dSPeter Maydell res = 0x7fff;
65*538b764dSPeter Maydell }
66*538b764dSPeter Maydell }
67*538b764dSPeter Maydell return res;
68*538b764dSPeter Maydell }
69*538b764dSPeter Maydell
70*538b764dSPeter Maydell /* Perform 8-bit signed saturating subtraction. */
sub8_sat(uint8_t a,uint8_t b)71*538b764dSPeter Maydell static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
72*538b764dSPeter Maydell {
73*538b764dSPeter Maydell uint8_t res;
74*538b764dSPeter Maydell
75*538b764dSPeter Maydell res = a - b;
76*538b764dSPeter Maydell if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
77*538b764dSPeter Maydell if (a & 0x80) {
78*538b764dSPeter Maydell res = 0x80;
79*538b764dSPeter Maydell } else {
80*538b764dSPeter Maydell res = 0x7f;
81*538b764dSPeter Maydell }
82*538b764dSPeter Maydell }
83*538b764dSPeter Maydell return res;
84*538b764dSPeter Maydell }
85*538b764dSPeter Maydell
86*538b764dSPeter Maydell #define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
87*538b764dSPeter Maydell #define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
88*538b764dSPeter Maydell #define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);
89*538b764dSPeter Maydell #define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);
90*538b764dSPeter Maydell #define PFX q
91*538b764dSPeter Maydell
92*538b764dSPeter Maydell #include "op_addsub.c.inc"
93*538b764dSPeter Maydell
94*538b764dSPeter Maydell /* Unsigned saturating arithmetic. */
add16_usat(uint16_t a,uint16_t b)95*538b764dSPeter Maydell static inline uint16_t add16_usat(uint16_t a, uint16_t b)
96*538b764dSPeter Maydell {
97*538b764dSPeter Maydell uint16_t res;
98*538b764dSPeter Maydell res = a + b;
99*538b764dSPeter Maydell if (res < a) {
100*538b764dSPeter Maydell res = 0xffff;
101*538b764dSPeter Maydell }
102*538b764dSPeter Maydell return res;
103*538b764dSPeter Maydell }
104*538b764dSPeter Maydell
sub16_usat(uint16_t a,uint16_t b)105*538b764dSPeter Maydell static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
106*538b764dSPeter Maydell {
107*538b764dSPeter Maydell if (a > b) {
108*538b764dSPeter Maydell return a - b;
109*538b764dSPeter Maydell } else {
110*538b764dSPeter Maydell return 0;
111*538b764dSPeter Maydell }
112*538b764dSPeter Maydell }
113*538b764dSPeter Maydell
add8_usat(uint8_t a,uint8_t b)114*538b764dSPeter Maydell static inline uint8_t add8_usat(uint8_t a, uint8_t b)
115*538b764dSPeter Maydell {
116*538b764dSPeter Maydell uint8_t res;
117*538b764dSPeter Maydell res = a + b;
118*538b764dSPeter Maydell if (res < a) {
119*538b764dSPeter Maydell res = 0xff;
120*538b764dSPeter Maydell }
121*538b764dSPeter Maydell return res;
122*538b764dSPeter Maydell }
123*538b764dSPeter Maydell
sub8_usat(uint8_t a,uint8_t b)124*538b764dSPeter Maydell static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
125*538b764dSPeter Maydell {
126*538b764dSPeter Maydell if (a > b) {
127*538b764dSPeter Maydell return a - b;
128*538b764dSPeter Maydell } else {
129*538b764dSPeter Maydell return 0;
130*538b764dSPeter Maydell }
131*538b764dSPeter Maydell }
132*538b764dSPeter Maydell
133*538b764dSPeter Maydell #define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
134*538b764dSPeter Maydell #define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
135*538b764dSPeter Maydell #define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);
136*538b764dSPeter Maydell #define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);
137*538b764dSPeter Maydell #define PFX uq
138*538b764dSPeter Maydell
139*538b764dSPeter Maydell #include "op_addsub.c.inc"
140*538b764dSPeter Maydell
141*538b764dSPeter Maydell /* Signed modulo arithmetic. */
142*538b764dSPeter Maydell #define SARITH16(a, b, n, op) do { \
143*538b764dSPeter Maydell int32_t sum; \
144*538b764dSPeter Maydell sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
145*538b764dSPeter Maydell RESULT(sum, n, 16); \
146*538b764dSPeter Maydell if (sum >= 0) \
147*538b764dSPeter Maydell ge |= 3 << (n * 2); \
148*538b764dSPeter Maydell } while (0)
149*538b764dSPeter Maydell
150*538b764dSPeter Maydell #define SARITH8(a, b, n, op) do { \
151*538b764dSPeter Maydell int32_t sum; \
152*538b764dSPeter Maydell sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
153*538b764dSPeter Maydell RESULT(sum, n, 8); \
154*538b764dSPeter Maydell if (sum >= 0) \
155*538b764dSPeter Maydell ge |= 1 << n; \
156*538b764dSPeter Maydell } while (0)
157*538b764dSPeter Maydell
158*538b764dSPeter Maydell
159*538b764dSPeter Maydell #define ADD16(a, b, n) SARITH16(a, b, n, +)
160*538b764dSPeter Maydell #define SUB16(a, b, n) SARITH16(a, b, n, -)
161*538b764dSPeter Maydell #define ADD8(a, b, n) SARITH8(a, b, n, +)
162*538b764dSPeter Maydell #define SUB8(a, b, n) SARITH8(a, b, n, -)
163*538b764dSPeter Maydell #define PFX s
164*538b764dSPeter Maydell #define ARITH_GE
165*538b764dSPeter Maydell
166*538b764dSPeter Maydell #include "op_addsub.c.inc"
167*538b764dSPeter Maydell
168*538b764dSPeter Maydell /* Unsigned modulo arithmetic. */
169*538b764dSPeter Maydell #define ADD16(a, b, n) do { \
170*538b764dSPeter Maydell uint32_t sum; \
171*538b764dSPeter Maydell sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
172*538b764dSPeter Maydell RESULT(sum, n, 16); \
173*538b764dSPeter Maydell if ((sum >> 16) == 1) \
174*538b764dSPeter Maydell ge |= 3 << (n * 2); \
175*538b764dSPeter Maydell } while (0)
176*538b764dSPeter Maydell
177*538b764dSPeter Maydell #define ADD8(a, b, n) do { \
178*538b764dSPeter Maydell uint32_t sum; \
179*538b764dSPeter Maydell sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
180*538b764dSPeter Maydell RESULT(sum, n, 8); \
181*538b764dSPeter Maydell if ((sum >> 8) == 1) \
182*538b764dSPeter Maydell ge |= 1 << n; \
183*538b764dSPeter Maydell } while (0)
184*538b764dSPeter Maydell
185*538b764dSPeter Maydell #define SUB16(a, b, n) do { \
186*538b764dSPeter Maydell uint32_t sum; \
187*538b764dSPeter Maydell sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
188*538b764dSPeter Maydell RESULT(sum, n, 16); \
189*538b764dSPeter Maydell if ((sum >> 16) == 0) \
190*538b764dSPeter Maydell ge |= 3 << (n * 2); \
191*538b764dSPeter Maydell } while (0)
192*538b764dSPeter Maydell
193*538b764dSPeter Maydell #define SUB8(a, b, n) do { \
194*538b764dSPeter Maydell uint32_t sum; \
195*538b764dSPeter Maydell sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
196*538b764dSPeter Maydell RESULT(sum, n, 8); \
197*538b764dSPeter Maydell if ((sum >> 8) == 0) \
198*538b764dSPeter Maydell ge |= 1 << n; \
199*538b764dSPeter Maydell } while (0)
200*538b764dSPeter Maydell
201*538b764dSPeter Maydell #define PFX u
202*538b764dSPeter Maydell #define ARITH_GE
203*538b764dSPeter Maydell
204*538b764dSPeter Maydell #include "op_addsub.c.inc"
205*538b764dSPeter Maydell
206*538b764dSPeter Maydell /* Halved signed arithmetic. */
207*538b764dSPeter Maydell #define ADD16(a, b, n) \
208*538b764dSPeter Maydell RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
209*538b764dSPeter Maydell #define SUB16(a, b, n) \
210*538b764dSPeter Maydell RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
211*538b764dSPeter Maydell #define ADD8(a, b, n) \
212*538b764dSPeter Maydell RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
213*538b764dSPeter Maydell #define SUB8(a, b, n) \
214*538b764dSPeter Maydell RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
215*538b764dSPeter Maydell #define PFX sh
216*538b764dSPeter Maydell
217*538b764dSPeter Maydell #include "op_addsub.c.inc"
218*538b764dSPeter Maydell
219*538b764dSPeter Maydell /* Halved unsigned arithmetic. */
220*538b764dSPeter Maydell #define ADD16(a, b, n) \
221*538b764dSPeter Maydell RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
222*538b764dSPeter Maydell #define SUB16(a, b, n) \
223*538b764dSPeter Maydell RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
224*538b764dSPeter Maydell #define ADD8(a, b, n) \
225*538b764dSPeter Maydell RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
226*538b764dSPeter Maydell #define SUB8(a, b, n) \
227*538b764dSPeter Maydell RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
228*538b764dSPeter Maydell #define PFX uh
229*538b764dSPeter Maydell
230*538b764dSPeter Maydell #include "op_addsub.c.inc"
231*538b764dSPeter Maydell
do_usad(uint8_t a,uint8_t b)232*538b764dSPeter Maydell static inline uint8_t do_usad(uint8_t a, uint8_t b)
233*538b764dSPeter Maydell {
234*538b764dSPeter Maydell if (a > b) {
235*538b764dSPeter Maydell return a - b;
236*538b764dSPeter Maydell } else {
237*538b764dSPeter Maydell return b - a;
238*538b764dSPeter Maydell }
239*538b764dSPeter Maydell }
240*538b764dSPeter Maydell
241*538b764dSPeter Maydell /* Unsigned sum of absolute byte differences. */
HELPER(usad8)242*538b764dSPeter Maydell uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
243*538b764dSPeter Maydell {
244*538b764dSPeter Maydell uint32_t sum;
245*538b764dSPeter Maydell sum = do_usad(a, b);
246*538b764dSPeter Maydell sum += do_usad(a >> 8, b >> 8);
247*538b764dSPeter Maydell sum += do_usad(a >> 16, b >> 16);
248*538b764dSPeter Maydell sum += do_usad(a >> 24, b >> 24);
249*538b764dSPeter Maydell return sum;
250*538b764dSPeter Maydell }
251*538b764dSPeter Maydell
252*538b764dSPeter Maydell /* For ARMv6 SEL instruction. */
HELPER(sel_flags)253*538b764dSPeter Maydell uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
254*538b764dSPeter Maydell {
255*538b764dSPeter Maydell uint32_t mask;
256*538b764dSPeter Maydell
257*538b764dSPeter Maydell mask = 0;
258*538b764dSPeter Maydell if (flags & 1) {
259*538b764dSPeter Maydell mask |= 0xff;
260*538b764dSPeter Maydell }
261*538b764dSPeter Maydell if (flags & 2) {
262*538b764dSPeter Maydell mask |= 0xff00;
263*538b764dSPeter Maydell }
264*538b764dSPeter Maydell if (flags & 4) {
265*538b764dSPeter Maydell mask |= 0xff0000;
266*538b764dSPeter Maydell }
267*538b764dSPeter Maydell if (flags & 8) {
268*538b764dSPeter Maydell mask |= 0xff000000;
269*538b764dSPeter Maydell }
270*538b764dSPeter Maydell return (a & mask) | (b & ~mask);
271*538b764dSPeter Maydell }
272*538b764dSPeter Maydell
273*538b764dSPeter Maydell /*
274*538b764dSPeter Maydell * CRC helpers.
275*538b764dSPeter Maydell * The upper bytes of val (above the number specified by 'bytes') must have
276*538b764dSPeter Maydell * been zeroed out by the caller.
277*538b764dSPeter Maydell */
HELPER(crc32)278*538b764dSPeter Maydell uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes)
279*538b764dSPeter Maydell {
280*538b764dSPeter Maydell uint8_t buf[4];
281*538b764dSPeter Maydell
282*538b764dSPeter Maydell stl_le_p(buf, val);
283*538b764dSPeter Maydell
284*538b764dSPeter Maydell /* zlib crc32 converts the accumulator and output to one's complement. */
285*538b764dSPeter Maydell return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff;
286*538b764dSPeter Maydell }
287*538b764dSPeter Maydell
HELPER(crc32c)288*538b764dSPeter Maydell uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
289*538b764dSPeter Maydell {
290*538b764dSPeter Maydell uint8_t buf[4];
291*538b764dSPeter Maydell
292*538b764dSPeter Maydell stl_le_p(buf, val);
293*538b764dSPeter Maydell
294*538b764dSPeter Maydell /* Linux crc32c converts the output to one's complement. */
295*538b764dSPeter Maydell return crc32c(acc, buf, bytes) ^ 0xffffffff;
296*538b764dSPeter Maydell }
297