qemu/target/tricore/op_helper.c
<<
>>
Prefs
   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
  28static void QEMU_NORETURN
  29raise_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
 100void 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
 106static 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
 114static 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
 127uint32_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
 135uint32_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
 148static 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
 172static 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
 189static 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
 206static 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
 237static 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
 267target_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
 276uint64_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
 301target_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
 311uint32_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
 357uint32_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
 404target_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
 413target_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
 423target_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
 432uint64_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
 457target_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
 467uint32_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
 513uint32_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
 559target_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
 568target_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
 578target_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
 587target_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
 597target_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
 613uint32_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
 620uint32_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
 633target_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
 648uint32_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
 673target_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
 685target_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
 697uint64_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
 730uint32_t
 731helper_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
 771uint64_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
 822uint32_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
 855uint64_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
 880target_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
 892target_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
 919uint64_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
 951uint64_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
 976uint32_t
 977helper_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
1019uint64_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
1071uint32_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
1104uint32_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
1127uint32_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
1150uint32_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
1174uint32_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
1199uint32_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
1237uint32_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
1275uint32_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
1303uint32_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
1329uint32_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
1354uint32_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
1392uint32_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
1430uint32_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
1458uint32_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
1484uint32_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
1509uint32_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
1526uint32_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
1541uint32_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
1553uint32_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
1563uint32_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
1577uint32_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
1591uint32_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
1606uint32_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)                                 \
1622uint32_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                                                              \
1636uint32_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                                                              \
1651uint32_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                                                              \
1669uint32_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                                                              \
1687uint64_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                                                              \
1709uint64_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
1731EXTREMA_H_B(max, >)
1732EXTREMA_H_B(min, <)
1733
1734#undef EXTREMA_H_B
1735
1736uint32_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
1754uint32_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
1772uint32_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
1790uint32_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
1803uint32_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
1823uint32_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
1861uint32_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
1881uint32_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
1895uint64_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
1912uint32_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
1948uint32_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
1990uint64_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
2018uint64_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
2041uint64_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
2058uint64_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
2081uint64_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
2098uint64_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
2121uint64_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
2153uint64_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
2171uint64_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
2200uint64_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
2220uint64_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
2242uint64_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}
2267uint32_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
2290uint32_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
2300static 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
2318static 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
2334static 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
2349static 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
2369static 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
2389static 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
2410static 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
2431void 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
2489void 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
2542void 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
2586void 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
2628void 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
2648void 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
2655void 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
2662void helper_stlcx(CPUTriCoreState *env, uint32_t ea)
2663{
2664    save_context_lower(env, ea);
2665}
2666
2667void helper_stucx(CPUTriCoreState *env, uint32_t ea)
2668{
2669    save_context_upper(env, ea);
2670}
2671
2672void 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
2715void 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
2758void 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
2788void helper_psw_write(CPUTriCoreState *env, uint32_t arg)
2789{
2790    psw_write(env, arg);
2791}
2792
2793uint32_t helper_psw_read(CPUTriCoreState *env)
2794{
2795    return psw_read(env);
2796}
2797
2798
2799static 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
2816void 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