/[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 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 13842 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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.62 2006/02/09 22:40:27 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 #define DYNTRANS_MISC_DECLARATIONS(arch,ARCH,addrtype) struct \
48 arch ## _instr_call { \
49 void (*f)(struct cpu *, struct arch ## _instr_call *); \
50 size_t arg[ARCH ## _N_IC_ARGS]; \
51 }; \
52 \
53 /* Translation cache struct for each physical page: */ \
54 struct arch ## _tc_physpage { \
55 struct arch ## _instr_call ics[ARCH ## _IC_ENTRIES_PER_PAGE+1];\
56 uint32_t next_ofs; /* (0 for end of chain) */ \
57 int flags; \
58 addrtype physaddr; \
59 }; \
60 \
61 struct arch ## _vpg_tlb_entry { \
62 uint8_t valid; \
63 uint8_t writeflag; \
64 addrtype vaddr_page; \
65 addrtype paddr_page; \
66 unsigned char *host_page; \
67 int64_t timestamp; \
68 };
69
70 /*
71 * Dyntrans "Instruction Translation Cache":
72 *
73 * cur_physpage is a pointer to the current physpage. (It _HAPPENS_ to
74 * be the same as cur_ic_page, because all the instrcalls should be placed
75 * first in the physpage struct!)
76 *
77 * cur_ic_page is a pointer to an array of xxx_IC_ENTRIES_PER_PAGE
78 * instruction call entries.
79 *
80 * next_ic points to the next such instruction call to be executed.
81 *
82 * combination_check, when set to non-NULL, is executed automatically after
83 * an instruction has been translated. (It check for combinations of
84 * instructions; low_addr is the offset of the translated instruction in the
85 * current page, NOT shifted right.)
86 */
87 #define DYNTRANS_ITC(arch) struct arch ## _tc_physpage *cur_physpage; \
88 struct arch ## _instr_call *cur_ic_page; \
89 struct arch ## _instr_call *next_ic; \
90 void (*combination_check)(struct cpu *, \
91 struct arch ## _instr_call *, int low_addr);
92
93 /*
94 * Virtual -> physical -> host address translation TLB entries:
95 * ------------------------------------------------------------
96 *
97 * Regardless of whether 32-bit or 64-bit address translation is used, the
98 * same TLB entry structure is used.
99 */
100 #define VPH_TLBS(arch,ARCH) \
101 struct arch ## _vpg_tlb_entry \
102 vph_tlb_entry[ARCH ## _MAX_VPH_TLB_ENTRIES];
103
104 /*
105 * 32-bit dyntrans emulated Virtual -> physical -> host address translation:
106 * -------------------------------------------------------------------------
107 *
108 * This stuff assumes that 4 KB pages are used. 20 bits to select a page
109 * means just 1 M entries needed. This is small enough that a couple of
110 * full-size tables can fit in virtual memory on modern hosts (both 32-bit
111 * and 64-bit hosts). :-)
112 *
113 * Usage: e.g. VPH32(arm,ARM,uint32_t,uint8_t)
114 * or VPH32(sparc,SPARC,uint64_t,uint16_t)
115 *
116 * The vph_tlb_entry entries are cpu dependent tlb entries.
117 *
118 * The host_load and host_store entries point to host pages; the phys_addr
119 * entries are uint32_t or uint64_t (emulated physical addresses).
120 *
121 * phys_page points to translation cache physpages.
122 *
123 * phystranslation is a bitmap which tells us whether a physical page has
124 * a code translation.
125 *
126 * vaddr_to_tlbindex is a virtual address to tlb index hint table.
127 * The values in this array are the tlb index plus 1, so a value of, say,
128 * 3 means tlb index 2. A value of 0 would mean a tlb index of -1, which
129 * is not a valid index. (I.e. no hit.)
130 */
131 #define N_VPH32_ENTRIES 1048576
132 #define VPH32(arch,ARCH,paddrtype,tlbindextype) \
133 unsigned char *host_load[N_VPH32_ENTRIES]; \
134 unsigned char *host_store[N_VPH32_ENTRIES]; \
135 paddrtype phys_addr[N_VPH32_ENTRIES]; \
136 struct arch ## _tc_physpage *phys_page[N_VPH32_ENTRIES]; \
137 uint32_t phystranslation[N_VPH32_ENTRIES/32]; \
138 tlbindextype vaddr_to_tlbindex[N_VPH32_ENTRIES];
139
140 /*
141 * 64-bit dyntrans emulated Virtual -> physical -> host address translation:
142 * -------------------------------------------------------------------------
143 *
144 * Usage: e.g. VPH64(alpha,ALPHA,uint8_t)
145 * or VPH64(sparc,SPARC,uint16_t)
146 *
147 * TODO
148 */
149 #define VPH64(arch,ARCH,tlbindextype) \
150 int dummy;
151
152 #include "cpu_alpha.h"
153 #include "cpu_arm.h"
154 #include "cpu_avr.h"
155 #include "cpu_hppa.h"
156 #include "cpu_i960.h"
157 #include "cpu_ia64.h"
158 #include "cpu_m68k.h"
159 #include "cpu_mips.h"
160 #include "cpu_ppc.h"
161 #include "cpu_sh.h"
162 #include "cpu_sparc.h"
163 #include "cpu_x86.h"
164
165 struct cpu;
166 struct emul;
167 struct machine;
168 struct memory;
169
170
171 struct cpu_family {
172 struct cpu_family *next;
173 int arch;
174
175 /* These are filled in by each CPU family's init function: */
176 char *name;
177 int (*cpu_new)(struct cpu *cpu, struct memory *mem,
178 struct machine *machine,
179 int cpu_id, char *cpu_type_name);
180 void (*list_available_types)(void);
181 void (*register_match)(struct machine *m,
182 char *name, int writeflag,
183 uint64_t *valuep, int *match_register);
184 int (*disassemble_instr)(struct cpu *cpu,
185 unsigned char *instr, int running,
186 uint64_t dumpaddr, int bintrans);
187 void (*register_dump)(struct cpu *cpu,
188 int gprs, int coprocs);
189 int (*run)(struct emul *emul,
190 struct machine *machine);
191 void (*dumpinfo)(struct cpu *cpu);
192 void (*show_full_statistics)(struct machine *m);
193 void (*tlbdump)(struct machine *m, int x,
194 int rawflag);
195 int (*interrupt)(struct cpu *cpu, uint64_t irq_nr);
196 int (*interrupt_ack)(struct cpu *cpu,
197 uint64_t irq_nr);
198 void (*functioncall_trace)(struct cpu *,
199 uint64_t f, int n_args);
200 };
201
202
203 /*
204 * More dyntrans stuff:
205 *
206 * The translation cache begins with N_BASE_TABLE_ENTRIES uint32_t offsets
207 * into the cache, for possible translation cache structs for physical pages.
208 */
209
210 /* Physpage flags: */
211 #define TRANSLATIONS 1
212 #define COMBINATIONS 2
213
214 #define DYNTRANS_CACHE_SIZE (16*1048576)
215 #define DYNTRANS_CACHE_MARGIN 300000
216
217 #define N_BASE_TABLE_ENTRIES 32768
218 #define PAGENR_TO_TABLE_INDEX(a) ((a) & (N_BASE_TABLE_ENTRIES-1))
219
220
221 #ifdef DYNTRANS_BACKEND
222
223 /* TODO: convert this into a fixed-size array? Might increase performace. */
224 struct dtb_fixup {
225 struct dtb_fixup *next;
226 int type; /* Fixup type [optional] */
227 void *addr; /* Address of the instruction
228 (in host memory) */
229 size_t data; /* Emulation data. */
230 };
231
232 struct translation_context {
233 /* Current address of where to emit host instructions: */
234 /* (NULL means no translation is currently being done.) */
235 void *p;
236
237 /* index of the instr_call of the first translated instruction: */
238 void *ic_page;
239 int start_instr_call_index;
240
241 /* Fixups needed after first translation pass: */
242 struct dtb_fixup *fixups;
243
244 int n_simple;
245
246 /* translation_buffer should have room for max_size bytes,
247 plus some margin. */
248 unsigned char *translation_buffer;
249 size_t cur_size;
250 };
251
252 #define DTB_TRANSLATION_SIZE_MAX 3072
253 #define DTB_TRANSLATION_SIZE_MARGIN 1024
254
255 void cpu_dtb_add_fixup(struct cpu *cpu, int type, void *addr, size_t data);
256 void cpu_dtb_do_fixups(struct cpu *cpu);
257
258 void dtb_host_cacheinvalidate(void *p, size_t len);
259 int dtb_function_prologue(struct translation_context *ctx, size_t *sizep);
260 int dtb_function_epilogue(struct translation_context *ctx, size_t *sizep);
261 int dtb_generate_fcall(struct cpu *cpu, struct translation_context *ctx,
262 size_t *sizep, size_t f, size_t instr_call_ptr);
263 int dtb_generate_ptr_inc(struct cpu *cpu, struct translation_context *ctx,
264 size_t *sizep, void *ptr, int amount);
265
266 #endif /* DYNTRANS_BACKEND */
267
268
269
270 /*
271 * The generic CPU struct:
272 */
273
274 struct cpu {
275 /* Pointer back to the machine this CPU is in: */
276 struct machine *machine;
277
278 int byte_order;
279 int running;
280 int dead;
281 int bootstrap_cpu_flag;
282 int cpu_id;
283 int is_32bit; /* 0 for 64-bit, 1 for 32-bit */
284 char *name;
285
286 struct memory *mem;
287 int (*memory_rw)(struct cpu *cpu,
288 struct memory *mem, uint64_t vaddr,
289 unsigned char *data, size_t len,
290 int writeflag, int cache_flags);
291 int (*translate_address)(struct cpu *, uint64_t vaddr,
292 uint64_t *return_addr, int flags);
293 void (*update_translation_table)(struct cpu *,
294 uint64_t vaddr_page, unsigned char *host_page,
295 int writeflag, uint64_t paddr_page);
296 void (*invalidate_translation_caches)(struct cpu *,
297 uint64_t paddr, int flags);
298 void (*invalidate_code_translation)(struct cpu *,
299 uint64_t paddr, int flags);
300 void (*useremul_syscall)(struct cpu *cpu, uint32_t code);
301
302 uint64_t pc;
303
304 #ifdef TRACE_NULL_CRASHES
305 /* TODO: remove this, it's MIPS only */
306 int trace_null_index;
307 uint64_t trace_null_addr[TRACE_NULL_N_ENTRIES];
308 #endif
309
310 int trace_tree_depth;
311
312 /*
313 * Dynamic translation:
314 */
315 int running_translated;
316 int n_translated_instrs;
317 unsigned char *translation_cache;
318 size_t translation_cache_cur_ofs;
319 #ifdef DYNTRANS_BACKEND
320 struct translation_context translation_context;
321 #endif
322
323 /*
324 * CPU-family dependent:
325 */
326 union {
327 struct alpha_cpu alpha;
328 struct arm_cpu arm;
329 struct avr_cpu avr;
330 struct hppa_cpu hppa;
331 struct i960_cpu i960;
332 struct ia64_cpu ia64;
333 struct m68k_cpu m68k;
334 struct mips_cpu mips;
335 struct ppc_cpu ppc;
336 struct sh_cpu sh;
337 struct sparc_cpu sparc;
338 struct x86_cpu x86;
339 } cd;
340 };
341
342
343 /* cpu.c: */
344 struct cpu *cpu_new(struct memory *mem, struct machine *machine,
345 int cpu_id, char *cpu_type_name);
346 void cpu_show_full_statistics(struct machine *m);
347 void cpu_tlbdump(struct machine *m, int x, int rawflag);
348 void cpu_register_match(struct machine *m, char *name,
349 int writeflag, uint64_t *valuep, int *match_register);
350 void cpu_register_dump(struct machine *m, struct cpu *cpu,
351 int gprs, int coprocs);
352 int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
353 unsigned char *instr, int running, uint64_t addr, int bintrans);
354 int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr);
355 int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr);
356 void cpu_functioncall_trace(struct cpu *cpu, uint64_t f);
357 void cpu_functioncall_trace_return(struct cpu *cpu);
358 void cpu_create_or_reset_tc(struct cpu *cpu);
359 void cpu_run_init(struct machine *machine);
360 int cpu_run(struct emul *emul, struct machine *machine);
361 void cpu_run_deinit(struct machine *machine);
362 void cpu_dumpinfo(struct machine *m, struct cpu *cpu);
363 void cpu_list_available_types(void);
364 void cpu_show_cycles(struct machine *machine, int forced);
365 struct cpu_family *cpu_family_ptr_by_number(int arch);
366 void cpu_init(void);
367
368
369 #define JUST_MARK_AS_NON_WRITABLE 1
370 #define INVALIDATE_ALL 2
371 #define INVALIDATE_PADDR 4
372 #define INVALIDATE_VADDR 8
373 #define INVALIDATE_VADDR_UPPER4 16 /* useful for PPC emulation */
374
375 #define TLB_CODE 0x02
376
377
378 #define CPU_FAMILY_INIT(n,s) int n ## _cpu_family_init( \
379 struct cpu_family *fp) { \
380 /* Fill in the cpu_family struct with valid data for this arch. */ \
381 fp->name = s; \
382 fp->cpu_new = n ## _cpu_new; \
383 fp->list_available_types = n ## _cpu_list_available_types; \
384 fp->register_match = n ## _cpu_register_match; \
385 fp->disassemble_instr = n ## _cpu_disassemble_instr; \
386 fp->register_dump = n ## _cpu_register_dump; \
387 fp->run = n ## _cpu_run; \
388 fp->dumpinfo = n ## _cpu_dumpinfo; \
389 fp->interrupt = n ## _cpu_interrupt; \
390 fp->interrupt_ack = n ## _cpu_interrupt_ack; \
391 fp->functioncall_trace = n ## _cpu_functioncall_trace; \
392 return 1; \
393 }
394
395 #define CPU_OLD_FAMILY_INIT(n,s) int n ## _cpu_family_init( \
396 struct cpu_family *fp) { \
397 /* Fill in the cpu_family struct with valid data for this arch. */ \
398 fp->name = s; \
399 fp->cpu_new = n ## _cpu_new; \
400 fp->list_available_types = n ## _cpu_list_available_types; \
401 fp->register_match = n ## _cpu_register_match; \
402 fp->disassemble_instr = n ## _cpu_disassemble_instr; \
403 fp->register_dump = n ## _cpu_register_dump; \
404 fp->run = n ## _OLD_cpu_run; \
405 fp->dumpinfo = n ## _cpu_dumpinfo; \
406 fp->show_full_statistics = n ## _cpu_show_full_statistics; \
407 fp->tlbdump = n ## _cpu_tlbdump; \
408 fp->interrupt = n ## _cpu_interrupt; \
409 fp->interrupt_ack = n ## _cpu_interrupt_ack; \
410 fp->functioncall_trace = n ## _cpu_functioncall_trace; \
411 return 1; \
412 }
413
414
415 #endif /* CPU_H */

  ViewVC Help
Powered by ViewVC 1.1.26