xref: /qemu/target/tricore/op_helper.c (revision 3a16ecb06355d0bfc8b547eba094ebaa44dce39f)
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