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. */ 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. */ 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. */ 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. */ 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. */ 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 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 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 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 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. */ 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. */ 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 */ 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 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