X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fppc%2Fcpu.c;h=c7e8bdf0c0031055d0dffd5be0f79e0a6ebef63e;hb=00923338dec84505addaf9cdeca2e9c844757824;hp=33094fe8d08af48ffea9100eeeba414c04b553f6;hpb=84bbbc3577f6191dca8be835e91c742f4ca865fd;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/ppc/cpu.c b/sim/ppc/cpu.c index 33094fe8d0..c7e8bdf0c0 100644 --- a/sim/ppc/cpu.c +++ b/sim/ppc/cpu.c @@ -1,10 +1,10 @@ /* This file is part of the program psim. - Copyright (C) 1994-1995, Andrew Cagney + Copyright (C) 1994-1997, Andrew Cagney This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -13,8 +13,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + along with this program; if not, see . */ @@ -22,10 +21,6 @@ #ifndef _CPU_C_ #define _CPU_C_ -#ifndef STATIC_INLINE_CPU -#define STATIC_INLINE_CPU STATIC_INLINE -#endif - #include #include "cpu.h" @@ -53,11 +48,9 @@ struct _cpu { vm_instruction_map *instruction_map; /* instructions */ vm_data_map *data_map; /* data */ - /* current state of interrupt inputs */ - int external_exception_pending; - /* the system this processor is contained within */ cpu_mon *monitor; + os_emul *os_emulation; psim *system; event_queue *events; int cpu_nr; @@ -70,6 +63,9 @@ struct _cpu { idecode_cache icache[WITH_IDECODE_CACHE_SIZE]; #endif + /* any interrupt state */ + interrupts ints; + /* address reservation: keep the physical address and the contents of memory at that address */ memory_reservation reservation; @@ -81,12 +77,12 @@ struct _cpu { }; - -INLINE_CPU cpu * +INLINE_CPU\ +(cpu *) cpu_create(psim *system, core *memory, - event_queue *events, cpu_mon *monitor, + os_emul *os_emulation, int cpu_nr) { cpu *processor = ZALLOC(cpu); @@ -96,70 +92,155 @@ cpu_create(psim *system, processor->virtual = vm_create(memory); processor->instruction_map = vm_create_instruction_map(processor->virtual); processor->data_map = vm_create_data_map(processor->virtual); - processor->model_ptr = model_create (processor); + + if (CURRENT_MODEL_ISSUE > 0) + processor->model_ptr = model_create (processor); /* link back to core system */ processor->system = system; - processor->events = events; + processor->events = psim_event_queue(system); processor->cpu_nr = cpu_nr; processor->monitor = monitor; + processor->os_emulation = os_emulation; return processor; } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_init(cpu *processor) { memset(&processor->regs, 0, sizeof(processor->regs)); - /* FIXME - should any of VM be inited also ? */ - - model_init (processor, processor->model_ptr); + /* vm init is delayed until after the device tree has been init as + the devices may further init the cpu */ + if (CURRENT_MODEL_ISSUE > 0) + model_init (processor->model_ptr); } /* find ones way home */ -INLINE_CPU psim * +INLINE_CPU\ +(psim *) cpu_system(cpu *processor) { return processor->system; } -INLINE_CPU int +INLINE_CPU\ +(int) cpu_nr(cpu *processor) { return processor->cpu_nr; } -INLINE_CPU event_queue * -cpu_event_queue(cpu *processor) +INLINE_CPU\ +(cpu_mon *) +cpu_monitor(cpu *processor) { - return processor->events; + return processor->monitor; } -INLINE_CPU cpu_mon * -cpu_monitor(cpu *processor) +INLINE_CPU\ +(os_emul *) +cpu_os_emulation(cpu *processor) { - return processor->monitor; + return processor->os_emulation; } -INLINE_CPU model_data * +INLINE_CPU\ +(model_data *) cpu_model(cpu *processor) { return processor->model_ptr; } + +/* program counter manipulation */ + +INLINE_CPU\ +(void) +cpu_set_program_counter(cpu *processor, + unsigned_word new_program_counter) +{ + processor->program_counter = new_program_counter; +} + +INLINE_CPU\ +(unsigned_word) +cpu_get_program_counter(cpu *processor) +{ + return processor->program_counter; +} + + +INLINE_CPU\ +(void) +cpu_restart(cpu *processor, + unsigned_word nia) +{ + ASSERT(processor != NULL); + cpu_set_program_counter(processor, nia); + psim_restart(processor->system, processor->cpu_nr); +} + +INLINE_CPU\ +(void) +cpu_halt(cpu *processor, + unsigned_word nia, + stop_reason reason, + int signal) +{ + ASSERT(processor != NULL); + if (CURRENT_MODEL_ISSUE > 0) + model_halt(processor->model_ptr); + cpu_set_program_counter(processor, nia); + psim_halt(processor->system, processor->cpu_nr, reason, signal); +} + +EXTERN_CPU\ +(void) +cpu_error(cpu *processor, + unsigned_word cia, + const char *fmt, + ...) +{ + char message[1024]; + va_list ap; + + /* format the message */ + va_start(ap, fmt); + vsprintf(message, fmt, ap); + va_end(ap); + + /* sanity check */ + if (strlen(message) >= sizeof(message)) + error("cpu_error: buffer overflow"); + + if (processor != NULL) { + printf_filtered("cpu %d, cia 0x%lx: %s\n", + processor->cpu_nr + 1, (unsigned long)cia, message); + cpu_halt(processor, cia, was_signalled, -1); + } + else { + error("cpu: %s", message); + } +} + + /* The processors local concept of time */ -INLINE_CPU signed64 +INLINE_CPU\ +(signed64) cpu_get_time_base(cpu *processor) { return (event_queue_time(processor->events) - processor->time_base_local_time); } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_set_time_base(cpu *processor, signed64 time_base) { @@ -167,42 +248,38 @@ cpu_set_time_base(cpu *processor, - time_base); } -INLINE_CPU signed32 +INLINE_CPU\ +(signed32) cpu_get_decrementer(cpu *processor) { return (processor->decrementer_local_time - event_queue_time(processor->events)); } -STATIC_INLINE_CPU void -cpu_decrement_event(event_queue *queue, - void *data) +STATIC_INLINE_CPU\ +(void) +cpu_decrement_event(void *data) { cpu *processor = (cpu*)data; - if (!decrementer_interrupt(processor)) { - processor->decrementer_event = event_queue_schedule(processor->events, - 1, /* NOW! */ - cpu_decrement_event, - processor); - } + processor->decrementer_event = NULL; + decrementer_interrupt(processor); } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_set_decrementer(cpu *processor, signed32 decrementer) { - signed64 old_decrementer = (processor->decrementer_local_time - - event_queue_time(processor->events)); + signed64 old_decrementer = cpu_get_decrementer(processor); event_queue_deschedule(processor->events, processor->decrementer_event); + processor->decrementer_event = NULL; processor->decrementer_local_time = (event_queue_time(processor->events) + decrementer); if (decrementer < 0 && old_decrementer >= 0) - /* dec interrupt occures if the sign of the decrement reg is - changed by the load operation */ - processor->decrementer_event = event_queue_schedule(processor->events, - 1, /* NOW! */ - cpu_decrement_event, - processor); + /* A decrementer interrupt occures if the sign of the decrement + register is changed from positive to negative by the load + instruction */ + decrementer_interrupt(processor); else if (decrementer >= 0) processor->decrementer_event = event_queue_schedule(processor->events, decrementer, @@ -211,52 +288,10 @@ cpu_set_decrementer(cpu *processor, } -/* program counter manipulation */ - -INLINE_CPU void -cpu_set_program_counter(cpu *processor, - unsigned_word new_program_counter) -{ - processor->program_counter = new_program_counter; -} - -INLINE_CPU unsigned_word -cpu_get_program_counter(cpu *processor) -{ - return processor->program_counter; -} - -INLINE_CPU void -cpu_restart(cpu *processor, - unsigned_word nia) -{ - processor->program_counter = nia; - psim_restart(processor->system, processor->cpu_nr); -} - -INLINE_CPU void -cpu_halt(cpu *processor, - unsigned_word cia, - stop_reason reason, - int signal) -{ - if (processor == NULL) { - error("cpu_halt() processor=NULL, cia=0x%x, reason=%d, signal=%d\n", - cia, - reason, - signal); - } - else { - model_halt(processor, processor->model_ptr); - processor->program_counter = cia; - psim_halt(processor->system, processor->cpu_nr, cia, reason, signal); - } -} - - #if WITH_IDECODE_CACHE_SIZE /* allow access to the cpu's instruction cache */ -INLINE_CPU idecode_cache * +INLINE_CPU\ +(idecode_cache *) cpu_icache_entry(cpu *processor, unsigned_word cia) { @@ -264,7 +299,8 @@ cpu_icache_entry(cpu *processor, } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_flush_icache(cpu *processor) { int i; @@ -277,22 +313,51 @@ cpu_flush_icache(cpu *processor) /* address map revelation */ -INLINE_CPU vm_instruction_map * +INLINE_CPU\ +(vm_instruction_map *) cpu_instruction_map(cpu *processor) { return processor->instruction_map; } -INLINE_CPU vm_data_map * +INLINE_CPU\ +(vm_data_map *) cpu_data_map(cpu *processor) { return processor->data_map; } +INLINE_CPU\ +(void) +cpu_page_tlb_invalidate_entry(cpu *processor, + unsigned_word ea) +{ + vm_page_tlb_invalidate_entry(processor->virtual, ea); +} + +INLINE_CPU\ +(void) +cpu_page_tlb_invalidate_all(cpu *processor) +{ + vm_page_tlb_invalidate_all(processor->virtual); +} + + +/* interrupt access */ + +INLINE_CPU\ +(interrupts *) +cpu_interrupts(cpu *processor) +{ + return &processor->ints; +} + + /* reservation access */ -INLINE_CPU memory_reservation * +INLINE_CPU\ +(memory_reservation *) cpu_reservation(cpu *processor) { return &processor->reservation; @@ -301,16 +366,19 @@ cpu_reservation(cpu *processor) /* register access */ -INLINE_CPU registers * +INLINE_CPU\ +(registers *) cpu_registers(cpu *processor) { return &processor->regs; } -INLINE_CPU void -cpu_synchronize_context(cpu *processor) +INLINE_CPU\ +(void) +cpu_synchronize_context(cpu *processor, + unsigned_word cia) { -#if (WITH_IDECODE_CACHE) +#if (WITH_IDECODE_CACHE_SIZE) /* kill of the cache */ cpu_flush_icache(processor); #endif @@ -319,13 +387,15 @@ cpu_synchronize_context(cpu *processor) vm_synchronize_context(processor->virtual, processor->regs.spr, processor->regs.sr, - processor->regs.msr); + processor->regs.msr, + processor, cia); } /* might again be useful one day */ -INLINE_CPU void +INLINE_CPU\ +(void) cpu_print_info(cpu *processor, int verbose) { }