qemu/target-alpha/cpu.h
<<
>>
Prefs
   1/*
   2 *  Alpha emulation cpu definitions for qemu.
   3 *
   4 *  Copyright (c) 2007 Jocelyn Mayer
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#if !defined (__CPU_ALPHA_H__)
  21#define __CPU_ALPHA_H__
  22
  23#include "config.h"
  24#include "qemu-common.h"
  25
  26#define TARGET_LONG_BITS 64
  27#define ALIGNED_ONLY
  28
  29#define CPUArchState struct CPUAlphaState
  30
  31#include "exec/cpu-defs.h"
  32
  33#include "fpu/softfloat.h"
  34
  35#define ELF_MACHINE     EM_ALPHA
  36
  37#define ICACHE_LINE_SIZE 32
  38#define DCACHE_LINE_SIZE 32
  39
  40#define TARGET_PAGE_BITS 13
  41
  42#ifdef CONFIG_USER_ONLY
  43/* ??? The kernel likes to give addresses in high memory.  If the host has
  44   more virtual address space than the guest, this can lead to impossible
  45   allocations.  Honor the long-standing assumption that only kernel addrs
  46   are negative, but otherwise allow allocations anywhere.  This could lead
  47   to tricky emulation problems for programs doing tagged addressing, but
  48   that's far fewer than encounter the impossible allocation problem.  */
  49#define TARGET_PHYS_ADDR_SPACE_BITS  63
  50#define TARGET_VIRT_ADDR_SPACE_BITS  63
  51#else
  52/* ??? EV4 has 34 phys addr bits, EV5 has 40, EV6 has 44.  */
  53#define TARGET_PHYS_ADDR_SPACE_BITS  44
  54#define TARGET_VIRT_ADDR_SPACE_BITS  (30 + TARGET_PAGE_BITS)
  55#endif
  56
  57/* Alpha major type */
  58enum {
  59    ALPHA_EV3  = 1,
  60    ALPHA_EV4  = 2,
  61    ALPHA_SIM  = 3,
  62    ALPHA_LCA  = 4,
  63    ALPHA_EV5  = 5, /* 21164 */
  64    ALPHA_EV45 = 6, /* 21064A */
  65    ALPHA_EV56 = 7, /* 21164A */
  66};
  67
  68/* EV4 minor type */
  69enum {
  70    ALPHA_EV4_2 = 0,
  71    ALPHA_EV4_3 = 1,
  72};
  73
  74/* LCA minor type */
  75enum {
  76    ALPHA_LCA_1 = 1, /* 21066 */
  77    ALPHA_LCA_2 = 2, /* 20166 */
  78    ALPHA_LCA_3 = 3, /* 21068 */
  79    ALPHA_LCA_4 = 4, /* 21068 */
  80    ALPHA_LCA_5 = 5, /* 21066A */
  81    ALPHA_LCA_6 = 6, /* 21068A */
  82};
  83
  84/* EV5 minor type */
  85enum {
  86    ALPHA_EV5_1 = 1, /* Rev BA, CA */
  87    ALPHA_EV5_2 = 2, /* Rev DA, EA */
  88    ALPHA_EV5_3 = 3, /* Pass 3 */
  89    ALPHA_EV5_4 = 4, /* Pass 3.2 */
  90    ALPHA_EV5_5 = 5, /* Pass 4 */
  91};
  92
  93/* EV45 minor type */
  94enum {
  95    ALPHA_EV45_1 = 1, /* Pass 1 */
  96    ALPHA_EV45_2 = 2, /* Pass 1.1 */
  97    ALPHA_EV45_3 = 3, /* Pass 2 */
  98};
  99
 100/* EV56 minor type */
 101enum {
 102    ALPHA_EV56_1 = 1, /* Pass 1 */
 103    ALPHA_EV56_2 = 2, /* Pass 2 */
 104};
 105
 106enum {
 107    IMPLVER_2106x = 0, /* EV4, EV45 & LCA45 */
 108    IMPLVER_21164 = 1, /* EV5, EV56 & PCA45 */
 109    IMPLVER_21264 = 2, /* EV6, EV67 & EV68x */
 110    IMPLVER_21364 = 3, /* EV7 & EV79 */
 111};
 112
 113enum {
 114    AMASK_BWX      = 0x00000001,
 115    AMASK_FIX      = 0x00000002,
 116    AMASK_CIX      = 0x00000004,
 117    AMASK_MVI      = 0x00000100,
 118    AMASK_TRAP     = 0x00000200,
 119    AMASK_PREFETCH = 0x00001000,
 120};
 121
 122enum {
 123    VAX_ROUND_NORMAL = 0,
 124    VAX_ROUND_CHOPPED,
 125};
 126
 127enum {
 128    IEEE_ROUND_NORMAL = 0,
 129    IEEE_ROUND_DYNAMIC,
 130    IEEE_ROUND_PLUS,
 131    IEEE_ROUND_MINUS,
 132    IEEE_ROUND_CHOPPED,
 133};
 134
 135/* IEEE floating-point operations encoding */
 136/* Trap mode */
 137enum {
 138    FP_TRAP_I   = 0x0,
 139    FP_TRAP_U   = 0x1,
 140    FP_TRAP_S  = 0x4,
 141    FP_TRAP_SU  = 0x5,
 142    FP_TRAP_SUI = 0x7,
 143};
 144
 145/* Rounding mode */
 146enum {
 147    FP_ROUND_CHOPPED = 0x0,
 148    FP_ROUND_MINUS   = 0x1,
 149    FP_ROUND_NORMAL  = 0x2,
 150    FP_ROUND_DYNAMIC = 0x3,
 151};
 152
 153/* FPCR bits */
 154#define FPCR_SUM                (1ULL << 63)
 155#define FPCR_INED               (1ULL << 62)
 156#define FPCR_UNFD               (1ULL << 61)
 157#define FPCR_UNDZ               (1ULL << 60)
 158#define FPCR_DYN_SHIFT          58
 159#define FPCR_DYN_CHOPPED        (0ULL << FPCR_DYN_SHIFT)
 160#define FPCR_DYN_MINUS          (1ULL << FPCR_DYN_SHIFT)
 161#define FPCR_DYN_NORMAL         (2ULL << FPCR_DYN_SHIFT)
 162#define FPCR_DYN_PLUS           (3ULL << FPCR_DYN_SHIFT)
 163#define FPCR_DYN_MASK           (3ULL << FPCR_DYN_SHIFT)
 164#define FPCR_IOV                (1ULL << 57)
 165#define FPCR_INE                (1ULL << 56)
 166#define FPCR_UNF                (1ULL << 55)
 167#define FPCR_OVF                (1ULL << 54)
 168#define FPCR_DZE                (1ULL << 53)
 169#define FPCR_INV                (1ULL << 52)
 170#define FPCR_OVFD               (1ULL << 51)
 171#define FPCR_DZED               (1ULL << 50)
 172#define FPCR_INVD               (1ULL << 49)
 173#define FPCR_DNZ                (1ULL << 48)
 174#define FPCR_DNOD               (1ULL << 47)
 175#define FPCR_STATUS_MASK        (FPCR_IOV | FPCR_INE | FPCR_UNF \
 176                                 | FPCR_OVF | FPCR_DZE | FPCR_INV)
 177
 178/* The silly software trap enables implemented by the kernel emulation.
 179   These are more or less architecturally required, since the real hardware
 180   has read-as-zero bits in the FPCR when the features aren't implemented.
 181   For the purposes of QEMU, we pretend the FPCR can hold everything.  */
 182#define SWCR_TRAP_ENABLE_INV    (1ULL << 1)
 183#define SWCR_TRAP_ENABLE_DZE    (1ULL << 2)
 184#define SWCR_TRAP_ENABLE_OVF    (1ULL << 3)
 185#define SWCR_TRAP_ENABLE_UNF    (1ULL << 4)
 186#define SWCR_TRAP_ENABLE_INE    (1ULL << 5)
 187#define SWCR_TRAP_ENABLE_DNO    (1ULL << 6)
 188#define SWCR_TRAP_ENABLE_MASK   ((1ULL << 7) - (1ULL << 1))
 189
 190#define SWCR_MAP_DMZ            (1ULL << 12)
 191#define SWCR_MAP_UMZ            (1ULL << 13)
 192#define SWCR_MAP_MASK           (SWCR_MAP_DMZ | SWCR_MAP_UMZ)
 193
 194#define SWCR_STATUS_INV         (1ULL << 17)
 195#define SWCR_STATUS_DZE         (1ULL << 18)
 196#define SWCR_STATUS_OVF         (1ULL << 19)
 197#define SWCR_STATUS_UNF         (1ULL << 20)
 198#define SWCR_STATUS_INE         (1ULL << 21)
 199#define SWCR_STATUS_DNO         (1ULL << 22)
 200#define SWCR_STATUS_MASK        ((1ULL << 23) - (1ULL << 17))
 201
 202#define SWCR_MASK  (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK)
 203
 204/* MMU modes definitions */
 205
 206/* Alpha has 5 MMU modes: PALcode, kernel, executive, supervisor, and user.
 207   The Unix PALcode only exposes the kernel and user modes; presumably
 208   executive and supervisor are used by VMS.
 209
 210   PALcode itself uses physical mode for code and kernel mode for data;
 211   there are PALmode instructions that can access data via physical mode
 212   or via an os-installed "alternate mode", which is one of the 4 above.
 213
 214   QEMU does not currently properly distinguish between code/data when
 215   looking up addresses.  To avoid having to address this issue, our
 216   emulated PALcode will cheat and use the KSEG mapping for its code+data
 217   rather than physical addresses.
 218
 219   Moreover, we're only emulating Unix PALcode, and not attempting VMS.
 220
 221   All of which allows us to drop all but kernel and user modes.
 222   Elide the unused MMU modes to save space.  */
 223
 224#define NB_MMU_MODES 2
 225
 226#define MMU_MODE0_SUFFIX _kernel
 227#define MMU_MODE1_SUFFIX _user
 228#define MMU_KERNEL_IDX   0
 229#define MMU_USER_IDX     1
 230
 231typedef struct CPUAlphaState CPUAlphaState;
 232
 233struct CPUAlphaState {
 234    uint64_t ir[31];
 235    float64 fir[31];
 236    uint64_t pc;
 237    uint64_t unique;
 238    uint64_t lock_addr;
 239    uint64_t lock_st_addr;
 240    uint64_t lock_value;
 241    float_status fp_status;
 242    /* The following fields make up the FPCR, but in FP_STATUS format.  */
 243    uint8_t fpcr_exc_status;
 244    uint8_t fpcr_exc_mask;
 245    uint8_t fpcr_dyn_round;
 246    uint8_t fpcr_flush_to_zero;
 247    uint8_t fpcr_dnod;
 248    uint8_t fpcr_undz;
 249
 250    /* The Internal Processor Registers.  Some of these we assume always
 251       exist for use in user-mode.  */
 252    uint8_t ps;
 253    uint8_t intr_flag;
 254    uint8_t pal_mode;
 255    uint8_t fen;
 256
 257    uint32_t pcc_ofs;
 258
 259    /* These pass data from the exception logic in the translator and
 260       helpers to the OS entry point.  This is used for both system
 261       emulation and user-mode.  */
 262    uint64_t trap_arg0;
 263    uint64_t trap_arg1;
 264    uint64_t trap_arg2;
 265
 266#if !defined(CONFIG_USER_ONLY)
 267    /* The internal data required by our emulation of the Unix PALcode.  */
 268    uint64_t exc_addr;
 269    uint64_t palbr;
 270    uint64_t ptbr;
 271    uint64_t vptptr;
 272    uint64_t sysval;
 273    uint64_t usp;
 274    uint64_t shadow[8];
 275    uint64_t scratch[24];
 276#endif
 277
 278    /* This alarm doesn't exist in real hardware; we wish it did.  */
 279    uint64_t alarm_expire;
 280
 281    /* Those resources are used only in QEMU core */
 282    CPU_COMMON
 283
 284    int error_code;
 285
 286    uint32_t features;
 287    uint32_t amask;
 288    int implver;
 289};
 290
 291#define cpu_list alpha_cpu_list
 292#define cpu_exec cpu_alpha_exec
 293#define cpu_gen_code cpu_alpha_gen_code
 294#define cpu_signal_handler cpu_alpha_signal_handler
 295
 296#include "exec/cpu-all.h"
 297#include "cpu-qom.h"
 298
 299enum {
 300    FEATURE_ASN    = 0x00000001,
 301    FEATURE_SPS    = 0x00000002,
 302    FEATURE_VIRBND = 0x00000004,
 303    FEATURE_TBCHK  = 0x00000008,
 304};
 305
 306enum {
 307    EXCP_RESET,
 308    EXCP_MCHK,
 309    EXCP_SMP_INTERRUPT,
 310    EXCP_CLK_INTERRUPT,
 311    EXCP_DEV_INTERRUPT,
 312    EXCP_MMFAULT,
 313    EXCP_UNALIGN,
 314    EXCP_OPCDEC,
 315    EXCP_ARITH,
 316    EXCP_FEN,
 317    EXCP_CALL_PAL,
 318    /* For Usermode emulation.  */
 319    EXCP_STL_C,
 320    EXCP_STQ_C,
 321};
 322
 323/* Alpha-specific interrupt pending bits.  */
 324#define CPU_INTERRUPT_TIMER     CPU_INTERRUPT_TGT_EXT_0
 325#define CPU_INTERRUPT_SMP       CPU_INTERRUPT_TGT_EXT_1
 326#define CPU_INTERRUPT_MCHK      CPU_INTERRUPT_TGT_EXT_2
 327
 328/* OSF/1 Page table bits.  */
 329enum {
 330    PTE_VALID = 0x0001,
 331    PTE_FOR   = 0x0002,  /* used for page protection (fault on read) */
 332    PTE_FOW   = 0x0004,  /* used for page protection (fault on write) */
 333    PTE_FOE   = 0x0008,  /* used for page protection (fault on exec) */
 334    PTE_ASM   = 0x0010,
 335    PTE_KRE   = 0x0100,
 336    PTE_URE   = 0x0200,
 337    PTE_KWE   = 0x1000,
 338    PTE_UWE   = 0x2000
 339};
 340
 341/* Hardware interrupt (entInt) constants.  */
 342enum {
 343    INT_K_IP,
 344    INT_K_CLK,
 345    INT_K_MCHK,
 346    INT_K_DEV,
 347    INT_K_PERF,
 348};
 349
 350/* Memory management (entMM) constants.  */
 351enum {
 352    MM_K_TNV,
 353    MM_K_ACV,
 354    MM_K_FOR,
 355    MM_K_FOE,
 356    MM_K_FOW
 357};
 358
 359/* Arithmetic exception (entArith) constants.  */
 360enum {
 361    EXC_M_SWC = 1,      /* Software completion */
 362    EXC_M_INV = 2,      /* Invalid operation */
 363    EXC_M_DZE = 4,      /* Division by zero */
 364    EXC_M_FOV = 8,      /* Overflow */
 365    EXC_M_UNF = 16,     /* Underflow */
 366    EXC_M_INE = 32,     /* Inexact result */
 367    EXC_M_IOV = 64      /* Integer Overflow */
 368};
 369
 370/* Processor status constants.  */
 371enum {
 372    /* Low 3 bits are interrupt mask level.  */
 373    PS_INT_MASK = 7,
 374
 375    /* Bits 4 and 5 are the mmu mode.  The VMS PALcode uses all 4 modes;
 376       The Unix PALcode only uses bit 4.  */
 377    PS_USER_MODE = 8
 378};
 379
 380static inline int cpu_mmu_index(CPUAlphaState *env)
 381{
 382    if (env->pal_mode) {
 383        return MMU_KERNEL_IDX;
 384    } else if (env->ps & PS_USER_MODE) {
 385        return MMU_USER_IDX;
 386    } else {
 387        return MMU_KERNEL_IDX;
 388    }
 389}
 390
 391enum {
 392    IR_V0   = 0,
 393    IR_T0   = 1,
 394    IR_T1   = 2,
 395    IR_T2   = 3,
 396    IR_T3   = 4,
 397    IR_T4   = 5,
 398    IR_T5   = 6,
 399    IR_T6   = 7,
 400    IR_T7   = 8,
 401    IR_S0   = 9,
 402    IR_S1   = 10,
 403    IR_S2   = 11,
 404    IR_S3   = 12,
 405    IR_S4   = 13,
 406    IR_S5   = 14,
 407    IR_S6   = 15,
 408    IR_FP   = IR_S6,
 409    IR_A0   = 16,
 410    IR_A1   = 17,
 411    IR_A2   = 18,
 412    IR_A3   = 19,
 413    IR_A4   = 20,
 414    IR_A5   = 21,
 415    IR_T8   = 22,
 416    IR_T9   = 23,
 417    IR_T10  = 24,
 418    IR_T11  = 25,
 419    IR_RA   = 26,
 420    IR_T12  = 27,
 421    IR_PV   = IR_T12,
 422    IR_AT   = 28,
 423    IR_GP   = 29,
 424    IR_SP   = 30,
 425    IR_ZERO = 31,
 426};
 427
 428void alpha_translate_init(void);
 429
 430AlphaCPU *cpu_alpha_init(const char *cpu_model);
 431
 432#define cpu_init(cpu_model) CPU(cpu_alpha_init(cpu_model))
 433
 434void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 435int cpu_alpha_exec(CPUAlphaState *s);
 436/* you can call this signal handler from your SIGBUS and SIGSEGV
 437   signal handlers to inform the virtual CPU of exceptions. non zero
 438   is returned if the signal was handled by the virtual CPU.  */
 439int cpu_alpha_signal_handler(int host_signum, void *pinfo,
 440                             void *puc);
 441int alpha_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 442                               int mmu_idx);
 443void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
 444void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
 445void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
 446
 447uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
 448void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
 449#ifndef CONFIG_USER_ONLY
 450void swap_shadow_regs(CPUAlphaState *env);
 451QEMU_NORETURN void alpha_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
 452                                               bool is_write, bool is_exec,
 453                                               int unused, unsigned size);
 454#endif
 455
 456/* Bits in TB->FLAGS that control how translation is processed.  */
 457enum {
 458    TB_FLAGS_PAL_MODE = 1,
 459    TB_FLAGS_FEN = 2,
 460    TB_FLAGS_USER_MODE = 8,
 461
 462    TB_FLAGS_AMASK_SHIFT = 4,
 463    TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT,
 464    TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT,
 465    TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT,
 466    TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT,
 467    TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT,
 468    TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
 469};
 470
 471static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
 472                                        target_ulong *cs_base, int *pflags)
 473{
 474    int flags = 0;
 475
 476    *pc = env->pc;
 477    *cs_base = 0;
 478
 479    if (env->pal_mode) {
 480        flags = TB_FLAGS_PAL_MODE;
 481    } else {
 482        flags = env->ps & PS_USER_MODE;
 483    }
 484    if (env->fen) {
 485        flags |= TB_FLAGS_FEN;
 486    }
 487    flags |= env->amask << TB_FLAGS_AMASK_SHIFT;
 488
 489    *pflags = flags;
 490}
 491
 492#include "exec/exec-all.h"
 493
 494#endif /* !defined (__CPU_ALPHA_H__) */
 495