/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (13 years, 3 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 dpavlin 4 #ifndef CPU_H
2     #define CPU_H
3    
4     /*
5 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
6 dpavlin 4 *
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 dpavlin 28 * $Id: cpu.h,v 1.84 2006/07/20 21:53:00 debug Exp $
32 dpavlin 4 *
33 dpavlin 22 * CPU-related definitions.
34 dpavlin 4 */
35    
36    
37     #include <sys/types.h>
38     #include <inttypes.h>
39     #include <sys/time.h>
40    
41 dpavlin 22 /* This is needed for undefining 'mips', 'ppc' etc. on weird systems: */
42 dpavlin 4 #include "../../config.h"
43    
44 dpavlin 22 /*
45     * Dyntrans misc declarations, used throughout the dyntrans code.
46 dpavlin 24 *
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 dpavlin 28 *
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 dpavlin 22 */
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 dpavlin 24 struct arch ## _instr_call ics[ARCH ## _IC_ENTRIES_PER_PAGE+2];\
78 dpavlin 22 uint32_t next_ofs; /* (0 for end of chain) */ \
79 dpavlin 28 uint32_t translations; \
80 dpavlin 22 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 dpavlin 24 #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 dpavlin 22 /*
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 dpavlin 26 struct arch ## _tc_physpage *physpage_template;\
130 dpavlin 22 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 dpavlin 24 * 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 dpavlin 22 */
189 dpavlin 24 #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 dpavlin 22
197 dpavlin 24
198     /* Include all CPUs' header files here: */
199 dpavlin 14 #include "cpu_alpha.h"
200 dpavlin 6 #include "cpu_arm.h"
201 dpavlin 14 #include "cpu_avr.h"
202     #include "cpu_hppa.h"
203     #include "cpu_i960.h"
204 dpavlin 12 #include "cpu_ia64.h"
205     #include "cpu_m68k.h"
206 dpavlin 4 #include "cpu_mips.h"
207     #include "cpu_ppc.h"
208 dpavlin 14 #include "cpu_sh.h"
209 dpavlin 12 #include "cpu_sparc.h"
210 dpavlin 28 #include "cpu_transputer.h"
211 dpavlin 4 #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 dpavlin 10 int (*cpu_new)(struct cpu *cpu, struct memory *mem,
226 dpavlin 4 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 dpavlin 24 uint64_t dumpaddr);
235 dpavlin 4 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 dpavlin 12 void (*functioncall_trace)(struct cpu *,
244     uint64_t f, int n_args);
245 dpavlin 24 char *(*gdb_stub)(struct cpu *, char *cmd);
246 dpavlin 26 void (*init_tables)(struct cpu *cpu);
247 dpavlin 4 };
248    
249    
250 dpavlin 12 /*
251 dpavlin 22 * More dyntrans stuff:
252 dpavlin 12 *
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 dpavlin 28 #define COMBINATIONS 1
259 dpavlin 12
260 dpavlin 24 /* 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 dpavlin 28 #define DYNTRANS_CACHE_SIZE (32*1048576)
270 dpavlin 26 #define DYNTRANS_CACHE_MARGIN 350000
271 dpavlin 12
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 dpavlin 4 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 dpavlin 12 int is_32bit; /* 0 for 64-bit, 1 for 32-bit */
290 dpavlin 4 char *name;
291    
292     struct memory *mem;
293 dpavlin 28
294     int (*run_instr)(struct cpu *cpu);
295 dpavlin 4 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 dpavlin 26 int (*translate_v2p)(struct cpu *, uint64_t vaddr,
300     uint64_t *return_paddr, int flags);
301 dpavlin 12 void (*update_translation_table)(struct cpu *,
302     uint64_t vaddr_page, unsigned char *host_page,
303     int writeflag, uint64_t paddr_page);
304 dpavlin 18 void (*invalidate_translation_caches)(struct cpu *,
305 dpavlin 14 uint64_t paddr, int flags);
306     void (*invalidate_code_translation)(struct cpu *,
307     uint64_t paddr, int flags);
308 dpavlin 12 void (*useremul_syscall)(struct cpu *cpu, uint32_t code);
309 dpavlin 24 int (*instruction_has_delayslot)(struct cpu *cpu,
310     unsigned char *ib);
311 dpavlin 4
312     uint64_t pc;
313    
314 dpavlin 12 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 dpavlin 24 uint64_t delay_jmpaddr; /* only used if delay_slot > 0 */
325     int delay_slot;
326    
327 dpavlin 12 /*
328     * CPU-family dependent:
329     */
330 dpavlin 4 union {
331 dpavlin 28 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 dpavlin 4 } 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 dpavlin 24 unsigned char *instr, int running, uint64_t addr);
358     char *cpu_gdb_stub(struct cpu *cpu, char *cmd);
359 dpavlin 4 int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr);
360     int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr);
361 dpavlin 12 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 dpavlin 4 void cpu_dumpinfo(struct machine *m, struct cpu *cpu);
367     void cpu_list_available_types(void);
368 dpavlin 10 void cpu_show_cycles(struct machine *machine, int forced);
369 dpavlin 4 struct cpu_family *cpu_family_ptr_by_number(int arch);
370     void cpu_init(void);
371    
372    
373 dpavlin 14 #define JUST_MARK_AS_NON_WRITABLE 1
374     #define INVALIDATE_ALL 2
375     #define INVALIDATE_PADDR 4
376     #define INVALIDATE_VADDR 8
377 dpavlin 22 #define INVALIDATE_VADDR_UPPER4 16 /* useful for PPC emulation */
378 dpavlin 14
379    
380 dpavlin 12 #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 dpavlin 20 fp->interrupt = n ## _cpu_interrupt; \
391     fp->interrupt_ack = n ## _cpu_interrupt_ack; \
392     fp->functioncall_trace = n ## _cpu_functioncall_trace; \
393 dpavlin 24 fp->gdb_stub = n ## _cpu_gdb_stub; \
394 dpavlin 12 fp->tlbdump = n ## _cpu_tlbdump; \
395 dpavlin 26 fp->init_tables = n ## _cpu_init_tables; \
396 dpavlin 12 return 1; \
397     }
398    
399    
400 dpavlin 4 #endif /* CPU_H */

  ViewVC Help
Powered by ViewVC 1.1.26