diff options
Diffstat (limited to 'target-alpha/cpu.h')
-rw-r--r-- | target-alpha/cpu.h | 375 |
1 files changed, 166 insertions, 209 deletions
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 686fb4a6a7..e98b32513c 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -192,171 +192,39 @@ enum { #define SWCR_MASK (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK) -/* Internal processor registers */ -/* XXX: TOFIX: most of those registers are implementation dependant */ -enum { -#if defined(CONFIG_USER_ONLY) - IPR_EXC_ADDR, - IPR_EXC_SUM, - IPR_EXC_MASK, -#else - /* Ebox IPRs */ - IPR_CC = 0xC0, /* 21264 */ - IPR_CC_CTL = 0xC1, /* 21264 */ -#define IPR_CC_CTL_ENA_SHIFT 32 -#define IPR_CC_CTL_COUNTER_MASK 0xfffffff0UL - IPR_VA = 0xC2, /* 21264 */ - IPR_VA_CTL = 0xC4, /* 21264 */ -#define IPR_VA_CTL_VA_48_SHIFT 1 -#define IPR_VA_CTL_VPTB_SHIFT 30 - IPR_VA_FORM = 0xC3, /* 21264 */ - /* Ibox IPRs */ - IPR_ITB_TAG = 0x00, /* 21264 */ - IPR_ITB_PTE = 0x01, /* 21264 */ - IPR_ITB_IAP = 0x02, - IPR_ITB_IA = 0x03, /* 21264 */ - IPR_ITB_IS = 0x04, /* 21264 */ - IPR_PMPC = 0x05, - IPR_EXC_ADDR = 0x06, /* 21264 */ - IPR_IVA_FORM = 0x07, /* 21264 */ - IPR_CM = 0x09, /* 21264 */ -#define IPR_CM_SHIFT 3 -#define IPR_CM_MASK (3ULL << IPR_CM_SHIFT) /* 21264 */ - IPR_IER = 0x0A, /* 21264 */ -#define IPR_IER_MASK 0x0000007fffffe000ULL - IPR_IER_CM = 0x0B, /* 21264: = CM | IER */ - IPR_SIRR = 0x0C, /* 21264 */ -#define IPR_SIRR_SHIFT 14 -#define IPR_SIRR_MASK 0x7fff - IPR_ISUM = 0x0D, /* 21264 */ - IPR_HW_INT_CLR = 0x0E, /* 21264 */ - IPR_EXC_SUM = 0x0F, - IPR_PAL_BASE = 0x10, - IPR_I_CTL = 0x11, -#define IPR_I_CTL_CHIP_ID_SHIFT 24 /* 21264 */ -#define IPR_I_CTL_BIST_FAIL (1 << 23) /* 21264 */ -#define IPR_I_CTL_IC_EN_SHIFT 2 /* 21264 */ -#define IPR_I_CTL_SDE1_SHIFT 7 /* 21264 */ -#define IPR_I_CTL_HWE_SHIFT 12 /* 21264 */ -#define IPR_I_CTL_VA_48_SHIFT 15 /* 21264 */ -#define IPR_I_CTL_SPE_SHIFT 3 /* 21264 */ -#define IPR_I_CTL_CALL_PAL_R23_SHIFT 20 /* 21264 */ - IPR_I_STAT = 0x16, /* 21264 */ - IPR_IC_FLUSH = 0x13, /* 21264 */ - IPR_IC_FLUSH_ASM = 0x12, /* 21264 */ - IPR_CLR_MAP = 0x15, - IPR_SLEEP = 0x17, - IPR_PCTX = 0x40, - IPR_PCTX_ASN = 0x01, /* field */ -#define IPR_PCTX_ASN_SHIFT 39 - IPR_PCTX_ASTER = 0x02, /* field */ -#define IPR_PCTX_ASTER_SHIFT 5 - IPR_PCTX_ASTRR = 0x04, /* field */ -#define IPR_PCTX_ASTRR_SHIFT 9 - IPR_PCTX_PPCE = 0x08, /* field */ -#define IPR_PCTX_PPCE_SHIFT 1 - IPR_PCTX_FPE = 0x10, /* field */ -#define IPR_PCTX_FPE_SHIFT 2 - IPR_PCTX_ALL = 0x5f, /* all fields */ - IPR_PCTR_CTL = 0x14, /* 21264 */ - /* Mbox IPRs */ - IPR_DTB_TAG0 = 0x20, /* 21264 */ - IPR_DTB_TAG1 = 0xA0, /* 21264 */ - IPR_DTB_PTE0 = 0x21, /* 21264 */ - IPR_DTB_PTE1 = 0xA1, /* 21264 */ - IPR_DTB_ALTMODE = 0xA6, - IPR_DTB_ALTMODE0 = 0x26, /* 21264 */ -#define IPR_DTB_ALTMODE_MASK 3 - IPR_DTB_IAP = 0xA2, - IPR_DTB_IA = 0xA3, /* 21264 */ - IPR_DTB_IS0 = 0x24, - IPR_DTB_IS1 = 0xA4, - IPR_DTB_ASN0 = 0x25, /* 21264 */ - IPR_DTB_ASN1 = 0xA5, /* 21264 */ -#define IPR_DTB_ASN_SHIFT 56 - IPR_MM_STAT = 0x27, /* 21264 */ - IPR_M_CTL = 0x28, /* 21264 */ -#define IPR_M_CTL_SPE_SHIFT 1 -#define IPR_M_CTL_SPE_MASK 7 - IPR_DC_CTL = 0x29, /* 21264 */ - IPR_DC_STAT = 0x2A, /* 21264 */ - /* Cbox IPRs */ - IPR_C_DATA = 0x2B, - IPR_C_SHIFT = 0x2C, - - IPR_ASN, - IPR_ASTEN, - IPR_ASTSR, - IPR_DATFX, - IPR_ESP, - IPR_FEN, - IPR_IPIR, - IPR_IPL, - IPR_KSP, - IPR_MCES, - IPR_PERFMON, - IPR_PCBB, - IPR_PRBR, - IPR_PTBR, - IPR_SCBB, - IPR_SISR, - IPR_SSP, - IPR_SYSPTBR, - IPR_TBCHK, - IPR_TBIA, - IPR_TBIAP, - IPR_TBIS, - IPR_TBISD, - IPR_TBISI, - IPR_USP, - IPR_VIRBND, - IPR_VPTB, - IPR_WHAMI, - IPR_ALT_MODE, -#endif - IPR_LAST, -}; +/* MMU modes definitions */ -typedef struct CPUAlphaState CPUAlphaState; +/* Alpha has 5 MMU modes: PALcode, kernel, executive, supervisor, and user. + The Unix PALcode only exposes the kernel and user modes; presumably + executive and supervisor are used by VMS. -typedef struct pal_handler_t pal_handler_t; -struct pal_handler_t { - /* Reset */ - void (*reset)(CPUAlphaState *env); - /* Uncorrectable hardware error */ - void (*machine_check)(CPUAlphaState *env); - /* Arithmetic exception */ - void (*arithmetic)(CPUAlphaState *env); - /* Interrupt / correctable hardware error */ - void (*interrupt)(CPUAlphaState *env); - /* Data fault */ - void (*dfault)(CPUAlphaState *env); - /* DTB miss pal */ - void (*dtb_miss_pal)(CPUAlphaState *env); - /* DTB miss native */ - void (*dtb_miss_native)(CPUAlphaState *env); - /* Unaligned access */ - void (*unalign)(CPUAlphaState *env); - /* ITB miss */ - void (*itb_miss)(CPUAlphaState *env); - /* Instruction stream access violation */ - void (*itb_acv)(CPUAlphaState *env); - /* Reserved or privileged opcode */ - void (*opcdec)(CPUAlphaState *env); - /* Floating point exception */ - void (*fen)(CPUAlphaState *env); - /* Call pal instruction */ - void (*call_pal)(CPUAlphaState *env, uint32_t palcode); -}; + PALcode itself uses physical mode for code and kernel mode for data; + there are PALmode instructions that can access data via physical mode + or via an os-installed "alternate mode", which is one of the 4 above. -#define NB_MMU_MODES 4 + QEMU does not currently properly distinguish between code/data when + looking up addresses. To avoid having to address this issue, our + emulated PALcode will cheat and use the KSEG mapping for its code+data + rather than physical addresses. + + Moreover, we're only emulating Unix PALcode, and not attempting VMS. + + All of which allows us to drop all but kernel and user modes. + Elide the unused MMU modes to save space. */ + +#define NB_MMU_MODES 2 + +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _user +#define MMU_KERNEL_IDX 0 +#define MMU_USER_IDX 1 + +typedef struct CPUAlphaState CPUAlphaState; struct CPUAlphaState { uint64_t ir[31]; float64 fir[31]; uint64_t pc; - uint64_t ipr[IPR_LAST]; - uint64_t ps; uint64_t unique; uint64_t lock_addr; uint64_t lock_st_addr; @@ -371,10 +239,33 @@ struct CPUAlphaState { uint8_t fpcr_dnod; uint8_t fpcr_undz; - /* Used for HW_LD / HW_ST */ - uint8_t saved_mode; - /* For RC and RS */ + /* The Internal Processor Registers. Some of these we assume always + exist for use in user-mode. */ + uint8_t ps; uint8_t intr_flag; + uint8_t pal_mode; + uint8_t fen; + + uint32_t pcc_ofs; + + /* These pass data from the exception logic in the translator and + helpers to the OS entry point. This is used for both system + emulation and user-mode. */ + uint64_t trap_arg0; + uint64_t trap_arg1; + uint64_t trap_arg2; + +#if !defined(CONFIG_USER_ONLY) + /* The internal data required by our emulation of the Unix PALcode. */ + uint64_t exc_addr; + uint64_t palbr; + uint64_t ptbr; + uint64_t vptptr; + uint64_t sysval; + uint64_t usp; + uint64_t shadow[8]; + uint64_t scratch[24]; +#endif #if TARGET_LONG_BITS > HOST_LONG_BITS /* temporary fixed-point registers @@ -386,14 +277,11 @@ struct CPUAlphaState { /* Those resources are used only in Qemu core */ CPU_COMMON - uint32_t hflags; - int error_code; uint32_t features; uint32_t amask; int implver; - pal_handler_t *pal_handler; }; #define cpu_init cpu_alpha_init @@ -401,17 +289,6 @@ struct CPUAlphaState { #define cpu_gen_code cpu_alpha_gen_code #define cpu_signal_handler cpu_alpha_signal_handler -/* MMU modes definitions */ -#define MMU_MODE0_SUFFIX _kernel -#define MMU_MODE1_SUFFIX _executive -#define MMU_MODE2_SUFFIX _supervisor -#define MMU_MODE3_SUFFIX _user -#define MMU_USER_IDX 3 -static inline int cpu_mmu_index (CPUState *env) -{ - return (env->ps >> 3) & 3; -} - #include "cpu-all.h" enum { @@ -422,36 +299,89 @@ enum { }; enum { - EXCP_RESET = 0x0000, - EXCP_MCHK = 0x0020, - EXCP_ARITH = 0x0060, - EXCP_HW_INTERRUPT = 0x00E0, - EXCP_DFAULT = 0x01E0, - EXCP_DTB_MISS_PAL = 0x09E0, - EXCP_ITB_MISS = 0x03E0, - EXCP_ITB_ACV = 0x07E0, - EXCP_DTB_MISS_NATIVE = 0x08E0, - EXCP_UNALIGN = 0x11E0, - EXCP_OPCDEC = 0x13E0, - EXCP_FEN = 0x17E0, - EXCP_CALL_PAL = 0x2000, - EXCP_CALL_PALP = 0x3000, - EXCP_CALL_PALE = 0x4000, - /* Pseudo exception for console */ - EXCP_CONSOLE_DISPATCH = 0x4001, - EXCP_CONSOLE_FIXUP = 0x4002, - EXCP_STL_C = 0x4003, - EXCP_STQ_C = 0x4004, + EXCP_RESET, + EXCP_MCHK, + EXCP_SMP_INTERRUPT, + EXCP_CLK_INTERRUPT, + EXCP_DEV_INTERRUPT, + EXCP_MMFAULT, + EXCP_UNALIGN, + EXCP_OPCDEC, + EXCP_ARITH, + EXCP_FEN, + EXCP_CALL_PAL, + /* For Usermode emulation. */ + EXCP_STL_C, + EXCP_STQ_C, }; -/* Arithmetic exception */ -#define EXC_M_IOV (1<<16) /* Integer Overflow */ -#define EXC_M_INE (1<<15) /* Inexact result */ -#define EXC_M_UNF (1<<14) /* Underflow */ -#define EXC_M_FOV (1<<13) /* Overflow */ -#define EXC_M_DZE (1<<12) /* Division by zero */ -#define EXC_M_INV (1<<11) /* Invalid operation */ -#define EXC_M_SWC (1<<10) /* Software completion */ +/* Alpha-specific interrupt pending bits. */ +#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0 +#define CPU_INTERRUPT_SMP CPU_INTERRUPT_TGT_EXT_1 +#define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2 + +/* OSF/1 Page table bits. */ +enum { + PTE_VALID = 0x0001, + PTE_FOR = 0x0002, /* used for page protection (fault on read) */ + PTE_FOW = 0x0004, /* used for page protection (fault on write) */ + PTE_FOE = 0x0008, /* used for page protection (fault on exec) */ + PTE_ASM = 0x0010, + PTE_KRE = 0x0100, + PTE_URE = 0x0200, + PTE_KWE = 0x1000, + PTE_UWE = 0x2000 +}; + +/* Hardware interrupt (entInt) constants. */ +enum { + INT_K_IP, + INT_K_CLK, + INT_K_MCHK, + INT_K_DEV, + INT_K_PERF, +}; + +/* Memory management (entMM) constants. */ +enum { + MM_K_TNV, + MM_K_ACV, + MM_K_FOR, + MM_K_FOE, + MM_K_FOW +}; + +/* Arithmetic exception (entArith) constants. */ +enum { + EXC_M_SWC = 1, /* Software completion */ + EXC_M_INV = 2, /* Invalid operation */ + EXC_M_DZE = 4, /* Division by zero */ + EXC_M_FOV = 8, /* Overflow */ + EXC_M_UNF = 16, /* Underflow */ + EXC_M_INE = 32, /* Inexact result */ + EXC_M_IOV = 64 /* Integer Overflow */ +}; + +/* Processor status constants. */ +enum { + /* Low 3 bits are interrupt mask level. */ + PS_INT_MASK = 7, + + /* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes; + The Unix PALcode only uses bit 4. */ + PS_USER_MODE = 8 +}; + +static inline int cpu_mmu_index(CPUState *env) +{ + if (env->pal_mode) { + return MMU_KERNEL_IDX; + } else if (env->ps & PS_USER_MODE) { + return MMU_USER_IDX; + } else { + return MMU_KERNEL_IDX; + } +} enum { IR_V0 = 0, @@ -504,19 +434,46 @@ void do_interrupt (CPUState *env); uint64_t cpu_alpha_load_fpcr (CPUState *env); void cpu_alpha_store_fpcr (CPUState *env, uint64_t val); -int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp); -int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); -#if !defined (CONFIG_USER_ONLY) -void pal_init (CPUState *env); -void call_pal (CPUState *env); +#ifndef CONFIG_USER_ONLY +void swap_shadow_regs(CPUState *env); +extern QEMU_NORETURN void do_unassigned_access(target_phys_addr_t addr, + int, int, int, int); #endif +/* Bits in TB->FLAGS that control how translation is processed. */ +enum { + TB_FLAGS_PAL_MODE = 1, + TB_FLAGS_FEN = 2, + TB_FLAGS_USER_MODE = 8, + + TB_FLAGS_AMASK_SHIFT = 4, + TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT, + TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT, + TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT, + TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT, + TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT, + TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT, +}; + static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, - target_ulong *cs_base, int *flags) + target_ulong *cs_base, int *pflags) { + int flags = 0; + *pc = env->pc; *cs_base = 0; - *flags = env->ps; + + if (env->pal_mode) { + flags = TB_FLAGS_PAL_MODE; + } else { + flags = env->ps & PS_USER_MODE; + } + if (env->fen) { + flags |= TB_FLAGS_FEN; + } + flags |= env->amask << TB_FLAGS_AMASK_SHIFT; + + *pflags = flags; } #if defined(CONFIG_USER_ONLY) |