1 /* This file is part of the program psim.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #ifndef STATIC_INLINE_CPU
26 #define STATIC_INLINE_CPU STATIC_INLINE
47 /* current instruction address */
48 unsigned_word program_counter;
51 core *physical; /* all of memory */
53 vm_instruction_map *instruction_map; /* instructions */
54 vm_data_map *data_map; /* data */
56 /* current state of interrupt inputs */
57 int external_exception_pending;
59 /* the system this processor is contained within */
65 /* Current CPU model information */
66 model_data *model_ptr;
68 #if WITH_IDECODE_CACHE_SIZE
69 /* a cache to store cracked instructions */
70 idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
73 /* address reservation: keep the physical address and the contents
74 of memory at that address */
75 memory_reservation reservation;
77 /* offset from event time to this cpu's idea of the local time */
78 signed64 time_base_local_time;
79 signed64 decrementer_local_time;
80 event_entry_tag decrementer_event;
86 cpu_create(psim *system,
92 cpu *processor = ZALLOC(cpu);
94 /* create the virtual memory map from the core */
95 processor->physical = memory;
96 processor->virtual = vm_create(memory);
97 processor->instruction_map = vm_create_instruction_map(processor->virtual);
98 processor->data_map = vm_create_data_map(processor->virtual);
100 if (CURRENT_MODEL_ISSUE > 0)
101 processor->model_ptr = model_create (processor);
103 /* link back to core system */
104 processor->system = system;
105 processor->events = events;
106 processor->cpu_nr = cpu_nr;
107 processor->monitor = monitor;
114 cpu_init(cpu *processor)
116 memset(&processor->regs, 0, sizeof(processor->regs));
117 /* FIXME - should any of VM be inited also ? */
119 if (CURRENT_MODEL_ISSUE > 0)
120 model_init (processor->model_ptr);
124 /* find ones way home */
127 cpu_system(cpu *processor)
129 return processor->system;
133 cpu_nr(cpu *processor)
135 return processor->cpu_nr;
138 INLINE_CPU event_queue *
139 cpu_event_queue(cpu *processor)
141 return processor->events;
145 cpu_monitor(cpu *processor)
147 return processor->monitor;
150 INLINE_CPU model_data *
151 cpu_model(cpu *processor)
153 return processor->model_ptr;
156 /* The processors local concept of time */
159 cpu_get_time_base(cpu *processor)
161 return (event_queue_time(processor->events)
162 - processor->time_base_local_time);
166 cpu_set_time_base(cpu *processor,
169 processor->time_base_local_time = (event_queue_time(processor->events)
174 cpu_get_decrementer(cpu *processor)
176 return (processor->decrementer_local_time
177 - event_queue_time(processor->events));
180 STATIC_INLINE_CPU void
181 cpu_decrement_event(event_queue *queue,
184 cpu *processor = (cpu*)data;
185 if (!decrementer_interrupt(processor)) {
186 processor->decrementer_event = event_queue_schedule(processor->events,
194 cpu_set_decrementer(cpu *processor,
195 signed32 decrementer)
197 signed64 old_decrementer = (processor->decrementer_local_time
198 - event_queue_time(processor->events));
199 event_queue_deschedule(processor->events, processor->decrementer_event);
200 processor->decrementer_local_time = (event_queue_time(processor->events)
202 if (decrementer < 0 && old_decrementer >= 0)
203 /* dec interrupt occures if the sign of the decrement reg is
204 changed by the load operation */
205 processor->decrementer_event = event_queue_schedule(processor->events,
209 else if (decrementer >= 0)
210 processor->decrementer_event = event_queue_schedule(processor->events,
217 /* program counter manipulation */
220 cpu_set_program_counter(cpu *processor,
221 unsigned_word new_program_counter)
223 processor->program_counter = new_program_counter;
226 INLINE_CPU unsigned_word
227 cpu_get_program_counter(cpu *processor)
229 return processor->program_counter;
233 cpu_restart(cpu *processor,
236 processor->program_counter = nia;
237 psim_restart(processor->system, processor->cpu_nr);
241 cpu_halt(cpu *processor,
246 if (processor == NULL) {
247 error("cpu_halt() processor=NULL, cia=0x%x, reason=%d, signal=%d\n",
253 if (CURRENT_MODEL_ISSUE > 0)
254 model_halt(processor->model_ptr);
256 processor->program_counter = cia;
257 psim_halt(processor->system, processor->cpu_nr, cia, reason, signal);
262 #if WITH_IDECODE_CACHE_SIZE
263 /* allow access to the cpu's instruction cache */
264 INLINE_CPU idecode_cache *
265 cpu_icache_entry(cpu *processor,
268 return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
273 cpu_flush_icache(cpu *processor)
276 /* force all addresses to 0xff... so that they never hit */
277 for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
278 processor->icache[i].address = MASK(0, 63);
283 /* address map revelation */
285 INLINE_CPU vm_instruction_map *
286 cpu_instruction_map(cpu *processor)
288 return processor->instruction_map;
291 INLINE_CPU vm_data_map *
292 cpu_data_map(cpu *processor)
294 return processor->data_map;
298 /* reservation access */
300 INLINE_CPU memory_reservation *
301 cpu_reservation(cpu *processor)
303 return &processor->reservation;
307 /* register access */
309 INLINE_CPU registers *
310 cpu_registers(cpu *processor)
312 return &processor->regs;
316 cpu_synchronize_context(cpu *processor)
318 #if (WITH_IDECODE_CACHE)
319 /* kill of the cache */
320 cpu_flush_icache(processor);
323 /* update virtual memory */
324 vm_synchronize_context(processor->virtual,
327 processor->regs.msr);
331 /* might again be useful one day */
334 cpu_print_info(cpu *processor, int verbose)