14c9649a9Sj_mayer /* 24c9649a9Sj_mayer * Alpha emulation cpu helpers for qemu. 34c9649a9Sj_mayer * 44c9649a9Sj_mayer * Copyright (c) 2007 Jocelyn Mayer 54c9649a9Sj_mayer * 64c9649a9Sj_mayer * This library is free software; you can redistribute it and/or 74c9649a9Sj_mayer * modify it under the terms of the GNU Lesser General Public 84c9649a9Sj_mayer * License as published by the Free Software Foundation; either 94c9649a9Sj_mayer * version 2 of the License, or (at your option) any later version. 104c9649a9Sj_mayer * 114c9649a9Sj_mayer * This library is distributed in the hope that it will be useful, 124c9649a9Sj_mayer * but WITHOUT ANY WARRANTY; without even the implied warranty of 134c9649a9Sj_mayer * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 144c9649a9Sj_mayer * Lesser General Public License for more details. 154c9649a9Sj_mayer * 164c9649a9Sj_mayer * You should have received a copy of the GNU Lesser General Public 178167ee88SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 184c9649a9Sj_mayer */ 194c9649a9Sj_mayer 204c9649a9Sj_mayer #include <stdint.h> 214c9649a9Sj_mayer #include <stdlib.h> 224c9649a9Sj_mayer #include <stdio.h> 234c9649a9Sj_mayer 244c9649a9Sj_mayer #include "cpu.h" 254c9649a9Sj_mayer #include "exec-all.h" 26ba0e276dSRichard Henderson #include "softfloat.h" 27ba0e276dSRichard Henderson 28ba0e276dSRichard Henderson uint64_t cpu_alpha_load_fpcr (CPUState *env) 29ba0e276dSRichard Henderson { 30ba0e276dSRichard Henderson uint64_t ret = 0; 31ba0e276dSRichard Henderson int flags, mask; 32ba0e276dSRichard Henderson 33ba0e276dSRichard Henderson flags = env->fp_status.float_exception_flags; 34ba0e276dSRichard Henderson ret |= (uint64_t) flags << 52; 35ba0e276dSRichard Henderson if (flags) 36ba0e276dSRichard Henderson ret |= FPCR_SUM; 37ba0e276dSRichard Henderson env->ipr[IPR_EXC_SUM] &= ~0x3E; 38ba0e276dSRichard Henderson env->ipr[IPR_EXC_SUM] |= flags << 1; 39ba0e276dSRichard Henderson 40ba0e276dSRichard Henderson mask = env->fp_status.float_exception_mask; 41ba0e276dSRichard Henderson if (mask & float_flag_invalid) 42ba0e276dSRichard Henderson ret |= FPCR_INVD; 43ba0e276dSRichard Henderson if (mask & float_flag_divbyzero) 44ba0e276dSRichard Henderson ret |= FPCR_DZED; 45ba0e276dSRichard Henderson if (mask & float_flag_overflow) 46ba0e276dSRichard Henderson ret |= FPCR_OVFD; 47ba0e276dSRichard Henderson if (mask & float_flag_underflow) 48ba0e276dSRichard Henderson ret |= FPCR_UNFD; 49ba0e276dSRichard Henderson if (mask & float_flag_inexact) 50ba0e276dSRichard Henderson ret |= FPCR_INED; 51ba0e276dSRichard Henderson 52ba0e276dSRichard Henderson switch (env->fp_status.float_rounding_mode) { 53ba0e276dSRichard Henderson case float_round_nearest_even: 54ba0e276dSRichard Henderson ret |= 2ULL << FPCR_DYN_SHIFT; 55ba0e276dSRichard Henderson break; 56ba0e276dSRichard Henderson case float_round_down: 57ba0e276dSRichard Henderson ret |= 1ULL << FPCR_DYN_SHIFT; 58ba0e276dSRichard Henderson break; 59ba0e276dSRichard Henderson case float_round_up: 60ba0e276dSRichard Henderson ret |= 3ULL << FPCR_DYN_SHIFT; 61ba0e276dSRichard Henderson break; 62ba0e276dSRichard Henderson case float_round_to_zero: 63ba0e276dSRichard Henderson break; 64ba0e276dSRichard Henderson } 65ba0e276dSRichard Henderson return ret; 66ba0e276dSRichard Henderson } 67ba0e276dSRichard Henderson 68ba0e276dSRichard Henderson void cpu_alpha_store_fpcr (CPUState *env, uint64_t val) 69ba0e276dSRichard Henderson { 70ba0e276dSRichard Henderson int round_mode, mask; 71ba0e276dSRichard Henderson 72ba0e276dSRichard Henderson set_float_exception_flags((val >> 52) & 0x3F, &env->fp_status); 73ba0e276dSRichard Henderson 74ba0e276dSRichard Henderson mask = 0; 75ba0e276dSRichard Henderson if (val & FPCR_INVD) 76ba0e276dSRichard Henderson mask |= float_flag_invalid; 77ba0e276dSRichard Henderson if (val & FPCR_DZED) 78ba0e276dSRichard Henderson mask |= float_flag_divbyzero; 79ba0e276dSRichard Henderson if (val & FPCR_OVFD) 80ba0e276dSRichard Henderson mask |= float_flag_overflow; 81ba0e276dSRichard Henderson if (val & FPCR_UNFD) 82ba0e276dSRichard Henderson mask |= float_flag_underflow; 83ba0e276dSRichard Henderson if (val & FPCR_INED) 84ba0e276dSRichard Henderson mask |= float_flag_inexact; 85ba0e276dSRichard Henderson env->fp_status.float_exception_mask = mask; 86ba0e276dSRichard Henderson 87ba0e276dSRichard Henderson switch ((val >> FPCR_DYN_SHIFT) & 3) { 88ba0e276dSRichard Henderson case 0: 89ba0e276dSRichard Henderson round_mode = float_round_to_zero; 90ba0e276dSRichard Henderson break; 91ba0e276dSRichard Henderson case 1: 92ba0e276dSRichard Henderson round_mode = float_round_down; 93ba0e276dSRichard Henderson break; 94ba0e276dSRichard Henderson case 2: 95ba0e276dSRichard Henderson round_mode = float_round_nearest_even; 96ba0e276dSRichard Henderson break; 97ba0e276dSRichard Henderson case 3: 98212df029SStefan Weil default: /* this avoids a gcc (< 4.4) warning */ 99ba0e276dSRichard Henderson round_mode = float_round_up; 100ba0e276dSRichard Henderson break; 101ba0e276dSRichard Henderson } 102ba0e276dSRichard Henderson set_float_rounding_mode(round_mode, &env->fp_status); 103ba0e276dSRichard Henderson } 1044c9649a9Sj_mayer 1054c9649a9Sj_mayer #if defined(CONFIG_USER_ONLY) 1064c9649a9Sj_mayer 1074c9649a9Sj_mayer int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, 1086ebbf390Sj_mayer int mmu_idx, int is_softmmu) 1094c9649a9Sj_mayer { 1104c9649a9Sj_mayer if (rw == 2) 1114c9649a9Sj_mayer env->exception_index = EXCP_ITB_MISS; 1124c9649a9Sj_mayer else 1134c9649a9Sj_mayer env->exception_index = EXCP_DFAULT; 1144c9649a9Sj_mayer env->ipr[IPR_EXC_ADDR] = address; 1154c9649a9Sj_mayer 1164c9649a9Sj_mayer return 1; 1174c9649a9Sj_mayer } 1184c9649a9Sj_mayer 119c227f099SAnthony Liguori target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr) 1204c9649a9Sj_mayer { 1214c9649a9Sj_mayer return addr; 1224c9649a9Sj_mayer } 1234c9649a9Sj_mayer 1244c9649a9Sj_mayer void do_interrupt (CPUState *env) 1254c9649a9Sj_mayer { 1264c9649a9Sj_mayer env->exception_index = -1; 1274c9649a9Sj_mayer } 1284c9649a9Sj_mayer 1294c9649a9Sj_mayer #else 1304c9649a9Sj_mayer 131c227f099SAnthony Liguori target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr) 1324c9649a9Sj_mayer { 1334c9649a9Sj_mayer return -1; 1344c9649a9Sj_mayer } 1354c9649a9Sj_mayer 1364c9649a9Sj_mayer int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw, 1376ebbf390Sj_mayer int mmu_idx, int is_softmmu) 1384c9649a9Sj_mayer { 1394c9649a9Sj_mayer uint32_t opc; 1404c9649a9Sj_mayer 1414c9649a9Sj_mayer if (rw == 2) { 1424c9649a9Sj_mayer /* Instruction translation buffer miss */ 1434c9649a9Sj_mayer env->exception_index = EXCP_ITB_MISS; 1444c9649a9Sj_mayer } else { 1454c9649a9Sj_mayer if (env->ipr[IPR_EXC_ADDR] & 1) 1464c9649a9Sj_mayer env->exception_index = EXCP_DTB_MISS_PAL; 1474c9649a9Sj_mayer else 1484c9649a9Sj_mayer env->exception_index = EXCP_DTB_MISS_NATIVE; 1494c9649a9Sj_mayer opc = (ldl_code(env->pc) >> 21) << 4; 1504c9649a9Sj_mayer if (rw) { 1514c9649a9Sj_mayer opc |= 0x9; 1524c9649a9Sj_mayer } else { 1534c9649a9Sj_mayer opc |= 0x4; 1544c9649a9Sj_mayer } 1554c9649a9Sj_mayer env->ipr[IPR_MM_STAT] = opc; 1564c9649a9Sj_mayer } 1574c9649a9Sj_mayer 1584c9649a9Sj_mayer return 1; 1594c9649a9Sj_mayer } 1604c9649a9Sj_mayer 1614c9649a9Sj_mayer int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp) 1624c9649a9Sj_mayer { 1634c9649a9Sj_mayer uint64_t hwpcb; 1644c9649a9Sj_mayer int ret = 0; 1654c9649a9Sj_mayer 1664c9649a9Sj_mayer hwpcb = env->ipr[IPR_PCBB]; 1674c9649a9Sj_mayer switch (iprn) { 1684c9649a9Sj_mayer case IPR_ASN: 1694c9649a9Sj_mayer if (env->features & FEATURE_ASN) 1704c9649a9Sj_mayer *valp = env->ipr[IPR_ASN]; 1714c9649a9Sj_mayer else 1724c9649a9Sj_mayer *valp = 0; 1734c9649a9Sj_mayer break; 1744c9649a9Sj_mayer case IPR_ASTEN: 1754c9649a9Sj_mayer *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60; 1764c9649a9Sj_mayer break; 1774c9649a9Sj_mayer case IPR_ASTSR: 1784c9649a9Sj_mayer *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60; 1794c9649a9Sj_mayer break; 1804c9649a9Sj_mayer case IPR_DATFX: 1814c9649a9Sj_mayer /* Write only */ 1824c9649a9Sj_mayer ret = -1; 1834c9649a9Sj_mayer break; 1844c9649a9Sj_mayer case IPR_ESP: 1854c9649a9Sj_mayer if (env->features & FEATURE_SPS) 1864c9649a9Sj_mayer *valp = env->ipr[IPR_ESP]; 1874c9649a9Sj_mayer else 1884c9649a9Sj_mayer *valp = ldq_raw(hwpcb + 8); 1894c9649a9Sj_mayer break; 1904c9649a9Sj_mayer case IPR_FEN: 1914c9649a9Sj_mayer *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63; 1924c9649a9Sj_mayer break; 1934c9649a9Sj_mayer case IPR_IPIR: 1944c9649a9Sj_mayer /* Write-only */ 1954c9649a9Sj_mayer ret = -1; 1964c9649a9Sj_mayer break; 1974c9649a9Sj_mayer case IPR_IPL: 1984c9649a9Sj_mayer *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59; 1994c9649a9Sj_mayer break; 2004c9649a9Sj_mayer case IPR_KSP: 2014c9649a9Sj_mayer if (!(env->ipr[IPR_EXC_ADDR] & 1)) { 2024c9649a9Sj_mayer ret = -1; 2034c9649a9Sj_mayer } else { 2044c9649a9Sj_mayer if (env->features & FEATURE_SPS) 2054c9649a9Sj_mayer *valp = env->ipr[IPR_KSP]; 2064c9649a9Sj_mayer else 2074c9649a9Sj_mayer *valp = ldq_raw(hwpcb + 0); 2084c9649a9Sj_mayer } 2094c9649a9Sj_mayer break; 2104c9649a9Sj_mayer case IPR_MCES: 2114c9649a9Sj_mayer *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59; 2124c9649a9Sj_mayer break; 2134c9649a9Sj_mayer case IPR_PERFMON: 2144c9649a9Sj_mayer /* Implementation specific */ 2154c9649a9Sj_mayer *valp = 0; 2164c9649a9Sj_mayer break; 2174c9649a9Sj_mayer case IPR_PCBB: 2184c9649a9Sj_mayer *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16; 2194c9649a9Sj_mayer break; 2204c9649a9Sj_mayer case IPR_PRBR: 2214c9649a9Sj_mayer *valp = env->ipr[IPR_PRBR]; 2224c9649a9Sj_mayer break; 2234c9649a9Sj_mayer case IPR_PTBR: 2244c9649a9Sj_mayer *valp = env->ipr[IPR_PTBR]; 2254c9649a9Sj_mayer break; 2264c9649a9Sj_mayer case IPR_SCBB: 2274c9649a9Sj_mayer *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]); 2284c9649a9Sj_mayer break; 2294c9649a9Sj_mayer case IPR_SIRR: 2304c9649a9Sj_mayer /* Write-only */ 2314c9649a9Sj_mayer ret = -1; 2324c9649a9Sj_mayer break; 2334c9649a9Sj_mayer case IPR_SISR: 2344c9649a9Sj_mayer *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]); 2354c9649a9Sj_mayer case IPR_SSP: 2364c9649a9Sj_mayer if (env->features & FEATURE_SPS) 2374c9649a9Sj_mayer *valp = env->ipr[IPR_SSP]; 2384c9649a9Sj_mayer else 2394c9649a9Sj_mayer *valp = ldq_raw(hwpcb + 16); 2404c9649a9Sj_mayer break; 2414c9649a9Sj_mayer case IPR_SYSPTBR: 2424c9649a9Sj_mayer if (env->features & FEATURE_VIRBND) 2434c9649a9Sj_mayer *valp = env->ipr[IPR_SYSPTBR]; 2444c9649a9Sj_mayer else 2454c9649a9Sj_mayer ret = -1; 2464c9649a9Sj_mayer break; 2474c9649a9Sj_mayer case IPR_TBCHK: 2484c9649a9Sj_mayer if ((env->features & FEATURE_TBCHK)) { 2494c9649a9Sj_mayer /* XXX: TODO */ 2504c9649a9Sj_mayer *valp = 0; 2514c9649a9Sj_mayer ret = -1; 2524c9649a9Sj_mayer } else { 2534c9649a9Sj_mayer ret = -1; 2544c9649a9Sj_mayer } 2554c9649a9Sj_mayer break; 2564c9649a9Sj_mayer case IPR_TBIA: 2574c9649a9Sj_mayer /* Write-only */ 2584c9649a9Sj_mayer ret = -1; 2594c9649a9Sj_mayer break; 2604c9649a9Sj_mayer case IPR_TBIAP: 2614c9649a9Sj_mayer /* Write-only */ 2624c9649a9Sj_mayer ret = -1; 2634c9649a9Sj_mayer break; 2644c9649a9Sj_mayer case IPR_TBIS: 2654c9649a9Sj_mayer /* Write-only */ 2664c9649a9Sj_mayer ret = -1; 2674c9649a9Sj_mayer break; 2684c9649a9Sj_mayer case IPR_TBISD: 2694c9649a9Sj_mayer /* Write-only */ 2704c9649a9Sj_mayer ret = -1; 2714c9649a9Sj_mayer break; 2724c9649a9Sj_mayer case IPR_TBISI: 2734c9649a9Sj_mayer /* Write-only */ 2744c9649a9Sj_mayer ret = -1; 2754c9649a9Sj_mayer break; 2764c9649a9Sj_mayer case IPR_USP: 2774c9649a9Sj_mayer if (env->features & FEATURE_SPS) 2784c9649a9Sj_mayer *valp = env->ipr[IPR_USP]; 2794c9649a9Sj_mayer else 2804c9649a9Sj_mayer *valp = ldq_raw(hwpcb + 24); 2814c9649a9Sj_mayer break; 2824c9649a9Sj_mayer case IPR_VIRBND: 2834c9649a9Sj_mayer if (env->features & FEATURE_VIRBND) 2844c9649a9Sj_mayer *valp = env->ipr[IPR_VIRBND]; 2854c9649a9Sj_mayer else 2864c9649a9Sj_mayer ret = -1; 2874c9649a9Sj_mayer break; 2884c9649a9Sj_mayer case IPR_VPTB: 2894c9649a9Sj_mayer *valp = env->ipr[IPR_VPTB]; 2904c9649a9Sj_mayer break; 2914c9649a9Sj_mayer case IPR_WHAMI: 2924c9649a9Sj_mayer *valp = env->ipr[IPR_WHAMI]; 2934c9649a9Sj_mayer break; 2944c9649a9Sj_mayer default: 2954c9649a9Sj_mayer /* Invalid */ 2964c9649a9Sj_mayer ret = -1; 2974c9649a9Sj_mayer break; 2984c9649a9Sj_mayer } 2994c9649a9Sj_mayer 3004c9649a9Sj_mayer return ret; 3014c9649a9Sj_mayer } 3024c9649a9Sj_mayer 3034c9649a9Sj_mayer int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp) 3044c9649a9Sj_mayer { 3054c9649a9Sj_mayer uint64_t hwpcb, tmp64; 3064c9649a9Sj_mayer uint8_t tmp8; 3074c9649a9Sj_mayer int ret = 0; 3084c9649a9Sj_mayer 3094c9649a9Sj_mayer hwpcb = env->ipr[IPR_PCBB]; 3104c9649a9Sj_mayer switch (iprn) { 3114c9649a9Sj_mayer case IPR_ASN: 3124c9649a9Sj_mayer /* Read-only */ 3134c9649a9Sj_mayer ret = -1; 3144c9649a9Sj_mayer break; 3154c9649a9Sj_mayer case IPR_ASTEN: 3164c9649a9Sj_mayer tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4; 3174c9649a9Sj_mayer *oldvalp = tmp8; 3184c9649a9Sj_mayer tmp8 &= val & 0xF; 3194c9649a9Sj_mayer tmp8 |= (val >> 4) & 0xF; 3204c9649a9Sj_mayer env->ipr[IPR_ASTEN] &= ~0xF; 3214c9649a9Sj_mayer env->ipr[IPR_ASTEN] |= tmp8; 3224c9649a9Sj_mayer ret = 1; 3234c9649a9Sj_mayer break; 3244c9649a9Sj_mayer case IPR_ASTSR: 3254c9649a9Sj_mayer tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4; 3264c9649a9Sj_mayer *oldvalp = tmp8; 3274c9649a9Sj_mayer tmp8 &= val & 0xF; 3284c9649a9Sj_mayer tmp8 |= (val >> 4) & 0xF; 3294c9649a9Sj_mayer env->ipr[IPR_ASTSR] &= ~0xF; 3304c9649a9Sj_mayer env->ipr[IPR_ASTSR] |= tmp8; 3314c9649a9Sj_mayer ret = 1; 3324c9649a9Sj_mayer case IPR_DATFX: 3334c9649a9Sj_mayer env->ipr[IPR_DATFX] &= ~0x1; 3344c9649a9Sj_mayer env->ipr[IPR_DATFX] |= val & 1; 3354c9649a9Sj_mayer tmp64 = ldq_raw(hwpcb + 56); 3364c9649a9Sj_mayer tmp64 &= ~0x8000000000000000ULL; 3374c9649a9Sj_mayer tmp64 |= (val & 1) << 63; 3384c9649a9Sj_mayer stq_raw(hwpcb + 56, tmp64); 3394c9649a9Sj_mayer break; 3404c9649a9Sj_mayer case IPR_ESP: 3414c9649a9Sj_mayer if (env->features & FEATURE_SPS) 3424c9649a9Sj_mayer env->ipr[IPR_ESP] = val; 3434c9649a9Sj_mayer else 3444c9649a9Sj_mayer stq_raw(hwpcb + 8, val); 3454c9649a9Sj_mayer break; 3464c9649a9Sj_mayer case IPR_FEN: 3474c9649a9Sj_mayer env->ipr[IPR_FEN] = val & 1; 3484c9649a9Sj_mayer tmp64 = ldq_raw(hwpcb + 56); 3494c9649a9Sj_mayer tmp64 &= ~1; 3504c9649a9Sj_mayer tmp64 |= val & 1; 3514c9649a9Sj_mayer stq_raw(hwpcb + 56, tmp64); 3524c9649a9Sj_mayer break; 3534c9649a9Sj_mayer case IPR_IPIR: 3544c9649a9Sj_mayer /* XXX: TODO: Send IRQ to CPU #ir[16] */ 3554c9649a9Sj_mayer break; 3564c9649a9Sj_mayer case IPR_IPL: 3574c9649a9Sj_mayer *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59; 3584c9649a9Sj_mayer env->ipr[IPR_IPL] &= ~0x1F; 3594c9649a9Sj_mayer env->ipr[IPR_IPL] |= val & 0x1F; 3604c9649a9Sj_mayer /* XXX: may issue an interrupt or ASR _now_ */ 3614c9649a9Sj_mayer ret = 1; 3624c9649a9Sj_mayer break; 3634c9649a9Sj_mayer case IPR_KSP: 3644c9649a9Sj_mayer if (!(env->ipr[IPR_EXC_ADDR] & 1)) { 3654c9649a9Sj_mayer ret = -1; 3664c9649a9Sj_mayer } else { 3674c9649a9Sj_mayer if (env->features & FEATURE_SPS) 3684c9649a9Sj_mayer env->ipr[IPR_KSP] = val; 3694c9649a9Sj_mayer else 3704c9649a9Sj_mayer stq_raw(hwpcb + 0, val); 3714c9649a9Sj_mayer } 3724c9649a9Sj_mayer break; 3734c9649a9Sj_mayer case IPR_MCES: 3744c9649a9Sj_mayer env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18); 3754c9649a9Sj_mayer env->ipr[IPR_MCES] |= val & 0x18; 3764c9649a9Sj_mayer break; 3774c9649a9Sj_mayer case IPR_PERFMON: 3784c9649a9Sj_mayer /* Implementation specific */ 3794c9649a9Sj_mayer *oldvalp = 0; 3804c9649a9Sj_mayer ret = 1; 3814c9649a9Sj_mayer break; 3824c9649a9Sj_mayer case IPR_PCBB: 3834c9649a9Sj_mayer /* Read-only */ 3844c9649a9Sj_mayer ret = -1; 3854c9649a9Sj_mayer break; 3864c9649a9Sj_mayer case IPR_PRBR: 3874c9649a9Sj_mayer env->ipr[IPR_PRBR] = val; 3884c9649a9Sj_mayer break; 3894c9649a9Sj_mayer case IPR_PTBR: 3904c9649a9Sj_mayer /* Read-only */ 3914c9649a9Sj_mayer ret = -1; 3924c9649a9Sj_mayer break; 3934c9649a9Sj_mayer case IPR_SCBB: 3944c9649a9Sj_mayer env->ipr[IPR_SCBB] = (uint32_t)val; 3954c9649a9Sj_mayer break; 3964c9649a9Sj_mayer case IPR_SIRR: 3974c9649a9Sj_mayer if (val & 0xF) { 3984c9649a9Sj_mayer env->ipr[IPR_SISR] |= 1 << (val & 0xF); 3994c9649a9Sj_mayer /* XXX: request a software interrupt _now_ */ 4004c9649a9Sj_mayer } 4014c9649a9Sj_mayer break; 4024c9649a9Sj_mayer case IPR_SISR: 4034c9649a9Sj_mayer /* Read-only */ 4044c9649a9Sj_mayer ret = -1; 4054c9649a9Sj_mayer break; 4064c9649a9Sj_mayer case IPR_SSP: 4074c9649a9Sj_mayer if (env->features & FEATURE_SPS) 4084c9649a9Sj_mayer env->ipr[IPR_SSP] = val; 4094c9649a9Sj_mayer else 4104c9649a9Sj_mayer stq_raw(hwpcb + 16, val); 4114c9649a9Sj_mayer break; 4124c9649a9Sj_mayer case IPR_SYSPTBR: 4134c9649a9Sj_mayer if (env->features & FEATURE_VIRBND) 4144c9649a9Sj_mayer env->ipr[IPR_SYSPTBR] = val; 4154c9649a9Sj_mayer else 4164c9649a9Sj_mayer ret = -1; 4174c9649a9Sj_mayer case IPR_TBCHK: 4184c9649a9Sj_mayer /* Read-only */ 4194c9649a9Sj_mayer ret = -1; 4204c9649a9Sj_mayer break; 4214c9649a9Sj_mayer case IPR_TBIA: 4224c9649a9Sj_mayer tlb_flush(env, 1); 4234c9649a9Sj_mayer break; 4244c9649a9Sj_mayer case IPR_TBIAP: 4254c9649a9Sj_mayer tlb_flush(env, 1); 4264c9649a9Sj_mayer break; 4274c9649a9Sj_mayer case IPR_TBIS: 4284c9649a9Sj_mayer tlb_flush_page(env, val); 4294c9649a9Sj_mayer break; 4304c9649a9Sj_mayer case IPR_TBISD: 4314c9649a9Sj_mayer tlb_flush_page(env, val); 4324c9649a9Sj_mayer break; 4334c9649a9Sj_mayer case IPR_TBISI: 4344c9649a9Sj_mayer tlb_flush_page(env, val); 4354c9649a9Sj_mayer break; 4364c9649a9Sj_mayer case IPR_USP: 4374c9649a9Sj_mayer if (env->features & FEATURE_SPS) 4384c9649a9Sj_mayer env->ipr[IPR_USP] = val; 4394c9649a9Sj_mayer else 4404c9649a9Sj_mayer stq_raw(hwpcb + 24, val); 4414c9649a9Sj_mayer break; 4424c9649a9Sj_mayer case IPR_VIRBND: 4434c9649a9Sj_mayer if (env->features & FEATURE_VIRBND) 4444c9649a9Sj_mayer env->ipr[IPR_VIRBND] = val; 4454c9649a9Sj_mayer else 4464c9649a9Sj_mayer ret = -1; 4474c9649a9Sj_mayer break; 4484c9649a9Sj_mayer case IPR_VPTB: 4494c9649a9Sj_mayer env->ipr[IPR_VPTB] = val; 4504c9649a9Sj_mayer break; 4514c9649a9Sj_mayer case IPR_WHAMI: 4524c9649a9Sj_mayer /* Read-only */ 4534c9649a9Sj_mayer ret = -1; 4544c9649a9Sj_mayer break; 4554c9649a9Sj_mayer default: 4564c9649a9Sj_mayer /* Invalid */ 4574c9649a9Sj_mayer ret = -1; 4584c9649a9Sj_mayer break; 4594c9649a9Sj_mayer } 4604c9649a9Sj_mayer 4614c9649a9Sj_mayer return ret; 4624c9649a9Sj_mayer } 4634c9649a9Sj_mayer 4644c9649a9Sj_mayer void do_interrupt (CPUState *env) 4654c9649a9Sj_mayer { 4664c9649a9Sj_mayer int excp; 4674c9649a9Sj_mayer 4684c9649a9Sj_mayer env->ipr[IPR_EXC_ADDR] = env->pc | 1; 4694c9649a9Sj_mayer excp = env->exception_index; 470ee0dc6d3SBlue Swirl env->exception_index = -1; 4714c9649a9Sj_mayer env->error_code = 0; 4724c9649a9Sj_mayer /* XXX: disable interrupts and memory mapping */ 4734c9649a9Sj_mayer if (env->ipr[IPR_PAL_BASE] != -1ULL) { 4744c9649a9Sj_mayer /* We use native PALcode */ 4754c9649a9Sj_mayer env->pc = env->ipr[IPR_PAL_BASE] + excp; 4764c9649a9Sj_mayer } else { 4774c9649a9Sj_mayer /* We use emulated PALcode */ 4784c9649a9Sj_mayer call_pal(env); 4794c9649a9Sj_mayer /* Emulate REI */ 4804c9649a9Sj_mayer env->pc = env->ipr[IPR_EXC_ADDR] & ~7; 4814c9649a9Sj_mayer env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1; 4824c9649a9Sj_mayer /* XXX: re-enable interrupts and memory mapping */ 4834c9649a9Sj_mayer } 4844c9649a9Sj_mayer } 4854c9649a9Sj_mayer #endif 4864c9649a9Sj_mayer 4874c9649a9Sj_mayer void cpu_dump_state (CPUState *env, FILE *f, 4884c9649a9Sj_mayer int (*cpu_fprintf)(FILE *f, const char *fmt, ...), 4894c9649a9Sj_mayer int flags) 4904c9649a9Sj_mayer { 491b55266b5Sblueswir1 static const char *linux_reg_names[] = { 4924c9649a9Sj_mayer "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ", 4934c9649a9Sj_mayer "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ", 4944c9649a9Sj_mayer "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ", 4954c9649a9Sj_mayer "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero", 4964c9649a9Sj_mayer }; 4974c9649a9Sj_mayer int i; 4984c9649a9Sj_mayer 4994c9649a9Sj_mayer cpu_fprintf(f, " PC " TARGET_FMT_lx " PS " TARGET_FMT_lx "\n", 5004c9649a9Sj_mayer env->pc, env->ps); 5014c9649a9Sj_mayer for (i = 0; i < 31; i++) { 5024c9649a9Sj_mayer cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i, 5034c9649a9Sj_mayer linux_reg_names[i], env->ir[i]); 5044c9649a9Sj_mayer if ((i % 3) == 2) 5054c9649a9Sj_mayer cpu_fprintf(f, "\n"); 5064c9649a9Sj_mayer } 5074c9649a9Sj_mayer cpu_fprintf(f, "\n"); 5084c9649a9Sj_mayer for (i = 0; i < 31; i++) { 5094c9649a9Sj_mayer cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i, 5104c9649a9Sj_mayer *((uint64_t *)(&env->fir[i]))); 5114c9649a9Sj_mayer if ((i % 3) == 2) 5124c9649a9Sj_mayer cpu_fprintf(f, "\n"); 5134c9649a9Sj_mayer } 51457a92c8eSaurel32 cpu_fprintf(f, "\nlock " TARGET_FMT_lx "\n", env->lock); 5154c9649a9Sj_mayer } 516