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