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