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 31800b941e5SAndreas Färber hwaddr alpha_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 319a3b9af16SRichard Henderson { 32000b941e5SAndreas Färber AlphaCPU *cpu = ALPHA_CPU(cs); 321a3b9af16SRichard Henderson target_ulong phys; 322a3b9af16SRichard Henderson int prot, fail; 323a3b9af16SRichard Henderson 32400b941e5SAndreas Färber fail = get_physical_address(&cpu->env, addr, 0, 0, &phys, &prot); 325a3b9af16SRichard Henderson return (fail >= 0 ? -1 : phys); 326a3b9af16SRichard Henderson } 327a3b9af16SRichard Henderson 3284d5712f1SAndreas Färber int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw, 32997b348e7SBlue Swirl int mmu_idx) 3304c9649a9Sj_mayer { 331a3b9af16SRichard Henderson target_ulong phys; 332a3b9af16SRichard Henderson int prot, fail; 333a3b9af16SRichard Henderson 334a3b9af16SRichard Henderson fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot); 335a3b9af16SRichard Henderson if (unlikely(fail >= 0)) { 336a3b9af16SRichard Henderson env->exception_index = EXCP_MMFAULT; 337a3b9af16SRichard Henderson env->trap_arg0 = addr; 338a3b9af16SRichard Henderson env->trap_arg1 = fail; 339a3b9af16SRichard Henderson env->trap_arg2 = (rw == 2 ? -1 : rw); 340a3b9af16SRichard Henderson return 1; 341a3b9af16SRichard Henderson } 342a3b9af16SRichard Henderson 343a3b9af16SRichard Henderson tlb_set_page(env, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, 344a3b9af16SRichard Henderson prot, mmu_idx, TARGET_PAGE_SIZE); 345129d8aa5SRichard Henderson return 0; 3464c9649a9Sj_mayer } 3473a6fa678SRichard Henderson #endif /* USER_ONLY */ 3484c9649a9Sj_mayer 34997a8ea5aSAndreas Färber void alpha_cpu_do_interrupt(CPUState *cs) 3504c9649a9Sj_mayer { 35197a8ea5aSAndreas Färber AlphaCPU *cpu = ALPHA_CPU(cs); 35297a8ea5aSAndreas Färber CPUAlphaState *env = &cpu->env; 3533a6fa678SRichard Henderson int i = env->exception_index; 3543a6fa678SRichard Henderson 3553a6fa678SRichard Henderson if (qemu_loglevel_mask(CPU_LOG_INT)) { 3563a6fa678SRichard Henderson static int count; 3573a6fa678SRichard Henderson const char *name = "<unknown>"; 3583a6fa678SRichard Henderson 3593a6fa678SRichard Henderson switch (i) { 3603a6fa678SRichard Henderson case EXCP_RESET: 3613a6fa678SRichard Henderson name = "reset"; 3623a6fa678SRichard Henderson break; 3633a6fa678SRichard Henderson case EXCP_MCHK: 3643a6fa678SRichard Henderson name = "mchk"; 3653a6fa678SRichard Henderson break; 3663a6fa678SRichard Henderson case EXCP_SMP_INTERRUPT: 3673a6fa678SRichard Henderson name = "smp_interrupt"; 3683a6fa678SRichard Henderson break; 3693a6fa678SRichard Henderson case EXCP_CLK_INTERRUPT: 3703a6fa678SRichard Henderson name = "clk_interrupt"; 3713a6fa678SRichard Henderson break; 3723a6fa678SRichard Henderson case EXCP_DEV_INTERRUPT: 3733a6fa678SRichard Henderson name = "dev_interrupt"; 3743a6fa678SRichard Henderson break; 3753a6fa678SRichard Henderson case EXCP_MMFAULT: 3763a6fa678SRichard Henderson name = "mmfault"; 3773a6fa678SRichard Henderson break; 3783a6fa678SRichard Henderson case EXCP_UNALIGN: 3793a6fa678SRichard Henderson name = "unalign"; 3803a6fa678SRichard Henderson break; 3813a6fa678SRichard Henderson case EXCP_OPCDEC: 3823a6fa678SRichard Henderson name = "opcdec"; 3833a6fa678SRichard Henderson break; 3843a6fa678SRichard Henderson case EXCP_ARITH: 3853a6fa678SRichard Henderson name = "arith"; 3863a6fa678SRichard Henderson break; 3873a6fa678SRichard Henderson case EXCP_FEN: 3883a6fa678SRichard Henderson name = "fen"; 3893a6fa678SRichard Henderson break; 3903a6fa678SRichard Henderson case EXCP_CALL_PAL: 3913a6fa678SRichard Henderson name = "call_pal"; 3923a6fa678SRichard Henderson break; 3933a6fa678SRichard Henderson case EXCP_STL_C: 3943a6fa678SRichard Henderson name = "stl_c"; 3953a6fa678SRichard Henderson break; 3963a6fa678SRichard Henderson case EXCP_STQ_C: 3973a6fa678SRichard Henderson name = "stq_c"; 3983a6fa678SRichard Henderson break; 3994c9649a9Sj_mayer } 4003a6fa678SRichard Henderson qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64 " sp=%016" PRIx64 "\n", 4013a6fa678SRichard Henderson ++count, name, env->error_code, env->pc, env->ir[IR_SP]); 4023a6fa678SRichard Henderson } 4033a6fa678SRichard Henderson 4043a6fa678SRichard Henderson env->exception_index = -1; 4053a6fa678SRichard Henderson 4063a6fa678SRichard Henderson #if !defined(CONFIG_USER_ONLY) 4073a6fa678SRichard Henderson switch (i) { 4083a6fa678SRichard Henderson case EXCP_RESET: 4093a6fa678SRichard Henderson i = 0x0000; 4103a6fa678SRichard Henderson break; 4113a6fa678SRichard Henderson case EXCP_MCHK: 4123a6fa678SRichard Henderson i = 0x0080; 4133a6fa678SRichard Henderson break; 4143a6fa678SRichard Henderson case EXCP_SMP_INTERRUPT: 4153a6fa678SRichard Henderson i = 0x0100; 4163a6fa678SRichard Henderson break; 4173a6fa678SRichard Henderson case EXCP_CLK_INTERRUPT: 4183a6fa678SRichard Henderson i = 0x0180; 4193a6fa678SRichard Henderson break; 4203a6fa678SRichard Henderson case EXCP_DEV_INTERRUPT: 4213a6fa678SRichard Henderson i = 0x0200; 4223a6fa678SRichard Henderson break; 4233a6fa678SRichard Henderson case EXCP_MMFAULT: 4243a6fa678SRichard Henderson i = 0x0280; 4253a6fa678SRichard Henderson break; 4263a6fa678SRichard Henderson case EXCP_UNALIGN: 4273a6fa678SRichard Henderson i = 0x0300; 4283a6fa678SRichard Henderson break; 4293a6fa678SRichard Henderson case EXCP_OPCDEC: 4303a6fa678SRichard Henderson i = 0x0380; 4313a6fa678SRichard Henderson break; 4323a6fa678SRichard Henderson case EXCP_ARITH: 4333a6fa678SRichard Henderson i = 0x0400; 4343a6fa678SRichard Henderson break; 4353a6fa678SRichard Henderson case EXCP_FEN: 4363a6fa678SRichard Henderson i = 0x0480; 4373a6fa678SRichard Henderson break; 4383a6fa678SRichard Henderson case EXCP_CALL_PAL: 4393a6fa678SRichard Henderson i = env->error_code; 4403a6fa678SRichard Henderson /* There are 64 entry points for both privileged and unprivileged, 4413a6fa678SRichard Henderson with bit 0x80 indicating unprivileged. Each entry point gets 4423a6fa678SRichard Henderson 64 bytes to do its job. */ 4433a6fa678SRichard Henderson if (i & 0x80) { 4443a6fa678SRichard Henderson i = 0x2000 + (i - 0x80) * 64; 4453a6fa678SRichard Henderson } else { 4463a6fa678SRichard Henderson i = 0x1000 + i * 64; 4473a6fa678SRichard Henderson } 4483a6fa678SRichard Henderson break; 4493a6fa678SRichard Henderson default: 4503a6fa678SRichard Henderson cpu_abort(env, "Unhandled CPU exception"); 4513a6fa678SRichard Henderson } 4523a6fa678SRichard Henderson 4533a6fa678SRichard Henderson /* Remember where the exception happened. Emulate real hardware in 4543a6fa678SRichard Henderson that the low bit of the PC indicates PALmode. */ 4553a6fa678SRichard Henderson env->exc_addr = env->pc | env->pal_mode; 4563a6fa678SRichard Henderson 4573a6fa678SRichard Henderson /* Continue execution at the PALcode entry point. */ 4583a6fa678SRichard Henderson env->pc = env->palbr + i; 4593a6fa678SRichard Henderson 4603a6fa678SRichard Henderson /* Switch to PALmode. */ 46121d2beaaSRichard Henderson if (!env->pal_mode) { 4623a6fa678SRichard Henderson env->pal_mode = 1; 46321d2beaaSRichard Henderson swap_shadow_regs(env); 46421d2beaaSRichard Henderson } 4653a6fa678SRichard Henderson #endif /* !USER_ONLY */ 4663a6fa678SRichard Henderson } 4674c9649a9Sj_mayer 468878096eeSAndreas Färber void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, 4694c9649a9Sj_mayer int flags) 4704c9649a9Sj_mayer { 471b55266b5Sblueswir1 static const char *linux_reg_names[] = { 4724c9649a9Sj_mayer "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ", 4734c9649a9Sj_mayer "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ", 4744c9649a9Sj_mayer "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ", 4754c9649a9Sj_mayer "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero", 4764c9649a9Sj_mayer }; 477878096eeSAndreas Färber AlphaCPU *cpu = ALPHA_CPU(cs); 478878096eeSAndreas Färber CPUAlphaState *env = &cpu->env; 4794c9649a9Sj_mayer int i; 4804c9649a9Sj_mayer 481129d8aa5SRichard Henderson cpu_fprintf(f, " PC " TARGET_FMT_lx " PS %02x\n", 4824c9649a9Sj_mayer env->pc, env->ps); 4834c9649a9Sj_mayer for (i = 0; i < 31; i++) { 4844c9649a9Sj_mayer cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i, 4854c9649a9Sj_mayer linux_reg_names[i], env->ir[i]); 4864c9649a9Sj_mayer if ((i % 3) == 2) 4874c9649a9Sj_mayer cpu_fprintf(f, "\n"); 4884c9649a9Sj_mayer } 4896910b8f6SRichard Henderson 4906910b8f6SRichard Henderson cpu_fprintf(f, "lock_a " TARGET_FMT_lx " lock_v " TARGET_FMT_lx "\n", 4916910b8f6SRichard Henderson env->lock_addr, env->lock_value); 4926910b8f6SRichard Henderson 4934c9649a9Sj_mayer for (i = 0; i < 31; i++) { 4944c9649a9Sj_mayer cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i, 4954c9649a9Sj_mayer *((uint64_t *)(&env->fir[i]))); 4964c9649a9Sj_mayer if ((i % 3) == 2) 4974c9649a9Sj_mayer cpu_fprintf(f, "\n"); 4984c9649a9Sj_mayer } 4996910b8f6SRichard Henderson cpu_fprintf(f, "\n"); 5004c9649a9Sj_mayer } 501b9f0923eSRichard Henderson 502b9f0923eSRichard Henderson /* This should only be called from translate, via gen_excp. 503b9f0923eSRichard Henderson We expect that ENV->PC has already been updated. */ 504b9f0923eSRichard Henderson void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error) 505b9f0923eSRichard Henderson { 506b9f0923eSRichard Henderson env->exception_index = excp; 507b9f0923eSRichard Henderson env->error_code = error; 508b9f0923eSRichard Henderson cpu_loop_exit(env); 509b9f0923eSRichard Henderson } 510b9f0923eSRichard Henderson 511b9f0923eSRichard Henderson /* This may be called from any of the helpers to set up EXCEPTION_INDEX. */ 51220503968SBlue Swirl void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr, 513b9f0923eSRichard Henderson int excp, int error) 514b9f0923eSRichard Henderson { 515b9f0923eSRichard Henderson env->exception_index = excp; 516b9f0923eSRichard Henderson env->error_code = error; 517a8a826a3SBlue Swirl if (retaddr) { 518a8a826a3SBlue Swirl cpu_restore_state(env, retaddr); 519a8a826a3SBlue Swirl } 520b9f0923eSRichard Henderson cpu_loop_exit(env); 521b9f0923eSRichard Henderson } 522b9f0923eSRichard Henderson 52320503968SBlue Swirl void QEMU_NORETURN arith_excp(CPUAlphaState *env, uintptr_t retaddr, 524b9f0923eSRichard Henderson int exc, uint64_t mask) 525b9f0923eSRichard Henderson { 526b9f0923eSRichard Henderson env->trap_arg0 = exc; 527b9f0923eSRichard Henderson env->trap_arg1 = mask; 528b9f0923eSRichard Henderson dynamic_excp(env, retaddr, EXCP_ARITH, 0); 529b9f0923eSRichard Henderson } 530