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