]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/ppc/cpu.c
Remove streq_hash in favor of htab_eq_string
[thirdparty/binutils-gdb.git] / sim / ppc / cpu.c
CommitLineData
c906108c
SS
1/* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
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
3fd725ef 7 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
8 (at your option) any later version.
9
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.
14
15 You should have received a copy of the GNU General Public License
51b318de 16 along with this program; if not, see <http://www.gnu.org/licenses/>.
c906108c
SS
17
18 */
19
20
21#ifndef _CPU_C_
22#define _CPU_C_
23
24#include <setjmp.h>
25
26#include "cpu.h"
27#include "idecode.h"
28
c906108c 29#include <string.h>
c906108c
SS
30
31struct _cpu {
32
33 /* the registers */
34 registers regs;
35
36 /* current instruction address */
37 unsigned_word program_counter;
38
39 /* the memory maps */
40 core *physical; /* all of memory */
41 vm *virtual;
42 vm_instruction_map *instruction_map; /* instructions */
43 vm_data_map *data_map; /* data */
44
45 /* the system this processor is contained within */
46 cpu_mon *monitor;
47 os_emul *os_emulation;
48 psim *system;
49 event_queue *events;
50 int cpu_nr;
51
52 /* Current CPU model information */
53 model_data *model_ptr;
54
55#if WITH_IDECODE_CACHE_SIZE
56 /* a cache to store cracked instructions */
57 idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
58#endif
59
60 /* any interrupt state */
61 interrupts ints;
62
63 /* address reservation: keep the physical address and the contents
64 of memory at that address */
65 memory_reservation reservation;
66
67 /* offset from event time to this cpu's idea of the local time */
68 signed64 time_base_local_time;
69 signed64 decrementer_local_time;
70 event_entry_tag decrementer_event;
71
72};
73
74INLINE_CPU\
75(cpu *)
76cpu_create(psim *system,
77 core *memory,
78 cpu_mon *monitor,
79 os_emul *os_emulation,
80 int cpu_nr)
81{
82 cpu *processor = ZALLOC(cpu);
83
84 /* create the virtual memory map from the core */
85 processor->physical = memory;
86 processor->virtual = vm_create(memory);
87 processor->instruction_map = vm_create_instruction_map(processor->virtual);
88 processor->data_map = vm_create_data_map(processor->virtual);
89
90 if (CURRENT_MODEL_ISSUE > 0)
91 processor->model_ptr = model_create (processor);
92
93 /* link back to core system */
94 processor->system = system;
95 processor->events = psim_event_queue(system);
96 processor->cpu_nr = cpu_nr;
97 processor->monitor = monitor;
98 processor->os_emulation = os_emulation;
99
100 return processor;
101}
102
103
104INLINE_CPU\
105(void)
106cpu_init(cpu *processor)
107{
108 memset(&processor->regs, 0, sizeof(processor->regs));
109 /* vm init is delayed until after the device tree has been init as
110 the devices may further init the cpu */
111 if (CURRENT_MODEL_ISSUE > 0)
112 model_init (processor->model_ptr);
113}
114
115
116/* find ones way home */
117
118INLINE_CPU\
119(psim *)
120cpu_system(cpu *processor)
121{
122 return processor->system;
123}
124
125INLINE_CPU\
126(int)
127cpu_nr(cpu *processor)
128{
129 return processor->cpu_nr;
130}
131
132INLINE_CPU\
133(cpu_mon *)
134cpu_monitor(cpu *processor)
135{
136 return processor->monitor;
137}
138
139INLINE_CPU\
140(os_emul *)
141cpu_os_emulation(cpu *processor)
142{
143 return processor->os_emulation;
144}
145
146INLINE_CPU\
147(model_data *)
148cpu_model(cpu *processor)
149{
150 return processor->model_ptr;
151}
152
153
154/* program counter manipulation */
155
156INLINE_CPU\
157(void)
158cpu_set_program_counter(cpu *processor,
159 unsigned_word new_program_counter)
160{
161 processor->program_counter = new_program_counter;
162}
163
164INLINE_CPU\
165(unsigned_word)
166cpu_get_program_counter(cpu *processor)
167{
168 return processor->program_counter;
169}
170
171
172INLINE_CPU\
173(void)
174cpu_restart(cpu *processor,
175 unsigned_word nia)
176{
177 ASSERT(processor != NULL);
178 cpu_set_program_counter(processor, nia);
179 psim_restart(processor->system, processor->cpu_nr);
180}
181
182INLINE_CPU\
183(void)
184cpu_halt(cpu *processor,
185 unsigned_word nia,
186 stop_reason reason,
187 int signal)
188{
189 ASSERT(processor != NULL);
190 if (CURRENT_MODEL_ISSUE > 0)
191 model_halt(processor->model_ptr);
192 cpu_set_program_counter(processor, nia);
193 psim_halt(processor->system, processor->cpu_nr, reason, signal);
194}
195
196EXTERN_CPU\
197(void)
198cpu_error(cpu *processor,
199 unsigned_word cia,
200 const char *fmt,
201 ...)
202{
203 char message[1024];
204 va_list ap;
205
206 /* format the message */
207 va_start(ap, fmt);
208 vsprintf(message, fmt, ap);
209 va_end(ap);
210
211 /* sanity check */
212 if (strlen(message) >= sizeof(message))
213 error("cpu_error: buffer overflow");
214
215 if (processor != NULL) {
216 printf_filtered("cpu %d, cia 0x%lx: %s\n",
217 processor->cpu_nr + 1, (unsigned long)cia, message);
218 cpu_halt(processor, cia, was_signalled, -1);
219 }
220 else {
221 error("cpu: %s", message);
222 }
223}
224
225
226/* The processors local concept of time */
227
228INLINE_CPU\
229(signed64)
230cpu_get_time_base(cpu *processor)
231{
232 return (event_queue_time(processor->events)
233 - processor->time_base_local_time);
234}
235
236INLINE_CPU\
237(void)
238cpu_set_time_base(cpu *processor,
239 signed64 time_base)
240{
241 processor->time_base_local_time = (event_queue_time(processor->events)
242 - time_base);
243}
244
245INLINE_CPU\
246(signed32)
247cpu_get_decrementer(cpu *processor)
248{
249 return (processor->decrementer_local_time
250 - event_queue_time(processor->events));
251}
252
253STATIC_INLINE_CPU\
254(void)
255cpu_decrement_event(void *data)
256{
257 cpu *processor = (cpu*)data;
258 processor->decrementer_event = NULL;
259 decrementer_interrupt(processor);
260}
261
262INLINE_CPU\
263(void)
264cpu_set_decrementer(cpu *processor,
265 signed32 decrementer)
266{
267 signed64 old_decrementer = cpu_get_decrementer(processor);
268 event_queue_deschedule(processor->events, processor->decrementer_event);
269 processor->decrementer_event = NULL;
270 processor->decrementer_local_time = (event_queue_time(processor->events)
271 + decrementer);
272 if (decrementer < 0 && old_decrementer >= 0)
273 /* A decrementer interrupt occures if the sign of the decrement
274 register is changed from positive to negative by the load
275 instruction */
276 decrementer_interrupt(processor);
277 else if (decrementer >= 0)
278 processor->decrementer_event = event_queue_schedule(processor->events,
279 decrementer,
280 cpu_decrement_event,
281 processor);
282}
283
284
285#if WITH_IDECODE_CACHE_SIZE
286/* allow access to the cpu's instruction cache */
287INLINE_CPU\
288(idecode_cache *)
289cpu_icache_entry(cpu *processor,
290 unsigned_word cia)
291{
292 return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
293}
294
295
296INLINE_CPU\
297(void)
298cpu_flush_icache(cpu *processor)
299{
300 int i;
301 /* force all addresses to 0xff... so that they never hit */
302 for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
303 processor->icache[i].address = MASK(0, 63);
304}
305#endif
306
307
308/* address map revelation */
309
310INLINE_CPU\
311(vm_instruction_map *)
312cpu_instruction_map(cpu *processor)
313{
314 return processor->instruction_map;
315}
316
317INLINE_CPU\
318(vm_data_map *)
319cpu_data_map(cpu *processor)
320{
321 return processor->data_map;
322}
323
324INLINE_CPU\
325(void)
326cpu_page_tlb_invalidate_entry(cpu *processor,
327 unsigned_word ea)
328{
329 vm_page_tlb_invalidate_entry(processor->virtual, ea);
330}
331
332INLINE_CPU\
333(void)
334cpu_page_tlb_invalidate_all(cpu *processor)
335{
336 vm_page_tlb_invalidate_all(processor->virtual);
337}
338
339
340/* interrupt access */
341
342INLINE_CPU\
343(interrupts *)
344cpu_interrupts(cpu *processor)
345{
346 return &processor->ints;
347}
348
349
350
351/* reservation access */
352
353INLINE_CPU\
354(memory_reservation *)
355cpu_reservation(cpu *processor)
356{
357 return &processor->reservation;
358}
359
360
361/* register access */
362
363INLINE_CPU\
364(registers *)
365cpu_registers(cpu *processor)
366{
367 return &processor->regs;
368}
369
370INLINE_CPU\
371(void)
372cpu_synchronize_context(cpu *processor,
373 unsigned_word cia)
374{
375#if (WITH_IDECODE_CACHE_SIZE)
376 /* kill of the cache */
377 cpu_flush_icache(processor);
378#endif
379
380 /* update virtual memory */
381 vm_synchronize_context(processor->virtual,
382 processor->regs.spr,
383 processor->regs.sr,
384 processor->regs.msr,
385 processor, cia);
386}
387
388
389/* might again be useful one day */
390
391INLINE_CPU\
392(void)
393cpu_print_info(cpu *processor, int verbose)
394{
395}
396
397#endif /* _CPU_C_ */