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" 256b4c305cSPaolo Bonzini #include "fpu/softfloat.h" 26b9f0923eSRichard Henderson #include "helper.h" 27ba0e276dSRichard Henderson 284d5712f1SAndreas Färber uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env) 29ba0e276dSRichard Henderson { 308443effbSRichard Henderson uint64_t r = 0; 318443effbSRichard Henderson uint8_t t; 32ba0e276dSRichard Henderson 338443effbSRichard Henderson t = env->fpcr_exc_status; 348443effbSRichard Henderson if (t) { 358443effbSRichard Henderson r = FPCR_SUM; 368443effbSRichard Henderson if (t & float_flag_invalid) { 378443effbSRichard Henderson r |= FPCR_INV; 388443effbSRichard Henderson } 398443effbSRichard Henderson if (t & float_flag_divbyzero) { 408443effbSRichard Henderson r |= FPCR_DZE; 418443effbSRichard Henderson } 428443effbSRichard Henderson if (t & float_flag_overflow) { 438443effbSRichard Henderson r |= FPCR_OVF; 448443effbSRichard Henderson } 458443effbSRichard Henderson if (t & float_flag_underflow) { 468443effbSRichard Henderson r |= FPCR_UNF; 478443effbSRichard Henderson } 488443effbSRichard Henderson if (t & float_flag_inexact) { 498443effbSRichard Henderson r |= FPCR_INE; 508443effbSRichard Henderson } 518443effbSRichard Henderson } 52ba0e276dSRichard Henderson 538443effbSRichard Henderson t = env->fpcr_exc_mask; 548443effbSRichard Henderson if (t & float_flag_invalid) { 558443effbSRichard Henderson r |= FPCR_INVD; 568443effbSRichard Henderson } 578443effbSRichard Henderson if (t & float_flag_divbyzero) { 588443effbSRichard Henderson r |= FPCR_DZED; 598443effbSRichard Henderson } 608443effbSRichard Henderson if (t & float_flag_overflow) { 618443effbSRichard Henderson r |= FPCR_OVFD; 628443effbSRichard Henderson } 638443effbSRichard Henderson if (t & float_flag_underflow) { 648443effbSRichard Henderson r |= FPCR_UNFD; 658443effbSRichard Henderson } 668443effbSRichard Henderson if (t & float_flag_inexact) { 678443effbSRichard Henderson r |= FPCR_INED; 688443effbSRichard Henderson } 69ba0e276dSRichard Henderson 708443effbSRichard Henderson switch (env->fpcr_dyn_round) { 71ba0e276dSRichard Henderson case float_round_nearest_even: 728443effbSRichard Henderson r |= FPCR_DYN_NORMAL; 73ba0e276dSRichard Henderson break; 74ba0e276dSRichard Henderson case float_round_down: 758443effbSRichard Henderson r |= FPCR_DYN_MINUS; 76ba0e276dSRichard Henderson break; 77ba0e276dSRichard Henderson case float_round_up: 788443effbSRichard Henderson r |= FPCR_DYN_PLUS; 79ba0e276dSRichard Henderson break; 80ba0e276dSRichard Henderson case float_round_to_zero: 818443effbSRichard Henderson r |= FPCR_DYN_CHOPPED; 82ba0e276dSRichard Henderson break; 83ba0e276dSRichard Henderson } 848443effbSRichard Henderson 8574343409SRichard Henderson if (env->fp_status.flush_inputs_to_zero) { 868443effbSRichard Henderson r |= FPCR_DNZ; 878443effbSRichard Henderson } 888443effbSRichard Henderson if (env->fpcr_dnod) { 898443effbSRichard Henderson r |= FPCR_DNOD; 908443effbSRichard Henderson } 918443effbSRichard Henderson if (env->fpcr_undz) { 928443effbSRichard Henderson r |= FPCR_UNDZ; 938443effbSRichard Henderson } 948443effbSRichard Henderson 958443effbSRichard Henderson return r; 96ba0e276dSRichard Henderson } 97ba0e276dSRichard Henderson 984d5712f1SAndreas Färber void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val) 99ba0e276dSRichard Henderson { 1008443effbSRichard Henderson uint8_t t; 101ba0e276dSRichard Henderson 1028443effbSRichard Henderson t = 0; 1038443effbSRichard Henderson if (val & FPCR_INV) { 1048443effbSRichard Henderson t |= float_flag_invalid; 1058443effbSRichard Henderson } 1068443effbSRichard Henderson if (val & FPCR_DZE) { 1078443effbSRichard Henderson t |= float_flag_divbyzero; 1088443effbSRichard Henderson } 1098443effbSRichard Henderson if (val & FPCR_OVF) { 1108443effbSRichard Henderson t |= float_flag_overflow; 1118443effbSRichard Henderson } 1128443effbSRichard Henderson if (val & FPCR_UNF) { 1138443effbSRichard Henderson t |= float_flag_underflow; 1148443effbSRichard Henderson } 1158443effbSRichard Henderson if (val & FPCR_INE) { 1168443effbSRichard Henderson t |= float_flag_inexact; 1178443effbSRichard Henderson } 1188443effbSRichard Henderson env->fpcr_exc_status = t; 119ba0e276dSRichard Henderson 1208443effbSRichard Henderson t = 0; 1218443effbSRichard Henderson if (val & FPCR_INVD) { 1228443effbSRichard Henderson t |= float_flag_invalid; 1238443effbSRichard Henderson } 1248443effbSRichard Henderson if (val & FPCR_DZED) { 1258443effbSRichard Henderson t |= float_flag_divbyzero; 1268443effbSRichard Henderson } 1278443effbSRichard Henderson if (val & FPCR_OVFD) { 1288443effbSRichard Henderson t |= float_flag_overflow; 1298443effbSRichard Henderson } 1308443effbSRichard Henderson if (val & FPCR_UNFD) { 1318443effbSRichard Henderson t |= float_flag_underflow; 1328443effbSRichard Henderson } 1338443effbSRichard Henderson if (val & FPCR_INED) { 1348443effbSRichard Henderson t |= float_flag_inexact; 1358443effbSRichard Henderson } 1368443effbSRichard Henderson env->fpcr_exc_mask = t; 137ba0e276dSRichard Henderson 1388443effbSRichard Henderson switch (val & FPCR_DYN_MASK) { 1398443effbSRichard Henderson case FPCR_DYN_CHOPPED: 1408443effbSRichard Henderson t = float_round_to_zero; 141ba0e276dSRichard Henderson break; 1428443effbSRichard Henderson case FPCR_DYN_MINUS: 1438443effbSRichard Henderson t = float_round_down; 144ba0e276dSRichard Henderson break; 1458443effbSRichard Henderson case FPCR_DYN_NORMAL: 1468443effbSRichard Henderson t = float_round_nearest_even; 147ba0e276dSRichard Henderson break; 1488443effbSRichard Henderson case FPCR_DYN_PLUS: 1498443effbSRichard Henderson t = float_round_up; 150ba0e276dSRichard Henderson break; 151ba0e276dSRichard Henderson } 1528443effbSRichard Henderson env->fpcr_dyn_round = t; 1538443effbSRichard Henderson 1548443effbSRichard Henderson env->fpcr_dnod = (val & FPCR_DNOD) != 0; 1558443effbSRichard Henderson env->fpcr_undz = (val & FPCR_UNDZ) != 0; 15674343409SRichard Henderson env->fpcr_flush_to_zero = env->fpcr_dnod & env->fpcr_undz; 15774343409SRichard Henderson env->fp_status.flush_inputs_to_zero = (val & FPCR_DNZ) != 0; 158ba0e276dSRichard Henderson } 1594c9649a9Sj_mayer 160a44a2777SRichard Henderson uint64_t helper_load_fpcr(CPUAlphaState *env) 161a44a2777SRichard Henderson { 162a44a2777SRichard Henderson return cpu_alpha_load_fpcr(env); 163a44a2777SRichard Henderson } 164a44a2777SRichard Henderson 165a44a2777SRichard Henderson void helper_store_fpcr(CPUAlphaState *env, uint64_t val) 166a44a2777SRichard Henderson { 167a44a2777SRichard Henderson cpu_alpha_store_fpcr(env, val); 168a44a2777SRichard Henderson } 169a44a2777SRichard Henderson 1704c9649a9Sj_mayer #if defined(CONFIG_USER_ONLY) 171a44a2777SRichard Henderson int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong address, 172a44a2777SRichard Henderson int rw, int mmu_idx) 1734c9649a9Sj_mayer { 17407b6c13bSRichard Henderson env->exception_index = EXCP_MMFAULT; 175129d8aa5SRichard Henderson env->trap_arg0 = address; 1764c9649a9Sj_mayer return 1; 1774c9649a9Sj_mayer } 1784c9649a9Sj_mayer #else 1794d5712f1SAndreas Färber void swap_shadow_regs(CPUAlphaState *env) 18021d2beaaSRichard Henderson { 18121d2beaaSRichard Henderson uint64_t i0, i1, i2, i3, i4, i5, i6, i7; 18221d2beaaSRichard Henderson 18321d2beaaSRichard Henderson i0 = env->ir[8]; 18421d2beaaSRichard Henderson i1 = env->ir[9]; 18521d2beaaSRichard Henderson i2 = env->ir[10]; 18621d2beaaSRichard Henderson i3 = env->ir[11]; 18721d2beaaSRichard Henderson i4 = env->ir[12]; 18821d2beaaSRichard Henderson i5 = env->ir[13]; 18921d2beaaSRichard Henderson i6 = env->ir[14]; 19021d2beaaSRichard Henderson i7 = env->ir[25]; 19121d2beaaSRichard Henderson 19221d2beaaSRichard Henderson env->ir[8] = env->shadow[0]; 19321d2beaaSRichard Henderson env->ir[9] = env->shadow[1]; 19421d2beaaSRichard Henderson env->ir[10] = env->shadow[2]; 19521d2beaaSRichard Henderson env->ir[11] = env->shadow[3]; 19621d2beaaSRichard Henderson env->ir[12] = env->shadow[4]; 19721d2beaaSRichard Henderson env->ir[13] = env->shadow[5]; 19821d2beaaSRichard Henderson env->ir[14] = env->shadow[6]; 19921d2beaaSRichard Henderson env->ir[25] = env->shadow[7]; 20021d2beaaSRichard Henderson 20121d2beaaSRichard Henderson env->shadow[0] = i0; 20221d2beaaSRichard Henderson env->shadow[1] = i1; 20321d2beaaSRichard Henderson env->shadow[2] = i2; 20421d2beaaSRichard Henderson env->shadow[3] = i3; 20521d2beaaSRichard Henderson env->shadow[4] = i4; 20621d2beaaSRichard Henderson env->shadow[5] = i5; 20721d2beaaSRichard Henderson env->shadow[6] = i6; 20821d2beaaSRichard Henderson env->shadow[7] = i7; 20921d2beaaSRichard Henderson } 21021d2beaaSRichard Henderson 211a3b9af16SRichard Henderson /* Returns the OSF/1 entMM failure indication, or -1 on success. */ 2124d5712f1SAndreas Färber static int get_physical_address(CPUAlphaState *env, target_ulong addr, 213a3b9af16SRichard Henderson int prot_need, int mmu_idx, 214a3b9af16SRichard Henderson target_ulong *pphys, int *pprot) 2154c9649a9Sj_mayer { 216a3b9af16SRichard Henderson target_long saddr = addr; 217a3b9af16SRichard Henderson target_ulong phys = 0; 218a3b9af16SRichard Henderson target_ulong L1pte, L2pte, L3pte; 219a3b9af16SRichard Henderson target_ulong pt, index; 220a3b9af16SRichard Henderson int prot = 0; 221a3b9af16SRichard Henderson int ret = MM_K_ACV; 222a3b9af16SRichard Henderson 223a3b9af16SRichard Henderson /* Ensure that the virtual address is properly sign-extended from 224a3b9af16SRichard Henderson the last implemented virtual address bit. */ 225a3b9af16SRichard Henderson if (saddr >> TARGET_VIRT_ADDR_SPACE_BITS != saddr >> 63) { 226a3b9af16SRichard Henderson goto exit; 2274c9649a9Sj_mayer } 2284c9649a9Sj_mayer 229a3b9af16SRichard Henderson /* Translate the superpage. */ 230a3b9af16SRichard Henderson /* ??? When we do more than emulate Unix PALcode, we'll need to 231fa6e0a63SRichard Henderson determine which KSEG is actually active. */ 232fa6e0a63SRichard Henderson if (saddr < 0 && ((saddr >> 41) & 3) == 2) { 233fa6e0a63SRichard Henderson /* User-space cannot access KSEG addresses. */ 234a3b9af16SRichard Henderson if (mmu_idx != MMU_KERNEL_IDX) { 235a3b9af16SRichard Henderson goto exit; 236a3b9af16SRichard Henderson } 237a3b9af16SRichard Henderson 238fa6e0a63SRichard Henderson /* For the benefit of the Typhoon chipset, move bit 40 to bit 43. 239fa6e0a63SRichard Henderson We would not do this if the 48-bit KSEG is enabled. */ 240a3b9af16SRichard Henderson phys = saddr & ((1ull << 40) - 1); 241fa6e0a63SRichard Henderson phys |= (saddr & (1ull << 40)) << 3; 242fa6e0a63SRichard Henderson 243a3b9af16SRichard Henderson prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 244a3b9af16SRichard Henderson ret = -1; 245a3b9af16SRichard Henderson goto exit; 246a3b9af16SRichard Henderson } 247a3b9af16SRichard Henderson 248a3b9af16SRichard Henderson /* Interpret the page table exactly like PALcode does. */ 249a3b9af16SRichard Henderson 250a3b9af16SRichard Henderson pt = env->ptbr; 251a3b9af16SRichard Henderson 252a3b9af16SRichard Henderson /* L1 page table read. */ 253a3b9af16SRichard Henderson index = (addr >> (TARGET_PAGE_BITS + 20)) & 0x3ff; 254a3b9af16SRichard Henderson L1pte = ldq_phys(pt + index*8); 255a3b9af16SRichard Henderson 256a3b9af16SRichard Henderson if (unlikely((L1pte & PTE_VALID) == 0)) { 257a3b9af16SRichard Henderson ret = MM_K_TNV; 258a3b9af16SRichard Henderson goto exit; 259a3b9af16SRichard Henderson } 260a3b9af16SRichard Henderson if (unlikely((L1pte & PTE_KRE) == 0)) { 261a3b9af16SRichard Henderson goto exit; 262a3b9af16SRichard Henderson } 263a3b9af16SRichard Henderson pt = L1pte >> 32 << TARGET_PAGE_BITS; 264a3b9af16SRichard Henderson 265a3b9af16SRichard Henderson /* L2 page table read. */ 266a3b9af16SRichard Henderson index = (addr >> (TARGET_PAGE_BITS + 10)) & 0x3ff; 267a3b9af16SRichard Henderson L2pte = ldq_phys(pt + index*8); 268a3b9af16SRichard Henderson 269a3b9af16SRichard Henderson if (unlikely((L2pte & PTE_VALID) == 0)) { 270a3b9af16SRichard Henderson ret = MM_K_TNV; 271a3b9af16SRichard Henderson goto exit; 272a3b9af16SRichard Henderson } 273a3b9af16SRichard Henderson if (unlikely((L2pte & PTE_KRE) == 0)) { 274a3b9af16SRichard Henderson goto exit; 275a3b9af16SRichard Henderson } 276a3b9af16SRichard Henderson pt = L2pte >> 32 << TARGET_PAGE_BITS; 277a3b9af16SRichard Henderson 278a3b9af16SRichard Henderson /* L3 page table read. */ 279a3b9af16SRichard Henderson index = (addr >> TARGET_PAGE_BITS) & 0x3ff; 280a3b9af16SRichard Henderson L3pte = ldq_phys(pt + index*8); 281a3b9af16SRichard Henderson 282a3b9af16SRichard Henderson phys = L3pte >> 32 << TARGET_PAGE_BITS; 283a3b9af16SRichard Henderson if (unlikely((L3pte & PTE_VALID) == 0)) { 284a3b9af16SRichard Henderson ret = MM_K_TNV; 285a3b9af16SRichard Henderson goto exit; 286a3b9af16SRichard Henderson } 287a3b9af16SRichard Henderson 288a3b9af16SRichard Henderson #if PAGE_READ != 1 || PAGE_WRITE != 2 || PAGE_EXEC != 4 289a3b9af16SRichard Henderson # error page bits out of date 290a3b9af16SRichard Henderson #endif 291a3b9af16SRichard Henderson 292a3b9af16SRichard Henderson /* Check access violations. */ 293a3b9af16SRichard Henderson if (L3pte & (PTE_KRE << mmu_idx)) { 294a3b9af16SRichard Henderson prot |= PAGE_READ | PAGE_EXEC; 295a3b9af16SRichard Henderson } 296a3b9af16SRichard Henderson if (L3pte & (PTE_KWE << mmu_idx)) { 297a3b9af16SRichard Henderson prot |= PAGE_WRITE; 298a3b9af16SRichard Henderson } 299a3b9af16SRichard Henderson if (unlikely((prot & prot_need) == 0 && prot_need)) { 300a3b9af16SRichard Henderson goto exit; 301a3b9af16SRichard Henderson } 302a3b9af16SRichard Henderson 303a3b9af16SRichard Henderson /* Check fault-on-operation violations. */ 304a3b9af16SRichard Henderson prot &= ~(L3pte >> 1); 305a3b9af16SRichard Henderson ret = -1; 306a3b9af16SRichard Henderson if (unlikely((prot & prot_need) == 0)) { 307a3b9af16SRichard Henderson ret = (prot_need & PAGE_EXEC ? MM_K_FOE : 308a3b9af16SRichard Henderson prot_need & PAGE_WRITE ? MM_K_FOW : 309a3b9af16SRichard Henderson prot_need & PAGE_READ ? MM_K_FOR : -1); 310a3b9af16SRichard Henderson } 311a3b9af16SRichard Henderson 312a3b9af16SRichard Henderson exit: 313a3b9af16SRichard Henderson *pphys = phys; 314a3b9af16SRichard Henderson *pprot = prot; 315a3b9af16SRichard Henderson return ret; 316a3b9af16SRichard Henderson } 317a3b9af16SRichard Henderson 318a8170e5eSAvi Kivity hwaddr cpu_get_phys_page_debug(CPUAlphaState *env, target_ulong addr) 319a3b9af16SRichard Henderson { 320a3b9af16SRichard Henderson target_ulong phys; 321a3b9af16SRichard Henderson int prot, fail; 322a3b9af16SRichard Henderson 323a3b9af16SRichard Henderson fail = get_physical_address(env, addr, 0, 0, &phys, &prot); 324a3b9af16SRichard Henderson return (fail >= 0 ? -1 : phys); 325a3b9af16SRichard Henderson } 326a3b9af16SRichard Henderson 3274d5712f1SAndreas Färber int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw, 32897b348e7SBlue Swirl int mmu_idx) 3294c9649a9Sj_mayer { 330a3b9af16SRichard Henderson target_ulong phys; 331a3b9af16SRichard Henderson int prot, fail; 332a3b9af16SRichard Henderson 333a3b9af16SRichard Henderson fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot); 334a3b9af16SRichard Henderson if (unlikely(fail >= 0)) { 335a3b9af16SRichard Henderson env->exception_index = EXCP_MMFAULT; 336a3b9af16SRichard Henderson env->trap_arg0 = addr; 337a3b9af16SRichard Henderson env->trap_arg1 = fail; 338a3b9af16SRichard Henderson env->trap_arg2 = (rw == 2 ? -1 : rw); 339a3b9af16SRichard Henderson return 1; 340a3b9af16SRichard Henderson } 341a3b9af16SRichard Henderson 342a3b9af16SRichard Henderson tlb_set_page(env, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, 343a3b9af16SRichard Henderson prot, mmu_idx, TARGET_PAGE_SIZE); 344129d8aa5SRichard Henderson return 0; 3454c9649a9Sj_mayer } 3463a6fa678SRichard Henderson #endif /* USER_ONLY */ 3474c9649a9Sj_mayer 34897a8ea5aSAndreas Färber void alpha_cpu_do_interrupt(CPUState *cs) 3494c9649a9Sj_mayer { 35097a8ea5aSAndreas Färber AlphaCPU *cpu = ALPHA_CPU(cs); 35197a8ea5aSAndreas Färber CPUAlphaState *env = &cpu->env; 3523a6fa678SRichard Henderson int i = env->exception_index; 3533a6fa678SRichard Henderson 3543a6fa678SRichard Henderson if (qemu_loglevel_mask(CPU_LOG_INT)) { 3553a6fa678SRichard Henderson static int count; 3563a6fa678SRichard Henderson const char *name = "<unknown>"; 3573a6fa678SRichard Henderson 3583a6fa678SRichard Henderson switch (i) { 3593a6fa678SRichard Henderson case EXCP_RESET: 3603a6fa678SRichard Henderson name = "reset"; 3613a6fa678SRichard Henderson break; 3623a6fa678SRichard Henderson case EXCP_MCHK: 3633a6fa678SRichard Henderson name = "mchk"; 3643a6fa678SRichard Henderson break; 3653a6fa678SRichard Henderson case EXCP_SMP_INTERRUPT: 3663a6fa678SRichard Henderson name = "smp_interrupt"; 3673a6fa678SRichard Henderson break; 3683a6fa678SRichard Henderson case EXCP_CLK_INTERRUPT: 3693a6fa678SRichard Henderson name = "clk_interrupt"; 3703a6fa678SRichard Henderson break; 3713a6fa678SRichard Henderson case EXCP_DEV_INTERRUPT: 3723a6fa678SRichard Henderson name = "dev_interrupt"; 3733a6fa678SRichard Henderson break; 3743a6fa678SRichard Henderson case EXCP_MMFAULT: 3753a6fa678SRichard Henderson name = "mmfault"; 3763a6fa678SRichard Henderson break; 3773a6fa678SRichard Henderson case EXCP_UNALIGN: 3783a6fa678SRichard Henderson name = "unalign"; 3793a6fa678SRichard Henderson break; 3803a6fa678SRichard Henderson case EXCP_OPCDEC: 3813a6fa678SRichard Henderson name = "opcdec"; 3823a6fa678SRichard Henderson break; 3833a6fa678SRichard Henderson case EXCP_ARITH: 3843a6fa678SRichard Henderson name = "arith"; 3853a6fa678SRichard Henderson break; 3863a6fa678SRichard Henderson case EXCP_FEN: 3873a6fa678SRichard Henderson name = "fen"; 3883a6fa678SRichard Henderson break; 3893a6fa678SRichard Henderson case EXCP_CALL_PAL: 3903a6fa678SRichard Henderson name = "call_pal"; 3913a6fa678SRichard Henderson break; 3923a6fa678SRichard Henderson case EXCP_STL_C: 3933a6fa678SRichard Henderson name = "stl_c"; 3943a6fa678SRichard Henderson break; 3953a6fa678SRichard Henderson case EXCP_STQ_C: 3963a6fa678SRichard Henderson name = "stq_c"; 3973a6fa678SRichard Henderson break; 3984c9649a9Sj_mayer } 3993a6fa678SRichard Henderson qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64 " sp=%016" PRIx64 "\n", 4003a6fa678SRichard Henderson ++count, name, env->error_code, env->pc, env->ir[IR_SP]); 4013a6fa678SRichard Henderson } 4023a6fa678SRichard Henderson 4033a6fa678SRichard Henderson env->exception_index = -1; 4043a6fa678SRichard Henderson 4053a6fa678SRichard Henderson #if !defined(CONFIG_USER_ONLY) 4063a6fa678SRichard Henderson switch (i) { 4073a6fa678SRichard Henderson case EXCP_RESET: 4083a6fa678SRichard Henderson i = 0x0000; 4093a6fa678SRichard Henderson break; 4103a6fa678SRichard Henderson case EXCP_MCHK: 4113a6fa678SRichard Henderson i = 0x0080; 4123a6fa678SRichard Henderson break; 4133a6fa678SRichard Henderson case EXCP_SMP_INTERRUPT: 4143a6fa678SRichard Henderson i = 0x0100; 4153a6fa678SRichard Henderson break; 4163a6fa678SRichard Henderson case EXCP_CLK_INTERRUPT: 4173a6fa678SRichard Henderson i = 0x0180; 4183a6fa678SRichard Henderson break; 4193a6fa678SRichard Henderson case EXCP_DEV_INTERRUPT: 4203a6fa678SRichard Henderson i = 0x0200; 4213a6fa678SRichard Henderson break; 4223a6fa678SRichard Henderson case EXCP_MMFAULT: 4233a6fa678SRichard Henderson i = 0x0280; 4243a6fa678SRichard Henderson break; 4253a6fa678SRichard Henderson case EXCP_UNALIGN: 4263a6fa678SRichard Henderson i = 0x0300; 4273a6fa678SRichard Henderson break; 4283a6fa678SRichard Henderson case EXCP_OPCDEC: 4293a6fa678SRichard Henderson i = 0x0380; 4303a6fa678SRichard Henderson break; 4313a6fa678SRichard Henderson case EXCP_ARITH: 4323a6fa678SRichard Henderson i = 0x0400; 4333a6fa678SRichard Henderson break; 4343a6fa678SRichard Henderson case EXCP_FEN: 4353a6fa678SRichard Henderson i = 0x0480; 4363a6fa678SRichard Henderson break; 4373a6fa678SRichard Henderson case EXCP_CALL_PAL: 4383a6fa678SRichard Henderson i = env->error_code; 4393a6fa678SRichard Henderson /* There are 64 entry points for both privileged and unprivileged, 4403a6fa678SRichard Henderson with bit 0x80 indicating unprivileged. Each entry point gets 4413a6fa678SRichard Henderson 64 bytes to do its job. */ 4423a6fa678SRichard Henderson if (i & 0x80) { 4433a6fa678SRichard Henderson i = 0x2000 + (i - 0x80) * 64; 4443a6fa678SRichard Henderson } else { 4453a6fa678SRichard Henderson i = 0x1000 + i * 64; 4463a6fa678SRichard Henderson } 4473a6fa678SRichard Henderson break; 4483a6fa678SRichard Henderson default: 4493a6fa678SRichard Henderson cpu_abort(env, "Unhandled CPU exception"); 4503a6fa678SRichard Henderson } 4513a6fa678SRichard Henderson 4523a6fa678SRichard Henderson /* Remember where the exception happened. Emulate real hardware in 4533a6fa678SRichard Henderson that the low bit of the PC indicates PALmode. */ 4543a6fa678SRichard Henderson env->exc_addr = env->pc | env->pal_mode; 4553a6fa678SRichard Henderson 4563a6fa678SRichard Henderson /* Continue execution at the PALcode entry point. */ 4573a6fa678SRichard Henderson env->pc = env->palbr + i; 4583a6fa678SRichard Henderson 4593a6fa678SRichard Henderson /* Switch to PALmode. */ 46021d2beaaSRichard Henderson if (!env->pal_mode) { 4613a6fa678SRichard Henderson env->pal_mode = 1; 46221d2beaaSRichard Henderson swap_shadow_regs(env); 46321d2beaaSRichard Henderson } 4643a6fa678SRichard Henderson #endif /* !USER_ONLY */ 4653a6fa678SRichard Henderson } 4664c9649a9Sj_mayer 467878096eeSAndreas Färber void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, 4684c9649a9Sj_mayer int flags) 4694c9649a9Sj_mayer { 470b55266b5Sblueswir1 static const char *linux_reg_names[] = { 4714c9649a9Sj_mayer "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ", 4724c9649a9Sj_mayer "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ", 4734c9649a9Sj_mayer "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ", 4744c9649a9Sj_mayer "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero", 4754c9649a9Sj_mayer }; 476878096eeSAndreas Färber AlphaCPU *cpu = ALPHA_CPU(cs); 477878096eeSAndreas Färber CPUAlphaState *env = &cpu->env; 4784c9649a9Sj_mayer int i; 4794c9649a9Sj_mayer 480129d8aa5SRichard Henderson cpu_fprintf(f, " PC " TARGET_FMT_lx " PS %02x\n", 4814c9649a9Sj_mayer env->pc, env->ps); 4824c9649a9Sj_mayer for (i = 0; i < 31; i++) { 4834c9649a9Sj_mayer cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i, 4844c9649a9Sj_mayer linux_reg_names[i], env->ir[i]); 4854c9649a9Sj_mayer if ((i % 3) == 2) 4864c9649a9Sj_mayer cpu_fprintf(f, "\n"); 4874c9649a9Sj_mayer } 4886910b8f6SRichard Henderson 4896910b8f6SRichard Henderson cpu_fprintf(f, "lock_a " TARGET_FMT_lx " lock_v " TARGET_FMT_lx "\n", 4906910b8f6SRichard Henderson env->lock_addr, env->lock_value); 4916910b8f6SRichard Henderson 4924c9649a9Sj_mayer for (i = 0; i < 31; i++) { 4934c9649a9Sj_mayer cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i, 4944c9649a9Sj_mayer *((uint64_t *)(&env->fir[i]))); 4954c9649a9Sj_mayer if ((i % 3) == 2) 4964c9649a9Sj_mayer cpu_fprintf(f, "\n"); 4974c9649a9Sj_mayer } 4986910b8f6SRichard Henderson cpu_fprintf(f, "\n"); 4994c9649a9Sj_mayer } 500b9f0923eSRichard Henderson 501b9f0923eSRichard Henderson /* This should only be called from translate, via gen_excp. 502b9f0923eSRichard Henderson We expect that ENV->PC has already been updated. */ 503b9f0923eSRichard Henderson void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error) 504b9f0923eSRichard Henderson { 505b9f0923eSRichard Henderson env->exception_index = excp; 506b9f0923eSRichard Henderson env->error_code = error; 507b9f0923eSRichard Henderson cpu_loop_exit(env); 508b9f0923eSRichard Henderson } 509b9f0923eSRichard Henderson 510b9f0923eSRichard Henderson /* This may be called from any of the helpers to set up EXCEPTION_INDEX. */ 51120503968SBlue Swirl void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, 512b9f0923eSRichard Henderson int excp, int error) 513b9f0923eSRichard Henderson { 514b9f0923eSRichard Henderson env->exception_index = excp; 515b9f0923eSRichard Henderson env->error_code = error; 516a8a826a3SBlue Swirl if (retaddr) { 517a8a826a3SBlue Swirl cpu_restore_state(env, retaddr); 518a8a826a3SBlue Swirl } 519b9f0923eSRichard Henderson cpu_loop_exit(env); 520b9f0923eSRichard Henderson } 521b9f0923eSRichard Henderson 52220503968SBlue Swirl void QEMU_NORETURN arith_excp(CPUAlphaState *env, uintptr_t retaddr, 523b9f0923eSRichard Henderson int exc, uint64_t mask) 524b9f0923eSRichard Henderson { 525b9f0923eSRichard Henderson env->trap_arg0 = exc; 526b9f0923eSRichard Henderson env->trap_arg1 = mask; 527b9f0923eSRichard Henderson dynamic_excp(env, retaddr, EXCP_ARITH, 0); 528b9f0923eSRichard Henderson } 529