--- trunk/src/cpus/cpu_arm.c 2007/10/08 16:19:37 22 +++ trunk/src/cpus/cpu_arm.c 2007/10/08 16:21:53 38 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Anders Gavare. All rights reserved. + * Copyright (C) 2005-2007 Anders Gavare. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: cpu_arm.c,v 1.54 2006/02/09 20:02:58 debug Exp $ + * $Id: cpu_arm.c,v 1.68 2007/03/26 02:01:35 debug Exp $ * * ARM CPU emulation. * @@ -42,10 +42,12 @@ #include "arm_cpu_types.h" #include "cpu.h" +#include "interrupt.h" #include "machine.h" #include "memory.h" #include "misc.h" #include "of.h" +#include "settings.h" #include "symbol.h" #define DYNTRANS_32 @@ -67,6 +69,9 @@ void arm_pc_to_pointers(struct cpu *cpu); #include "quick_pc_to_pointers.h" +void arm_irq_interrupt_assert(struct interrupt *interrupt); +void arm_irq_interrupt_deassert(struct interrupt *interrupt); + /* * arm_cpu_new(): @@ -77,7 +82,7 @@ int arm_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, int cpu_id, char *cpu_type_name) { - int any_cache = 0, i, found; + int i, found; struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS; /* Scan the list for this cpu type: */ @@ -92,16 +97,18 @@ if (found == -1) return 0; + cpu->run_instr = arm_run_instr; cpu->memory_rw = arm_memory_rw; cpu->update_translation_table = arm_update_translation_table; cpu->invalidate_translation_caches = arm_invalidate_translation_caches; cpu->invalidate_code_translation = arm_invalidate_code_translation; - cpu->translate_address = arm_translate_address; + cpu->translate_v2p = arm_translate_v2p; cpu->cd.arm.cpu_type = cpu_type_defs[found]; cpu->name = cpu->cd.arm.cpu_type.name; cpu->is_32bit = 1; + cpu->byte_order = EMUL_LITTLE_ENDIAN; cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F; cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32 @@ -119,15 +126,15 @@ /* Only show name and caches etc for CPU nr 0: */ if (cpu_id == 0) { debug("%s", cpu->name); - if (cpu->cd.arm.cpu_type.icache_shift != 0) - any_cache = 1; - if (cpu->cd.arm.cpu_type.dcache_shift != 0) - any_cache = 1; - if (any_cache) { - debug(" (I+D = %i+%i KB", - (int)(1 << (cpu->cd.arm.cpu_type.icache_shift-10)), - (int)(1 << (cpu->cd.arm.cpu_type.dcache_shift-10))); - debug(")"); + if (cpu->cd.arm.cpu_type.icache_shift != 0 || + cpu->cd.arm.cpu_type.dcache_shift != 0) { + int isize = cpu->cd.arm.cpu_type.icache_shift; + int dsize = cpu->cd.arm.cpu_type.dcache_shift; + if (isize != 0) + isize = 1 << (isize - 10); + if (dsize != 0) + dsize = 1 << (dsize - 10); + debug(" (I+D = %i+%i KB)", isize, dsize); } } @@ -162,6 +169,28 @@ cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28; + CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc); + for (i=0; icd.arm.r[i]); + + /* Register the CPU's "IRQ" and "FIQ" interrupts: */ + { + struct interrupt template; + char name[50]; + snprintf(name, sizeof(name), "%s.irq", cpu->path); + + memset(&template, 0, sizeof(template)); + template.line = 0; + template.name = name; + template.extra = cpu; + template.interrupt_assert = arm_irq_interrupt_assert; + template.interrupt_deassert = arm_irq_interrupt_deassert; + interrupt_handler_register(&template); + + /* FIQ: TODO */ + } + + return 1; } @@ -185,7 +214,7 @@ } cpu->cd.arm.control |= ARM_CONTROL_MMU; - cpu->translate_address = arm_translate_address_mmu; + cpu->translate_v2p = arm_translate_v2p_mmu; cpu->cd.arm.dacr |= 0x00000003; cpu->cd.arm.ttb = ttb_addr; @@ -303,36 +332,6 @@ /* - * arm_cpu_register_match(): - */ -void arm_cpu_register_match(struct machine *m, char *name, - int writeflag, uint64_t *valuep, int *match_register) -{ - int i, cpunr = 0; - - /* CPU number: */ - - /* TODO */ - - /* Register names: */ - for (i=0; icpus[cpunr]->cd.arm.r[i] = *valuep; - if (i == ARM_PC) - m->cpus[cpunr]->pc = *valuep; - } else { - *valuep = m->cpus[cpunr]->cd.arm.r[i]; - if (i == ARM_PC) - *valuep = m->cpus[cpunr]->pc; - } - *match_register = 1; - } - } -} - - -/* * arm_cpu_register_dump(): * * Dump cpu registers in a relatively readable format. @@ -714,47 +713,32 @@ /* - * arm_cpu_interrupt(): + * arm_cpu_tlbdump(): * - * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA, - * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt(). + * Called from the debugger to dump the TLB in a readable format. + * x is the cpu number to dump, or -1 to dump all CPUs. * - * TODO: don't hardcode to footbridge! + * If rawflag is nonzero, then the TLB contents isn't formated nicely, + * just dumped. */ -int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr) +void arm_cpu_tlbdump(struct machine *m, int x, int rawflag) { - /* fatal("arm_cpu_interrupt(): 0x%x\n", (int)irq_nr); */ - if (irq_nr <= 64) { - if (cpu->machine->md_interrupt != NULL) - cpu->machine->md_interrupt(cpu->machine, - cpu, irq_nr, 1); - else - fatal("arm_cpu_interrupt(): irq_nr=%i md_interrupt ==" - " NULL\n", (int)irq_nr); - } else { - /* Assert ARM IRQs: */ - cpu->cd.arm.irq_asserted = 1; - } - - return 1; } /* - * arm_cpu_interrupt_ack(): + * arm_irq_interrupt_assert(): + * arm_irq_interrupt_deassert(): */ -int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr) +void arm_irq_interrupt_assert(struct interrupt *interrupt) { - if (irq_nr <= 64) { - if (cpu->machine->md_interrupt != NULL) - cpu->machine->md_interrupt(cpu->machine, - cpu, irq_nr, 0); - } else { - /* De-assert ARM IRQs: */ - cpu->cd.arm.irq_asserted = 0; - } - - return 1; + struct cpu *cpu = (struct cpu *) interrupt->extra; + cpu->cd.arm.irq_asserted = 1; +} +void arm_irq_interrupt_deassert(struct interrupt *interrupt) +{ + struct cpu *cpu = (struct cpu *) interrupt->extra; + cpu->cd.arm.irq_asserted = 0; } @@ -771,7 +755,7 @@ * cpu->pc for relative addresses. */ int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib, - int running, uint64_t dumpaddr, int bintrans) + int running, uint64_t dumpaddr) { uint32_t iw, tmp; int main_opcode, secondary_opcode, s_bit, r16, r12, r8;