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