/[gxemul]/trunk/src/include/cpu.h
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/include/cpu.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 13891 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 #ifndef CPU_H
2 #define CPU_H
3
4 /*
5 * Copyright (C) 2005-2006 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.h,v 1.84 2006/07/20 21:53:00 debug Exp $
32 *
33 * CPU-related definitions.
34 */
35
36
37 #include <sys/types.h>
38 #include <inttypes.h>
39 #include <sys/time.h>
40
41 /* This is needed for undefining 'mips', 'ppc' etc. on weird systems: */
42 #include "../../config.h"
43
44 /*
45 * Dyntrans misc declarations, used throughout the dyntrans code.
46 *
47 * Note that there is place for all instruction calls within a page,
48 * and then 2 more. The first one of these "extra" instruction slots is
49 * the end-of-page slot. It transfers control to the first instruction
50 * slot on the next (virtual) page.
51 *
52 * The second of these extra instruction slots is an additional
53 * end-of-page slot for delay-slot architectures. On e.g. MIPS, a branch
54 * instruction can "nullify" (skip) the delay-slot. If the end-of-page
55 * slot is skipped, then we end up one step after that. That's where the
56 * end_of_page2 slot is. :)
57 *
58 * next_ofs points to the next page in a chain of possible pages.
59 * (several pages can be in the same chain, but only one matches the
60 * specific physaddr.)
61 *
62 * flags contains special flags. Currently only COMBINATIONS, which indicates
63 * that the page has instruction combinations.
64 *
65 * translations is a tiny bitmap indicating which parts of the page have
66 * actual translations. Bit 0 corresponds to the lowest 1/32th of the page,
67 * bit 1 to the second-lowest 1/32th, and so on.
68 */
69 #define DYNTRANS_MISC_DECLARATIONS(arch,ARCH,addrtype) struct \
70 arch ## _instr_call { \
71 void (*f)(struct cpu *, struct arch ## _instr_call *); \
72 size_t arg[ARCH ## _N_IC_ARGS]; \
73 }; \
74 \
75 /* Translation cache struct for each physical page: */ \
76 struct arch ## _tc_physpage { \
77 struct arch ## _instr_call ics[ARCH ## _IC_ENTRIES_PER_PAGE+2];\
78 uint32_t next_ofs; /* (0 for end of chain) */ \
79 uint32_t translations; \
80 int flags; \
81 addrtype physaddr; \
82 }; \
83 \
84 struct arch ## _vpg_tlb_entry { \
85 uint8_t valid; \
86 uint8_t writeflag; \
87 addrtype vaddr_page; \
88 addrtype paddr_page; \
89 unsigned char *host_page; \
90 int64_t timestamp; \
91 };
92
93 #define DYNTRANS_MISC64_DECLARATIONS(arch,ARCH,tlbindextype) \
94 struct arch ## _l3_64_table { \
95 unsigned char *host_load[1 << ARCH ## _L3N]; \
96 unsigned char *host_store[1 << ARCH ## _L3N]; \
97 uint64_t phys_addr[1 << ARCH ## _L3N]; \
98 tlbindextype vaddr_to_tlbindex[1 << ARCH ## _L3N]; \
99 struct arch ## _tc_physpage *phys_page[1 << ARCH ## _L3N]; \
100 struct arch ## _l3_64_table *next; \
101 int refcount; \
102 }; \
103 struct arch ## _l2_64_table { \
104 struct arch ## _l3_64_table *l3[1 << ARCH ## _L2N]; \
105 struct arch ## _l2_64_table *next; \
106 int refcount; \
107 };
108
109 /*
110 * Dyntrans "Instruction Translation Cache":
111 *
112 * cur_physpage is a pointer to the current physpage. (It _HAPPENS_ to
113 * be the same as cur_ic_page, because all the instrcalls should be placed
114 * first in the physpage struct!)
115 *
116 * cur_ic_page is a pointer to an array of xxx_IC_ENTRIES_PER_PAGE
117 * instruction call entries.
118 *
119 * next_ic points to the next such instruction call to be executed.
120 *
121 * combination_check, when set to non-NULL, is executed automatically after
122 * an instruction has been translated. (It check for combinations of
123 * instructions; low_addr is the offset of the translated instruction in the
124 * current page, NOT shifted right.)
125 */
126 #define DYNTRANS_ITC(arch) struct arch ## _tc_physpage *cur_physpage; \
127 struct arch ## _instr_call *cur_ic_page; \
128 struct arch ## _instr_call *next_ic; \
129 struct arch ## _tc_physpage *physpage_template;\
130 void (*combination_check)(struct cpu *, \
131 struct arch ## _instr_call *, int low_addr);
132
133 /*
134 * Virtual -> physical -> host address translation TLB entries:
135 * ------------------------------------------------------------
136 *
137 * Regardless of whether 32-bit or 64-bit address translation is used, the
138 * same TLB entry structure is used.
139 */
140 #define VPH_TLBS(arch,ARCH) \
141 struct arch ## _vpg_tlb_entry \
142 vph_tlb_entry[ARCH ## _MAX_VPH_TLB_ENTRIES];
143
144 /*
145 * 32-bit dyntrans emulated Virtual -> physical -> host address translation:
146 * -------------------------------------------------------------------------
147 *
148 * This stuff assumes that 4 KB pages are used. 20 bits to select a page
149 * means just 1 M entries needed. This is small enough that a couple of
150 * full-size tables can fit in virtual memory on modern hosts (both 32-bit
151 * and 64-bit hosts). :-)
152 *
153 * Usage: e.g. VPH32(arm,ARM,uint32_t,uint8_t)
154 * or VPH32(sparc,SPARC,uint64_t,uint16_t)
155 *
156 * The vph_tlb_entry entries are cpu dependent tlb entries.
157 *
158 * The host_load and host_store entries point to host pages; the phys_addr
159 * entries are uint32_t or uint64_t (emulated physical addresses).
160 *
161 * phys_page points to translation cache physpages.
162 *
163 * vaddr_to_tlbindex is a virtual address to tlb index hint table.
164 * The values in this array are the tlb index plus 1, so a value of, say,
165 * 3 means tlb index 2. A value of 0 would mean a tlb index of -1, which
166 * is not a valid index. (I.e. no hit.)
167 */
168 #define N_VPH32_ENTRIES 1048576
169 #define VPH32(arch,ARCH,paddrtype,tlbindextype) \
170 unsigned char *host_load[N_VPH32_ENTRIES]; \
171 unsigned char *host_store[N_VPH32_ENTRIES]; \
172 paddrtype phys_addr[N_VPH32_ENTRIES]; \
173 struct arch ## _tc_physpage *phys_page[N_VPH32_ENTRIES]; \
174 tlbindextype vaddr_to_tlbindex[N_VPH32_ENTRIES];
175
176 /*
177 * 64-bit dyntrans emulated Virtual -> physical -> host address translation:
178 * -------------------------------------------------------------------------
179 *
180 * Usage: e.g. VPH64(alpha,ALPHA,uint8_t)
181 * or VPH64(sparc,SPARC,uint16_t)
182 *
183 * l1_64 is an array containing poiners to l2 tables.
184 *
185 * l2_64_dummy is a pointer to a "dummy l2 table". Instead of having NULL
186 * pointers in l1_64 for unused slots, a pointer to the dummy table can be
187 * used.
188 */
189 #define DYNTRANS_L1N 17
190 #define VPH64(arch,ARCH,tlbindextype) \
191 struct arch ## _l3_64_table *l3_64_dummy; \
192 struct arch ## _l3_64_table *next_free_l3; \
193 struct arch ## _l2_64_table *l2_64_dummy; \
194 struct arch ## _l2_64_table *next_free_l2; \
195 struct arch ## _l2_64_table *l1_64[1 << DYNTRANS_L1N];
196
197
198 /* Include all CPUs' header files here: */
199 #include "cpu_alpha.h"
200 #include "cpu_arm.h"
201 #include "cpu_avr.h"
202 #include "cpu_hppa.h"
203 #include "cpu_i960.h"
204 #include "cpu_ia64.h"
205 #include "cpu_m68k.h"
206 #include "cpu_mips.h"
207 #include "cpu_ppc.h"
208 #include "cpu_sh.h"
209 #include "cpu_sparc.h"
210 #include "cpu_transputer.h"
211 #include "cpu_x86.h"
212
213 struct cpu;
214 struct emul;
215 struct machine;
216 struct memory;
217
218
219 struct cpu_family {
220 struct cpu_family *next;
221 int arch;
222
223 /* These are filled in by each CPU family's init function: */
224 char *name;
225 int (*cpu_new)(struct cpu *cpu, struct memory *mem,
226 struct machine *machine,
227 int cpu_id, char *cpu_type_name);
228 void (*list_available_types)(void);
229 void (*register_match)(struct machine *m,
230 char *name, int writeflag,
231 uint64_t *valuep, int *match_register);
232 int (*disassemble_instr)(struct cpu *cpu,
233 unsigned char *instr, int running,
234 uint64_t dumpaddr);
235 void (*register_dump)(struct cpu *cpu,
236 int gprs, int coprocs);
237 void (*dumpinfo)(struct cpu *cpu);
238 void (*tlbdump)(struct machine *m, int x,
239 int rawflag);
240 int (*interrupt)(struct cpu *cpu, uint64_t irq_nr);
241 int (*interrupt_ack)(struct cpu *cpu,
242 uint64_t irq_nr);
243 void (*functioncall_trace)(struct cpu *,
244 uint64_t f, int n_args);
245 char *(*gdb_stub)(struct cpu *, char *cmd);
246 void (*init_tables)(struct cpu *cpu);
247 };
248
249
250 /*
251 * More dyntrans stuff:
252 *
253 * The translation cache begins with N_BASE_TABLE_ENTRIES uint32_t offsets
254 * into the cache, for possible translation cache structs for physical pages.
255 */
256
257 /* Physpage flags: */
258 #define COMBINATIONS 1
259
260 /* Meaning of delay_slot: */
261 #define NOT_DELAYED 0
262 #define DELAYED 1
263 #define TO_BE_DELAYED 2
264 #define EXCEPTION_IN_DELAY_SLOT 0x100
265
266 #define N_SAFE_DYNTRANS_LIMIT_SHIFT 14
267 #define N_SAFE_DYNTRANS_LIMIT ((1 << (N_SAFE_DYNTRANS_LIMIT_SHIFT - 1)) - 1)
268
269 #define DYNTRANS_CACHE_SIZE (32*1048576)
270 #define DYNTRANS_CACHE_MARGIN 350000
271
272 #define N_BASE_TABLE_ENTRIES 32768
273 #define PAGENR_TO_TABLE_INDEX(a) ((a) & (N_BASE_TABLE_ENTRIES-1))
274
275
276 /*
277 * The generic CPU struct:
278 */
279
280 struct cpu {
281 /* Pointer back to the machine this CPU is in: */
282 struct machine *machine;
283
284 int byte_order;
285 int running;
286 int dead;
287 int bootstrap_cpu_flag;
288 int cpu_id;
289 int is_32bit; /* 0 for 64-bit, 1 for 32-bit */
290 char *name;
291
292 struct memory *mem;
293
294 int (*run_instr)(struct cpu *cpu);
295 int (*memory_rw)(struct cpu *cpu,
296 struct memory *mem, uint64_t vaddr,
297 unsigned char *data, size_t len,
298 int writeflag, int cache_flags);
299 int (*translate_v2p)(struct cpu *, uint64_t vaddr,
300 uint64_t *return_paddr, int flags);
301 void (*update_translation_table)(struct cpu *,
302 uint64_t vaddr_page, unsigned char *host_page,
303 int writeflag, uint64_t paddr_page);
304 void (*invalidate_translation_caches)(struct cpu *,
305 uint64_t paddr, int flags);
306 void (*invalidate_code_translation)(struct cpu *,
307 uint64_t paddr, int flags);
308 void (*useremul_syscall)(struct cpu *cpu, uint32_t code);
309 int (*instruction_has_delayslot)(struct cpu *cpu,
310 unsigned char *ib);
311
312 uint64_t pc;
313
314 int trace_tree_depth;
315
316 /*
317 * Dynamic translation:
318 */
319 int running_translated;
320 int n_translated_instrs;
321 unsigned char *translation_cache;
322 size_t translation_cache_cur_ofs;
323
324 uint64_t delay_jmpaddr; /* only used if delay_slot > 0 */
325 int delay_slot;
326
327 /*
328 * CPU-family dependent:
329 */
330 union {
331 struct alpha_cpu alpha;
332 struct arm_cpu arm;
333 struct avr_cpu avr;
334 struct hppa_cpu hppa;
335 struct i960_cpu i960;
336 struct ia64_cpu ia64;
337 struct m68k_cpu m68k;
338 struct mips_cpu mips;
339 struct ppc_cpu ppc;
340 struct sh_cpu sh;
341 struct sparc_cpu sparc;
342 struct transputer_cpu transputer;
343 struct x86_cpu x86;
344 } cd;
345 };
346
347
348 /* cpu.c: */
349 struct cpu *cpu_new(struct memory *mem, struct machine *machine,
350 int cpu_id, char *cpu_type_name);
351 void cpu_tlbdump(struct machine *m, int x, int rawflag);
352 void cpu_register_match(struct machine *m, char *name,
353 int writeflag, uint64_t *valuep, int *match_register);
354 void cpu_register_dump(struct machine *m, struct cpu *cpu,
355 int gprs, int coprocs);
356 int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
357 unsigned char *instr, int running, uint64_t addr);
358 char *cpu_gdb_stub(struct cpu *cpu, char *cmd);
359 int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr);
360 int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr);
361 void cpu_functioncall_trace(struct cpu *cpu, uint64_t f);
362 void cpu_functioncall_trace_return(struct cpu *cpu);
363 void cpu_create_or_reset_tc(struct cpu *cpu);
364 void cpu_run_init(struct machine *machine);
365 void cpu_run_deinit(struct machine *machine);
366 void cpu_dumpinfo(struct machine *m, struct cpu *cpu);
367 void cpu_list_available_types(void);
368 void cpu_show_cycles(struct machine *machine, int forced);
369 struct cpu_family *cpu_family_ptr_by_number(int arch);
370 void cpu_init(void);
371
372
373 #define JUST_MARK_AS_NON_WRITABLE 1
374 #define INVALIDATE_ALL 2
375 #define INVALIDATE_PADDR 4
376 #define INVALIDATE_VADDR 8
377 #define INVALIDATE_VADDR_UPPER4 16 /* useful for PPC emulation */
378
379
380 #define CPU_FAMILY_INIT(n,s) int n ## _cpu_family_init( \
381 struct cpu_family *fp) { \
382 /* Fill in the cpu_family struct with valid data for this arch. */ \
383 fp->name = s; \
384 fp->cpu_new = n ## _cpu_new; \
385 fp->list_available_types = n ## _cpu_list_available_types; \
386 fp->register_match = n ## _cpu_register_match; \
387 fp->disassemble_instr = n ## _cpu_disassemble_instr; \
388 fp->register_dump = n ## _cpu_register_dump; \
389 fp->dumpinfo = n ## _cpu_dumpinfo; \
390 fp->interrupt = n ## _cpu_interrupt; \
391 fp->interrupt_ack = n ## _cpu_interrupt_ack; \
392 fp->functioncall_trace = n ## _cpu_functioncall_trace; \
393 fp->gdb_stub = n ## _cpu_gdb_stub; \
394 fp->tlbdump = n ## _cpu_tlbdump; \
395 fp->init_tables = n ## _cpu_init_tables; \
396 return 1; \
397 }
398
399
400 #endif /* CPU_H */

  ViewVC Help
Powered by ViewVC 1.1.26