|
|
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:
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:
279: /* Those resources are used only in Qemu core */
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"
295:
296: enum {
297: FEATURE_ASN = 0x00000001,
298: FEATURE_SPS = 0x00000002,
299: FEATURE_VIRBND = 0x00000004,
300: FEATURE_TBCHK = 0x00000008,
301: };
302:
303: enum {
1.1.1.6 root 304: EXCP_RESET,
305: EXCP_MCHK,
306: EXCP_SMP_INTERRUPT,
307: EXCP_CLK_INTERRUPT,
308: EXCP_DEV_INTERRUPT,
309: EXCP_MMFAULT,
310: EXCP_UNALIGN,
311: EXCP_OPCDEC,
312: EXCP_ARITH,
313: EXCP_FEN,
314: EXCP_CALL_PAL,
315: /* For Usermode emulation. */
316: EXCP_STL_C,
317: EXCP_STQ_C,
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. */
326: enum {
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. */
339: enum {
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. */
348: enum {
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. */
357: enum {
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: enum {
369: /* Low 3 bits are interrupt mask level. */
370: PS_INT_MASK = 7,
371:
372: /* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes;
373: The Unix PALcode only uses bit 4. */
374: PS_USER_MODE = 8
375: };
376:
377: static inline int cpu_mmu_index(CPUState *env)
378: {
379: if (env->pal_mode) {
380: return MMU_KERNEL_IDX;
381: } else if (env->ps & PS_USER_MODE) {
382: return MMU_USER_IDX;
383: } else {
384: return MMU_KERNEL_IDX;
385: }
386: }
1.1 root 387:
388: enum {
389: IR_V0 = 0,
390: IR_T0 = 1,
391: IR_T1 = 2,
392: IR_T2 = 3,
393: IR_T3 = 4,
394: IR_T4 = 5,
395: IR_T5 = 6,
396: IR_T6 = 7,
397: IR_T7 = 8,
398: IR_S0 = 9,
399: IR_S1 = 10,
400: IR_S2 = 11,
401: IR_S3 = 12,
402: IR_S4 = 13,
403: IR_S5 = 14,
404: IR_S6 = 15,
1.1.1.5 root 405: IR_FP = IR_S6,
1.1 root 406: IR_A0 = 16,
407: IR_A1 = 17,
408: IR_A2 = 18,
409: IR_A3 = 19,
410: IR_A4 = 20,
411: IR_A5 = 21,
412: IR_T8 = 22,
413: IR_T9 = 23,
414: IR_T10 = 24,
415: IR_T11 = 25,
416: IR_RA = 26,
417: IR_T12 = 27,
1.1.1.5 root 418: IR_PV = IR_T12,
1.1 root 419: IR_AT = 28,
420: IR_GP = 29,
421: IR_SP = 30,
422: IR_ZERO = 31,
423: };
424:
425: CPUAlphaState * cpu_alpha_init (const char *cpu_model);
426: int cpu_alpha_exec(CPUAlphaState *s);
427: /* you can call this signal handler from your SIGBUS and SIGSEGV
428: signal handlers to inform the virtual CPU of exceptions. non zero
429: is returned if the signal was handled by the virtual CPU. */
430: int cpu_alpha_signal_handler(int host_signum, void *pinfo,
431: void *puc);
1.1.1.2 root 432: int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
1.1.1.7 ! root 433: int mmu_idx);
1.1.1.4 root 434: #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
1.1.1.2 root 435: void do_interrupt (CPUState *env);
436:
1.1.1.5 root 437: uint64_t cpu_alpha_load_fpcr (CPUState *env);
438: void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
1.1.1.6 root 439: #ifndef CONFIG_USER_ONLY
440: void swap_shadow_regs(CPUState *env);
441: QEMU_NORETURN void cpu_unassigned_access(CPUState *env1,
442: target_phys_addr_t addr, int is_write,
443: int is_exec, int unused, int size);
1.1.1.2 root 444: #endif
445:
1.1.1.6 root 446: /* Bits in TB->FLAGS that control how translation is processed. */
447: enum {
448: TB_FLAGS_PAL_MODE = 1,
449: TB_FLAGS_FEN = 2,
450: TB_FLAGS_USER_MODE = 8,
451:
452: TB_FLAGS_AMASK_SHIFT = 4,
453: TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT,
454: TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT,
455: TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT,
456: TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT,
457: TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT,
458: TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
459: };
460:
1.1.1.2 root 461: static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
1.1.1.6 root 462: target_ulong *cs_base, int *pflags)
1.1.1.2 root 463: {
1.1.1.6 root 464: int flags = 0;
465:
1.1.1.2 root 466: *pc = env->pc;
467: *cs_base = 0;
1.1.1.6 root 468:
469: if (env->pal_mode) {
470: flags = TB_FLAGS_PAL_MODE;
471: } else {
472: flags = env->ps & PS_USER_MODE;
473: }
474: if (env->fen) {
475: flags |= TB_FLAGS_FEN;
476: }
477: flags |= env->amask << TB_FLAGS_AMASK_SHIFT;
478:
479: *pflags = flags;
1.1.1.2 root 480: }
1.1 root 481:
1.1.1.5 root 482: #if defined(CONFIG_USER_ONLY)
483: static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
484: {
485: if (newsp) {
486: env->ir[IR_SP] = newsp;
487: }
488: env->ir[IR_V0] = 0;
489: env->ir[IR_A3] = 0;
490: }
491:
492: static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
493: {
494: env->unique = newtls;
495: }
496: #endif
497:
1.1.1.6 root 498: static inline bool cpu_has_work(CPUState *env)
499: {
500: /* Here we are checking to see if the CPU should wake up from HALT.
501: We will have gotten into this state only for WTINT from PALmode. */
502: /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
503: asleep even if (some) interrupts have been asserted. For now,
504: assume that if a CPU really wants to stay asleep, it will mask
505: interrupts at the chipset level, which will prevent these bits
506: from being set in the first place. */
507: return env->interrupt_request & (CPU_INTERRUPT_HARD
508: | CPU_INTERRUPT_TIMER
509: | CPU_INTERRUPT_SMP
510: | CPU_INTERRUPT_MCHK);
511: }
512:
513: #include "exec-all.h"
514:
515: static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
516: {
517: env->pc = tb->pc;
518: }
519:
1.1 root 520: #endif /* !defined (__CPU_ALPHA_H__) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.