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