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