Include ld-lib.exp from ctf-lib.exp
[binutils-gdb.git] / sim / ppc / cpu.c
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 3 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, see <http://www.gnu.org/licenses/>.
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
29 #include <string.h>
30
31 struct _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
74 INLINE_CPU\
75 (cpu *)
76 cpu_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
104 INLINE_CPU\
105 (void)
106 cpu_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
118 INLINE_CPU\
119 (psim *)
120 cpu_system(cpu *processor)
121 {
122 return processor->system;
123 }
124
125 INLINE_CPU\
126 (int)
127 cpu_nr(cpu *processor)
128 {
129 return processor->cpu_nr;
130 }
131
132 INLINE_CPU\
133 (cpu_mon *)
134 cpu_monitor(cpu *processor)
135 {
136 return processor->monitor;
137 }
138
139 INLINE_CPU\
140 (os_emul *)
141 cpu_os_emulation(cpu *processor)
142 {
143 return processor->os_emulation;
144 }
145
146 INLINE_CPU\
147 (model_data *)
148 cpu_model(cpu *processor)
149 {
150 return processor->model_ptr;
151 }
152
153
154 /* program counter manipulation */
155
156 INLINE_CPU\
157 (void)
158 cpu_set_program_counter(cpu *processor,
159 unsigned_word new_program_counter)
160 {
161 processor->program_counter = new_program_counter;
162 }
163
164 INLINE_CPU\
165 (unsigned_word)
166 cpu_get_program_counter(cpu *processor)
167 {
168 return processor->program_counter;
169 }
170
171
172 INLINE_CPU\
173 (void)
174 cpu_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
182 INLINE_CPU\
183 (void)
184 cpu_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
196 EXTERN_CPU\
197 (void)
198 cpu_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
228 INLINE_CPU\
229 (signed64)
230 cpu_get_time_base(cpu *processor)
231 {
232 return (event_queue_time(processor->events)
233 - processor->time_base_local_time);
234 }
235
236 INLINE_CPU\
237 (void)
238 cpu_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
245 INLINE_CPU\
246 (signed32)
247 cpu_get_decrementer(cpu *processor)
248 {
249 return (processor->decrementer_local_time
250 - event_queue_time(processor->events));
251 }
252
253 STATIC_INLINE_CPU\
254 (void)
255 cpu_decrement_event(void *data)
256 {
257 cpu *processor = (cpu*)data;
258 processor->decrementer_event = NULL;
259 decrementer_interrupt(processor);
260 }
261
262 INLINE_CPU\
263 (void)
264 cpu_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 */
287 INLINE_CPU\
288 (idecode_cache *)
289 cpu_icache_entry(cpu *processor,
290 unsigned_word cia)
291 {
292 return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
293 }
294
295
296 INLINE_CPU\
297 (void)
298 cpu_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
310 INLINE_CPU\
311 (vm_instruction_map *)
312 cpu_instruction_map(cpu *processor)
313 {
314 return processor->instruction_map;
315 }
316
317 INLINE_CPU\
318 (vm_data_map *)
319 cpu_data_map(cpu *processor)
320 {
321 return processor->data_map;
322 }
323
324 INLINE_CPU\
325 (void)
326 cpu_page_tlb_invalidate_entry(cpu *processor,
327 unsigned_word ea)
328 {
329 vm_page_tlb_invalidate_entry(processor->virtual, ea);
330 }
331
332 INLINE_CPU\
333 (void)
334 cpu_page_tlb_invalidate_all(cpu *processor)
335 {
336 vm_page_tlb_invalidate_all(processor->virtual);
337 }
338
339
340 /* interrupt access */
341
342 INLINE_CPU\
343 (interrupts *)
344 cpu_interrupts(cpu *processor)
345 {
346 return &processor->ints;
347 }
348
349
350
351 /* reservation access */
352
353 INLINE_CPU\
354 (memory_reservation *)
355 cpu_reservation(cpu *processor)
356 {
357 return &processor->reservation;
358 }
359
360
361 /* register access */
362
363 INLINE_CPU\
364 (registers *)
365 cpu_registers(cpu *processor)
366 {
367 return &processor->regs;
368 }
369
370 INLINE_CPU\
371 (void)
372 cpu_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
391 INLINE_CPU\
392 (void)
393 cpu_print_info(cpu *processor, int verbose)
394 {
395 }
396
397 #endif /* _CPU_C_ */