1 |
#ifndef CPU_MIPS_H |
2 |
#define CPU_MIPS_H |
3 |
|
4 |
/* |
5 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or without |
8 |
* modification, are permitted provided that the following conditions are met: |
9 |
* |
10 |
* 1. Redistributions of source code must retain the above copyright |
11 |
* notice, this list of conditions and the following disclaimer. |
12 |
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
* notice, this list of conditions and the following disclaimer in the |
14 |
* documentation and/or other materials provided with the distribution. |
15 |
* 3. The name of the author may not be used to endorse or promote products |
16 |
* derived from this software without specific prior written permission. |
17 |
* |
18 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
19 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
21 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
22 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
24 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 |
* SUCH DAMAGE. |
29 |
* |
30 |
* |
31 |
* $Id: cpu_mips.h,v 1.21 2005/08/28 20:16:24 debug Exp $ |
32 |
*/ |
33 |
|
34 |
#include "misc.h" |
35 |
|
36 |
/* |
37 |
* ENABLE_MIPS16 should be defined on the cc commandline using -D, if you |
38 |
* want it. (This is done by ./configure --mips16) |
39 |
*/ |
40 |
/* #define MFHILO_DELAY */ |
41 |
|
42 |
struct cpu_family; |
43 |
struct emul; |
44 |
struct machine; |
45 |
|
46 |
/* |
47 |
* CPU type definitions: See mips_cpu_types.h. |
48 |
*/ |
49 |
|
50 |
struct mips_cpu_type_def { |
51 |
char *name; |
52 |
int rev; |
53 |
int sub; |
54 |
char flags; |
55 |
char exc_model; /* EXC3K or EXC4K */ |
56 |
char mmu_model; /* MMU3K or MMU4K */ |
57 |
char isa_level; /* 1, 2, 3, 4, 5, 32, 64 */ |
58 |
int nr_of_tlb_entries; /* 32, 48, 64, ... */ |
59 |
char instrs_per_cycle; /* simplified, 1, 2, or 4 */ |
60 |
int picache; |
61 |
int pilinesize; |
62 |
int piways; |
63 |
int pdcache; |
64 |
int pdlinesize; |
65 |
int pdways; |
66 |
int scache; |
67 |
int slinesize; |
68 |
int sways; |
69 |
}; |
70 |
|
71 |
#define INITIAL_PC 0xffffffffbfc00000ULL |
72 |
#define INITIAL_STACK_POINTER (0xffffffffa0008000ULL - 256) |
73 |
|
74 |
|
75 |
/* |
76 |
* Coproc 0: |
77 |
*/ |
78 |
#define N_MIPS_COPROC_REGS 32 |
79 |
struct mips_tlb { |
80 |
uint64_t hi; |
81 |
uint64_t lo0; |
82 |
uint64_t lo1; |
83 |
uint64_t mask; |
84 |
}; |
85 |
|
86 |
|
87 |
/* |
88 |
* Coproc 1: |
89 |
*/ |
90 |
#define N_MIPS_FCRS 32 |
91 |
|
92 |
struct mips_coproc { |
93 |
int coproc_nr; |
94 |
uint64_t reg[N_MIPS_COPROC_REGS]; |
95 |
|
96 |
/* Only for COP0: */ |
97 |
struct mips_tlb *tlbs; |
98 |
int nr_of_tlbs; |
99 |
|
100 |
/* Only for COP1: floating point control registers */ |
101 |
/* (Maybe also for COP0?) */ |
102 |
uint64_t fcr[N_MIPS_FCRS]; |
103 |
}; |
104 |
|
105 |
#define N_MIPS_COPROCS 4 |
106 |
|
107 |
#define N_MIPS_GPRS 32 /* General purpose registers */ |
108 |
#define N_MIPS_FPRS 32 /* Floating point registers */ |
109 |
|
110 |
/* |
111 |
* These should all be 2 characters wide: |
112 |
* |
113 |
* NOTE: These are for 32-bit ABIs. For the 64-bit ABI, registers 8..11 |
114 |
* are used to pass arguments and are then called "a4".."a7". |
115 |
* |
116 |
* TODO: Should there be two different variants of this? It's not really |
117 |
* possible to figure out in some easy way if the code running was |
118 |
* written for a 32-bit or 64-bit ABI. |
119 |
*/ |
120 |
#define MIPS_REGISTER_NAMES { \ |
121 |
"zr", "at", "v0", "v1", "a0", "a1", "a2", "a3", \ |
122 |
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \ |
123 |
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \ |
124 |
"t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" } |
125 |
|
126 |
#define MIPS_GPR_ZERO 0 /* zero */ |
127 |
#define MIPS_GPR_AT 1 /* at */ |
128 |
#define MIPS_GPR_V0 2 /* v0 */ |
129 |
#define MIPS_GPR_V1 3 /* v1 */ |
130 |
#define MIPS_GPR_A0 4 /* a0 */ |
131 |
#define MIPS_GPR_A1 5 /* a1 */ |
132 |
#define MIPS_GPR_A2 6 /* a2 */ |
133 |
#define MIPS_GPR_A3 7 /* a3 */ |
134 |
#define MIPS_GPR_T0 8 /* t0 */ |
135 |
#define MIPS_GPR_T1 9 /* t1 */ |
136 |
#define MIPS_GPR_T2 10 /* t2 */ |
137 |
#define MIPS_GPR_T3 11 /* t3 */ |
138 |
#define MIPS_GPR_T4 12 /* t4 */ |
139 |
#define MIPS_GPR_T5 13 /* t5 */ |
140 |
#define MIPS_GPR_T6 14 /* t6 */ |
141 |
#define MIPS_GPR_T7 15 /* t7 */ |
142 |
#define MIPS_GPR_S0 16 /* s0 */ |
143 |
#define MIPS_GPR_S1 17 /* s1 */ |
144 |
#define MIPS_GPR_S2 18 /* s2 */ |
145 |
#define MIPS_GPR_S3 19 /* s3 */ |
146 |
#define MIPS_GPR_S4 20 /* s4 */ |
147 |
#define MIPS_GPR_S5 21 /* s5 */ |
148 |
#define MIPS_GPR_S6 22 /* s6 */ |
149 |
#define MIPS_GPR_S7 23 /* s7 */ |
150 |
#define MIPS_GPR_T8 24 /* t8 */ |
151 |
#define MIPS_GPR_T9 25 /* t9 */ |
152 |
#define MIPS_GPR_K0 26 /* k0 */ |
153 |
#define MIPS_GPR_K1 27 /* k1 */ |
154 |
#define MIPS_GPR_GP 28 /* gp */ |
155 |
#define MIPS_GPR_SP 29 /* sp */ |
156 |
#define MIPS_GPR_FP 30 /* fp */ |
157 |
#define MIPS_GPR_RA 31 /* ra */ |
158 |
|
159 |
/* Meaning of delay_slot: */ |
160 |
#define NOT_DELAYED 0 |
161 |
#define DELAYED 1 |
162 |
#define TO_BE_DELAYED 2 |
163 |
|
164 |
#define N_HI6 64 |
165 |
#define N_SPECIAL 64 |
166 |
#define N_REGIMM 32 |
167 |
|
168 |
/* Number of "tiny" translation cache entries: */ |
169 |
#define N_TRANSLATION_CACHE_INSTR 5 |
170 |
#define N_TRANSLATION_CACHE_DATA 5 |
171 |
|
172 |
struct translation_cache_entry { |
173 |
int wf; |
174 |
uint64_t vaddr_pfn; |
175 |
uint64_t paddr; |
176 |
}; |
177 |
|
178 |
/* This should be a value which the program counter |
179 |
can "never" have: */ |
180 |
#define PC_LAST_PAGE_IMPOSSIBLE_VALUE 3 |
181 |
|
182 |
/* An "impossible" paddr: */ |
183 |
#define IMPOSSIBLE_PADDR 0x1212343456566767ULL |
184 |
|
185 |
#define DEFAULT_PCACHE_SIZE 15 /* 32 KB */ |
186 |
#define DEFAULT_PCACHE_LINESIZE 5 /* 32 bytes */ |
187 |
|
188 |
struct r3000_cache_line { |
189 |
uint32_t tag_paddr; |
190 |
int tag_valid; |
191 |
}; |
192 |
#define R3000_TAG_VALID 1 |
193 |
#define R3000_TAG_DIRTY 2 |
194 |
|
195 |
struct r4000_cache_line { |
196 |
char dummy; |
197 |
}; |
198 |
|
199 |
#define BINTRANS_DONT_RUN_NEXT 0x1000000 |
200 |
#define BINTRANS_N_MASK 0x0ffffff |
201 |
|
202 |
#define N_SAFE_BINTRANS_LIMIT_SHIFT 14 |
203 |
#define N_SAFE_BINTRANS_LIMIT ((1 << (N_SAFE_BINTRANS_LIMIT_SHIFT - 1)) - 1) |
204 |
|
205 |
#define N_BINTRANS_VADDR_TO_HOST 20 |
206 |
|
207 |
/* Virtual to host address translation tables: */ |
208 |
struct vth32_table { |
209 |
void *haddr_entry[1024 * 2]; |
210 |
uint32_t paddr_entry[1024]; |
211 |
uint32_t *bintrans_chunks[1024]; |
212 |
struct vth32_table *next_free; |
213 |
int refcount; |
214 |
}; |
215 |
|
216 |
struct mips_cpu { |
217 |
struct mips_cpu_type_def cpu_type; |
218 |
|
219 |
struct mips_coproc *coproc[N_MIPS_COPROCS]; |
220 |
|
221 |
int compare_register_set; |
222 |
|
223 |
/* Special purpose registers: */ |
224 |
uint64_t pc_last; /* PC of last instruction */ |
225 |
uint64_t hi; |
226 |
uint64_t lo; |
227 |
|
228 |
/* General purpose registers: */ |
229 |
uint64_t gpr[N_MIPS_GPRS]; |
230 |
|
231 |
/* |
232 |
* The translation_cached stuff is used to speed up the |
233 |
* most recent lookups into the TLB. Whenever the TLB is |
234 |
* written to, translation_cached[] must be filled with zeros. |
235 |
*/ |
236 |
#ifdef USE_TINY_CACHE |
237 |
struct translation_cache_entry |
238 |
translation_cache_instr[N_TRANSLATION_CACHE_INSTR]; |
239 |
struct translation_cache_entry |
240 |
translation_cache_data[N_TRANSLATION_CACHE_DATA]; |
241 |
#endif |
242 |
|
243 |
/* |
244 |
* For faster memory lookup when running instructions: |
245 |
* |
246 |
* Reading memory to load instructions is a very common thing in the |
247 |
* emulator, and an instruction is very often read from the address |
248 |
* following the previously executed instruction. That means that we |
249 |
* don't have to go through the TLB each time. |
250 |
* |
251 |
* We then get the vaddr -> paddr translation for free. There is an |
252 |
* even better case when the paddr is a RAM address (as opposed to an |
253 |
* address in a memory mapped device). Then we can figure out the |
254 |
* address in the host's memory directly, and skip the paddr -> host |
255 |
* address calculation as well. |
256 |
* |
257 |
* A modification to the TLB should set the virtual_page variable to |
258 |
* an "impossible" value, so that there won't be a hit on the next |
259 |
* instruction. |
260 |
*/ |
261 |
uint64_t pc_last_virtual_page; |
262 |
uint64_t pc_last_physical_page; |
263 |
unsigned char *pc_last_host_4k_page; |
264 |
|
265 |
/* MIPS Bintrans: */ |
266 |
int dont_run_next_bintrans; |
267 |
int bintrans_instructions_executed; /* set to the |
268 |
number of bintranslated instructions executed |
269 |
when running a bintrans codechunk */ |
270 |
int pc_bintrans_paddr_valid; |
271 |
uint64_t pc_bintrans_paddr; |
272 |
unsigned char *pc_bintrans_host_4kpage; |
273 |
|
274 |
/* Chunk base address: */ |
275 |
unsigned char *chunk_base_address; |
276 |
|
277 |
/* This should work for 32-bit MIPS emulation: */ |
278 |
struct vth32_table *vaddr_to_hostaddr_nulltable; |
279 |
struct vth32_table *vaddr_to_hostaddr_r2k3k_icachetable; |
280 |
struct vth32_table *vaddr_to_hostaddr_r2k3k_dcachetable; |
281 |
struct vth32_table **vaddr_to_hostaddr_table0_kernel; |
282 |
struct vth32_table **vaddr_to_hostaddr_table0_cacheisol_i; |
283 |
struct vth32_table **vaddr_to_hostaddr_table0_cacheisol_d; |
284 |
struct vth32_table **vaddr_to_hostaddr_table0_user; |
285 |
struct vth32_table **vaddr_to_hostaddr_table0; /* should point to kernel or user */ |
286 |
struct vth32_table *next_free_vth_table; |
287 |
|
288 |
/* Testing... */ |
289 |
unsigned char **host_load; |
290 |
unsigned char **host_store; |
291 |
unsigned char **host_load_orig; |
292 |
unsigned char **host_store_orig; |
293 |
unsigned char **huge_r2k3k_cache_table; |
294 |
|
295 |
/* For 64-bit (generic) emulation: */ |
296 |
unsigned char *(*fast_vaddr_to_hostaddr)(struct cpu *cpu, |
297 |
uint64_t vaddr, int writeflag); |
298 |
int bintrans_next_index; |
299 |
int bintrans_data_writable[N_BINTRANS_VADDR_TO_HOST]; |
300 |
uint64_t bintrans_data_vaddr[N_BINTRANS_VADDR_TO_HOST]; |
301 |
unsigned char *bintrans_data_hostpage[N_BINTRANS_VADDR_TO_HOST]; |
302 |
|
303 |
void (*bintrans_load_32bit)(struct cpu *); /* Note: incorrect args */ |
304 |
void (*bintrans_store_32bit)(struct cpu *); /* Note: incorrect args */ |
305 |
void (*bintrans_jump_to_32bit_pc)(struct cpu *); |
306 |
void (*bintrans_simple_exception)(struct cpu *, int); |
307 |
void (*bintrans_fast_rfe)(struct cpu *); |
308 |
void (*bintrans_fast_eret)(struct cpu *); |
309 |
void (*bintrans_fast_tlbwri)(struct cpu *, int); |
310 |
void (*bintrans_fast_tlbpr)(struct cpu *, int); |
311 |
|
312 |
#ifdef ENABLE_MIPS16 |
313 |
int mips16; /* non-zero if MIPS16 code is allowed */ |
314 |
uint16_t mips16_extend; /* set on 'extend' instructions to the entire 16-bit extend instruction */ |
315 |
#endif |
316 |
|
317 |
#ifdef ENABLE_INSTRUCTION_DELAYS |
318 |
int instruction_delay; |
319 |
#endif |
320 |
|
321 |
uint64_t delay_jmpaddr; /* only used if delay_slot > 0 */ |
322 |
int delay_slot; |
323 |
int nullify_next; /* set to 1 if next instruction |
324 |
is to be nullified */ |
325 |
|
326 |
/* This is set to non-zero, if it is possible at all that an |
327 |
interrupt will occur. */ |
328 |
int cached_interrupt_is_possible; |
329 |
|
330 |
int show_trace_delay; /* 0=normal, > 0 = delay until show_trace */ |
331 |
uint64_t show_trace_addr; |
332 |
|
333 |
int last_was_jumptoself; |
334 |
int jump_to_self_reg; |
335 |
|
336 |
#ifdef MFHILO_DELAY |
337 |
int mfhi_delay; /* instructions since last mfhi */ |
338 |
int mflo_delay; /* instructions since last mflo */ |
339 |
#endif |
340 |
|
341 |
int rmw; /* Read-Modify-Write */ |
342 |
int rmw_len; /* Length of rmw modification */ |
343 |
uint64_t rmw_addr; /* Address of rmw modification */ |
344 |
|
345 |
/* |
346 |
* TODO: The R5900 has 128-bit registers. I'm not really sure |
347 |
* whether they are used a lot or not, at least with code produced |
348 |
* with gcc they are not. An important case however is lq and sq |
349 |
* (load and store of 128-bit values). These "upper halves" of R5900 |
350 |
* quadwords can be used in those cases. |
351 |
* |
352 |
* TODO: Generalize this. |
353 |
*/ |
354 |
uint64_t gpr_quadhi[N_MIPS_GPRS]; |
355 |
|
356 |
|
357 |
/* |
358 |
* Statistics: |
359 |
*/ |
360 |
long stats_opcode[N_HI6]; |
361 |
long stats__special[N_SPECIAL]; |
362 |
long stats__regimm[N_REGIMM]; |
363 |
long stats__special2[N_SPECIAL]; |
364 |
|
365 |
/* Data and Instruction caches: */ |
366 |
unsigned char *cache[2]; |
367 |
void *cache_tags[2]; |
368 |
uint64_t cache_last_paddr[2]; |
369 |
int cache_size[2]; |
370 |
int cache_linesize[2]; |
371 |
int cache_mask[2]; |
372 |
int cache_miss_penalty[2]; |
373 |
|
374 |
/* Other stuff: */ |
375 |
uint64_t cop0_config_select1; |
376 |
}; |
377 |
|
378 |
|
379 |
/* cpu_mips.c: */ |
380 |
void mips_cpu_show_full_statistics(struct machine *m); |
381 |
void mips_cpu_tlbdump(struct machine *m, int x, int rawflag); |
382 |
void mips_cpu_register_match(struct machine *m, char *name, |
383 |
int writeflag, uint64_t *valuep, int *match_register); |
384 |
void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs); |
385 |
int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr, |
386 |
int running, uint64_t addr, int bintrans); |
387 |
int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr); |
388 |
int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr); |
389 |
void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr, |
390 |
/* uint64_t pagemask, */ int coproc_nr, uint64_t vaddr_vpn2, |
391 |
int vaddr_asid, int x_64); |
392 |
void mips_cpu_cause_simple_exception(struct cpu *cpu, int exc_code); |
393 |
int mips_cpu_run(struct emul *emul, struct machine *machine); |
394 |
void mips_cpu_dumpinfo(struct cpu *cpu); |
395 |
void mips_cpu_list_available_types(void); |
396 |
int mips_cpu_family_init(struct cpu_family *); |
397 |
|
398 |
|
399 |
/* cpu_mips_coproc.c: */ |
400 |
struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr); |
401 |
void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size, |
402 |
uint64_t vaddr, uint64_t paddr0, uint64_t paddr1, |
403 |
int valid0, int valid1, int dirty0, int dirty1, int global, int asid, |
404 |
int cachealgo0, int cachealgo1); |
405 |
void mips_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
406 |
unsigned char *host_page, int writeflag, uint64_t paddr_page); |
407 |
void clear_all_chunks_from_all_tables(struct cpu *cpu); |
408 |
void mips_invalidate_translation_caches_paddr(struct cpu *cpu, uint64_t, int); |
409 |
void coproc_register_read(struct cpu *cpu, |
410 |
struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select); |
411 |
void coproc_register_write(struct cpu *cpu, |
412 |
struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64, |
413 |
int select); |
414 |
void coproc_tlbpr(struct cpu *cpu, int readflag); |
415 |
void coproc_tlbwri(struct cpu *cpu, int randomflag); |
416 |
void coproc_rfe(struct cpu *cpu); |
417 |
void coproc_eret(struct cpu *cpu); |
418 |
void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr, |
419 |
uint32_t function, int unassemble_only, int running); |
420 |
|
421 |
|
422 |
/* memory_mips.c: */ |
423 |
int memory_cache_R3000(struct cpu *cpu, int cache, uint64_t paddr, |
424 |
int writeflag, size_t len, unsigned char *data); |
425 |
int mips_memory_rw(struct cpu *cpu, struct memory *mem, uint64_t vaddr, |
426 |
unsigned char *data, size_t len, int writeflag, int cache_flags); |
427 |
|
428 |
|
429 |
/* mips16.c: */ |
430 |
int mips16_to_32(struct cpu *cpu, unsigned char *instr16, unsigned char *instr); |
431 |
|
432 |
|
433 |
#endif /* CPU_MIPS_H */ |