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