/[gxemul]/trunk/src/cpu.c
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/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 16080 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


1 dpavlin 2 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 2 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 30 * $Id: cpu.c,v 1.349 2006/07/26 23:21:47 debug Exp $
29 dpavlin 2 *
30     * Common routines for CPU emulation. (Not specific to any CPU type.)
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <sys/types.h>
36 dpavlin 22 #include <sys/mman.h>
37 dpavlin 2 #include <string.h>
38    
39     #include "cpu.h"
40     #include "machine.h"
41 dpavlin 12 #include "memory.h"
42 dpavlin 2 #include "misc.h"
43    
44    
45     static struct cpu_family *first_cpu_family = NULL;
46    
47    
48     /*
49     * cpu_new():
50     *
51     * Create a new cpu object. Each family is tried in sequence until a
52     * CPU family recognizes the cpu_type_name.
53     */
54     struct cpu *cpu_new(struct memory *mem, struct machine *machine,
55     int cpu_id, char *name)
56     {
57 dpavlin 10 struct cpu *cpu;
58 dpavlin 2 struct cpu_family *fp;
59     char *cpu_type_name;
60    
61     if (name == NULL) {
62     fprintf(stderr, "cpu_new(): cpu name = NULL?\n");
63     exit(1);
64     }
65    
66     cpu_type_name = strdup(name);
67     if (cpu_type_name == NULL) {
68     fprintf(stderr, "cpu_new(): out of memory\n");
69     exit(1);
70     }
71    
72 dpavlin 12 cpu = zeroed_alloc(sizeof(struct cpu));
73 dpavlin 10
74     cpu->memory_rw = NULL;
75     cpu->name = cpu_type_name;
76     cpu->mem = mem;
77     cpu->machine = machine;
78     cpu->cpu_id = cpu_id;
79     cpu->byte_order = EMUL_LITTLE_ENDIAN;
80     cpu->running = 0;
81    
82 dpavlin 12 cpu_create_or_reset_tc(cpu);
83    
84 dpavlin 2 fp = first_cpu_family;
85    
86     while (fp != NULL) {
87     if (fp->cpu_new != NULL) {
88 dpavlin 10 if (fp->cpu_new(cpu, mem, machine, cpu_id,
89     cpu_type_name)) {
90     /* Sanity check: */
91     if (cpu->memory_rw == NULL) {
92     fatal("\ncpu_new(): memory_rw == "
93     "NULL\n");
94 dpavlin 2 exit(1);
95     }
96 dpavlin 26 break;
97 dpavlin 2 }
98     }
99    
100     fp = fp->next;
101     }
102    
103 dpavlin 26 if (fp == NULL) {
104     fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name);
105     return NULL;
106     }
107    
108     fp->init_tables(cpu);
109    
110     return cpu;
111 dpavlin 2 }
112    
113    
114     /*
115     * cpu_tlbdump():
116     *
117     * Called from the debugger to dump the TLB in a readable format.
118     * x is the cpu number to dump, or -1 to dump all CPUs.
119     *
120     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
121     * just dumped.
122     */
123     void cpu_tlbdump(struct machine *m, int x, int rawflag)
124     {
125     if (m->cpu_family == NULL || m->cpu_family->tlbdump == NULL)
126     fatal("cpu_tlbdump(): NULL\n");
127     else
128     m->cpu_family->tlbdump(m, x, rawflag);
129     }
130    
131    
132     /*
133     * cpu_register_match():
134     *
135     * Used by the debugger.
136     */
137     void cpu_register_match(struct machine *m, char *name,
138     int writeflag, uint64_t *valuep, int *match_register)
139     {
140     if (m->cpu_family == NULL || m->cpu_family->register_match == NULL)
141     fatal("cpu_register_match(): NULL\n");
142     else
143     m->cpu_family->register_match(m, name, writeflag,
144     valuep, match_register);
145     }
146    
147    
148     /*
149     * cpu_disassemble_instr():
150     *
151     * Convert an instruction word into human readable format, for instruction
152     * tracing.
153     */
154     int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
155 dpavlin 24 unsigned char *instr, int running, uint64_t addr)
156 dpavlin 2 {
157     if (m->cpu_family == NULL || m->cpu_family->disassemble_instr == NULL) {
158     fatal("cpu_disassemble_instr(): NULL\n");
159     return 0;
160     } else
161     return m->cpu_family->disassemble_instr(cpu, instr,
162 dpavlin 24 running, addr);
163 dpavlin 2 }
164    
165    
166     /*
167     * cpu_register_dump():
168     *
169     * Dump cpu registers in a relatively readable format.
170     *
171 dpavlin 18 * gprs: set to non-zero to dump GPRs. (CPU dependent.)
172     * coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependent.)
173 dpavlin 2 */
174     void cpu_register_dump(struct machine *m, struct cpu *cpu,
175     int gprs, int coprocs)
176     {
177     if (m->cpu_family == NULL || m->cpu_family->register_dump == NULL)
178     fatal("cpu_register_dump(): NULL\n");
179     else
180     m->cpu_family->register_dump(cpu, gprs, coprocs);
181     }
182    
183    
184     /*
185 dpavlin 24 * cpu_gdb_stub():
186     *
187     * Execute a "remote GDB" command. Return value is a pointer to a newly
188     * allocated response string, if the command was successfully executed. If
189     * there was an error, NULL is returned.
190     */
191     char *cpu_gdb_stub(struct cpu *cpu, char *cmd)
192     {
193     if (cpu->machine->cpu_family == NULL ||
194     cpu->machine->cpu_family->gdb_stub == NULL) {
195     fatal("cpu_gdb_stub(): NULL\n");
196     return NULL;
197     } else
198     return cpu->machine->cpu_family->gdb_stub(cpu, cmd);
199     }
200    
201    
202     /*
203 dpavlin 2 * cpu_interrupt():
204     *
205     * Assert an interrupt.
206     * Return value is 1 if the interrupt was asserted, 0 otherwise.
207     */
208     int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
209     {
210     if (cpu->machine->cpu_family == NULL ||
211     cpu->machine->cpu_family->interrupt == NULL) {
212     fatal("cpu_interrupt(): NULL\n");
213     return 0;
214     } else
215     return cpu->machine->cpu_family->interrupt(cpu, irq_nr);
216     }
217    
218    
219     /*
220     * cpu_interrupt_ack():
221     *
222     * Acknowledge an interrupt.
223     * Return value is 1 if the interrupt was deasserted, 0 otherwise.
224     */
225     int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
226     {
227     if (cpu->machine->cpu_family == NULL ||
228     cpu->machine->cpu_family->interrupt_ack == NULL) {
229     /* debug("cpu_interrupt_ack(): NULL\n"); */
230     return 0;
231     } else
232     return cpu->machine->cpu_family->interrupt_ack(cpu, irq_nr);
233     }
234    
235    
236     /*
237 dpavlin 12 * cpu_functioncall_trace():
238     *
239     * This function should be called if machine->show_trace_tree is enabled, and
240     * a function call is being made. f contains the address of the function.
241     */
242     void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
243     {
244     int i, n_args = -1;
245     char *symbol;
246     uint64_t offset;
247    
248     if (cpu->machine->ncpus > 1)
249     fatal("cpu%i:\t", cpu->cpu_id);
250    
251     cpu->trace_tree_depth ++;
252 dpavlin 14 if (cpu->trace_tree_depth > 100)
253     cpu->trace_tree_depth = 100;
254 dpavlin 12 for (i=0; i<cpu->trace_tree_depth; i++)
255     fatal(" ");
256    
257     fatal("<");
258     symbol = get_symbol_name_and_n_args(&cpu->machine->symbol_context,
259     f, &offset, &n_args);
260     if (symbol != NULL)
261     fatal("%s", symbol);
262     else {
263     if (cpu->is_32bit)
264 dpavlin 24 fatal("0x%"PRIx32, (uint32_t) f);
265 dpavlin 12 else
266 dpavlin 24 fatal("0x%"PRIx64, (uint64_t) f);
267 dpavlin 12 }
268     fatal("(");
269    
270     if (cpu->machine->cpu_family->functioncall_trace != NULL)
271     cpu->machine->cpu_family->functioncall_trace(cpu, f, n_args);
272    
273     fatal(")>\n");
274 dpavlin 24
275     #ifdef PRINT_MEMORY_CHECKSUM
276     /* Temporary hack for finding bugs: */
277     fatal("call chksum=%016"PRIx64"\n", memory_checksum(cpu->mem));
278     #endif
279 dpavlin 12 }
280    
281    
282     /*
283     * cpu_functioncall_trace_return():
284     *
285     * This function should be called if machine->show_trace_tree is enabled, and
286     * a function is being returned from.
287     *
288     * TODO: Print return value? This could be implemented similar to the
289     * cpu->functioncall_trace function call above.
290     */
291     void cpu_functioncall_trace_return(struct cpu *cpu)
292     {
293     cpu->trace_tree_depth --;
294     if (cpu->trace_tree_depth < 0)
295     cpu->trace_tree_depth = 0;
296     }
297    
298    
299     /*
300     * cpu_create_or_reset_tc():
301     *
302     * Create the translation cache in memory (ie allocate memory for it), if
303     * necessary, and then reset it to an initial state.
304     */
305     void cpu_create_or_reset_tc(struct cpu *cpu)
306     {
307 dpavlin 22 size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN;
308 dpavlin 12
309 dpavlin 24 if (cpu->translation_cache == NULL)
310     cpu->translation_cache = zeroed_alloc(s);
311 dpavlin 22
312 dpavlin 12 /* Create an empty table at the beginning of the translation cache: */
313     memset(cpu->translation_cache, 0, sizeof(uint32_t)
314     * N_BASE_TABLE_ENTRIES);
315    
316     cpu->translation_cache_cur_ofs =
317     N_BASE_TABLE_ENTRIES * sizeof(uint32_t);
318    
319     /*
320     * There might be other translation pointers that still point to
321     * within the translation_cache region. Let's invalidate those too:
322     */
323 dpavlin 14 if (cpu->invalidate_code_translation != NULL)
324     cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
325 dpavlin 12 }
326    
327    
328     /*
329 dpavlin 2 * cpu_dumpinfo():
330     *
331     * Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)
332 dpavlin 18 * is outputed, and it is up to CPU dependent code to complete the line.
333 dpavlin 2 */
334     void cpu_dumpinfo(struct machine *m, struct cpu *cpu)
335     {
336     debug("cpu%i: %s, %s", cpu->cpu_id, cpu->name,
337     cpu->running? "running" : "stopped");
338    
339     if (m->cpu_family == NULL || m->cpu_family->dumpinfo == NULL)
340     fatal("cpu_dumpinfo(): NULL\n");
341     else
342     m->cpu_family->dumpinfo(cpu);
343     }
344    
345    
346     /*
347     * cpu_list_available_types():
348     *
349     * Print a list of available CPU types for each cpu family.
350     */
351     void cpu_list_available_types(void)
352     {
353     struct cpu_family *fp;
354 dpavlin 22 int iadd = DEBUG_INDENTATION;
355 dpavlin 2
356     fp = first_cpu_family;
357    
358     if (fp == NULL) {
359     debug("No CPUs defined!\n");
360     return;
361     }
362    
363     while (fp != NULL) {
364     debug("%s:\n", fp->name);
365     debug_indentation(iadd);
366     if (fp->list_available_types != NULL)
367     fp->list_available_types();
368     else
369     debug("(internal error: list_available_types"
370     " = NULL)\n");
371     debug_indentation(-iadd);
372    
373     fp = fp->next;
374     }
375     }
376    
377    
378     /*
379     * cpu_run_deinit():
380     *
381     * Shuts down all CPUs in a machine when ending a simulation. (This function
382     * should only need to be called once for each machine.)
383     */
384 dpavlin 12 void cpu_run_deinit(struct machine *machine)
385 dpavlin 2 {
386     int te;
387    
388     /*
389 dpavlin 28 * Two last ticks of every hardware device. This will allow e.g.
390     * framebuffers to draw the last updates to the screen before halting.
391     *
392     * TODO: This should be refactored when redesigning the mainbus
393     * concepts!
394 dpavlin 2 */
395     for (te=0; te<machine->n_tick_entries; te++) {
396     machine->tick_func[te](machine->cpus[0],
397     machine->tick_extra[te]);
398     machine->tick_func[te](machine->cpus[0],
399     machine->tick_extra[te]);
400     }
401    
402 dpavlin 28 if (machine->show_nr_of_instructions)
403 dpavlin 10 cpu_show_cycles(machine, 1);
404 dpavlin 2
405     fflush(stdout);
406     }
407    
408    
409     /*
410     * cpu_show_cycles():
411     *
412     * If automatic adjustment of clock interrupts is turned on, then recalculate
413     * emulated_hz. Also, if show_nr_of_instructions is on, then print a
414     * line to stdout about how many instructions/cycles have been executed so
415     * far.
416     */
417 dpavlin 10 void cpu_show_cycles(struct machine *machine, int forced)
418 dpavlin 2 {
419     uint64_t offset, pc;
420     char *symbol;
421 dpavlin 12 int64_t mseconds, ninstrs, is, avg;
422 dpavlin 2 struct timeval tv;
423 dpavlin 24 int h, m, s, ms, d;
424 dpavlin 2
425     static int64_t mseconds_last = 0;
426     static int64_t ninstrs_last = -1;
427    
428     pc = machine->cpus[machine->bootstrap_cpu]->pc;
429    
430     gettimeofday(&tv, NULL);
431 dpavlin 10 mseconds = (tv.tv_sec - machine->starttime.tv_sec) * 1000
432     + (tv.tv_usec - machine->starttime.tv_usec) / 1000;
433 dpavlin 2
434     if (mseconds == 0)
435     mseconds = 1;
436    
437     if (mseconds - mseconds_last == 0)
438     mseconds ++;
439    
440 dpavlin 28 ninstrs = machine->ninstrs_since_gettimeofday;
441 dpavlin 2
442     if (machine->automatic_clock_adjustment) {
443     static int first_adjustment = 1;
444    
445     /* Current nr of cycles per second: */
446     int64_t cur_cycles_per_second = 1000 *
447 dpavlin 24 (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
448 dpavlin 2
449 dpavlin 24 /* fatal("[ CYCLES PER SECOND = %"PRIi64" ]\n",
450     cur_cycles_per_second); */
451    
452 dpavlin 2 if (cur_cycles_per_second < 1000000)
453     cur_cycles_per_second = 1000000;
454    
455     if (first_adjustment) {
456     machine->emulated_hz = cur_cycles_per_second;
457     first_adjustment = 0;
458     } else {
459     machine->emulated_hz = (15 * machine->emulated_hz +
460     cur_cycles_per_second) / 16;
461     }
462    
463 dpavlin 24 /* fatal("[ updating emulated_hz to %"PRIi64" Hz ]\n",
464     machine->emulated_hz); */
465 dpavlin 2 }
466    
467    
468     /* RETURN here, unless show_nr_of_instructions (-N) is turned on: */
469     if (!machine->show_nr_of_instructions && !forced)
470     goto do_return;
471    
472 dpavlin 28 printf("[ %"PRIi64" instrs", (int64_t)machine->ninstrs);
473 dpavlin 2
474     if (!machine->automatic_clock_adjustment) {
475     d = machine->emulated_hz / 1000;
476     if (d < 1)
477     d = 1;
478 dpavlin 28 ms = machine->ninstrs / d;
479 dpavlin 2 h = ms / 3600000;
480     ms -= 3600000 * h;
481     m = ms / 60000;
482     ms -= 60000 * m;
483     s = ms / 1000;
484     ms -= 1000 * s;
485    
486 dpavlin 22 printf(", emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms);
487 dpavlin 2 }
488    
489     /* Instructions per second, and average so far: */
490 dpavlin 12 is = 1000 * (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
491     avg = (long long)1000 * ninstrs / mseconds;
492     if (is < 0)
493     is = 0;
494     if (avg < 0)
495     avg = 0;
496 dpavlin 24 printf("; i/s=%"PRIi64" avg=%"PRIi64, is, avg);
497 dpavlin 2
498     symbol = get_symbol_name(&machine->symbol_context, pc, &offset);
499    
500 dpavlin 12 if (machine->ncpus == 1) {
501     if (machine->cpus[machine->bootstrap_cpu]->is_32bit)
502 dpavlin 24 printf("; pc=0x%08"PRIx32, (uint32_t) pc);
503 dpavlin 12 else
504 dpavlin 24 printf("; pc=0x%016"PRIx64, (uint64_t) pc);
505 dpavlin 12 }
506 dpavlin 2
507 dpavlin 10 if (symbol != NULL)
508     printf(" <%s>", symbol);
509     printf(" ]\n");
510 dpavlin 2
511     do_return:
512     ninstrs_last = ninstrs;
513     mseconds_last = mseconds;
514     }
515    
516    
517     /*
518     * cpu_run_init():
519     *
520     * Prepare to run instructions on all CPUs in this machine. (This function
521     * should only need to be called once for each machine.)
522     */
523 dpavlin 12 void cpu_run_init(struct machine *machine)
524 dpavlin 2 {
525 dpavlin 28 machine->ninstrs_flush = 0;
526     machine->ninstrs = 0;
527     machine->ninstrs_show = 0;
528 dpavlin 2
529     /* For performance measurement: */
530     gettimeofday(&machine->starttime, NULL);
531 dpavlin 28 machine->ninstrs_since_gettimeofday = 0;
532 dpavlin 2 }
533    
534    
535     /*
536     * add_cpu_family():
537     *
538     * Allocates a cpu_family struct and calls an init function for the
539     * family to fill in reasonable data and pointers.
540     */
541     static void add_cpu_family(int (*family_init)(struct cpu_family *), int arch)
542     {
543     struct cpu_family *fp, *tmp;
544     int res;
545    
546     fp = malloc(sizeof(struct cpu_family));
547     if (fp == NULL) {
548     fprintf(stderr, "add_cpu_family(): out of memory\n");
549     exit(1);
550     }
551     memset(fp, 0, sizeof(struct cpu_family));
552    
553     /*
554     * family_init() returns 1 if the struct has been filled with
555     * valid data, 0 if suppor for the cpu family isn't compiled
556     * into the emulator.
557     */
558     res = family_init(fp);
559     if (!res) {
560     free(fp);
561     return;
562     }
563     fp->arch = arch;
564     fp->next = NULL;
565    
566     /* Add last in family chain: */
567     tmp = first_cpu_family;
568     if (tmp == NULL) {
569     first_cpu_family = fp;
570     } else {
571     while (tmp->next != NULL)
572     tmp = tmp->next;
573     tmp->next = fp;
574     }
575     }
576    
577    
578     /*
579     * cpu_family_ptr_by_number():
580     *
581     * Returns a pointer to a CPU family based on the ARCH_* integers.
582     */
583     struct cpu_family *cpu_family_ptr_by_number(int arch)
584     {
585     struct cpu_family *fp;
586     fp = first_cpu_family;
587    
588     /* YUCK! This is too hardcoded! TODO */
589    
590     while (fp != NULL) {
591     if (arch == fp->arch)
592     return fp;
593     fp = fp->next;
594     }
595    
596     return NULL;
597     }
598    
599    
600     /*
601     * cpu_init():
602     *
603     * Should be called before any other cpu_*() function.
604     */
605     void cpu_init(void)
606     {
607     /* Note: These are registered in alphabetic order. */
608 dpavlin 12
609     #ifdef ENABLE_ALPHA
610     add_cpu_family(alpha_cpu_family_init, ARCH_ALPHA);
611     #endif
612    
613     #ifdef ENABLE_ARM
614 dpavlin 6 add_cpu_family(arm_cpu_family_init, ARCH_ARM);
615 dpavlin 12 #endif
616    
617 dpavlin 14 #ifdef ENABLE_AVR
618     add_cpu_family(avr_cpu_family_init, ARCH_AVR);
619     #endif
620    
621     #ifdef ENABLE_HPPA
622     add_cpu_family(hppa_cpu_family_init, ARCH_HPPA);
623     #endif
624    
625     #ifdef ENABLE_I960
626     add_cpu_family(i960_cpu_family_init, ARCH_I960);
627     #endif
628    
629 dpavlin 12 #ifdef ENABLE_IA64
630     add_cpu_family(ia64_cpu_family_init, ARCH_IA64);
631     #endif
632    
633     #ifdef ENABLE_M68K
634     add_cpu_family(m68k_cpu_family_init, ARCH_M68K);
635     #endif
636    
637     #ifdef ENABLE_MIPS
638 dpavlin 2 add_cpu_family(mips_cpu_family_init, ARCH_MIPS);
639 dpavlin 12 #endif
640    
641     #ifdef ENABLE_PPC
642 dpavlin 2 add_cpu_family(ppc_cpu_family_init, ARCH_PPC);
643 dpavlin 12 #endif
644    
645 dpavlin 14 #ifdef ENABLE_SH
646     add_cpu_family(sh_cpu_family_init, ARCH_SH);
647     #endif
648    
649 dpavlin 12 #ifdef ENABLE_SPARC
650     add_cpu_family(sparc_cpu_family_init, ARCH_SPARC);
651     #endif
652    
653 dpavlin 28 #ifdef ENABLE_TRANSPUTER
654     add_cpu_family(transputer_cpu_family_init, ARCH_TRANSPUTER);
655     #endif
656    
657 dpavlin 12 #ifdef ENABLE_X86
658 dpavlin 4 add_cpu_family(x86_cpu_family_init, ARCH_X86);
659 dpavlin 12 #endif
660 dpavlin 2 }
661    

  ViewVC Help
Powered by ViewVC 1.1.26