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

Contents of /trunk/src/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
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 * $Id: cpu.c,v 1.349 2006/07/26 23:21:47 debug Exp $
29 *
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 #include <sys/mman.h>
37 #include <string.h>
38
39 #include "cpu.h"
40 #include "machine.h"
41 #include "memory.h"
42 #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 struct cpu *cpu;
58 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 cpu = zeroed_alloc(sizeof(struct cpu));
73
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 cpu_create_or_reset_tc(cpu);
83
84 fp = first_cpu_family;
85
86 while (fp != NULL) {
87 if (fp->cpu_new != NULL) {
88 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 exit(1);
95 }
96 break;
97 }
98 }
99
100 fp = fp->next;
101 }
102
103 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 }
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 unsigned char *instr, int running, uint64_t addr)
156 {
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 running, addr);
163 }
164
165
166 /*
167 * cpu_register_dump():
168 *
169 * Dump cpu registers in a relatively readable format.
170 *
171 * 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 */
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 * 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 * 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 * 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 if (cpu->trace_tree_depth > 100)
253 cpu->trace_tree_depth = 100;
254 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 fatal("0x%"PRIx32, (uint32_t) f);
265 else
266 fatal("0x%"PRIx64, (uint64_t) f);
267 }
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
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 }
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 size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN;
308
309 if (cpu->translation_cache == NULL)
310 cpu->translation_cache = zeroed_alloc(s);
311
312 /* 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 if (cpu->invalidate_code_translation != NULL)
324 cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
325 }
326
327
328 /*
329 * cpu_dumpinfo():
330 *
331 * Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)
332 * is outputed, and it is up to CPU dependent code to complete the line.
333 */
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 int iadd = DEBUG_INDENTATION;
355
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 void cpu_run_deinit(struct machine *machine)
385 {
386 int te;
387
388 /*
389 * 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 */
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 if (machine->show_nr_of_instructions)
403 cpu_show_cycles(machine, 1);
404
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 void cpu_show_cycles(struct machine *machine, int forced)
418 {
419 uint64_t offset, pc;
420 char *symbol;
421 int64_t mseconds, ninstrs, is, avg;
422 struct timeval tv;
423 int h, m, s, ms, d;
424
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 mseconds = (tv.tv_sec - machine->starttime.tv_sec) * 1000
432 + (tv.tv_usec - machine->starttime.tv_usec) / 1000;
433
434 if (mseconds == 0)
435 mseconds = 1;
436
437 if (mseconds - mseconds_last == 0)
438 mseconds ++;
439
440 ninstrs = machine->ninstrs_since_gettimeofday;
441
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 (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
448
449 /* fatal("[ CYCLES PER SECOND = %"PRIi64" ]\n",
450 cur_cycles_per_second); */
451
452 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 /* fatal("[ updating emulated_hz to %"PRIi64" Hz ]\n",
464 machine->emulated_hz); */
465 }
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 printf("[ %"PRIi64" instrs", (int64_t)machine->ninstrs);
473
474 if (!machine->automatic_clock_adjustment) {
475 d = machine->emulated_hz / 1000;
476 if (d < 1)
477 d = 1;
478 ms = machine->ninstrs / d;
479 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 printf(", emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms);
487 }
488
489 /* Instructions per second, and average so far: */
490 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 printf("; i/s=%"PRIi64" avg=%"PRIi64, is, avg);
497
498 symbol = get_symbol_name(&machine->symbol_context, pc, &offset);
499
500 if (machine->ncpus == 1) {
501 if (machine->cpus[machine->bootstrap_cpu]->is_32bit)
502 printf("; pc=0x%08"PRIx32, (uint32_t) pc);
503 else
504 printf("; pc=0x%016"PRIx64, (uint64_t) pc);
505 }
506
507 if (symbol != NULL)
508 printf(" <%s>", symbol);
509 printf(" ]\n");
510
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 void cpu_run_init(struct machine *machine)
524 {
525 machine->ninstrs_flush = 0;
526 machine->ninstrs = 0;
527 machine->ninstrs_show = 0;
528
529 /* For performance measurement: */
530 gettimeofday(&machine->starttime, NULL);
531 machine->ninstrs_since_gettimeofday = 0;
532 }
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
609 #ifdef ENABLE_ALPHA
610 add_cpu_family(alpha_cpu_family_init, ARCH_ALPHA);
611 #endif
612
613 #ifdef ENABLE_ARM
614 add_cpu_family(arm_cpu_family_init, ARCH_ARM);
615 #endif
616
617 #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 #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 add_cpu_family(mips_cpu_family_init, ARCH_MIPS);
639 #endif
640
641 #ifdef ENABLE_PPC
642 add_cpu_family(ppc_cpu_family_init, ARCH_PPC);
643 #endif
644
645 #ifdef ENABLE_SH
646 add_cpu_family(sh_cpu_family_init, ARCH_SH);
647 #endif
648
649 #ifdef ENABLE_SPARC
650 add_cpu_family(sparc_cpu_family_init, ARCH_SPARC);
651 #endif
652
653 #ifdef ENABLE_TRANSPUTER
654 add_cpu_family(transputer_cpu_family_init, ARCH_TRANSPUTER);
655 #endif
656
657 #ifdef ENABLE_X86
658 add_cpu_family(x86_cpu_family_init, ARCH_X86);
659 #endif
660 }
661

  ViewVC Help
Powered by ViewVC 1.1.26