Fix building Loongarch BFD with a 32-bit compiler
[binutils-gdb.git] / sim / ppc / cpu.c
blobb89be03648b980a9a8a13d845ca0f8108f75782e
1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
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.
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, see <http://www.gnu.org/licenses/>.
21 #ifndef _CPU_C_
22 #define _CPU_C_
24 /* This must come before any other includes. */
25 #include "defs.h"
27 #include <setjmp.h>
29 #include "cpu.h"
30 #include "idecode.h"
32 #include <string.h>
34 struct _cpu {
36 /* the registers */
37 registers regs;
39 /* current instruction address */
40 unsigned_word program_counter;
42 /* the memory maps */
43 core *physical; /* all of memory */
44 vm *virtual;
45 vm_instruction_map *instruction_map; /* instructions */
46 vm_data_map *data_map; /* data */
48 /* the system this processor is contained within */
49 cpu_mon *monitor;
50 os_emul *os_emulation;
51 psim *system;
52 event_queue *events;
53 int cpu_nr;
55 /* Current CPU model information */
56 model_data *model_ptr;
58 #if WITH_IDECODE_CACHE_SIZE
59 /* a cache to store cracked instructions */
60 idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
61 #endif
63 /* any interrupt state */
64 interrupts ints;
66 /* address reservation: keep the physical address and the contents
67 of memory at that address */
68 memory_reservation reservation;
70 /* offset from event time to this cpu's idea of the local time */
71 int64_t time_base_local_time;
72 int64_t decrementer_local_time;
73 event_entry_tag decrementer_event;
77 INLINE_CPU\
78 (cpu *)
79 cpu_create(psim *system,
80 core *memory,
81 cpu_mon *monitor,
82 os_emul *os_emulation,
83 int cpu_nr)
85 cpu *processor = ZALLOC(cpu);
87 /* create the virtual memory map from the core */
88 processor->physical = memory;
89 processor->virtual = vm_create(memory);
90 processor->instruction_map = vm_create_instruction_map(processor->virtual);
91 processor->data_map = vm_create_data_map(processor->virtual);
93 if (CURRENT_MODEL_ISSUE > 0)
94 processor->model_ptr = model_create (processor);
96 /* link back to core system */
97 processor->system = system;
98 processor->events = psim_event_queue(system);
99 processor->cpu_nr = cpu_nr;
100 processor->monitor = monitor;
101 processor->os_emulation = os_emulation;
103 return processor;
107 INLINE_CPU\
108 (void)
109 cpu_init(cpu *processor)
111 memset(&processor->regs, 0, sizeof(processor->regs));
112 /* vm init is delayed until after the device tree has been init as
113 the devices may further init the cpu */
114 if (CURRENT_MODEL_ISSUE > 0)
115 model_init (processor->model_ptr);
119 /* find ones way home */
121 INLINE_CPU\
122 (psim *)
123 cpu_system(cpu *processor)
125 return processor->system;
128 INLINE_CPU\
129 (int)
130 cpu_nr(cpu *processor)
132 return processor->cpu_nr;
135 INLINE_CPU\
136 (cpu_mon *)
137 cpu_monitor(cpu *processor)
139 return processor->monitor;
142 INLINE_CPU\
143 (os_emul *)
144 cpu_os_emulation(cpu *processor)
146 return processor->os_emulation;
149 INLINE_CPU\
150 (model_data *)
151 cpu_model(cpu *processor)
153 return processor->model_ptr;
157 /* program counter manipulation */
159 INLINE_CPU\
160 (void)
161 cpu_set_program_counter(cpu *processor,
162 unsigned_word new_program_counter)
164 processor->program_counter = new_program_counter;
167 INLINE_CPU\
168 (unsigned_word)
169 cpu_get_program_counter(cpu *processor)
171 return processor->program_counter;
175 INLINE_CPU\
176 (void)
177 cpu_restart(cpu *processor,
178 unsigned_word nia)
180 ASSERT(processor != NULL);
181 cpu_set_program_counter(processor, nia);
182 psim_restart(processor->system, processor->cpu_nr);
185 INLINE_CPU\
186 (void)
187 cpu_halt(cpu *processor,
188 unsigned_word nia,
189 stop_reason reason,
190 int signal)
192 ASSERT(processor != NULL);
193 if (CURRENT_MODEL_ISSUE > 0)
194 model_halt(processor->model_ptr);
195 cpu_set_program_counter(processor, nia);
196 psim_halt(processor->system, processor->cpu_nr, reason, signal);
199 EXTERN_CPU\
200 (void)
201 cpu_error(cpu *processor,
202 unsigned_word cia,
203 const char *fmt,
204 ...)
206 char message[1024];
207 va_list ap;
209 /* format the message */
210 va_start(ap, fmt);
211 vsprintf(message, fmt, ap);
212 va_end(ap);
214 /* sanity check */
215 if (strlen(message) >= sizeof(message))
216 error("cpu_error: buffer overflow");
218 if (processor != NULL) {
219 printf_filtered("cpu %d, cia 0x%lx: %s\n",
220 processor->cpu_nr + 1, (unsigned long)cia, message);
221 cpu_halt(processor, cia, was_signalled, -1);
223 else {
224 error("cpu: %s", message);
229 /* The processors local concept of time */
231 INLINE_CPU\
232 (int64_t)
233 cpu_get_time_base(cpu *processor)
235 return (event_queue_time(processor->events)
236 - processor->time_base_local_time);
239 INLINE_CPU\
240 (void)
241 cpu_set_time_base(cpu *processor,
242 int64_t time_base)
244 processor->time_base_local_time = (event_queue_time(processor->events)
245 - time_base);
248 INLINE_CPU\
249 (int32_t)
250 cpu_get_decrementer(cpu *processor)
252 return (processor->decrementer_local_time
253 - event_queue_time(processor->events));
256 STATIC_INLINE_CPU\
257 (void)
258 cpu_decrement_event(void *data)
260 cpu *processor = (cpu*)data;
261 processor->decrementer_event = NULL;
262 decrementer_interrupt(processor);
265 INLINE_CPU\
266 (void)
267 cpu_set_decrementer(cpu *processor,
268 int32_t decrementer)
270 int64_t old_decrementer = cpu_get_decrementer(processor);
271 event_queue_deschedule(processor->events, processor->decrementer_event);
272 processor->decrementer_event = NULL;
273 processor->decrementer_local_time = (event_queue_time(processor->events)
274 + decrementer);
275 if (decrementer < 0 && old_decrementer >= 0)
276 /* A decrementer interrupt occures if the sign of the decrement
277 register is changed from positive to negative by the load
278 instruction */
279 decrementer_interrupt(processor);
280 else if (decrementer >= 0)
281 processor->decrementer_event = event_queue_schedule(processor->events,
282 decrementer,
283 cpu_decrement_event,
284 processor);
288 #if WITH_IDECODE_CACHE_SIZE
289 /* allow access to the cpu's instruction cache */
290 INLINE_CPU\
291 (idecode_cache *)
292 cpu_icache_entry(cpu *processor,
293 unsigned_word cia)
295 return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
299 INLINE_CPU\
300 (void)
301 cpu_flush_icache(cpu *processor)
303 int i;
304 /* force all addresses to 0xff... so that they never hit */
305 for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
306 processor->icache[i].address = MASK(0, 63);
308 #endif
311 /* address map revelation */
313 INLINE_CPU\
314 (vm_instruction_map *)
315 cpu_instruction_map(cpu *processor)
317 return processor->instruction_map;
320 INLINE_CPU\
321 (vm_data_map *)
322 cpu_data_map(cpu *processor)
324 return processor->data_map;
327 INLINE_CPU\
328 (void)
329 cpu_page_tlb_invalidate_entry(cpu *processor,
330 unsigned_word ea)
332 vm_page_tlb_invalidate_entry(processor->virtual, ea);
335 INLINE_CPU\
336 (void)
337 cpu_page_tlb_invalidate_all(cpu *processor)
339 vm_page_tlb_invalidate_all(processor->virtual);
343 /* interrupt access */
345 INLINE_CPU\
346 (interrupts *)
347 cpu_interrupts(cpu *processor)
349 return &processor->ints;
354 /* reservation access */
356 INLINE_CPU\
357 (memory_reservation *)
358 cpu_reservation(cpu *processor)
360 return &processor->reservation;
364 /* register access */
366 INLINE_CPU\
367 (registers *)
368 cpu_registers(cpu *processor)
370 return &processor->regs;
373 INLINE_CPU\
374 (void)
375 cpu_synchronize_context(cpu *processor,
376 unsigned_word cia)
378 #if (WITH_IDECODE_CACHE_SIZE)
379 /* kill of the cache */
380 cpu_flush_icache(processor);
381 #endif
383 /* update virtual memory */
384 vm_synchronize_context(processor->virtual,
385 processor->regs.spr,
386 processor->regs.sr,
387 processor->regs.msr,
388 processor, cia);
392 /* might again be useful one day */
394 INLINE_CPU\
395 (void)
396 cpu_print_info(cpu *processor, int verbose)
400 #endif /* _CPU_C_ */