1 /* This file is part of the program psim.
3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
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 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "cpu.h" /* includes psim.h */
39 #include "libiberty.h"
40 #include "gdb/signals.h"
42 /* system structure, actual size of processor array determined at
49 os_emul
*os_emulation
;
52 /* escape routine for inner functions */
54 void *path_to_restart
;
56 /* status from last halt */
57 psim_status halt_status
;
59 /* the processors proper */
61 int last_cpu
; /* CPU that last (tried to) execute an instruction */
62 cpu
*processors
[MAX_NR_PROCESSORS
];
66 enum bfd_endian current_target_byte_order
;
67 int current_environment
;
68 int current_alignment
;
69 int current_floating_point
;
70 int current_model_issue
= MODEL_ISSUE_IGNORE
;
71 int current_stdio
= DO_USE_STDIO
;
72 model_enum current_model
= WITH_DEFAULT_MODEL
;
75 /* create the device tree */
81 device
*root
= tree_parse(NULL
, "core");
82 tree_parse(root
, "/aliases");
83 tree_parse(root
, "/options");
84 tree_parse(root
, "/chosen");
85 tree_parse(root
, "/packages");
86 tree_parse(root
, "/cpus");
87 tree_parse(root
, "/openprom");
88 tree_parse(root
, "/openprom/init");
89 tree_parse(root
, "/openprom/trace");
90 tree_parse(root
, "/openprom/options");
96 find_arg(const char *err_msg
,
101 if (argv
[*ptr_to_argp
] == NULL
)
102 error("%s", err_msg
);
103 return argv
[*ptr_to_argp
];
108 psim_usage (int verbose
, int help
, SIM_OPEN_KIND kind
)
110 printf_filtered("Usage:\n");
111 printf_filtered("\n");
112 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
113 printf_filtered("\n");
114 printf_filtered("Where\n");
115 printf_filtered("\n");
116 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
118 printf_filtered("\t This can either be a PowerPC binary or\n");
119 printf_filtered("\t a text file containing a device tree\n");
120 printf_filtered("\t specification.\n");
121 printf_filtered("\t PSIM will attempt to determine from the\n");
122 printf_filtered("\t specified <image> the intended emulation\n");
123 printf_filtered("\t environment.\n");
124 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
125 printf_filtered("\t environment can be specified using the\n");
126 printf_filtered("\t `-e' option (described below).\n");
127 printf_filtered("\n"); }
128 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
130 printf_filtered("\t These arguments will be passed to\n");
131 printf_filtered("\t <image> (as standard C argv, argc)\n");
132 printf_filtered("\t when <image> is started.\n");
133 printf_filtered("\n"); }
134 printf_filtered("\t<psim-option> See below\n");
135 printf_filtered("\n");
136 printf_filtered("The following are valid <psim-option>s:\n");
137 printf_filtered("\n");
139 printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
141 printf_filtered("\n");
144 printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
146 printf_filtered("\t Specify -i2 for a more detailed display\n");
147 printf_filtered("\n");
150 printf_filtered("\t-I Print execution unit statistics\n");
151 if (verbose
) { printf_filtered("\n"); }
153 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
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 solaris - UEA + Solaris system calls\n");
159 printf_filtered("\t linux - UEA + Linux system calls\n");
160 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
161 printf_filtered("\n"); }
163 printf_filtered("\t-E <endian> Specify the endianness of the target\n");
165 printf_filtered("\t Can be any of the following:\n");
166 printf_filtered("\t big - big endian target\n");
167 printf_filtered("\t little - little endian target\n");
168 printf_filtered("\n"); }
170 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
171 if (verbose
) { printf_filtered("\n"); }
173 printf_filtered("\t-h -? -H give more detailed usage\n");
174 if (verbose
) { printf_filtered("\n"); }
176 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
178 printf_filtered("\t Selects the processor to use when\n");
179 printf_filtered("\t modeling execution units. Includes:\n");
180 printf_filtered("\t 604, 603 and 603e\n");
181 printf_filtered("\n"); }
183 printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
185 printf_filtered("\t Specifies the number of processors that are\n");
186 printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
187 printf_filtered("\t simulation\n");
188 printf_filtered("\n"); }
190 printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
191 if (verbose
) { printf_filtered("\n"); }
193 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
194 if (verbose
) { printf_filtered("\n"); }
196 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
197 if (verbose
) { printf_filtered("\n"); }
199 printf_filtered("\n");
200 trace_usage(verbose
);
201 device_usage(verbose
);
203 printf_filtered("\n");
207 if (kind
== SIM_OPEN_STANDALONE
)
209 if (REPORT_BUGS_TO
[0])
210 printf ("Report bugs to %s\n", REPORT_BUGS_TO
);
215 /* Test "string" for containing a string of digits that form a number
216 between "min" and "max". The return value is the number or "err". */
218 int is_num(const char *string
, int min
, int max
, int err
)
222 for ( ; *string
; ++string
)
224 if (!isdigit(*string
))
229 result
= result
* 10 + (*string
- '0');
231 if (result
< min
|| result
> max
)
239 psim_options(device
*root
,
243 device
*current
= root
;
248 while (argv
[argp
] != NULL
&& argv
[argp
][0] == '-') {
249 const char *p
= argv
[argp
] + 1;
254 printf_filtered ("Invalid Option: %s\n", argv
[argp
]);
255 psim_usage (0, 0, kind
);
258 param
= find_arg("Missing <count> option for -c (max-iterations)\n", &argp
, argv
);
259 tree_parse(root
, "/openprom/options/max-iterations %s", param
);
262 param
= find_arg("Missing <emul> option for -e (os-emul)\n", &argp
, argv
);
263 tree_parse(root
, "/openprom/options/os-emul %s", param
);
266 /* endian spec, ignored for now */
267 param
= find_arg("Missing <endian> option for -E (target-endian)\n", &argp
, argv
);
268 if (strcmp (param
, "big") == 0)
269 tree_parse (root
, "/options/little-endian? false");
270 else if (strcmp (param
, "little") == 0)
271 tree_parse (root
, "/options/little-endian? true");
274 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
275 psim_usage (0, 0, kind
);
280 param
= find_arg("Missing <file> option for -f\n", &argp
, argv
);
281 psim_merge_device_file(root
, param
);
285 psim_usage (1, 1, kind
);
288 psim_usage (2, 1, kind
);
292 tree_parse(root
, "/openprom/trace/print-info %c", p
[1]);
296 tree_parse(root
, "/openprom/trace/print-info 1");
300 tree_parse(root
, "/openprom/trace/print-info 2");
301 tree_parse(root
, "/openprom/options/model-issue %d",
302 MODEL_ISSUE_PROCESS
);
305 param
= find_arg("Missing <model> option for -m (model)\n", &argp
, argv
);
306 tree_parse(root
, "/openprom/options/model \"%s", param
);
309 param
= find_arg("Missing <nr-smp> option for -n (smp)\n", &argp
, argv
);
310 tree_parse(root
, "/openprom/options/smp %s", param
);
313 param
= find_arg("Missing <dev-spec> option for -o\n", &argp
, argv
);
314 if (memcmp(param
, "mpc860c0", 8) == 0)
316 if (param
[8] == '\0')
317 tree_parse(root
, "/options/mpc860c0 5");
318 else if (param
[8] == '=' && is_num(param
+9, 1, 10, 0))
320 tree_parse(root
, "/options/mpc860c0 %s", param
+9);
322 else error("Invalid mpc860c0 option for -o\n");
325 current
= tree_parse(current
, "%s", param
);
328 param
= find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp
, argv
);
329 tree_parse(root
, "/openprom/options/oea-memory-size %s",
333 param
= find_arg("Missing <trace> option for -t (trace/*)\n", &argp
, argv
);
335 tree_parse(root
, "/openprom/trace/%s 0", param
+1);
337 tree_parse(root
, "/openprom/trace/%s 1", param
);
340 /* it's a long option of the form --optionname=optionvalue.
341 Such options can be passed through if we are invoked by
343 if (strstr(argv
[argp
], "architecture") != NULL
) {
344 /* we must consume the argument here, so that we get out
346 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
347 printf_filtered("Warning - architecture parameter ignored\n");
349 else if (strcmp (argv
[argp
], "--help") == 0)
351 psim_usage (0, 1, kind
);
354 else if (strncmp (argv
[argp
], "--sysroot=",
355 sizeof ("--sysroot=") - 1) == 0)
356 /* Ignore this option. */
357 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
358 else if (strcmp (argv
[argp
], "--version") == 0)
360 extern const char version
[];
361 printf ("GNU simulator %s%s\n", PKGVERSION
, version
);
362 printf ("Copyright (C) 2024 Free Software Foundation, Inc.\n");
364 License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\
365 \nThis is free software: you are free to change and redistribute it.\n\
366 There is NO WARRANTY, to the extent permitted by law.\n");
367 if (kind
== SIM_OPEN_STANDALONE
)
374 printf_filtered ("Invalid option: %s\n", argv
[argp
]);
375 psim_usage (0, 0, kind
);
384 /* force the trace node to process its options now *before* the tree
385 initialization occures */
386 device_ioctl(tree_find_device(root
, "/openprom/trace"),
388 device_ioctl_set_trace
);
391 void semantic_init(device
* root
);
395 /* return where the options end */
401 psim_command(device
*root
,
405 if (argv
[argp
] == NULL
) {
408 else if (strcmp(argv
[argp
], "trace") == 0) {
409 const char *opt
= find_arg("Missing <trace> option", &argp
, argv
);
411 trace_option(opt
+ 1, 0);
413 trace_option(opt
, 1);
415 else if (strcmp(*argv
, "change-media") == 0) {
416 const char *device
= find_arg("Missing device name", &argp
, argv
);
417 const char *media
= argv
[++argp
];
418 device_ioctl(tree_find_device(root
, device
), NULL
, 0,
419 device_ioctl_change_media
, media
);
422 printf_filtered("Unknown PSIM command %s, try\n", argv
[argp
]);
423 printf_filtered(" trace <trace-option>\n");
424 printf_filtered(" change-media <device> [ <new-image> ]\n");
429 /* create the simulator proper from the device tree and executable */
433 psim_create(const char *file_name
,
439 os_emul
*os_emulation
;
442 /* given this partially populated device tree, os_emul_create() uses
443 it and file_name to determine the selected emulation and hence
444 further populate the tree with any other required nodes. */
446 os_emulation
= os_emul_create(file_name
, root
);
447 if (os_emulation
== NULL
)
448 error("psim: either file %s was not recognized or unreconized or unknown os-emulation type\n", file_name
);
450 /* fill in the missing real number of CPU's */
451 nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
452 if (MAX_NR_PROCESSORS
< nr_cpus
)
453 error("target and configured number of cpus conflict\n");
455 /* fill in the missing TARGET BYTE ORDER information */
456 current_target_byte_order
457 = (tree_find_boolean_property(root
, "/options/little-endian?")
460 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
461 error("target and configured byte order conflict\n");
463 /* fill in the missing OEA/VEA information */
464 env
= tree_find_string_property(root
, "/openprom/options/env");
465 current_environment
= ((strcmp(env
, "user") == 0
466 || strcmp(env
, "uea") == 0)
468 : (strcmp(env
, "virtual") == 0
469 || strcmp(env
, "vea") == 0)
470 ? VIRTUAL_ENVIRONMENT
471 : (strcmp(env
, "operating") == 0
472 || strcmp(env
, "oea") == 0)
473 ? OPERATING_ENVIRONMENT
475 if (current_environment
== 0)
476 error("unreconized /options env property\n");
477 if (CURRENT_ENVIRONMENT
!= current_environment
)
478 error("target and configured environment conflict\n");
480 /* fill in the missing ALLIGNMENT information */
482 = (tree_find_boolean_property(root
, "/openprom/options/strict-alignment?")
484 : NONSTRICT_ALIGNMENT
);
485 if (CURRENT_ALIGNMENT
!= current_alignment
)
486 error("target and configured alignment conflict\n");
488 /* fill in the missing FLOATING POINT information */
489 current_floating_point
490 = (tree_find_boolean_property(root
, "/openprom/options/floating-point?")
491 ? HARD_FLOATING_POINT
492 : SOFT_FLOATING_POINT
);
493 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
494 error("target and configured floating-point conflict\n");
496 /* fill in the missing STDIO information */
498 = (tree_find_boolean_property(root
, "/openprom/options/use-stdio?")
501 if (CURRENT_STDIO
!= current_stdio
)
502 error("target and configured stdio interface conflict\n");
504 /* sort out the level of detail for issue modeling */
506 = tree_find_integer_property(root
, "/openprom/options/model-issue");
507 if (CURRENT_MODEL_ISSUE
!= current_model_issue
)
508 error("target and configured model-issue conflict\n");
510 /* sort out our model architecture - wrong.
512 FIXME: this should be obtaining the required information from the
513 device tree via the "/chosen" property "cpu" which is an instance
514 (ihandle) for the only executing processor. By converting that
515 ihandle into the corresponding cpu's phandle and then querying
516 the "name" property, the cpu type can be determined. Ok? */
518 model_set(tree_find_string_property(root
, "/openprom/options/model"));
521 system
= ZALLOC(psim
);
522 system
->events
= event_queue_create();
523 system
->memory
= core_from_device(root
);
524 system
->monitor
= mon_create();
525 system
->nr_cpus
= nr_cpus
;
526 system
->os_emulation
= os_emulation
;
527 system
->devices
= root
;
529 /* now all the processors attaching to each their per-cpu information */
530 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
531 system
->processors
[cpu_nr
] = cpu_create(system
,
533 mon_cpu(system
->monitor
,
535 system
->os_emulation
,
539 /* dump out the contents of the device tree */
540 if (ppc_trace
[trace_print_device_tree
] || ppc_trace
[trace_dump_device_tree
])
542 if (ppc_trace
[trace_dump_device_tree
])
549 /* allow the simulation to stop/restart abnormaly */
553 psim_set_halt_and_restart(psim
*system
,
555 void *restart_jmp_buf
)
557 system
->path_to_halt
= halt_jmp_buf
;
558 system
->path_to_restart
= restart_jmp_buf
;
563 psim_clear_halt_and_restart(psim
*system
)
565 system
->path_to_halt
= NULL
;
566 system
->path_to_restart
= NULL
;
571 psim_restart(psim
*system
,
574 ASSERT(current_cpu
>= 0 && current_cpu
< system
->nr_cpus
);
575 ASSERT(system
->path_to_restart
!= NULL
);
576 system
->last_cpu
= current_cpu
;
577 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
581 static ATTRIBUTE_NORETURN
void
582 cntrl_c_simulation(void *data
)
586 psim_nr_cpus(system
),
593 psim_stop(psim
*system
)
595 event_queue_schedule_after_signal(psim_event_queue(system
),
603 psim_halt(psim
*system
,
608 ASSERT(current_cpu
>= 0 && current_cpu
<= system
->nr_cpus
);
609 ASSERT(system
->path_to_halt
!= NULL
);
610 system
->last_cpu
= current_cpu
;
611 system
->halt_status
.reason
= reason
;
612 system
->halt_status
.signal
= signal
;
613 if (current_cpu
== system
->nr_cpus
) {
614 system
->halt_status
.cpu_nr
= 0;
615 system
->halt_status
.program_counter
=
616 cpu_get_program_counter(system
->processors
[0]);
619 system
->halt_status
.cpu_nr
= current_cpu
;
620 system
->halt_status
.program_counter
=
621 cpu_get_program_counter(system
->processors
[current_cpu
]);
623 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
629 psim_last_cpu(psim
*system
)
631 return system
->last_cpu
;
636 psim_nr_cpus(psim
*system
)
638 return system
->nr_cpus
;
643 psim_get_status(psim
*system
)
645 return system
->halt_status
;
651 psim_cpu(psim
*system
,
654 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
657 return system
->processors
[cpu_nr
];
663 psim_device(psim
*system
,
666 return tree_find_device(system
->devices
, path
);
671 psim_event_queue(psim
*system
)
673 return system
->events
;
680 psim_max_iterations_exceeded(void *data
)
684 system
->nr_cpus
, /* halted during an event */
692 psim_init(psim
*system
)
696 /* scrub the monitor */
697 mon_init(system
->monitor
, system
->nr_cpus
);
699 /* trash any pending events */
700 event_queue_init(system
->events
);
702 /* if needed, schedule a halt event. FIXME - In the future this
703 will be replaced by a more generic change to psim_command(). A
704 new command `schedule NNN halt' being added. */
705 if (tree_find_property(system
->devices
, "/openprom/options/max-iterations")) {
706 event_queue_schedule(system
->events
,
707 tree_find_integer_property(system
->devices
,
708 "/openprom/options/max-iterations") - 2,
709 psim_max_iterations_exceeded
,
713 /* scrub all the cpus */
714 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
715 cpu_init(system
->processors
[cpu_nr
]);
717 /* init all the devices (which updates the cpus) */
718 tree_init(system
->devices
, system
);
720 /* and the emulation (which needs an initialized device tree) */
721 os_emul_init(system
->os_emulation
, system
->nr_cpus
);
723 /* now sync each cpu against the initialized state of its registers */
724 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++) {
725 cpu
*processor
= system
->processors
[cpu_nr
];
726 cpu_synchronize_context(processor
, cpu_get_program_counter(processor
));
727 cpu_page_tlb_invalidate_all(processor
);
730 /* force loop to start with first cpu */
731 system
->last_cpu
= -1;
736 psim_stack(psim
*system
,
740 /* pass the stack device the argv/envp and let it work out what to
742 device
*stack_device
= tree_find_device(system
->devices
,
743 "/openprom/init/stack");
744 if (stack_device
!= (device
*)0) {
745 unsigned_word stack_pointer
;
746 ASSERT (psim_read_register(system
, 0, &stack_pointer
, "sp",
747 cooked_transfer
) > 0);
748 device_ioctl(stack_device
,
751 device_ioctl_create_stack
,
760 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
765 psim_step(psim
*system
)
767 volatile int keep_running
= 0;
768 idecode_run_until_stop(system
, &keep_running
,
769 system
->events
, system
->processors
, system
->nr_cpus
);
774 psim_run(psim
*system
)
777 system
->events
, system
->processors
, system
->nr_cpus
);
781 /* storage manipulation functions */
785 psim_read_register(psim
*system
,
791 register_descriptions description
;
794 unsigned_word unsigned_word
;
795 unsigned_1 unsigned_1
;
796 unsigned_2 unsigned_2
;
797 unsigned_4 unsigned_4
;
798 unsigned_8 unsigned_8
;
799 unsigned_16 unsigned_16
;
810 /* find our processor */
811 if (which_cpu
== MAX_NR_PROCESSORS
) {
812 if (system
->last_cpu
== system
->nr_cpus
813 || system
->last_cpu
== -1)
816 which_cpu
= system
->last_cpu
;
818 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
820 processor
= system
->processors
[which_cpu
];
822 /* find the register description */
823 description
= register_description(reg
);
824 if (description
.type
== reg_invalid
)
827 /* get the cooked value */
828 switch (description
.type
) {
831 cooked_buf
.gpreg
= cpu_registers(processor
)->gpr
[description
.index
];
835 cooked_buf
.spreg
= cpu_registers(processor
)->spr
[description
.index
];
839 cooked_buf
.sreg
= cpu_registers(processor
)->sr
[description
.index
];
843 cooked_buf
.fpreg
= cpu_registers(processor
)->fpr
[description
.index
];
847 cooked_buf
.unsigned_word
= cpu_get_program_counter(processor
);
851 cooked_buf
.creg
= cpu_registers(processor
)->cr
;
855 cooked_buf
.msreg
= cpu_registers(processor
)->msr
;
859 cooked_buf
.fpscreg
= cpu_registers(processor
)->fpscr
;
863 cooked_buf
.unsigned_word
= mon_get_number_of_insns(system
->monitor
,
868 if (cpu_model(processor
) == NULL
)
869 error("$stalls only valid if processor unit model enabled (-I)\n");
870 cooked_buf
.unsigned_word
= model_get_number_of_stalls(cpu_model(processor
));
874 if (cpu_model(processor
) == NULL
)
875 error("$cycles only valid if processor unit model enabled (-I)\n");
876 cooked_buf
.unsigned_word
= model_get_number_of_cycles(cpu_model(processor
));
881 cooked_buf
.vreg
= cpu_registers(processor
)->altivec
.vr
[description
.index
];
885 cooked_buf
.vscreg
= cpu_registers(processor
)->altivec
.vscr
;
891 cooked_buf
.gpreg
= cpu_registers(processor
)->e500
.gprh
[description
.index
];
895 cooked_buf
.uint64_t = EVR(description
.index
);
899 cooked_buf
.accreg
= cpu_registers(processor
)->e500
.acc
;
904 printf_filtered("psim_read_register(processor=%p,buf=%p,reg=%s) %s\n",
905 processor
, buf
, reg
, "read of this register unimplemented");
909 /* the PSIM internal values are in host order. To fetch raw data,
910 they need to be converted into target order and then returned */
911 if (mode
== raw_transfer
) {
912 /* FIXME - assumes that all registers are simple integers */
913 switch (description
.size
) {
915 *(unsigned_1
*)buf
= H2T_1(cooked_buf
.unsigned_1
);
918 *(unsigned_2
*)buf
= H2T_2(cooked_buf
.unsigned_2
);
921 *(unsigned_4
*)buf
= H2T_4(cooked_buf
.unsigned_4
);
924 *(unsigned_8
*)buf
= H2T_8(cooked_buf
.unsigned_8
);
928 unsigned_16 v
= H2T_16(cooked_buf
.unsigned_16
);
929 memcpy(buf
/*dest*/, &v
, description
.size
);
935 memcpy(buf
/*dest*/, cooked_buf
.bytes
/*src*/, description
.size
);
938 return description
.size
;
945 psim_write_register(psim
*system
,
952 register_descriptions description
;
955 unsigned_word unsigned_word
;
956 unsigned_1 unsigned_1
;
957 unsigned_2 unsigned_2
;
958 unsigned_4 unsigned_4
;
959 unsigned_8 unsigned_8
;
960 unsigned_16 unsigned_16
;
970 /* find our processor */
971 if (which_cpu
== MAX_NR_PROCESSORS
) {
972 if (system
->last_cpu
== system
->nr_cpus
973 || system
->last_cpu
== -1)
976 which_cpu
= system
->last_cpu
;
979 /* find the description of the register */
980 description
= register_description(reg
);
981 if (description
.type
== reg_invalid
)
984 if (which_cpu
== -1) {
986 for (i
= 0; i
< system
->nr_cpus
; i
++)
987 psim_write_register(system
, i
, buf
, reg
, mode
);
988 return description
.size
;
990 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
992 processor
= system
->processors
[which_cpu
];
994 /* If the data is coming in raw (target order), need to cook it
995 into host order before putting it into PSIM's internal structures */
996 if (mode
== raw_transfer
) {
997 switch (description
.size
) {
999 cooked_buf
.unsigned_1
= T2H_1(*(unsigned_1
*)buf
);
1002 cooked_buf
.unsigned_2
= T2H_2(*(unsigned_2
*)buf
);
1005 cooked_buf
.unsigned_4
= T2H_4(*(unsigned_4
*)buf
);
1008 cooked_buf
.unsigned_8
= T2H_8(*(unsigned_8
*)buf
);
1011 cooked_buf
.unsigned_16
= T2H_16(*(unsigned_16
*)buf
);
1016 memcpy(cooked_buf
.bytes
/*dest*/, buf
/*src*/, description
.size
);
1019 /* put the cooked value into the register */
1020 switch (description
.type
) {
1023 cpu_registers(processor
)->gpr
[description
.index
] = cooked_buf
.gpreg
;
1027 cpu_registers(processor
)->fpr
[description
.index
] = cooked_buf
.fpreg
;
1031 cpu_set_program_counter(processor
, cooked_buf
.unsigned_word
);
1035 cpu_registers(processor
)->spr
[description
.index
] = cooked_buf
.spreg
;
1039 cpu_registers(processor
)->sr
[description
.index
] = cooked_buf
.sreg
;
1043 cpu_registers(processor
)->cr
= cooked_buf
.creg
;
1047 cpu_registers(processor
)->msr
= cooked_buf
.msreg
;
1051 cpu_registers(processor
)->fpscr
= cooked_buf
.fpscreg
;
1056 cpu_registers(processor
)->e500
.gprh
[description
.index
] = cooked_buf
.gpreg
;
1062 v
= cooked_buf
.uint64_t;
1063 cpu_registers(processor
)->e500
.gprh
[description
.index
] = v
>> 32;
1064 cpu_registers(processor
)->gpr
[description
.index
] = v
;
1069 cpu_registers(processor
)->e500
.acc
= cooked_buf
.accreg
;
1075 cpu_registers(processor
)->altivec
.vr
[description
.index
] = cooked_buf
.vreg
;
1079 cpu_registers(processor
)->altivec
.vscr
= cooked_buf
.vscreg
;
1084 printf_filtered("psim_write_register(processor=%p,buf=%p,reg=%s) %s\n",
1085 processor
, buf
, reg
, "read of this register unimplemented");
1089 return description
.size
;
1096 psim_read_memory(psim
*system
,
1099 unsigned_word vaddr
,
1103 if (which_cpu
== MAX_NR_PROCESSORS
) {
1104 if (system
->last_cpu
== system
->nr_cpus
1105 || system
->last_cpu
== -1)
1108 which_cpu
= system
->last_cpu
;
1110 processor
= system
->processors
[which_cpu
];
1111 return vm_data_map_read_buffer(cpu_data_map(processor
),
1112 buffer
, vaddr
, nr_bytes
,
1119 psim_write_memory(psim
*system
,
1122 unsigned_word vaddr
,
1124 int violate_read_only_section
)
1127 if (which_cpu
== MAX_NR_PROCESSORS
) {
1128 if (system
->last_cpu
== system
->nr_cpus
1129 || system
->last_cpu
== -1)
1132 which_cpu
= system
->last_cpu
;
1134 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
1135 processor
= system
->processors
[which_cpu
];
1136 return vm_data_map_write_buffer(cpu_data_map(processor
),
1137 buffer
, vaddr
, nr_bytes
, 1/*violate-read-only*/,
1144 psim_print_info(psim
*system
,
1147 mon_print_info(system
, system
->monitor
, verbose
);
1151 /* Merge a device tree and a device file. */
1155 psim_merge_device_file(device
*root
,
1156 const char *file_name
)
1160 char device_path
[1000];
1163 /* try opening the file */
1164 description
= fopen(file_name
, "r");
1165 if (description
== NULL
) {
1167 error("Invalid file %s specified", file_name
);
1172 while (fgets(device_path
, sizeof(device_path
), description
)) {
1174 /* check that the full line was read */
1175 if (strchr(device_path
, '\n') == NULL
) {
1176 fclose(description
);
1177 error("%s:%d: line to long - %s",
1178 file_name
, line_nr
, device_path
);
1181 *strchr(device_path
, '\n') = '\0';
1183 /* skip comments ("#" or ";") and blank lines lines */
1184 for (device
= device_path
;
1185 *device
!= '\0' && isspace(*device
);
1187 if (device
[0] == '#'
1189 || device
[0] == '\0')
1191 /* merge any appended lines */
1192 while (device_path
[strlen(device_path
) - 1] == '\\') {
1193 int curlen
= strlen(device_path
) - 1;
1195 device_path
[curlen
] = '\0';
1196 /* append the next line */
1197 if (!fgets(device_path
+ curlen
, sizeof(device_path
) - curlen
, description
)) {
1198 fclose(description
);
1199 error("%s:%d: unexpected eof in line continuation - %s",
1200 file_name
, line_nr
, device_path
);
1202 if (strchr(device_path
, '\n') == NULL
) {
1203 fclose(description
);
1204 error("%s:%d: line to long - %s",
1205 file_name
, line_nr
, device_path
);
1208 *strchr(device_path
, '\n') = '\0';
1211 /* parse this line */
1212 current
= tree_parse(current
, "%s", device
);
1214 fclose(description
);
1218 #endif /* _PSIM_C_ */