Format #instructions with commas
[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 struct _cpu {
35
36 /* the registers */
37 registers regs;
38
39 /* current instruction address */
40 unsigned_word program_counter;
41
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 */
47
48 /* current state of interrupt inputs */
49 int external_exception_pending;
50
51 /* the system this processor is contained within */
52 psim *system;
53 event_queue *events;
54 int cpu_nr;
55
56 /* if required, a cache to store decoded instructions */
57 #if WITH_IDECODE_CACHE
58 idecode_cache icache[IDECODE_CACHE_SIZE];
59 #endif
60
61 /* address reservation: keep the physical address and the contents
62 of memory at that address */
63 memory_reservation reservation;
64
65 /* offset from event time to this cpu's idea of the local time */
66 signed64 time_base_local_time;
67 signed64 decrementer_local_time;
68 event_entry_tag decrementer_event;
69
70 /* Counts of number of instructions executed. */
71 long number_of_insns;
72 };
73
74
75 INLINE_CPU cpu *
76 cpu_create(psim *system,
77 core *memory,
78 event_queue *events,
79 int cpu_nr)
80 {
81 cpu *processor = ZALLOC(cpu);
82
83 /* create the virtual memory map from the core */
84 processor->physical = memory;
85 processor->virtual = vm_create(memory);
86 processor->instruction_map = vm_create_instruction_map(processor->virtual);
87 processor->data_map = vm_create_data_map(processor->virtual);
88
89 /* link back to core system */
90 processor->system = system;
91 processor->events = events;
92 processor->cpu_nr = cpu_nr;
93
94 return processor;
95 }
96
97
98 /* find ones way home */
99
100 INLINE_CPU psim *
101 cpu_system(cpu *processor)
102 {
103 return processor->system;
104 }
105
106 INLINE_CPU int
107 cpu_nr(cpu *processor)
108 {
109 return processor->cpu_nr;
110 }
111
112 INLINE_CPU event_queue *
113 cpu_event_queue(cpu *processor)
114 {
115 return processor->events;
116 }
117
118
119 /* The processors local concept of time */
120
121 INLINE_CPU signed64
122 cpu_get_time_base(cpu *processor)
123 {
124 return (event_queue_time(processor->events)
125 + processor->time_base_local_time);
126 }
127
128 INLINE_CPU void
129 cpu_set_time_base(cpu *processor,
130 signed64 time_base)
131 {
132 processor->time_base_local_time = (event_queue_time(processor->events)
133 - time_base);
134 }
135
136 INLINE_CPU signed32
137 cpu_get_decrementer(cpu *processor)
138 {
139 return (processor->decrementer_local_time
140 - event_queue_time(processor->events));
141 }
142
143 STATIC_INLINE_CPU void
144 cpu_decrement_event(event_queue *queue,
145 void *data)
146 {
147 cpu *processor = (cpu*)data;
148 if (!decrementer_interrupt(processor)) {
149 processor->decrementer_event = event_queue_schedule(processor->events,
150 1, /* NOW! */
151 cpu_decrement_event,
152 processor);
153 }
154 }
155
156 INLINE_CPU void
157 cpu_set_decrementer(cpu *processor,
158 signed32 decrementer)
159 {
160 signed64 old_decrementer = (processor->decrementer_local_time
161 - event_queue_time(processor->events));
162 event_queue_deschedule(processor->events, processor->decrementer_event);
163 processor->decrementer_local_time = (event_queue_time(processor->events)
164 + decrementer);
165 if (decrementer < 0 && old_decrementer >= 0)
166 /* dec interrupt occures if the sign of the decrement reg is
167 changed by the load operation */
168 processor->decrementer_event = event_queue_schedule(processor->events,
169 1, /* NOW! */
170 cpu_decrement_event,
171 processor);
172 else if (decrementer >= 0)
173 processor->decrementer_event = event_queue_schedule(processor->events,
174 decrementer,
175 cpu_decrement_event,
176 processor);
177 }
178
179
180 /* program counter manipulation */
181
182 INLINE_CPU void
183 cpu_set_program_counter(cpu *processor,
184 unsigned_word new_program_counter)
185 {
186 processor->program_counter = new_program_counter;
187 }
188
189 INLINE_CPU unsigned_word
190 cpu_get_program_counter(cpu *processor)
191 {
192 return processor->program_counter;
193 }
194
195 INLINE_CPU void
196 cpu_restart(cpu *processor,
197 unsigned_word nia)
198 {
199 processor->program_counter = nia;
200 psim_restart(processor->system, processor->cpu_nr);
201 }
202
203 INLINE_CPU void
204 cpu_halt(cpu *processor,
205 unsigned_word cia,
206 stop_reason reason,
207 int signal)
208 {
209 if (processor == NULL) {
210 error("cpu_halt() processor=NULL, cia=0x%x, reason=%d, signal=%d\n",
211 cia,
212 reason,
213 signal);
214 }
215 else {
216 processor->program_counter = cia;
217 psim_halt(processor->system, processor->cpu_nr, cia, reason, signal);
218 }
219 }
220
221
222 #if WITH_IDECODE_CACHE
223 /* allow access to the cpu's instruction cache */
224 INLINE_CPU idecode_cache *
225 cpu_icache(cpu *processor)
226 {
227 return processor->icache;
228 }
229 #endif
230
231
232 /* address map revelation */
233
234 INLINE_CPU vm_instruction_map *
235 cpu_instruction_map(cpu *processor)
236 {
237 return processor->instruction_map;
238 }
239
240 INLINE_CPU vm_data_map *
241 cpu_data_map(cpu *processor)
242 {
243 return processor->data_map;
244 }
245
246
247 /* reservation access */
248
249 INLINE_CPU memory_reservation *
250 cpu_reservation(cpu *processor)
251 {
252 return &processor->reservation;
253 }
254
255
256 /* register access */
257
258 INLINE_CPU registers *
259 cpu_registers(cpu *processor)
260 {
261 return &processor->regs;
262 }
263
264 INLINE_CPU void
265 cpu_synchronize_context(cpu *processor)
266 {
267 #if WITH_IDECODE_CACHE
268 /* kill off the contents of the cache */
269 int i;
270 for (i = 0; i < IDECODE_CACHE_SIZE; i++)
271 processor->icache[i].address = MASK(0,63);
272 #endif
273
274 /* don't allow the processor to change endian modes */
275 if ((cpu_registers(processor)->msr & msr_little_endian_mode)
276 && CURRENT_TARGET_BYTE_ORDER != LITTLE_ENDIAN) {
277 error("vm_synchronize_context() - unsuported change of byte order\n");
278 }
279
280 /* update virtual memory */
281 vm_synchronize_context(processor->virtual,
282 processor->regs.spr,
283 processor->regs.sr,
284 processor->regs.msr);
285 }
286
287
288 /* # of instructions counter access */
289
290 INLINE_CPU void
291 cpu_increment_number_of_insns(cpu *processor)
292 {
293 processor->number_of_insns++;
294 }
295
296 INLINE_CPU long
297 cpu_get_number_of_insns(cpu *processor)
298 {
299 return processor->number_of_insns;
300 }
301
302 static INLINE_CPU char *
303 cpu_add_commas(char *endbuf, long value)
304 {
305 int comma = 3;
306
307 *--endbuf = '\0';
308 do {
309 if (comma-- == 0)
310 {
311 *--endbuf = ',';
312 comma = 2;
313 }
314
315 *--endbuf = (value % 10) + '0';
316 } while ((value /= 10) != 0);
317
318 return endbuf;
319 }
320
321 INLINE_CPU void
322 cpu_print_info(cpu *processor, int verbose)
323 {
324 char buffer[20];
325
326 printf_filtered("CPU #%d executed %s instructions.\n",
327 processor->cpu_nr+1,
328 cpu_add_commas(buffer + sizeof(buffer), processor->number_of_insns));
329 }
330
331 #endif /* _CPU_C_ */
This page took 0.054553 seconds and 5 git commands to generate.