| 1 | /* |
| 2 | * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by |
| 6 | * the Free Software Foundation; either version 2 of the License, or |
| 7 | * (at your option) any later version. |
| 8 | * |
| 9 | * This program is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
| 16 | */ |
| 17 | |
| 18 | #ifndef HEXAGON_MMVEC_MACROS_H |
| 19 | #define HEXAGON_MMVEC_MACROS_H |
| 20 | |
| 21 | #include "qemu/host-utils.h" |
| 22 | #include "arch.h" |
| 23 | #include "mmvec/system_ext_mmvec.h" |
| 24 | #include "accel/tcg/getpc.h" |
| 25 | #include "accel/tcg/probe.h" |
| 26 | #include "mmvec/hvx_ieee_fp.h" |
| 27 | |
| 28 | #define fBFLOAT() |
| 29 | #define fCVI_VX_NO_TMP_LD() |
| 30 | |
| 31 | #ifndef QEMU_GENERATE |
| 32 | #define VdV (*(MMVector *restrict)(VdV_void)) |
| 33 | #define VsV (*(MMVector *restrict)(VsV_void)) |
| 34 | #define VuV (*(MMVector *restrict)(VuV_void)) |
| 35 | #define VvV (*(MMVector *restrict)(VvV_void)) |
| 36 | #define VwV (*(MMVector *restrict)(VwV_void)) |
| 37 | #define VxV (*(MMVector *restrict)(VxV_void)) |
| 38 | #define VyV (*(MMVector *restrict)(VyV_void)) |
| 39 | |
| 40 | #define VddV (*(MMVectorPair *restrict)(VddV_void)) |
| 41 | #define VuuV (*(MMVectorPair *restrict)(VuuV_void)) |
| 42 | #define VvvV (*(MMVectorPair *restrict)(VvvV_void)) |
| 43 | #define VxxV (*(MMVectorPair *restrict)(VxxV_void)) |
| 44 | |
| 45 | #define QeV (*(MMQReg *restrict)(QeV_void)) |
| 46 | #define QdV (*(MMQReg *restrict)(QdV_void)) |
| 47 | #define QsV (*(MMQReg *restrict)(QsV_void)) |
| 48 | #define QtV (*(MMQReg *restrict)(QtV_void)) |
| 49 | #define QuV (*(MMQReg *restrict)(QuV_void)) |
| 50 | #define QvV (*(MMQReg *restrict)(QvV_void)) |
| 51 | #define QxV (*(MMQReg *restrict)(QxV_void)) |
| 52 | #endif |
| 53 | |
| 54 | #define LOG_VTCM_BYTE(VA, MASK, VAL, IDX) \ |
| 55 | do { \ |
| 56 | env->vtcm_log.data.ub[IDX] = (VAL); \ |
| 57 | if (MASK) { \ |
| 58 | set_bit((IDX), env->vtcm_log.mask); \ |
| 59 | } else { \ |
| 60 | clear_bit((IDX), env->vtcm_log.mask); \ |
| 61 | } \ |
| 62 | env->vtcm_log.va[IDX] = (VA); \ |
| 63 | } while (0) |
| 64 | |
| 65 | #define fNOTQ(VAL) \ |
| 66 | ({ \ |
| 67 | MMQReg _ret; \ |
| 68 | int _i_; \ |
| 69 | for (_i_ = 0; _i_ < fVECSIZE() / 64; _i_++) { \ |
| 70 | _ret.ud[_i_] = ~VAL.ud[_i_]; \ |
| 71 | } \ |
| 72 | _ret;\ |
| 73 | }) |
| 74 | #define fGETQBITS(REG, WIDTH, MASK, BITNO) \ |
| 75 | ((MASK) & (REG.w[(BITNO) >> 5] >> ((BITNO) & 0x1f))) |
| 76 | #define fGETQBIT(REG, BITNO) fGETQBITS(REG, 1, 1, BITNO) |
| 77 | #define fGENMASKW(QREG, IDX) \ |
| 78 | (((fGETQBIT(QREG, (IDX * 4 + 0)) ? 0xFF : 0x0) << 0) | \ |
| 79 | ((fGETQBIT(QREG, (IDX * 4 + 1)) ? 0xFF : 0x0) << 8) | \ |
| 80 | ((fGETQBIT(QREG, (IDX * 4 + 2)) ? 0xFF : 0x0) << 16) | \ |
| 81 | ((fGETQBIT(QREG, (IDX * 4 + 3)) ? 0xFF : 0x0) << 24)) |
| 82 | #define fGETNIBBLE(IDX, SRC) (fSXTN(4, 8, (SRC >> (4 * IDX)) & 0xF)) |
| 83 | #define fGETCRUMB(IDX, SRC) (fSXTN(2, 8, (SRC >> (2 * IDX)) & 0x3)) |
| 84 | #define fGETCRUMB_SYMMETRIC(IDX, SRC) \ |
| 85 | ((fGETCRUMB(IDX, SRC) >= 0 ? (2 - fGETCRUMB(IDX, SRC)) \ |
| 86 | : fGETCRUMB(IDX, SRC))) |
| 87 | #define fGENMASKH(QREG, IDX) \ |
| 88 | (((fGETQBIT(QREG, (IDX * 2 + 0)) ? 0xFF : 0x0) << 0) | \ |
| 89 | ((fGETQBIT(QREG, (IDX * 2 + 1)) ? 0xFF : 0x0) << 8)) |
| 90 | #define fGETMASKW(VREG, QREG, IDX) (VREG.w[IDX] & fGENMASKW((QREG), IDX)) |
| 91 | #define fGETMASKH(VREG, QREG, IDX) (VREG.h[IDX] & fGENMASKH((QREG), IDX)) |
| 92 | #define fCONDMASK8(QREG, IDX, YESVAL, NOVAL) \ |
| 93 | (fGETQBIT(QREG, IDX) ? (YESVAL) : (NOVAL)) |
| 94 | #define fCONDMASK16(QREG, IDX, YESVAL, NOVAL) \ |
| 95 | ((fGENMASKH(QREG, IDX) & (YESVAL)) | \ |
| 96 | (fGENMASKH(fNOTQ(QREG), IDX) & (NOVAL))) |
| 97 | #define fCONDMASK32(QREG, IDX, YESVAL, NOVAL) \ |
| 98 | ((fGENMASKW(QREG, IDX) & (YESVAL)) | \ |
| 99 | (fGENMASKW(fNOTQ(QREG), IDX) & (NOVAL))) |
| 100 | #define fSETQBITS(REG, WIDTH, MASK, BITNO, VAL) \ |
| 101 | do { \ |
| 102 | uint32_t __TMP = (VAL); \ |
| 103 | REG.w[(BITNO) >> 5] &= ~((MASK) << ((BITNO) & 0x1f)); \ |
| 104 | REG.w[(BITNO) >> 5] |= (((__TMP) & (MASK)) << ((BITNO) & 0x1f)); \ |
| 105 | } while (0) |
| 106 | #define fSETQBIT(REG, BITNO, VAL) fSETQBITS(REG, 1, 1, BITNO, VAL) |
| 107 | #define fVBYTES() (fVECSIZE()) |
| 108 | #define fVALIGN(ADDR, LOG2_ALIGNMENT) (ADDR = ADDR & ~(LOG2_ALIGNMENT - 1)) |
| 109 | #define fVLASTBYTE(ADDR, LOG2_ALIGNMENT) (ADDR = ADDR | (LOG2_ALIGNMENT - 1)) |
| 110 | #define fVELEM(WIDTH) ((fVECSIZE() * 8) / WIDTH) |
| 111 | #define fVECLOGSIZE() (7) |
| 112 | #define fVECSIZE() (1 << fVECLOGSIZE()) |
| 113 | #define fSWAPB(A, B) do { uint8_t tmp = A; A = B; B = tmp; } while (0) |
| 114 | #define fV_AL_CHECK(EA, MASK) \ |
| 115 | if ((EA) & (MASK)) { \ |
| 116 | warn("aligning misaligned vector. EA=%08x", (EA)); \ |
| 117 | } |
| 118 | #define fSCATTER_INIT(REGION_START, LENGTH, ELEMENT_SIZE) \ |
| 119 | mem_vector_scatter_init(env) |
| 120 | #define fGATHER_INIT(REGION_START, LENGTH, ELEMENT_SIZE) \ |
| 121 | mem_vector_gather_init(env) |
| 122 | #define fSCATTER_FINISH(OP) |
| 123 | #define fGATHER_FINISH() |
| 124 | #define fLOG_SCATTER_OP(SIZE) \ |
| 125 | do { \ |
| 126 | env->vtcm_log.op = true; \ |
| 127 | env->vtcm_log.op_size = SIZE; \ |
| 128 | } while (0) |
| 129 | #define fVLOG_VTCM_WORD_INCREMENT(EA, OFFSET, INC, IDX, ALIGNMENT, LEN) \ |
| 130 | do { \ |
| 131 | int log_byte = 0; \ |
| 132 | target_ulong va = EA; \ |
| 133 | target_ulong va_high = EA + LEN; \ |
| 134 | for (int i0 = 0; i0 < 4; i0++) { \ |
| 135 | log_byte = (va + i0) <= va_high; \ |
| 136 | LOG_VTCM_BYTE(va + i0, log_byte, INC. ub[4 * IDX + i0], \ |
| 137 | 4 * IDX + i0); \ |
| 138 | } \ |
| 139 | } while (0) |
| 140 | #define fVLOG_VTCM_HALFWORD_INCREMENT(EA, OFFSET, INC, IDX, ALIGNMENT, LEN) \ |
| 141 | do { \ |
| 142 | int log_byte = 0; \ |
| 143 | target_ulong va = EA; \ |
| 144 | target_ulong va_high = EA + LEN; \ |
| 145 | for (int i0 = 0; i0 < 2; i0++) { \ |
| 146 | log_byte = (va + i0) <= va_high; \ |
| 147 | LOG_VTCM_BYTE(va + i0, log_byte, INC.ub[2 * IDX + i0], \ |
| 148 | 2 * IDX + i0); \ |
| 149 | } \ |
| 150 | } while (0) |
| 151 | |
| 152 | #define fVLOG_VTCM_HALFWORD_INCREMENT_DV(EA, OFFSET, INC, IDX, IDX2, IDX_H, \ |
| 153 | ALIGNMENT, LEN) \ |
| 154 | do { \ |
| 155 | int log_byte = 0; \ |
| 156 | target_ulong va = EA; \ |
| 157 | target_ulong va_high = EA + LEN; \ |
| 158 | for (int i0 = 0; i0 < 2; i0++) { \ |
| 159 | log_byte = (va + i0) <= va_high; \ |
| 160 | LOG_VTCM_BYTE(va + i0, log_byte, INC.ub[2 * IDX + i0], \ |
| 161 | 2 * IDX + i0); \ |
| 162 | } \ |
| 163 | } while (0) |
| 164 | |
| 165 | /* NOTE - Will this always be tmp_VRegs[0]; */ |
| 166 | #define GATHER_FUNCTION(EA, OFFSET, IDX, LEN, ELEMENT_SIZE, BANK_IDX, QVAL) \ |
| 167 | do { \ |
| 168 | int i0; \ |
| 169 | target_ulong va = EA; \ |
| 170 | target_ulong va_high = EA + LEN; \ |
| 171 | uintptr_t ra = GETPC(); \ |
| 172 | int log_byte = 0; \ |
| 173 | for (i0 = 0; i0 < ELEMENT_SIZE; i0++) { \ |
| 174 | log_byte = ((va + i0) <= va_high) && QVAL; \ |
| 175 | uint8_t B; \ |
| 176 | B = cpu_ldub_data_ra(env, EA + i0, ra); \ |
| 177 | env->tmp_VRegs[0].ub[ELEMENT_SIZE * IDX + i0] = B; \ |
| 178 | LOG_VTCM_BYTE(va + i0, log_byte, B, ELEMENT_SIZE * IDX + i0); \ |
| 179 | } \ |
| 180 | } while (0) |
| 181 | #define fVLOG_VTCM_GATHER_WORD(EA, OFFSET, IDX, LEN) \ |
| 182 | do { \ |
| 183 | GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, 1); \ |
| 184 | } while (0) |
| 185 | #define fVLOG_VTCM_GATHER_HALFWORD(EA, OFFSET, IDX, LEN) \ |
| 186 | do { \ |
| 187 | GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, 1); \ |
| 188 | } while (0) |
| 189 | #define fVLOG_VTCM_GATHER_HALFWORD_DV(EA, OFFSET, IDX, IDX2, IDX_H, LEN) \ |
| 190 | do { \ |
| 191 | GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, (2 * IDX2 + IDX_H), 1); \ |
| 192 | } while (0) |
| 193 | #define fVLOG_VTCM_GATHER_WORDQ(EA, OFFSET, IDX, Q, LEN) \ |
| 194 | do { \ |
| 195 | GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, \ |
| 196 | fGETQBIT(QsV, 4 * IDX + i0)); \ |
| 197 | } while (0) |
| 198 | #define fVLOG_VTCM_GATHER_HALFWORDQ(EA, OFFSET, IDX, Q, LEN) \ |
| 199 | do { \ |
| 200 | GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, \ |
| 201 | fGETQBIT(QsV, 2 * IDX + i0)); \ |
| 202 | } while (0) |
| 203 | #define fVLOG_VTCM_GATHER_HALFWORDQ_DV(EA, OFFSET, IDX, IDX2, IDX_H, Q, LEN) \ |
| 204 | do { \ |
| 205 | GATHER_FUNCTION(EA, OFFSET, IDX, LEN, 2, (2 * IDX2 + IDX_H), \ |
| 206 | fGETQBIT(QsV, 2 * IDX + i0)); \ |
| 207 | } while (0) |
| 208 | #define SCATTER_OP_WRITE_TO_MEM(TYPE) \ |
| 209 | do { \ |
| 210 | ra = GETPC(); \ |
| 211 | for (int i = 0; i < sizeof(MMVector); i += sizeof(TYPE)) { \ |
| 212 | if (test_bit(i, env->vtcm_log.mask)) { \ |
| 213 | TYPE dst = 0; \ |
| 214 | TYPE inc = 0; \ |
| 215 | for (int j = 0; j < sizeof(TYPE); j++) { \ |
| 216 | uint8_t val; \ |
| 217 | val = cpu_ldub_data_ra(env, env->vtcm_log.va[i + j], ra); \ |
| 218 | dst |= val << (8 * j); \ |
| 219 | inc |= env->vtcm_log.data.ub[j + i] << (8 * j); \ |
| 220 | clear_bit(j + i, env->vtcm_log.mask); \ |
| 221 | env->vtcm_log.data.ub[j + i] = 0; \ |
| 222 | } \ |
| 223 | dst += inc; \ |
| 224 | for (int j = 0; j < sizeof(TYPE); j++) { \ |
| 225 | cpu_stb_data_ra(env, env->vtcm_log.va[i + j], \ |
| 226 | (dst >> (8 * j)) & 0xFF, ra); \ |
| 227 | } \ |
| 228 | } \ |
| 229 | } \ |
| 230 | } while (0) |
| 231 | #define SCATTER_OP_PROBE_MEM(TYPE, MMU_IDX, RETADDR) \ |
| 232 | do { \ |
| 233 | for (int i = 0; i < sizeof(MMVector); i += sizeof(TYPE)) { \ |
| 234 | if (test_bit(i, env->vtcm_log.mask)) { \ |
| 235 | for (int j = 0; j < sizeof(TYPE); j++) { \ |
| 236 | probe_read(env, env->vtcm_log.va[i + j], 1, \ |
| 237 | MMU_IDX, RETADDR); \ |
| 238 | probe_write(env, env->vtcm_log.va[i + j], 1, \ |
| 239 | MMU_IDX, RETADDR); \ |
| 240 | } \ |
| 241 | } \ |
| 242 | } \ |
| 243 | } while (0) |
| 244 | #define SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, ELEM_SIZE, BANK_IDX, QVAL, IN) \ |
| 245 | do { \ |
| 246 | int i0; \ |
| 247 | target_ulong va = EA; \ |
| 248 | target_ulong va_high = EA + LEN; \ |
| 249 | int log_byte = 0; \ |
| 250 | for (i0 = 0; i0 < ELEM_SIZE; i0++) { \ |
| 251 | log_byte = ((va + i0) <= va_high) && QVAL; \ |
| 252 | LOG_VTCM_BYTE(va + i0, log_byte, IN.ub[ELEM_SIZE * IDX + i0], \ |
| 253 | ELEM_SIZE * IDX + i0); \ |
| 254 | } \ |
| 255 | } while (0) |
| 256 | #define fVLOG_VTCM_HALFWORD(EA, OFFSET, IN, IDX, LEN) \ |
| 257 | do { \ |
| 258 | SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, 1, IN); \ |
| 259 | } while (0) |
| 260 | #define fVLOG_VTCM_WORD(EA, OFFSET, IN, IDX, LEN) \ |
| 261 | do { \ |
| 262 | SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, 1, IN); \ |
| 263 | } while (0) |
| 264 | #define fVLOG_VTCM_HALFWORDQ(EA, OFFSET, IN, IDX, Q, LEN) \ |
| 265 | do { \ |
| 266 | SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, IDX, \ |
| 267 | fGETQBIT(QsV, 2 * IDX + i0), IN); \ |
| 268 | } while (0) |
| 269 | #define fVLOG_VTCM_WORDQ(EA, OFFSET, IN, IDX, Q, LEN) \ |
| 270 | do { \ |
| 271 | SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 4, IDX, \ |
| 272 | fGETQBIT(QsV, 4 * IDX + i0), IN); \ |
| 273 | } while (0) |
| 274 | #define fVLOG_VTCM_HALFWORD_DV(EA, OFFSET, IN, IDX, IDX2, IDX_H, LEN) \ |
| 275 | do { \ |
| 276 | SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, \ |
| 277 | (2 * IDX2 + IDX_H), 1, IN); \ |
| 278 | } while (0) |
| 279 | #define fVLOG_VTCM_HALFWORDQ_DV(EA, OFFSET, IN, IDX, Q, IDX2, IDX_H, LEN) \ |
| 280 | do { \ |
| 281 | SCATTER_FUNCTION(EA, OFFSET, IDX, LEN, 2, (2 * IDX2 + IDX_H), \ |
| 282 | fGETQBIT(QsV, 2 * IDX + i0), IN); \ |
| 283 | } while (0) |
| 284 | #define fSTORERELEASE(EA, TYPE) \ |
| 285 | do { \ |
| 286 | fV_AL_CHECK(EA, fVECSIZE() - 1); \ |
| 287 | } while (0) |
| 288 | #ifdef QEMU_GENERATE |
| 289 | #define fLOADMMV(EA, DST) gen_vreg_load(ctx, DST##_off, EA, true) |
| 290 | #endif |
| 291 | #ifdef QEMU_GENERATE |
| 292 | #define fLOADMMVU(EA, DST) gen_vreg_load(ctx, DST##_off, EA, false) |
| 293 | #endif |
| 294 | #ifdef QEMU_GENERATE |
| 295 | #define fSTOREMMV(EA, SRC) \ |
| 296 | gen_vreg_store(ctx, EA, SRC##_off, insn->slot, true) |
| 297 | #endif |
| 298 | #ifdef QEMU_GENERATE |
| 299 | #define fSTOREMMVQ(EA, SRC, MASK) \ |
| 300 | gen_vreg_masked_store(ctx, EA, SRC##_off, MASK##_off, insn->slot, false) |
| 301 | #endif |
| 302 | #ifdef QEMU_GENERATE |
| 303 | #define fSTOREMMVNQ(EA, SRC, MASK) \ |
| 304 | gen_vreg_masked_store(ctx, EA, SRC##_off, MASK##_off, insn->slot, true) |
| 305 | #endif |
| 306 | #ifdef QEMU_GENERATE |
| 307 | #define fSTOREMMVU(EA, SRC) \ |
| 308 | gen_vreg_store(ctx, EA, SRC##_off, insn->slot, false) |
| 309 | #endif |
| 310 | #define fVFOREACH(WIDTH, VAR) for (VAR = 0; VAR < fVELEM(WIDTH); VAR++) |
| 311 | #define fVARRAY_ELEMENT_ACCESS(ARRAY, TYPE, INDEX) \ |
| 312 | ARRAY.v[(INDEX) / (fVECSIZE() / (sizeof(ARRAY.TYPE[0])))].TYPE[(INDEX) % \ |
| 313 | (fVECSIZE() / (sizeof(ARRAY.TYPE[0])))] |
| 314 | |
| 315 | #define fVSATDW(U, V) fVSATW(((((long long)U) << 32) | fZXTN(32, 64, V))) |
| 316 | #define fVASL_SATHI(U, V) fVSATW(((U) << 1) | ((V) >> 31)) |
| 317 | #define fVUADDSAT(WIDTH, U, V) \ |
| 318 | fVSATUN(WIDTH, fZXTN(WIDTH, 2 * WIDTH, U) + fZXTN(WIDTH, 2 * WIDTH, V)) |
| 319 | #define fVSADDSAT(WIDTH, U, V) \ |
| 320 | fVSATN(WIDTH, fSXTN(WIDTH, 2 * WIDTH, U) + fSXTN(WIDTH, 2 * WIDTH, V)) |
| 321 | #define fVUSUBSAT(WIDTH, U, V) \ |
| 322 | fVSATUN(WIDTH, fZXTN(WIDTH, 2 * WIDTH, U) - fZXTN(WIDTH, 2 * WIDTH, V)) |
| 323 | #define fVSSUBSAT(WIDTH, U, V) \ |
| 324 | fVSATN(WIDTH, fSXTN(WIDTH, 2 * WIDTH, U) - fSXTN(WIDTH, 2 * WIDTH, V)) |
| 325 | #define fVAVGU(WIDTH, U, V) \ |
| 326 | ((fZXTN(WIDTH, 2 * WIDTH, U) + fZXTN(WIDTH, 2 * WIDTH, V)) >> 1) |
| 327 | #define fVAVGURND(WIDTH, U, V) \ |
| 328 | ((fZXTN(WIDTH, 2 * WIDTH, U) + fZXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1) |
| 329 | #define fVNAVGU(WIDTH, U, V) \ |
| 330 | ((fZXTN(WIDTH, 2 * WIDTH, U) - fZXTN(WIDTH, 2 * WIDTH, V)) >> 1) |
| 331 | #define fVNAVGURNDSAT(WIDTH, U, V) \ |
| 332 | fVSATUN(WIDTH, ((fZXTN(WIDTH, 2 * WIDTH, U) - \ |
| 333 | fZXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1)) |
| 334 | #define fVAVGS(WIDTH, U, V) \ |
| 335 | ((fSXTN(WIDTH, 2 * WIDTH, U) + fSXTN(WIDTH, 2 * WIDTH, V)) >> 1) |
| 336 | #define fVAVGSRND(WIDTH, U, V) \ |
| 337 | ((fSXTN(WIDTH, 2 * WIDTH, U) + fSXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1) |
| 338 | #define fVNAVGS(WIDTH, U, V) \ |
| 339 | ((fSXTN(WIDTH, 2 * WIDTH, U) - fSXTN(WIDTH, 2 * WIDTH, V)) >> 1) |
| 340 | #define fVNAVGSRND(WIDTH, U, V) \ |
| 341 | ((fSXTN(WIDTH, 2 * WIDTH, U) - fSXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1) |
| 342 | #define fVNAVGSRNDSAT(WIDTH, U, V) \ |
| 343 | fVSATN(WIDTH, ((fSXTN(WIDTH, 2 * WIDTH, U) - \ |
| 344 | fSXTN(WIDTH, 2 * WIDTH, V) + 1) >> 1)) |
| 345 | #define fVNOROUND(VAL, SHAMT) VAL |
| 346 | #define fVNOSAT(VAL) VAL |
| 347 | #define fVROUND(VAL, SHAMT) \ |
| 348 | ((VAL) + (((SHAMT) > 0) ? (1LL << ((SHAMT) - 1)) : 0)) |
| 349 | #define fCARRY_FROM_ADD32(A, B, C) \ |
| 350 | (((fZXTN(32, 64, A) + fZXTN(32, 64, B) + C) >> 32) & 1) |
| 351 | #define fUARCH_NOTE_PUMP_4X() |
| 352 | #define fUARCH_NOTE_PUMP_2X() |
| 353 | |
| 354 | #define IV1DEAD() |
| 355 | |
| 356 | #define fGET10BIT(COE, VAL, POS) \ |
| 357 | do { \ |
| 358 | COE = (sextract32(VAL, 24 + 2 * POS, 2) << 8) | \ |
| 359 | extract32(VAL, POS * 8, 8); \ |
| 360 | } while (0) \ |
| 361 | ; |
| 362 | |
| 363 | #define fCMPGT_SF(A, B) cmpgt_sf(A, B, &env->hvx_fp_status) |
| 364 | #define fCMPGT_HF(A, B) cmpgt_hf(A, B, &env->hvx_fp_status) |
| 365 | #define fCMPGT_BF(A, B) fCMPGT_SF((uint32_t)(A) << 16, (uint32_t)(B) << 16) |
| 366 | |
| 367 | #endif |