148e06fe0SBastian Koppelmann /* 248e06fe0SBastian Koppelmann * Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn 348e06fe0SBastian Koppelmann * 448e06fe0SBastian Koppelmann * This library is free software; you can redistribute it and/or 548e06fe0SBastian Koppelmann * modify it under the terms of the GNU Lesser General Public 648e06fe0SBastian Koppelmann * License as published by the Free Software Foundation; either 748e06fe0SBastian Koppelmann * version 2 of the License, or (at your option) any later version. 848e06fe0SBastian Koppelmann * 948e06fe0SBastian Koppelmann * This library is distributed in the hope that it will be useful, 1048e06fe0SBastian Koppelmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 1148e06fe0SBastian Koppelmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1248e06fe0SBastian Koppelmann * Lesser General Public License for more details. 1348e06fe0SBastian Koppelmann * 1448e06fe0SBastian Koppelmann * You should have received a copy of the GNU Lesser General Public 1548e06fe0SBastian Koppelmann * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1648e06fe0SBastian Koppelmann */ 1748e06fe0SBastian Koppelmann #include <stdlib.h> 1848e06fe0SBastian Koppelmann #include "cpu.h" 1948e06fe0SBastian Koppelmann #include "qemu/host-utils.h" 2048e06fe0SBastian Koppelmann #include "exec/helper-proto.h" 2148e06fe0SBastian Koppelmann #include "exec/cpu_ldst.h" 2248e06fe0SBastian Koppelmann 233a16ecb0SBastian Koppelmann /* Addressing mode helper */ 243a16ecb0SBastian Koppelmann 253a16ecb0SBastian Koppelmann static uint16_t reverse16(uint16_t val) 263a16ecb0SBastian Koppelmann { 273a16ecb0SBastian Koppelmann uint8_t high = (uint8_t)(val >> 8); 283a16ecb0SBastian Koppelmann uint8_t low = (uint8_t)(val & 0xff); 293a16ecb0SBastian Koppelmann 303a16ecb0SBastian Koppelmann uint16_t rh, rl; 313a16ecb0SBastian Koppelmann 323a16ecb0SBastian Koppelmann rl = (uint16_t)((high * 0x0202020202ULL & 0x010884422010ULL) % 1023); 333a16ecb0SBastian Koppelmann rh = (uint16_t)((low * 0x0202020202ULL & 0x010884422010ULL) % 1023); 343a16ecb0SBastian Koppelmann 353a16ecb0SBastian Koppelmann return (rh << 8) | rl; 363a16ecb0SBastian Koppelmann } 373a16ecb0SBastian Koppelmann 383a16ecb0SBastian Koppelmann uint32_t helper_br_update(uint32_t reg) 393a16ecb0SBastian Koppelmann { 403a16ecb0SBastian Koppelmann uint32_t index = reg & 0xffff; 413a16ecb0SBastian Koppelmann uint32_t incr = reg >> 16; 423a16ecb0SBastian Koppelmann uint32_t new_index = reverse16(reverse16(index) + reverse16(incr)); 433a16ecb0SBastian Koppelmann return reg - index + new_index; 443a16ecb0SBastian Koppelmann } 453a16ecb0SBastian Koppelmann 463a16ecb0SBastian Koppelmann uint32_t helper_circ_update(uint32_t reg, uint32_t off) 473a16ecb0SBastian Koppelmann { 483a16ecb0SBastian Koppelmann uint32_t index = reg & 0xffff; 493a16ecb0SBastian Koppelmann uint32_t length = reg >> 16; 503a16ecb0SBastian Koppelmann int32_t new_index = index + off; 513a16ecb0SBastian Koppelmann if (new_index < 0) { 523a16ecb0SBastian Koppelmann new_index += length; 533a16ecb0SBastian Koppelmann } else { 543a16ecb0SBastian Koppelmann new_index %= length; 553a16ecb0SBastian Koppelmann } 563a16ecb0SBastian Koppelmann return reg - index + new_index; 573a16ecb0SBastian Koppelmann } 583a16ecb0SBastian Koppelmann 592692802aSBastian Koppelmann #define SSOV(env, ret, arg, len) do { \ 602692802aSBastian Koppelmann int64_t max_pos = INT##len ##_MAX; \ 612692802aSBastian Koppelmann int64_t max_neg = INT##len ##_MIN; \ 622692802aSBastian Koppelmann if (arg > max_pos) { \ 632692802aSBastian Koppelmann env->PSW_USB_V = (1 << 31); \ 642692802aSBastian Koppelmann env->PSW_USB_SV = (1 << 31); \ 652692802aSBastian Koppelmann ret = (target_ulong)max_pos; \ 662692802aSBastian Koppelmann } else { \ 672692802aSBastian Koppelmann if (arg < max_neg) { \ 682692802aSBastian Koppelmann env->PSW_USB_V = (1 << 31); \ 692692802aSBastian Koppelmann env->PSW_USB_SV = (1 << 31); \ 702692802aSBastian Koppelmann ret = (target_ulong)max_neg; \ 712692802aSBastian Koppelmann } else { \ 722692802aSBastian Koppelmann env->PSW_USB_V = 0; \ 732692802aSBastian Koppelmann ret = (target_ulong)arg; \ 742692802aSBastian Koppelmann } \ 752692802aSBastian Koppelmann } \ 762692802aSBastian Koppelmann env->PSW_USB_AV = arg ^ arg * 2u; \ 772692802aSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; \ 782692802aSBastian Koppelmann } while (0) 792692802aSBastian Koppelmann 800974257eSBastian Koppelmann #define SUOV(env, ret, arg, len) do { \ 810974257eSBastian Koppelmann int64_t max_pos = UINT##len ##_MAX; \ 820974257eSBastian Koppelmann if (arg > max_pos) { \ 830974257eSBastian Koppelmann env->PSW_USB_V = (1 << 31); \ 840974257eSBastian Koppelmann env->PSW_USB_SV = (1 << 31); \ 850974257eSBastian Koppelmann ret = (target_ulong)max_pos; \ 860974257eSBastian Koppelmann } else { \ 870974257eSBastian Koppelmann if (arg < 0) { \ 880974257eSBastian Koppelmann env->PSW_USB_V = (1 << 31); \ 890974257eSBastian Koppelmann env->PSW_USB_SV = (1 << 31); \ 900974257eSBastian Koppelmann ret = 0; \ 910974257eSBastian Koppelmann } else { \ 920974257eSBastian Koppelmann env->PSW_USB_V = 0; \ 930974257eSBastian Koppelmann ret = (target_ulong)arg; \ 940974257eSBastian Koppelmann } \ 950974257eSBastian Koppelmann } \ 960974257eSBastian Koppelmann env->PSW_USB_AV = arg ^ arg * 2u; \ 970974257eSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; \ 980974257eSBastian Koppelmann } while (0) 990974257eSBastian Koppelmann 1000974257eSBastian Koppelmann 1012692802aSBastian Koppelmann target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, 1022692802aSBastian Koppelmann target_ulong r2) 1032692802aSBastian Koppelmann { 1042692802aSBastian Koppelmann target_ulong ret; 1052692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 1062692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 1072692802aSBastian Koppelmann int64_t result = t1 + t2; 1082692802aSBastian Koppelmann SSOV(env, ret, result, 32); 1092692802aSBastian Koppelmann return ret; 1102692802aSBastian Koppelmann } 1112692802aSBastian Koppelmann 1120974257eSBastian Koppelmann target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, 1130974257eSBastian Koppelmann target_ulong r2) 1140974257eSBastian Koppelmann { 1150974257eSBastian Koppelmann target_ulong ret; 1160974257eSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 1170974257eSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 1180974257eSBastian Koppelmann int64_t result = t1 + t2; 1190974257eSBastian Koppelmann SUOV(env, ret, result, 32); 1200974257eSBastian Koppelmann return ret; 1210974257eSBastian Koppelmann } 1220974257eSBastian Koppelmann 1232692802aSBastian Koppelmann target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, 1242692802aSBastian Koppelmann target_ulong r2) 1252692802aSBastian Koppelmann { 1262692802aSBastian Koppelmann target_ulong ret; 1272692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 1282692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 1292692802aSBastian Koppelmann int64_t result = t1 - t2; 1302692802aSBastian Koppelmann SSOV(env, ret, result, 32); 1312692802aSBastian Koppelmann return ret; 1322692802aSBastian Koppelmann } 1332692802aSBastian Koppelmann 1340974257eSBastian Koppelmann target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, 1350974257eSBastian Koppelmann target_ulong r2) 1360974257eSBastian Koppelmann { 1370974257eSBastian Koppelmann target_ulong ret; 1380974257eSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 1390974257eSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 1400974257eSBastian Koppelmann int64_t result = t1 - t2; 1410974257eSBastian Koppelmann SUOV(env, ret, result, 32); 1420974257eSBastian Koppelmann return ret; 1430974257eSBastian Koppelmann } 1440974257eSBastian Koppelmann 1450974257eSBastian Koppelmann target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1, 1460974257eSBastian Koppelmann target_ulong r2) 1470974257eSBastian Koppelmann { 1480974257eSBastian Koppelmann target_ulong ret; 1490974257eSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 1500974257eSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 1510974257eSBastian Koppelmann int64_t result = t1 * t2; 1520974257eSBastian Koppelmann SSOV(env, ret, result, 32); 1530974257eSBastian Koppelmann return ret; 1540974257eSBastian Koppelmann } 1550974257eSBastian Koppelmann 1560974257eSBastian Koppelmann target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, 1570974257eSBastian Koppelmann target_ulong r2) 1580974257eSBastian Koppelmann { 1590974257eSBastian Koppelmann target_ulong ret; 1600974257eSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 1610974257eSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 1620974257eSBastian Koppelmann int64_t result = t1 * t2; 1630974257eSBastian Koppelmann SUOV(env, ret, result, 32); 1640974257eSBastian Koppelmann return ret; 1650974257eSBastian Koppelmann } 1660974257eSBastian Koppelmann 1670974257eSBastian Koppelmann target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, 1680974257eSBastian Koppelmann target_ulong r2) 1690974257eSBastian Koppelmann { 1700974257eSBastian Koppelmann target_ulong ret; 1710974257eSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 1720974257eSBastian Koppelmann int32_t t2 = sextract64(r2, 0, 6); 1730974257eSBastian Koppelmann int64_t result; 1740974257eSBastian Koppelmann if (t2 == 0) { 1750974257eSBastian Koppelmann result = t1; 1760974257eSBastian Koppelmann } else if (t2 > 0) { 1770974257eSBastian Koppelmann result = t1 << t2; 1780974257eSBastian Koppelmann } else { 1790974257eSBastian Koppelmann result = t1 >> -t2; 1800974257eSBastian Koppelmann } 1810974257eSBastian Koppelmann SSOV(env, ret, result, 32); 1820974257eSBastian Koppelmann return ret; 1830974257eSBastian Koppelmann } 1840974257eSBastian Koppelmann 1850974257eSBastian Koppelmann target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1, 1860974257eSBastian Koppelmann target_ulong r2) 1870974257eSBastian Koppelmann { 1880974257eSBastian Koppelmann target_ulong ret; 1890974257eSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 1900974257eSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 1910974257eSBastian Koppelmann int64_t result; 1920974257eSBastian Koppelmann 1930974257eSBastian Koppelmann if (t1 > t2) { 1940974257eSBastian Koppelmann result = t1 - t2; 1950974257eSBastian Koppelmann } else { 1960974257eSBastian Koppelmann result = t2 - t1; 1970974257eSBastian Koppelmann } 1980974257eSBastian Koppelmann SSOV(env, ret, result, 32); 1990974257eSBastian Koppelmann return ret; 2000974257eSBastian Koppelmann } 201328f1f0fSBastian Koppelmann 202328f1f0fSBastian Koppelmann target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1, 203328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 204328f1f0fSBastian Koppelmann { 205328f1f0fSBastian Koppelmann target_ulong ret; 206328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 207328f1f0fSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 208328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 209328f1f0fSBastian Koppelmann int64_t result; 210328f1f0fSBastian Koppelmann 211328f1f0fSBastian Koppelmann result = t2 + (t1 * t3); 212328f1f0fSBastian Koppelmann SSOV(env, ret, result, 32); 213328f1f0fSBastian Koppelmann return ret; 214328f1f0fSBastian Koppelmann } 215328f1f0fSBastian Koppelmann 216328f1f0fSBastian Koppelmann target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, 217328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 218328f1f0fSBastian Koppelmann { 219328f1f0fSBastian Koppelmann target_ulong ret; 220328f1f0fSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 221328f1f0fSBastian Koppelmann uint64_t t2 = extract64(r2, 0, 32); 222328f1f0fSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 223328f1f0fSBastian Koppelmann int64_t result; 224328f1f0fSBastian Koppelmann 225328f1f0fSBastian Koppelmann result = t2 + (t1 * t3); 226328f1f0fSBastian Koppelmann SUOV(env, ret, result, 32); 227328f1f0fSBastian Koppelmann return ret; 228328f1f0fSBastian Koppelmann } 229328f1f0fSBastian Koppelmann 230328f1f0fSBastian Koppelmann uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, 231328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 232328f1f0fSBastian Koppelmann { 233328f1f0fSBastian Koppelmann uint64_t ret, ovf; 234328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 235328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 236328f1f0fSBastian Koppelmann int64_t mul; 237328f1f0fSBastian Koppelmann 238328f1f0fSBastian Koppelmann mul = t1 * t3; 239328f1f0fSBastian Koppelmann ret = mul + r2; 240328f1f0fSBastian Koppelmann ovf = (ret ^ mul) & ~(mul ^ r2); 241328f1f0fSBastian Koppelmann 242328f1f0fSBastian Koppelmann if ((int64_t)ovf < 0) { 243328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 244328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 245328f1f0fSBastian Koppelmann /* ext_ret > MAX_INT */ 246328f1f0fSBastian Koppelmann if (mul >= 0) { 247328f1f0fSBastian Koppelmann ret = INT64_MAX; 248328f1f0fSBastian Koppelmann /* ext_ret < MIN_INT */ 249328f1f0fSBastian Koppelmann } else { 250328f1f0fSBastian Koppelmann ret = INT64_MIN; 251328f1f0fSBastian Koppelmann } 252328f1f0fSBastian Koppelmann } else { 253328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 254328f1f0fSBastian Koppelmann } 255328f1f0fSBastian Koppelmann t1 = ret >> 32; 256328f1f0fSBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 257328f1f0fSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 258328f1f0fSBastian Koppelmann 259328f1f0fSBastian Koppelmann return ret; 260328f1f0fSBastian Koppelmann } 261328f1f0fSBastian Koppelmann 262328f1f0fSBastian Koppelmann uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1, 263328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 264328f1f0fSBastian Koppelmann { 265328f1f0fSBastian Koppelmann uint64_t ret, mul; 266328f1f0fSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 267328f1f0fSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 268328f1f0fSBastian Koppelmann 269328f1f0fSBastian Koppelmann mul = t1 * t3; 270328f1f0fSBastian Koppelmann ret = mul + r2; 271328f1f0fSBastian Koppelmann 272328f1f0fSBastian Koppelmann if (ret < r2) { 273328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 274328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 275328f1f0fSBastian Koppelmann /* saturate */ 276328f1f0fSBastian Koppelmann ret = UINT64_MAX; 277328f1f0fSBastian Koppelmann } else { 278328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 279328f1f0fSBastian Koppelmann } 280328f1f0fSBastian Koppelmann t1 = ret >> 32; 281328f1f0fSBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 282328f1f0fSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 283328f1f0fSBastian Koppelmann return ret; 284328f1f0fSBastian Koppelmann } 285328f1f0fSBastian Koppelmann 286328f1f0fSBastian Koppelmann target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1, 287328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 288328f1f0fSBastian Koppelmann { 289328f1f0fSBastian Koppelmann target_ulong ret; 290328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 291328f1f0fSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 292328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 293328f1f0fSBastian Koppelmann int64_t result; 294328f1f0fSBastian Koppelmann 295328f1f0fSBastian Koppelmann result = t2 - (t1 * t3); 296328f1f0fSBastian Koppelmann SSOV(env, ret, result, 32); 297328f1f0fSBastian Koppelmann return ret; 298328f1f0fSBastian Koppelmann } 299328f1f0fSBastian Koppelmann 300328f1f0fSBastian Koppelmann target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, 301328f1f0fSBastian Koppelmann target_ulong r2, target_ulong r3) 302328f1f0fSBastian Koppelmann { 303328f1f0fSBastian Koppelmann target_ulong ret; 304328f1f0fSBastian Koppelmann int64_t t1 = extract64(r1, 0, 32); 305328f1f0fSBastian Koppelmann int64_t t2 = extract64(r2, 0, 32); 306328f1f0fSBastian Koppelmann int64_t t3 = extract64(r3, 0, 32); 307328f1f0fSBastian Koppelmann int64_t result; 308328f1f0fSBastian Koppelmann 309328f1f0fSBastian Koppelmann result = t2 - (t1 * t3); 310328f1f0fSBastian Koppelmann SUOV(env, ret, result, 32); 311328f1f0fSBastian Koppelmann return ret; 312328f1f0fSBastian Koppelmann } 313328f1f0fSBastian Koppelmann 314328f1f0fSBastian Koppelmann uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, 315328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 316328f1f0fSBastian Koppelmann { 317328f1f0fSBastian Koppelmann uint64_t ret, ovf; 318328f1f0fSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 319328f1f0fSBastian Koppelmann int64_t t3 = sextract64(r3, 0, 32); 320328f1f0fSBastian Koppelmann int64_t mul; 321328f1f0fSBastian Koppelmann 322328f1f0fSBastian Koppelmann mul = t1 * t3; 323328f1f0fSBastian Koppelmann ret = r2 - mul; 324328f1f0fSBastian Koppelmann ovf = (ret ^ r2) & (mul ^ r2); 325328f1f0fSBastian Koppelmann 326328f1f0fSBastian Koppelmann if ((int64_t)ovf < 0) { 327328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 328328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 329328f1f0fSBastian Koppelmann /* ext_ret > MAX_INT */ 330328f1f0fSBastian Koppelmann if (mul < 0) { 331328f1f0fSBastian Koppelmann ret = INT64_MAX; 332328f1f0fSBastian Koppelmann /* ext_ret < MIN_INT */ 333328f1f0fSBastian Koppelmann } else { 334328f1f0fSBastian Koppelmann ret = INT64_MIN; 335328f1f0fSBastian Koppelmann } 336328f1f0fSBastian Koppelmann } else { 337328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 338328f1f0fSBastian Koppelmann } 339328f1f0fSBastian Koppelmann t1 = ret >> 32; 340328f1f0fSBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 341328f1f0fSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 342328f1f0fSBastian Koppelmann return ret; 343328f1f0fSBastian Koppelmann } 344328f1f0fSBastian Koppelmann 345328f1f0fSBastian Koppelmann uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1, 346328f1f0fSBastian Koppelmann uint64_t r2, target_ulong r3) 347328f1f0fSBastian Koppelmann { 348328f1f0fSBastian Koppelmann uint64_t ret, mul; 349328f1f0fSBastian Koppelmann uint64_t t1 = extract64(r1, 0, 32); 350328f1f0fSBastian Koppelmann uint64_t t3 = extract64(r3, 0, 32); 351328f1f0fSBastian Koppelmann 352328f1f0fSBastian Koppelmann mul = t1 * t3; 353328f1f0fSBastian Koppelmann ret = r2 - mul; 354328f1f0fSBastian Koppelmann 355328f1f0fSBastian Koppelmann if (ret > r2) { 356328f1f0fSBastian Koppelmann env->PSW_USB_V = (1 << 31); 357328f1f0fSBastian Koppelmann env->PSW_USB_SV = (1 << 31); 358328f1f0fSBastian Koppelmann /* saturate */ 359328f1f0fSBastian Koppelmann ret = 0; 360328f1f0fSBastian Koppelmann } else { 361328f1f0fSBastian Koppelmann env->PSW_USB_V = 0; 362328f1f0fSBastian Koppelmann } 363328f1f0fSBastian Koppelmann t1 = ret >> 32; 364328f1f0fSBastian Koppelmann env->PSW_USB_AV = t1 ^ t1 * 2u; 365328f1f0fSBastian Koppelmann env->PSW_USB_SAV |= env->PSW_USB_AV; 366328f1f0fSBastian Koppelmann return ret; 367328f1f0fSBastian Koppelmann } 368328f1f0fSBastian Koppelmann 3699a31922bSBastian Koppelmann /* context save area (CSA) related helpers */ 3709a31922bSBastian Koppelmann 3719a31922bSBastian Koppelmann static int cdc_increment(target_ulong *psw) 3729a31922bSBastian Koppelmann { 3739a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 3749a31922bSBastian Koppelmann return 0; 3759a31922bSBastian Koppelmann } 3769a31922bSBastian Koppelmann 3779a31922bSBastian Koppelmann (*psw)++; 3789a31922bSBastian Koppelmann /* check for overflow */ 3799a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 3809a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 3819a31922bSBastian Koppelmann int count = *psw & mask; 3829a31922bSBastian Koppelmann if (count == 0) { 3839a31922bSBastian Koppelmann (*psw)--; 3849a31922bSBastian Koppelmann return 1; 3859a31922bSBastian Koppelmann } 3869a31922bSBastian Koppelmann return 0; 3879a31922bSBastian Koppelmann } 3889a31922bSBastian Koppelmann 3899a31922bSBastian Koppelmann static int cdc_decrement(target_ulong *psw) 3909a31922bSBastian Koppelmann { 3919a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 3929a31922bSBastian Koppelmann return 0; 3939a31922bSBastian Koppelmann } 3949a31922bSBastian Koppelmann /* check for underflow */ 3959a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 3969a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 3979a31922bSBastian Koppelmann int count = *psw & mask; 3989a31922bSBastian Koppelmann if (count == 0) { 3999a31922bSBastian Koppelmann return 1; 4009a31922bSBastian Koppelmann } 4019a31922bSBastian Koppelmann (*psw)--; 4029a31922bSBastian Koppelmann return 0; 4039a31922bSBastian Koppelmann } 4049a31922bSBastian Koppelmann 40544ea3430SBastian Koppelmann static bool cdc_zero(target_ulong *psw) 40644ea3430SBastian Koppelmann { 40744ea3430SBastian Koppelmann int cdc = *psw & MASK_PSW_CDC; 40844ea3430SBastian Koppelmann /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == 40944ea3430SBastian Koppelmann 7'b1111111, otherwise returns FALSE. */ 41044ea3430SBastian Koppelmann if (cdc == 0x7f) { 41144ea3430SBastian Koppelmann return true; 41244ea3430SBastian Koppelmann } 41344ea3430SBastian Koppelmann /* find CDC.COUNT */ 41444ea3430SBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 41544ea3430SBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 41644ea3430SBastian Koppelmann int count = *psw & mask; 41744ea3430SBastian Koppelmann return count == 0; 41844ea3430SBastian Koppelmann } 41944ea3430SBastian Koppelmann 420030c58dfSBastian Koppelmann static void save_context_upper(CPUTriCoreState *env, int ea) 4219a31922bSBastian Koppelmann { 4229a31922bSBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 4239a31922bSBastian Koppelmann cpu_stl_data(env, ea+4, env->PSW); 4249a31922bSBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[10]); 4259a31922bSBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[11]); 4269a31922bSBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[8]); 4279a31922bSBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[9]); 4289a31922bSBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[10]); 4299a31922bSBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[11]); 4309a31922bSBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[12]); 4319a31922bSBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[13]); 4329a31922bSBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[14]); 4339a31922bSBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[15]); 4349a31922bSBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[12]); 4359a31922bSBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[13]); 4369a31922bSBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[14]); 4379a31922bSBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[15]); 4389a31922bSBastian Koppelmann } 4399a31922bSBastian Koppelmann 440030c58dfSBastian Koppelmann static void save_context_lower(CPUTriCoreState *env, int ea) 4415de93515SBastian Koppelmann { 4425de93515SBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 443030c58dfSBastian Koppelmann cpu_stl_data(env, ea+4, env->gpr_a[11]); 4445de93515SBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[2]); 4455de93515SBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[3]); 4465de93515SBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[0]); 4475de93515SBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[1]); 4485de93515SBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[2]); 4495de93515SBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[3]); 4505de93515SBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[4]); 4515de93515SBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[5]); 4525de93515SBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[6]); 4535de93515SBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[7]); 4545de93515SBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[4]); 4555de93515SBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[5]); 4565de93515SBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[6]); 4575de93515SBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[7]); 4585de93515SBastian Koppelmann } 4595de93515SBastian Koppelmann 4609a31922bSBastian Koppelmann static void restore_context_upper(CPUTriCoreState *env, int ea, 4619a31922bSBastian Koppelmann target_ulong *new_PCXI, target_ulong *new_PSW) 4629a31922bSBastian Koppelmann { 4639a31922bSBastian Koppelmann *new_PCXI = cpu_ldl_data(env, ea); 4649a31922bSBastian Koppelmann *new_PSW = cpu_ldl_data(env, ea+4); 4659a31922bSBastian Koppelmann env->gpr_a[10] = cpu_ldl_data(env, ea+8); 4669a31922bSBastian Koppelmann env->gpr_a[11] = cpu_ldl_data(env, ea+12); 4679a31922bSBastian Koppelmann env->gpr_d[8] = cpu_ldl_data(env, ea+16); 4689a31922bSBastian Koppelmann env->gpr_d[9] = cpu_ldl_data(env, ea+20); 4699a31922bSBastian Koppelmann env->gpr_d[10] = cpu_ldl_data(env, ea+24); 4709a31922bSBastian Koppelmann env->gpr_d[11] = cpu_ldl_data(env, ea+28); 4719a31922bSBastian Koppelmann env->gpr_a[12] = cpu_ldl_data(env, ea+32); 4729a31922bSBastian Koppelmann env->gpr_a[13] = cpu_ldl_data(env, ea+36); 4739a31922bSBastian Koppelmann env->gpr_a[14] = cpu_ldl_data(env, ea+40); 4749a31922bSBastian Koppelmann env->gpr_a[15] = cpu_ldl_data(env, ea+44); 4759a31922bSBastian Koppelmann env->gpr_d[12] = cpu_ldl_data(env, ea+48); 4769a31922bSBastian Koppelmann env->gpr_d[13] = cpu_ldl_data(env, ea+52); 4779a31922bSBastian Koppelmann env->gpr_d[14] = cpu_ldl_data(env, ea+56); 4789a31922bSBastian Koppelmann env->gpr_d[15] = cpu_ldl_data(env, ea+60); 4799a31922bSBastian Koppelmann } 4809a31922bSBastian Koppelmann 48159543d4eSBastian Koppelmann static void restore_context_lower(CPUTriCoreState *env, int ea, 48259543d4eSBastian Koppelmann target_ulong *ra, target_ulong *pcxi) 48359543d4eSBastian Koppelmann { 48459543d4eSBastian Koppelmann *pcxi = cpu_ldl_data(env, ea); 48559543d4eSBastian Koppelmann *ra = cpu_ldl_data(env, ea+4); 48659543d4eSBastian Koppelmann env->gpr_a[2] = cpu_ldl_data(env, ea+8); 48759543d4eSBastian Koppelmann env->gpr_a[3] = cpu_ldl_data(env, ea+12); 48859543d4eSBastian Koppelmann env->gpr_d[0] = cpu_ldl_data(env, ea+16); 48959543d4eSBastian Koppelmann env->gpr_d[1] = cpu_ldl_data(env, ea+20); 49059543d4eSBastian Koppelmann env->gpr_d[2] = cpu_ldl_data(env, ea+24); 49159543d4eSBastian Koppelmann env->gpr_d[3] = cpu_ldl_data(env, ea+28); 49259543d4eSBastian Koppelmann env->gpr_a[4] = cpu_ldl_data(env, ea+32); 49359543d4eSBastian Koppelmann env->gpr_a[5] = cpu_ldl_data(env, ea+36); 49459543d4eSBastian Koppelmann env->gpr_a[6] = cpu_ldl_data(env, ea+40); 49559543d4eSBastian Koppelmann env->gpr_a[7] = cpu_ldl_data(env, ea+44); 49659543d4eSBastian Koppelmann env->gpr_d[4] = cpu_ldl_data(env, ea+48); 49759543d4eSBastian Koppelmann env->gpr_d[5] = cpu_ldl_data(env, ea+52); 49859543d4eSBastian Koppelmann env->gpr_d[6] = cpu_ldl_data(env, ea+56); 49959543d4eSBastian Koppelmann env->gpr_d[7] = cpu_ldl_data(env, ea+60); 50059543d4eSBastian Koppelmann } 50159543d4eSBastian Koppelmann 5029a31922bSBastian Koppelmann void helper_call(CPUTriCoreState *env, uint32_t next_pc) 5039a31922bSBastian Koppelmann { 5049a31922bSBastian Koppelmann target_ulong tmp_FCX; 5059a31922bSBastian Koppelmann target_ulong ea; 5069a31922bSBastian Koppelmann target_ulong new_FCX; 5079a31922bSBastian Koppelmann target_ulong psw; 5089a31922bSBastian Koppelmann 5099a31922bSBastian Koppelmann psw = psw_read(env); 5109a31922bSBastian Koppelmann /* if (FCX == 0) trap(FCU); */ 5119a31922bSBastian Koppelmann if (env->FCX == 0) { 5129a31922bSBastian Koppelmann /* FCU trap */ 5139a31922bSBastian Koppelmann } 5149a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ 5159a31922bSBastian Koppelmann if (psw & MASK_PSW_CDE) { 5169a31922bSBastian Koppelmann if (cdc_increment(&psw)) { 5179a31922bSBastian Koppelmann /* CDO trap */ 5189a31922bSBastian Koppelmann } 5199a31922bSBastian Koppelmann } 5209a31922bSBastian Koppelmann /* PSW.CDE = 1;*/ 5219a31922bSBastian Koppelmann psw |= MASK_PSW_CDE; 5229a31922bSBastian Koppelmann /* tmp_FCX = FCX; */ 5239a31922bSBastian Koppelmann tmp_FCX = env->FCX; 5249a31922bSBastian Koppelmann /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 5259a31922bSBastian Koppelmann ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 5269a31922bSBastian Koppelmann ((env->FCX & MASK_FCX_FCXO) << 6); 527030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 528030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 529030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 5309a31922bSBastian Koppelmann A[12], A[13], A[14], A[15], D[12], D[13], D[14], 5319a31922bSBastian Koppelmann D[15]}; */ 532030c58dfSBastian Koppelmann save_context_upper(env, ea); 5339a31922bSBastian Koppelmann 5349a31922bSBastian Koppelmann /* PCXI.PCPN = ICR.CCPN; */ 5359a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 5369a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 5379a31922bSBastian Koppelmann /* PCXI.PIE = ICR.IE; */ 5389a31922bSBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 5399a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 5409a31922bSBastian Koppelmann /* PCXI.UL = 1; */ 5419a31922bSBastian Koppelmann env->PCXI |= MASK_PCXI_UL; 5429a31922bSBastian Koppelmann 5439a31922bSBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0]; */ 5449a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 5459a31922bSBastian Koppelmann /* FCX[19: 0] = new_FCX[19: 0]; */ 5469a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 5479a31922bSBastian Koppelmann /* A[11] = next_pc[31: 0]; */ 5489a31922bSBastian Koppelmann env->gpr_a[11] = next_pc; 5499a31922bSBastian Koppelmann 5509a31922bSBastian Koppelmann /* if (tmp_FCX == LCX) trap(FCD);*/ 5519a31922bSBastian Koppelmann if (tmp_FCX == env->LCX) { 5529a31922bSBastian Koppelmann /* FCD trap */ 5539a31922bSBastian Koppelmann } 5549a31922bSBastian Koppelmann psw_write(env, psw); 5559a31922bSBastian Koppelmann } 5569a31922bSBastian Koppelmann 5579a31922bSBastian Koppelmann void helper_ret(CPUTriCoreState *env) 5589a31922bSBastian Koppelmann { 5599a31922bSBastian Koppelmann target_ulong ea; 5609a31922bSBastian Koppelmann target_ulong new_PCXI; 5619a31922bSBastian Koppelmann target_ulong new_PSW, psw; 5629a31922bSBastian Koppelmann 5639a31922bSBastian Koppelmann psw = psw_read(env); 5649a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ 5659a31922bSBastian Koppelmann if (env->PSW & MASK_PSW_CDE) { 5669a31922bSBastian Koppelmann if (cdc_decrement(&(env->PSW))) { 5679a31922bSBastian Koppelmann /* CDU trap */ 5689a31922bSBastian Koppelmann } 5699a31922bSBastian Koppelmann } 5709a31922bSBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 5719a31922bSBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 5729a31922bSBastian Koppelmann /* CSU trap */ 5739a31922bSBastian Koppelmann } 5749a31922bSBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 5759a31922bSBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 5769a31922bSBastian Koppelmann /* CTYP trap */ 5779a31922bSBastian Koppelmann } 5789a31922bSBastian Koppelmann /* PC = {A11 [31: 1], 1’b0}; */ 5799a31922bSBastian Koppelmann env->PC = env->gpr_a[11] & 0xfffffffe; 5809a31922bSBastian Koppelmann 5819a31922bSBastian Koppelmann /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ 5829a31922bSBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 5839a31922bSBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 5849a31922bSBastian Koppelmann /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 585030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 5869a31922bSBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 587030c58dfSBastian Koppelmann /* M(EA, word) = FCX; */ 588030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 5899a31922bSBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 5909a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 5919a31922bSBastian Koppelmann /* PCXI = new_PCXI; */ 5929a31922bSBastian Koppelmann env->PCXI = new_PCXI; 5939a31922bSBastian Koppelmann 5949a31922bSBastian Koppelmann if (tricore_feature(env, TRICORE_FEATURE_13)) { 5959a31922bSBastian Koppelmann /* PSW = new_PSW */ 5969a31922bSBastian Koppelmann psw_write(env, new_PSW); 5979a31922bSBastian Koppelmann } else { 5989a31922bSBastian Koppelmann /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */ 5999a31922bSBastian Koppelmann psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000))); 6009a31922bSBastian Koppelmann } 6019a31922bSBastian Koppelmann } 6029a31922bSBastian Koppelmann 6035de93515SBastian Koppelmann void helper_bisr(CPUTriCoreState *env, uint32_t const9) 6045de93515SBastian Koppelmann { 6055de93515SBastian Koppelmann target_ulong tmp_FCX; 6065de93515SBastian Koppelmann target_ulong ea; 6075de93515SBastian Koppelmann target_ulong new_FCX; 6085de93515SBastian Koppelmann 6095de93515SBastian Koppelmann if (env->FCX == 0) { 6105de93515SBastian Koppelmann /* FCU trap */ 6115de93515SBastian Koppelmann } 6125de93515SBastian Koppelmann 6135de93515SBastian Koppelmann tmp_FCX = env->FCX; 6145de93515SBastian Koppelmann ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6); 6155de93515SBastian Koppelmann 616030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 617030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 618030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4] 619030c58dfSBastian Koppelmann , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */ 620030c58dfSBastian Koppelmann save_context_lower(env, ea); 621030c58dfSBastian Koppelmann 6225de93515SBastian Koppelmann 6235de93515SBastian Koppelmann /* PCXI.PCPN = ICR.CCPN */ 6245de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 6255de93515SBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 6265de93515SBastian Koppelmann /* PCXI.PIE = ICR.IE */ 6275de93515SBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 6285de93515SBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 6295de93515SBastian Koppelmann /* PCXI.UL = 0 */ 6305de93515SBastian Koppelmann env->PCXI &= ~(MASK_PCXI_UL); 6315de93515SBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0] */ 6325de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 6335de93515SBastian Koppelmann /* FXC[19: 0] = new_FCX[19: 0] */ 6345de93515SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 6355de93515SBastian Koppelmann /* ICR.IE = 1 */ 6365de93515SBastian Koppelmann env->ICR |= MASK_ICR_IE; 6375de93515SBastian Koppelmann 6385de93515SBastian Koppelmann env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/ 6395de93515SBastian Koppelmann 6405de93515SBastian Koppelmann if (tmp_FCX == env->LCX) { 6415de93515SBastian Koppelmann /* FCD trap */ 6425de93515SBastian Koppelmann } 6435de93515SBastian Koppelmann } 6445de93515SBastian Koppelmann 64544ea3430SBastian Koppelmann void helper_rfe(CPUTriCoreState *env) 64644ea3430SBastian Koppelmann { 64744ea3430SBastian Koppelmann target_ulong ea; 64844ea3430SBastian Koppelmann target_ulong new_PCXI; 64944ea3430SBastian Koppelmann target_ulong new_PSW; 65044ea3430SBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 65144ea3430SBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 65244ea3430SBastian Koppelmann /* raise csu trap */ 65344ea3430SBastian Koppelmann } 65444ea3430SBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 65544ea3430SBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 65644ea3430SBastian Koppelmann /* raise CTYP trap */ 65744ea3430SBastian Koppelmann } 65844ea3430SBastian Koppelmann /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ 65944ea3430SBastian Koppelmann if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { 66044ea3430SBastian Koppelmann /* raise MNG trap */ 66144ea3430SBastian Koppelmann } 66244ea3430SBastian Koppelmann /* ICR.IE = PCXI.PIE; */ 66344ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); 66444ea3430SBastian Koppelmann /* ICR.CCPN = PCXI.PCPN; */ 66544ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_CCPN) + 66644ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCPN) >> 24); 66744ea3430SBastian Koppelmann /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ 66844ea3430SBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 66944ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 67044ea3430SBastian Koppelmann /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 671030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 67244ea3430SBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 673030c58dfSBastian Koppelmann /* M(EA, word) = FCX;*/ 674030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 67544ea3430SBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 67644ea3430SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 67744ea3430SBastian Koppelmann /* PCXI = new_PCXI; */ 67844ea3430SBastian Koppelmann env->PCXI = new_PCXI; 67944ea3430SBastian Koppelmann /* write psw */ 68044ea3430SBastian Koppelmann psw_write(env, new_PSW); 68144ea3430SBastian Koppelmann } 68244ea3430SBastian Koppelmann 68359543d4eSBastian Koppelmann void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) 68459543d4eSBastian Koppelmann { 68559543d4eSBastian Koppelmann uint32_t dummy; 68659543d4eSBastian Koppelmann /* insn doesn't load PCXI and RA */ 68759543d4eSBastian Koppelmann restore_context_lower(env, ea, &dummy, &dummy); 68859543d4eSBastian Koppelmann } 68959543d4eSBastian Koppelmann 69059543d4eSBastian Koppelmann void helper_lducx(CPUTriCoreState *env, uint32_t ea) 69159543d4eSBastian Koppelmann { 69259543d4eSBastian Koppelmann uint32_t dummy; 69359543d4eSBastian Koppelmann /* insn doesn't load PCXI and PSW */ 69459543d4eSBastian Koppelmann restore_context_upper(env, ea, &dummy, &dummy); 69559543d4eSBastian Koppelmann } 69659543d4eSBastian Koppelmann 69759543d4eSBastian Koppelmann void helper_stlcx(CPUTriCoreState *env, uint32_t ea) 69859543d4eSBastian Koppelmann { 69959543d4eSBastian Koppelmann save_context_lower(env, ea); 70059543d4eSBastian Koppelmann } 70159543d4eSBastian Koppelmann 70259543d4eSBastian Koppelmann void helper_stucx(CPUTriCoreState *env, uint32_t ea) 70359543d4eSBastian Koppelmann { 70459543d4eSBastian Koppelmann save_context_upper(env, ea); 70559543d4eSBastian Koppelmann } 70659543d4eSBastian Koppelmann 7072b2f7d97SBastian Koppelmann void helper_psw_write(CPUTriCoreState *env, uint32_t arg) 7082b2f7d97SBastian Koppelmann { 7092b2f7d97SBastian Koppelmann psw_write(env, arg); 7102b2f7d97SBastian Koppelmann } 7112b2f7d97SBastian Koppelmann 7122b2f7d97SBastian Koppelmann uint32_t helper_psw_read(CPUTriCoreState *env) 7132b2f7d97SBastian Koppelmann { 7142b2f7d97SBastian Koppelmann return psw_read(env); 7152b2f7d97SBastian Koppelmann } 7162b2f7d97SBastian Koppelmann 7172b2f7d97SBastian Koppelmann 7182d30267eSBastian Koppelmann static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 7192d30267eSBastian Koppelmann uint32_t exception, 7202d30267eSBastian Koppelmann int error_code, 7212d30267eSBastian Koppelmann uintptr_t pc) 7222d30267eSBastian Koppelmann { 7232d30267eSBastian Koppelmann CPUState *cs = CPU(tricore_env_get_cpu(env)); 7242d30267eSBastian Koppelmann cs->exception_index = exception; 7252d30267eSBastian Koppelmann env->error_code = error_code; 7262d30267eSBastian Koppelmann 7272d30267eSBastian Koppelmann if (pc) { 7282d30267eSBastian Koppelmann /* now we have a real cpu fault */ 7292d30267eSBastian Koppelmann cpu_restore_state(cs, pc); 7302d30267eSBastian Koppelmann } 7312d30267eSBastian Koppelmann 7322d30267eSBastian Koppelmann cpu_loop_exit(cs); 7332d30267eSBastian Koppelmann } 7342d30267eSBastian Koppelmann 73548e06fe0SBastian Koppelmann void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, 73648e06fe0SBastian Koppelmann uintptr_t retaddr) 73748e06fe0SBastian Koppelmann { 7382d30267eSBastian Koppelmann int ret; 7392d30267eSBastian Koppelmann ret = cpu_tricore_handle_mmu_fault(cs, addr, is_write, mmu_idx); 7402d30267eSBastian Koppelmann if (ret) { 7412d30267eSBastian Koppelmann TriCoreCPU *cpu = TRICORE_CPU(cs); 7422d30267eSBastian Koppelmann CPUTriCoreState *env = &cpu->env; 7432d30267eSBastian Koppelmann do_raise_exception_err(env, cs->exception_index, 7442d30267eSBastian Koppelmann env->error_code, retaddr); 74548e06fe0SBastian Koppelmann } 7462d30267eSBastian Koppelmann } 747