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