Abort if we find the program has an .interp section
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
CommitLineData
8b3797aa
MM
1/* This file is part of the program psim.
2
eada1efc 3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
8b3797aa
MM
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 _PSIM_C_
23#define _PSIM_C_
24
eada1efc
MM
25#include "inline.c"
26
a983c8f0
MM
27#include <stdio.h>
28#include <ctype.h>
a983c8f0 29
c494cadd
MM
30#ifdef HAVE_STDLIB_H
31#include <stdlib.h>
32#endif
33
8b3797aa
MM
34#include <setjmp.h>
35
36#include "cpu.h" /* includes psim.h */
37#include "idecode.h"
eada1efc 38#include "options.h"
8b3797aa 39
c494cadd
MM
40#ifdef HAVE_STRING_H
41#include <string.h>
42#else
43#ifdef HAVE_STRINGS_H
44#include <strings.h>
45#endif
46#endif
47
a983c8f0
MM
48#include "bfd.h"
49
50
8b3797aa
MM
51/* system structure, actual size of processor array determined at
52 runtime */
53
54struct _psim {
55 event_queue *events;
eada1efc 56 device *devices;
a983c8f0 57 mon *monitor;
eada1efc 58 os_emul *os_emulation;
8b3797aa 59 core *memory;
eada1efc 60
8b3797aa
MM
61 /* escape routine for inner functions */
62 void *path_to_halt;
63 void *path_to_restart;
eada1efc 64
8b3797aa
MM
65 /* status from last halt */
66 psim_status halt_status;
eada1efc
MM
67
68 /* the processors proper */
8b3797aa
MM
69 int nr_cpus;
70 int last_cpu; /* CPU that last (tried to) execute an instruction */
a983c8f0 71 cpu *processors[MAX_NR_PROCESSORS];
8b3797aa
MM
72};
73
74
75int current_target_byte_order;
76int current_host_byte_order;
77int current_environment;
78int current_alignment;
a983c8f0 79int current_floating_point;
290ad14a 80int current_model_issue = MODEL_ISSUE_IGNORE;
28816f45 81model_enum current_model = WITH_DEFAULT_MODEL;
a983c8f0
MM
82
83
eada1efc 84/* create the device tree */
a983c8f0 85
eada1efc
MM
86INLINE_PSIM\
87(device *)
88psim_tree(void)
a983c8f0 89{
eada1efc
MM
90 device *root = core_device_create();
91 device_tree_add_parsed(root, "/aliases");
92 device_tree_add_parsed(root, "/options");
93 device_tree_add_parsed(root, "/chosen");
94 device_tree_add_parsed(root, "/packages");
95 device_tree_add_parsed(root, "/cpus");
96 device_tree_add_parsed(root, "/openprom");
97 device_tree_add_parsed(root, "/openprom/init");
98 device_tree_add_parsed(root, "/openprom/trace");
99 device_tree_add_parsed(root, "/openprom/options");
100 return root;
a983c8f0
MM
101}
102
eada1efc
MM
103STATIC_INLINE_PSIM\
104(char *)
105find_arg(char *err_msg,
106 int *ptr_to_argp,
107 char **argv)
a983c8f0 108{
eada1efc
MM
109 *ptr_to_argp += 1;
110 if (argv[*ptr_to_argp] == NULL)
111 error(err_msg);
112 return argv[*ptr_to_argp];
a983c8f0
MM
113}
114
eada1efc
MM
115INLINE_PSIM\
116(void)
117psim_usage(int verbose)
a983c8f0 118{
eada1efc
MM
119 printf_filtered("Usage:\n");
120 printf_filtered("\n");
121 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
122 printf_filtered("\n");
123 printf_filtered("Where\n");
124 printf_filtered("\n");
125 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
126 if (verbose) {
127 printf_filtered("\t This can either be a PowerPC binary or\n");
128 printf_filtered("\t a text file containing a device tree\n");
129 printf_filtered("\t specification.\n");
130 printf_filtered("\t PSIM will attempt to determine from the\n");
131 printf_filtered("\t specified <image> the intended emulation\n");
132 printf_filtered("\t environment.\n");
133 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
134 printf_filtered("\t environment can be specified using the\n");
135 printf_filtered("\t `-e' option (described below).\n");
136 printf_filtered("\n"); }
137 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
138 if (verbose) {
139 printf_filtered("\t These arguments will be passed to\n");
140 printf_filtered("\t <image> (as standard C argv, argc)\n");
141 printf_filtered("\t when <image> is started.\n");
142 printf_filtered("\n"); }
143 printf_filtered("\t<psim-option> See below\n");
144 printf_filtered("\n");
145 printf_filtered("The following are valid <psim-option>s:\n");
146 printf_filtered("\n");
147 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
148 if (verbose) {
149 printf_filtered("\t Selects the processor to use when\n");
150 printf_filtered("\t modeling execution units. Includes:\n");
151 printf_filtered("\t 604, 603 and 603e\n");
152 printf_filtered("\n"); }
153 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
154 if (verbose) {
155 printf_filtered("\t Can be any of the following:\n");
156 printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
157 printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
88f1eac4
MM
158 printf_filtered("\t solaris - UEA + Solaris system calls\n");
159 printf_filtered("\t linux - UEA + Linux system calls\n");
eada1efc
MM
160 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
161 printf_filtered("\n"); }
162 printf_filtered("\t-i Print instruction counting statistics\n");
163 if (verbose) { printf_filtered("\n"); }
164 printf_filtered("\t-I Print execution unit statistics\n");
165 if (verbose) { printf_filtered("\n"); }
166 printf_filtered("\t-r <size> Set RAM size in bytes (OEA environments)\n");
167 if (verbose) { printf_filtered("\n"); }
168 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
169 if (verbose) { printf_filtered("\n"); }
170 printf_filtered("\t-o <spec> add device <spec> to the device tree\n");
171 if (verbose) { printf_filtered("\n"); }
172 printf_filtered("\t-h -? -H give more detailed usage\n");
173 if (verbose) { printf_filtered("\n"); }
174 printf_filtered("\n");
175 trace_usage(verbose);
176 device_usage(verbose);
177 if (verbose > 1) {
178 printf_filtered("\n");
179 print_options();
a983c8f0 180 }
eada1efc 181 error("");
a983c8f0
MM
182}
183
eada1efc
MM
184INLINE_PSIM\
185(char **)
186psim_options(device *root,
187 char **argv)
a983c8f0 188{
eada1efc
MM
189 device *current = root;
190 int argp;
191 if (argv == NULL)
192 return NULL;
193 argp = 0;
194 while (argv[argp] != NULL && argv[argp][0] == '-') {
195 char *p = argv[argp] + 1;
196 char *param;
197 while (*p != '\0') {
198 switch (*p) {
199 default:
200 psim_usage(0);
201 error ("");
202 break;
203 case 'e':
204 param = find_arg("Missing <emul> option for -e\n", &argp, argv);
205 device_tree_add_parsed(root, "/openprom/options/os-emul %s", param);
206 break;
207 case 'h':
208 case '?':
209 psim_usage(1);
210 break;
211 case 'H':
212 psim_usage(2);
213 break;
214 case 'i':
215 device_tree_add_parsed(root, "/openprom/trace/print-info 1");
216 break;
217 case 'I':
218 device_tree_add_parsed(root, "/openprom/trace/print-info 2");
219 device_tree_add_parsed(root, "/openprom/options/model-issue %d",
220 MODEL_ISSUE_PROCESS);
221 break;
222 case 'm':
223 param = find_arg("Missing <model> option for -m\n", &argp, argv);
7a543ca4 224 device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
eada1efc
MM
225 break;
226 case 'o':
227 param = find_arg("Missing <device> option for -o\n", &argp, argv);
228 current = device_tree_add_parsed(current, "%s", param);
229 break;
230 case 'r':
231 param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
232 device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx",
233 atol(param));
234 break;
235 case 't':
236 param = find_arg("Missing <trace> option for -t\n", &argp, argv);
237 if (param[0] == '!')
238 device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1);
239 else
240 device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
241 break;
a983c8f0 242 }
eada1efc 243 p += 1;
a983c8f0 244 }
eada1efc 245 argp += 1;
a983c8f0 246 }
eada1efc
MM
247 /* force the trace node to (re)process its options */
248 device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL);
249 /* return where the options end */
250 return argv + argp;
a983c8f0
MM
251}
252
253
eada1efc 254/* create the simulator proper from the device tree and executable */
8b3797aa 255
eada1efc
MM
256INLINE_PSIM\
257(psim *)
258psim_create(const char *file_name,
259 device *root)
8b3797aa
MM
260{
261 int cpu_nr;
a983c8f0 262 const char *env;
8b3797aa 263 psim *system;
eada1efc
MM
264 os_emul *os_emulation;
265 int nr_cpus;
8b3797aa 266
eada1efc
MM
267 /* given this partially populated device tree, os_emul_create() uses
268 it and file_name to determine the selected emulation and hence
269 further populate the tree with any other required nodes. */
270
271 os_emulation = os_emul_create(file_name, root);
272 if (os_emulation == NULL)
273 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
8b3797aa 274
a983c8f0 275 /* fill in the missing real number of CPU's */
eada1efc
MM
276 nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
277 if (MAX_NR_PROCESSORS < nr_cpus)
278 error("target and configured number of cpus conflict\n");
a983c8f0
MM
279
280 /* fill in the missing TARGET BYTE ORDER information */
eada1efc
MM
281 current_target_byte_order
282 = (device_find_boolean_property(root, "/options/little-endian?")
283 ? LITTLE_ENDIAN
284 : BIG_ENDIAN);
a983c8f0 285 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
eada1efc 286 error("target and configured byte order conflict\n");
8b3797aa 287
a983c8f0
MM
288 /* fill in the missing HOST BYTE ORDER information */
289 current_host_byte_order = (current_host_byte_order = 1,
290 (*(char*)(&current_host_byte_order)
291 ? LITTLE_ENDIAN
292 : BIG_ENDIAN));
293 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
eada1efc 294 error("host and configured byte order conflict\n");
8b3797aa
MM
295
296 /* fill in the missing OEA/VEA information */
eada1efc 297 env = device_find_string_property(root, "/openprom/options/env");
4dcb0cdd
MM
298 current_environment = ((strcmp(env, "user") == 0
299 || strcmp(env, "uea") == 0)
a983c8f0 300 ? USER_ENVIRONMENT
4dcb0cdd
MM
301 : (strcmp(env, "virtual") == 0
302 || strcmp(env, "vea") == 0)
8b3797aa 303 ? VIRTUAL_ENVIRONMENT
4dcb0cdd
MM
304 : (strcmp(env, "operating") == 0
305 || strcmp(env, "oea") == 0)
a983c8f0
MM
306 ? OPERATING_ENVIRONMENT
307 : 0);
308 if (current_environment == 0)
eada1efc 309 error("unreconized /options env property\n");
a983c8f0 310 if (CURRENT_ENVIRONMENT != current_environment)
eada1efc 311 error("target and configured environment conflict\n");
8b3797aa
MM
312
313 /* fill in the missing ALLIGNMENT information */
eada1efc
MM
314 current_alignment
315 = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
316 ? STRICT_ALIGNMENT
317 : NONSTRICT_ALIGNMENT);
a983c8f0 318 if (CURRENT_ALIGNMENT != current_alignment)
eada1efc 319 error("target and configured alignment conflict\n");
a983c8f0
MM
320
321 /* fill in the missing FLOATING POINT information */
eada1efc
MM
322 current_floating_point
323 = (device_find_boolean_property(root, "/openprom/options/floating-point?")
324 ? HARD_FLOATING_POINT
325 : SOFT_FLOATING_POINT);
a983c8f0 326 if (CURRENT_FLOATING_POINT != current_floating_point)
eada1efc
MM
327 error("target and configured floating-point conflict\n");
328
329 /* sort out the level of detail for issue modeling */
330 current_model_issue
331 = device_find_integer_property(root, "/openprom/options/model-issue");
332 if (CURRENT_MODEL_ISSUE != current_model_issue)
333 error("target and configured model-issue conflict\n");
334
335 /* sort out our model architecture - wrong.
336
337 FIXME: this should be obtaining the required information from the
338 device tree via the "/chosen" property "cpu" which is an instance
339 (ihandle) for the only executing processor. By converting that
340 ihandle into the corresponding cpu's phandle and then querying
341 the "name" property, the cpu type can be determined. Ok? */
342
343 model_set(device_find_string_property(root, "/openprom/options/model"));
344
345 /* create things */
346 system = ZALLOC(psim);
347 system->events = event_queue_create();
348 system->memory = core_create(root);
349 system->monitor = mon_create();
350 system->nr_cpus = nr_cpus;
351 system->os_emulation = os_emulation;
352 system->devices = root;
353
354 /* now all the processors attaching to each their per-cpu information */
355 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
356 system->processors[cpu_nr] = cpu_create(system,
357 system->memory,
eada1efc
MM
358 mon_cpu(system->monitor,
359 cpu_nr),
360 system->os_emulation,
361 cpu_nr);
362 }
363
364 /* dump out the contents of the device tree */
365 if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
366 device_tree_traverse(root, device_tree_print_device, NULL, NULL);
367 if (ppc_trace[trace_dump_device_tree])
368 error("");
8b3797aa
MM
369
370 return system;
371}
372
373
374/* allow the simulation to stop/restart abnormaly */
375
eada1efc
MM
376STATIC_INLINE_PSIM\
377(void)
8b3797aa
MM
378psim_set_halt_and_restart(psim *system,
379 void *halt_jmp_buf,
380 void *restart_jmp_buf)
381{
382 system->path_to_halt = halt_jmp_buf;
383 system->path_to_restart = restart_jmp_buf;
384}
385
eada1efc
MM
386STATIC_INLINE_PSIM\
387(void)
8b3797aa
MM
388psim_clear_halt_and_restart(psim *system)
389{
390 system->path_to_halt = NULL;
391 system->path_to_restart = NULL;
392}
393
eada1efc
MM
394INLINE_PSIM\
395(void)
8b3797aa
MM
396psim_restart(psim *system,
397 int current_cpu)
398{
399 system->last_cpu = current_cpu;
400 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
401}
402
403
eada1efc
MM
404INLINE_PSIM\
405(void)
8b3797aa
MM
406psim_halt(psim *system,
407 int current_cpu,
8b3797aa
MM
408 stop_reason reason,
409 int signal)
410{
88f1eac4 411 ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
8b3797aa
MM
412 system->last_cpu = current_cpu;
413 system->halt_status.cpu_nr = current_cpu;
414 system->halt_status.reason = reason;
415 system->halt_status.signal = signal;
88f1eac4
MM
416 system->halt_status.program_counter =
417 cpu_get_program_counter(system->processors[current_cpu]);
8b3797aa
MM
418 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
419}
420
eada1efc
MM
421INLINE_PSIM\
422(psim_status)
8b3797aa
MM
423psim_get_status(psim *system)
424{
425 return system->halt_status;
426}
427
428
eada1efc
MM
429INLINE_PSIM\
430(cpu *)
8b3797aa
MM
431psim_cpu(psim *system,
432 int cpu_nr)
433{
434 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
435 return NULL;
436 else
437 return system->processors[cpu_nr];
438}
439
440
eada1efc
MM
441INLINE_PSIM\
442(device *)
a983c8f0
MM
443psim_device(psim *system,
444 const char *path)
8b3797aa 445{
a983c8f0 446 return device_tree_find_device(system->devices, path);
8b3797aa
MM
447}
448
88f1eac4
MM
449INLINE_PSIM\
450(event_queue *)
451psim_event_queue(psim *system)
452{
453 return system->events;
454}
455
8b3797aa 456
8b3797aa 457
eada1efc
MM
458INLINE_PSIM\
459(void)
a983c8f0 460psim_init(psim *system)
8b3797aa 461{
a983c8f0 462 int cpu_nr;
8b3797aa 463
a983c8f0
MM
464 /* scrub the monitor */
465 mon_init(system->monitor, system->nr_cpus);
eada1efc
MM
466 os_emul_init(system->os_emulation, system->nr_cpus);
467 event_queue_init(system->events);
8b3797aa 468
a983c8f0
MM
469 /* scrub all the cpus */
470 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
471 cpu_init(system->processors[cpu_nr]);
8b3797aa 472
eada1efc 473 /* init all the devices (which updates the cpus) */
a983c8f0 474 device_tree_init(system->devices, system);
8b3797aa 475
eada1efc
MM
476 /* now sync each cpu against the initialized state of its registers */
477 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
478 cpu_synchronize_context(system->processors[cpu_nr]);
479 cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
480 }
481
a983c8f0
MM
482 /* force loop to restart */
483 system->last_cpu = system->nr_cpus - 1;
8b3797aa
MM
484}
485
eada1efc
MM
486INLINE_PSIM\
487(void)
8b3797aa
MM
488psim_stack(psim *system,
489 char **argv,
490 char **envp)
491{
a983c8f0
MM
492 /* pass the stack device the argv/envp and let it work out what to
493 do with it */
eada1efc
MM
494 device *stack_device = device_tree_find_device(system->devices,
495 "/openprom/init/stack");
496 if (stack_device != (device*)0) {
497 unsigned_word stack_pointer;
498 psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
499 device_ioctl(stack_device,
500 system,
501 NULL, /*cpu*/
502 0, /*cia*/
503 stack_pointer,
504 argv,
505 envp);
506 }
8b3797aa
MM
507}
508
509
510
511/* EXECUTE REAL CODE:
512
513 Unfortunatly, there are multiple cases to consider vis:
514
515 <icache> X <smp> X <events> X <keep-running-flag> X ...
516
517 Consequently this function is written in multiple different ways */
518
eada1efc
MM
519STATIC_INLINE_PSIM\
520(void)
8b3797aa
MM
521run_until_stop(psim *system,
522 volatile int *keep_running)
523{
a983c8f0
MM
524 jmp_buf halt;
525 jmp_buf restart;
a983c8f0 526#if WITH_IDECODE_CACHE_SIZE
eada1efc 527 int cpu_nr;
a983c8f0
MM
528 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
529 cpu_flush_icache(system->processors[cpu_nr]);
530#endif
531 psim_set_halt_and_restart(system, &halt, &restart);
8b3797aa 532
a983c8f0 533#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
8b3797aa
MM
534
535 /* CASE 1: No instruction cache and no SMP.
536
537 In this case, we can take advantage of the fact that the current
538 instruction address does not need to be returned to the cpu
539 object after every execution of an instruction. Instead it only
540 needs to be saved when either A. the main loop exits or B. a
541 cpu-{halt,restart} call forces the loop to be re-entered. The
542 later functions always save the current cpu instruction
543 address. */
544
8b3797aa
MM
545 if (!setjmp(halt)) {
546 do {
547 if (!setjmp(restart)) {
548 cpu *const processor = system->processors[0];
549 unsigned_word cia = cpu_get_program_counter(processor);
550 do {
551 if (WITH_EVENTS) {
552 if (event_queue_tick(system->events)) {
553 cpu_set_program_counter(processor, cia);
554 event_queue_process(system->events);
555 cia = cpu_get_program_counter(processor);
556 }
557 }
558 {
559 instruction_word const instruction
560 = vm_instruction_map_read(cpu_instruction_map(processor),
561 processor, cia);
562 cia = idecode_issue(processor, instruction, cia);
563 }
564 } while (keep_running == NULL || *keep_running);
565 cpu_set_program_counter(processor, cia);
566 }
567 } while(keep_running == NULL || *keep_running);
568 }
8b3797aa
MM
569#endif
570
571
a983c8f0 572#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
8b3797aa
MM
573
574 /* CASE 2: Instruction case but no SMP
575
576 Here, the additional complexity comes from there being two
577 different cache implementations. A simple function address cache
578 or a full cracked instruction cache */
579
8b3797aa
MM
580 if (!setjmp(halt)) {
581 do {
582 if (!setjmp(restart)) {
583 cpu *const processor = system->processors[0];
584 unsigned_word cia = cpu_get_program_counter(processor);
585 do {
586 if (WITH_EVENTS)
587 if (event_queue_tick(system->events)) {
588 cpu_set_program_counter(processor, cia);
589 event_queue_process(system->events);
590 cia = cpu_get_program_counter(processor);
591 }
592 {
a983c8f0
MM
593 idecode_cache *const cache_entry = cpu_icache_entry(processor,
594 cia);
8b3797aa
MM
595 if (cache_entry->address == cia) {
596 idecode_semantic *const semantic = cache_entry->semantic;
8b3797aa 597 cia = semantic(processor, cache_entry, cia);
8b3797aa
MM
598 }
599 else {
600 instruction_word const instruction
601 = vm_instruction_map_read(cpu_instruction_map(processor),
602 processor,
603 cia);
8b3797aa
MM
604 idecode_semantic *const semantic = idecode(processor,
605 instruction,
606 cia,
607 cache_entry);
28816f45 608
eada1efc
MM
609 if (WITH_MON != 0)
610 mon_event(mon_event_icache_miss, processor, cia);
8b3797aa
MM
611 cache_entry->address = cia;
612 cache_entry->semantic = semantic;
8b3797aa 613 cia = semantic(processor, cache_entry, cia);
8b3797aa
MM
614 }
615 }
616 } while (keep_running == NULL || *keep_running);
617 cpu_set_program_counter(processor, cia);
618 }
619 } while(keep_running == NULL || *keep_running);
620 }
8b3797aa
MM
621#endif
622
623
a983c8f0 624#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
8b3797aa
MM
625
626 /* CASE 3: No ICACHE but SMP
627
628 The complexity here comes from needing to correctly restart the
629 system when it is aborted. In particular if cpu0 requests a
630 restart, the next cpu is still cpu1. Cpu0 being restarted after
631 all the other CPU's and the event queue have been processed */
632
8b3797aa
MM
633 if (!setjmp(halt)) {
634 int first_cpu = setjmp(restart);
635 if (first_cpu == 0)
636 first_cpu = system->last_cpu + 1;
637 do {
638 int current_cpu;
639 for (current_cpu = first_cpu, first_cpu = 0;
640 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
641 current_cpu++) {
642 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
643 if (event_queue_tick(system->events))
644 event_queue_process(system->events);
645 }
646 else {
647 cpu *const processor = system->processors[current_cpu];
648 unsigned_word const cia = cpu_get_program_counter(processor);
649 instruction_word instruction =
650 vm_instruction_map_read(cpu_instruction_map(processor),
651 processor,
652 cia);
653 cpu_set_program_counter(processor,
654 idecode_issue(processor, instruction, cia));
655 }
656 if (!(keep_running == NULL || *keep_running)) {
657 system->last_cpu = current_cpu;
658 break;
659 }
660 }
661 } while (keep_running == NULL || *keep_running);
662 }
8b3797aa
MM
663#endif
664
a983c8f0 665#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
8b3797aa
MM
666
667 /* CASE 4: ICACHE and SMP ...
668
669 This time, everything goes wrong. Need to restart loops
670 correctly, need to save the program counter and finally need to
671 keep track of each processors current address! */
672
8b3797aa
MM
673 if (!setjmp(halt)) {
674 int first_cpu = setjmp(restart);
675 if (!first_cpu)
676 first_cpu = system->last_cpu + 1;
677 do {
678 int current_cpu;
679 for (current_cpu = first_cpu, first_cpu = 0;
680 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
681 current_cpu++) {
682 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
683 if (event_queue_tick(system->events))
684 event_queue_process(system->events);
685 }
686 else {
687 cpu *processor = system->processors[current_cpu];
688 unsigned_word const cia = cpu_get_program_counter(processor);
a983c8f0 689 idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
8b3797aa
MM
690 if (cache_entry->address == cia) {
691 idecode_semantic *semantic = cache_entry->semantic;
8b3797aa 692 cpu_set_program_counter(processor,
a983c8f0 693 semantic(processor, cache_entry, cia));
8b3797aa
MM
694 }
695 else {
696 instruction_word instruction =
697 vm_instruction_map_read(cpu_instruction_map(processor),
698 processor,
699 cia);
8b3797aa
MM
700 idecode_semantic *semantic = idecode(processor,
701 instruction,
702 cia,
703 cache_entry);
28816f45 704
eada1efc
MM
705 if (WITH_MON != 0)
706 mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
8b3797aa
MM
707 cache_entry->address = cia;
708 cache_entry->semantic = semantic;
8b3797aa 709 cpu_set_program_counter(processor,
a983c8f0 710 semantic(processor, cache_entry, cia));
8b3797aa
MM
711 }
712 }
713 if (!(keep_running == NULL || *keep_running))
714 break;
715 }
716 } while (keep_running == NULL || *keep_running);
717 }
8b3797aa 718#endif
a983c8f0
MM
719
720 psim_clear_halt_and_restart(system);
8b3797aa
MM
721}
722
723
724/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
725 thing */
726
eada1efc
MM
727INLINE_PSIM\
728(void)
8b3797aa
MM
729psim_step(psim *system)
730{
731 volatile int keep_running = 0;
a983c8f0 732 run_until_stop(system, &keep_running);
8b3797aa
MM
733}
734
eada1efc
MM
735INLINE_PSIM\
736(void)
8b3797aa
MM
737psim_run(psim *system)
738{
739 run_until_stop(system, NULL);
740}
741
eada1efc
MM
742INLINE_PSIM\
743(void)
8b3797aa
MM
744psim_run_until_stop(psim *system,
745 volatile int *keep_running)
746{
747 run_until_stop(system, keep_running);
748}
749
750
751
752/* storage manipulation functions */
753
eada1efc
MM
754INLINE_PSIM\
755(void)
8b3797aa
MM
756psim_read_register(psim *system,
757 int which_cpu,
758 void *buf,
759 const char reg[],
760 transfer_mode mode)
761{
762 register_descriptions description;
7a543ca4 763 char cooked_buf[sizeof(unsigned_8)];
8b3797aa
MM
764 cpu *processor;
765
766 /* find our processor */
a983c8f0 767 if (which_cpu == MAX_NR_PROCESSORS)
8b3797aa 768 which_cpu = system->last_cpu;
a983c8f0
MM
769 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
770 error("psim_read_register() - invalid processor %d\n", which_cpu);
8b3797aa
MM
771 processor = system->processors[which_cpu];
772
773 /* find the register description */
774 description = register_description(reg);
775 if (description.type == reg_invalid)
776 error("psim_read_register() invalid register name `%s'\n", reg);
777
778 /* get the cooked value */
779 switch (description.type) {
780
781 case reg_gpr:
782 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
783 break;
784
785 case reg_spr:
786 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
787 break;
788
789 case reg_sr:
790 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
791 break;
792
793 case reg_fpr:
794 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
795 break;
796
797 case reg_pc:
798 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
799 break;
800
801 case reg_cr:
802 *(creg*)cooked_buf = cpu_registers(processor)->cr;
803 break;
804
805 case reg_msr:
806 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
807 break;
808
809 default:
45525d8d
MM
810 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
811 (unsigned long)processor, (unsigned long)buf, reg,
8b3797aa
MM
812 "read of this register unimplemented");
813 break;
814
815 }
816
817 /* the PSIM internal values are in host order. To fetch raw data,
818 they need to be converted into target order and then returned */
819 if (mode == raw_transfer) {
820 /* FIXME - assumes that all registers are simple integers */
821 switch (description.size) {
822 case 1:
823 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
824 break;
825 case 2:
826 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
827 break;
828 case 4:
829 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
830 break;
831 case 8:
832 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
833 break;
834 }
835 }
836 else {
45525d8d 837 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
8b3797aa
MM
838 }
839
840}
841
842
843
eada1efc
MM
844INLINE_PSIM\
845(void)
8b3797aa
MM
846psim_write_register(psim *system,
847 int which_cpu,
848 const void *buf,
849 const char reg[],
850 transfer_mode mode)
851{
852 cpu *processor;
853 register_descriptions description;
7a543ca4 854 char cooked_buf[sizeof(unsigned_8)];
8b3797aa
MM
855
856 /* find our processor */
a983c8f0
MM
857 if (which_cpu == MAX_NR_PROCESSORS)
858 which_cpu = system->last_cpu;
8b3797aa
MM
859 if (which_cpu == -1) {
860 int i;
861 for (i = 0; i < system->nr_cpus; i++)
862 psim_write_register(system, i, buf, reg, mode);
863 return;
864 }
8b3797aa
MM
865 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
866 error("psim_read_register() - invalid processor %d\n", which_cpu);
867 }
868
869 processor = system->processors[which_cpu];
870
871 /* find the description of the register */
872 description = register_description(reg);
873 if (description.type == reg_invalid)
874 error("psim_write_register() invalid register name %s\n", reg);
875
876 /* If the data is comming in raw (target order), need to cook it
877 into host order before putting it into PSIM's internal structures */
878 if (mode == raw_transfer) {
879 switch (description.size) {
880 case 1:
881 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
882 break;
883 case 2:
884 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
885 break;
886 case 4:
887 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
888 break;
889 case 8:
890 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
891 break;
892 }
893 }
894 else {
45525d8d 895 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
8b3797aa
MM
896 }
897
898 /* put the cooked value into the register */
899 switch (description.type) {
900
901 case reg_gpr:
902 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
903 break;
904
905 case reg_fpr:
906 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
907 break;
908
909 case reg_pc:
910 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
911 break;
912
913 case reg_spr:
914 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
915 break;
916
917 case reg_sr:
918 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
919 break;
920
921 case reg_cr:
922 cpu_registers(processor)->cr = *(creg*)cooked_buf;
923 break;
924
925 case reg_msr:
926 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
927 break;
928
929 default:
45525d8d
MM
930 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
931 (unsigned long)processor, (unsigned long)cooked_buf, reg,
8b3797aa
MM
932 "read of this register unimplemented");
933 break;
934
935 }
936
937}
938
939
940
eada1efc
MM
941INLINE_PSIM\
942(unsigned)
8b3797aa
MM
943psim_read_memory(psim *system,
944 int which_cpu,
945 void *buffer,
946 unsigned_word vaddr,
a983c8f0 947 unsigned nr_bytes)
8b3797aa
MM
948{
949 cpu *processor;
a983c8f0 950 if (which_cpu == MAX_NR_PROCESSORS)
8b3797aa 951 which_cpu = system->last_cpu;
a983c8f0
MM
952 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
953 error("psim_read_memory() invalid cpu\n");
8b3797aa
MM
954 processor = system->processors[which_cpu];
955 return vm_data_map_read_buffer(cpu_data_map(processor),
a983c8f0 956 buffer, vaddr, nr_bytes);
8b3797aa
MM
957}
958
959
eada1efc
MM
960INLINE_PSIM\
961(unsigned)
8b3797aa
MM
962psim_write_memory(psim *system,
963 int which_cpu,
964 const void *buffer,
965 unsigned_word vaddr,
a983c8f0 966 unsigned nr_bytes,
8b3797aa
MM
967 int violate_read_only_section)
968{
969 cpu *processor;
a983c8f0 970 if (which_cpu == MAX_NR_PROCESSORS)
8b3797aa 971 which_cpu = system->last_cpu;
a983c8f0
MM
972 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
973 error("psim_read_memory() invalid cpu\n");
8b3797aa
MM
974 processor = system->processors[which_cpu];
975 return vm_data_map_write_buffer(cpu_data_map(processor),
a983c8f0 976 buffer, vaddr, nr_bytes, 1);
8b3797aa
MM
977}
978
979
eada1efc
MM
980INLINE_PSIM\
981(void)
a983c8f0
MM
982psim_print_info(psim *system,
983 int verbose)
83d96c6e 984{
73c4941b 985 mon_print_info(system, system->monitor, verbose);
83d96c6e
MM
986}
987
a983c8f0 988
eada1efc
MM
989/* Merge a device tree and a device file. */
990
991INLINE_PSIM\
992(void)
993psim_merge_device_file(device *root,
994 const char *file_name)
995{
996 FILE *description = fopen(file_name, "r");
997 int line_nr = 0;
998 char device_path[1000];
999 device *current = root;
1000 while (fgets(device_path, sizeof(device_path), description)) {
1001 /* check all of line was read */
1002 if (strchr(device_path, '\n') == NULL) {
1003 fclose(description);
1004 error("create_filed_device_tree() line %d to long: %s\n",
1005 line_nr, device_path);
1006 }
1007 line_nr++;
1008 /* parse this line */
1009 current = device_tree_add_parsed(current, "%s", device_path);
1010 }
1011 fclose(description);
1012}
1013
1014
8b3797aa 1015#endif /* _PSIM_C_ */
This page took 0.092443 seconds and 4 git commands to generate.