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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Mon Oct 8 16:19:43 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 20022 byte(s)
0.3.8
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.329 2006/01/16 04:48:08 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 extern int quiet_mode;
46 extern int show_opcode_statistics;
47 extern int dyntrans_backend_enable;
48
49 static struct cpu_family *first_cpu_family = NULL;
50
51
52 /*
53 * cpu_new():
54 *
55 * Create a new cpu object. Each family is tried in sequence until a
56 * CPU family recognizes the cpu_type_name.
57 */
58 struct cpu *cpu_new(struct memory *mem, struct machine *machine,
59 int cpu_id, char *name)
60 {
61 struct cpu *cpu;
62 struct cpu_family *fp;
63 char *cpu_type_name;
64
65 if (name == NULL) {
66 fprintf(stderr, "cpu_new(): cpu name = NULL?\n");
67 exit(1);
68 }
69
70 cpu_type_name = strdup(name);
71 if (cpu_type_name == NULL) {
72 fprintf(stderr, "cpu_new(): out of memory\n");
73 exit(1);
74 }
75
76 cpu = zeroed_alloc(sizeof(struct cpu));
77
78 cpu->memory_rw = NULL;
79 cpu->name = cpu_type_name;
80 cpu->mem = mem;
81 cpu->machine = machine;
82 cpu->cpu_id = cpu_id;
83 cpu->byte_order = EMUL_LITTLE_ENDIAN;
84 cpu->bootstrap_cpu_flag = 0;
85 cpu->running = 0;
86
87 cpu_create_or_reset_tc(cpu);
88
89 fp = first_cpu_family;
90
91 while (fp != NULL) {
92 if (fp->cpu_new != NULL) {
93 if (fp->cpu_new(cpu, mem, machine, cpu_id,
94 cpu_type_name)) {
95 /* Sanity check: */
96 if (cpu->memory_rw == NULL) {
97 fatal("\ncpu_new(): memory_rw == "
98 "NULL\n");
99 exit(1);
100 }
101 return cpu;
102 }
103 }
104
105 fp = fp->next;
106 }
107
108 fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name);
109 exit(1);
110 }
111
112
113 /*
114 * cpu_show_full_statistics():
115 *
116 * Show detailed statistics on opcode usage on each cpu.
117 */
118 void cpu_show_full_statistics(struct machine *m)
119 {
120 if (m->cpu_family == NULL ||
121 m->cpu_family->show_full_statistics == NULL)
122 fatal("cpu_show_full_statistics(): NULL\n");
123 else
124 m->cpu_family->show_full_statistics(m);
125 }
126
127
128 /*
129 * cpu_tlbdump():
130 *
131 * Called from the debugger to dump the TLB in a readable format.
132 * x is the cpu number to dump, or -1 to dump all CPUs.
133 *
134 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
135 * just dumped.
136 */
137 void cpu_tlbdump(struct machine *m, int x, int rawflag)
138 {
139 if (m->cpu_family == NULL || m->cpu_family->tlbdump == NULL)
140 fatal("cpu_tlbdump(): NULL\n");
141 else
142 m->cpu_family->tlbdump(m, x, rawflag);
143 }
144
145
146 /*
147 * cpu_register_match():
148 *
149 * Used by the debugger.
150 */
151 void cpu_register_match(struct machine *m, char *name,
152 int writeflag, uint64_t *valuep, int *match_register)
153 {
154 if (m->cpu_family == NULL || m->cpu_family->register_match == NULL)
155 fatal("cpu_register_match(): NULL\n");
156 else
157 m->cpu_family->register_match(m, name, writeflag,
158 valuep, match_register);
159 }
160
161
162 /*
163 * cpu_disassemble_instr():
164 *
165 * Convert an instruction word into human readable format, for instruction
166 * tracing.
167 */
168 int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
169 unsigned char *instr, int running, uint64_t addr, int bintrans)
170 {
171 if (m->cpu_family == NULL || m->cpu_family->disassemble_instr == NULL) {
172 fatal("cpu_disassemble_instr(): NULL\n");
173 return 0;
174 } else
175 return m->cpu_family->disassemble_instr(cpu, instr,
176 running, addr, bintrans);
177 }
178
179
180 /*
181 * cpu_register_dump():
182 *
183 * Dump cpu registers in a relatively readable format.
184 *
185 * gprs: set to non-zero to dump GPRs. (CPU dependent.)
186 * coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependent.)
187 */
188 void cpu_register_dump(struct machine *m, struct cpu *cpu,
189 int gprs, int coprocs)
190 {
191 if (m->cpu_family == NULL || m->cpu_family->register_dump == NULL)
192 fatal("cpu_register_dump(): NULL\n");
193 else
194 m->cpu_family->register_dump(cpu, gprs, coprocs);
195 }
196
197
198 /*
199 * cpu_interrupt():
200 *
201 * Assert an interrupt.
202 * Return value is 1 if the interrupt was asserted, 0 otherwise.
203 */
204 int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
205 {
206 if (cpu->machine->cpu_family == NULL ||
207 cpu->machine->cpu_family->interrupt == NULL) {
208 fatal("cpu_interrupt(): NULL\n");
209 return 0;
210 } else
211 return cpu->machine->cpu_family->interrupt(cpu, irq_nr);
212 }
213
214
215 /*
216 * cpu_interrupt_ack():
217 *
218 * Acknowledge an interrupt.
219 * Return value is 1 if the interrupt was deasserted, 0 otherwise.
220 */
221 int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
222 {
223 if (cpu->machine->cpu_family == NULL ||
224 cpu->machine->cpu_family->interrupt_ack == NULL) {
225 /* debug("cpu_interrupt_ack(): NULL\n"); */
226 return 0;
227 } else
228 return cpu->machine->cpu_family->interrupt_ack(cpu, irq_nr);
229 }
230
231
232 /*
233 * cpu_functioncall_trace():
234 *
235 * This function should be called if machine->show_trace_tree is enabled, and
236 * a function call is being made. f contains the address of the function.
237 */
238 void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
239 {
240 int i, n_args = -1;
241 char *symbol;
242 uint64_t offset;
243
244 if (cpu->machine->ncpus > 1)
245 fatal("cpu%i:\t", cpu->cpu_id);
246
247 cpu->trace_tree_depth ++;
248 if (cpu->trace_tree_depth > 100)
249 cpu->trace_tree_depth = 100;
250 for (i=0; i<cpu->trace_tree_depth; i++)
251 fatal(" ");
252
253 fatal("<");
254 symbol = get_symbol_name_and_n_args(&cpu->machine->symbol_context,
255 f, &offset, &n_args);
256 if (symbol != NULL)
257 fatal("%s", symbol);
258 else {
259 if (cpu->is_32bit)
260 fatal("0x%08x", (int)f);
261 else
262 fatal("0x%llx", (long long)f);
263 }
264 fatal("(");
265
266 if (cpu->machine->cpu_family->functioncall_trace != NULL)
267 cpu->machine->cpu_family->functioncall_trace(cpu, f, n_args);
268
269 fatal(")>\n");
270 }
271
272
273 /*
274 * cpu_functioncall_trace_return():
275 *
276 * This function should be called if machine->show_trace_tree is enabled, and
277 * a function is being returned from.
278 *
279 * TODO: Print return value? This could be implemented similar to the
280 * cpu->functioncall_trace function call above.
281 */
282 void cpu_functioncall_trace_return(struct cpu *cpu)
283 {
284 cpu->trace_tree_depth --;
285 if (cpu->trace_tree_depth < 0)
286 cpu->trace_tree_depth = 0;
287 }
288
289
290 /*
291 * cpu_create_or_reset_tc():
292 *
293 * Create the translation cache in memory (ie allocate memory for it), if
294 * necessary, and then reset it to an initial state.
295 */
296 void cpu_create_or_reset_tc(struct cpu *cpu)
297 {
298 size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN;
299
300 if (cpu->translation_cache == NULL) {
301 #ifdef DYNTRANS_BACKEND
302 if (dyntrans_backend_enable) {
303 cpu->translation_cache = (unsigned char *) mmap(NULL,
304 s, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON |
305 MAP_PRIVATE, -1, 0);
306 if (cpu->translation_cache == NULL) {
307 dyntrans_backend_enable = 0;
308 fatal("%\n% WARNING! Dyntrans backend disabled"
309 ", because mmap() failed.\n%\n");
310 }
311 }
312 #endif
313 if (cpu->translation_cache == NULL)
314 cpu->translation_cache = zeroed_alloc(s);
315 }
316
317 /* Create an empty table at the beginning of the translation cache: */
318 memset(cpu->translation_cache, 0, sizeof(uint32_t)
319 * N_BASE_TABLE_ENTRIES);
320
321 cpu->translation_cache_cur_ofs =
322 N_BASE_TABLE_ENTRIES * sizeof(uint32_t);
323
324 /*
325 * There might be other translation pointers that still point to
326 * within the translation_cache region. Let's invalidate those too:
327 */
328 if (cpu->invalidate_code_translation != NULL)
329 cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
330 }
331
332
333 /*
334 * cpu_run():
335 *
336 * Run instructions on all CPUs in this machine, for a "medium duration"
337 * (or until all CPUs have halted).
338 *
339 * Return value is 1 if anything happened, 0 if all CPUs are stopped.
340 */
341 int cpu_run(struct emul *emul, struct machine *m)
342 {
343 if (m->cpu_family == NULL || m->cpu_family->run == NULL) {
344 fatal("cpu_run(): NULL\n");
345 return 0;
346 } else
347 return m->cpu_family->run(emul, m);
348 }
349
350
351 /*
352 * cpu_dumpinfo():
353 *
354 * Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)
355 * is outputed, and it is up to CPU dependent code to complete the line.
356 */
357 void cpu_dumpinfo(struct machine *m, struct cpu *cpu)
358 {
359 debug("cpu%i: %s, %s", cpu->cpu_id, cpu->name,
360 cpu->running? "running" : "stopped");
361
362 if (m->cpu_family == NULL || m->cpu_family->dumpinfo == NULL)
363 fatal("cpu_dumpinfo(): NULL\n");
364 else
365 m->cpu_family->dumpinfo(cpu);
366 }
367
368
369 /*
370 * cpu_list_available_types():
371 *
372 * Print a list of available CPU types for each cpu family.
373 */
374 void cpu_list_available_types(void)
375 {
376 struct cpu_family *fp;
377 int iadd = DEBUG_INDENTATION;
378
379 fp = first_cpu_family;
380
381 if (fp == NULL) {
382 debug("No CPUs defined!\n");
383 return;
384 }
385
386 while (fp != NULL) {
387 debug("%s:\n", fp->name);
388 debug_indentation(iadd);
389 if (fp->list_available_types != NULL)
390 fp->list_available_types();
391 else
392 debug("(internal error: list_available_types"
393 " = NULL)\n");
394 debug_indentation(-iadd);
395
396 fp = fp->next;
397 }
398 }
399
400
401 /*
402 * cpu_run_deinit():
403 *
404 * Shuts down all CPUs in a machine when ending a simulation. (This function
405 * should only need to be called once for each machine.)
406 */
407 void cpu_run_deinit(struct machine *machine)
408 {
409 int te;
410
411 /*
412 * Two last ticks of every hardware device. This will allow
413 * framebuffers to draw the last updates to the screen before
414 * halting.
415 */
416 for (te=0; te<machine->n_tick_entries; te++) {
417 machine->tick_func[te](machine->cpus[0],
418 machine->tick_extra[te]);
419 machine->tick_func[te](machine->cpus[0],
420 machine->tick_extra[te]);
421 }
422
423 debug("cpu_run_deinit(): All CPUs halted.\n");
424
425 if (machine->show_nr_of_instructions || !quiet_mode)
426 cpu_show_cycles(machine, 1);
427
428 if (show_opcode_statistics)
429 cpu_show_full_statistics(machine);
430
431 fflush(stdout);
432 }
433
434
435 /*
436 * cpu_show_cycles():
437 *
438 * If automatic adjustment of clock interrupts is turned on, then recalculate
439 * emulated_hz. Also, if show_nr_of_instructions is on, then print a
440 * line to stdout about how many instructions/cycles have been executed so
441 * far.
442 */
443 void cpu_show_cycles(struct machine *machine, int forced)
444 {
445 uint64_t offset, pc;
446 char *symbol;
447 int64_t mseconds, ninstrs, is, avg;
448 struct timeval tv;
449 int h, m, s, ms, d, instrs_per_cycle = 1;
450
451 static int64_t mseconds_last = 0;
452 static int64_t ninstrs_last = -1;
453
454 switch (machine->arch) {
455 case ARCH_MIPS:
456 instrs_per_cycle = machine->cpus[machine->bootstrap_cpu]->
457 cd.mips.cpu_type.instrs_per_cycle;
458 break;
459 }
460
461 pc = machine->cpus[machine->bootstrap_cpu]->pc;
462
463 gettimeofday(&tv, NULL);
464 mseconds = (tv.tv_sec - machine->starttime.tv_sec) * 1000
465 + (tv.tv_usec - machine->starttime.tv_usec) / 1000;
466
467 if (mseconds == 0)
468 mseconds = 1;
469
470 if (mseconds - mseconds_last == 0)
471 mseconds ++;
472
473 ninstrs = machine->ncycles_since_gettimeofday * instrs_per_cycle;
474
475 if (machine->automatic_clock_adjustment) {
476 static int first_adjustment = 1;
477
478 /* Current nr of cycles per second: */
479 int64_t cur_cycles_per_second = 1000 *
480 (ninstrs-ninstrs_last) / (mseconds-mseconds_last)
481 / instrs_per_cycle;
482
483 if (cur_cycles_per_second < 1000000)
484 cur_cycles_per_second = 1000000;
485
486 if (first_adjustment) {
487 machine->emulated_hz = cur_cycles_per_second;
488 first_adjustment = 0;
489 } else {
490 machine->emulated_hz = (15 * machine->emulated_hz +
491 cur_cycles_per_second) / 16;
492 }
493
494 /* debug("[ updating emulated_hz to %lli Hz ]\n",
495 (long long)machine->emulated_hz); */
496 }
497
498
499 /* RETURN here, unless show_nr_of_instructions (-N) is turned on: */
500 if (!machine->show_nr_of_instructions && !forced)
501 goto do_return;
502
503 printf("[ %lli instrs",
504 (long long)(machine->ncycles * instrs_per_cycle));
505
506 if (!machine->automatic_clock_adjustment) {
507 d = machine->emulated_hz / 1000;
508 if (d < 1)
509 d = 1;
510 ms = machine->ncycles / d;
511 h = ms / 3600000;
512 ms -= 3600000 * h;
513 m = ms / 60000;
514 ms -= 60000 * m;
515 s = ms / 1000;
516 ms -= 1000 * s;
517
518 printf(", emulated time = %02i:%02i:%02i.%03i; ", h, m, s, ms);
519 }
520
521 /* Instructions per second, and average so far: */
522 is = 1000 * (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
523 avg = (long long)1000 * ninstrs / mseconds;
524 if (is < 0)
525 is = 0;
526 if (avg < 0)
527 avg = 0;
528 printf("; i/s=%lli avg=%lli", (long long)is, (long long)avg);
529
530 symbol = get_symbol_name(&machine->symbol_context, pc, &offset);
531
532 if (machine->ncpus == 1) {
533 if (machine->cpus[machine->bootstrap_cpu]->is_32bit)
534 printf("; pc=0x%08x", (int)pc);
535 else
536 printf("; pc=0x%016llx", (long long)pc);
537 }
538
539 if (symbol != NULL)
540 printf(" <%s>", symbol);
541 printf(" ]\n");
542
543 do_return:
544 ninstrs_last = ninstrs;
545 mseconds_last = mseconds;
546 }
547
548
549 /*
550 * cpu_run_init():
551 *
552 * Prepare to run instructions on all CPUs in this machine. (This function
553 * should only need to be called once for each machine.)
554 */
555 void cpu_run_init(struct machine *machine)
556 {
557 int ncpus = machine->ncpus;
558 int te;
559
560 machine->a_few_cycles = 1048576;
561 machine->ncycles_flush = 0;
562 machine->ncycles = 0;
563 machine->ncycles_show = 0;
564
565 /*
566 * Instead of doing { one cycle, check hardware ticks }, we
567 * can do { n cycles, check hardware ticks }, as long as
568 * n is at most as much as the lowest number of cycles/tick
569 * for any hardware device.
570 */
571 for (te=0; te<machine->n_tick_entries; te++) {
572 if (machine->ticks_reset_value[te] < machine->a_few_cycles)
573 machine->a_few_cycles = machine->ticks_reset_value[te];
574 }
575
576 machine->a_few_cycles >>= 1;
577 if (machine->a_few_cycles < 1)
578 machine->a_few_cycles = 1;
579
580 if (ncpus > 1 && machine->max_random_cycles_per_chunk == 0)
581 machine->a_few_cycles = 1;
582
583 /* debug("cpu_run_init(): a_few_cycles = %i\n",
584 machine->a_few_cycles); */
585
586 /* For performance measurement: */
587 gettimeofday(&machine->starttime, NULL);
588 machine->ncycles_since_gettimeofday = 0;
589 }
590
591
592 /*
593 * add_cpu_family():
594 *
595 * Allocates a cpu_family struct and calls an init function for the
596 * family to fill in reasonable data and pointers.
597 */
598 static void add_cpu_family(int (*family_init)(struct cpu_family *), int arch)
599 {
600 struct cpu_family *fp, *tmp;
601 int res;
602
603 fp = malloc(sizeof(struct cpu_family));
604 if (fp == NULL) {
605 fprintf(stderr, "add_cpu_family(): out of memory\n");
606 exit(1);
607 }
608 memset(fp, 0, sizeof(struct cpu_family));
609
610 /*
611 * family_init() returns 1 if the struct has been filled with
612 * valid data, 0 if suppor for the cpu family isn't compiled
613 * into the emulator.
614 */
615 res = family_init(fp);
616 if (!res) {
617 free(fp);
618 return;
619 }
620 fp->arch = arch;
621 fp->next = NULL;
622
623 /* Add last in family chain: */
624 tmp = first_cpu_family;
625 if (tmp == NULL) {
626 first_cpu_family = fp;
627 } else {
628 while (tmp->next != NULL)
629 tmp = tmp->next;
630 tmp->next = fp;
631 }
632 }
633
634
635 /*
636 * cpu_family_ptr_by_number():
637 *
638 * Returns a pointer to a CPU family based on the ARCH_* integers.
639 */
640 struct cpu_family *cpu_family_ptr_by_number(int arch)
641 {
642 struct cpu_family *fp;
643 fp = first_cpu_family;
644
645 /* YUCK! This is too hardcoded! TODO */
646
647 while (fp != NULL) {
648 if (arch == fp->arch)
649 return fp;
650 fp = fp->next;
651 }
652
653 return NULL;
654 }
655
656
657 #ifdef DYNTRANS_BACKEND
658 /*
659 * cpu_dtb_add_fixup():
660 *
661 * Add a fixup entry to a currently ongoing dyntrans backend translation.
662 */
663 void cpu_dtb_add_fixup(struct cpu *cpu, int type, void *addr, size_t data)
664 {
665 struct dtb_fixup *fixup = malloc(sizeof (struct dtb_fixup));
666 if (fixup == NULL) {
667 fprintf(stderr, "out of memory\n"),
668 exit(1);
669 }
670
671 /* memset(fixup, 0, sizeof(struct dtb_fixup)); */
672
673 fixup->next = cpu->translation_context.fixups;
674 cpu->translation_context.fixups = fixup;
675
676 fixup->type = type;
677 fixup->addr = addr;
678 fixup->data = data;
679
680 /* printf("{ fixup added: host addr %p, data=%p }\n", addr,
681 (void *)data); */
682 }
683
684
685 /*
686 * cpu_dtb_do_fixups():
687 *
688 * This function should be called when a chunk of code has been translated,
689 * and post-fixup is to be applied (i.e. add data which for some reason was
690 * not included in the generated code).
691 *
692 * If no fixup is necessary for a specific host platform, then it still needs
693 * an empty do_fixups routine here (just set done = 1).
694 */
695 void cpu_dtb_do_fixups(struct cpu *cpu)
696 {
697 for (;;) {
698 int done = 0;
699 size_t omit_addr;
700
701 struct dtb_fixup *fixup = cpu->translation_context.fixups;
702 if (fixup == NULL)
703 break;
704
705 cpu->translation_context.fixups = fixup->next;
706
707 #ifdef DYNTRANS_BACKEND_ALPHA
708 /* Add the data at the end of the new translation: */
709 /*printf("%p %p\n", fixup->addr, fixup->data);*/
710 omit_addr = (size_t)cpu->translation_context.p -
711 (size_t)cpu->translation_context.translation_buffer;
712 /*printf("omit_addr = %016llx\n", (long long)omit_addr);*/
713 omit_addr = ((omit_addr - 1) | (sizeof(uint64_t) - 1)) + 1;
714 /*printf("omit_addr = %016llx\n", (long long)omit_addr);*/
715 {
716 uint64_t *x = (void *)(omit_addr + (size_t)cpu->
717 translation_context.translation_buffer);
718 uint32_t *fixup_instr = (void *)fixup->addr;
719 size_t ofs = omit_addr;
720 if (ofs > 0x7fff) {
721 fatal("Alpha fixup > 0x7fff!\n");
722 exit(1);
723 }
724 *x = fixup->data;
725 /*printf("orig instr = 0x%08x\n", *fixup_instr);*/
726 (*fixup_instr) &= ~0xffff;
727 (*fixup_instr) |= ofs;
728 /*printf("new instr = 0x%08x\n", *fixup_instr);*/
729 }
730 omit_addr += sizeof(uint64_t);
731 cpu->translation_context.p = (void *)
732 ((size_t)cpu->translation_context.translation_buffer
733 + omit_addr);
734 done = 1;
735 #endif /* DYNTRANS_BACKEND_ALPHA */
736
737 if (!done)
738 fatal("!!! cpu_dtb_do_fixups() not implemented yet"
739 " for this host architecture!\n");
740 }
741 }
742
743 #endif /* DYNTRANS_BACKEND */
744
745
746 /*
747 * cpu_init():
748 *
749 * Should be called before any other cpu_*() function.
750 */
751 void cpu_init(void)
752 {
753 /* Note: These are registered in alphabetic order. */
754
755 #ifdef ENABLE_ALPHA
756 add_cpu_family(alpha_cpu_family_init, ARCH_ALPHA);
757 #endif
758
759 #ifdef ENABLE_ARM
760 add_cpu_family(arm_cpu_family_init, ARCH_ARM);
761 #endif
762
763 #ifdef ENABLE_AVR
764 add_cpu_family(avr_cpu_family_init, ARCH_AVR);
765 #endif
766
767 #ifdef ENABLE_HPPA
768 add_cpu_family(hppa_cpu_family_init, ARCH_HPPA);
769 #endif
770
771 #ifdef ENABLE_I960
772 add_cpu_family(i960_cpu_family_init, ARCH_I960);
773 #endif
774
775 #ifdef ENABLE_IA64
776 add_cpu_family(ia64_cpu_family_init, ARCH_IA64);
777 #endif
778
779 #ifdef ENABLE_M68K
780 add_cpu_family(m68k_cpu_family_init, ARCH_M68K);
781 #endif
782
783 #ifdef ENABLE_MIPS
784 add_cpu_family(mips_cpu_family_init, ARCH_MIPS);
785 #endif
786
787 #ifdef ENABLE_PPC
788 add_cpu_family(ppc_cpu_family_init, ARCH_PPC);
789 #endif
790
791 #ifdef ENABLE_SH
792 add_cpu_family(sh_cpu_family_init, ARCH_SH);
793 #endif
794
795 #ifdef ENABLE_SPARC
796 add_cpu_family(sparc_cpu_family_init, ARCH_SPARC);
797 #endif
798
799 #ifdef ENABLE_X86
800 add_cpu_family(x86_cpu_family_init, ARCH_X86);
801 #endif
802 }
803

  ViewVC Help
Powered by ViewVC 1.1.26