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