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