1 /* 2 * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library 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 GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 #include "qemu/osdep.h" 18 #include "cpu.h" 19 #include "qemu/host-utils.h" 20 #include "exec/helper-proto.h" 21 #include "exec/exec-all.h" 22 #include "exec/cpu_ldst.h" 23 #include <zlib.h> /* for crc32 */ 24 25 26 /* Exception helpers */ 27 28 static void QEMU_NORETURN 29 raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin, 30 uintptr_t pc, uint32_t fcd_pc) 31 { 32 CPUState *cs = CPU(tricore_env_get_cpu(env)); 33 /* in case we come from a helper-call we need to restore the PC */ 34 if (pc) { 35 cpu_restore_state(cs, pc); 36 } 37 38 /* Tin is loaded into d[15] */ 39 env->gpr_d[15] = tin; 40 41 if (class == TRAPC_CTX_MNG && tin == TIN3_FCU) { 42 /* upper context cannot be saved, if the context list is empty */ 43 } else { 44 helper_svucx(env); 45 } 46 47 /* The return address in a[11] is updated */ 48 if (class == TRAPC_CTX_MNG && tin == TIN3_FCD) { 49 env->SYSCON |= MASK_SYSCON_FCD_SF; 50 /* when we run out of CSAs after saving a context a FCD trap is taken 51 and the return address is the start of the trap handler which used 52 the last CSA */ 53 env->gpr_a[11] = fcd_pc; 54 } else if (class == TRAPC_SYSCALL) { 55 env->gpr_a[11] = env->PC + 4; 56 } else { 57 env->gpr_a[11] = env->PC; 58 } 59 /* The stack pointer in A[10] is set to the Interrupt Stack Pointer (ISP) 60 when the processor was not previously using the interrupt stack 61 (in case of PSW.IS = 0). The stack pointer bit is set for using the 62 interrupt stack: PSW.IS = 1. */ 63 if ((env->PSW & MASK_PSW_IS) == 0) { 64 env->gpr_a[10] = env->ISP; 65 } 66 env->PSW |= MASK_PSW_IS; 67 /* The I/O mode is set to Supervisor mode, which means all permissions 68 are enabled: PSW.IO = 10 B .*/ 69 env->PSW |= (2 << 10); 70 71 /*The current Protection Register Set is set to 0: PSW.PRS = 00 B .*/ 72 env->PSW &= ~MASK_PSW_PRS; 73 74 /* The Call Depth Counter (CDC) is cleared, and the call depth limit is 75 set for 64: PSW.CDC = 0000000 B .*/ 76 env->PSW &= ~MASK_PSW_CDC; 77 78 /* Call Depth Counter is enabled, PSW.CDE = 1. */ 79 env->PSW |= MASK_PSW_CDE; 80 81 /* Write permission to global registers A[0], A[1], A[8], A[9] is 82 disabled: PSW.GW = 0. */ 83 env->PSW &= ~MASK_PSW_GW; 84 85 /*The interrupt system is globally disabled: ICR.IE = 0. The ‘old’ 86 ICR.IE and ICR.CCPN are saved */ 87 88 /* PCXI.PIE = ICR.IE */ 89 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 90 ((env->ICR & MASK_ICR_IE) << 15)); 91 /* PCXI.PCPN = ICR.CCPN */ 92 env->PCXI = (env->PCXI & 0xffffff) + 93 ((env->ICR & MASK_ICR_CCPN) << 24); 94 /* Update PC using the trap vector table */ 95 env->PC = env->BTV | (class << 5); 96 97 cpu_loop_exit(cs); 98 } 99 100 void helper_raise_exception_sync(CPUTriCoreState *env, uint32_t class, 101 uint32_t tin) 102 { 103 raise_exception_sync_internal(env, class, tin, 0, 0); 104 } 105 106 static void raise_exception_sync_helper(CPUTriCoreState *env, uint32_t class, 107 uint32_t tin, uintptr_t pc) 108 { 109 raise_exception_sync_internal(env, class, tin, pc, 0); 110 } 111 112 /* Addressing mode helper */ 113 114 static uint16_t reverse16(uint16_t val) 115 { 116 uint8_t high = (uint8_t)(val >> 8); 117 uint8_t low = (uint8_t)(val & 0xff); 118 119 uint16_t rh, rl; 120 121 rl = (uint16_t)((high * 0x0202020202ULL & 0x010884422010ULL) % 1023); 122 rh = (uint16_t)((low * 0x0202020202ULL & 0x010884422010ULL) % 1023); 123 124 return (rh << 8) | rl; 125 } 126 127 uint32_t helper_br_update(uint32_t reg) 128 { 129 uint32_t index = reg & 0xffff; 130 uint32_t incr = reg >> 16; 131 uint32_t new_index = reverse16(reverse16(index) + reverse16(incr)); 132 return reg - index + new_index; 133 } 134 135 uint32_t helper_circ_update(uint32_t reg, uint32_t off) 136 { 137 uint32_t index = reg & 0xffff; 138 uint32_t length = reg >> 16; 139 int32_t new_index = index + off; 140 if (new_index < 0) { 141 new_index += length; 142 } else { 143 new_index %= length; 144 } 145 return reg - index + new_index; 146 } 147 148 static uint32_t ssov32(CPUTriCoreState *env, int64_t arg) 149 { 150 uint32_t ret; 151 int64_t max_pos = INT32_MAX; 152 int64_t max_neg = INT32_MIN; 153 if (arg > max_pos) { 154 env->PSW_USB_V = (1 << 31); 155 env->PSW_USB_SV = (1 << 31); 156 ret = (target_ulong)max_pos; 157 } else { 158 if (arg < max_neg) { 159 env->PSW_USB_V = (1 << 31); 160 env->PSW_USB_SV = (1 << 31); 161 ret = (target_ulong)max_neg; 162 } else { 163 env->PSW_USB_V = 0; 164 ret = (target_ulong)arg; 165 } 166 } 167 env->PSW_USB_AV = arg ^ arg * 2u; 168 env->PSW_USB_SAV |= env->PSW_USB_AV; 169 return ret; 170 } 171 172 static uint32_t suov32_pos(CPUTriCoreState *env, uint64_t arg) 173 { 174 uint32_t ret; 175 uint64_t max_pos = UINT32_MAX; 176 if (arg > max_pos) { 177 env->PSW_USB_V = (1 << 31); 178 env->PSW_USB_SV = (1 << 31); 179 ret = (target_ulong)max_pos; 180 } else { 181 env->PSW_USB_V = 0; 182 ret = (target_ulong)arg; 183 } 184 env->PSW_USB_AV = arg ^ arg * 2u; 185 env->PSW_USB_SAV |= env->PSW_USB_AV; 186 return ret; 187 } 188 189 static uint32_t suov32_neg(CPUTriCoreState *env, int64_t arg) 190 { 191 uint32_t ret; 192 193 if (arg < 0) { 194 env->PSW_USB_V = (1 << 31); 195 env->PSW_USB_SV = (1 << 31); 196 ret = 0; 197 } else { 198 env->PSW_USB_V = 0; 199 ret = (target_ulong)arg; 200 } 201 env->PSW_USB_AV = arg ^ arg * 2u; 202 env->PSW_USB_SAV |= env->PSW_USB_AV; 203 return ret; 204 } 205 206 static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) 207 { 208 int32_t max_pos = INT16_MAX; 209 int32_t max_neg = INT16_MIN; 210 int32_t av0, av1; 211 212 env->PSW_USB_V = 0; 213 av0 = hw0 ^ hw0 * 2u; 214 if (hw0 > max_pos) { 215 env->PSW_USB_V = (1 << 31); 216 hw0 = max_pos; 217 } else if (hw0 < max_neg) { 218 env->PSW_USB_V = (1 << 31); 219 hw0 = max_neg; 220 } 221 222 av1 = hw1 ^ hw1 * 2u; 223 if (hw1 > max_pos) { 224 env->PSW_USB_V = (1 << 31); 225 hw1 = max_pos; 226 } else if (hw1 < max_neg) { 227 env->PSW_USB_V = (1 << 31); 228 hw1 = max_neg; 229 } 230 231 env->PSW_USB_SV |= env->PSW_USB_V; 232 env->PSW_USB_AV = (av0 | av1) << 16; 233 env->PSW_USB_SAV |= env->PSW_USB_AV; 234 return (hw0 & 0xffff) | (hw1 << 16); 235 } 236 237 static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) 238 { 239 int32_t max_pos = UINT16_MAX; 240 int32_t av0, av1; 241 242 env->PSW_USB_V = 0; 243 av0 = hw0 ^ hw0 * 2u; 244 if (hw0 > max_pos) { 245 env->PSW_USB_V = (1 << 31); 246 hw0 = max_pos; 247 } else if (hw0 < 0) { 248 env->PSW_USB_V = (1 << 31); 249 hw0 = 0; 250 } 251 252 av1 = hw1 ^ hw1 * 2u; 253 if (hw1 > max_pos) { 254 env->PSW_USB_V = (1 << 31); 255 hw1 = max_pos; 256 } else if (hw1 < 0) { 257 env->PSW_USB_V = (1 << 31); 258 hw1 = 0; 259 } 260 261 env->PSW_USB_SV |= env->PSW_USB_V; 262 env->PSW_USB_AV = (av0 | av1) << 16; 263 env->PSW_USB_SAV |= env->PSW_USB_AV; 264 return (hw0 & 0xffff) | (hw1 << 16); 265 } 266 267 target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, 268 target_ulong r2) 269 { 270 int64_t t1 = sextract64(r1, 0, 32); 271 int64_t t2 = sextract64(r2, 0, 32); 272 int64_t result = t1 + t2; 273 return ssov32(env, result); 274 } 275 276 uint64_t helper_add64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) 277 { 278 uint64_t result; 279 int64_t ovf; 280 281 result = r1 + r2; 282 ovf = (result ^ r1) & ~(r1 ^ r2); 283 env->PSW_USB_AV = (result ^ result * 2u) >> 32; 284 env->PSW_USB_SAV |= env->PSW_USB_AV; 285 if (ovf < 0) { 286 env->PSW_USB_V = (1 << 31); 287 env->PSW_USB_SV = (1 << 31); 288 /* ext_ret > MAX_INT */ 289 if ((int64_t)r1 >= 0) { 290 result = INT64_MAX; 291 /* ext_ret < MIN_INT */ 292 } else { 293 result = INT64_MIN; 294 } 295 } else { 296 env->PSW_USB_V = 0; 297 } 298 return result; 299 } 300 301 target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1, 302 target_ulong r2) 303 { 304 int32_t ret_hw0, ret_hw1; 305 306 ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16); 307 ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16); 308 return ssov16(env, ret_hw0, ret_hw1); 309 } 310 311 uint32_t helper_addr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 312 uint32_t r2_h) 313 { 314 int64_t mul_res0 = sextract64(r1, 0, 32); 315 int64_t mul_res1 = sextract64(r1, 32, 32); 316 int64_t r2_low = sextract64(r2_l, 0, 32); 317 int64_t r2_high = sextract64(r2_h, 0, 32); 318 int64_t result0, result1; 319 uint32_t ovf0, ovf1; 320 uint32_t avf0, avf1; 321 322 ovf0 = ovf1 = 0; 323 324 result0 = r2_low + mul_res0 + 0x8000; 325 result1 = r2_high + mul_res1 + 0x8000; 326 327 avf0 = result0 * 2u; 328 avf0 = result0 ^ avf0; 329 avf1 = result1 * 2u; 330 avf1 = result1 ^ avf1; 331 332 if (result0 > INT32_MAX) { 333 ovf0 = (1 << 31); 334 result0 = INT32_MAX; 335 } else if (result0 < INT32_MIN) { 336 ovf0 = (1 << 31); 337 result0 = INT32_MIN; 338 } 339 340 if (result1 > INT32_MAX) { 341 ovf1 = (1 << 31); 342 result1 = INT32_MAX; 343 } else if (result1 < INT32_MIN) { 344 ovf1 = (1 << 31); 345 result1 = INT32_MIN; 346 } 347 348 env->PSW_USB_V = ovf0 | ovf1; 349 env->PSW_USB_SV |= env->PSW_USB_V; 350 351 env->PSW_USB_AV = avf0 | avf1; 352 env->PSW_USB_SAV |= env->PSW_USB_AV; 353 354 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 355 } 356 357 uint32_t helper_addsur_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 358 uint32_t r2_h) 359 { 360 int64_t mul_res0 = sextract64(r1, 0, 32); 361 int64_t mul_res1 = sextract64(r1, 32, 32); 362 int64_t r2_low = sextract64(r2_l, 0, 32); 363 int64_t r2_high = sextract64(r2_h, 0, 32); 364 int64_t result0, result1; 365 uint32_t ovf0, ovf1; 366 uint32_t avf0, avf1; 367 368 ovf0 = ovf1 = 0; 369 370 result0 = r2_low - mul_res0 + 0x8000; 371 result1 = r2_high + mul_res1 + 0x8000; 372 373 avf0 = result0 * 2u; 374 avf0 = result0 ^ avf0; 375 avf1 = result1 * 2u; 376 avf1 = result1 ^ avf1; 377 378 if (result0 > INT32_MAX) { 379 ovf0 = (1 << 31); 380 result0 = INT32_MAX; 381 } else if (result0 < INT32_MIN) { 382 ovf0 = (1 << 31); 383 result0 = INT32_MIN; 384 } 385 386 if (result1 > INT32_MAX) { 387 ovf1 = (1 << 31); 388 result1 = INT32_MAX; 389 } else if (result1 < INT32_MIN) { 390 ovf1 = (1 << 31); 391 result1 = INT32_MIN; 392 } 393 394 env->PSW_USB_V = ovf0 | ovf1; 395 env->PSW_USB_SV |= env->PSW_USB_V; 396 397 env->PSW_USB_AV = avf0 | avf1; 398 env->PSW_USB_SAV |= env->PSW_USB_AV; 399 400 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 401 } 402 403 404 target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, 405 target_ulong r2) 406 { 407 int64_t t1 = extract64(r1, 0, 32); 408 int64_t t2 = extract64(r2, 0, 32); 409 int64_t result = t1 + t2; 410 return suov32_pos(env, result); 411 } 412 413 target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1, 414 target_ulong r2) 415 { 416 int32_t ret_hw0, ret_hw1; 417 418 ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16); 419 ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16); 420 return suov16(env, ret_hw0, ret_hw1); 421 } 422 423 target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, 424 target_ulong r2) 425 { 426 int64_t t1 = sextract64(r1, 0, 32); 427 int64_t t2 = sextract64(r2, 0, 32); 428 int64_t result = t1 - t2; 429 return ssov32(env, result); 430 } 431 432 uint64_t helper_sub64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) 433 { 434 uint64_t result; 435 int64_t ovf; 436 437 result = r1 - r2; 438 ovf = (result ^ r1) & (r1 ^ r2); 439 env->PSW_USB_AV = (result ^ result * 2u) >> 32; 440 env->PSW_USB_SAV |= env->PSW_USB_AV; 441 if (ovf < 0) { 442 env->PSW_USB_V = (1 << 31); 443 env->PSW_USB_SV = (1 << 31); 444 /* ext_ret > MAX_INT */ 445 if ((int64_t)r1 >= 0) { 446 result = INT64_MAX; 447 /* ext_ret < MIN_INT */ 448 } else { 449 result = INT64_MIN; 450 } 451 } else { 452 env->PSW_USB_V = 0; 453 } 454 return result; 455 } 456 457 target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1, 458 target_ulong r2) 459 { 460 int32_t ret_hw0, ret_hw1; 461 462 ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16); 463 ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16); 464 return ssov16(env, ret_hw0, ret_hw1); 465 } 466 467 uint32_t helper_subr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 468 uint32_t r2_h) 469 { 470 int64_t mul_res0 = sextract64(r1, 0, 32); 471 int64_t mul_res1 = sextract64(r1, 32, 32); 472 int64_t r2_low = sextract64(r2_l, 0, 32); 473 int64_t r2_high = sextract64(r2_h, 0, 32); 474 int64_t result0, result1; 475 uint32_t ovf0, ovf1; 476 uint32_t avf0, avf1; 477 478 ovf0 = ovf1 = 0; 479 480 result0 = r2_low - mul_res0 + 0x8000; 481 result1 = r2_high - mul_res1 + 0x8000; 482 483 avf0 = result0 * 2u; 484 avf0 = result0 ^ avf0; 485 avf1 = result1 * 2u; 486 avf1 = result1 ^ avf1; 487 488 if (result0 > INT32_MAX) { 489 ovf0 = (1 << 31); 490 result0 = INT32_MAX; 491 } else if (result0 < INT32_MIN) { 492 ovf0 = (1 << 31); 493 result0 = INT32_MIN; 494 } 495 496 if (result1 > INT32_MAX) { 497 ovf1 = (1 << 31); 498 result1 = INT32_MAX; 499 } else if (result1 < INT32_MIN) { 500 ovf1 = (1 << 31); 501 result1 = INT32_MIN; 502 } 503 504 env->PSW_USB_V = ovf0 | ovf1; 505 env->PSW_USB_SV |= env->PSW_USB_V; 506 507 env->PSW_USB_AV = avf0 | avf1; 508 env->PSW_USB_SAV |= env->PSW_USB_AV; 509 510 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 511 } 512 513 uint32_t helper_subadr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 514 uint32_t r2_h) 515 { 516 int64_t mul_res0 = sextract64(r1, 0, 32); 517 int64_t mul_res1 = sextract64(r1, 32, 32); 518 int64_t r2_low = sextract64(r2_l, 0, 32); 519 int64_t r2_high = sextract64(r2_h, 0, 32); 520 int64_t result0, result1; 521 uint32_t ovf0, ovf1; 522 uint32_t avf0, avf1; 523 524 ovf0 = ovf1 = 0; 525 526 result0 = r2_low + mul_res0 + 0x8000; 527 result1 = r2_high - mul_res1 + 0x8000; 528 529 avf0 = result0 * 2u; 530 avf0 = result0 ^ avf0; 531 avf1 = result1 * 2u; 532 avf1 = result1 ^ avf1; 533 534 if (result0 > INT32_MAX) { 535 ovf0 = (1 << 31); 536 result0 = INT32_MAX; 537 } else if (result0 < INT32_MIN) { 538 ovf0 = (1 << 31); 539 result0 = INT32_MIN; 540 } 541 542 if (result1 > INT32_MAX) { 543 ovf1 = (1 << 31); 544 result1 = INT32_MAX; 545 } else if (result1 < INT32_MIN) { 546 ovf1 = (1 << 31); 547 result1 = INT32_MIN; 548 } 549 550 env->PSW_USB_V = ovf0 | ovf1; 551 env->PSW_USB_SV |= env->PSW_USB_V; 552 553 env->PSW_USB_AV = avf0 | avf1; 554 env->PSW_USB_SAV |= env->PSW_USB_AV; 555 556 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 557 } 558 559 target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, 560 target_ulong r2) 561 { 562 int64_t t1 = extract64(r1, 0, 32); 563 int64_t t2 = extract64(r2, 0, 32); 564 int64_t result = t1 - t2; 565 return suov32_neg(env, result); 566 } 567 568 target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1, 569 target_ulong r2) 570 { 571 int32_t ret_hw0, ret_hw1; 572 573 ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16); 574 ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16); 575 return suov16(env, ret_hw0, ret_hw1); 576 } 577 578 target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, 579 target_ulong r2) 580 { 581 int64_t t1 = sextract64(r1, 0, 32); 582 int64_t t2 = sextract64(r2, 0, 32); 583 int64_t result = t1 * t2; 584 return ssov32(env, result); 585 } 586 587 target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, 588 target_ulong r2) 589 { 590 int64_t t1 = extract64(r1, 0, 32); 591 int64_t t2 = extract64(r2, 0, 32); 592 int64_t result = t1 * t2; 593 594 return suov32_pos(env, result); 595 } 596 597 target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, 598 target_ulong r2) 599 { 600 int64_t t1 = sextract64(r1, 0, 32); 601 int32_t t2 = sextract64(r2, 0, 6); 602 int64_t result; 603 if (t2 == 0) { 604 result = t1; 605 } else if (t2 > 0) { 606 result = t1 << t2; 607 } else { 608 result = t1 >> -t2; 609 } 610 return ssov32(env, result); 611 } 612 613 uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1) 614 { 615 target_ulong result; 616 result = ((int32_t)r1 >= 0) ? r1 : (0 - r1); 617 return ssov32(env, result); 618 } 619 620 uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1) 621 { 622 int32_t ret_h0, ret_h1; 623 624 ret_h0 = sextract32(r1, 0, 16); 625 ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0); 626 627 ret_h1 = sextract32(r1, 16, 16); 628 ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1); 629 630 return ssov16(env, ret_h0, ret_h1); 631 } 632 633 target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, 634 target_ulong r2) 635 { 636 int64_t t1 = sextract64(r1, 0, 32); 637 int64_t t2 = sextract64(r2, 0, 32); 638 int64_t result; 639 640 if (t1 > t2) { 641 result = t1 - t2; 642 } else { 643 result = t2 - t1; 644 } 645 return ssov32(env, result); 646 } 647 648 uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1, 649 target_ulong r2) 650 { 651 int32_t t1, t2; 652 int32_t ret_h0, ret_h1; 653 654 t1 = sextract32(r1, 0, 16); 655 t2 = sextract32(r2, 0, 16); 656 if (t1 > t2) { 657 ret_h0 = t1 - t2; 658 } else { 659 ret_h0 = t2 - t1; 660 } 661 662 t1 = sextract32(r1, 16, 16); 663 t2 = sextract32(r2, 16, 16); 664 if (t1 > t2) { 665 ret_h1 = t1 - t2; 666 } else { 667 ret_h1 = t2 - t1; 668 } 669 670 return ssov16(env, ret_h0, ret_h1); 671 } 672 673 target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, 674 target_ulong r2, target_ulong r3) 675 { 676 int64_t t1 = sextract64(r1, 0, 32); 677 int64_t t2 = sextract64(r2, 0, 32); 678 int64_t t3 = sextract64(r3, 0, 32); 679 int64_t result; 680 681 result = t2 + (t1 * t3); 682 return ssov32(env, result); 683 } 684 685 target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, 686 target_ulong r2, target_ulong r3) 687 { 688 uint64_t t1 = extract64(r1, 0, 32); 689 uint64_t t2 = extract64(r2, 0, 32); 690 uint64_t t3 = extract64(r3, 0, 32); 691 int64_t result; 692 693 result = t2 + (t1 * t3); 694 return suov32_pos(env, result); 695 } 696 697 uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, 698 uint64_t r2, target_ulong r3) 699 { 700 uint64_t ret, ovf; 701 int64_t t1 = sextract64(r1, 0, 32); 702 int64_t t3 = sextract64(r3, 0, 32); 703 int64_t mul; 704 705 mul = t1 * t3; 706 ret = mul + r2; 707 ovf = (ret ^ mul) & ~(mul ^ r2); 708 709 t1 = ret >> 32; 710 env->PSW_USB_AV = t1 ^ t1 * 2u; 711 env->PSW_USB_SAV |= env->PSW_USB_AV; 712 713 if ((int64_t)ovf < 0) { 714 env->PSW_USB_V = (1 << 31); 715 env->PSW_USB_SV = (1 << 31); 716 /* ext_ret > MAX_INT */ 717 if (mul >= 0) { 718 ret = INT64_MAX; 719 /* ext_ret < MIN_INT */ 720 } else { 721 ret = INT64_MIN; 722 } 723 } else { 724 env->PSW_USB_V = 0; 725 } 726 727 return ret; 728 } 729 730 uint32_t 731 helper_madd32_q_add_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) 732 { 733 int64_t result; 734 735 result = (r1 + r2); 736 737 env->PSW_USB_AV = (result ^ result * 2u); 738 env->PSW_USB_SAV |= env->PSW_USB_AV; 739 740 /* we do the saturation by hand, since we produce an overflow on the host 741 if the mul before was (0x80000000 * 0x80000000) << 1). If this is the 742 case, we flip the saturated value. */ 743 if (r2 == 0x8000000000000000LL) { 744 if (result > 0x7fffffffLL) { 745 env->PSW_USB_V = (1 << 31); 746 env->PSW_USB_SV = (1 << 31); 747 result = INT32_MIN; 748 } else if (result < -0x80000000LL) { 749 env->PSW_USB_V = (1 << 31); 750 env->PSW_USB_SV = (1 << 31); 751 result = INT32_MAX; 752 } else { 753 env->PSW_USB_V = 0; 754 } 755 } else { 756 if (result > 0x7fffffffLL) { 757 env->PSW_USB_V = (1 << 31); 758 env->PSW_USB_SV = (1 << 31); 759 result = INT32_MAX; 760 } else if (result < -0x80000000LL) { 761 env->PSW_USB_V = (1 << 31); 762 env->PSW_USB_SV = (1 << 31); 763 result = INT32_MIN; 764 } else { 765 env->PSW_USB_V = 0; 766 } 767 } 768 return (uint32_t)result; 769 } 770 771 uint64_t helper_madd64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2, 772 uint32_t r3, uint32_t n) 773 { 774 int64_t t1 = (int64_t)r1; 775 int64_t t2 = sextract64(r2, 0, 32); 776 int64_t t3 = sextract64(r3, 0, 32); 777 int64_t result, mul; 778 int64_t ovf; 779 780 mul = (t2 * t3) << n; 781 result = mul + t1; 782 783 env->PSW_USB_AV = (result ^ result * 2u) >> 32; 784 env->PSW_USB_SAV |= env->PSW_USB_AV; 785 786 ovf = (result ^ mul) & ~(mul ^ t1); 787 /* we do the saturation by hand, since we produce an overflow on the host 788 if the mul was (0x80000000 * 0x80000000) << 1). If this is the 789 case, we flip the saturated value. */ 790 if ((r2 == 0x80000000) && (r3 == 0x80000000) && (n == 1)) { 791 if (ovf >= 0) { 792 env->PSW_USB_V = (1 << 31); 793 env->PSW_USB_SV = (1 << 31); 794 /* ext_ret > MAX_INT */ 795 if (mul < 0) { 796 result = INT64_MAX; 797 /* ext_ret < MIN_INT */ 798 } else { 799 result = INT64_MIN; 800 } 801 } else { 802 env->PSW_USB_V = 0; 803 } 804 } else { 805 if (ovf < 0) { 806 env->PSW_USB_V = (1 << 31); 807 env->PSW_USB_SV = (1 << 31); 808 /* ext_ret > MAX_INT */ 809 if (mul >= 0) { 810 result = INT64_MAX; 811 /* ext_ret < MIN_INT */ 812 } else { 813 result = INT64_MIN; 814 } 815 } else { 816 env->PSW_USB_V = 0; 817 } 818 } 819 return (uint64_t)result; 820 } 821 822 uint32_t helper_maddr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2, 823 uint32_t r3, uint32_t n) 824 { 825 int64_t t1 = sextract64(r1, 0, 32); 826 int64_t t2 = sextract64(r2, 0, 32); 827 int64_t t3 = sextract64(r3, 0, 32); 828 int64_t mul, ret; 829 830 if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { 831 mul = 0x7fffffff; 832 } else { 833 mul = (t2 * t3) << n; 834 } 835 836 ret = t1 + mul + 0x8000; 837 838 env->PSW_USB_AV = ret ^ ret * 2u; 839 env->PSW_USB_SAV |= env->PSW_USB_AV; 840 841 if (ret > 0x7fffffffll) { 842 env->PSW_USB_V = (1 << 31); 843 env->PSW_USB_SV |= env->PSW_USB_V; 844 ret = INT32_MAX; 845 } else if (ret < -0x80000000ll) { 846 env->PSW_USB_V = (1 << 31); 847 env->PSW_USB_SV |= env->PSW_USB_V; 848 ret = INT32_MIN; 849 } else { 850 env->PSW_USB_V = 0; 851 } 852 return ret & 0xffff0000ll; 853 } 854 855 uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1, 856 uint64_t r2, target_ulong r3) 857 { 858 uint64_t ret, mul; 859 uint64_t t1 = extract64(r1, 0, 32); 860 uint64_t t3 = extract64(r3, 0, 32); 861 862 mul = t1 * t3; 863 ret = mul + r2; 864 865 t1 = ret >> 32; 866 env->PSW_USB_AV = t1 ^ t1 * 2u; 867 env->PSW_USB_SAV |= env->PSW_USB_AV; 868 869 if (ret < r2) { 870 env->PSW_USB_V = (1 << 31); 871 env->PSW_USB_SV = (1 << 31); 872 /* saturate */ 873 ret = UINT64_MAX; 874 } else { 875 env->PSW_USB_V = 0; 876 } 877 return ret; 878 } 879 880 target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1, 881 target_ulong r2, target_ulong r3) 882 { 883 int64_t t1 = sextract64(r1, 0, 32); 884 int64_t t2 = sextract64(r2, 0, 32); 885 int64_t t3 = sextract64(r3, 0, 32); 886 int64_t result; 887 888 result = t2 - (t1 * t3); 889 return ssov32(env, result); 890 } 891 892 target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, 893 target_ulong r2, target_ulong r3) 894 { 895 uint64_t t1 = extract64(r1, 0, 32); 896 uint64_t t2 = extract64(r2, 0, 32); 897 uint64_t t3 = extract64(r3, 0, 32); 898 uint64_t result; 899 uint64_t mul; 900 901 mul = (t1 * t3); 902 result = t2 - mul; 903 904 env->PSW_USB_AV = result ^ result * 2u; 905 env->PSW_USB_SAV |= env->PSW_USB_AV; 906 /* we calculate ovf by hand here, because the multiplication can overflow on 907 the host, which would give false results if we compare to less than 908 zero */ 909 if (mul > t2) { 910 env->PSW_USB_V = (1 << 31); 911 env->PSW_USB_SV = (1 << 31); 912 result = 0; 913 } else { 914 env->PSW_USB_V = 0; 915 } 916 return result; 917 } 918 919 uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, 920 uint64_t r2, target_ulong r3) 921 { 922 uint64_t ret, ovf; 923 int64_t t1 = sextract64(r1, 0, 32); 924 int64_t t3 = sextract64(r3, 0, 32); 925 int64_t mul; 926 927 mul = t1 * t3; 928 ret = r2 - mul; 929 ovf = (ret ^ r2) & (mul ^ r2); 930 931 t1 = ret >> 32; 932 env->PSW_USB_AV = t1 ^ t1 * 2u; 933 env->PSW_USB_SAV |= env->PSW_USB_AV; 934 935 if ((int64_t)ovf < 0) { 936 env->PSW_USB_V = (1 << 31); 937 env->PSW_USB_SV = (1 << 31); 938 /* ext_ret > MAX_INT */ 939 if (mul < 0) { 940 ret = INT64_MAX; 941 /* ext_ret < MIN_INT */ 942 } else { 943 ret = INT64_MIN; 944 } 945 } else { 946 env->PSW_USB_V = 0; 947 } 948 return ret; 949 } 950 951 uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1, 952 uint64_t r2, target_ulong r3) 953 { 954 uint64_t ret, mul; 955 uint64_t t1 = extract64(r1, 0, 32); 956 uint64_t t3 = extract64(r3, 0, 32); 957 958 mul = t1 * t3; 959 ret = r2 - mul; 960 961 t1 = ret >> 32; 962 env->PSW_USB_AV = t1 ^ t1 * 2u; 963 env->PSW_USB_SAV |= env->PSW_USB_AV; 964 965 if (ret > r2) { 966 env->PSW_USB_V = (1 << 31); 967 env->PSW_USB_SV = (1 << 31); 968 /* saturate */ 969 ret = 0; 970 } else { 971 env->PSW_USB_V = 0; 972 } 973 return ret; 974 } 975 976 uint32_t 977 helper_msub32_q_sub_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2) 978 { 979 int64_t result; 980 int64_t t1 = (int64_t)r1; 981 int64_t t2 = (int64_t)r2; 982 983 result = t1 - t2; 984 985 env->PSW_USB_AV = (result ^ result * 2u); 986 env->PSW_USB_SAV |= env->PSW_USB_AV; 987 988 /* we do the saturation by hand, since we produce an overflow on the host 989 if the mul before was (0x80000000 * 0x80000000) << 1). If this is the 990 case, we flip the saturated value. */ 991 if (r2 == 0x8000000000000000LL) { 992 if (result > 0x7fffffffLL) { 993 env->PSW_USB_V = (1 << 31); 994 env->PSW_USB_SV = (1 << 31); 995 result = INT32_MIN; 996 } else if (result < -0x80000000LL) { 997 env->PSW_USB_V = (1 << 31); 998 env->PSW_USB_SV = (1 << 31); 999 result = INT32_MAX; 1000 } else { 1001 env->PSW_USB_V = 0; 1002 } 1003 } else { 1004 if (result > 0x7fffffffLL) { 1005 env->PSW_USB_V = (1 << 31); 1006 env->PSW_USB_SV = (1 << 31); 1007 result = INT32_MAX; 1008 } else if (result < -0x80000000LL) { 1009 env->PSW_USB_V = (1 << 31); 1010 env->PSW_USB_SV = (1 << 31); 1011 result = INT32_MIN; 1012 } else { 1013 env->PSW_USB_V = 0; 1014 } 1015 } 1016 return (uint32_t)result; 1017 } 1018 1019 uint64_t helper_msub64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2, 1020 uint32_t r3, uint32_t n) 1021 { 1022 int64_t t1 = (int64_t)r1; 1023 int64_t t2 = sextract64(r2, 0, 32); 1024 int64_t t3 = sextract64(r3, 0, 32); 1025 int64_t result, mul; 1026 int64_t ovf; 1027 1028 mul = (t2 * t3) << n; 1029 result = t1 - mul; 1030 1031 env->PSW_USB_AV = (result ^ result * 2u) >> 32; 1032 env->PSW_USB_SAV |= env->PSW_USB_AV; 1033 1034 ovf = (result ^ t1) & (t1 ^ mul); 1035 /* we do the saturation by hand, since we produce an overflow on the host 1036 if the mul before was (0x80000000 * 0x80000000) << 1). If this is the 1037 case, we flip the saturated value. */ 1038 if (mul == 0x8000000000000000LL) { 1039 if (ovf >= 0) { 1040 env->PSW_USB_V = (1 << 31); 1041 env->PSW_USB_SV = (1 << 31); 1042 /* ext_ret > MAX_INT */ 1043 if (mul >= 0) { 1044 result = INT64_MAX; 1045 /* ext_ret < MIN_INT */ 1046 } else { 1047 result = INT64_MIN; 1048 } 1049 } else { 1050 env->PSW_USB_V = 0; 1051 } 1052 } else { 1053 if (ovf < 0) { 1054 env->PSW_USB_V = (1 << 31); 1055 env->PSW_USB_SV = (1 << 31); 1056 /* ext_ret > MAX_INT */ 1057 if (mul < 0) { 1058 result = INT64_MAX; 1059 /* ext_ret < MIN_INT */ 1060 } else { 1061 result = INT64_MIN; 1062 } 1063 } else { 1064 env->PSW_USB_V = 0; 1065 } 1066 } 1067 1068 return (uint64_t)result; 1069 } 1070 1071 uint32_t helper_msubr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2, 1072 uint32_t r3, uint32_t n) 1073 { 1074 int64_t t1 = sextract64(r1, 0, 32); 1075 int64_t t2 = sextract64(r2, 0, 32); 1076 int64_t t3 = sextract64(r3, 0, 32); 1077 int64_t mul, ret; 1078 1079 if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { 1080 mul = 0x7fffffff; 1081 } else { 1082 mul = (t2 * t3) << n; 1083 } 1084 1085 ret = t1 - mul + 0x8000; 1086 1087 env->PSW_USB_AV = ret ^ ret * 2u; 1088 env->PSW_USB_SAV |= env->PSW_USB_AV; 1089 1090 if (ret > 0x7fffffffll) { 1091 env->PSW_USB_V = (1 << 31); 1092 env->PSW_USB_SV |= env->PSW_USB_V; 1093 ret = INT32_MAX; 1094 } else if (ret < -0x80000000ll) { 1095 env->PSW_USB_V = (1 << 31); 1096 env->PSW_USB_SV |= env->PSW_USB_V; 1097 ret = INT32_MIN; 1098 } else { 1099 env->PSW_USB_V = 0; 1100 } 1101 return ret & 0xffff0000ll; 1102 } 1103 1104 uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg) 1105 { 1106 int32_t b, i; 1107 int32_t ovf = 0; 1108 int32_t avf = 0; 1109 int32_t ret = 0; 1110 1111 for (i = 0; i < 4; i++) { 1112 b = sextract32(arg, i * 8, 8); 1113 b = (b >= 0) ? b : (0 - b); 1114 ovf |= (b > 0x7F) || (b < -0x80); 1115 avf |= b ^ b * 2u; 1116 ret |= (b & 0xff) << (i * 8); 1117 } 1118 1119 env->PSW_USB_V = ovf << 31; 1120 env->PSW_USB_SV |= env->PSW_USB_V; 1121 env->PSW_USB_AV = avf << 24; 1122 env->PSW_USB_SAV |= env->PSW_USB_AV; 1123 1124 return ret; 1125 } 1126 1127 uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg) 1128 { 1129 int32_t h, i; 1130 int32_t ovf = 0; 1131 int32_t avf = 0; 1132 int32_t ret = 0; 1133 1134 for (i = 0; i < 2; i++) { 1135 h = sextract32(arg, i * 16, 16); 1136 h = (h >= 0) ? h : (0 - h); 1137 ovf |= (h > 0x7FFF) || (h < -0x8000); 1138 avf |= h ^ h * 2u; 1139 ret |= (h & 0xffff) << (i * 16); 1140 } 1141 1142 env->PSW_USB_V = ovf << 31; 1143 env->PSW_USB_SV |= env->PSW_USB_V; 1144 env->PSW_USB_AV = avf << 16; 1145 env->PSW_USB_SAV |= env->PSW_USB_AV; 1146 1147 return ret; 1148 } 1149 1150 uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1151 { 1152 int32_t b, i; 1153 int32_t extr_r2; 1154 int32_t ovf = 0; 1155 int32_t avf = 0; 1156 int32_t ret = 0; 1157 1158 for (i = 0; i < 4; i++) { 1159 extr_r2 = sextract32(r2, i * 8, 8); 1160 b = sextract32(r1, i * 8, 8); 1161 b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b); 1162 ovf |= (b > 0x7F) || (b < -0x80); 1163 avf |= b ^ b * 2u; 1164 ret |= (b & 0xff) << (i * 8); 1165 } 1166 1167 env->PSW_USB_V = ovf << 31; 1168 env->PSW_USB_SV |= env->PSW_USB_V; 1169 env->PSW_USB_AV = avf << 24; 1170 env->PSW_USB_SAV |= env->PSW_USB_AV; 1171 return ret; 1172 } 1173 1174 uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1175 { 1176 int32_t h, i; 1177 int32_t extr_r2; 1178 int32_t ovf = 0; 1179 int32_t avf = 0; 1180 int32_t ret = 0; 1181 1182 for (i = 0; i < 2; i++) { 1183 extr_r2 = sextract32(r2, i * 16, 16); 1184 h = sextract32(r1, i * 16, 16); 1185 h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h); 1186 ovf |= (h > 0x7FFF) || (h < -0x8000); 1187 avf |= h ^ h * 2u; 1188 ret |= (h & 0xffff) << (i * 16); 1189 } 1190 1191 env->PSW_USB_V = ovf << 31; 1192 env->PSW_USB_SV |= env->PSW_USB_V; 1193 env->PSW_USB_AV = avf << 16; 1194 env->PSW_USB_SAV |= env->PSW_USB_AV; 1195 1196 return ret; 1197 } 1198 1199 uint32_t helper_addr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 1200 uint32_t r2_h) 1201 { 1202 int64_t mul_res0 = sextract64(r1, 0, 32); 1203 int64_t mul_res1 = sextract64(r1, 32, 32); 1204 int64_t r2_low = sextract64(r2_l, 0, 32); 1205 int64_t r2_high = sextract64(r2_h, 0, 32); 1206 int64_t result0, result1; 1207 uint32_t ovf0, ovf1; 1208 uint32_t avf0, avf1; 1209 1210 ovf0 = ovf1 = 0; 1211 1212 result0 = r2_low + mul_res0 + 0x8000; 1213 result1 = r2_high + mul_res1 + 0x8000; 1214 1215 if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { 1216 ovf0 = (1 << 31); 1217 } 1218 1219 if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { 1220 ovf1 = (1 << 31); 1221 } 1222 1223 env->PSW_USB_V = ovf0 | ovf1; 1224 env->PSW_USB_SV |= env->PSW_USB_V; 1225 1226 avf0 = result0 * 2u; 1227 avf0 = result0 ^ avf0; 1228 avf1 = result1 * 2u; 1229 avf1 = result1 ^ avf1; 1230 1231 env->PSW_USB_AV = avf0 | avf1; 1232 env->PSW_USB_SAV |= env->PSW_USB_AV; 1233 1234 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 1235 } 1236 1237 uint32_t helper_addsur_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 1238 uint32_t r2_h) 1239 { 1240 int64_t mul_res0 = sextract64(r1, 0, 32); 1241 int64_t mul_res1 = sextract64(r1, 32, 32); 1242 int64_t r2_low = sextract64(r2_l, 0, 32); 1243 int64_t r2_high = sextract64(r2_h, 0, 32); 1244 int64_t result0, result1; 1245 uint32_t ovf0, ovf1; 1246 uint32_t avf0, avf1; 1247 1248 ovf0 = ovf1 = 0; 1249 1250 result0 = r2_low - mul_res0 + 0x8000; 1251 result1 = r2_high + mul_res1 + 0x8000; 1252 1253 if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { 1254 ovf0 = (1 << 31); 1255 } 1256 1257 if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { 1258 ovf1 = (1 << 31); 1259 } 1260 1261 env->PSW_USB_V = ovf0 | ovf1; 1262 env->PSW_USB_SV |= env->PSW_USB_V; 1263 1264 avf0 = result0 * 2u; 1265 avf0 = result0 ^ avf0; 1266 avf1 = result1 * 2u; 1267 avf1 = result1 ^ avf1; 1268 1269 env->PSW_USB_AV = avf0 | avf1; 1270 env->PSW_USB_SAV |= env->PSW_USB_AV; 1271 1272 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 1273 } 1274 1275 uint32_t helper_maddr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2, 1276 uint32_t r3, uint32_t n) 1277 { 1278 int64_t t1 = sextract64(r1, 0, 32); 1279 int64_t t2 = sextract64(r2, 0, 32); 1280 int64_t t3 = sextract64(r3, 0, 32); 1281 int64_t mul, ret; 1282 1283 if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { 1284 mul = 0x7fffffff; 1285 } else { 1286 mul = (t2 * t3) << n; 1287 } 1288 1289 ret = t1 + mul + 0x8000; 1290 1291 if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) { 1292 env->PSW_USB_V = (1 << 31); 1293 env->PSW_USB_SV |= env->PSW_USB_V; 1294 } else { 1295 env->PSW_USB_V = 0; 1296 } 1297 env->PSW_USB_AV = ret ^ ret * 2u; 1298 env->PSW_USB_SAV |= env->PSW_USB_AV; 1299 1300 return ret & 0xffff0000ll; 1301 } 1302 1303 uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1304 { 1305 int32_t b, i; 1306 int32_t extr_r1, extr_r2; 1307 int32_t ovf = 0; 1308 int32_t avf = 0; 1309 uint32_t ret = 0; 1310 1311 for (i = 0; i < 4; i++) { 1312 extr_r1 = sextract32(r1, i * 8, 8); 1313 extr_r2 = sextract32(r2, i * 8, 8); 1314 1315 b = extr_r1 + extr_r2; 1316 ovf |= ((b > 0x7f) || (b < -0x80)); 1317 avf |= b ^ b * 2u; 1318 ret |= ((b & 0xff) << (i*8)); 1319 } 1320 1321 env->PSW_USB_V = (ovf << 31); 1322 env->PSW_USB_SV |= env->PSW_USB_V; 1323 env->PSW_USB_AV = avf << 24; 1324 env->PSW_USB_SAV |= env->PSW_USB_AV; 1325 1326 return ret; 1327 } 1328 1329 uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1330 { 1331 int32_t h, i; 1332 int32_t extr_r1, extr_r2; 1333 int32_t ovf = 0; 1334 int32_t avf = 0; 1335 int32_t ret = 0; 1336 1337 for (i = 0; i < 2; i++) { 1338 extr_r1 = sextract32(r1, i * 16, 16); 1339 extr_r2 = sextract32(r2, i * 16, 16); 1340 h = extr_r1 + extr_r2; 1341 ovf |= ((h > 0x7fff) || (h < -0x8000)); 1342 avf |= h ^ h * 2u; 1343 ret |= (h & 0xffff) << (i * 16); 1344 } 1345 1346 env->PSW_USB_V = (ovf << 31); 1347 env->PSW_USB_SV |= env->PSW_USB_V; 1348 env->PSW_USB_AV = (avf << 16); 1349 env->PSW_USB_SAV |= env->PSW_USB_AV; 1350 1351 return ret; 1352 } 1353 1354 uint32_t helper_subr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 1355 uint32_t r2_h) 1356 { 1357 int64_t mul_res0 = sextract64(r1, 0, 32); 1358 int64_t mul_res1 = sextract64(r1, 32, 32); 1359 int64_t r2_low = sextract64(r2_l, 0, 32); 1360 int64_t r2_high = sextract64(r2_h, 0, 32); 1361 int64_t result0, result1; 1362 uint32_t ovf0, ovf1; 1363 uint32_t avf0, avf1; 1364 1365 ovf0 = ovf1 = 0; 1366 1367 result0 = r2_low - mul_res0 + 0x8000; 1368 result1 = r2_high - mul_res1 + 0x8000; 1369 1370 if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { 1371 ovf0 = (1 << 31); 1372 } 1373 1374 if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { 1375 ovf1 = (1 << 31); 1376 } 1377 1378 env->PSW_USB_V = ovf0 | ovf1; 1379 env->PSW_USB_SV |= env->PSW_USB_V; 1380 1381 avf0 = result0 * 2u; 1382 avf0 = result0 ^ avf0; 1383 avf1 = result1 * 2u; 1384 avf1 = result1 ^ avf1; 1385 1386 env->PSW_USB_AV = avf0 | avf1; 1387 env->PSW_USB_SAV |= env->PSW_USB_AV; 1388 1389 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 1390 } 1391 1392 uint32_t helper_subadr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l, 1393 uint32_t r2_h) 1394 { 1395 int64_t mul_res0 = sextract64(r1, 0, 32); 1396 int64_t mul_res1 = sextract64(r1, 32, 32); 1397 int64_t r2_low = sextract64(r2_l, 0, 32); 1398 int64_t r2_high = sextract64(r2_h, 0, 32); 1399 int64_t result0, result1; 1400 uint32_t ovf0, ovf1; 1401 uint32_t avf0, avf1; 1402 1403 ovf0 = ovf1 = 0; 1404 1405 result0 = r2_low + mul_res0 + 0x8000; 1406 result1 = r2_high - mul_res1 + 0x8000; 1407 1408 if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) { 1409 ovf0 = (1 << 31); 1410 } 1411 1412 if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) { 1413 ovf1 = (1 << 31); 1414 } 1415 1416 env->PSW_USB_V = ovf0 | ovf1; 1417 env->PSW_USB_SV |= env->PSW_USB_V; 1418 1419 avf0 = result0 * 2u; 1420 avf0 = result0 ^ avf0; 1421 avf1 = result1 * 2u; 1422 avf1 = result1 ^ avf1; 1423 1424 env->PSW_USB_AV = avf0 | avf1; 1425 env->PSW_USB_SAV |= env->PSW_USB_AV; 1426 1427 return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL); 1428 } 1429 1430 uint32_t helper_msubr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2, 1431 uint32_t r3, uint32_t n) 1432 { 1433 int64_t t1 = sextract64(r1, 0, 32); 1434 int64_t t2 = sextract64(r2, 0, 32); 1435 int64_t t3 = sextract64(r3, 0, 32); 1436 int64_t mul, ret; 1437 1438 if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) { 1439 mul = 0x7fffffff; 1440 } else { 1441 mul = (t2 * t3) << n; 1442 } 1443 1444 ret = t1 - mul + 0x8000; 1445 1446 if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) { 1447 env->PSW_USB_V = (1 << 31); 1448 env->PSW_USB_SV |= env->PSW_USB_V; 1449 } else { 1450 env->PSW_USB_V = 0; 1451 } 1452 env->PSW_USB_AV = ret ^ ret * 2u; 1453 env->PSW_USB_SAV |= env->PSW_USB_AV; 1454 1455 return ret & 0xffff0000ll; 1456 } 1457 1458 uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1459 { 1460 int32_t b, i; 1461 int32_t extr_r1, extr_r2; 1462 int32_t ovf = 0; 1463 int32_t avf = 0; 1464 uint32_t ret = 0; 1465 1466 for (i = 0; i < 4; i++) { 1467 extr_r1 = sextract32(r1, i * 8, 8); 1468 extr_r2 = sextract32(r2, i * 8, 8); 1469 1470 b = extr_r1 - extr_r2; 1471 ovf |= ((b > 0x7f) || (b < -0x80)); 1472 avf |= b ^ b * 2u; 1473 ret |= ((b & 0xff) << (i*8)); 1474 } 1475 1476 env->PSW_USB_V = (ovf << 31); 1477 env->PSW_USB_SV |= env->PSW_USB_V; 1478 env->PSW_USB_AV = avf << 24; 1479 env->PSW_USB_SAV |= env->PSW_USB_AV; 1480 1481 return ret; 1482 } 1483 1484 uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1485 { 1486 int32_t h, i; 1487 int32_t extr_r1, extr_r2; 1488 int32_t ovf = 0; 1489 int32_t avf = 0; 1490 int32_t ret = 0; 1491 1492 for (i = 0; i < 2; i++) { 1493 extr_r1 = sextract32(r1, i * 16, 16); 1494 extr_r2 = sextract32(r2, i * 16, 16); 1495 h = extr_r1 - extr_r2; 1496 ovf |= ((h > 0x7fff) || (h < -0x8000)); 1497 avf |= h ^ h * 2u; 1498 ret |= (h & 0xffff) << (i * 16); 1499 } 1500 1501 env->PSW_USB_V = (ovf << 31); 1502 env->PSW_USB_SV |= env->PSW_USB_V; 1503 env->PSW_USB_AV = avf << 16; 1504 env->PSW_USB_SAV |= env->PSW_USB_AV; 1505 1506 return ret; 1507 } 1508 1509 uint32_t helper_eq_b(target_ulong r1, target_ulong r2) 1510 { 1511 int32_t ret; 1512 int32_t i, msk; 1513 1514 ret = 0; 1515 msk = 0xff; 1516 for (i = 0; i < 4; i++) { 1517 if ((r1 & msk) == (r2 & msk)) { 1518 ret |= msk; 1519 } 1520 msk = msk << 8; 1521 } 1522 1523 return ret; 1524 } 1525 1526 uint32_t helper_eq_h(target_ulong r1, target_ulong r2) 1527 { 1528 int32_t ret = 0; 1529 1530 if ((r1 & 0xffff) == (r2 & 0xffff)) { 1531 ret = 0xffff; 1532 } 1533 1534 if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) { 1535 ret |= 0xffff0000; 1536 } 1537 1538 return ret; 1539 } 1540 1541 uint32_t helper_eqany_b(target_ulong r1, target_ulong r2) 1542 { 1543 int32_t i; 1544 uint32_t ret = 0; 1545 1546 for (i = 0; i < 4; i++) { 1547 ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8)); 1548 } 1549 1550 return ret; 1551 } 1552 1553 uint32_t helper_eqany_h(target_ulong r1, target_ulong r2) 1554 { 1555 uint32_t ret; 1556 1557 ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16)); 1558 ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16)); 1559 1560 return ret; 1561 } 1562 1563 uint32_t helper_lt_b(target_ulong r1, target_ulong r2) 1564 { 1565 int32_t i; 1566 uint32_t ret = 0; 1567 1568 for (i = 0; i < 4; i++) { 1569 if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) { 1570 ret |= (0xff << (i * 8)); 1571 } 1572 } 1573 1574 return ret; 1575 } 1576 1577 uint32_t helper_lt_bu(target_ulong r1, target_ulong r2) 1578 { 1579 int32_t i; 1580 uint32_t ret = 0; 1581 1582 for (i = 0; i < 4; i++) { 1583 if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) { 1584 ret |= (0xff << (i * 8)); 1585 } 1586 } 1587 1588 return ret; 1589 } 1590 1591 uint32_t helper_lt_h(target_ulong r1, target_ulong r2) 1592 { 1593 uint32_t ret = 0; 1594 1595 if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) { 1596 ret |= 0xffff; 1597 } 1598 1599 if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) { 1600 ret |= 0xffff0000; 1601 } 1602 1603 return ret; 1604 } 1605 1606 uint32_t helper_lt_hu(target_ulong r1, target_ulong r2) 1607 { 1608 uint32_t ret = 0; 1609 1610 if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) { 1611 ret |= 0xffff; 1612 } 1613 1614 if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) { 1615 ret |= 0xffff0000; 1616 } 1617 1618 return ret; 1619 } 1620 1621 #define EXTREMA_H_B(name, op) \ 1622 uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \ 1623 { \ 1624 int32_t i, extr_r1, extr_r2; \ 1625 uint32_t ret = 0; \ 1626 \ 1627 for (i = 0; i < 4; i++) { \ 1628 extr_r1 = sextract32(r1, i * 8, 8); \ 1629 extr_r2 = sextract32(r2, i * 8, 8); \ 1630 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1631 ret |= (extr_r1 & 0xff) << (i * 8); \ 1632 } \ 1633 return ret; \ 1634 } \ 1635 \ 1636 uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\ 1637 { \ 1638 int32_t i; \ 1639 uint32_t extr_r1, extr_r2; \ 1640 uint32_t ret = 0; \ 1641 \ 1642 for (i = 0; i < 4; i++) { \ 1643 extr_r1 = extract32(r1, i * 8, 8); \ 1644 extr_r2 = extract32(r2, i * 8, 8); \ 1645 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1646 ret |= (extr_r1 & 0xff) << (i * 8); \ 1647 } \ 1648 return ret; \ 1649 } \ 1650 \ 1651 uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \ 1652 { \ 1653 int32_t extr_r1, extr_r2; \ 1654 uint32_t ret = 0; \ 1655 \ 1656 extr_r1 = sextract32(r1, 0, 16); \ 1657 extr_r2 = sextract32(r2, 0, 16); \ 1658 ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1659 ret = ret & 0xffff; \ 1660 \ 1661 extr_r1 = sextract32(r1, 16, 16); \ 1662 extr_r2 = sextract32(r2, 16, 16); \ 1663 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1664 ret |= extr_r1 << 16; \ 1665 \ 1666 return ret; \ 1667 } \ 1668 \ 1669 uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\ 1670 { \ 1671 uint32_t extr_r1, extr_r2; \ 1672 uint32_t ret = 0; \ 1673 \ 1674 extr_r1 = extract32(r1, 0, 16); \ 1675 extr_r2 = extract32(r2, 0, 16); \ 1676 ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1677 ret = ret & 0xffff; \ 1678 \ 1679 extr_r1 = extract32(r1, 16, 16); \ 1680 extr_r2 = extract32(r2, 16, 16); \ 1681 extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \ 1682 ret |= extr_r1 << (16); \ 1683 \ 1684 return ret; \ 1685 } \ 1686 \ 1687 uint64_t helper_ix##name(uint64_t r1, uint32_t r2) \ 1688 { \ 1689 int64_t r2l, r2h, r1hl; \ 1690 uint64_t ret = 0; \ 1691 \ 1692 ret = ((r1 + 2) & 0xffff); \ 1693 r2l = sextract64(r2, 0, 16); \ 1694 r2h = sextract64(r2, 16, 16); \ 1695 r1hl = sextract64(r1, 32, 16); \ 1696 \ 1697 if ((r2l op ## = r2h) && (r2l op r1hl)) { \ 1698 ret |= (r2l & 0xffff) << 32; \ 1699 ret |= extract64(r1, 0, 16) << 16; \ 1700 } else if ((r2h op r2l) && (r2h op r1hl)) { \ 1701 ret |= extract64(r2, 16, 16) << 32; \ 1702 ret |= extract64(r1 + 1, 0, 16) << 16; \ 1703 } else { \ 1704 ret |= r1 & 0xffffffff0000ull; \ 1705 } \ 1706 return ret; \ 1707 } \ 1708 \ 1709 uint64_t helper_ix##name ##_u(uint64_t r1, uint32_t r2) \ 1710 { \ 1711 int64_t r2l, r2h, r1hl; \ 1712 uint64_t ret = 0; \ 1713 \ 1714 ret = ((r1 + 2) & 0xffff); \ 1715 r2l = extract64(r2, 0, 16); \ 1716 r2h = extract64(r2, 16, 16); \ 1717 r1hl = extract64(r1, 32, 16); \ 1718 \ 1719 if ((r2l op ## = r2h) && (r2l op r1hl)) { \ 1720 ret |= (r2l & 0xffff) << 32; \ 1721 ret |= extract64(r1, 0, 16) << 16; \ 1722 } else if ((r2h op r2l) && (r2h op r1hl)) { \ 1723 ret |= extract64(r2, 16, 16) << 32; \ 1724 ret |= extract64(r1 + 1, 0, 16) << 16; \ 1725 } else { \ 1726 ret |= r1 & 0xffffffff0000ull; \ 1727 } \ 1728 return ret; \ 1729 } 1730 1731 EXTREMA_H_B(max, >) 1732 EXTREMA_H_B(min, <) 1733 1734 #undef EXTREMA_H_B 1735 1736 uint32_t helper_clo_h(target_ulong r1) 1737 { 1738 uint32_t ret_hw0 = extract32(r1, 0, 16); 1739 uint32_t ret_hw1 = extract32(r1, 16, 16); 1740 1741 ret_hw0 = clo32(ret_hw0 << 16); 1742 ret_hw1 = clo32(ret_hw1 << 16); 1743 1744 if (ret_hw0 > 16) { 1745 ret_hw0 = 16; 1746 } 1747 if (ret_hw1 > 16) { 1748 ret_hw1 = 16; 1749 } 1750 1751 return ret_hw0 | (ret_hw1 << 16); 1752 } 1753 1754 uint32_t helper_clz_h(target_ulong r1) 1755 { 1756 uint32_t ret_hw0 = extract32(r1, 0, 16); 1757 uint32_t ret_hw1 = extract32(r1, 16, 16); 1758 1759 ret_hw0 = clz32(ret_hw0 << 16); 1760 ret_hw1 = clz32(ret_hw1 << 16); 1761 1762 if (ret_hw0 > 16) { 1763 ret_hw0 = 16; 1764 } 1765 if (ret_hw1 > 16) { 1766 ret_hw1 = 16; 1767 } 1768 1769 return ret_hw0 | (ret_hw1 << 16); 1770 } 1771 1772 uint32_t helper_cls_h(target_ulong r1) 1773 { 1774 uint32_t ret_hw0 = extract32(r1, 0, 16); 1775 uint32_t ret_hw1 = extract32(r1, 16, 16); 1776 1777 ret_hw0 = clrsb32(ret_hw0 << 16); 1778 ret_hw1 = clrsb32(ret_hw1 << 16); 1779 1780 if (ret_hw0 > 15) { 1781 ret_hw0 = 15; 1782 } 1783 if (ret_hw1 > 15) { 1784 ret_hw1 = 15; 1785 } 1786 1787 return ret_hw0 | (ret_hw1 << 16); 1788 } 1789 1790 uint32_t helper_sh(target_ulong r1, target_ulong r2) 1791 { 1792 int32_t shift_count = sextract32(r2, 0, 6); 1793 1794 if (shift_count == -32) { 1795 return 0; 1796 } else if (shift_count < 0) { 1797 return r1 >> -shift_count; 1798 } else { 1799 return r1 << shift_count; 1800 } 1801 } 1802 1803 uint32_t helper_sh_h(target_ulong r1, target_ulong r2) 1804 { 1805 int32_t ret_hw0, ret_hw1; 1806 int32_t shift_count; 1807 1808 shift_count = sextract32(r2, 0, 5); 1809 1810 if (shift_count == -16) { 1811 return 0; 1812 } else if (shift_count < 0) { 1813 ret_hw0 = extract32(r1, 0, 16) >> -shift_count; 1814 ret_hw1 = extract32(r1, 16, 16) >> -shift_count; 1815 return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 1816 } else { 1817 ret_hw0 = extract32(r1, 0, 16) << shift_count; 1818 ret_hw1 = extract32(r1, 16, 16) << shift_count; 1819 return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 1820 } 1821 } 1822 1823 uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2) 1824 { 1825 int32_t shift_count; 1826 int64_t result, t1; 1827 uint32_t ret; 1828 1829 shift_count = sextract32(r2, 0, 6); 1830 t1 = sextract32(r1, 0, 32); 1831 1832 if (shift_count == 0) { 1833 env->PSW_USB_C = env->PSW_USB_V = 0; 1834 ret = r1; 1835 } else if (shift_count == -32) { 1836 env->PSW_USB_C = r1; 1837 env->PSW_USB_V = 0; 1838 ret = t1 >> 31; 1839 } else if (shift_count > 0) { 1840 result = t1 << shift_count; 1841 /* calc carry */ 1842 env->PSW_USB_C = ((result & 0xffffffff00000000ULL) != 0); 1843 /* calc v */ 1844 env->PSW_USB_V = (((result > 0x7fffffffLL) || 1845 (result < -0x80000000LL)) << 31); 1846 /* calc sv */ 1847 env->PSW_USB_SV |= env->PSW_USB_V; 1848 ret = (uint32_t)result; 1849 } else { 1850 env->PSW_USB_V = 0; 1851 env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1)); 1852 ret = t1 >> -shift_count; 1853 } 1854 1855 env->PSW_USB_AV = ret ^ ret * 2u; 1856 env->PSW_USB_SAV |= env->PSW_USB_AV; 1857 1858 return ret; 1859 } 1860 1861 uint32_t helper_sha_h(target_ulong r1, target_ulong r2) 1862 { 1863 int32_t shift_count; 1864 int32_t ret_hw0, ret_hw1; 1865 1866 shift_count = sextract32(r2, 0, 5); 1867 1868 if (shift_count == 0) { 1869 return r1; 1870 } else if (shift_count < 0) { 1871 ret_hw0 = sextract32(r1, 0, 16) >> -shift_count; 1872 ret_hw1 = sextract32(r1, 16, 16) >> -shift_count; 1873 return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 1874 } else { 1875 ret_hw0 = sextract32(r1, 0, 16) << shift_count; 1876 ret_hw1 = sextract32(r1, 16, 16) << shift_count; 1877 return (ret_hw0 & 0xffff) | (ret_hw1 << 16); 1878 } 1879 } 1880 1881 uint32_t helper_bmerge(target_ulong r1, target_ulong r2) 1882 { 1883 uint32_t i, ret; 1884 1885 ret = 0; 1886 for (i = 0; i < 16; i++) { 1887 ret |= (r1 & 1) << (2 * i + 1); 1888 ret |= (r2 & 1) << (2 * i); 1889 r1 = r1 >> 1; 1890 r2 = r2 >> 1; 1891 } 1892 return ret; 1893 } 1894 1895 uint64_t helper_bsplit(uint32_t r1) 1896 { 1897 int32_t i; 1898 uint64_t ret; 1899 1900 ret = 0; 1901 for (i = 0; i < 32; i = i + 2) { 1902 /* even */ 1903 ret |= (r1 & 1) << (i/2); 1904 r1 = r1 >> 1; 1905 /* odd */ 1906 ret |= (uint64_t)(r1 & 1) << (i/2 + 32); 1907 r1 = r1 >> 1; 1908 } 1909 return ret; 1910 } 1911 1912 uint32_t helper_parity(target_ulong r1) 1913 { 1914 uint32_t ret; 1915 uint32_t nOnes, i; 1916 1917 ret = 0; 1918 nOnes = 0; 1919 for (i = 0; i < 8; i++) { 1920 ret ^= (r1 & 1); 1921 r1 = r1 >> 1; 1922 } 1923 /* second byte */ 1924 nOnes = 0; 1925 for (i = 0; i < 8; i++) { 1926 nOnes ^= (r1 & 1); 1927 r1 = r1 >> 1; 1928 } 1929 ret |= nOnes << 8; 1930 /* third byte */ 1931 nOnes = 0; 1932 for (i = 0; i < 8; i++) { 1933 nOnes ^= (r1 & 1); 1934 r1 = r1 >> 1; 1935 } 1936 ret |= nOnes << 16; 1937 /* fourth byte */ 1938 nOnes = 0; 1939 for (i = 0; i < 8; i++) { 1940 nOnes ^= (r1 & 1); 1941 r1 = r1 >> 1; 1942 } 1943 ret |= nOnes << 24; 1944 1945 return ret; 1946 } 1947 1948 uint32_t helper_pack(uint32_t carry, uint32_t r1_low, uint32_t r1_high, 1949 target_ulong r2) 1950 { 1951 uint32_t ret; 1952 int32_t fp_exp, fp_frac, temp_exp, fp_exp_frac; 1953 int32_t int_exp = r1_high; 1954 int32_t int_mant = r1_low; 1955 uint32_t flag_rnd = (int_mant & (1 << 7)) && ( 1956 (int_mant & (1 << 8)) || 1957 (int_mant & 0x7f) || 1958 (carry != 0)); 1959 if (((int_mant & (1<<31)) == 0) && (int_exp == 255)) { 1960 fp_exp = 255; 1961 fp_frac = extract32(int_mant, 8, 23); 1962 } else if ((int_mant & (1<<31)) && (int_exp >= 127)) { 1963 fp_exp = 255; 1964 fp_frac = 0; 1965 } else if ((int_mant & (1<<31)) && (int_exp <= -128)) { 1966 fp_exp = 0; 1967 fp_frac = 0; 1968 } else if (int_mant == 0) { 1969 fp_exp = 0; 1970 fp_frac = 0; 1971 } else { 1972 if (((int_mant & (1 << 31)) == 0)) { 1973 temp_exp = 0; 1974 } else { 1975 temp_exp = int_exp + 128; 1976 } 1977 fp_exp_frac = (((temp_exp & 0xff) << 23) | 1978 extract32(int_mant, 8, 23)) 1979 + flag_rnd; 1980 fp_exp = extract32(fp_exp_frac, 23, 8); 1981 fp_frac = extract32(fp_exp_frac, 0, 23); 1982 } 1983 ret = r2 & (1 << 31); 1984 ret = ret + (fp_exp << 23); 1985 ret = ret + (fp_frac & 0x7fffff); 1986 1987 return ret; 1988 } 1989 1990 uint64_t helper_unpack(target_ulong arg1) 1991 { 1992 int32_t fp_exp = extract32(arg1, 23, 8); 1993 int32_t fp_frac = extract32(arg1, 0, 23); 1994 uint64_t ret; 1995 int32_t int_exp, int_mant; 1996 1997 if (fp_exp == 255) { 1998 int_exp = 255; 1999 int_mant = (fp_frac << 7); 2000 } else if ((fp_exp == 0) && (fp_frac == 0)) { 2001 int_exp = -127; 2002 int_mant = 0; 2003 } else if ((fp_exp == 0) && (fp_frac != 0)) { 2004 int_exp = -126; 2005 int_mant = (fp_frac << 7); 2006 } else { 2007 int_exp = fp_exp - 127; 2008 int_mant = (fp_frac << 7); 2009 int_mant |= (1 << 30); 2010 } 2011 ret = int_exp; 2012 ret = ret << 32; 2013 ret |= int_mant; 2014 2015 return ret; 2016 } 2017 2018 uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 2019 { 2020 uint64_t ret; 2021 int32_t abs_sig_dividend, abs_divisor; 2022 2023 ret = sextract32(r1, 0, 32); 2024 ret = ret << 24; 2025 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 2026 ret |= 0xffffff; 2027 } 2028 2029 abs_sig_dividend = abs((int32_t)r1) >> 8; 2030 abs_divisor = abs((int32_t)r2); 2031 /* calc overflow 2032 ofv if (a/b >= 255) <=> (a/255 >= b) */ 2033 env->PSW_USB_V = (abs_sig_dividend >= abs_divisor) << 31; 2034 env->PSW_USB_V = env->PSW_USB_V << 31; 2035 env->PSW_USB_SV |= env->PSW_USB_V; 2036 env->PSW_USB_AV = 0; 2037 2038 return ret; 2039 } 2040 2041 uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 2042 { 2043 uint64_t ret = sextract32(r1, 0, 32); 2044 2045 ret = ret << 24; 2046 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 2047 ret |= 0xffffff; 2048 } 2049 /* calc overflow */ 2050 env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80))); 2051 env->PSW_USB_V = env->PSW_USB_V << 31; 2052 env->PSW_USB_SV |= env->PSW_USB_V; 2053 env->PSW_USB_AV = 0; 2054 2055 return ret; 2056 } 2057 2058 uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 2059 { 2060 uint64_t ret; 2061 int32_t abs_sig_dividend, abs_divisor; 2062 2063 ret = sextract32(r1, 0, 32); 2064 ret = ret << 16; 2065 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 2066 ret |= 0xffff; 2067 } 2068 2069 abs_sig_dividend = abs((int32_t)r1) >> 16; 2070 abs_divisor = abs((int32_t)r2); 2071 /* calc overflow 2072 ofv if (a/b >= 0xffff) <=> (a/0xffff >= b) */ 2073 env->PSW_USB_V = (abs_sig_dividend >= abs_divisor) << 31; 2074 env->PSW_USB_V = env->PSW_USB_V << 31; 2075 env->PSW_USB_SV |= env->PSW_USB_V; 2076 env->PSW_USB_AV = 0; 2077 2078 return ret; 2079 } 2080 2081 uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 2082 { 2083 uint64_t ret = sextract32(r1, 0, 32); 2084 2085 ret = ret << 16; 2086 if (!((r1 & 0x80000000) == (r2 & 0x80000000))) { 2087 ret |= 0xffff; 2088 } 2089 /* calc overflow */ 2090 env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000))); 2091 env->PSW_USB_V = env->PSW_USB_V << 31; 2092 env->PSW_USB_SV |= env->PSW_USB_V; 2093 env->PSW_USB_AV = 0; 2094 2095 return ret; 2096 } 2097 2098 uint64_t helper_dvadj(uint64_t r1, uint32_t r2) 2099 { 2100 int32_t x_sign = (r1 >> 63); 2101 int32_t q_sign = x_sign ^ (r2 >> 31); 2102 int32_t eq_pos = x_sign & ((r1 >> 32) == r2); 2103 int32_t eq_neg = x_sign & ((r1 >> 32) == -r2); 2104 uint32_t quotient; 2105 uint64_t remainder; 2106 2107 if ((q_sign & ~eq_neg) | eq_pos) { 2108 quotient = (r1 + 1) & 0xffffffff; 2109 } else { 2110 quotient = r1 & 0xffffffff; 2111 } 2112 2113 if (eq_pos | eq_neg) { 2114 remainder = 0; 2115 } else { 2116 remainder = (r1 & 0xffffffff00000000ull); 2117 } 2118 return remainder | quotient; 2119 } 2120 2121 uint64_t helper_dvstep(uint64_t r1, uint32_t r2) 2122 { 2123 int32_t dividend_sign = extract64(r1, 63, 1); 2124 int32_t divisor_sign = extract32(r2, 31, 1); 2125 int32_t quotient_sign = (dividend_sign != divisor_sign); 2126 int32_t addend, dividend_quotient, remainder; 2127 int32_t i, temp; 2128 2129 if (quotient_sign) { 2130 addend = r2; 2131 } else { 2132 addend = -r2; 2133 } 2134 dividend_quotient = (int32_t)r1; 2135 remainder = (int32_t)(r1 >> 32); 2136 2137 for (i = 0; i < 8; i++) { 2138 remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1); 2139 dividend_quotient <<= 1; 2140 temp = remainder + addend; 2141 if ((temp < 0) == dividend_sign) { 2142 remainder = temp; 2143 } 2144 if (((temp < 0) == dividend_sign)) { 2145 dividend_quotient = dividend_quotient | !quotient_sign; 2146 } else { 2147 dividend_quotient = dividend_quotient | quotient_sign; 2148 } 2149 } 2150 return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; 2151 } 2152 2153 uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2) 2154 { 2155 int32_t dividend_quotient = extract64(r1, 0, 32); 2156 int64_t remainder = extract64(r1, 32, 32); 2157 int32_t i; 2158 int64_t temp; 2159 for (i = 0; i < 8; i++) { 2160 remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1); 2161 dividend_quotient <<= 1; 2162 temp = (remainder & 0xffffffff) - r2; 2163 if (temp >= 0) { 2164 remainder = temp; 2165 } 2166 dividend_quotient = dividend_quotient | !(temp < 0); 2167 } 2168 return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; 2169 } 2170 2171 uint64_t helper_divide(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 2172 { 2173 int32_t quotient, remainder; 2174 int32_t dividend = (int32_t)r1; 2175 int32_t divisor = (int32_t)r2; 2176 2177 if (divisor == 0) { 2178 if (dividend >= 0) { 2179 quotient = 0x7fffffff; 2180 remainder = 0; 2181 } else { 2182 quotient = 0x80000000; 2183 remainder = 0; 2184 } 2185 env->PSW_USB_V = (1 << 31); 2186 } else if ((divisor == 0xffffffff) && (dividend == 0x80000000)) { 2187 quotient = 0x7fffffff; 2188 remainder = 0; 2189 env->PSW_USB_V = (1 << 31); 2190 } else { 2191 remainder = dividend % divisor; 2192 quotient = (dividend - remainder)/divisor; 2193 env->PSW_USB_V = 0; 2194 } 2195 env->PSW_USB_SV |= env->PSW_USB_V; 2196 env->PSW_USB_AV = 0; 2197 return ((uint64_t)remainder << 32) | (uint32_t)quotient; 2198 } 2199 2200 uint64_t helper_divide_u(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 2201 { 2202 uint32_t quotient, remainder; 2203 uint32_t dividend = r1; 2204 uint32_t divisor = r2; 2205 2206 if (divisor == 0) { 2207 quotient = 0xffffffff; 2208 remainder = 0; 2209 env->PSW_USB_V = (1 << 31); 2210 } else { 2211 remainder = dividend % divisor; 2212 quotient = (dividend - remainder)/divisor; 2213 env->PSW_USB_V = 0; 2214 } 2215 env->PSW_USB_SV |= env->PSW_USB_V; 2216 env->PSW_USB_AV = 0; 2217 return ((uint64_t)remainder << 32) | quotient; 2218 } 2219 2220 uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01, 2221 uint32_t arg10, uint32_t arg11, uint32_t n) 2222 { 2223 uint32_t result0, result1; 2224 2225 int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && 2226 ((arg10 & 0xffff) == 0x8000) && (n == 1); 2227 int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && 2228 ((arg11 & 0xffff) == 0x8000) && (n == 1); 2229 if (sc1) { 2230 result1 = 0x7fffffff; 2231 } else { 2232 result1 = (((uint32_t)(arg00 * arg10)) << n); 2233 } 2234 if (sc0) { 2235 result0 = 0x7fffffff; 2236 } else { 2237 result0 = (((uint32_t)(arg01 * arg11)) << n); 2238 } 2239 return (((uint64_t)result1 << 32)) | result0; 2240 } 2241 2242 uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01, 2243 uint32_t arg10, uint32_t arg11, uint32_t n) 2244 { 2245 uint64_t ret; 2246 int64_t result0, result1; 2247 2248 int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && 2249 ((arg10 & 0xffff) == 0x8000) && (n == 1); 2250 int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && 2251 ((arg11 & 0xffff) == 0x8000) && (n == 1); 2252 2253 if (sc1) { 2254 result1 = 0x7fffffff; 2255 } else { 2256 result1 = (((int32_t)arg00 * (int32_t)arg10) << n); 2257 } 2258 if (sc0) { 2259 result0 = 0x7fffffff; 2260 } else { 2261 result0 = (((int32_t)arg01 * (int32_t)arg11) << n); 2262 } 2263 ret = (result1 + result0); 2264 ret = ret << 16; 2265 return ret; 2266 } 2267 uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01, 2268 uint32_t arg10, uint32_t arg11, uint32_t n) 2269 { 2270 uint32_t result0, result1; 2271 2272 int32_t sc1 = ((arg00 & 0xffff) == 0x8000) && 2273 ((arg10 & 0xffff) == 0x8000) && (n == 1); 2274 int32_t sc0 = ((arg01 & 0xffff) == 0x8000) && 2275 ((arg11 & 0xffff) == 0x8000) && (n == 1); 2276 2277 if (sc1) { 2278 result1 = 0x7fffffff; 2279 } else { 2280 result1 = ((arg00 * arg10) << n) + 0x8000; 2281 } 2282 if (sc0) { 2283 result0 = 0x7fffffff; 2284 } else { 2285 result0 = ((arg01 * arg11) << n) + 0x8000; 2286 } 2287 return (result1 & 0xffff0000) | (result0 >> 16); 2288 } 2289 2290 uint32_t helper_crc32(uint32_t arg0, uint32_t arg1) 2291 { 2292 uint8_t buf[4]; 2293 stl_be_p(buf, arg0); 2294 2295 return crc32(arg1, buf, 4); 2296 } 2297 2298 /* context save area (CSA) related helpers */ 2299 2300 static int cdc_increment(target_ulong *psw) 2301 { 2302 if ((*psw & MASK_PSW_CDC) == 0x7f) { 2303 return 0; 2304 } 2305 2306 (*psw)++; 2307 /* check for overflow */ 2308 int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 2309 int mask = (1u << (7 - lo)) - 1; 2310 int count = *psw & mask; 2311 if (count == 0) { 2312 (*psw)--; 2313 return 1; 2314 } 2315 return 0; 2316 } 2317 2318 static int cdc_decrement(target_ulong *psw) 2319 { 2320 if ((*psw & MASK_PSW_CDC) == 0x7f) { 2321 return 0; 2322 } 2323 /* check for underflow */ 2324 int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 2325 int mask = (1u << (7 - lo)) - 1; 2326 int count = *psw & mask; 2327 if (count == 0) { 2328 return 1; 2329 } 2330 (*psw)--; 2331 return 0; 2332 } 2333 2334 static bool cdc_zero(target_ulong *psw) 2335 { 2336 int cdc = *psw & MASK_PSW_CDC; 2337 /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == 2338 7'b1111111, otherwise returns FALSE. */ 2339 if (cdc == 0x7f) { 2340 return true; 2341 } 2342 /* find CDC.COUNT */ 2343 int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 2344 int mask = (1u << (7 - lo)) - 1; 2345 int count = *psw & mask; 2346 return count == 0; 2347 } 2348 2349 static void save_context_upper(CPUTriCoreState *env, int ea) 2350 { 2351 cpu_stl_data(env, ea, env->PCXI); 2352 cpu_stl_data(env, ea+4, psw_read(env)); 2353 cpu_stl_data(env, ea+8, env->gpr_a[10]); 2354 cpu_stl_data(env, ea+12, env->gpr_a[11]); 2355 cpu_stl_data(env, ea+16, env->gpr_d[8]); 2356 cpu_stl_data(env, ea+20, env->gpr_d[9]); 2357 cpu_stl_data(env, ea+24, env->gpr_d[10]); 2358 cpu_stl_data(env, ea+28, env->gpr_d[11]); 2359 cpu_stl_data(env, ea+32, env->gpr_a[12]); 2360 cpu_stl_data(env, ea+36, env->gpr_a[13]); 2361 cpu_stl_data(env, ea+40, env->gpr_a[14]); 2362 cpu_stl_data(env, ea+44, env->gpr_a[15]); 2363 cpu_stl_data(env, ea+48, env->gpr_d[12]); 2364 cpu_stl_data(env, ea+52, env->gpr_d[13]); 2365 cpu_stl_data(env, ea+56, env->gpr_d[14]); 2366 cpu_stl_data(env, ea+60, env->gpr_d[15]); 2367 } 2368 2369 static void save_context_lower(CPUTriCoreState *env, int ea) 2370 { 2371 cpu_stl_data(env, ea, env->PCXI); 2372 cpu_stl_data(env, ea+4, env->gpr_a[11]); 2373 cpu_stl_data(env, ea+8, env->gpr_a[2]); 2374 cpu_stl_data(env, ea+12, env->gpr_a[3]); 2375 cpu_stl_data(env, ea+16, env->gpr_d[0]); 2376 cpu_stl_data(env, ea+20, env->gpr_d[1]); 2377 cpu_stl_data(env, ea+24, env->gpr_d[2]); 2378 cpu_stl_data(env, ea+28, env->gpr_d[3]); 2379 cpu_stl_data(env, ea+32, env->gpr_a[4]); 2380 cpu_stl_data(env, ea+36, env->gpr_a[5]); 2381 cpu_stl_data(env, ea+40, env->gpr_a[6]); 2382 cpu_stl_data(env, ea+44, env->gpr_a[7]); 2383 cpu_stl_data(env, ea+48, env->gpr_d[4]); 2384 cpu_stl_data(env, ea+52, env->gpr_d[5]); 2385 cpu_stl_data(env, ea+56, env->gpr_d[6]); 2386 cpu_stl_data(env, ea+60, env->gpr_d[7]); 2387 } 2388 2389 static void restore_context_upper(CPUTriCoreState *env, int ea, 2390 target_ulong *new_PCXI, target_ulong *new_PSW) 2391 { 2392 *new_PCXI = cpu_ldl_data(env, ea); 2393 *new_PSW = cpu_ldl_data(env, ea+4); 2394 env->gpr_a[10] = cpu_ldl_data(env, ea+8); 2395 env->gpr_a[11] = cpu_ldl_data(env, ea+12); 2396 env->gpr_d[8] = cpu_ldl_data(env, ea+16); 2397 env->gpr_d[9] = cpu_ldl_data(env, ea+20); 2398 env->gpr_d[10] = cpu_ldl_data(env, ea+24); 2399 env->gpr_d[11] = cpu_ldl_data(env, ea+28); 2400 env->gpr_a[12] = cpu_ldl_data(env, ea+32); 2401 env->gpr_a[13] = cpu_ldl_data(env, ea+36); 2402 env->gpr_a[14] = cpu_ldl_data(env, ea+40); 2403 env->gpr_a[15] = cpu_ldl_data(env, ea+44); 2404 env->gpr_d[12] = cpu_ldl_data(env, ea+48); 2405 env->gpr_d[13] = cpu_ldl_data(env, ea+52); 2406 env->gpr_d[14] = cpu_ldl_data(env, ea+56); 2407 env->gpr_d[15] = cpu_ldl_data(env, ea+60); 2408 } 2409 2410 static void restore_context_lower(CPUTriCoreState *env, int ea, 2411 target_ulong *ra, target_ulong *pcxi) 2412 { 2413 *pcxi = cpu_ldl_data(env, ea); 2414 *ra = cpu_ldl_data(env, ea+4); 2415 env->gpr_a[2] = cpu_ldl_data(env, ea+8); 2416 env->gpr_a[3] = cpu_ldl_data(env, ea+12); 2417 env->gpr_d[0] = cpu_ldl_data(env, ea+16); 2418 env->gpr_d[1] = cpu_ldl_data(env, ea+20); 2419 env->gpr_d[2] = cpu_ldl_data(env, ea+24); 2420 env->gpr_d[3] = cpu_ldl_data(env, ea+28); 2421 env->gpr_a[4] = cpu_ldl_data(env, ea+32); 2422 env->gpr_a[5] = cpu_ldl_data(env, ea+36); 2423 env->gpr_a[6] = cpu_ldl_data(env, ea+40); 2424 env->gpr_a[7] = cpu_ldl_data(env, ea+44); 2425 env->gpr_d[4] = cpu_ldl_data(env, ea+48); 2426 env->gpr_d[5] = cpu_ldl_data(env, ea+52); 2427 env->gpr_d[6] = cpu_ldl_data(env, ea+56); 2428 env->gpr_d[7] = cpu_ldl_data(env, ea+60); 2429 } 2430 2431 void helper_call(CPUTriCoreState *env, uint32_t next_pc) 2432 { 2433 target_ulong tmp_FCX; 2434 target_ulong ea; 2435 target_ulong new_FCX; 2436 target_ulong psw; 2437 2438 psw = psw_read(env); 2439 /* if (FCX == 0) trap(FCU); */ 2440 if (env->FCX == 0) { 2441 /* FCU trap */ 2442 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); 2443 } 2444 /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ 2445 if (psw & MASK_PSW_CDE) { 2446 if (cdc_increment(&psw)) { 2447 /* CDO trap */ 2448 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CDO, GETPC()); 2449 } 2450 } 2451 /* PSW.CDE = 1;*/ 2452 psw |= MASK_PSW_CDE; 2453 /* tmp_FCX = FCX; */ 2454 tmp_FCX = env->FCX; 2455 /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 2456 ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 2457 ((env->FCX & MASK_FCX_FCXO) << 6); 2458 /* new_FCX = M(EA, word); */ 2459 new_FCX = cpu_ldl_data(env, ea); 2460 /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 2461 A[12], A[13], A[14], A[15], D[12], D[13], D[14], 2462 D[15]}; */ 2463 save_context_upper(env, ea); 2464 2465 /* PCXI.PCPN = ICR.CCPN; */ 2466 env->PCXI = (env->PCXI & 0xffffff) + 2467 ((env->ICR & MASK_ICR_CCPN) << 24); 2468 /* PCXI.PIE = ICR.IE; */ 2469 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 2470 ((env->ICR & MASK_ICR_IE) << 15)); 2471 /* PCXI.UL = 1; */ 2472 env->PCXI |= MASK_PCXI_UL; 2473 2474 /* PCXI[19: 0] = FCX[19: 0]; */ 2475 env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 2476 /* FCX[19: 0] = new_FCX[19: 0]; */ 2477 env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 2478 /* A[11] = next_pc[31: 0]; */ 2479 env->gpr_a[11] = next_pc; 2480 2481 /* if (tmp_FCX == LCX) trap(FCD);*/ 2482 if (tmp_FCX == env->LCX) { 2483 /* FCD trap */ 2484 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); 2485 } 2486 psw_write(env, psw); 2487 } 2488 2489 void helper_ret(CPUTriCoreState *env) 2490 { 2491 target_ulong ea; 2492 target_ulong new_PCXI; 2493 target_ulong new_PSW, psw; 2494 2495 psw = psw_read(env); 2496 /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ 2497 if (psw & MASK_PSW_CDE) { 2498 if (cdc_decrement(&psw)) { 2499 /* CDU trap */ 2500 psw_write(env, psw); 2501 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CDU, GETPC()); 2502 } 2503 } 2504 /* if (PCXI[19: 0] == 0) then trap(CSU); */ 2505 if ((env->PCXI & 0xfffff) == 0) { 2506 /* CSU trap */ 2507 psw_write(env, psw); 2508 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC()); 2509 } 2510 /* if (PCXI.UL == 0) then trap(CTYP); */ 2511 if ((env->PCXI & MASK_PCXI_UL) == 0) { 2512 /* CTYP trap */ 2513 cdc_increment(&psw); /* restore to the start of helper */ 2514 psw_write(env, psw); 2515 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC()); 2516 } 2517 /* PC = {A11 [31: 1], 1’b0}; */ 2518 env->PC = env->gpr_a[11] & 0xfffffffe; 2519 2520 /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ 2521 ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 2522 ((env->PCXI & MASK_PCXI_PCXO) << 6); 2523 /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 2524 A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 2525 restore_context_upper(env, ea, &new_PCXI, &new_PSW); 2526 /* M(EA, word) = FCX; */ 2527 cpu_stl_data(env, ea, env->FCX); 2528 /* FCX[19: 0] = PCXI[19: 0]; */ 2529 env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 2530 /* PCXI = new_PCXI; */ 2531 env->PCXI = new_PCXI; 2532 2533 if (tricore_feature(env, TRICORE_FEATURE_13)) { 2534 /* PSW = new_PSW */ 2535 psw_write(env, new_PSW); 2536 } else { 2537 /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */ 2538 psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000))); 2539 } 2540 } 2541 2542 void helper_bisr(CPUTriCoreState *env, uint32_t const9) 2543 { 2544 target_ulong tmp_FCX; 2545 target_ulong ea; 2546 target_ulong new_FCX; 2547 2548 if (env->FCX == 0) { 2549 /* FCU trap */ 2550 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); 2551 } 2552 2553 tmp_FCX = env->FCX; 2554 ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6); 2555 2556 /* new_FCX = M(EA, word); */ 2557 new_FCX = cpu_ldl_data(env, ea); 2558 /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4] 2559 , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */ 2560 save_context_lower(env, ea); 2561 2562 2563 /* PCXI.PCPN = ICR.CCPN */ 2564 env->PCXI = (env->PCXI & 0xffffff) + 2565 ((env->ICR & MASK_ICR_CCPN) << 24); 2566 /* PCXI.PIE = ICR.IE */ 2567 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 2568 ((env->ICR & MASK_ICR_IE) << 15)); 2569 /* PCXI.UL = 0 */ 2570 env->PCXI &= ~(MASK_PCXI_UL); 2571 /* PCXI[19: 0] = FCX[19: 0] */ 2572 env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 2573 /* FXC[19: 0] = new_FCX[19: 0] */ 2574 env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 2575 /* ICR.IE = 1 */ 2576 env->ICR |= MASK_ICR_IE; 2577 2578 env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/ 2579 2580 if (tmp_FCX == env->LCX) { 2581 /* FCD trap */ 2582 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); 2583 } 2584 } 2585 2586 void helper_rfe(CPUTriCoreState *env) 2587 { 2588 target_ulong ea; 2589 target_ulong new_PCXI; 2590 target_ulong new_PSW; 2591 /* if (PCXI[19: 0] == 0) then trap(CSU); */ 2592 if ((env->PCXI & 0xfffff) == 0) { 2593 /* raise csu trap */ 2594 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC()); 2595 } 2596 /* if (PCXI.UL == 0) then trap(CTYP); */ 2597 if ((env->PCXI & MASK_PCXI_UL) == 0) { 2598 /* raise CTYP trap */ 2599 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC()); 2600 } 2601 /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ 2602 if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { 2603 /* raise NEST trap */ 2604 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_NEST, GETPC()); 2605 } 2606 env->PC = env->gpr_a[11] & ~0x1; 2607 /* ICR.IE = PCXI.PIE; */ 2608 env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); 2609 /* ICR.CCPN = PCXI.PCPN; */ 2610 env->ICR = (env->ICR & ~MASK_ICR_CCPN) + 2611 ((env->PCXI & MASK_PCXI_PCPN) >> 24); 2612 /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ 2613 ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 2614 ((env->PCXI & MASK_PCXI_PCXO) << 6); 2615 /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 2616 A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 2617 restore_context_upper(env, ea, &new_PCXI, &new_PSW); 2618 /* M(EA, word) = FCX;*/ 2619 cpu_stl_data(env, ea, env->FCX); 2620 /* FCX[19: 0] = PCXI[19: 0]; */ 2621 env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 2622 /* PCXI = new_PCXI; */ 2623 env->PCXI = new_PCXI; 2624 /* write psw */ 2625 psw_write(env, new_PSW); 2626 } 2627 2628 void helper_rfm(CPUTriCoreState *env) 2629 { 2630 env->PC = (env->gpr_a[11] & ~0x1); 2631 /* ICR.IE = PCXI.PIE; */ 2632 env->ICR = (env->ICR & ~MASK_ICR_IE) | 2633 ((env->PCXI & MASK_PCXI_PIE) >> 15); 2634 /* ICR.CCPN = PCXI.PCPN; */ 2635 env->ICR = (env->ICR & ~MASK_ICR_CCPN) | 2636 ((env->PCXI & MASK_PCXI_PCPN) >> 24); 2637 /* {PCXI, PSW, A[10], A[11]} = M(DCX, 4 * word); */ 2638 env->PCXI = cpu_ldl_data(env, env->DCX); 2639 psw_write(env, cpu_ldl_data(env, env->DCX+4)); 2640 env->gpr_a[10] = cpu_ldl_data(env, env->DCX+8); 2641 env->gpr_a[11] = cpu_ldl_data(env, env->DCX+12); 2642 2643 if (tricore_feature(env, TRICORE_FEATURE_131)) { 2644 env->DBGTCR = 0; 2645 } 2646 } 2647 2648 void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) 2649 { 2650 uint32_t dummy; 2651 /* insn doesn't load PCXI and RA */ 2652 restore_context_lower(env, ea, &dummy, &dummy); 2653 } 2654 2655 void helper_lducx(CPUTriCoreState *env, uint32_t ea) 2656 { 2657 uint32_t dummy; 2658 /* insn doesn't load PCXI and PSW */ 2659 restore_context_upper(env, ea, &dummy, &dummy); 2660 } 2661 2662 void helper_stlcx(CPUTriCoreState *env, uint32_t ea) 2663 { 2664 save_context_lower(env, ea); 2665 } 2666 2667 void helper_stucx(CPUTriCoreState *env, uint32_t ea) 2668 { 2669 save_context_upper(env, ea); 2670 } 2671 2672 void helper_svlcx(CPUTriCoreState *env) 2673 { 2674 target_ulong tmp_FCX; 2675 target_ulong ea; 2676 target_ulong new_FCX; 2677 2678 if (env->FCX == 0) { 2679 /* FCU trap */ 2680 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); 2681 } 2682 /* tmp_FCX = FCX; */ 2683 tmp_FCX = env->FCX; 2684 /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 2685 ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 2686 ((env->FCX & MASK_FCX_FCXO) << 6); 2687 /* new_FCX = M(EA, word); */ 2688 new_FCX = cpu_ldl_data(env, ea); 2689 /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 2690 A[12], A[13], A[14], A[15], D[12], D[13], D[14], 2691 D[15]}; */ 2692 save_context_lower(env, ea); 2693 2694 /* PCXI.PCPN = ICR.CCPN; */ 2695 env->PCXI = (env->PCXI & 0xffffff) + 2696 ((env->ICR & MASK_ICR_CCPN) << 24); 2697 /* PCXI.PIE = ICR.IE; */ 2698 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 2699 ((env->ICR & MASK_ICR_IE) << 15)); 2700 /* PCXI.UL = 0; */ 2701 env->PCXI &= ~MASK_PCXI_UL; 2702 2703 /* PCXI[19: 0] = FCX[19: 0]; */ 2704 env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 2705 /* FCX[19: 0] = new_FCX[19: 0]; */ 2706 env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 2707 2708 /* if (tmp_FCX == LCX) trap(FCD);*/ 2709 if (tmp_FCX == env->LCX) { 2710 /* FCD trap */ 2711 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); 2712 } 2713 } 2714 2715 void helper_svucx(CPUTriCoreState *env) 2716 { 2717 target_ulong tmp_FCX; 2718 target_ulong ea; 2719 target_ulong new_FCX; 2720 2721 if (env->FCX == 0) { 2722 /* FCU trap */ 2723 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC()); 2724 } 2725 /* tmp_FCX = FCX; */ 2726 tmp_FCX = env->FCX; 2727 /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 2728 ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 2729 ((env->FCX & MASK_FCX_FCXO) << 6); 2730 /* new_FCX = M(EA, word); */ 2731 new_FCX = cpu_ldl_data(env, ea); 2732 /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 2733 A[12], A[13], A[14], A[15], D[12], D[13], D[14], 2734 D[15]}; */ 2735 save_context_upper(env, ea); 2736 2737 /* PCXI.PCPN = ICR.CCPN; */ 2738 env->PCXI = (env->PCXI & 0xffffff) + 2739 ((env->ICR & MASK_ICR_CCPN) << 24); 2740 /* PCXI.PIE = ICR.IE; */ 2741 env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 2742 ((env->ICR & MASK_ICR_IE) << 15)); 2743 /* PCXI.UL = 1; */ 2744 env->PCXI |= MASK_PCXI_UL; 2745 2746 /* PCXI[19: 0] = FCX[19: 0]; */ 2747 env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 2748 /* FCX[19: 0] = new_FCX[19: 0]; */ 2749 env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 2750 2751 /* if (tmp_FCX == LCX) trap(FCD);*/ 2752 if (tmp_FCX == env->LCX) { 2753 /* FCD trap */ 2754 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC()); 2755 } 2756 } 2757 2758 void helper_rslcx(CPUTriCoreState *env) 2759 { 2760 target_ulong ea; 2761 target_ulong new_PCXI; 2762 /* if (PCXI[19: 0] == 0) then trap(CSU); */ 2763 if ((env->PCXI & 0xfffff) == 0) { 2764 /* CSU trap */ 2765 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC()); 2766 } 2767 /* if (PCXI.UL == 1) then trap(CTYP); */ 2768 if ((env->PCXI & MASK_PCXI_UL) != 0) { 2769 /* CTYP trap */ 2770 raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC()); 2771 } 2772 /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ 2773 ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 2774 ((env->PCXI & MASK_PCXI_PCXO) << 6); 2775 /* {new_PCXI, A[11], A[10], A[11], D[8], D[9], D[10], D[11], A[12], 2776 A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 2777 restore_context_lower(env, ea, &env->gpr_a[11], &new_PCXI); 2778 /* M(EA, word) = FCX; */ 2779 cpu_stl_data(env, ea, env->FCX); 2780 /* M(EA, word) = FCX; */ 2781 cpu_stl_data(env, ea, env->FCX); 2782 /* FCX[19: 0] = PCXI[19: 0]; */ 2783 env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 2784 /* PCXI = new_PCXI; */ 2785 env->PCXI = new_PCXI; 2786 } 2787 2788 void helper_psw_write(CPUTriCoreState *env, uint32_t arg) 2789 { 2790 psw_write(env, arg); 2791 } 2792 2793 uint32_t helper_psw_read(CPUTriCoreState *env) 2794 { 2795 return psw_read(env); 2796 } 2797 2798 2799 static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 2800 uint32_t exception, 2801 int error_code, 2802 uintptr_t pc) 2803 { 2804 CPUState *cs = CPU(tricore_env_get_cpu(env)); 2805 cs->exception_index = exception; 2806 env->error_code = error_code; 2807 2808 if (pc) { 2809 /* now we have a real cpu fault */ 2810 cpu_restore_state(cs, pc); 2811 } 2812 2813 cpu_loop_exit(cs); 2814 } 2815 2816 void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, 2817 int mmu_idx, uintptr_t retaddr) 2818 { 2819 int ret; 2820 ret = cpu_tricore_handle_mmu_fault(cs, addr, access_type, mmu_idx); 2821 if (ret) { 2822 TriCoreCPU *cpu = TRICORE_CPU(cs); 2823 CPUTriCoreState *env = &cpu->env; 2824 do_raise_exception_err(env, cs->exception_index, 2825 env->error_code, retaddr); 2826 } 2827 } 2828