January 23rd merge
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef _PSIM_C_
23 #define _PSIM_C_
24
25 #include "cpu.h" /* includes psim.h */
26 #include "idecode.h"
27 #include "options.h"
28
29 #include "tree.h"
30
31 #include <stdio.h>
32 #include <ctype.h>
33
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37
38 #include <setjmp.h>
39
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
48
49 #include "bfd.h"
50
51
52 /* system structure, actual size of processor array determined at
53 runtime */
54
55 struct _psim {
56 event_queue *events;
57 device *devices;
58 mon *monitor;
59 os_emul *os_emulation;
60 core *memory;
61
62 /* escape routine for inner functions */
63 void *path_to_halt;
64 void *path_to_restart;
65
66 /* status from last halt */
67 psim_status halt_status;
68
69 /* the processors proper */
70 int nr_cpus;
71 int last_cpu; /* CPU that last (tried to) execute an instruction */
72 cpu *processors[MAX_NR_PROCESSORS];
73 };
74
75
76 int current_target_byte_order;
77 int current_host_byte_order;
78 int current_environment;
79 int current_alignment;
80 int current_floating_point;
81 int current_model_issue = MODEL_ISSUE_IGNORE;
82 int current_stdio = DO_USE_STDIO;
83 model_enum current_model = WITH_DEFAULT_MODEL;
84
85
86 /* create the device tree */
87
88 INLINE_PSIM\
89 (device *)
90 psim_tree(void)
91 {
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");
102 return root;
103 }
104
105 STATIC_INLINE_PSIM\
106 (char *)
107 find_arg(char *err_msg,
108 int *ptr_to_argp,
109 char **argv)
110 {
111 *ptr_to_argp += 1;
112 if (argv[*ptr_to_argp] == NULL)
113 error(err_msg);
114 return argv[*ptr_to_argp];
115 }
116
117 INLINE_PSIM\
118 (void)
119 psim_usage(int verbose)
120 {
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");
127 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
128 if (verbose) {
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");
138 printf_filtered("\n"); }
139 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
140 if (verbose) {
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");
144 printf_filtered("\n"); }
145 printf_filtered("\t<psim-option> See below\n");
146 printf_filtered("\n");
147 printf_filtered("The following are valid <psim-option>s:\n");
148 printf_filtered("\n");
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");
157 if (verbose) {
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");
164 printf_filtered("\n"); }
165
166 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
167 if (verbose) { printf_filtered("\n"); }
168
169 printf_filtered("\t-h -? -H give more detailed usage\n");
170 if (verbose) { printf_filtered("\n"); }
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");
187 if (verbose) { printf_filtered("\n"); }
188
189 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
190 if (verbose) { printf_filtered("\n"); }
191
192 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
193 if (verbose) { printf_filtered("\n"); }
194
195 printf_filtered("\n");
196 trace_usage(verbose);
197 device_usage(verbose);
198 if (verbose > 1) {
199 printf_filtered("\n");
200 print_options();
201 }
202 error("");
203 }
204
205 INLINE_PSIM\
206 (char **)
207 psim_options(device *root,
208 char **argv)
209 {
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);
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);
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':
240 tree_parse(root, "/openprom/trace/print-info 1");
241 break;
242 case 'I':
243 tree_parse(root, "/openprom/trace/print-info 2");
244 tree_parse(root, "/openprom/options/model-issue %d",
245 MODEL_ISSUE_PROCESS);
246 break;
247 case 'm':
248 param = find_arg("Missing <model> option for -m\n", &argp, argv);
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);
254 break;
255 case 'o':
256 param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
257 current = tree_parse(current, "%s", param);
258 break;
259 case 'r':
260 param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
261 tree_parse(root, "/openprom/options/oea-memory-size %s",
262 param);
263 break;
264 case 't':
265 param = find_arg("Missing <trace> option for -t\n", &argp, argv);
266 if (param[0] == '!')
267 tree_parse(root, "/openprom/trace/%s 0", param+1);
268 else
269 tree_parse(root, "/openprom/trace/%s 1", param);
270 break;
271 }
272 p += 1;
273 }
274 argp += 1;
275 }
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);
281
282 /* return where the options end */
283 return argv + argp;
284 }
285
286 INLINE_PSIM\
287 (void)
288 psim_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
315
316 /* create the simulator proper from the device tree and executable */
317
318 INLINE_PSIM\
319 (psim *)
320 psim_create(const char *file_name,
321 device *root)
322 {
323 int cpu_nr;
324 const char *env;
325 psim *system;
326 os_emul *os_emulation;
327 int nr_cpus;
328
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);
336
337 /* fill in the missing real number of CPU's */
338 nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
339 if (MAX_NR_PROCESSORS < nr_cpus)
340 error("target and configured number of cpus conflict\n");
341
342 /* fill in the missing TARGET BYTE ORDER information */
343 current_target_byte_order
344 = (tree_find_boolean_property(root, "/options/little-endian?")
345 ? LITTLE_ENDIAN
346 : BIG_ENDIAN);
347 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
348 error("target and configured byte order conflict\n");
349
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)
356 error("host and configured byte order conflict\n");
357
358 /* fill in the missing OEA/VEA information */
359 env = tree_find_string_property(root, "/openprom/options/env");
360 current_environment = ((strcmp(env, "user") == 0
361 || strcmp(env, "uea") == 0)
362 ? USER_ENVIRONMENT
363 : (strcmp(env, "virtual") == 0
364 || strcmp(env, "vea") == 0)
365 ? VIRTUAL_ENVIRONMENT
366 : (strcmp(env, "operating") == 0
367 || strcmp(env, "oea") == 0)
368 ? OPERATING_ENVIRONMENT
369 : 0);
370 if (current_environment == 0)
371 error("unreconized /options env property\n");
372 if (CURRENT_ENVIRONMENT != current_environment)
373 error("target and configured environment conflict\n");
374
375 /* fill in the missing ALLIGNMENT information */
376 current_alignment
377 = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
378 ? STRICT_ALIGNMENT
379 : NONSTRICT_ALIGNMENT);
380 if (CURRENT_ALIGNMENT != current_alignment)
381 error("target and configured alignment conflict\n");
382
383 /* fill in the missing FLOATING POINT information */
384 current_floating_point
385 = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
386 ? HARD_FLOATING_POINT
387 : SOFT_FLOATING_POINT);
388 if (CURRENT_FLOATING_POINT != current_floating_point)
389 error("target and configured floating-point conflict\n");
390
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
399 /* sort out the level of detail for issue modeling */
400 current_model_issue
401 = tree_find_integer_property(root, "/openprom/options/model-issue");
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
413 model_set(tree_find_string_property(root, "/openprom/options/model"));
414
415 /* create things */
416 system = ZALLOC(psim);
417 system->events = event_queue_create();
418 system->memory = core_from_device(root);
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,
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])
436 tree_print(root);
437 if (ppc_trace[trace_dump_device_tree])
438 error("");
439
440 return system;
441 }
442
443
444 /* allow the simulation to stop/restart abnormaly */
445
446 INLINE_PSIM\
447 (void)
448 psim_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
456 INLINE_PSIM\
457 (void)
458 psim_clear_halt_and_restart(psim *system)
459 {
460 system->path_to_halt = NULL;
461 system->path_to_restart = NULL;
462 }
463
464 INLINE_PSIM\
465 (void)
466 psim_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
474 INLINE_PSIM\
475 (void)
476 psim_halt(psim *system,
477 int current_cpu,
478 stop_reason reason,
479 int signal)
480 {
481 ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
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;
486 system->halt_status.program_counter =
487 cpu_get_program_counter(system->processors[current_cpu]);
488 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
489 }
490
491
492 INLINE_PSIM\
493 (int)
494 psim_last_cpu(psim *system)
495 {
496 return system->last_cpu;
497 }
498
499 INLINE_PSIM\
500 (int)
501 psim_nr_cpus(psim *system)
502 {
503 return system->nr_cpus;
504 }
505
506 INLINE_PSIM\
507 (psim_status)
508 psim_get_status(psim *system)
509 {
510 return system->halt_status;
511 }
512
513
514 INLINE_PSIM\
515 (cpu *)
516 psim_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
526 INLINE_PSIM\
527 (device *)
528 psim_device(psim *system,
529 const char *path)
530 {
531 return tree_find_device(system->devices, path);
532 }
533
534 INLINE_PSIM\
535 (event_queue *)
536 psim_event_queue(psim *system)
537 {
538 return system->events;
539 }
540
541
542
543 INLINE_PSIM\
544 (void)
545 psim_init(psim *system)
546 {
547 int cpu_nr;
548
549 /* scrub the monitor */
550 mon_init(system->monitor, system->nr_cpus);
551
552 /* trash any pending events */
553 event_queue_init(system->events);
554
555 /* scrub all the cpus */
556 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
557 cpu_init(system->processors[cpu_nr]);
558
559 /* init all the devices (which updates the cpus) */
560 tree_init(system->devices, system);
561
562 /* and the emulation (which needs an initialized device tree) */
563 os_emul_init(system->os_emulation, system->nr_cpus);
564
565 /* now sync each cpu against the initialized state of its registers */
566 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
567 cpu *processor = system->processors[cpu_nr];
568 cpu_synchronize_context(processor, cpu_get_program_counter(processor));
569 cpu_page_tlb_invalidate_all(processor);
570 }
571
572 /* force loop to start with first cpu (after processing events) */
573 system->last_cpu = system->nr_cpus - 1;
574 }
575
576 INLINE_PSIM\
577 (void)
578 psim_stack(psim *system,
579 char **argv,
580 char **envp)
581 {
582 /* pass the stack device the argv/envp and let it work out what to
583 do with it */
584 device *stack_device = tree_find_device(system->devices,
585 "/openprom/init/stack");
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,
590 NULL, /*cpu*/
591 0, /*cia*/
592 device_ioctl_create_stack,
593 stack_pointer,
594 argv,
595 envp);
596 }
597 }
598
599
600
601 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
602 thing */
603
604 INLINE_PSIM\
605 (void)
606 psim_step(psim *system)
607 {
608 volatile int keep_running = 0;
609 idecode_run_until_stop(system, &keep_running,
610 system->events, system->processors, system->nr_cpus);
611 }
612
613 INLINE_PSIM\
614 (void)
615 psim_run(psim *system)
616 {
617 idecode_run(system,
618 system->events, system->processors, system->nr_cpus);
619 }
620
621 INLINE_PSIM\
622 (void)
623 psim_run_until_stop(psim *system,
624 volatile int *keep_running)
625 {
626 idecode_run_until_stop(system, keep_running,
627 system->events, system->processors, system->nr_cpus);
628 }
629
630
631
632 /* storage manipulation functions */
633
634 INLINE_PSIM\
635 (void)
636 psim_read_register(psim *system,
637 int which_cpu,
638 void *buf,
639 const char reg[],
640 transfer_mode mode)
641 {
642 register_descriptions description;
643 char cooked_buf[sizeof(unsigned_8)];
644 cpu *processor;
645
646 /* find our processor */
647 if (which_cpu == MAX_NR_PROCESSORS)
648 which_cpu = system->last_cpu;
649 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
650 error("psim_read_register() - invalid processor %d\n", which_cpu);
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
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
706 default:
707 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
708 (unsigned long)processor, (unsigned long)buf, reg,
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 {
734 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
735 }
736
737 }
738
739
740
741 INLINE_PSIM\
742 (void)
743 psim_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;
751 char cooked_buf[sizeof(unsigned_8)];
752
753 /* find our processor */
754 if (which_cpu == MAX_NR_PROCESSORS)
755 which_cpu = system->last_cpu;
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 }
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 {
792 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
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:
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,
829 "read of this register unimplemented");
830 break;
831
832 }
833
834 }
835
836
837
838 INLINE_PSIM\
839 (unsigned)
840 psim_read_memory(psim *system,
841 int which_cpu,
842 void *buffer,
843 unsigned_word vaddr,
844 unsigned nr_bytes)
845 {
846 cpu *processor;
847 if (which_cpu == MAX_NR_PROCESSORS)
848 which_cpu = system->last_cpu;
849 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
850 error("psim_read_memory() invalid cpu\n");
851 processor = system->processors[which_cpu];
852 return vm_data_map_read_buffer(cpu_data_map(processor),
853 buffer, vaddr, nr_bytes,
854 NULL, -1);
855 }
856
857
858 INLINE_PSIM\
859 (unsigned)
860 psim_write_memory(psim *system,
861 int which_cpu,
862 const void *buffer,
863 unsigned_word vaddr,
864 unsigned nr_bytes,
865 int violate_read_only_section)
866 {
867 cpu *processor;
868 if (which_cpu == MAX_NR_PROCESSORS)
869 which_cpu = system->last_cpu;
870 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
871 error("psim_read_memory() invalid cpu\n");
872 processor = system->processors[which_cpu];
873 return vm_data_map_write_buffer(cpu_data_map(processor),
874 buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
875 NULL, -1);
876 }
877
878
879 INLINE_PSIM\
880 (void)
881 psim_print_info(psim *system,
882 int verbose)
883 {
884 mon_print_info(system, system->monitor, verbose);
885 }
886
887
888 /* Merge a device tree and a device file. */
889
890 INLINE_PSIM\
891 (void)
892 psim_merge_device_file(device *root,
893 const char *file_name)
894 {
895 FILE *description;
896 int line_nr;
897 char device_path[1000];
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;
909 while (fgets(device_path, sizeof(device_path), description)) {
910 char *device;
911 /* check that the full line was read */
912 if (strchr(device_path, '\n') == NULL) {
913 fclose(description);
914 error("%s:%d: line to long - %s",
915 file_name, line_nr, device_path);
916 }
917 else
918 *strchr(device_path, '\n') = '\0';
919 line_nr++;
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 }
948 /* parse this line */
949 current = tree_parse(current, "%s", device);
950 }
951 fclose(description);
952 }
953
954
955 #endif /* _PSIM_C_ */
This page took 0.050075 seconds and 5 git commands to generate.