33094fe8d08af48ffea9100eeeba414c04b553f6
[deliverable/binutils-gdb.git] / sim / ppc / cpu.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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 #ifndef STATIC_INLINE_CPU
26 #define STATIC_INLINE_CPU STATIC_INLINE
27 #endif
28
29 #include <setjmp.h>
30
31 #include "cpu.h"
32 #include "idecode.h"
33
34 #ifdef HAVE_STRING_H
35 #include <string.h>
36 #else
37 #ifdef HAVE_STRINGS_H
38 #include <strings.h>
39 #endif
40 #endif
41
42 struct _cpu {
43
44 /* the registers */
45 registers regs;
46
47 /* current instruction address */
48 unsigned_word program_counter;
49
50 /* the memory maps */
51 core *physical; /* all of memory */
52 vm *virtual;
53 vm_instruction_map *instruction_map; /* instructions */
54 vm_data_map *data_map; /* data */
55
56 /* current state of interrupt inputs */
57 int external_exception_pending;
58
59 /* the system this processor is contained within */
60 cpu_mon *monitor;
61 psim *system;
62 event_queue *events;
63 int cpu_nr;
64
65 /* Current CPU model information */
66 model_data *model_ptr;
67
68 #if WITH_IDECODE_CACHE_SIZE
69 /* a cache to store cracked instructions */
70 idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
71 #endif
72
73 /* address reservation: keep the physical address and the contents
74 of memory at that address */
75 memory_reservation reservation;
76
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;
81
82 };
83
84
85 INLINE_CPU cpu *
86 cpu_create(psim *system,
87 core *memory,
88 event_queue *events,
89 cpu_mon *monitor,
90 int cpu_nr)
91 {
92 cpu *processor = ZALLOC(cpu);
93
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);
99 processor->model_ptr = model_create (processor);
100
101 /* link back to core system */
102 processor->system = system;
103 processor->events = events;
104 processor->cpu_nr = cpu_nr;
105 processor->monitor = monitor;
106
107 return processor;
108 }
109
110
111 INLINE_CPU void
112 cpu_init(cpu *processor)
113 {
114 memset(&processor->regs, 0, sizeof(processor->regs));
115 /* FIXME - should any of VM be inited also ? */
116
117 model_init (processor, processor->model_ptr);
118 }
119
120
121 /* find ones way home */
122
123 INLINE_CPU psim *
124 cpu_system(cpu *processor)
125 {
126 return processor->system;
127 }
128
129 INLINE_CPU int
130 cpu_nr(cpu *processor)
131 {
132 return processor->cpu_nr;
133 }
134
135 INLINE_CPU event_queue *
136 cpu_event_queue(cpu *processor)
137 {
138 return processor->events;
139 }
140
141 INLINE_CPU cpu_mon *
142 cpu_monitor(cpu *processor)
143 {
144 return processor->monitor;
145 }
146
147 INLINE_CPU model_data *
148 cpu_model(cpu *processor)
149 {
150 return processor->model_ptr;
151 }
152
153 /* The processors local concept of time */
154
155 INLINE_CPU signed64
156 cpu_get_time_base(cpu *processor)
157 {
158 return (event_queue_time(processor->events)
159 - processor->time_base_local_time);
160 }
161
162 INLINE_CPU void
163 cpu_set_time_base(cpu *processor,
164 signed64 time_base)
165 {
166 processor->time_base_local_time = (event_queue_time(processor->events)
167 - time_base);
168 }
169
170 INLINE_CPU signed32
171 cpu_get_decrementer(cpu *processor)
172 {
173 return (processor->decrementer_local_time
174 - event_queue_time(processor->events));
175 }
176
177 STATIC_INLINE_CPU void
178 cpu_decrement_event(event_queue *queue,
179 void *data)
180 {
181 cpu *processor = (cpu*)data;
182 if (!decrementer_interrupt(processor)) {
183 processor->decrementer_event = event_queue_schedule(processor->events,
184 1, /* NOW! */
185 cpu_decrement_event,
186 processor);
187 }
188 }
189
190 INLINE_CPU void
191 cpu_set_decrementer(cpu *processor,
192 signed32 decrementer)
193 {
194 signed64 old_decrementer = (processor->decrementer_local_time
195 - event_queue_time(processor->events));
196 event_queue_deschedule(processor->events, processor->decrementer_event);
197 processor->decrementer_local_time = (event_queue_time(processor->events)
198 + decrementer);
199 if (decrementer < 0 && old_decrementer >= 0)
200 /* dec interrupt occures if the sign of the decrement reg is
201 changed by the load operation */
202 processor->decrementer_event = event_queue_schedule(processor->events,
203 1, /* NOW! */
204 cpu_decrement_event,
205 processor);
206 else if (decrementer >= 0)
207 processor->decrementer_event = event_queue_schedule(processor->events,
208 decrementer,
209 cpu_decrement_event,
210 processor);
211 }
212
213
214 /* program counter manipulation */
215
216 INLINE_CPU void
217 cpu_set_program_counter(cpu *processor,
218 unsigned_word new_program_counter)
219 {
220 processor->program_counter = new_program_counter;
221 }
222
223 INLINE_CPU unsigned_word
224 cpu_get_program_counter(cpu *processor)
225 {
226 return processor->program_counter;
227 }
228
229 INLINE_CPU void
230 cpu_restart(cpu *processor,
231 unsigned_word nia)
232 {
233 processor->program_counter = nia;
234 psim_restart(processor->system, processor->cpu_nr);
235 }
236
237 INLINE_CPU void
238 cpu_halt(cpu *processor,
239 unsigned_word cia,
240 stop_reason reason,
241 int signal)
242 {
243 if (processor == NULL) {
244 error("cpu_halt() processor=NULL, cia=0x%x, reason=%d, signal=%d\n",
245 cia,
246 reason,
247 signal);
248 }
249 else {
250 model_halt(processor, processor->model_ptr);
251 processor->program_counter = cia;
252 psim_halt(processor->system, processor->cpu_nr, cia, reason, signal);
253 }
254 }
255
256
257 #if WITH_IDECODE_CACHE_SIZE
258 /* allow access to the cpu's instruction cache */
259 INLINE_CPU idecode_cache *
260 cpu_icache_entry(cpu *processor,
261 unsigned_word cia)
262 {
263 return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
264 }
265
266
267 INLINE_CPU void
268 cpu_flush_icache(cpu *processor)
269 {
270 int i;
271 /* force all addresses to 0xff... so that they never hit */
272 for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
273 processor->icache[i].address = MASK(0, 63);
274 }
275 #endif
276
277
278 /* address map revelation */
279
280 INLINE_CPU vm_instruction_map *
281 cpu_instruction_map(cpu *processor)
282 {
283 return processor->instruction_map;
284 }
285
286 INLINE_CPU vm_data_map *
287 cpu_data_map(cpu *processor)
288 {
289 return processor->data_map;
290 }
291
292
293 /* reservation access */
294
295 INLINE_CPU memory_reservation *
296 cpu_reservation(cpu *processor)
297 {
298 return &processor->reservation;
299 }
300
301
302 /* register access */
303
304 INLINE_CPU registers *
305 cpu_registers(cpu *processor)
306 {
307 return &processor->regs;
308 }
309
310 INLINE_CPU void
311 cpu_synchronize_context(cpu *processor)
312 {
313 #if (WITH_IDECODE_CACHE)
314 /* kill of the cache */
315 cpu_flush_icache(processor);
316 #endif
317
318 /* update virtual memory */
319 vm_synchronize_context(processor->virtual,
320 processor->regs.spr,
321 processor->regs.sr,
322 processor->regs.msr);
323 }
324
325
326 /* might again be useful one day */
327
328 INLINE_CPU void
329 cpu_print_info(cpu *processor, int verbose)
330 {
331 }
332
333 #endif /* _CPU_C_ */
This page took 0.036166 seconds and 4 git commands to generate.