Commit | Line | Data |
---|---|---|
ef016f83 MF |
1 | /* Simulator for Analog Devices Blackfin processors. |
2 | ||
61baf725 | 3 | Copyright (C) 2005-2017 Free Software Foundation, Inc. |
ef016f83 MF |
4 | Contributed by Analog Devices, Inc. |
5 | ||
6 | This file is part of simulators. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #ifndef _BFIN_SIM_H_ | |
22 | #define _BFIN_SIM_H_ | |
23 | ||
24 | #include <stdbool.h> | |
25 | #include <stdint.h> | |
26 | ||
27 | typedef uint8_t bu8; | |
28 | typedef uint16_t bu16; | |
29 | typedef uint32_t bu32; | |
30 | typedef uint64_t bu40; | |
31 | typedef uint64_t bu64; | |
32 | typedef int8_t bs8; | |
33 | typedef int16_t bs16; | |
34 | typedef int32_t bs32; | |
35 | typedef int64_t bs40; | |
36 | typedef int64_t bs64; | |
37 | ||
38 | /* For dealing with parallel instructions, we must avoid changing our register | |
39 | file until all parallel insns have been simulated. This queue of stores | |
40 | can be used to delay a modification. | |
41 | XXX: Should go and convert all 32 bit insns to use this. */ | |
42 | struct store { | |
43 | bu32 *addr; | |
44 | bu32 val; | |
45 | }; | |
46 | ||
99265d6b MF |
47 | enum bfin_parallel_group { |
48 | BFIN_PARALLEL_NONE, | |
49 | BFIN_PARALLEL_GROUP0, /* 32bit slot. */ | |
50 | BFIN_PARALLEL_GROUP1, /* 16bit group1. */ | |
51 | BFIN_PARALLEL_GROUP2, /* 16bit group2. */ | |
52 | }; | |
53 | ||
ef016f83 MF |
54 | /* The KSP/USP handling wrt SP may not follow the hardware exactly (the hw |
55 | looks at current mode and uses either SP or USP based on that. We instead | |
56 | always operate on SP and mirror things in KSP and USP. During a CEC | |
57 | transition, we take care of syncing the values. This lowers the simulation | |
58 | complexity and speeds things up a bit. */ | |
59 | struct bfin_cpu_state | |
60 | { | |
61 | bu32 dpregs[16], iregs[4], mregs[4], bregs[4], lregs[4], cycles[3]; | |
62 | bu32 ax[2], aw[2]; | |
63 | bu32 lt[2], lc[2], lb[2]; | |
64 | bu32 ksp, usp, seqstat, syscfg, rets, reti, retx, retn, rete; | |
65 | bu32 pc, emudat[2]; | |
66 | /* These ASTAT flags need not be bu32, but it makes pointers easier. */ | |
67 | bu32 ac0, ac0_copy, ac1, an, aq; | |
68 | union { struct { bu32 av0; bu32 av1; }; bu32 av [2]; }; | |
69 | union { struct { bu32 av0s; bu32 av1s; }; bu32 avs[2]; }; | |
70 | bu32 az, cc, v, v_copy, vs; | |
71 | bu32 rnd_mod; | |
72 | bu32 v_internal; | |
73 | bu32 astat_reserved; | |
74 | ||
75 | /* Set by an instruction emulation function if we performed a jump. We | |
76 | cannot compare oldpc to newpc as this ignores the "jump 0;" case. */ | |
77 | bool did_jump; | |
78 | ||
79 | /* Used by the CEC to figure out where to return to. */ | |
80 | bu32 insn_len; | |
81 | ||
82 | /* How many cycles did this insn take to complete ? */ | |
83 | bu32 cycle_delay; | |
84 | ||
85 | /* The pc currently being interpreted in parallel insns. */ | |
86 | bu32 multi_pc; | |
87 | ||
99265d6b MF |
88 | /* Some insns are valid in group1, and others in group2, so we |
89 | need to keep track of the exact slot we're processing. */ | |
90 | enum bfin_parallel_group group; | |
91 | ||
ef016f83 MF |
92 | /* Needed for supporting the DISALGNEXCPT instruction */ |
93 | int dis_algn_expt; | |
94 | ||
95 | /* See notes above for struct store. */ | |
96 | struct store stores[20]; | |
97 | int n_stores; | |
98 | ||
99 | #if (WITH_HW) | |
100 | /* Cache heavily used CPU-specific device pointers. */ | |
101 | void *cec_cache; | |
102 | void *evt_cache; | |
103 | void *mmu_cache; | |
104 | void *trace_cache; | |
105 | #endif | |
106 | }; | |
107 | ||
108 | #define REG_H_L(h, l) (((h) & 0xffff0000) | ((l) & 0x0000ffff)) | |
109 | ||
110 | #define DREG(x) (BFIN_CPU_STATE.dpregs[x]) | |
111 | #define PREG(x) (BFIN_CPU_STATE.dpregs[x + 8]) | |
112 | #define SPREG PREG (6) | |
113 | #define FPREG PREG (7) | |
114 | #define IREG(x) (BFIN_CPU_STATE.iregs[x]) | |
115 | #define MREG(x) (BFIN_CPU_STATE.mregs[x]) | |
116 | #define BREG(x) (BFIN_CPU_STATE.bregs[x]) | |
117 | #define LREG(x) (BFIN_CPU_STATE.lregs[x]) | |
118 | #define AXREG(x) (BFIN_CPU_STATE.ax[x]) | |
119 | #define AWREG(x) (BFIN_CPU_STATE.aw[x]) | |
120 | #define CCREG (BFIN_CPU_STATE.cc) | |
121 | #define LCREG(x) (BFIN_CPU_STATE.lc[x]) | |
122 | #define LTREG(x) (BFIN_CPU_STATE.lt[x]) | |
123 | #define LBREG(x) (BFIN_CPU_STATE.lb[x]) | |
124 | #define CYCLESREG (BFIN_CPU_STATE.cycles[0]) | |
125 | #define CYCLES2REG (BFIN_CPU_STATE.cycles[1]) | |
126 | #define CYCLES2SHDREG (BFIN_CPU_STATE.cycles[2]) | |
127 | #define KSPREG (BFIN_CPU_STATE.ksp) | |
128 | #define USPREG (BFIN_CPU_STATE.usp) | |
129 | #define SEQSTATREG (BFIN_CPU_STATE.seqstat) | |
130 | #define SYSCFGREG (BFIN_CPU_STATE.syscfg) | |
131 | #define RETSREG (BFIN_CPU_STATE.rets) | |
132 | #define RETIREG (BFIN_CPU_STATE.reti) | |
133 | #define RETXREG (BFIN_CPU_STATE.retx) | |
134 | #define RETNREG (BFIN_CPU_STATE.retn) | |
135 | #define RETEREG (BFIN_CPU_STATE.rete) | |
136 | #define PCREG (BFIN_CPU_STATE.pc) | |
137 | #define EMUDAT_INREG (BFIN_CPU_STATE.emudat[0]) | |
138 | #define EMUDAT_OUTREG (BFIN_CPU_STATE.emudat[1]) | |
139 | #define INSN_LEN (BFIN_CPU_STATE.insn_len) | |
99265d6b | 140 | #define PARALLEL_GROUP (BFIN_CPU_STATE.group) |
ef016f83 MF |
141 | #define CYCLE_DELAY (BFIN_CPU_STATE.cycle_delay) |
142 | #define DIS_ALGN_EXPT (BFIN_CPU_STATE.dis_algn_expt) | |
143 | ||
144 | #define EXCAUSE_SHIFT 0 | |
145 | #define EXCAUSE_MASK (0x3f << EXCAUSE_SHIFT) | |
146 | #define EXCAUSE ((SEQSTATREG & EXCAUSE_MASK) >> EXCAUSE_SHIFT) | |
147 | #define HWERRCAUSE_SHIFT 14 | |
148 | #define HWERRCAUSE_MASK (0x1f << HWERRCAUSE_SHIFT) | |
149 | #define HWERRCAUSE ((SEQSTATREG & HWERRCAUSE_MASK) >> HWERRCAUSE_SHIFT) | |
150 | ||
151 | #define _SET_CORE32REG_IDX(reg, p, x, val) \ | |
152 | do { \ | |
153 | bu32 __v = (val); \ | |
154 | TRACE_REGISTER (cpu, "wrote "#p"%i = %#x", x, __v); \ | |
155 | reg = __v; \ | |
156 | } while (0) | |
157 | #define SET_DREG(x, val) _SET_CORE32REG_IDX (DREG (x), R, x, val) | |
158 | #define SET_PREG(x, val) _SET_CORE32REG_IDX (PREG (x), P, x, val) | |
159 | #define SET_IREG(x, val) _SET_CORE32REG_IDX (IREG (x), I, x, val) | |
160 | #define SET_MREG(x, val) _SET_CORE32REG_IDX (MREG (x), M, x, val) | |
161 | #define SET_BREG(x, val) _SET_CORE32REG_IDX (BREG (x), B, x, val) | |
162 | #define SET_LREG(x, val) _SET_CORE32REG_IDX (LREG (x), L, x, val) | |
163 | #define SET_LCREG(x, val) _SET_CORE32REG_IDX (LCREG (x), LC, x, val) | |
164 | #define SET_LTREG(x, val) _SET_CORE32REG_IDX (LTREG (x), LT, x, val) | |
165 | #define SET_LBREG(x, val) _SET_CORE32REG_IDX (LBREG (x), LB, x, val) | |
166 | ||
167 | #define SET_DREG_L_H(x, l, h) SET_DREG (x, REG_H_L (h, l)) | |
168 | #define SET_DREG_L(x, l) SET_DREG (x, REG_H_L (DREG (x), l)) | |
169 | #define SET_DREG_H(x, h) SET_DREG (x, REG_H_L (h, DREG (x))) | |
170 | ||
171 | #define _SET_CORE32REG_ALU(reg, p, x, val) \ | |
172 | do { \ | |
173 | bu32 __v = (val); \ | |
174 | TRACE_REGISTER (cpu, "wrote A%i"#p" = %#x", x, __v); \ | |
175 | reg = __v; \ | |
176 | } while (0) | |
177 | #define SET_AXREG(x, val) _SET_CORE32REG_ALU (AXREG (x), X, x, val) | |
178 | #define SET_AWREG(x, val) _SET_CORE32REG_ALU (AWREG (x), W, x, val) | |
179 | ||
180 | #define SET_AREG(x, val) \ | |
181 | do { \ | |
182 | bu40 __a = (val); \ | |
183 | SET_AXREG (x, (__a >> 32) & 0xff); \ | |
184 | SET_AWREG (x, __a); \ | |
185 | } while (0) | |
186 | #define SET_AREG32(x, val) \ | |
187 | do { \ | |
188 | SET_AWREG (x, val); \ | |
189 | SET_AXREG (x, -(AWREG (x) >> 31)); \ | |
190 | } while (0) | |
191 | ||
192 | #define _SET_CORE32REG(reg, val) \ | |
193 | do { \ | |
194 | bu32 __v = (val); \ | |
195 | TRACE_REGISTER (cpu, "wrote "#reg" = %#x", __v); \ | |
196 | reg##REG = __v; \ | |
197 | } while (0) | |
198 | #define SET_FPREG(val) _SET_CORE32REG (FP, val) | |
199 | #define SET_SPREG(val) _SET_CORE32REG (SP, val) | |
200 | #define SET_CYCLESREG(val) _SET_CORE32REG (CYCLES, val) | |
201 | #define SET_CYCLES2REG(val) _SET_CORE32REG (CYCLES2, val) | |
202 | #define SET_CYCLES2SHDREG(val) _SET_CORE32REG (CYCLES2SHD, val) | |
203 | #define SET_KSPREG(val) _SET_CORE32REG (KSP, val) | |
204 | #define SET_USPREG(val) _SET_CORE32REG (USP, val) | |
205 | #define SET_SYSCFGREG(val) _SET_CORE32REG (SYSCFG, val) | |
206 | #define SET_RETSREG(val) _SET_CORE32REG (RETS, val) | |
207 | #define SET_RETIREG(val) _SET_CORE32REG (RETI, val) | |
208 | #define SET_RETXREG(val) _SET_CORE32REG (RETX, val) | |
209 | #define SET_RETNREG(val) _SET_CORE32REG (RETN, val) | |
210 | #define SET_RETEREG(val) _SET_CORE32REG (RETE, val) | |
211 | #define SET_PCREG(val) _SET_CORE32REG (PC, val) | |
212 | ||
213 | #define _SET_CORE32REGFIELD(reg, field, val, mask, shift) \ | |
214 | do { \ | |
215 | bu32 __f = (val); \ | |
216 | bu32 __v = ((reg##REG) & ~(mask)) | (__f << (shift)); \ | |
217 | TRACE_REGISTER (cpu, "wrote "#field" = %#x ("#reg" = %#x)", __f, __v); \ | |
218 | reg##REG = __v; \ | |
219 | } while (0) | |
220 | #define SET_SEQSTATREG(val) _SET_CORE32REG (SEQSTAT, val) | |
221 | #define SET_EXCAUSE(excp) _SET_CORE32REGFIELD (SEQSTAT, EXCAUSE, excp, EXCAUSE_MASK, EXCAUSE_SHIFT) | |
222 | #define SET_HWERRCAUSE(hwerr) _SET_CORE32REGFIELD (SEQSTAT, HWERRCAUSE, hwerr, HWERRCAUSE_MASK, HWERRCAUSE_SHIFT) | |
223 | ||
224 | #define AZ_BIT 0 | |
225 | #define AN_BIT 1 | |
226 | #define AC0_COPY_BIT 2 | |
227 | #define V_COPY_BIT 3 | |
228 | #define CC_BIT 5 | |
229 | #define AQ_BIT 6 | |
230 | #define RND_MOD_BIT 8 | |
231 | #define AC0_BIT 12 | |
232 | #define AC1_BIT 13 | |
233 | #define AV0_BIT 16 | |
234 | #define AV0S_BIT 17 | |
235 | #define AV1_BIT 18 | |
236 | #define AV1S_BIT 19 | |
237 | #define V_BIT 24 | |
238 | #define VS_BIT 25 | |
239 | #define ASTAT_DEFINED_BITS \ | |
240 | ((1 << AZ_BIT) | (1 << AN_BIT) | (1 << AC0_COPY_BIT) | (1 << V_COPY_BIT) \ | |
241 | |(1 << CC_BIT) | (1 << AQ_BIT) \ | |
242 | |(1 << RND_MOD_BIT) \ | |
243 | |(1 << AC0_BIT) | (1 << AC1_BIT) \ | |
244 | |(1 << AV0_BIT) | (1 << AV0S_BIT) | (1 << AV1_BIT) | (1 << AV1S_BIT) \ | |
245 | |(1 << V_BIT) | (1 << VS_BIT)) | |
246 | ||
247 | #define ASTATREG(field) (BFIN_CPU_STATE.field) | |
248 | #define ASTAT_DEPOSIT(field, bit) (ASTATREG(field) << (bit)) | |
249 | #define ASTAT \ | |
250 | (ASTAT_DEPOSIT(az, AZ_BIT) \ | |
251 | |ASTAT_DEPOSIT(an, AN_BIT) \ | |
252 | |ASTAT_DEPOSIT(ac0_copy, AC0_COPY_BIT) \ | |
253 | |ASTAT_DEPOSIT(v_copy, V_COPY_BIT) \ | |
254 | |ASTAT_DEPOSIT(cc, CC_BIT) \ | |
255 | |ASTAT_DEPOSIT(aq, AQ_BIT) \ | |
256 | |ASTAT_DEPOSIT(rnd_mod, RND_MOD_BIT) \ | |
257 | |ASTAT_DEPOSIT(ac0, AC0_BIT) \ | |
258 | |ASTAT_DEPOSIT(ac1, AC1_BIT) \ | |
259 | |ASTAT_DEPOSIT(av0, AV0_BIT) \ | |
260 | |ASTAT_DEPOSIT(av0s, AV0S_BIT) \ | |
261 | |ASTAT_DEPOSIT(av1, AV1_BIT) \ | |
262 | |ASTAT_DEPOSIT(av1s, AV1S_BIT) \ | |
263 | |ASTAT_DEPOSIT(v, V_BIT) \ | |
264 | |ASTAT_DEPOSIT(vs, VS_BIT) \ | |
265 | |ASTATREG(astat_reserved)) | |
266 | ||
267 | #define ASTAT_EXTRACT(a, bit) (((a) >> bit) & 1) | |
268 | #define _SET_ASTAT(a, field, bit) (ASTATREG(field) = ASTAT_EXTRACT(a, bit)) | |
269 | #define SET_ASTAT(a) \ | |
270 | do { \ | |
271 | TRACE_REGISTER (cpu, "wrote ASTAT = %#x", a); \ | |
272 | _SET_ASTAT(a, az, AZ_BIT); \ | |
273 | _SET_ASTAT(a, an, AN_BIT); \ | |
274 | _SET_ASTAT(a, ac0_copy, AC0_COPY_BIT); \ | |
275 | _SET_ASTAT(a, v_copy, V_COPY_BIT); \ | |
276 | _SET_ASTAT(a, cc, CC_BIT); \ | |
277 | _SET_ASTAT(a, aq, AQ_BIT); \ | |
278 | _SET_ASTAT(a, rnd_mod, RND_MOD_BIT); \ | |
279 | _SET_ASTAT(a, ac0, AC0_BIT); \ | |
280 | _SET_ASTAT(a, ac1, AC1_BIT); \ | |
281 | _SET_ASTAT(a, av0, AV0_BIT); \ | |
282 | _SET_ASTAT(a, av0s, AV0S_BIT); \ | |
283 | _SET_ASTAT(a, av1, AV1_BIT); \ | |
284 | _SET_ASTAT(a, av1s, AV1S_BIT); \ | |
285 | _SET_ASTAT(a, v, V_BIT); \ | |
286 | _SET_ASTAT(a, vs, VS_BIT); \ | |
287 | ASTATREG(astat_reserved) = (a) & ~ASTAT_DEFINED_BITS; \ | |
288 | } while (0) | |
289 | #define SET_ASTATREG(field, val) \ | |
290 | do { \ | |
291 | int __v = !!(val); \ | |
292 | TRACE_REGISTER (cpu, "wrote ASTAT["#field"] = %i", __v); \ | |
293 | ASTATREG (field) = __v; \ | |
294 | if (&ASTATREG (field) == &ASTATREG (ac0)) \ | |
295 | { \ | |
296 | TRACE_REGISTER (cpu, "wrote ASTAT["#field"_copy] = %i", __v); \ | |
297 | ASTATREG (ac0_copy) = __v; \ | |
298 | } \ | |
299 | else if (&ASTATREG (field) == &ASTATREG (v)) \ | |
300 | { \ | |
301 | TRACE_REGISTER (cpu, "wrote ASTAT["#field"_copy] = %i", __v); \ | |
302 | ASTATREG (v_copy) = __v; \ | |
303 | } \ | |
304 | } while (0) | |
305 | #define SET_CCREG(val) SET_ASTATREG (cc, val) | |
306 | ||
307 | #define SYSCFG_SSSTEP (1 << 0) | |
308 | #define SYSCFG_CCEN (1 << 1) | |
309 | #define SYSCFG_SNEN (1 << 2) | |
310 | ||
311 | #define __PUT_MEM(taddr, v, size) \ | |
312 | do { \ | |
313 | bu##size __v = (v); \ | |
314 | bu32 __taddr = (taddr); \ | |
315 | int __cnt, __bytes = size / 8; \ | |
316 | mmu_check_addr (cpu, __taddr, true, false, __bytes); \ | |
317 | __cnt = sim_core_write_buffer (CPU_STATE(cpu), cpu, write_map, \ | |
318 | (void *)&__v, __taddr, __bytes); \ | |
319 | if (__cnt != __bytes) \ | |
320 | mmu_process_fault (cpu, __taddr, true, false, false, true); \ | |
bb11f3ed | 321 | BFIN_TRACE_CORE (cpu, __taddr, __bytes, write_map, __v); \ |
ef016f83 MF |
322 | } while (0) |
323 | #define PUT_BYTE(taddr, v) __PUT_MEM(taddr, v, 8) | |
324 | #define PUT_WORD(taddr, v) __PUT_MEM(taddr, v, 16) | |
325 | #define PUT_LONG(taddr, v) __PUT_MEM(taddr, v, 32) | |
326 | ||
327 | #define __GET_MEM(taddr, size, inst, map) \ | |
328 | ({ \ | |
329 | bu##size __ret; \ | |
330 | bu32 __taddr = (taddr); \ | |
331 | int __cnt, __bytes = size / 8; \ | |
332 | mmu_check_addr (cpu, __taddr, false, inst, __bytes); \ | |
333 | __cnt = sim_core_read_buffer (CPU_STATE(cpu), cpu, map, \ | |
334 | (void *)&__ret, __taddr, __bytes); \ | |
335 | if (__cnt != __bytes) \ | |
336 | mmu_process_fault (cpu, __taddr, false, inst, false, true); \ | |
bb11f3ed | 337 | BFIN_TRACE_CORE (cpu, __taddr, __bytes, map, __ret); \ |
ef016f83 MF |
338 | __ret; \ |
339 | }) | |
340 | #define _GET_MEM(taddr, size) __GET_MEM(taddr, size, false, read_map) | |
341 | #define GET_BYTE(taddr) _GET_MEM(taddr, 8) | |
342 | #define GET_WORD(taddr) _GET_MEM(taddr, 16) | |
343 | #define GET_LONG(taddr) _GET_MEM(taddr, 32) | |
344 | ||
345 | #define IFETCH(taddr) __GET_MEM(taddr, 16, true, exec_map) | |
346 | #define IFETCH_CHECK(taddr) mmu_check_addr (cpu, taddr, false, true, 2) | |
347 | ||
348 | extern void bfin_syscall (SIM_CPU *); | |
349 | extern bu32 interp_insn_bfin (SIM_CPU *, bu32); | |
350 | extern bu32 hwloop_get_next_pc (SIM_CPU *, bu32, bu32); | |
351 | ||
352 | /* Defines for Blackfin memory layouts. */ | |
353 | #define BFIN_ASYNC_BASE 0x20000000 | |
354 | #define BFIN_SYSTEM_MMR_BASE 0xFFC00000 | |
355 | #define BFIN_CORE_MMR_BASE 0xFFE00000 | |
356 | #define BFIN_L1_SRAM_SCRATCH 0xFFB00000 | |
357 | #define BFIN_L1_SRAM_SCRATCH_SIZE 0x1000 | |
358 | #define BFIN_L1_SRAM_SCRATCH_END (BFIN_L1_SRAM_SCRATCH + BFIN_L1_SRAM_SCRATCH_SIZE) | |
359 | ||
360 | #define BFIN_L1_CACHE_BYTES 32 | |
361 | ||
362 | #endif |