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