1 /* 2 * Copyright(c) 2019-2024 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 #include "qemu/osdep.h" 19 #include "qemu/log.h" 20 #include "exec/exec-all.h" 21 #include "accel/tcg/cpu-ldst.h" 22 #include "accel/tcg/probe.h" 23 #include "exec/helper-proto.h" 24 #include "fpu/softfloat.h" 25 #include "cpu.h" 26 #include "internal.h" 27 #include "macros.h" 28 #include "arch.h" 29 #include "hex_arch_types.h" 30 #include "fma_emu.h" 31 #include "mmvec/mmvec.h" 32 #include "mmvec/macros.h" 33 #include "op_helper.h" 34 #include "translate.h" 35 36 #define SF_BIAS 127 37 #define SF_MANTBITS 23 38 39 /* Exceptions processing helpers */ 40 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env, 41 uint32_t exception, 42 uintptr_t pc) 43 { 44 CPUState *cs = env_cpu(env); 45 qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception); 46 cs->exception_index = exception; 47 cpu_loop_exit_restore(cs, pc); 48 } 49 50 G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp) 51 { 52 hexagon_raise_exception_err(env, excp, 0); 53 } 54 55 void log_store32(CPUHexagonState *env, target_ulong addr, 56 target_ulong val, int width, int slot) 57 { 58 env->mem_log_stores[slot].va = addr; 59 env->mem_log_stores[slot].width = width; 60 env->mem_log_stores[slot].data32 = val; 61 } 62 63 void log_store64(CPUHexagonState *env, target_ulong addr, 64 int64_t val, int width, int slot) 65 { 66 env->mem_log_stores[slot].va = addr; 67 env->mem_log_stores[slot].width = width; 68 env->mem_log_stores[slot].data64 = val; 69 } 70 71 static void commit_store(CPUHexagonState *env, int slot_num, uintptr_t ra) 72 { 73 uint8_t width = env->mem_log_stores[slot_num].width; 74 target_ulong va = env->mem_log_stores[slot_num].va; 75 76 switch (width) { 77 case 1: 78 cpu_stb_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra); 79 break; 80 case 2: 81 cpu_stw_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra); 82 break; 83 case 4: 84 cpu_stl_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra); 85 break; 86 case 8: 87 cpu_stq_data_ra(env, va, env->mem_log_stores[slot_num].data64, ra); 88 break; 89 default: 90 g_assert_not_reached(); 91 } 92 } 93 94 void HELPER(commit_store)(CPUHexagonState *env, int slot_num) 95 { 96 uintptr_t ra = GETPC(); 97 commit_store(env, slot_num, ra); 98 } 99 100 void HELPER(gather_store)(CPUHexagonState *env, uint32_t addr, int slot) 101 { 102 mem_gather_store(env, addr, slot); 103 } 104 105 void HELPER(commit_hvx_stores)(CPUHexagonState *env) 106 { 107 uintptr_t ra = GETPC(); 108 109 /* Normal (possibly masked) vector store */ 110 for (int i = 0; i < VSTORES_MAX; i++) { 111 if (env->vstore_pending[i]) { 112 env->vstore_pending[i] = 0; 113 target_ulong va = env->vstore[i].va; 114 int size = env->vstore[i].size; 115 for (int j = 0; j < size; j++) { 116 if (test_bit(j, env->vstore[i].mask)) { 117 cpu_stb_data_ra(env, va + j, env->vstore[i].data.ub[j], ra); 118 } 119 } 120 } 121 } 122 123 /* Scatter store */ 124 if (env->vtcm_pending) { 125 env->vtcm_pending = false; 126 if (env->vtcm_log.op) { 127 /* Need to perform the scatter read/modify/write at commit time */ 128 if (env->vtcm_log.op_size == 2) { 129 SCATTER_OP_WRITE_TO_MEM(uint16_t); 130 } else if (env->vtcm_log.op_size == 4) { 131 /* Word Scatter += */ 132 SCATTER_OP_WRITE_TO_MEM(uint32_t); 133 } else { 134 g_assert_not_reached(); 135 } 136 } else { 137 for (int i = 0; i < sizeof(MMVector); i++) { 138 if (test_bit(i, env->vtcm_log.mask)) { 139 cpu_stb_data_ra(env, env->vtcm_log.va[i], 140 env->vtcm_log.data.ub[i], ra); 141 clear_bit(i, env->vtcm_log.mask); 142 env->vtcm_log.data.ub[i] = 0; 143 } 144 145 } 146 } 147 } 148 } 149 150 int32_t HELPER(fcircadd)(int32_t RxV, int32_t offset, int32_t M, int32_t CS) 151 { 152 uint32_t K_const = extract32(M, 24, 4); 153 uint32_t length = extract32(M, 0, 17); 154 uint32_t new_ptr = RxV + offset; 155 uint32_t start_addr; 156 uint32_t end_addr; 157 158 if (K_const == 0 && length >= 4) { 159 start_addr = CS; 160 end_addr = start_addr + length; 161 } else { 162 /* 163 * Versions v3 and earlier used the K value to specify a power-of-2 size 164 * 2^(K+2) that is greater than the buffer length 165 */ 166 int32_t mask = (1 << (K_const + 2)) - 1; 167 start_addr = RxV & (~mask); 168 end_addr = start_addr | length; 169 } 170 171 if (new_ptr >= end_addr) { 172 new_ptr -= length; 173 } else if (new_ptr < start_addr) { 174 new_ptr += length; 175 } 176 177 return new_ptr; 178 } 179 180 uint32_t HELPER(fbrev)(uint32_t addr) 181 { 182 /* 183 * Bit reverse the low 16 bits of the address 184 */ 185 return deposit32(addr, 0, 16, revbit16(addr)); 186 } 187 188 static float32 build_float32(uint8_t sign, uint32_t exp, uint32_t mant) 189 { 190 return make_float32( 191 ((sign & 1) << 31) | 192 ((exp & 0xff) << SF_MANTBITS) | 193 (mant & ((1 << SF_MANTBITS) - 1))); 194 } 195 196 /* 197 * sfrecipa, sfinvsqrta have two 32-bit results 198 * r0,p0=sfrecipa(r1,r2) 199 * r0,p0=sfinvsqrta(r1) 200 * 201 * Since helpers can only return a single value, we pack the two results 202 * into a 64-bit value. 203 */ 204 uint64_t HELPER(sfrecipa)(CPUHexagonState *env, float32 RsV, float32 RtV) 205 { 206 int32_t PeV = 0; 207 float32 RdV; 208 int idx; 209 int adjust; 210 int mant; 211 int exp; 212 213 arch_fpop_start(env); 214 if (arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status)) { 215 PeV = adjust; 216 idx = (RtV >> 16) & 0x7f; 217 mant = (recip_lookup_table[idx] << 15) | 1; 218 exp = SF_BIAS - (float32_getexp(RtV) - SF_BIAS) - 1; 219 RdV = build_float32(extract32(RtV, 31, 1), exp, mant); 220 } 221 arch_fpop_end(env); 222 return ((uint64_t)RdV << 32) | PeV; 223 } 224 225 uint64_t HELPER(sfinvsqrta)(CPUHexagonState *env, float32 RsV) 226 { 227 int PeV = 0; 228 float32 RdV; 229 int idx; 230 int adjust; 231 int mant; 232 int exp; 233 234 arch_fpop_start(env); 235 if (arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status)) { 236 PeV = adjust; 237 idx = (RsV >> 17) & 0x7f; 238 mant = (invsqrt_lookup_table[idx] << 15); 239 exp = SF_BIAS - ((float32_getexp(RsV) - SF_BIAS) >> 1) - 1; 240 RdV = build_float32(extract32(RsV, 31, 1), exp, mant); 241 } 242 arch_fpop_end(env); 243 return ((uint64_t)RdV << 32) | PeV; 244 } 245 246 int64_t HELPER(vacsh_val)(CPUHexagonState *env, 247 int64_t RxxV, int64_t RssV, int64_t RttV, 248 uint32_t pkt_need_commit) 249 { 250 for (int i = 0; i < 4; i++) { 251 int xv = sextract64(RxxV, i * 16, 16); 252 int sv = sextract64(RssV, i * 16, 16); 253 int tv = sextract64(RttV, i * 16, 16); 254 int max; 255 xv = xv + tv; 256 sv = sv - tv; 257 max = xv > sv ? xv : sv; 258 /* Note that fSATH can set the OVF bit in usr */ 259 RxxV = deposit64(RxxV, i * 16, 16, fSATH(max)); 260 } 261 return RxxV; 262 } 263 264 int32_t HELPER(vacsh_pred)(CPUHexagonState *env, 265 int64_t RxxV, int64_t RssV, int64_t RttV) 266 { 267 int32_t PeV = 0; 268 for (int i = 0; i < 4; i++) { 269 int xv = sextract64(RxxV, i * 16, 16); 270 int sv = sextract64(RssV, i * 16, 16); 271 int tv = sextract64(RttV, i * 16, 16); 272 xv = xv + tv; 273 sv = sv - tv; 274 PeV = deposit32(PeV, i * 2, 1, (xv > sv)); 275 PeV = deposit32(PeV, i * 2 + 1, 1, (xv > sv)); 276 } 277 return PeV; 278 } 279 280 int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV) 281 { 282 int64_t RddV = 0; 283 size4u_t state; 284 size4u_t valMPS; 285 size4u_t bitpos; 286 size4u_t range; 287 size4u_t offset; 288 size4u_t rLPS; 289 size4u_t rMPS; 290 291 state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0); 292 valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8); 293 bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0); 294 range = fGETWORD(0, RssV); 295 offset = fGETWORD(1, RssV); 296 297 /* calculate rLPS */ 298 range <<= bitpos; 299 offset <<= bitpos; 300 rLPS = rLPS_table_64x4[state][(range >> 29) & 3]; 301 rLPS = rLPS << 23; /* left aligned */ 302 303 /* calculate rMPS */ 304 rMPS = (range & 0xff800000) - rLPS; 305 306 /* most probable region */ 307 if (offset < rMPS) { 308 RddV = AC_next_state_MPS_64[state]; 309 fINSERT_RANGE(RddV, 8, 8, valMPS); 310 fINSERT_RANGE(RddV, 31, 23, (rMPS >> 23)); 311 fSETWORD(1, RddV, offset); 312 } 313 /* least probable region */ 314 else { 315 RddV = AC_next_state_LPS_64[state]; 316 fINSERT_RANGE(RddV, 8, 8, ((!state) ? (1 - valMPS) : (valMPS))); 317 fINSERT_RANGE(RddV, 31, 23, (rLPS >> 23)); 318 fSETWORD(1, RddV, (offset - rMPS)); 319 } 320 return RddV; 321 } 322 323 int32_t HELPER(cabacdecbin_pred)(int64_t RssV, int64_t RttV) 324 { 325 int32_t p0 = 0; 326 size4u_t state; 327 size4u_t valMPS; 328 size4u_t bitpos; 329 size4u_t range; 330 size4u_t offset; 331 size4u_t rLPS; 332 size4u_t rMPS; 333 334 state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0); 335 valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8); 336 bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0); 337 range = fGETWORD(0, RssV); 338 offset = fGETWORD(1, RssV); 339 340 /* calculate rLPS */ 341 range <<= bitpos; 342 offset <<= bitpos; 343 rLPS = rLPS_table_64x4[state][(range >> 29) & 3]; 344 rLPS = rLPS << 23; /* left aligned */ 345 346 /* calculate rMPS */ 347 rMPS = (range & 0xff800000) - rLPS; 348 349 /* most probable region */ 350 if (offset < rMPS) { 351 p0 = valMPS; 352 353 } 354 /* least probable region */ 355 else { 356 p0 = valMPS ^ 1; 357 } 358 return p0; 359 } 360 361 static void probe_store(CPUHexagonState *env, int slot, int mmu_idx, 362 bool is_predicated, uintptr_t retaddr) 363 { 364 if (!is_predicated || !(env->slot_cancelled & (1 << slot))) { 365 size1u_t width = env->mem_log_stores[slot].width; 366 target_ulong va = env->mem_log_stores[slot].va; 367 probe_write(env, va, width, mmu_idx, retaddr); 368 } 369 } 370 371 /* 372 * Called from a mem_noshuf packet to make sure the load doesn't 373 * raise an exception 374 */ 375 void HELPER(probe_noshuf_load)(CPUHexagonState *env, target_ulong va, 376 int size, int mmu_idx) 377 { 378 uintptr_t retaddr = GETPC(); 379 probe_read(env, va, size, mmu_idx, retaddr); 380 } 381 382 /* Called during packet commit when there are two scalar stores */ 383 void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int args) 384 { 385 int mmu_idx = FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX); 386 bool is_predicated = 387 FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED); 388 uintptr_t ra = GETPC(); 389 probe_store(env, 0, mmu_idx, is_predicated, ra); 390 } 391 392 static void probe_hvx_stores(CPUHexagonState *env, int mmu_idx, 393 uintptr_t retaddr) 394 { 395 /* Normal (possibly masked) vector store */ 396 for (int i = 0; i < VSTORES_MAX; i++) { 397 if (env->vstore_pending[i]) { 398 target_ulong va = env->vstore[i].va; 399 int size = env->vstore[i].size; 400 for (int j = 0; j < size; j++) { 401 if (test_bit(j, env->vstore[i].mask)) { 402 probe_write(env, va + j, 1, mmu_idx, retaddr); 403 } 404 } 405 } 406 } 407 408 /* Scatter store */ 409 if (env->vtcm_pending) { 410 if (env->vtcm_log.op) { 411 /* Need to perform the scatter read/modify/write at commit time */ 412 if (env->vtcm_log.op_size == 2) { 413 SCATTER_OP_PROBE_MEM(size2u_t, mmu_idx, retaddr); 414 } else if (env->vtcm_log.op_size == 4) { 415 /* Word Scatter += */ 416 SCATTER_OP_PROBE_MEM(size4u_t, mmu_idx, retaddr); 417 } else { 418 g_assert_not_reached(); 419 } 420 } else { 421 for (int i = 0; i < sizeof(MMVector); i++) { 422 if (test_bit(i, env->vtcm_log.mask)) { 423 probe_write(env, env->vtcm_log.va[i], 1, mmu_idx, retaddr); 424 } 425 426 } 427 } 428 } 429 } 430 431 void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx) 432 { 433 uintptr_t retaddr = GETPC(); 434 probe_hvx_stores(env, mmu_idx, retaddr); 435 } 436 437 void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask) 438 { 439 bool has_st0 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0); 440 bool has_st1 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1); 441 bool has_hvx_stores = 442 FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_HVX_STORES); 443 bool s0_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED); 444 bool s1_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED); 445 int mmu_idx = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX); 446 uintptr_t ra = GETPC(); 447 448 if (has_st0) { 449 probe_store(env, 0, mmu_idx, s0_is_pred, ra); 450 } 451 if (has_st1) { 452 probe_store(env, 1, mmu_idx, s1_is_pred, ra); 453 } 454 if (has_hvx_stores) { 455 probe_hvx_stores(env, mmu_idx, ra); 456 } 457 } 458 459 #ifndef CONFIG_HEXAGON_IDEF_PARSER 460 /* 461 * mem_noshuf 462 * Section 5.5 of the Hexagon V67 Programmer's Reference Manual 463 * 464 * If the load is in slot 0 and there is a store in slot1 (that 465 * wasn't cancelled), we have to do the store first. 466 */ 467 static void check_noshuf(CPUHexagonState *env, bool pkt_has_store_s1, 468 uint32_t slot, target_ulong vaddr, int size, 469 uintptr_t ra) 470 { 471 if (slot == 0 && pkt_has_store_s1 && 472 ((env->slot_cancelled & (1 << 1)) == 0)) { 473 probe_read(env, vaddr, size, MMU_USER_IDX, ra); 474 commit_store(env, 1, ra); 475 } 476 } 477 #endif 478 479 /* Floating point */ 480 float64 HELPER(conv_sf2df)(CPUHexagonState *env, float32 RsV) 481 { 482 float64 out_f64; 483 arch_fpop_start(env); 484 out_f64 = float32_to_float64(RsV, &env->fp_status); 485 arch_fpop_end(env); 486 return out_f64; 487 } 488 489 float32 HELPER(conv_df2sf)(CPUHexagonState *env, float64 RssV) 490 { 491 float32 out_f32; 492 arch_fpop_start(env); 493 out_f32 = float64_to_float32(RssV, &env->fp_status); 494 arch_fpop_end(env); 495 return out_f32; 496 } 497 498 float32 HELPER(conv_uw2sf)(CPUHexagonState *env, int32_t RsV) 499 { 500 float32 RdV; 501 arch_fpop_start(env); 502 RdV = uint32_to_float32(RsV, &env->fp_status); 503 arch_fpop_end(env); 504 return RdV; 505 } 506 507 float64 HELPER(conv_uw2df)(CPUHexagonState *env, int32_t RsV) 508 { 509 float64 RddV; 510 arch_fpop_start(env); 511 RddV = uint32_to_float64(RsV, &env->fp_status); 512 arch_fpop_end(env); 513 return RddV; 514 } 515 516 float32 HELPER(conv_w2sf)(CPUHexagonState *env, int32_t RsV) 517 { 518 float32 RdV; 519 arch_fpop_start(env); 520 RdV = int32_to_float32(RsV, &env->fp_status); 521 arch_fpop_end(env); 522 return RdV; 523 } 524 525 float64 HELPER(conv_w2df)(CPUHexagonState *env, int32_t RsV) 526 { 527 float64 RddV; 528 arch_fpop_start(env); 529 RddV = int32_to_float64(RsV, &env->fp_status); 530 arch_fpop_end(env); 531 return RddV; 532 } 533 534 float32 HELPER(conv_ud2sf)(CPUHexagonState *env, int64_t RssV) 535 { 536 float32 RdV; 537 arch_fpop_start(env); 538 RdV = uint64_to_float32(RssV, &env->fp_status); 539 arch_fpop_end(env); 540 return RdV; 541 } 542 543 float64 HELPER(conv_ud2df)(CPUHexagonState *env, int64_t RssV) 544 { 545 float64 RddV; 546 arch_fpop_start(env); 547 RddV = uint64_to_float64(RssV, &env->fp_status); 548 arch_fpop_end(env); 549 return RddV; 550 } 551 552 float32 HELPER(conv_d2sf)(CPUHexagonState *env, int64_t RssV) 553 { 554 float32 RdV; 555 arch_fpop_start(env); 556 RdV = int64_to_float32(RssV, &env->fp_status); 557 arch_fpop_end(env); 558 return RdV; 559 } 560 561 float64 HELPER(conv_d2df)(CPUHexagonState *env, int64_t RssV) 562 { 563 float64 RddV; 564 arch_fpop_start(env); 565 RddV = int64_to_float64(RssV, &env->fp_status); 566 arch_fpop_end(env); 567 return RddV; 568 } 569 570 uint32_t HELPER(conv_sf2uw)(CPUHexagonState *env, float32 RsV) 571 { 572 uint32_t RdV; 573 arch_fpop_start(env); 574 /* Hexagon checks the sign before rounding */ 575 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) { 576 float_raise(float_flag_invalid, &env->fp_status); 577 RdV = 0; 578 } else { 579 RdV = float32_to_uint32(RsV, &env->fp_status); 580 } 581 arch_fpop_end(env); 582 return RdV; 583 } 584 585 int32_t HELPER(conv_sf2w)(CPUHexagonState *env, float32 RsV) 586 { 587 int32_t RdV; 588 arch_fpop_start(env); 589 /* Hexagon returns -1 for NaN */ 590 if (float32_is_any_nan(RsV)) { 591 float_raise(float_flag_invalid, &env->fp_status); 592 RdV = -1; 593 } else { 594 RdV = float32_to_int32(RsV, &env->fp_status); 595 } 596 arch_fpop_end(env); 597 return RdV; 598 } 599 600 uint64_t HELPER(conv_sf2ud)(CPUHexagonState *env, float32 RsV) 601 { 602 uint64_t RddV; 603 arch_fpop_start(env); 604 /* Hexagon checks the sign before rounding */ 605 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) { 606 float_raise(float_flag_invalid, &env->fp_status); 607 RddV = 0; 608 } else { 609 RddV = float32_to_uint64(RsV, &env->fp_status); 610 } 611 arch_fpop_end(env); 612 return RddV; 613 } 614 615 int64_t HELPER(conv_sf2d)(CPUHexagonState *env, float32 RsV) 616 { 617 int64_t RddV; 618 arch_fpop_start(env); 619 /* Hexagon returns -1 for NaN */ 620 if (float32_is_any_nan(RsV)) { 621 float_raise(float_flag_invalid, &env->fp_status); 622 RddV = -1; 623 } else { 624 RddV = float32_to_int64(RsV, &env->fp_status); 625 } 626 arch_fpop_end(env); 627 return RddV; 628 } 629 630 uint32_t HELPER(conv_df2uw)(CPUHexagonState *env, float64 RssV) 631 { 632 uint32_t RdV; 633 arch_fpop_start(env); 634 /* Hexagon checks the sign before rounding */ 635 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) { 636 float_raise(float_flag_invalid, &env->fp_status); 637 RdV = 0; 638 } else { 639 RdV = float64_to_uint32(RssV, &env->fp_status); 640 } 641 arch_fpop_end(env); 642 return RdV; 643 } 644 645 int32_t HELPER(conv_df2w)(CPUHexagonState *env, float64 RssV) 646 { 647 int32_t RdV; 648 arch_fpop_start(env); 649 /* Hexagon returns -1 for NaN */ 650 if (float64_is_any_nan(RssV)) { 651 float_raise(float_flag_invalid, &env->fp_status); 652 RdV = -1; 653 } else { 654 RdV = float64_to_int32(RssV, &env->fp_status); 655 } 656 arch_fpop_end(env); 657 return RdV; 658 } 659 660 uint64_t HELPER(conv_df2ud)(CPUHexagonState *env, float64 RssV) 661 { 662 uint64_t RddV; 663 arch_fpop_start(env); 664 /* Hexagon checks the sign before rounding */ 665 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) { 666 float_raise(float_flag_invalid, &env->fp_status); 667 RddV = 0; 668 } else { 669 RddV = float64_to_uint64(RssV, &env->fp_status); 670 } 671 arch_fpop_end(env); 672 return RddV; 673 } 674 675 int64_t HELPER(conv_df2d)(CPUHexagonState *env, float64 RssV) 676 { 677 int64_t RddV; 678 arch_fpop_start(env); 679 /* Hexagon returns -1 for NaN */ 680 if (float64_is_any_nan(RssV)) { 681 float_raise(float_flag_invalid, &env->fp_status); 682 RddV = -1; 683 } else { 684 RddV = float64_to_int64(RssV, &env->fp_status); 685 } 686 arch_fpop_end(env); 687 return RddV; 688 } 689 690 uint32_t HELPER(conv_sf2uw_chop)(CPUHexagonState *env, float32 RsV) 691 { 692 uint32_t RdV; 693 arch_fpop_start(env); 694 /* Hexagon checks the sign before rounding */ 695 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) { 696 float_raise(float_flag_invalid, &env->fp_status); 697 RdV = 0; 698 } else { 699 RdV = float32_to_uint32_round_to_zero(RsV, &env->fp_status); 700 } 701 arch_fpop_end(env); 702 return RdV; 703 } 704 705 int32_t HELPER(conv_sf2w_chop)(CPUHexagonState *env, float32 RsV) 706 { 707 int32_t RdV; 708 arch_fpop_start(env); 709 /* Hexagon returns -1 for NaN */ 710 if (float32_is_any_nan(RsV)) { 711 float_raise(float_flag_invalid, &env->fp_status); 712 RdV = -1; 713 } else { 714 RdV = float32_to_int32_round_to_zero(RsV, &env->fp_status); 715 } 716 arch_fpop_end(env); 717 return RdV; 718 } 719 720 uint64_t HELPER(conv_sf2ud_chop)(CPUHexagonState *env, float32 RsV) 721 { 722 uint64_t RddV; 723 arch_fpop_start(env); 724 /* Hexagon checks the sign before rounding */ 725 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) { 726 float_raise(float_flag_invalid, &env->fp_status); 727 RddV = 0; 728 } else { 729 RddV = float32_to_uint64_round_to_zero(RsV, &env->fp_status); 730 } 731 arch_fpop_end(env); 732 return RddV; 733 } 734 735 int64_t HELPER(conv_sf2d_chop)(CPUHexagonState *env, float32 RsV) 736 { 737 int64_t RddV; 738 arch_fpop_start(env); 739 /* Hexagon returns -1 for NaN */ 740 if (float32_is_any_nan(RsV)) { 741 float_raise(float_flag_invalid, &env->fp_status); 742 RddV = -1; 743 } else { 744 RddV = float32_to_int64_round_to_zero(RsV, &env->fp_status); 745 } 746 arch_fpop_end(env); 747 return RddV; 748 } 749 750 uint32_t HELPER(conv_df2uw_chop)(CPUHexagonState *env, float64 RssV) 751 { 752 uint32_t RdV; 753 arch_fpop_start(env); 754 /* Hexagon checks the sign before rounding */ 755 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) { 756 float_raise(float_flag_invalid, &env->fp_status); 757 RdV = 0; 758 } else { 759 RdV = float64_to_uint32_round_to_zero(RssV, &env->fp_status); 760 } 761 arch_fpop_end(env); 762 return RdV; 763 } 764 765 int32_t HELPER(conv_df2w_chop)(CPUHexagonState *env, float64 RssV) 766 { 767 int32_t RdV; 768 arch_fpop_start(env); 769 /* Hexagon returns -1 for NaN */ 770 if (float64_is_any_nan(RssV)) { 771 float_raise(float_flag_invalid, &env->fp_status); 772 RdV = -1; 773 } else { 774 RdV = float64_to_int32_round_to_zero(RssV, &env->fp_status); 775 } 776 arch_fpop_end(env); 777 return RdV; 778 } 779 780 uint64_t HELPER(conv_df2ud_chop)(CPUHexagonState *env, float64 RssV) 781 { 782 uint64_t RddV; 783 arch_fpop_start(env); 784 /* Hexagon checks the sign before rounding */ 785 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) { 786 float_raise(float_flag_invalid, &env->fp_status); 787 RddV = 0; 788 } else { 789 RddV = float64_to_uint64_round_to_zero(RssV, &env->fp_status); 790 } 791 arch_fpop_end(env); 792 return RddV; 793 } 794 795 int64_t HELPER(conv_df2d_chop)(CPUHexagonState *env, float64 RssV) 796 { 797 int64_t RddV; 798 arch_fpop_start(env); 799 /* Hexagon returns -1 for NaN */ 800 if (float64_is_any_nan(RssV)) { 801 float_raise(float_flag_invalid, &env->fp_status); 802 RddV = -1; 803 } else { 804 RddV = float64_to_int64_round_to_zero(RssV, &env->fp_status); 805 } 806 arch_fpop_end(env); 807 return RddV; 808 } 809 810 float32 HELPER(sfadd)(CPUHexagonState *env, float32 RsV, float32 RtV) 811 { 812 float32 RdV; 813 arch_fpop_start(env); 814 RdV = float32_add(RsV, RtV, &env->fp_status); 815 arch_fpop_end(env); 816 return RdV; 817 } 818 819 float32 HELPER(sfsub)(CPUHexagonState *env, float32 RsV, float32 RtV) 820 { 821 float32 RdV; 822 arch_fpop_start(env); 823 RdV = float32_sub(RsV, RtV, &env->fp_status); 824 arch_fpop_end(env); 825 return RdV; 826 } 827 828 int32_t HELPER(sfcmpeq)(CPUHexagonState *env, float32 RsV, float32 RtV) 829 { 830 int32_t PdV; 831 arch_fpop_start(env); 832 PdV = f8BITSOF(float32_eq_quiet(RsV, RtV, &env->fp_status)); 833 arch_fpop_end(env); 834 return PdV; 835 } 836 837 int32_t HELPER(sfcmpgt)(CPUHexagonState *env, float32 RsV, float32 RtV) 838 { 839 int cmp; 840 int32_t PdV; 841 arch_fpop_start(env); 842 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status); 843 PdV = f8BITSOF(cmp == float_relation_greater); 844 arch_fpop_end(env); 845 return PdV; 846 } 847 848 int32_t HELPER(sfcmpge)(CPUHexagonState *env, float32 RsV, float32 RtV) 849 { 850 int cmp; 851 int32_t PdV; 852 arch_fpop_start(env); 853 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status); 854 PdV = f8BITSOF(cmp == float_relation_greater || 855 cmp == float_relation_equal); 856 arch_fpop_end(env); 857 return PdV; 858 } 859 860 int32_t HELPER(sfcmpuo)(CPUHexagonState *env, float32 RsV, float32 RtV) 861 { 862 int32_t PdV; 863 arch_fpop_start(env); 864 PdV = f8BITSOF(float32_unordered_quiet(RsV, RtV, &env->fp_status)); 865 arch_fpop_end(env); 866 return PdV; 867 } 868 869 float32 HELPER(sfmax)(CPUHexagonState *env, float32 RsV, float32 RtV) 870 { 871 float32 RdV; 872 arch_fpop_start(env); 873 RdV = float32_maximum_number(RsV, RtV, &env->fp_status); 874 arch_fpop_end(env); 875 return RdV; 876 } 877 878 float32 HELPER(sfmin)(CPUHexagonState *env, float32 RsV, float32 RtV) 879 { 880 float32 RdV; 881 arch_fpop_start(env); 882 RdV = float32_minimum_number(RsV, RtV, &env->fp_status); 883 arch_fpop_end(env); 884 return RdV; 885 } 886 887 int32_t HELPER(sfclass)(CPUHexagonState *env, float32 RsV, int32_t uiV) 888 { 889 int32_t PdV = 0; 890 arch_fpop_start(env); 891 if (fGETBIT(0, uiV) && float32_is_zero(RsV)) { 892 PdV = 0xff; 893 } 894 if (fGETBIT(1, uiV) && float32_is_normal(RsV)) { 895 PdV = 0xff; 896 } 897 if (fGETBIT(2, uiV) && float32_is_denormal(RsV)) { 898 PdV = 0xff; 899 } 900 if (fGETBIT(3, uiV) && float32_is_infinity(RsV)) { 901 PdV = 0xff; 902 } 903 if (fGETBIT(4, uiV) && float32_is_any_nan(RsV)) { 904 PdV = 0xff; 905 } 906 set_float_exception_flags(0, &env->fp_status); 907 arch_fpop_end(env); 908 return PdV; 909 } 910 911 float32 HELPER(sffixupn)(CPUHexagonState *env, float32 RsV, float32 RtV) 912 { 913 float32 RdV = 0; 914 int adjust; 915 arch_fpop_start(env); 916 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status); 917 RdV = RsV; 918 arch_fpop_end(env); 919 return RdV; 920 } 921 922 float32 HELPER(sffixupd)(CPUHexagonState *env, float32 RsV, float32 RtV) 923 { 924 float32 RdV = 0; 925 int adjust; 926 arch_fpop_start(env); 927 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status); 928 RdV = RtV; 929 arch_fpop_end(env); 930 return RdV; 931 } 932 933 float32 HELPER(sffixupr)(CPUHexagonState *env, float32 RsV) 934 { 935 float32 RdV = 0; 936 int adjust; 937 arch_fpop_start(env); 938 arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status); 939 RdV = RsV; 940 arch_fpop_end(env); 941 return RdV; 942 } 943 944 float64 HELPER(dfadd)(CPUHexagonState *env, float64 RssV, float64 RttV) 945 { 946 float64 RddV; 947 arch_fpop_start(env); 948 RddV = float64_add(RssV, RttV, &env->fp_status); 949 arch_fpop_end(env); 950 return RddV; 951 } 952 953 float64 HELPER(dfsub)(CPUHexagonState *env, float64 RssV, float64 RttV) 954 { 955 float64 RddV; 956 arch_fpop_start(env); 957 RddV = float64_sub(RssV, RttV, &env->fp_status); 958 arch_fpop_end(env); 959 return RddV; 960 } 961 962 float64 HELPER(dfmax)(CPUHexagonState *env, float64 RssV, float64 RttV) 963 { 964 float64 RddV; 965 arch_fpop_start(env); 966 RddV = float64_maximum_number(RssV, RttV, &env->fp_status); 967 arch_fpop_end(env); 968 return RddV; 969 } 970 971 float64 HELPER(dfmin)(CPUHexagonState *env, float64 RssV, float64 RttV) 972 { 973 float64 RddV; 974 arch_fpop_start(env); 975 RddV = float64_minimum_number(RssV, RttV, &env->fp_status); 976 arch_fpop_end(env); 977 return RddV; 978 } 979 980 int32_t HELPER(dfcmpeq)(CPUHexagonState *env, float64 RssV, float64 RttV) 981 { 982 int32_t PdV; 983 arch_fpop_start(env); 984 PdV = f8BITSOF(float64_eq_quiet(RssV, RttV, &env->fp_status)); 985 arch_fpop_end(env); 986 return PdV; 987 } 988 989 int32_t HELPER(dfcmpgt)(CPUHexagonState *env, float64 RssV, float64 RttV) 990 { 991 int cmp; 992 int32_t PdV; 993 arch_fpop_start(env); 994 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status); 995 PdV = f8BITSOF(cmp == float_relation_greater); 996 arch_fpop_end(env); 997 return PdV; 998 } 999 1000 int32_t HELPER(dfcmpge)(CPUHexagonState *env, float64 RssV, float64 RttV) 1001 { 1002 int cmp; 1003 int32_t PdV; 1004 arch_fpop_start(env); 1005 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status); 1006 PdV = f8BITSOF(cmp == float_relation_greater || 1007 cmp == float_relation_equal); 1008 arch_fpop_end(env); 1009 return PdV; 1010 } 1011 1012 int32_t HELPER(dfcmpuo)(CPUHexagonState *env, float64 RssV, float64 RttV) 1013 { 1014 int32_t PdV; 1015 arch_fpop_start(env); 1016 PdV = f8BITSOF(float64_unordered_quiet(RssV, RttV, &env->fp_status)); 1017 arch_fpop_end(env); 1018 return PdV; 1019 } 1020 1021 int32_t HELPER(dfclass)(CPUHexagonState *env, float64 RssV, int32_t uiV) 1022 { 1023 int32_t PdV = 0; 1024 arch_fpop_start(env); 1025 if (fGETBIT(0, uiV) && float64_is_zero(RssV)) { 1026 PdV = 0xff; 1027 } 1028 if (fGETBIT(1, uiV) && float64_is_normal(RssV)) { 1029 PdV = 0xff; 1030 } 1031 if (fGETBIT(2, uiV) && float64_is_denormal(RssV)) { 1032 PdV = 0xff; 1033 } 1034 if (fGETBIT(3, uiV) && float64_is_infinity(RssV)) { 1035 PdV = 0xff; 1036 } 1037 if (fGETBIT(4, uiV) && float64_is_any_nan(RssV)) { 1038 PdV = 0xff; 1039 } 1040 set_float_exception_flags(0, &env->fp_status); 1041 arch_fpop_end(env); 1042 return PdV; 1043 } 1044 1045 float32 HELPER(sfmpy)(CPUHexagonState *env, float32 RsV, float32 RtV) 1046 { 1047 float32 RdV; 1048 arch_fpop_start(env); 1049 RdV = float32_mul(RsV, RtV, &env->fp_status); 1050 arch_fpop_end(env); 1051 return RdV; 1052 } 1053 1054 float32 HELPER(sffma)(CPUHexagonState *env, float32 RxV, 1055 float32 RsV, float32 RtV) 1056 { 1057 arch_fpop_start(env); 1058 RxV = float32_muladd(RsV, RtV, RxV, 0, &env->fp_status); 1059 arch_fpop_end(env); 1060 return RxV; 1061 } 1062 1063 float32 HELPER(sffma_sc)(CPUHexagonState *env, float32 RxV, 1064 float32 RsV, float32 RtV, float32 PuV) 1065 { 1066 arch_fpop_start(env); 1067 RxV = float32_muladd_scalbn(RsV, RtV, RxV, fSXTN(8, 64, PuV), 1068 float_muladd_suppress_add_product_zero, 1069 &env->fp_status); 1070 arch_fpop_end(env); 1071 return RxV; 1072 } 1073 1074 float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV, 1075 float32 RsV, float32 RtV) 1076 { 1077 arch_fpop_start(env); 1078 RxV = float32_muladd(RsV, RtV, RxV, float_muladd_negate_product, 1079 &env->fp_status); 1080 arch_fpop_end(env); 1081 return RxV; 1082 } 1083 1084 static float32 do_sffma_lib(CPUHexagonState *env, float32 RxV, 1085 float32 RsV, float32 RtV, int negate) 1086 { 1087 int flags; 1088 1089 arch_fpop_start(env); 1090 1091 set_float_rounding_mode(float_round_nearest_even_max, &env->fp_status); 1092 RxV = float32_muladd(RsV, RtV, RxV, 1093 negate | float_muladd_suppress_add_product_zero, 1094 &env->fp_status); 1095 1096 flags = get_float_exception_flags(&env->fp_status); 1097 if (flags) { 1098 /* Flags are suppressed by this instruction. */ 1099 set_float_exception_flags(0, &env->fp_status); 1100 1101 /* Return 0 for Inf - Inf. */ 1102 if (flags & float_flag_invalid_isi) { 1103 RxV = 0; 1104 } 1105 } 1106 1107 arch_fpop_end(env); 1108 return RxV; 1109 } 1110 1111 float32 HELPER(sffma_lib)(CPUHexagonState *env, float32 RxV, 1112 float32 RsV, float32 RtV) 1113 { 1114 return do_sffma_lib(env, RxV, RsV, RtV, 0); 1115 } 1116 1117 float32 HELPER(sffms_lib)(CPUHexagonState *env, float32 RxV, 1118 float32 RsV, float32 RtV) 1119 { 1120 return do_sffma_lib(env, RxV, RsV, RtV, float_muladd_negate_product); 1121 } 1122 1123 float64 HELPER(dfmpyfix)(CPUHexagonState *env, float64 RssV, float64 RttV) 1124 { 1125 int64_t RddV; 1126 arch_fpop_start(env); 1127 if (float64_is_denormal(RssV) && 1128 (float64_getexp(RttV) >= 512) && 1129 float64_is_normal(RttV)) { 1130 RddV = float64_mul(RssV, make_float64(0x4330000000000000), 1131 &env->fp_status); 1132 } else if (float64_is_denormal(RttV) && 1133 (float64_getexp(RssV) >= 512) && 1134 float64_is_normal(RssV)) { 1135 RddV = float64_mul(RssV, make_float64(0x3cb0000000000000), 1136 &env->fp_status); 1137 } else { 1138 RddV = RssV; 1139 } 1140 arch_fpop_end(env); 1141 return RddV; 1142 } 1143 1144 float64 HELPER(dfmpyhh)(CPUHexagonState *env, float64 RxxV, 1145 float64 RssV, float64 RttV) 1146 { 1147 arch_fpop_start(env); 1148 RxxV = internal_mpyhh(RssV, RttV, RxxV, &env->fp_status); 1149 arch_fpop_end(env); 1150 return RxxV; 1151 } 1152 1153 /* Histogram instructions */ 1154 1155 void HELPER(vhist)(CPUHexagonState *env) 1156 { 1157 MMVector *input = &env->tmp_VRegs[0]; 1158 1159 for (int lane = 0; lane < 8; lane++) { 1160 for (int i = 0; i < sizeof(MMVector) / 8; ++i) { 1161 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i]; 1162 unsigned char regno = value >> 3; 1163 unsigned char element = value & 7; 1164 1165 env->VRegs[regno].uh[(sizeof(MMVector) / 16) * lane + element]++; 1166 } 1167 } 1168 } 1169 1170 void HELPER(vhistq)(CPUHexagonState *env) 1171 { 1172 MMVector *input = &env->tmp_VRegs[0]; 1173 1174 for (int lane = 0; lane < 8; lane++) { 1175 for (int i = 0; i < sizeof(MMVector) / 8; ++i) { 1176 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i]; 1177 unsigned char regno = value >> 3; 1178 unsigned char element = value & 7; 1179 1180 if (fGETQBIT(env->qtmp, sizeof(MMVector) / 8 * lane + i)) { 1181 env->VRegs[regno].uh[ 1182 (sizeof(MMVector) / 16) * lane + element]++; 1183 } 1184 } 1185 } 1186 } 1187 1188 void HELPER(vwhist256)(CPUHexagonState *env) 1189 { 1190 MMVector *input = &env->tmp_VRegs[0]; 1191 1192 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1193 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1194 unsigned int weight = fGETUBYTE(1, input->h[i]); 1195 unsigned int vindex = (bucket >> 3) & 0x1F; 1196 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7); 1197 1198 env->VRegs[vindex].uh[elindex] = 1199 env->VRegs[vindex].uh[elindex] + weight; 1200 } 1201 } 1202 1203 void HELPER(vwhist256q)(CPUHexagonState *env) 1204 { 1205 MMVector *input = &env->tmp_VRegs[0]; 1206 1207 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1208 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1209 unsigned int weight = fGETUBYTE(1, input->h[i]); 1210 unsigned int vindex = (bucket >> 3) & 0x1F; 1211 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7); 1212 1213 if (fGETQBIT(env->qtmp, 2 * i)) { 1214 env->VRegs[vindex].uh[elindex] = 1215 env->VRegs[vindex].uh[elindex] + weight; 1216 } 1217 } 1218 } 1219 1220 void HELPER(vwhist256_sat)(CPUHexagonState *env) 1221 { 1222 MMVector *input = &env->tmp_VRegs[0]; 1223 1224 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1225 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1226 unsigned int weight = fGETUBYTE(1, input->h[i]); 1227 unsigned int vindex = (bucket >> 3) & 0x1F; 1228 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7); 1229 1230 env->VRegs[vindex].uh[elindex] = 1231 fVSATUH(env->VRegs[vindex].uh[elindex] + weight); 1232 } 1233 } 1234 1235 void HELPER(vwhist256q_sat)(CPUHexagonState *env) 1236 { 1237 MMVector *input = &env->tmp_VRegs[0]; 1238 1239 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1240 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1241 unsigned int weight = fGETUBYTE(1, input->h[i]); 1242 unsigned int vindex = (bucket >> 3) & 0x1F; 1243 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7); 1244 1245 if (fGETQBIT(env->qtmp, 2 * i)) { 1246 env->VRegs[vindex].uh[elindex] = 1247 fVSATUH(env->VRegs[vindex].uh[elindex] + weight); 1248 } 1249 } 1250 } 1251 1252 void HELPER(vwhist128)(CPUHexagonState *env) 1253 { 1254 MMVector *input = &env->tmp_VRegs[0]; 1255 1256 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1257 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1258 unsigned int weight = fGETUBYTE(1, input->h[i]); 1259 unsigned int vindex = (bucket >> 3) & 0x1F; 1260 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3); 1261 1262 env->VRegs[vindex].uw[elindex] = 1263 env->VRegs[vindex].uw[elindex] + weight; 1264 } 1265 } 1266 1267 void HELPER(vwhist128q)(CPUHexagonState *env) 1268 { 1269 MMVector *input = &env->tmp_VRegs[0]; 1270 1271 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1272 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1273 unsigned int weight = fGETUBYTE(1, input->h[i]); 1274 unsigned int vindex = (bucket >> 3) & 0x1F; 1275 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3); 1276 1277 if (fGETQBIT(env->qtmp, 2 * i)) { 1278 env->VRegs[vindex].uw[elindex] = 1279 env->VRegs[vindex].uw[elindex] + weight; 1280 } 1281 } 1282 } 1283 1284 void HELPER(vwhist128m)(CPUHexagonState *env, int32_t uiV) 1285 { 1286 MMVector *input = &env->tmp_VRegs[0]; 1287 1288 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1289 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1290 unsigned int weight = fGETUBYTE(1, input->h[i]); 1291 unsigned int vindex = (bucket >> 3) & 0x1F; 1292 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3); 1293 1294 if ((bucket & 1) == uiV) { 1295 env->VRegs[vindex].uw[elindex] = 1296 env->VRegs[vindex].uw[elindex] + weight; 1297 } 1298 } 1299 } 1300 1301 void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV) 1302 { 1303 MMVector *input = &env->tmp_VRegs[0]; 1304 1305 for (int i = 0; i < (sizeof(MMVector) / 2); i++) { 1306 unsigned int bucket = fGETUBYTE(0, input->h[i]); 1307 unsigned int weight = fGETUBYTE(1, input->h[i]); 1308 unsigned int vindex = (bucket >> 3) & 0x1F; 1309 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3); 1310 1311 if (((bucket & 1) == uiV) && fGETQBIT(env->qtmp, 2 * i)) { 1312 env->VRegs[vindex].uw[elindex] = 1313 env->VRegs[vindex].uw[elindex] + weight; 1314 } 1315 } 1316 } 1317 1318 /* These macros can be referenced in the generated helper functions */ 1319 #define warn(...) /* Nothing */ 1320 #define fatal(...) g_assert_not_reached(); 1321 1322 #define BOGUS_HELPER(tag) \ 1323 printf("ERROR: bogus helper: " #tag "\n") 1324 1325 #include "helper_funcs_generated.c.inc" 1326