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   QEMU does not currently properly distinguish between code/data when
 213   looking up addresses.  To avoid having to address this issue, our
 214   emulated PALcode will cheat and use the KSEG mapping for its code+data
 215   rather than physical addresses.
 216
 217   Moreover, we're only emulating Unix PALcode, and not attempting VMS.
 218
 219   All of which allows us to drop all but kernel and user modes.
 220   Elide the unused MMU modes to save space.  */
 221
 222#define NB_MMU_MODES 2
 223
 224#define MMU_MODE0_SUFFIX _kernel
 225#define MMU_MODE1_SUFFIX _user
 226#define MMU_KERNEL_IDX   0
 227#define MMU_USER_IDX     1
 228
 229typedef struct CPUAlphaState CPUAlphaState;
 230
 231struct CPUAlphaState {
 232    uint64_t ir[31];
 233    float64 fir[31];
 234    uint64_t pc;
 235    uint64_t unique;
 236    uint64_t lock_addr;
 237    uint64_t lock_st_addr;
 238    uint64_t lock_value;
 239
 240    /* The FPCR, and disassembled portions thereof.  */
 241    uint32_t fpcr;
 242    uint32_t fpcr_exc_enable;
 243    float_status fp_status;
 244    uint8_t fpcr_dyn_round;
 245    uint8_t fpcr_flush_to_zero;
 246
 247    /* The Internal Processor Registers.  Some of these we assume always
 248       exist for use in user-mode.  */
 249    uint8_t ps;
 250    uint8_t intr_flag;
 251    uint8_t pal_mode;
 252    uint8_t fen;
 253
 254    uint32_t pcc_ofs;
 255
 256    /* These pass data from the exception logic in the translator and
 257       helpers to the OS entry point.  This is used for both system
 258       emulation and user-mode.  */
 259    uint64_t trap_arg0;
 260    uint64_t trap_arg1;
 261    uint64_t trap_arg2;
 262
 263#if !defined(CONFIG_USER_ONLY)
 264    /* The internal data required by our emulation of the Unix PALcode.  */
 265    uint64_t exc_addr;
 266    uint64_t palbr;
 267    uint64_t ptbr;
 268    uint64_t vptptr;
 269    uint64_t sysval;
 270    uint64_t usp;
 271    uint64_t shadow[8];
 272    uint64_t scratch[24];
 273#endif
 274
 275    /* This alarm doesn't exist in real hardware; we wish it did.  */
 276    uint64_t alarm_expire;
 277
 278    /* Those resources are used only in QEMU core */
 279    CPU_COMMON
 280
 281    int error_code;
 282
 283    uint32_t features;
 284    uint32_t amask;
 285    int implver;
 286};
 287
 288/**
 289 * AlphaCPU:
 290 * @env: #CPUAlphaState
 291 *
 292 * An Alpha CPU.
 293 */
 294struct AlphaCPU {
 295    /*< private >*/
 296    CPUState parent_obj;
 297    /*< public >*/
 298
 299    CPUAlphaState env;
 300
 301    /* This alarm doesn't exist in real hardware; we wish it did.  */
 302    QEMUTimer *alarm_timer;
 303};
 304
 305static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
 306{
 307    return container_of(env, AlphaCPU, env);
 308}
 309
 310#define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
 311
 312#define ENV_OFFSET offsetof(AlphaCPU, env)
 313
 314#ifndef CONFIG_USER_ONLY
 315extern const struct VMStateDescription vmstate_alpha_cpu;
 316#endif
 317
 318void alpha_cpu_do_interrupt(CPUState *cpu);
 319bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
 320void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 321                          int flags);
 322hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 323int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 324int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 325void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
 326                                   MMUAccessType access_type,
 327                                   int mmu_idx, uintptr_t retaddr);
 328
 329#define cpu_list alpha_cpu_list
 330#define cpu_signal_handler cpu_alpha_signal_handler
 331
 332#include "exec/cpu-all.h"
 333
 334enum {
 335    FEATURE_ASN    = 0x00000001,
 336    FEATURE_SPS    = 0x00000002,
 337    FEATURE_VIRBND = 0x00000004,
 338    FEATURE_TBCHK  = 0x00000008,
 339};
 340
 341enum {
 342    EXCP_RESET,
 343    EXCP_MCHK,
 344    EXCP_SMP_INTERRUPT,
 345    EXCP_CLK_INTERRUPT,
 346    EXCP_DEV_INTERRUPT,
 347    EXCP_MMFAULT,
 348    EXCP_UNALIGN,
 349    EXCP_OPCDEC,
 350    EXCP_ARITH,
 351    EXCP_FEN,
 352    EXCP_CALL_PAL,
 353    /* For Usermode emulation.  */
 354    EXCP_STL_C,
 355    EXCP_STQ_C,
 356};
 357
 358/* Alpha-specific interrupt pending bits.  */
 359#define CPU_INTERRUPT_TIMER     CPU_INTERRUPT_TGT_EXT_0
 360#define CPU_INTERRUPT_SMP       CPU_INTERRUPT_TGT_EXT_1
 361#define CPU_INTERRUPT_MCHK      CPU_INTERRUPT_TGT_EXT_2
 362
 363/* OSF/1 Page table bits.  */
 364enum {
 365    PTE_VALID = 0x0001,
 366    PTE_FOR   = 0x0002,  /* used for page protection (fault on read) */
 367    PTE_FOW   = 0x0004,  /* used for page protection (fault on write) */
 368    PTE_FOE   = 0x0008,  /* used for page protection (fault on exec) */
 369    PTE_ASM   = 0x0010,
 370    PTE_KRE   = 0x0100,
 371    PTE_URE   = 0x0200,
 372    PTE_KWE   = 0x1000,
 373    PTE_UWE   = 0x2000
 374};
 375
 376/* Hardware interrupt (entInt) constants.  */
 377enum {
 378    INT_K_IP,
 379    INT_K_CLK,
 380    INT_K_MCHK,
 381    INT_K_DEV,
 382    INT_K_PERF,
 383};
 384
 385/* Memory management (entMM) constants.  */
 386enum {
 387    MM_K_TNV,
 388    MM_K_ACV,
 389    MM_K_FOR,
 390    MM_K_FOE,
 391    MM_K_FOW
 392};
 393
 394/* Arithmetic exception (entArith) constants.  */
 395enum {
 396    EXC_M_SWC = 1,      /* Software completion */
 397    EXC_M_INV = 2,      /* Invalid operation */
 398    EXC_M_DZE = 4,      /* Division by zero */
 399    EXC_M_FOV = 8,      /* Overflow */
 400    EXC_M_UNF = 16,     /* Underflow */
 401    EXC_M_INE = 32,     /* Inexact result */
 402    EXC_M_IOV = 64      /* Integer Overflow */
 403};
 404
 405/* Processor status constants.  */
 406enum {
 407    /* Low 3 bits are interrupt mask level.  */
 408    PS_INT_MASK = 7,
 409
 410    /* Bits 4 and 5 are the mmu mode.  The VMS PALcode uses all 4 modes;
 411       The Unix PALcode only uses bit 4.  */
 412    PS_USER_MODE = 8
 413};
 414
 415static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
 416{
 417    if (env->pal_mode) {
 418        return MMU_KERNEL_IDX;
 419    } else if (env->ps & PS_USER_MODE) {
 420        return MMU_USER_IDX;
 421    } else {
 422        return MMU_KERNEL_IDX;
 423    }
 424}
 425
 426enum {
 427    IR_V0   = 0,
 428    IR_T0   = 1,
 429    IR_T1   = 2,
 430    IR_T2   = 3,
 431    IR_T3   = 4,
 432    IR_T4   = 5,
 433    IR_T5   = 6,
 434    IR_T6   = 7,
 435    IR_T7   = 8,
 436    IR_S0   = 9,
 437    IR_S1   = 10,
 438    IR_S2   = 11,
 439    IR_S3   = 12,
 440    IR_S4   = 13,
 441    IR_S5   = 14,
 442    IR_S6   = 15,
 443    IR_FP   = IR_S6,
 444    IR_A0   = 16,
 445    IR_A1   = 17,
 446    IR_A2   = 18,
 447    IR_A3   = 19,
 448    IR_A4   = 20,
 449    IR_A5   = 21,
 450    IR_T8   = 22,
 451    IR_T9   = 23,
 452    IR_T10  = 24,
 453    IR_T11  = 25,
 454    IR_RA   = 26,
 455    IR_T12  = 27,
 456    IR_PV   = IR_T12,
 457    IR_AT   = 28,
 458    IR_GP   = 29,
 459    IR_SP   = 30,
 460    IR_ZERO = 31,
 461};
 462
 463void alpha_translate_init(void);
 464
 465AlphaCPU *cpu_alpha_init(const char *cpu_model);
 466
 467#define cpu_init(cpu_model) CPU(cpu_alpha_init(cpu_model))
 468
 469void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 470/* you can call this signal handler from your SIGBUS and SIGSEGV
 471   signal handlers to inform the virtual CPU of exceptions. non zero
 472   is returned if the signal was handled by the virtual CPU.  */
 473int cpu_alpha_signal_handler(int host_signum, void *pinfo,
 474                             void *puc);
 475int alpha_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 476                               int mmu_idx);
 477void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
 478void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
 479void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
 480
 481uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
 482void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
 483uint64_t cpu_alpha_load_gr(CPUAlphaState *env, unsigned reg);
 484void cpu_alpha_store_gr(CPUAlphaState *env, unsigned reg, uint64_t val);
 485#ifndef CONFIG_USER_ONLY
 486QEMU_NORETURN void alpha_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
 487                                               bool is_write, bool is_exec,
 488                                               int unused, unsigned size);
 489#endif
 490
 491/* Bits in TB->FLAGS that control how translation is processed.  */
 492enum {
 493    TB_FLAGS_PAL_MODE = 1,
 494    TB_FLAGS_FEN = 2,
 495    TB_FLAGS_USER_MODE = 8,
 496
 497    TB_FLAGS_AMASK_SHIFT = 4,
 498    TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT,
 499    TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT,
 500    TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT,
 501    TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT,
 502    TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT,
 503    TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
 504};
 505
 506static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
 507                                        target_ulong *cs_base, uint32_t *pflags)
 508{
 509    int flags = 0;
 510
 511    *pc = env->pc;
 512    *cs_base = 0;
 513
 514    if (env->pal_mode) {
 515        flags = TB_FLAGS_PAL_MODE;
 516    } else {
 517        flags = env->ps & PS_USER_MODE;
 518    }
 519    if (env->fen) {
 520        flags |= TB_FLAGS_FEN;
 521    }
 522    flags |= env->amask << TB_FLAGS_AMASK_SHIFT;
 523
 524    *pflags = flags;
 525}
 526
 527#endif /* ALPHA_CPU_H */
 528