]>
Commit | Line | Data |
---|---|---|
032c76bc CW |
1 | /* |
2 | * Altera Nios II virtual CPU header | |
3 | * | |
4 | * Copyright (c) 2012 Chris Wulff <crwulff@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 | |
18 | * <http://www.gnu.org/licenses/lgpl-2.1.html> | |
19 | */ | |
58ea30f5 MA |
20 | |
21 | #ifndef NIOS2_CPU_H | |
22 | #define NIOS2_CPU_H | |
032c76bc | 23 | |
74433bf0 | 24 | #include "exec/cpu-defs.h" |
2e5b09fd | 25 | #include "hw/core/cpu.h" |
e96568a4 | 26 | #include "hw/registerfields.h" |
db1015e9 | 27 | #include "qom/object.h" |
032c76bc | 28 | |
1ea4a06a | 29 | typedef struct CPUArchState CPUNios2State; |
032c76bc CW |
30 | #if !defined(CONFIG_USER_ONLY) |
31 | #include "mmu.h" | |
32 | #endif | |
33 | ||
34 | #define TYPE_NIOS2_CPU "nios2-cpu" | |
35 | ||
9295b1aa | 36 | OBJECT_DECLARE_CPU_TYPE(Nios2CPU, Nios2CPUClass, NIOS2_CPU) |
032c76bc CW |
37 | |
38 | /** | |
39 | * Nios2CPUClass: | |
4245a716 | 40 | * @parent_phases: The parent class' reset phase handlers. |
032c76bc CW |
41 | * |
42 | * A Nios2 CPU model. | |
43 | */ | |
db1015e9 | 44 | struct Nios2CPUClass { |
032c76bc | 45 | CPUClass parent_class; |
032c76bc CW |
46 | |
47 | DeviceRealize parent_realize; | |
4245a716 | 48 | ResettablePhases parent_phases; |
db1015e9 | 49 | }; |
032c76bc CW |
50 | |
51 | #define TARGET_HAS_ICE 1 | |
52 | ||
53 | /* Configuration options for Nios II */ | |
54 | #define RESET_ADDRESS 0x00000000 | |
55 | #define EXCEPTION_ADDRESS 0x00000004 | |
56 | #define FAST_TLB_MISS_ADDRESS 0x00000008 | |
57 | ||
5ea3e997 AG |
58 | #define NUM_GP_REGS 32 |
59 | #define NUM_CR_REGS 32 | |
032c76bc | 60 | |
945a5bd3 RH |
61 | #ifndef CONFIG_USER_ONLY |
62 | /* 63 shadow register sets; index 0 is the primary register set. */ | |
63 | #define NUM_REG_SETS 64 | |
64 | #endif | |
65 | ||
032c76bc | 66 | /* General purpose register aliases */ |
bdb307b4 RH |
67 | enum { |
68 | R_ZERO = 0, | |
69 | R_AT = 1, | |
70 | R_RET0 = 2, | |
71 | R_RET1 = 3, | |
72 | R_ARG0 = 4, | |
73 | R_ARG1 = 5, | |
74 | R_ARG2 = 6, | |
75 | R_ARG3 = 7, | |
76 | R_ET = 24, | |
77 | R_BT = 25, | |
78 | R_GP = 26, | |
79 | R_SP = 27, | |
80 | R_FP = 28, | |
81 | R_EA = 29, | |
82 | R_BA = 30, | |
6bcc59ca | 83 | R_SSTATUS = 30, |
bdb307b4 RH |
84 | R_RA = 31, |
85 | }; | |
032c76bc CW |
86 | |
87 | /* Control register aliases */ | |
bdb307b4 RH |
88 | enum { |
89 | CR_STATUS = 0, | |
90 | CR_ESTATUS = 1, | |
91 | CR_BSTATUS = 2, | |
92 | CR_IENABLE = 3, | |
93 | CR_IPENDING = 4, | |
94 | CR_CPUID = 5, | |
95 | CR_EXCEPTION = 7, | |
96 | CR_PTEADDR = 8, | |
97 | CR_TLBACC = 9, | |
98 | CR_TLBMISC = 10, | |
99 | CR_ENCINJ = 11, | |
100 | CR_BADADDR = 12, | |
101 | CR_CONFIG = 13, | |
102 | CR_MPUBASE = 14, | |
103 | CR_MPUACC = 15, | |
104 | }; | |
e96568a4 RH |
105 | |
106 | FIELD(CR_STATUS, PIE, 0, 1) | |
107 | FIELD(CR_STATUS, U, 1, 1) | |
108 | FIELD(CR_STATUS, EH, 2, 1) | |
109 | FIELD(CR_STATUS, IH, 3, 1) | |
110 | FIELD(CR_STATUS, IL, 4, 6) | |
111 | FIELD(CR_STATUS, CRS, 10, 6) | |
112 | FIELD(CR_STATUS, PRS, 16, 6) | |
113 | FIELD(CR_STATUS, NMI, 22, 1) | |
114 | FIELD(CR_STATUS, RSIE, 23, 1) | |
a25c4eff | 115 | FIELD(CR_STATUS, SRS, 31, 1) /* only in sstatus */ |
e96568a4 RH |
116 | |
117 | #define CR_STATUS_PIE R_CR_STATUS_PIE_MASK | |
118 | #define CR_STATUS_U R_CR_STATUS_U_MASK | |
119 | #define CR_STATUS_EH R_CR_STATUS_EH_MASK | |
120 | #define CR_STATUS_IH R_CR_STATUS_IH_MASK | |
121 | #define CR_STATUS_NMI R_CR_STATUS_NMI_MASK | |
122 | #define CR_STATUS_RSIE R_CR_STATUS_RSIE_MASK | |
a25c4eff | 123 | #define CR_STATUS_SRS R_CR_STATUS_SRS_MASK |
e96568a4 | 124 | |
bf754c96 RH |
125 | FIELD(CR_EXCEPTION, CAUSE, 2, 5) |
126 | FIELD(CR_EXCEPTION, ECCFTL, 31, 1) | |
127 | ||
0a1fc630 RH |
128 | FIELD(CR_PTEADDR, VPN, 2, 20) |
129 | FIELD(CR_PTEADDR, PTBASE, 22, 10) | |
130 | ||
9d636563 RH |
131 | FIELD(CR_TLBACC, PFN, 0, 20) |
132 | FIELD(CR_TLBACC, G, 20, 1) | |
133 | FIELD(CR_TLBACC, X, 21, 1) | |
134 | FIELD(CR_TLBACC, W, 22, 1) | |
135 | FIELD(CR_TLBACC, R, 23, 1) | |
136 | FIELD(CR_TLBACC, C, 24, 1) | |
137 | FIELD(CR_TLBACC, IG, 25, 7) | |
138 | ||
139 | #define CR_TLBACC_C R_CR_TLBACC_C_MASK | |
140 | #define CR_TLBACC_R R_CR_TLBACC_R_MASK | |
141 | #define CR_TLBACC_W R_CR_TLBACC_W_MASK | |
142 | #define CR_TLBACC_X R_CR_TLBACC_X_MASK | |
143 | #define CR_TLBACC_G R_CR_TLBACC_G_MASK | |
144 | ||
17c20fe3 RH |
145 | FIELD(CR_TLBMISC, D, 0, 1) |
146 | FIELD(CR_TLBMISC, PERM, 1, 1) | |
147 | FIELD(CR_TLBMISC, BAD, 2, 1) | |
148 | FIELD(CR_TLBMISC, DBL, 3, 1) | |
149 | FIELD(CR_TLBMISC, PID, 4, 14) | |
150 | FIELD(CR_TLBMISC, WE, 18, 1) | |
151 | FIELD(CR_TLBMISC, RD, 19, 1) | |
152 | FIELD(CR_TLBMISC, WAY, 20, 4) | |
153 | FIELD(CR_TLBMISC, EE, 24, 1) | |
154 | ||
155 | #define CR_TLBMISC_EE R_CR_TLBMISC_EE_MASK | |
156 | #define CR_TLBMISC_RD R_CR_TLBMISC_RD_MASK | |
157 | #define CR_TLBMISC_WE R_CR_TLBMISC_WE_MASK | |
158 | #define CR_TLBMISC_DBL R_CR_TLBMISC_DBL_MASK | |
159 | #define CR_TLBMISC_BAD R_CR_TLBMISC_BAD_MASK | |
160 | #define CR_TLBMISC_PERM R_CR_TLBMISC_PERM_MASK | |
161 | #define CR_TLBMISC_D R_CR_TLBMISC_D_MASK | |
162 | ||
032c76bc | 163 | /* Exceptions */ |
413a99a9 | 164 | #define EXCP_BREAK 0x1000 |
24ca3134 | 165 | #define EXCP_SEMIHOST 0x1001 |
032c76bc CW |
166 | #define EXCP_RESET 0 |
167 | #define EXCP_PRESET 1 | |
168 | #define EXCP_IRQ 2 | |
169 | #define EXCP_TRAP 3 | |
170 | #define EXCP_UNIMPL 4 | |
171 | #define EXCP_ILLEGAL 5 | |
172 | #define EXCP_UNALIGN 6 | |
173 | #define EXCP_UNALIGND 7 | |
174 | #define EXCP_DIV 8 | |
be77e1d5 | 175 | #define EXCP_SUPERA_X 9 |
032c76bc | 176 | #define EXCP_SUPERI 10 |
be77e1d5 RH |
177 | #define EXCP_SUPERA_D 11 |
178 | #define EXCP_TLB_X 12 | |
179 | #define EXCP_TLB_D (0x1000 | EXCP_TLB_X) | |
180 | #define EXCP_PERM_X 13 | |
181 | #define EXCP_PERM_R 14 | |
182 | #define EXCP_PERM_W 15 | |
032c76bc CW |
183 | #define EXCP_MPUI 16 |
184 | #define EXCP_MPUD 17 | |
185 | ||
1ea4a06a | 186 | struct CPUArchState { |
945a5bd3 | 187 | #ifdef CONFIG_USER_ONLY |
b8f036a9 | 188 | uint32_t regs[NUM_GP_REGS]; |
945a5bd3 RH |
189 | #else |
190 | uint32_t shadow_regs[NUM_REG_SETS][NUM_GP_REGS]; | |
191 | /* Pointer into shadow_regs for the current register set. */ | |
192 | uint32_t *regs; | |
193 | #endif | |
b8f036a9 | 194 | uint32_t ctrl[NUM_CR_REGS]; |
17a406ee | 195 | uint32_t pc; |
032c76bc CW |
196 | |
197 | #if !defined(CONFIG_USER_ONLY) | |
198 | Nios2MMU mmu; | |
032c76bc | 199 | #endif |
87d7bfdb | 200 | int error_code; |
032c76bc CW |
201 | }; |
202 | ||
796945d5 RH |
203 | typedef struct { |
204 | uint32_t writable; | |
205 | uint32_t readonly; | |
206 | } ControlRegState; | |
207 | ||
032c76bc CW |
208 | /** |
209 | * Nios2CPU: | |
210 | * @env: #CPUNios2State | |
211 | * | |
212 | * A Nios2 CPU. | |
213 | */ | |
b36e239e | 214 | struct ArchCPU { |
032c76bc | 215 | CPUState parent_obj; |
032c76bc CW |
216 | |
217 | CPUNios2State env; | |
5b146dc7 | 218 | |
345b7a87 | 219 | bool diverr_present; |
032c76bc | 220 | bool mmu_present; |
3a030870 | 221 | bool eic_present; |
345b7a87 | 222 | |
032c76bc CW |
223 | uint32_t pid_num_bits; |
224 | uint32_t tlb_num_ways; | |
225 | uint32_t tlb_num_entries; | |
226 | ||
227 | /* Addresses that are hard-coded in the FPGA build settings */ | |
228 | uint32_t reset_addr; | |
229 | uint32_t exception_addr; | |
230 | uint32_t fast_tlb_miss_addr; | |
796945d5 RH |
231 | |
232 | /* Bits within each control register which are reserved or readonly. */ | |
233 | ControlRegState cr_state[NUM_CR_REGS]; | |
a25c4eff RH |
234 | |
235 | /* External Interrupt Controller Interface */ | |
236 | uint32_t rha; /* Requested handler address */ | |
237 | uint32_t ril; /* Requested interrupt level */ | |
238 | uint32_t rrs; /* Requested register set */ | |
239 | bool rnmi; /* Requested nonmaskable interrupt */ | |
db1015e9 | 240 | }; |
032c76bc | 241 | |
032c76bc | 242 | |
796945d5 RH |
243 | static inline bool nios2_cr_reserved(const ControlRegState *s) |
244 | { | |
245 | return (s->writable | s->readonly) == 0; | |
246 | } | |
247 | ||
945a5bd3 RH |
248 | static inline void nios2_update_crs(CPUNios2State *env) |
249 | { | |
250 | #ifndef CONFIG_USER_ONLY | |
251 | unsigned crs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, CRS); | |
252 | env->regs = env->shadow_regs[crs]; | |
253 | #endif | |
254 | } | |
255 | ||
032c76bc | 256 | void nios2_tcg_init(void); |
032c76bc | 257 | void nios2_cpu_do_interrupt(CPUState *cs); |
fad866da | 258 | void dump_mmu(CPUNios2State *env); |
90c84c56 | 259 | void nios2_cpu_dump_state(CPUState *cpu, FILE *f, int flags); |
8905770b MAL |
260 | G_NORETURN void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, |
261 | MMUAccessType access_type, int mmu_idx, | |
262 | uintptr_t retaddr); | |
e84f1768 RH |
263 | G_NORETURN void nios2_cpu_loop_exit_advance(CPUNios2State *env, |
264 | uintptr_t retaddr); | |
032c76bc | 265 | |
413a99a9 SL |
266 | void do_nios2_semihosting(CPUNios2State *env); |
267 | ||
0dacec87 | 268 | #define CPU_RESOLVING_TYPE TYPE_NIOS2_CPU |
032c76bc CW |
269 | |
270 | #define cpu_gen_code cpu_nios2_gen_code | |
032c76bc CW |
271 | |
272 | #define CPU_SAVE_VERSION 1 | |
273 | ||
032c76bc | 274 | /* MMU modes definitions */ |
032c76bc CW |
275 | #define MMU_SUPERVISOR_IDX 0 |
276 | #define MMU_USER_IDX 1 | |
277 | ||
278 | static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch) | |
279 | { | |
b8f036a9 | 280 | return (env->ctrl[CR_STATUS] & CR_STATUS_U) ? MMU_USER_IDX : |
032c76bc CW |
281 | MMU_SUPERVISOR_IDX; |
282 | } | |
283 | ||
fb4de9d2 | 284 | #ifndef CONFIG_USER_ONLY |
6d2d454a | 285 | hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); |
0137c93f RH |
286 | bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size, |
287 | MMUAccessType access_type, int mmu_idx, | |
288 | bool probe, uintptr_t retaddr); | |
fac94cb3 | 289 | #endif |
032c76bc | 290 | |
4f7c64b3 | 291 | typedef CPUNios2State CPUArchState; |
2161a612 | 292 | typedef Nios2CPU ArchCPU; |
4f7c64b3 | 293 | |
032c76bc | 294 | #include "exec/cpu-all.h" |
032c76bc | 295 | |
945a5bd3 RH |
296 | FIELD(TBFLAGS, CRS0, 0, 1) /* Set if CRS == 0. */ |
297 | FIELD(TBFLAGS, U, 1, 1) /* Overlaps CR_STATUS_U */ | |
298 | FIELD(TBFLAGS, R0_0, 2, 1) /* Set if R0 == 0. */ | |
299 | ||
bb5de525 AJ |
300 | static inline void cpu_get_tb_cpu_state(CPUNios2State *env, vaddr *pc, |
301 | uint64_t *cs_base, uint32_t *flags) | |
032c76bc | 302 | { |
945a5bd3 RH |
303 | unsigned crs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, CRS); |
304 | ||
17a406ee | 305 | *pc = env->pc; |
032c76bc | 306 | *cs_base = 0; |
945a5bd3 RH |
307 | *flags = (env->ctrl[CR_STATUS] & CR_STATUS_U) |
308 | | (crs ? 0 : R_TBFLAGS_CRS0_MASK) | |
309 | | (env->regs[0] ? 0 : R_TBFLAGS_R0_0_MASK); | |
032c76bc CW |
310 | } |
311 | ||
58ea30f5 | 312 | #endif /* NIOS2_CPU_H */ |