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 } 2019a31922bSBastian Koppelmann /* context save area (CSA) related helpers */ 2029a31922bSBastian Koppelmann 2039a31922bSBastian Koppelmann static int cdc_increment(target_ulong *psw) 2049a31922bSBastian Koppelmann { 2059a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 2069a31922bSBastian Koppelmann return 0; 2079a31922bSBastian Koppelmann } 2089a31922bSBastian Koppelmann 2099a31922bSBastian Koppelmann (*psw)++; 2109a31922bSBastian Koppelmann /* check for overflow */ 2119a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 2129a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 2139a31922bSBastian Koppelmann int count = *psw & mask; 2149a31922bSBastian Koppelmann if (count == 0) { 2159a31922bSBastian Koppelmann (*psw)--; 2169a31922bSBastian Koppelmann return 1; 2179a31922bSBastian Koppelmann } 2189a31922bSBastian Koppelmann return 0; 2199a31922bSBastian Koppelmann } 2209a31922bSBastian Koppelmann 2219a31922bSBastian Koppelmann static int cdc_decrement(target_ulong *psw) 2229a31922bSBastian Koppelmann { 2239a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 2249a31922bSBastian Koppelmann return 0; 2259a31922bSBastian Koppelmann } 2269a31922bSBastian Koppelmann /* check for underflow */ 2279a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 2289a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 2299a31922bSBastian Koppelmann int count = *psw & mask; 2309a31922bSBastian Koppelmann if (count == 0) { 2319a31922bSBastian Koppelmann return 1; 2329a31922bSBastian Koppelmann } 2339a31922bSBastian Koppelmann (*psw)--; 2349a31922bSBastian Koppelmann return 0; 2359a31922bSBastian Koppelmann } 2369a31922bSBastian Koppelmann 23744ea3430SBastian Koppelmann static bool cdc_zero(target_ulong *psw) 23844ea3430SBastian Koppelmann { 23944ea3430SBastian Koppelmann int cdc = *psw & MASK_PSW_CDC; 24044ea3430SBastian Koppelmann /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == 24144ea3430SBastian Koppelmann 7'b1111111, otherwise returns FALSE. */ 24244ea3430SBastian Koppelmann if (cdc == 0x7f) { 24344ea3430SBastian Koppelmann return true; 24444ea3430SBastian Koppelmann } 24544ea3430SBastian Koppelmann /* find CDC.COUNT */ 24644ea3430SBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 24744ea3430SBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 24844ea3430SBastian Koppelmann int count = *psw & mask; 24944ea3430SBastian Koppelmann return count == 0; 25044ea3430SBastian Koppelmann } 25144ea3430SBastian Koppelmann 252030c58dfSBastian Koppelmann static void save_context_upper(CPUTriCoreState *env, int ea) 2539a31922bSBastian Koppelmann { 2549a31922bSBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 2559a31922bSBastian Koppelmann cpu_stl_data(env, ea+4, env->PSW); 2569a31922bSBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[10]); 2579a31922bSBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[11]); 2589a31922bSBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[8]); 2599a31922bSBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[9]); 2609a31922bSBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[10]); 2619a31922bSBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[11]); 2629a31922bSBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[12]); 2639a31922bSBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[13]); 2649a31922bSBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[14]); 2659a31922bSBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[15]); 2669a31922bSBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[12]); 2679a31922bSBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[13]); 2689a31922bSBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[14]); 2699a31922bSBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[15]); 2709a31922bSBastian Koppelmann } 2719a31922bSBastian Koppelmann 272030c58dfSBastian Koppelmann static void save_context_lower(CPUTriCoreState *env, int ea) 2735de93515SBastian Koppelmann { 2745de93515SBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 275030c58dfSBastian Koppelmann cpu_stl_data(env, ea+4, env->gpr_a[11]); 2765de93515SBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[2]); 2775de93515SBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[3]); 2785de93515SBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[0]); 2795de93515SBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[1]); 2805de93515SBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[2]); 2815de93515SBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[3]); 2825de93515SBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[4]); 2835de93515SBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[5]); 2845de93515SBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[6]); 2855de93515SBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[7]); 2865de93515SBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[4]); 2875de93515SBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[5]); 2885de93515SBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[6]); 2895de93515SBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[7]); 2905de93515SBastian Koppelmann } 2915de93515SBastian Koppelmann 2929a31922bSBastian Koppelmann static void restore_context_upper(CPUTriCoreState *env, int ea, 2939a31922bSBastian Koppelmann target_ulong *new_PCXI, target_ulong *new_PSW) 2949a31922bSBastian Koppelmann { 2959a31922bSBastian Koppelmann *new_PCXI = cpu_ldl_data(env, ea); 2969a31922bSBastian Koppelmann *new_PSW = cpu_ldl_data(env, ea+4); 2979a31922bSBastian Koppelmann env->gpr_a[10] = cpu_ldl_data(env, ea+8); 2989a31922bSBastian Koppelmann env->gpr_a[11] = cpu_ldl_data(env, ea+12); 2999a31922bSBastian Koppelmann env->gpr_d[8] = cpu_ldl_data(env, ea+16); 3009a31922bSBastian Koppelmann env->gpr_d[9] = cpu_ldl_data(env, ea+20); 3019a31922bSBastian Koppelmann env->gpr_d[10] = cpu_ldl_data(env, ea+24); 3029a31922bSBastian Koppelmann env->gpr_d[11] = cpu_ldl_data(env, ea+28); 3039a31922bSBastian Koppelmann env->gpr_a[12] = cpu_ldl_data(env, ea+32); 3049a31922bSBastian Koppelmann env->gpr_a[13] = cpu_ldl_data(env, ea+36); 3059a31922bSBastian Koppelmann env->gpr_a[14] = cpu_ldl_data(env, ea+40); 3069a31922bSBastian Koppelmann env->gpr_a[15] = cpu_ldl_data(env, ea+44); 3079a31922bSBastian Koppelmann env->gpr_d[12] = cpu_ldl_data(env, ea+48); 3089a31922bSBastian Koppelmann env->gpr_d[13] = cpu_ldl_data(env, ea+52); 3099a31922bSBastian Koppelmann env->gpr_d[14] = cpu_ldl_data(env, ea+56); 3109a31922bSBastian Koppelmann env->gpr_d[15] = cpu_ldl_data(env, ea+60); 3119a31922bSBastian Koppelmann } 3129a31922bSBastian Koppelmann 31359543d4eSBastian Koppelmann static void restore_context_lower(CPUTriCoreState *env, int ea, 31459543d4eSBastian Koppelmann target_ulong *ra, target_ulong *pcxi) 31559543d4eSBastian Koppelmann { 31659543d4eSBastian Koppelmann *pcxi = cpu_ldl_data(env, ea); 31759543d4eSBastian Koppelmann *ra = cpu_ldl_data(env, ea+4); 31859543d4eSBastian Koppelmann env->gpr_a[2] = cpu_ldl_data(env, ea+8); 31959543d4eSBastian Koppelmann env->gpr_a[3] = cpu_ldl_data(env, ea+12); 32059543d4eSBastian Koppelmann env->gpr_d[0] = cpu_ldl_data(env, ea+16); 32159543d4eSBastian Koppelmann env->gpr_d[1] = cpu_ldl_data(env, ea+20); 32259543d4eSBastian Koppelmann env->gpr_d[2] = cpu_ldl_data(env, ea+24); 32359543d4eSBastian Koppelmann env->gpr_d[3] = cpu_ldl_data(env, ea+28); 32459543d4eSBastian Koppelmann env->gpr_a[4] = cpu_ldl_data(env, ea+32); 32559543d4eSBastian Koppelmann env->gpr_a[5] = cpu_ldl_data(env, ea+36); 32659543d4eSBastian Koppelmann env->gpr_a[6] = cpu_ldl_data(env, ea+40); 32759543d4eSBastian Koppelmann env->gpr_a[7] = cpu_ldl_data(env, ea+44); 32859543d4eSBastian Koppelmann env->gpr_d[4] = cpu_ldl_data(env, ea+48); 32959543d4eSBastian Koppelmann env->gpr_d[5] = cpu_ldl_data(env, ea+52); 33059543d4eSBastian Koppelmann env->gpr_d[6] = cpu_ldl_data(env, ea+56); 33159543d4eSBastian Koppelmann env->gpr_d[7] = cpu_ldl_data(env, ea+60); 33259543d4eSBastian Koppelmann } 33359543d4eSBastian Koppelmann 3349a31922bSBastian Koppelmann void helper_call(CPUTriCoreState *env, uint32_t next_pc) 3359a31922bSBastian Koppelmann { 3369a31922bSBastian Koppelmann target_ulong tmp_FCX; 3379a31922bSBastian Koppelmann target_ulong ea; 3389a31922bSBastian Koppelmann target_ulong new_FCX; 3399a31922bSBastian Koppelmann target_ulong psw; 3409a31922bSBastian Koppelmann 3419a31922bSBastian Koppelmann psw = psw_read(env); 3429a31922bSBastian Koppelmann /* if (FCX == 0) trap(FCU); */ 3439a31922bSBastian Koppelmann if (env->FCX == 0) { 3449a31922bSBastian Koppelmann /* FCU trap */ 3459a31922bSBastian Koppelmann } 3469a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ 3479a31922bSBastian Koppelmann if (psw & MASK_PSW_CDE) { 3489a31922bSBastian Koppelmann if (cdc_increment(&psw)) { 3499a31922bSBastian Koppelmann /* CDO trap */ 3509a31922bSBastian Koppelmann } 3519a31922bSBastian Koppelmann } 3529a31922bSBastian Koppelmann /* PSW.CDE = 1;*/ 3539a31922bSBastian Koppelmann psw |= MASK_PSW_CDE; 3549a31922bSBastian Koppelmann /* tmp_FCX = FCX; */ 3559a31922bSBastian Koppelmann tmp_FCX = env->FCX; 3569a31922bSBastian Koppelmann /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 3579a31922bSBastian Koppelmann ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 3589a31922bSBastian Koppelmann ((env->FCX & MASK_FCX_FCXO) << 6); 359030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 360030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 361030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 3629a31922bSBastian Koppelmann A[12], A[13], A[14], A[15], D[12], D[13], D[14], 3639a31922bSBastian Koppelmann D[15]}; */ 364030c58dfSBastian Koppelmann save_context_upper(env, ea); 3659a31922bSBastian Koppelmann 3669a31922bSBastian Koppelmann /* PCXI.PCPN = ICR.CCPN; */ 3679a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 3689a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 3699a31922bSBastian Koppelmann /* PCXI.PIE = ICR.IE; */ 3709a31922bSBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 3719a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 3729a31922bSBastian Koppelmann /* PCXI.UL = 1; */ 3739a31922bSBastian Koppelmann env->PCXI |= MASK_PCXI_UL; 3749a31922bSBastian Koppelmann 3759a31922bSBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0]; */ 3769a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 3779a31922bSBastian Koppelmann /* FCX[19: 0] = new_FCX[19: 0]; */ 3789a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 3799a31922bSBastian Koppelmann /* A[11] = next_pc[31: 0]; */ 3809a31922bSBastian Koppelmann env->gpr_a[11] = next_pc; 3819a31922bSBastian Koppelmann 3829a31922bSBastian Koppelmann /* if (tmp_FCX == LCX) trap(FCD);*/ 3839a31922bSBastian Koppelmann if (tmp_FCX == env->LCX) { 3849a31922bSBastian Koppelmann /* FCD trap */ 3859a31922bSBastian Koppelmann } 3869a31922bSBastian Koppelmann psw_write(env, psw); 3879a31922bSBastian Koppelmann } 3889a31922bSBastian Koppelmann 3899a31922bSBastian Koppelmann void helper_ret(CPUTriCoreState *env) 3909a31922bSBastian Koppelmann { 3919a31922bSBastian Koppelmann target_ulong ea; 3929a31922bSBastian Koppelmann target_ulong new_PCXI; 3939a31922bSBastian Koppelmann target_ulong new_PSW, psw; 3949a31922bSBastian Koppelmann 3959a31922bSBastian Koppelmann psw = psw_read(env); 3969a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ 3979a31922bSBastian Koppelmann if (env->PSW & MASK_PSW_CDE) { 3989a31922bSBastian Koppelmann if (cdc_decrement(&(env->PSW))) { 3999a31922bSBastian Koppelmann /* CDU trap */ 4009a31922bSBastian Koppelmann } 4019a31922bSBastian Koppelmann } 4029a31922bSBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 4039a31922bSBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 4049a31922bSBastian Koppelmann /* CSU trap */ 4059a31922bSBastian Koppelmann } 4069a31922bSBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 4079a31922bSBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 4089a31922bSBastian Koppelmann /* CTYP trap */ 4099a31922bSBastian Koppelmann } 4109a31922bSBastian Koppelmann /* PC = {A11 [31: 1], 1’b0}; */ 4119a31922bSBastian Koppelmann env->PC = env->gpr_a[11] & 0xfffffffe; 4129a31922bSBastian Koppelmann 4139a31922bSBastian Koppelmann /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ 4149a31922bSBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 4159a31922bSBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 4169a31922bSBastian Koppelmann /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 417030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 4189a31922bSBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 419030c58dfSBastian Koppelmann /* M(EA, word) = FCX; */ 420030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 4219a31922bSBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 4229a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 4239a31922bSBastian Koppelmann /* PCXI = new_PCXI; */ 4249a31922bSBastian Koppelmann env->PCXI = new_PCXI; 4259a31922bSBastian Koppelmann 4269a31922bSBastian Koppelmann if (tricore_feature(env, TRICORE_FEATURE_13)) { 4279a31922bSBastian Koppelmann /* PSW = new_PSW */ 4289a31922bSBastian Koppelmann psw_write(env, new_PSW); 4299a31922bSBastian Koppelmann } else { 4309a31922bSBastian Koppelmann /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */ 4319a31922bSBastian Koppelmann psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000))); 4329a31922bSBastian Koppelmann } 4339a31922bSBastian Koppelmann } 4349a31922bSBastian Koppelmann 4355de93515SBastian Koppelmann void helper_bisr(CPUTriCoreState *env, uint32_t const9) 4365de93515SBastian Koppelmann { 4375de93515SBastian Koppelmann target_ulong tmp_FCX; 4385de93515SBastian Koppelmann target_ulong ea; 4395de93515SBastian Koppelmann target_ulong new_FCX; 4405de93515SBastian Koppelmann 4415de93515SBastian Koppelmann if (env->FCX == 0) { 4425de93515SBastian Koppelmann /* FCU trap */ 4435de93515SBastian Koppelmann } 4445de93515SBastian Koppelmann 4455de93515SBastian Koppelmann tmp_FCX = env->FCX; 4465de93515SBastian Koppelmann ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6); 4475de93515SBastian Koppelmann 448030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 449030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 450030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4] 451030c58dfSBastian Koppelmann , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */ 452030c58dfSBastian Koppelmann save_context_lower(env, ea); 453030c58dfSBastian Koppelmann 4545de93515SBastian Koppelmann 4555de93515SBastian Koppelmann /* PCXI.PCPN = ICR.CCPN */ 4565de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 4575de93515SBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 4585de93515SBastian Koppelmann /* PCXI.PIE = ICR.IE */ 4595de93515SBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 4605de93515SBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 4615de93515SBastian Koppelmann /* PCXI.UL = 0 */ 4625de93515SBastian Koppelmann env->PCXI &= ~(MASK_PCXI_UL); 4635de93515SBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0] */ 4645de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 4655de93515SBastian Koppelmann /* FXC[19: 0] = new_FCX[19: 0] */ 4665de93515SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 4675de93515SBastian Koppelmann /* ICR.IE = 1 */ 4685de93515SBastian Koppelmann env->ICR |= MASK_ICR_IE; 4695de93515SBastian Koppelmann 4705de93515SBastian Koppelmann env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/ 4715de93515SBastian Koppelmann 4725de93515SBastian Koppelmann if (tmp_FCX == env->LCX) { 4735de93515SBastian Koppelmann /* FCD trap */ 4745de93515SBastian Koppelmann } 4755de93515SBastian Koppelmann } 4765de93515SBastian Koppelmann 47744ea3430SBastian Koppelmann void helper_rfe(CPUTriCoreState *env) 47844ea3430SBastian Koppelmann { 47944ea3430SBastian Koppelmann target_ulong ea; 48044ea3430SBastian Koppelmann target_ulong new_PCXI; 48144ea3430SBastian Koppelmann target_ulong new_PSW; 48244ea3430SBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 48344ea3430SBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 48444ea3430SBastian Koppelmann /* raise csu trap */ 48544ea3430SBastian Koppelmann } 48644ea3430SBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 48744ea3430SBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 48844ea3430SBastian Koppelmann /* raise CTYP trap */ 48944ea3430SBastian Koppelmann } 49044ea3430SBastian Koppelmann /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ 49144ea3430SBastian Koppelmann if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { 49244ea3430SBastian Koppelmann /* raise MNG trap */ 49344ea3430SBastian Koppelmann } 49444ea3430SBastian Koppelmann /* ICR.IE = PCXI.PIE; */ 49544ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); 49644ea3430SBastian Koppelmann /* ICR.CCPN = PCXI.PCPN; */ 49744ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_CCPN) + 49844ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCPN) >> 24); 49944ea3430SBastian Koppelmann /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ 50044ea3430SBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 50144ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 50244ea3430SBastian Koppelmann /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 503030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 50444ea3430SBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 505030c58dfSBastian Koppelmann /* M(EA, word) = FCX;*/ 506030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 50744ea3430SBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 50844ea3430SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 50944ea3430SBastian Koppelmann /* PCXI = new_PCXI; */ 51044ea3430SBastian Koppelmann env->PCXI = new_PCXI; 51144ea3430SBastian Koppelmann /* write psw */ 51244ea3430SBastian Koppelmann psw_write(env, new_PSW); 51344ea3430SBastian Koppelmann } 51444ea3430SBastian Koppelmann 51559543d4eSBastian Koppelmann void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) 51659543d4eSBastian Koppelmann { 51759543d4eSBastian Koppelmann uint32_t dummy; 51859543d4eSBastian Koppelmann /* insn doesn't load PCXI and RA */ 51959543d4eSBastian Koppelmann restore_context_lower(env, ea, &dummy, &dummy); 52059543d4eSBastian Koppelmann } 52159543d4eSBastian Koppelmann 52259543d4eSBastian Koppelmann void helper_lducx(CPUTriCoreState *env, uint32_t ea) 52359543d4eSBastian Koppelmann { 52459543d4eSBastian Koppelmann uint32_t dummy; 52559543d4eSBastian Koppelmann /* insn doesn't load PCXI and PSW */ 52659543d4eSBastian Koppelmann restore_context_upper(env, ea, &dummy, &dummy); 52759543d4eSBastian Koppelmann } 52859543d4eSBastian Koppelmann 52959543d4eSBastian Koppelmann void helper_stlcx(CPUTriCoreState *env, uint32_t ea) 53059543d4eSBastian Koppelmann { 53159543d4eSBastian Koppelmann save_context_lower(env, ea); 53259543d4eSBastian Koppelmann } 53359543d4eSBastian Koppelmann 53459543d4eSBastian Koppelmann void helper_stucx(CPUTriCoreState *env, uint32_t ea) 53559543d4eSBastian Koppelmann { 53659543d4eSBastian Koppelmann save_context_upper(env, ea); 53759543d4eSBastian Koppelmann } 53859543d4eSBastian Koppelmann 5392d30267eSBastian Koppelmann static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 5402d30267eSBastian Koppelmann uint32_t exception, 5412d30267eSBastian Koppelmann int error_code, 5422d30267eSBastian Koppelmann uintptr_t pc) 5432d30267eSBastian Koppelmann { 5442d30267eSBastian Koppelmann CPUState *cs = CPU(tricore_env_get_cpu(env)); 5452d30267eSBastian Koppelmann cs->exception_index = exception; 5462d30267eSBastian Koppelmann env->error_code = error_code; 5472d30267eSBastian Koppelmann 5482d30267eSBastian Koppelmann if (pc) { 5492d30267eSBastian Koppelmann /* now we have a real cpu fault */ 5502d30267eSBastian Koppelmann cpu_restore_state(cs, pc); 5512d30267eSBastian Koppelmann } 5522d30267eSBastian Koppelmann 5532d30267eSBastian Koppelmann cpu_loop_exit(cs); 5542d30267eSBastian Koppelmann } 5552d30267eSBastian Koppelmann 55648e06fe0SBastian Koppelmann void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, 55748e06fe0SBastian Koppelmann uintptr_t retaddr) 55848e06fe0SBastian Koppelmann { 5592d30267eSBastian Koppelmann int ret; 5602d30267eSBastian Koppelmann ret = cpu_tricore_handle_mmu_fault(cs, addr, is_write, mmu_idx); 5612d30267eSBastian Koppelmann if (ret) { 5622d30267eSBastian Koppelmann TriCoreCPU *cpu = TRICORE_CPU(cs); 5632d30267eSBastian Koppelmann CPUTriCoreState *env = &cpu->env; 5642d30267eSBastian Koppelmann do_raise_exception_err(env, cs->exception_index, 5652d30267eSBastian Koppelmann env->error_code, retaddr); 56648e06fe0SBastian Koppelmann } 5672d30267eSBastian Koppelmann } 568