1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu.c,v 1.361 2006/10/25 09:24:05 debug Exp $ |
* $Id: cpu.c,v 1.370 2007/02/10 14:29:54 debug Exp $ |
29 |
* |
* |
30 |
* Common routines for CPU emulation. (Not specific to any CPU type.) |
* Common routines for CPU emulation. (Not specific to any CPU type.) |
31 |
*/ |
*/ |
43 |
#include "settings.h" |
#include "settings.h" |
44 |
|
|
45 |
|
|
46 |
|
extern size_t dyntrans_cache_size; |
47 |
|
extern int native_code_translation_enabled; |
48 |
|
|
49 |
static struct cpu_family *first_cpu_family = NULL; |
static struct cpu_family *first_cpu_family = NULL; |
50 |
|
|
51 |
|
|
79 |
|
|
80 |
cpu = zeroed_alloc(sizeof(struct cpu)); |
cpu = zeroed_alloc(sizeof(struct cpu)); |
81 |
|
|
82 |
|
cpu->path = malloc(strlen(machine->path) + 15); |
83 |
|
if (cpu->path == NULL) { |
84 |
|
fprintf(stderr, "cpu_new(): out of memory\n"); |
85 |
|
exit(1); |
86 |
|
} |
87 |
|
snprintf(cpu->path, strlen(machine->path) + 15, |
88 |
|
"%s.cpu[%i]", machine->path, cpu_id); |
89 |
|
|
90 |
cpu->memory_rw = NULL; |
cpu->memory_rw = NULL; |
91 |
cpu->name = cpu_type_name; |
cpu->name = cpu_type_name; |
92 |
cpu->mem = mem; |
cpu->mem = mem; |
158 |
|
|
159 |
settings_destroy(cpu->settings); |
settings_destroy(cpu->settings); |
160 |
|
|
161 |
|
if (cpu->path != NULL) |
162 |
|
free(cpu->path); |
163 |
|
|
164 |
/* TODO: This assumes that zeroed_alloc() actually succeeded |
/* TODO: This assumes that zeroed_alloc() actually succeeded |
165 |
with using mmap(), and not malloc()! */ |
with using mmap(), and not malloc()! */ |
166 |
munmap((void *)cpu, sizeof(struct cpu)); |
munmap((void *)cpu, sizeof(struct cpu)); |
240 |
|
|
241 |
|
|
242 |
/* |
/* |
|
* cpu_interrupt(): |
|
|
* |
|
|
* Assert an interrupt. |
|
|
* Return value is 1 if the interrupt was asserted, 0 otherwise. |
|
|
*/ |
|
|
int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr) |
|
|
{ |
|
|
if (cpu->machine->cpu_family == NULL || |
|
|
cpu->machine->cpu_family->interrupt == NULL) { |
|
|
fatal("cpu_interrupt(): NULL\n"); |
|
|
return 0; |
|
|
} else |
|
|
return cpu->machine->cpu_family->interrupt(cpu, irq_nr); |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
* cpu_interrupt_ack(): |
|
|
* |
|
|
* Acknowledge an interrupt. |
|
|
* Return value is 1 if the interrupt was deasserted, 0 otherwise. |
|
|
*/ |
|
|
int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr) |
|
|
{ |
|
|
if (cpu->machine->cpu_family == NULL || |
|
|
cpu->machine->cpu_family->interrupt_ack == NULL) { |
|
|
/* debug("cpu_interrupt_ack(): NULL\n"); */ |
|
|
return 0; |
|
|
} else |
|
|
return cpu->machine->cpu_family->interrupt_ack(cpu, irq_nr); |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
243 |
* cpu_functioncall_trace(): |
* cpu_functioncall_trace(): |
244 |
* |
* |
245 |
* This function should be called if machine->show_trace_tree is enabled, and |
* This function should be called if machine->show_trace_tree is enabled, and |
310 |
*/ |
*/ |
311 |
void cpu_create_or_reset_tc(struct cpu *cpu) |
void cpu_create_or_reset_tc(struct cpu *cpu) |
312 |
{ |
{ |
313 |
size_t s = DYNTRANS_CACHE_SIZE + DYNTRANS_CACHE_MARGIN; |
size_t s = dyntrans_cache_size + DYNTRANS_CACHE_MARGIN; |
314 |
|
|
315 |
if (cpu->translation_cache == NULL) |
if (cpu->translation_cache == NULL) { |
316 |
cpu->translation_cache = zeroed_alloc(s); |
cpu->translation_cache = zeroed_alloc(s); |
317 |
|
|
318 |
|
#ifdef NATIVE_CODE_GENERATION |
319 |
|
if (native_code_translation_enabled) { |
320 |
|
mprotect(cpu->translation_cache, s, |
321 |
|
PROT_READ | PROT_WRITE | PROT_EXEC); |
322 |
|
} |
323 |
|
#endif |
324 |
|
} |
325 |
|
|
326 |
|
cpu->currently_translating_to_native = 0; |
327 |
|
|
328 |
/* Create an empty table at the beginning of the translation cache: */ |
/* Create an empty table at the beginning of the translation cache: */ |
329 |
memset(cpu->translation_cache, 0, sizeof(uint32_t) |
memset(cpu->translation_cache, 0, sizeof(uint32_t) |
330 |
* N_BASE_TABLE_ENTRIES); |
* N_BASE_TABLE_ENTRIES); |
599 |
add_cpu_family(avr_cpu_family_init, ARCH_AVR); |
add_cpu_family(avr_cpu_family_init, ARCH_AVR); |
600 |
#endif |
#endif |
601 |
|
|
|
#ifdef ENABLE_AVR32 |
|
|
add_cpu_family(avr32_cpu_family_init, ARCH_AVR32); |
|
|
#endif |
|
|
|
|
602 |
#ifdef ENABLE_RCA180X |
#ifdef ENABLE_RCA180X |
603 |
add_cpu_family(rca180x_cpu_family_init, ARCH_RCA180X); |
add_cpu_family(rca180x_cpu_family_init, ARCH_RCA180X); |
604 |
#endif |
#endif |
605 |
|
|
|
#ifdef ENABLE_HPPA |
|
|
add_cpu_family(hppa_cpu_family_init, ARCH_HPPA); |
|
|
#endif |
|
|
|
|
|
#ifdef ENABLE_I960 |
|
|
add_cpu_family(i960_cpu_family_init, ARCH_I960); |
|
|
#endif |
|
|
|
|
|
#ifdef ENABLE_IA64 |
|
|
add_cpu_family(ia64_cpu_family_init, ARCH_IA64); |
|
|
#endif |
|
|
|
|
606 |
#ifdef ENABLE_M68K |
#ifdef ENABLE_M68K |
607 |
add_cpu_family(m68k_cpu_family_init, ARCH_M68K); |
add_cpu_family(m68k_cpu_family_init, ARCH_M68K); |
608 |
#endif |
#endif |
626 |
#ifdef ENABLE_TRANSPUTER |
#ifdef ENABLE_TRANSPUTER |
627 |
add_cpu_family(transputer_cpu_family_init, ARCH_TRANSPUTER); |
add_cpu_family(transputer_cpu_family_init, ARCH_TRANSPUTER); |
628 |
#endif |
#endif |
|
|
|
|
#ifdef ENABLE_X86 |
|
|
add_cpu_family(x86_cpu_family_init, ARCH_X86); |
|
|
#endif |
|
629 |
} |
} |
630 |
|
|