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 802692802aSBastian Koppelmann target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1, 812692802aSBastian Koppelmann target_ulong r2) 822692802aSBastian Koppelmann { 832692802aSBastian Koppelmann target_ulong ret; 842692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 852692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 862692802aSBastian Koppelmann int64_t result = t1 + t2; 872692802aSBastian Koppelmann SSOV(env, ret, result, 32); 882692802aSBastian Koppelmann return ret; 892692802aSBastian Koppelmann } 902692802aSBastian Koppelmann 912692802aSBastian Koppelmann target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1, 922692802aSBastian Koppelmann target_ulong r2) 932692802aSBastian Koppelmann { 942692802aSBastian Koppelmann target_ulong ret; 952692802aSBastian Koppelmann int64_t t1 = sextract64(r1, 0, 32); 962692802aSBastian Koppelmann int64_t t2 = sextract64(r2, 0, 32); 972692802aSBastian Koppelmann int64_t result = t1 - t2; 982692802aSBastian Koppelmann SSOV(env, ret, result, 32); 992692802aSBastian Koppelmann return ret; 1002692802aSBastian Koppelmann } 1012692802aSBastian Koppelmann 1029a31922bSBastian Koppelmann /* context save area (CSA) related helpers */ 1039a31922bSBastian Koppelmann 1049a31922bSBastian Koppelmann static int cdc_increment(target_ulong *psw) 1059a31922bSBastian Koppelmann { 1069a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 1079a31922bSBastian Koppelmann return 0; 1089a31922bSBastian Koppelmann } 1099a31922bSBastian Koppelmann 1109a31922bSBastian Koppelmann (*psw)++; 1119a31922bSBastian Koppelmann /* check for overflow */ 1129a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 1139a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 1149a31922bSBastian Koppelmann int count = *psw & mask; 1159a31922bSBastian Koppelmann if (count == 0) { 1169a31922bSBastian Koppelmann (*psw)--; 1179a31922bSBastian Koppelmann return 1; 1189a31922bSBastian Koppelmann } 1199a31922bSBastian Koppelmann return 0; 1209a31922bSBastian Koppelmann } 1219a31922bSBastian Koppelmann 1229a31922bSBastian Koppelmann static int cdc_decrement(target_ulong *psw) 1239a31922bSBastian Koppelmann { 1249a31922bSBastian Koppelmann if ((*psw & MASK_PSW_CDC) == 0x7f) { 1259a31922bSBastian Koppelmann return 0; 1269a31922bSBastian Koppelmann } 1279a31922bSBastian Koppelmann /* check for underflow */ 1289a31922bSBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 1299a31922bSBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 1309a31922bSBastian Koppelmann int count = *psw & mask; 1319a31922bSBastian Koppelmann if (count == 0) { 1329a31922bSBastian Koppelmann return 1; 1339a31922bSBastian Koppelmann } 1349a31922bSBastian Koppelmann (*psw)--; 1359a31922bSBastian Koppelmann return 0; 1369a31922bSBastian Koppelmann } 1379a31922bSBastian Koppelmann 13844ea3430SBastian Koppelmann static bool cdc_zero(target_ulong *psw) 13944ea3430SBastian Koppelmann { 14044ea3430SBastian Koppelmann int cdc = *psw & MASK_PSW_CDC; 14144ea3430SBastian Koppelmann /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC == 14244ea3430SBastian Koppelmann 7'b1111111, otherwise returns FALSE. */ 14344ea3430SBastian Koppelmann if (cdc == 0x7f) { 14444ea3430SBastian Koppelmann return true; 14544ea3430SBastian Koppelmann } 14644ea3430SBastian Koppelmann /* find CDC.COUNT */ 14744ea3430SBastian Koppelmann int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7)); 14844ea3430SBastian Koppelmann int mask = (1u << (7 - lo)) - 1; 14944ea3430SBastian Koppelmann int count = *psw & mask; 15044ea3430SBastian Koppelmann return count == 0; 15144ea3430SBastian Koppelmann } 15244ea3430SBastian Koppelmann 153030c58dfSBastian Koppelmann static void save_context_upper(CPUTriCoreState *env, int ea) 1549a31922bSBastian Koppelmann { 1559a31922bSBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 1569a31922bSBastian Koppelmann cpu_stl_data(env, ea+4, env->PSW); 1579a31922bSBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[10]); 1589a31922bSBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[11]); 1599a31922bSBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[8]); 1609a31922bSBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[9]); 1619a31922bSBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[10]); 1629a31922bSBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[11]); 1639a31922bSBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[12]); 1649a31922bSBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[13]); 1659a31922bSBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[14]); 1669a31922bSBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[15]); 1679a31922bSBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[12]); 1689a31922bSBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[13]); 1699a31922bSBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[14]); 1709a31922bSBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[15]); 1719a31922bSBastian Koppelmann } 1729a31922bSBastian Koppelmann 173030c58dfSBastian Koppelmann static void save_context_lower(CPUTriCoreState *env, int ea) 1745de93515SBastian Koppelmann { 1755de93515SBastian Koppelmann cpu_stl_data(env, ea, env->PCXI); 176030c58dfSBastian Koppelmann cpu_stl_data(env, ea+4, env->gpr_a[11]); 1775de93515SBastian Koppelmann cpu_stl_data(env, ea+8, env->gpr_a[2]); 1785de93515SBastian Koppelmann cpu_stl_data(env, ea+12, env->gpr_a[3]); 1795de93515SBastian Koppelmann cpu_stl_data(env, ea+16, env->gpr_d[0]); 1805de93515SBastian Koppelmann cpu_stl_data(env, ea+20, env->gpr_d[1]); 1815de93515SBastian Koppelmann cpu_stl_data(env, ea+24, env->gpr_d[2]); 1825de93515SBastian Koppelmann cpu_stl_data(env, ea+28, env->gpr_d[3]); 1835de93515SBastian Koppelmann cpu_stl_data(env, ea+32, env->gpr_a[4]); 1845de93515SBastian Koppelmann cpu_stl_data(env, ea+36, env->gpr_a[5]); 1855de93515SBastian Koppelmann cpu_stl_data(env, ea+40, env->gpr_a[6]); 1865de93515SBastian Koppelmann cpu_stl_data(env, ea+44, env->gpr_a[7]); 1875de93515SBastian Koppelmann cpu_stl_data(env, ea+48, env->gpr_d[4]); 1885de93515SBastian Koppelmann cpu_stl_data(env, ea+52, env->gpr_d[5]); 1895de93515SBastian Koppelmann cpu_stl_data(env, ea+56, env->gpr_d[6]); 1905de93515SBastian Koppelmann cpu_stl_data(env, ea+60, env->gpr_d[7]); 1915de93515SBastian Koppelmann } 1925de93515SBastian Koppelmann 1939a31922bSBastian Koppelmann static void restore_context_upper(CPUTriCoreState *env, int ea, 1949a31922bSBastian Koppelmann target_ulong *new_PCXI, target_ulong *new_PSW) 1959a31922bSBastian Koppelmann { 1969a31922bSBastian Koppelmann *new_PCXI = cpu_ldl_data(env, ea); 1979a31922bSBastian Koppelmann *new_PSW = cpu_ldl_data(env, ea+4); 1989a31922bSBastian Koppelmann env->gpr_a[10] = cpu_ldl_data(env, ea+8); 1999a31922bSBastian Koppelmann env->gpr_a[11] = cpu_ldl_data(env, ea+12); 2009a31922bSBastian Koppelmann env->gpr_d[8] = cpu_ldl_data(env, ea+16); 2019a31922bSBastian Koppelmann env->gpr_d[9] = cpu_ldl_data(env, ea+20); 2029a31922bSBastian Koppelmann env->gpr_d[10] = cpu_ldl_data(env, ea+24); 2039a31922bSBastian Koppelmann env->gpr_d[11] = cpu_ldl_data(env, ea+28); 2049a31922bSBastian Koppelmann env->gpr_a[12] = cpu_ldl_data(env, ea+32); 2059a31922bSBastian Koppelmann env->gpr_a[13] = cpu_ldl_data(env, ea+36); 2069a31922bSBastian Koppelmann env->gpr_a[14] = cpu_ldl_data(env, ea+40); 2079a31922bSBastian Koppelmann env->gpr_a[15] = cpu_ldl_data(env, ea+44); 2089a31922bSBastian Koppelmann env->gpr_d[12] = cpu_ldl_data(env, ea+48); 2099a31922bSBastian Koppelmann env->gpr_d[13] = cpu_ldl_data(env, ea+52); 2109a31922bSBastian Koppelmann env->gpr_d[14] = cpu_ldl_data(env, ea+56); 2119a31922bSBastian Koppelmann env->gpr_d[15] = cpu_ldl_data(env, ea+60); 2129a31922bSBastian Koppelmann } 2139a31922bSBastian Koppelmann 21459543d4eSBastian Koppelmann static void restore_context_lower(CPUTriCoreState *env, int ea, 21559543d4eSBastian Koppelmann target_ulong *ra, target_ulong *pcxi) 21659543d4eSBastian Koppelmann { 21759543d4eSBastian Koppelmann *pcxi = cpu_ldl_data(env, ea); 21859543d4eSBastian Koppelmann *ra = cpu_ldl_data(env, ea+4); 21959543d4eSBastian Koppelmann env->gpr_a[2] = cpu_ldl_data(env, ea+8); 22059543d4eSBastian Koppelmann env->gpr_a[3] = cpu_ldl_data(env, ea+12); 22159543d4eSBastian Koppelmann env->gpr_d[0] = cpu_ldl_data(env, ea+16); 22259543d4eSBastian Koppelmann env->gpr_d[1] = cpu_ldl_data(env, ea+20); 22359543d4eSBastian Koppelmann env->gpr_d[2] = cpu_ldl_data(env, ea+24); 22459543d4eSBastian Koppelmann env->gpr_d[3] = cpu_ldl_data(env, ea+28); 22559543d4eSBastian Koppelmann env->gpr_a[4] = cpu_ldl_data(env, ea+32); 22659543d4eSBastian Koppelmann env->gpr_a[5] = cpu_ldl_data(env, ea+36); 22759543d4eSBastian Koppelmann env->gpr_a[6] = cpu_ldl_data(env, ea+40); 22859543d4eSBastian Koppelmann env->gpr_a[7] = cpu_ldl_data(env, ea+44); 22959543d4eSBastian Koppelmann env->gpr_d[4] = cpu_ldl_data(env, ea+48); 23059543d4eSBastian Koppelmann env->gpr_d[5] = cpu_ldl_data(env, ea+52); 23159543d4eSBastian Koppelmann env->gpr_d[6] = cpu_ldl_data(env, ea+56); 23259543d4eSBastian Koppelmann env->gpr_d[7] = cpu_ldl_data(env, ea+60); 23359543d4eSBastian Koppelmann } 23459543d4eSBastian Koppelmann 2359a31922bSBastian Koppelmann void helper_call(CPUTriCoreState *env, uint32_t next_pc) 2369a31922bSBastian Koppelmann { 2379a31922bSBastian Koppelmann target_ulong tmp_FCX; 2389a31922bSBastian Koppelmann target_ulong ea; 2399a31922bSBastian Koppelmann target_ulong new_FCX; 2409a31922bSBastian Koppelmann target_ulong psw; 2419a31922bSBastian Koppelmann 2429a31922bSBastian Koppelmann psw = psw_read(env); 2439a31922bSBastian Koppelmann /* if (FCX == 0) trap(FCU); */ 2449a31922bSBastian Koppelmann if (env->FCX == 0) { 2459a31922bSBastian Koppelmann /* FCU trap */ 2469a31922bSBastian Koppelmann } 2479a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */ 2489a31922bSBastian Koppelmann if (psw & MASK_PSW_CDE) { 2499a31922bSBastian Koppelmann if (cdc_increment(&psw)) { 2509a31922bSBastian Koppelmann /* CDO trap */ 2519a31922bSBastian Koppelmann } 2529a31922bSBastian Koppelmann } 2539a31922bSBastian Koppelmann /* PSW.CDE = 1;*/ 2549a31922bSBastian Koppelmann psw |= MASK_PSW_CDE; 2559a31922bSBastian Koppelmann /* tmp_FCX = FCX; */ 2569a31922bSBastian Koppelmann tmp_FCX = env->FCX; 2579a31922bSBastian Koppelmann /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */ 2589a31922bSBastian Koppelmann ea = ((env->FCX & MASK_FCX_FCXS) << 12) + 2599a31922bSBastian Koppelmann ((env->FCX & MASK_FCX_FCXO) << 6); 260030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 261030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 262030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], 2639a31922bSBastian Koppelmann A[12], A[13], A[14], A[15], D[12], D[13], D[14], 2649a31922bSBastian Koppelmann D[15]}; */ 265030c58dfSBastian Koppelmann save_context_upper(env, ea); 2669a31922bSBastian Koppelmann 2679a31922bSBastian Koppelmann /* PCXI.PCPN = ICR.CCPN; */ 2689a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 2699a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 2709a31922bSBastian Koppelmann /* PCXI.PIE = ICR.IE; */ 2719a31922bSBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 2729a31922bSBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 2739a31922bSBastian Koppelmann /* PCXI.UL = 1; */ 2749a31922bSBastian Koppelmann env->PCXI |= MASK_PCXI_UL; 2759a31922bSBastian Koppelmann 2769a31922bSBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0]; */ 2779a31922bSBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 2789a31922bSBastian Koppelmann /* FCX[19: 0] = new_FCX[19: 0]; */ 2799a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 2809a31922bSBastian Koppelmann /* A[11] = next_pc[31: 0]; */ 2819a31922bSBastian Koppelmann env->gpr_a[11] = next_pc; 2829a31922bSBastian Koppelmann 2839a31922bSBastian Koppelmann /* if (tmp_FCX == LCX) trap(FCD);*/ 2849a31922bSBastian Koppelmann if (tmp_FCX == env->LCX) { 2859a31922bSBastian Koppelmann /* FCD trap */ 2869a31922bSBastian Koppelmann } 2879a31922bSBastian Koppelmann psw_write(env, psw); 2889a31922bSBastian Koppelmann } 2899a31922bSBastian Koppelmann 2909a31922bSBastian Koppelmann void helper_ret(CPUTriCoreState *env) 2919a31922bSBastian Koppelmann { 2929a31922bSBastian Koppelmann target_ulong ea; 2939a31922bSBastian Koppelmann target_ulong new_PCXI; 2949a31922bSBastian Koppelmann target_ulong new_PSW, psw; 2959a31922bSBastian Koppelmann 2969a31922bSBastian Koppelmann psw = psw_read(env); 2979a31922bSBastian Koppelmann /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/ 2989a31922bSBastian Koppelmann if (env->PSW & MASK_PSW_CDE) { 2999a31922bSBastian Koppelmann if (cdc_decrement(&(env->PSW))) { 3009a31922bSBastian Koppelmann /* CDU trap */ 3019a31922bSBastian Koppelmann } 3029a31922bSBastian Koppelmann } 3039a31922bSBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 3049a31922bSBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 3059a31922bSBastian Koppelmann /* CSU trap */ 3069a31922bSBastian Koppelmann } 3079a31922bSBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 3089a31922bSBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 3099a31922bSBastian Koppelmann /* CTYP trap */ 3109a31922bSBastian Koppelmann } 3119a31922bSBastian Koppelmann /* PC = {A11 [31: 1], 1’b0}; */ 3129a31922bSBastian Koppelmann env->PC = env->gpr_a[11] & 0xfffffffe; 3139a31922bSBastian Koppelmann 3149a31922bSBastian Koppelmann /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */ 3159a31922bSBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 3169a31922bSBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 3179a31922bSBastian Koppelmann /* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 318030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 3199a31922bSBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 320030c58dfSBastian Koppelmann /* M(EA, word) = FCX; */ 321030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 3229a31922bSBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 3239a31922bSBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 3249a31922bSBastian Koppelmann /* PCXI = new_PCXI; */ 3259a31922bSBastian Koppelmann env->PCXI = new_PCXI; 3269a31922bSBastian Koppelmann 3279a31922bSBastian Koppelmann if (tricore_feature(env, TRICORE_FEATURE_13)) { 3289a31922bSBastian Koppelmann /* PSW = new_PSW */ 3299a31922bSBastian Koppelmann psw_write(env, new_PSW); 3309a31922bSBastian Koppelmann } else { 3319a31922bSBastian Koppelmann /* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */ 3329a31922bSBastian Koppelmann psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000))); 3339a31922bSBastian Koppelmann } 3349a31922bSBastian Koppelmann } 3359a31922bSBastian Koppelmann 3365de93515SBastian Koppelmann void helper_bisr(CPUTriCoreState *env, uint32_t const9) 3375de93515SBastian Koppelmann { 3385de93515SBastian Koppelmann target_ulong tmp_FCX; 3395de93515SBastian Koppelmann target_ulong ea; 3405de93515SBastian Koppelmann target_ulong new_FCX; 3415de93515SBastian Koppelmann 3425de93515SBastian Koppelmann if (env->FCX == 0) { 3435de93515SBastian Koppelmann /* FCU trap */ 3445de93515SBastian Koppelmann } 3455de93515SBastian Koppelmann 3465de93515SBastian Koppelmann tmp_FCX = env->FCX; 3475de93515SBastian Koppelmann ea = ((env->FCX & 0xf0000) << 12) + ((env->FCX & 0xffff) << 6); 3485de93515SBastian Koppelmann 349030c58dfSBastian Koppelmann /* new_FCX = M(EA, word); */ 350030c58dfSBastian Koppelmann new_FCX = cpu_ldl_data(env, ea); 351030c58dfSBastian Koppelmann /* M(EA, 16 * word) = {PCXI, A[11], A[2], A[3], D[0], D[1], D[2], D[3], A[4] 352030c58dfSBastian Koppelmann , A[5], A[6], A[7], D[4], D[5], D[6], D[7]}; */ 353030c58dfSBastian Koppelmann save_context_lower(env, ea); 354030c58dfSBastian Koppelmann 3555de93515SBastian Koppelmann 3565de93515SBastian Koppelmann /* PCXI.PCPN = ICR.CCPN */ 3575de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xffffff) + 3585de93515SBastian Koppelmann ((env->ICR & MASK_ICR_CCPN) << 24); 3595de93515SBastian Koppelmann /* PCXI.PIE = ICR.IE */ 3605de93515SBastian Koppelmann env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) + 3615de93515SBastian Koppelmann ((env->ICR & MASK_ICR_IE) << 15)); 3625de93515SBastian Koppelmann /* PCXI.UL = 0 */ 3635de93515SBastian Koppelmann env->PCXI &= ~(MASK_PCXI_UL); 3645de93515SBastian Koppelmann /* PCXI[19: 0] = FCX[19: 0] */ 3655de93515SBastian Koppelmann env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff); 3665de93515SBastian Koppelmann /* FXC[19: 0] = new_FCX[19: 0] */ 3675de93515SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff); 3685de93515SBastian Koppelmann /* ICR.IE = 1 */ 3695de93515SBastian Koppelmann env->ICR |= MASK_ICR_IE; 3705de93515SBastian Koppelmann 3715de93515SBastian Koppelmann env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/ 3725de93515SBastian Koppelmann 3735de93515SBastian Koppelmann if (tmp_FCX == env->LCX) { 3745de93515SBastian Koppelmann /* FCD trap */ 3755de93515SBastian Koppelmann } 3765de93515SBastian Koppelmann } 3775de93515SBastian Koppelmann 37844ea3430SBastian Koppelmann void helper_rfe(CPUTriCoreState *env) 37944ea3430SBastian Koppelmann { 38044ea3430SBastian Koppelmann target_ulong ea; 38144ea3430SBastian Koppelmann target_ulong new_PCXI; 38244ea3430SBastian Koppelmann target_ulong new_PSW; 38344ea3430SBastian Koppelmann /* if (PCXI[19: 0] == 0) then trap(CSU); */ 38444ea3430SBastian Koppelmann if ((env->PCXI & 0xfffff) == 0) { 38544ea3430SBastian Koppelmann /* raise csu trap */ 38644ea3430SBastian Koppelmann } 38744ea3430SBastian Koppelmann /* if (PCXI.UL == 0) then trap(CTYP); */ 38844ea3430SBastian Koppelmann if ((env->PCXI & MASK_PCXI_UL) == 0) { 38944ea3430SBastian Koppelmann /* raise CTYP trap */ 39044ea3430SBastian Koppelmann } 39144ea3430SBastian Koppelmann /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */ 39244ea3430SBastian Koppelmann if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { 39344ea3430SBastian Koppelmann /* raise MNG trap */ 39444ea3430SBastian Koppelmann } 39544ea3430SBastian Koppelmann /* ICR.IE = PCXI.PIE; */ 39644ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); 39744ea3430SBastian Koppelmann /* ICR.CCPN = PCXI.PCPN; */ 39844ea3430SBastian Koppelmann env->ICR = (env->ICR & ~MASK_ICR_CCPN) + 39944ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCPN) >> 24); 40044ea3430SBastian Koppelmann /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/ 40144ea3430SBastian Koppelmann ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) + 40244ea3430SBastian Koppelmann ((env->PCXI & MASK_PCXI_PCXO) << 6); 40344ea3430SBastian Koppelmann /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12], 404030c58dfSBastian Koppelmann A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ 40544ea3430SBastian Koppelmann restore_context_upper(env, ea, &new_PCXI, &new_PSW); 406030c58dfSBastian Koppelmann /* M(EA, word) = FCX;*/ 407030c58dfSBastian Koppelmann cpu_stl_data(env, ea, env->FCX); 40844ea3430SBastian Koppelmann /* FCX[19: 0] = PCXI[19: 0]; */ 40944ea3430SBastian Koppelmann env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff); 41044ea3430SBastian Koppelmann /* PCXI = new_PCXI; */ 41144ea3430SBastian Koppelmann env->PCXI = new_PCXI; 41244ea3430SBastian Koppelmann /* write psw */ 41344ea3430SBastian Koppelmann psw_write(env, new_PSW); 41444ea3430SBastian Koppelmann } 41544ea3430SBastian Koppelmann 41659543d4eSBastian Koppelmann void helper_ldlcx(CPUTriCoreState *env, uint32_t ea) 41759543d4eSBastian Koppelmann { 41859543d4eSBastian Koppelmann uint32_t dummy; 41959543d4eSBastian Koppelmann /* insn doesn't load PCXI and RA */ 42059543d4eSBastian Koppelmann restore_context_lower(env, ea, &dummy, &dummy); 42159543d4eSBastian Koppelmann } 42259543d4eSBastian Koppelmann 42359543d4eSBastian Koppelmann void helper_lducx(CPUTriCoreState *env, uint32_t ea) 42459543d4eSBastian Koppelmann { 42559543d4eSBastian Koppelmann uint32_t dummy; 42659543d4eSBastian Koppelmann /* insn doesn't load PCXI and PSW */ 42759543d4eSBastian Koppelmann restore_context_upper(env, ea, &dummy, &dummy); 42859543d4eSBastian Koppelmann } 42959543d4eSBastian Koppelmann 43059543d4eSBastian Koppelmann void helper_stlcx(CPUTriCoreState *env, uint32_t ea) 43159543d4eSBastian Koppelmann { 43259543d4eSBastian Koppelmann save_context_lower(env, ea); 43359543d4eSBastian Koppelmann } 43459543d4eSBastian Koppelmann 43559543d4eSBastian Koppelmann void helper_stucx(CPUTriCoreState *env, uint32_t ea) 43659543d4eSBastian Koppelmann { 43759543d4eSBastian Koppelmann save_context_upper(env, ea); 43859543d4eSBastian Koppelmann } 43959543d4eSBastian Koppelmann 4402d30267eSBastian Koppelmann static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env, 4412d30267eSBastian Koppelmann uint32_t exception, 4422d30267eSBastian Koppelmann int error_code, 4432d30267eSBastian Koppelmann uintptr_t pc) 4442d30267eSBastian Koppelmann { 4452d30267eSBastian Koppelmann CPUState *cs = CPU(tricore_env_get_cpu(env)); 4462d30267eSBastian Koppelmann cs->exception_index = exception; 4472d30267eSBastian Koppelmann env->error_code = error_code; 4482d30267eSBastian Koppelmann 4492d30267eSBastian Koppelmann if (pc) { 4502d30267eSBastian Koppelmann /* now we have a real cpu fault */ 4512d30267eSBastian Koppelmann cpu_restore_state(cs, pc); 4522d30267eSBastian Koppelmann } 4532d30267eSBastian Koppelmann 4542d30267eSBastian Koppelmann cpu_loop_exit(cs); 4552d30267eSBastian Koppelmann } 4562d30267eSBastian Koppelmann 45748e06fe0SBastian Koppelmann void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, 45848e06fe0SBastian Koppelmann uintptr_t retaddr) 45948e06fe0SBastian Koppelmann { 4602d30267eSBastian Koppelmann int ret; 4612d30267eSBastian Koppelmann ret = cpu_tricore_handle_mmu_fault(cs, addr, is_write, mmu_idx); 4622d30267eSBastian Koppelmann if (ret) { 4632d30267eSBastian Koppelmann TriCoreCPU *cpu = TRICORE_CPU(cs); 4642d30267eSBastian Koppelmann CPUTriCoreState *env = &cpu->env; 4652d30267eSBastian Koppelmann do_raise_exception_err(env, cs->exception_index, 4662d30267eSBastian Koppelmann env->error_code, retaddr); 46748e06fe0SBastian Koppelmann } 4682d30267eSBastian Koppelmann } 469