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