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