xref: /openbmc/qemu/target/openrisc/cpu.h (revision fd87be1dada5672f877e03c2ca8504458292c479)
1  /*
2   * OpenRISC virtual CPU header.
3   *
4   * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
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 OPENRISC_CPU_H
21  #define OPENRISC_CPU_H
22  
23  #include "cpu-qom.h"
24  #include "exec/cpu-defs.h"
25  #include "fpu/softfloat-types.h"
26  
27  /**
28   * OpenRISCCPUClass:
29   * @parent_realize: The parent class' realize handler.
30   * @parent_phases: The parent class' reset phase handlers.
31   *
32   * A OpenRISC CPU model.
33   */
34  struct OpenRISCCPUClass {
35      CPUClass parent_class;
36  
37      DeviceRealize parent_realize;
38      ResettablePhases parent_phases;
39  };
40  
41  #define TARGET_INSN_START_EXTRA_WORDS 1
42  
43  enum {
44      MMU_NOMMU_IDX = 0,
45      MMU_SUPERVISOR_IDX = 1,
46      MMU_USER_IDX = 2,
47  };
48  
49  #define SET_FP_CAUSE(reg, v)    do {\
50                                      (reg) = ((reg) & ~(0x3f << 12)) | \
51                                              ((v & 0x3f) << 12);\
52                                  } while (0)
53  #define GET_FP_ENABLE(reg)       (((reg) >>  7) & 0x1f)
54  #define UPDATE_FP_FLAGS(reg, v)   do {\
55                                        (reg) |= ((v & 0x1f) << 2);\
56                                    } while (0)
57  
58  /* Interrupt */
59  #define NR_IRQS  32
60  
61  /* Unit presece register */
62  enum {
63      UPR_UP = (1 << 0),
64      UPR_DCP = (1 << 1),
65      UPR_ICP = (1 << 2),
66      UPR_DMP = (1 << 3),
67      UPR_IMP = (1 << 4),
68      UPR_MP = (1 << 5),
69      UPR_DUP = (1 << 6),
70      UPR_PCUR = (1 << 7),
71      UPR_PMP = (1 << 8),
72      UPR_PICP = (1 << 9),
73      UPR_TTP = (1 << 10),
74      UPR_CUP = (255 << 24),
75  };
76  
77  /* CPU configure register */
78  enum {
79      CPUCFGR_NSGF = (15 << 0),
80      CPUCFGR_CGF = (1 << 4),
81      CPUCFGR_OB32S = (1 << 5),
82      CPUCFGR_OB64S = (1 << 6),
83      CPUCFGR_OF32S = (1 << 7),
84      CPUCFGR_OF64S = (1 << 8),
85      CPUCFGR_OV64S = (1 << 9),
86      CPUCFGR_ND = (1 << 10),
87      CPUCFGR_AVRP = (1 << 11),
88      CPUCFGR_EVBARP = (1 << 12),
89      CPUCFGR_ISRP = (1 << 13),
90      CPUCFGR_AECSRP = (1 << 14),
91      CPUCFGR_OF64A32S = (1 << 15),
92  };
93  
94  /* DMMU configure register */
95  enum {
96      DMMUCFGR_NTW = (3 << 0),
97      DMMUCFGR_NTS = (7 << 2),
98      DMMUCFGR_NAE = (7 << 5),
99      DMMUCFGR_CRI = (1 << 8),
100      DMMUCFGR_PRI = (1 << 9),
101      DMMUCFGR_TEIRI = (1 << 10),
102      DMMUCFGR_HTR = (1 << 11),
103  };
104  
105  /* IMMU configure register */
106  enum {
107      IMMUCFGR_NTW = (3 << 0),
108      IMMUCFGR_NTS = (7 << 2),
109      IMMUCFGR_NAE = (7 << 5),
110      IMMUCFGR_CRI = (1 << 8),
111      IMMUCFGR_PRI = (1 << 9),
112      IMMUCFGR_TEIRI = (1 << 10),
113      IMMUCFGR_HTR = (1 << 11),
114  };
115  
116  /* Power management register */
117  enum {
118      PMR_SDF = (15 << 0),
119      PMR_DME = (1 << 4),
120      PMR_SME = (1 << 5),
121      PMR_DCGE = (1 << 6),
122      PMR_SUME = (1 << 7),
123  };
124  
125  /* Float point control status register */
126  enum {
127      FPCSR_FPEE = 1,
128      FPCSR_RM = (3 << 1),
129      FPCSR_OVF = (1 << 3),
130      FPCSR_UNF = (1 << 4),
131      FPCSR_SNF = (1 << 5),
132      FPCSR_QNF = (1 << 6),
133      FPCSR_ZF = (1 << 7),
134      FPCSR_IXF = (1 << 8),
135      FPCSR_IVF = (1 << 9),
136      FPCSR_INF = (1 << 10),
137      FPCSR_DZF = (1 << 11),
138  };
139  
140  /* Exceptions indices */
141  enum {
142      EXCP_RESET    = 0x1,
143      EXCP_BUSERR   = 0x2,
144      EXCP_DPF      = 0x3,
145      EXCP_IPF      = 0x4,
146      EXCP_TICK     = 0x5,
147      EXCP_ALIGN    = 0x6,
148      EXCP_ILLEGAL  = 0x7,
149      EXCP_INT      = 0x8,
150      EXCP_DTLBMISS = 0x9,
151      EXCP_ITLBMISS = 0xa,
152      EXCP_RANGE    = 0xb,
153      EXCP_SYSCALL  = 0xc,
154      EXCP_FPE      = 0xd,
155      EXCP_TRAP     = 0xe,
156      EXCP_NR,
157  };
158  
159  /* Supervisor register */
160  enum {
161      SR_SM = (1 << 0),
162      SR_TEE = (1 << 1),
163      SR_IEE = (1 << 2),
164      SR_DCE = (1 << 3),
165      SR_ICE = (1 << 4),
166      SR_DME = (1 << 5),
167      SR_IME = (1 << 6),
168      SR_LEE = (1 << 7),
169      SR_CE  = (1 << 8),
170      SR_F   = (1 << 9),
171      SR_CY  = (1 << 10),
172      SR_OV  = (1 << 11),
173      SR_OVE = (1 << 12),
174      SR_DSX = (1 << 13),
175      SR_EPH = (1 << 14),
176      SR_FO  = (1 << 15),
177      SR_SUMRA = (1 << 16),
178      SR_SCE = (1 << 17),
179  };
180  
181  /* Tick Timer Mode Register */
182  enum {
183      TTMR_TP = (0xfffffff),
184      TTMR_IP = (1 << 28),
185      TTMR_IE = (1 << 29),
186      TTMR_M  = (3 << 30),
187  };
188  
189  /* Timer Mode */
190  enum {
191      TIMER_NONE = (0 << 30),
192      TIMER_INTR = (1 << 30),
193      TIMER_SHOT = (2 << 30),
194      TIMER_CONT = (3 << 30),
195  };
196  
197  /* TLB size */
198  enum {
199      TLB_SIZE = 128,
200      TLB_MASK = TLB_SIZE - 1,
201  };
202  
203  /* TLB prot */
204  enum {
205      URE = (1 << 6),
206      UWE = (1 << 7),
207      SRE = (1 << 8),
208      SWE = (1 << 9),
209  
210      SXE = (1 << 6),
211      UXE = (1 << 7),
212  };
213  
214  typedef struct OpenRISCTLBEntry {
215      uint32_t mr;
216      uint32_t tr;
217  } OpenRISCTLBEntry;
218  
219  #ifndef CONFIG_USER_ONLY
220  typedef struct CPUOpenRISCTLBContext {
221      OpenRISCTLBEntry itlb[TLB_SIZE];
222      OpenRISCTLBEntry dtlb[TLB_SIZE];
223  
224      int (*cpu_openrisc_map_address_code)(OpenRISCCPU *cpu,
225                                           hwaddr *physical,
226                                           int *prot,
227                                           target_ulong address, int rw);
228      int (*cpu_openrisc_map_address_data)(OpenRISCCPU *cpu,
229                                           hwaddr *physical,
230                                           int *prot,
231                                           target_ulong address, int rw);
232  } CPUOpenRISCTLBContext;
233  #endif
234  
235  typedef struct CPUArchState {
236      target_ulong shadow_gpr[16][32]; /* Shadow registers */
237  
238      target_ulong pc;          /* Program counter */
239      target_ulong ppc;         /* Prev PC */
240      target_ulong jmp_pc;      /* Jump PC */
241  
242      uint64_t mac;             /* Multiply registers MACHI:MACLO */
243  
244      target_ulong epcr;        /* Exception PC register */
245      target_ulong eear;        /* Exception EA register */
246  
247      target_ulong sr_f;        /* the SR_F bit, values 0, 1.  */
248      target_ulong sr_cy;       /* the SR_CY bit, values 0, 1.  */
249      target_long  sr_ov;       /* the SR_OV bit (in the sign bit only) */
250      uint32_t sr;              /* Supervisor register, without SR_{F,CY,OV} */
251      uint32_t esr;             /* Exception supervisor register */
252      uint32_t evbar;           /* Exception vector base address register */
253      uint32_t pmr;             /* Power Management Register */
254      uint32_t fpcsr;           /* Float register */
255      float_status fp_status;
256  
257      target_ulong lock_addr;
258      target_ulong lock_value;
259  
260      uint32_t dflag;           /* In delay slot (boolean) */
261  
262  #ifndef CONFIG_USER_ONLY
263      CPUOpenRISCTLBContext tlb;
264  #endif
265  
266      /* Fields up to this point are cleared by a CPU reset */
267      struct {} end_reset_fields;
268  
269      /* Fields from here on are preserved across CPU reset. */
270      uint32_t vr;              /* Version register */
271      uint32_t vr2;             /* Version register 2 */
272      uint32_t avr;             /* Architecture version register */
273      uint32_t upr;             /* Unit presence register */
274      uint32_t cpucfgr;         /* CPU configure register */
275      uint32_t dmmucfgr;        /* DMMU configure register */
276      uint32_t immucfgr;        /* IMMU configure register */
277  
278  #ifndef CONFIG_USER_ONLY
279      QEMUTimer *timer;
280      uint32_t ttmr;          /* Timer tick mode register */
281      int is_counting;
282  
283      uint32_t picmr;         /* Interrupt mask register */
284      uint32_t picsr;         /* Interrupt control register */
285  #endif
286  } CPUOpenRISCState;
287  
288  /**
289   * OpenRISCCPU:
290   * @env: #CPUOpenRISCState
291   *
292   * A OpenRISC CPU.
293   */
294  struct ArchCPU {
295      CPUState parent_obj;
296  
297      CPUOpenRISCState env;
298  };
299  
300  void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
301  int openrisc_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
302  int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
303  void openrisc_translate_init(void);
304  int print_insn_or1k(bfd_vma addr, disassemble_info *info);
305  
306  #ifndef CONFIG_USER_ONLY
307  hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
308  
309  bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
310                             MMUAccessType access_type, int mmu_idx,
311                             bool probe, uintptr_t retaddr);
312  
313  extern const VMStateDescription vmstate_openrisc_cpu;
314  
315  void openrisc_cpu_do_interrupt(CPUState *cpu);
316  bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req);
317  
318  /* hw/openrisc_pic.c */
319  void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
320  
321  /* hw/openrisc_timer.c */
322  void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
323  uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu);
324  void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val);
325  void cpu_openrisc_count_update(OpenRISCCPU *cpu);
326  void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
327  void cpu_openrisc_count_start(OpenRISCCPU *cpu);
328  void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
329  #endif
330  
331  #define CPU_RESOLVING_TYPE TYPE_OPENRISC_CPU
332  
333  #include "exec/cpu-all.h"
334  
335  #define TB_FLAGS_SM    SR_SM
336  #define TB_FLAGS_DME   SR_DME
337  #define TB_FLAGS_IME   SR_IME
338  #define TB_FLAGS_OVE   SR_OVE
339  #define TB_FLAGS_DFLAG 2      /* reuse SR_TEE */
340  #define TB_FLAGS_R0_0  4      /* reuse SR_IEE */
341  
cpu_get_gpr(const CPUOpenRISCState * env,int i)342  static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i)
343  {
344      return env->shadow_gpr[0][i];
345  }
346  
cpu_set_gpr(CPUOpenRISCState * env,int i,uint32_t val)347  static inline void cpu_set_gpr(CPUOpenRISCState *env, int i, uint32_t val)
348  {
349      env->shadow_gpr[0][i] = val;
350  }
351  
cpu_get_tb_cpu_state(CPUOpenRISCState * env,vaddr * pc,uint64_t * cs_base,uint32_t * flags)352  static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, vaddr *pc,
353                                          uint64_t *cs_base, uint32_t *flags)
354  {
355      *pc = env->pc;
356      *cs_base = 0;
357      *flags = (env->dflag ? TB_FLAGS_DFLAG : 0)
358             | (cpu_get_gpr(env, 0) ? 0 : TB_FLAGS_R0_0)
359             | (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE));
360  }
361  
cpu_get_sr(const CPUOpenRISCState * env)362  static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env)
363  {
364      return (env->sr
365              + env->sr_f * SR_F
366              + env->sr_cy * SR_CY
367              + (env->sr_ov < 0) * SR_OV);
368  }
369  
cpu_set_sr(CPUOpenRISCState * env,uint32_t val)370  static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val)
371  {
372      env->sr_f = (val & SR_F) != 0;
373      env->sr_cy = (val & SR_CY) != 0;
374      env->sr_ov = (val & SR_OV ? -1 : 0);
375      env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO;
376  }
377  
378  void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val);
379  
380  #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
381  
382  #endif /* OPENRISC_CPU_H */
383