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 */
51 #include "libiberty.h"
52 #include "gdb/signals.h"
54 /* system structure, actual size of processor array determined at
61 os_emul
*os_emulation
;
64 /* escape routine for inner functions */
66 void *path_to_restart
;
68 /* status from last halt */
69 psim_status halt_status
;
71 /* the processors proper */
73 int last_cpu
; /* CPU that last (tried to) execute an instruction */
74 cpu
*processors
[MAX_NR_PROCESSORS
];
78 int current_target_byte_order
;
79 int current_host_byte_order
;
80 int current_environment
;
81 int current_alignment
;
82 int current_floating_point
;
83 int current_model_issue
= MODEL_ISSUE_IGNORE
;
84 int current_stdio
= DO_USE_STDIO
;
85 model_enum current_model
= WITH_DEFAULT_MODEL
;
88 /* create the device tree */
94 device
*root
= tree_parse(NULL
, "core");
95 tree_parse(root
, "/aliases");
96 tree_parse(root
, "/options");
97 tree_parse(root
, "/chosen");
98 tree_parse(root
, "/packages");
99 tree_parse(root
, "/cpus");
100 tree_parse(root
, "/openprom");
101 tree_parse(root
, "/openprom/init");
102 tree_parse(root
, "/openprom/trace");
103 tree_parse(root
, "/openprom/options");
109 find_arg(char *err_msg
,
114 if (argv
[*ptr_to_argp
] == NULL
)
116 return argv
[*ptr_to_argp
];
121 psim_usage(int verbose
, int help
)
123 printf_filtered("Usage:\n");
124 printf_filtered("\n");
125 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
126 printf_filtered("\n");
127 printf_filtered("Where\n");
128 printf_filtered("\n");
129 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
131 printf_filtered("\t This can either be a PowerPC binary or\n");
132 printf_filtered("\t a text file containing a device tree\n");
133 printf_filtered("\t specification.\n");
134 printf_filtered("\t PSIM will attempt to determine from the\n");
135 printf_filtered("\t specified <image> the intended emulation\n");
136 printf_filtered("\t environment.\n");
137 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
138 printf_filtered("\t environment can be specified using the\n");
139 printf_filtered("\t `-e' option (described below).\n");
140 printf_filtered("\n"); }
141 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
143 printf_filtered("\t These arguments will be passed to\n");
144 printf_filtered("\t <image> (as standard C argv, argc)\n");
145 printf_filtered("\t when <image> is started.\n");
146 printf_filtered("\n"); }
147 printf_filtered("\t<psim-option> See below\n");
148 printf_filtered("\n");
149 printf_filtered("The following are valid <psim-option>s:\n");
150 printf_filtered("\n");
152 printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
154 printf_filtered("\n");
157 printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
159 printf_filtered("\t Specify -i2 for a more detailed display\n");
160 printf_filtered("\n");
163 printf_filtered("\t-I Print execution unit statistics\n");
164 if (verbose
) { printf_filtered("\n"); }
166 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
168 printf_filtered("\t Can be any of the following:\n");
169 printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
170 printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
171 printf_filtered("\t solaris - UEA + Solaris system calls\n");
172 printf_filtered("\t linux - UEA + Linux system calls\n");
173 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
174 printf_filtered("\n"); }
176 printf_filtered("\t-E <endian> Specify the endianness of the target\n");
178 printf_filtered("\t Can be any of the following:\n");
179 printf_filtered("\t big - big endian target\n");
180 printf_filtered("\t little - little endian target\n");
181 printf_filtered("\n"); }
183 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
184 if (verbose
) { printf_filtered("\n"); }
186 printf_filtered("\t-h -? -H give more detailed usage\n");
187 if (verbose
) { printf_filtered("\n"); }
189 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
191 printf_filtered("\t Selects the processor to use when\n");
192 printf_filtered("\t modeling execution units. Includes:\n");
193 printf_filtered("\t 604, 603 and 603e\n");
194 printf_filtered("\n"); }
196 printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
198 printf_filtered("\t Specifies the number of processors that are\n");
199 printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
200 printf_filtered("\t simulation\n");
201 printf_filtered("\n"); }
203 printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
204 if (verbose
) { printf_filtered("\n"); }
206 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
207 if (verbose
) { printf_filtered("\n"); }
209 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
210 if (verbose
) { printf_filtered("\n"); }
212 printf_filtered("\n");
213 trace_usage(verbose
);
214 device_usage(verbose
);
216 printf_filtered("\n");
220 if (REPORT_BUGS_TO
[0])
221 printf ("Report bugs to %s\n", REPORT_BUGS_TO
);
225 /* Test "string" for containing a string of digits that form a number
226 between "min" and "max". The return value is the number or "err". */
228 int is_num( char *string
, int min
, int max
, int err
)
232 for ( ; *string
; ++string
)
234 if (!isdigit(*string
))
239 result
= result
* 10 + (*string
- '0');
241 if (result
< min
|| result
> max
)
249 psim_options(device
*root
,
252 device
*current
= root
;
257 while (argv
[argp
] != NULL
&& argv
[argp
][0] == '-') {
258 char *p
= argv
[argp
] + 1;
263 printf_filtered ("Invalid Option: %s\n", argv
[argp
]);
268 param
= find_arg("Missing <count> option for -c (max-iterations)\n", &argp
, argv
);
269 tree_parse(root
, "/openprom/options/max-iterations %s", param
);
272 param
= find_arg("Missing <emul> option for -e (os-emul)\n", &argp
, argv
);
273 tree_parse(root
, "/openprom/options/os-emul %s", param
);
276 /* endian spec, ignored for now */
277 param
= find_arg("Missing <endian> option for -E (target-endian)\n", &argp
, argv
);
278 if (strcmp (param
, "big") == 0)
279 tree_parse (root
, "/options/little-endian? false");
280 else if (strcmp (param
, "little") == 0)
281 tree_parse (root
, "/options/little-endian? true");
284 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
289 param
= find_arg("Missing <file> option for -f\n", &argp
, argv
);
290 psim_merge_device_file(root
, param
);
301 tree_parse(root
, "/openprom/trace/print-info %c", p
[1]);
305 tree_parse(root
, "/openprom/trace/print-info 1");
309 tree_parse(root
, "/openprom/trace/print-info 2");
310 tree_parse(root
, "/openprom/options/model-issue %d",
311 MODEL_ISSUE_PROCESS
);
314 param
= find_arg("Missing <model> option for -m (model)\n", &argp
, argv
);
315 tree_parse(root
, "/openprom/options/model \"%s", param
);
318 param
= find_arg("Missing <nr-smp> option for -n (smp)\n", &argp
, argv
);
319 tree_parse(root
, "/openprom/options/smp %s", param
);
322 param
= find_arg("Missing <dev-spec> option for -o\n", &argp
, argv
);
323 if (memcmp(param
, "mpc860c0", 8) == 0)
325 if (param
[8] == '\0')
326 tree_parse(root
, "/options/mpc860c0 5");
327 else if (param
[8] == '=' && is_num(param
+9, 1, 10, 0))
329 tree_parse(root
, "/options/mpc860c0 %s", param
+9);
331 else error("Invalid mpc860c0 option for -o\n");
334 current
= tree_parse(current
, "%s", param
);
337 param
= find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp
, argv
);
338 tree_parse(root
, "/openprom/options/oea-memory-size %s",
342 param
= find_arg("Missing <trace> option for -t (trace/*)\n", &argp
, argv
);
344 tree_parse(root
, "/openprom/trace/%s 0", param
+1);
346 tree_parse(root
, "/openprom/trace/%s 1", param
);
349 /* it's a long option of the form --optionname=optionvalue.
350 Such options can be passed through if we are invoked by
352 if (strstr(argv
[argp
], "architecture") != NULL
) {
353 /* we must consume the argument here, so that we get out
355 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
356 printf_filtered("Warning - architecture parameter ignored\n");
358 else if (strcmp (argv
[argp
], "--help") == 0)
360 else if (strncmp (argv
[argp
], "--sysroot=",
361 sizeof ("--sysroot=") - 1) == 0)
362 /* Ignore this option. */
363 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
364 else if (strcmp (argv
[argp
], "--version") == 0)
366 extern const char version
[];
367 printf ("GNU simulator %s%s\n", PKGVERSION
, version
);
372 printf_filtered ("Invalid option: %s\n", argv
[argp
]);
382 /* force the trace node to process its options now *before* the tree
383 initialization occures */
384 device_ioctl(tree_find_device(root
, "/openprom/trace"),
386 device_ioctl_set_trace
);
389 void semantic_init(device
* root
);
393 /* return where the options end */
399 psim_command(device
*root
,
403 if (argv
[argp
] == NULL
) {
406 else if (strcmp(argv
[argp
], "trace") == 0) {
407 const char *opt
= find_arg("Missing <trace> option", &argp
, argv
);
409 trace_option(opt
+ 1, 0);
411 trace_option(opt
, 1);
413 else if (strcmp(*argv
, "change-media") == 0) {
414 char *device
= find_arg("Missing device name", &argp
, argv
);
415 char *media
= argv
[++argp
];
416 device_ioctl(tree_find_device(root
, device
), NULL
, 0,
417 device_ioctl_change_media
, media
);
420 printf_filtered("Unknown PSIM command %s, try\n", argv
[argp
]);
421 printf_filtered(" trace <trace-option>\n");
422 printf_filtered(" change-media <device> [ <new-image> ]\n");
427 /* create the simulator proper from the device tree and executable */
431 psim_create(const char *file_name
,
437 os_emul
*os_emulation
;
440 /* given this partially populated device tree, os_emul_create() uses
441 it and file_name to determine the selected emulation and hence
442 further populate the tree with any other required nodes. */
444 os_emulation
= os_emul_create(file_name
, root
);
445 if (os_emulation
== NULL
)
446 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name
);
448 /* fill in the missing real number of CPU's */
449 nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
450 if (MAX_NR_PROCESSORS
< nr_cpus
)
451 error("target and configured number of cpus conflict\n");
453 /* fill in the missing TARGET BYTE ORDER information */
454 current_target_byte_order
455 = (tree_find_boolean_property(root
, "/options/little-endian?")
458 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
459 error("target and configured byte order conflict\n");
461 /* fill in the missing HOST BYTE ORDER information */
462 current_host_byte_order
= (current_host_byte_order
= 1,
463 (*(char*)(¤t_host_byte_order
)
466 if (CURRENT_HOST_BYTE_ORDER
!= current_host_byte_order
)
467 error("host and configured byte order conflict\n");
469 /* fill in the missing OEA/VEA information */
470 env
= tree_find_string_property(root
, "/openprom/options/env");
471 current_environment
= ((strcmp(env
, "user") == 0
472 || strcmp(env
, "uea") == 0)
474 : (strcmp(env
, "virtual") == 0
475 || strcmp(env
, "vea") == 0)
476 ? VIRTUAL_ENVIRONMENT
477 : (strcmp(env
, "operating") == 0
478 || strcmp(env
, "oea") == 0)
479 ? OPERATING_ENVIRONMENT
481 if (current_environment
== 0)
482 error("unreconized /options env property\n");
483 if (CURRENT_ENVIRONMENT
!= current_environment
)
484 error("target and configured environment conflict\n");
486 /* fill in the missing ALLIGNMENT information */
488 = (tree_find_boolean_property(root
, "/openprom/options/strict-alignment?")
490 : NONSTRICT_ALIGNMENT
);
491 if (CURRENT_ALIGNMENT
!= current_alignment
)
492 error("target and configured alignment conflict\n");
494 /* fill in the missing FLOATING POINT information */
495 current_floating_point
496 = (tree_find_boolean_property(root
, "/openprom/options/floating-point?")
497 ? HARD_FLOATING_POINT
498 : SOFT_FLOATING_POINT
);
499 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
500 error("target and configured floating-point conflict\n");
502 /* fill in the missing STDIO information */
504 = (tree_find_boolean_property(root
, "/openprom/options/use-stdio?")
507 if (CURRENT_STDIO
!= current_stdio
)
508 error("target and configured stdio interface conflict\n");
510 /* sort out the level of detail for issue modeling */
512 = tree_find_integer_property(root
, "/openprom/options/model-issue");
513 if (CURRENT_MODEL_ISSUE
!= current_model_issue
)
514 error("target and configured model-issue conflict\n");
516 /* sort out our model architecture - wrong.
518 FIXME: this should be obtaining the required information from the
519 device tree via the "/chosen" property "cpu" which is an instance
520 (ihandle) for the only executing processor. By converting that
521 ihandle into the corresponding cpu's phandle and then querying
522 the "name" property, the cpu type can be determined. Ok? */
524 model_set(tree_find_string_property(root
, "/openprom/options/model"));
527 system
= ZALLOC(psim
);
528 system
->events
= event_queue_create();
529 system
->memory
= core_from_device(root
);
530 system
->monitor
= mon_create();
531 system
->nr_cpus
= nr_cpus
;
532 system
->os_emulation
= os_emulation
;
533 system
->devices
= root
;
535 /* now all the processors attaching to each their per-cpu information */
536 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
537 system
->processors
[cpu_nr
] = cpu_create(system
,
539 mon_cpu(system
->monitor
,
541 system
->os_emulation
,
545 /* dump out the contents of the device tree */
546 if (ppc_trace
[trace_print_device_tree
] || ppc_trace
[trace_dump_device_tree
])
548 if (ppc_trace
[trace_dump_device_tree
])
555 /* allow the simulation to stop/restart abnormaly */
559 psim_set_halt_and_restart(psim
*system
,
561 void *restart_jmp_buf
)
563 system
->path_to_halt
= halt_jmp_buf
;
564 system
->path_to_restart
= restart_jmp_buf
;
569 psim_clear_halt_and_restart(psim
*system
)
571 system
->path_to_halt
= NULL
;
572 system
->path_to_restart
= NULL
;
577 psim_restart(psim
*system
,
580 ASSERT(current_cpu
>= 0 && current_cpu
< system
->nr_cpus
);
581 ASSERT(system
->path_to_restart
!= NULL
);
582 system
->last_cpu
= current_cpu
;
583 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
588 cntrl_c_simulation(void *data
)
592 psim_nr_cpus(system
),
599 psim_stop(psim
*system
)
601 event_queue_schedule_after_signal(psim_event_queue(system
),
609 psim_halt(psim
*system
,
614 ASSERT(current_cpu
>= 0 && current_cpu
<= system
->nr_cpus
);
615 ASSERT(system
->path_to_halt
!= NULL
);
616 system
->last_cpu
= current_cpu
;
617 system
->halt_status
.reason
= reason
;
618 system
->halt_status
.signal
= signal
;
619 if (current_cpu
== system
->nr_cpus
) {
620 system
->halt_status
.cpu_nr
= 0;
621 system
->halt_status
.program_counter
=
622 cpu_get_program_counter(system
->processors
[0]);
625 system
->halt_status
.cpu_nr
= current_cpu
;
626 system
->halt_status
.program_counter
=
627 cpu_get_program_counter(system
->processors
[current_cpu
]);
629 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
635 psim_last_cpu(psim
*system
)
637 return system
->last_cpu
;
642 psim_nr_cpus(psim
*system
)
644 return system
->nr_cpus
;
649 psim_get_status(psim
*system
)
651 return system
->halt_status
;
657 psim_cpu(psim
*system
,
660 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
663 return system
->processors
[cpu_nr
];
669 psim_device(psim
*system
,
672 return tree_find_device(system
->devices
, path
);
677 psim_event_queue(psim
*system
)
679 return system
->events
;
686 psim_max_iterations_exceeded(void *data
)
690 system
->nr_cpus
, /* halted during an event */
698 psim_init(psim
*system
)
702 /* scrub the monitor */
703 mon_init(system
->monitor
, system
->nr_cpus
);
705 /* trash any pending events */
706 event_queue_init(system
->events
);
708 /* if needed, schedule a halt event. FIXME - In the future this
709 will be replaced by a more generic change to psim_command(). A
710 new command `schedule NNN halt' being added. */
711 if (tree_find_property(system
->devices
, "/openprom/options/max-iterations")) {
712 event_queue_schedule(system
->events
,
713 tree_find_integer_property(system
->devices
,
714 "/openprom/options/max-iterations") - 2,
715 psim_max_iterations_exceeded
,
719 /* scrub all the cpus */
720 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
721 cpu_init(system
->processors
[cpu_nr
]);
723 /* init all the devices (which updates the cpus) */
724 tree_init(system
->devices
, system
);
726 /* and the emulation (which needs an initialized device tree) */
727 os_emul_init(system
->os_emulation
, system
->nr_cpus
);
729 /* now sync each cpu against the initialized state of its registers */
730 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++) {
731 cpu
*processor
= system
->processors
[cpu_nr
];
732 cpu_synchronize_context(processor
, cpu_get_program_counter(processor
));
733 cpu_page_tlb_invalidate_all(processor
);
736 /* force loop to start with first cpu */
737 system
->last_cpu
= -1;
742 psim_stack(psim
*system
,
746 /* pass the stack device the argv/envp and let it work out what to
748 device
*stack_device
= tree_find_device(system
->devices
,
749 "/openprom/init/stack");
750 if (stack_device
!= (device
*)0) {
751 unsigned_word stack_pointer
;
752 ASSERT (psim_read_register(system
, 0, &stack_pointer
, "sp",
753 cooked_transfer
) > 0);
754 device_ioctl(stack_device
,
757 device_ioctl_create_stack
,
766 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
771 psim_step(psim
*system
)
773 volatile int keep_running
= 0;
774 idecode_run_until_stop(system
, &keep_running
,
775 system
->events
, system
->processors
, system
->nr_cpus
);
780 psim_run(psim
*system
)
783 system
->events
, system
->processors
, system
->nr_cpus
);
787 /* storage manipulation functions */
791 psim_read_register(psim
*system
,
797 register_descriptions description
;
801 /* find our processor */
802 if (which_cpu
== MAX_NR_PROCESSORS
) {
803 if (system
->last_cpu
== system
->nr_cpus
804 || system
->last_cpu
== -1)
807 which_cpu
= system
->last_cpu
;
809 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
811 processor
= system
->processors
[which_cpu
];
813 /* find the register description */
814 description
= register_description(reg
);
815 if (description
.type
== reg_invalid
)
817 cooked_buf
= alloca (description
.size
);
819 /* get the cooked value */
820 switch (description
.type
) {
823 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
827 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
831 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
835 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
839 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
843 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
847 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
851 *(fpscreg
*)cooked_buf
= cpu_registers(processor
)->fpscr
;
855 *(unsigned_word
*)cooked_buf
= mon_get_number_of_insns(system
->monitor
,
860 if (cpu_model(processor
) == NULL
)
861 error("$stalls only valid if processor unit model enabled (-I)\n");
862 *(unsigned_word
*)cooked_buf
= model_get_number_of_stalls(cpu_model(processor
));
866 if (cpu_model(processor
) == NULL
)
867 error("$cycles only valid if processor unit model enabled (-I)\n");
868 *(unsigned_word
*)cooked_buf
= model_get_number_of_cycles(cpu_model(processor
));
873 *(vreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vr
[description
.index
];
877 *(vscreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vscr
;
883 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->e500
.gprh
[description
.index
];
887 *(unsigned64
*)cooked_buf
= EVR(description
.index
);
891 *(accreg
*)cooked_buf
= cpu_registers(processor
)->e500
.acc
;
896 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
897 (unsigned long)processor
, (unsigned long)buf
, reg
,
898 "read of this register unimplemented");
903 /* the PSIM internal values are in host order. To fetch raw data,
904 they need to be converted into target order and then returned */
905 if (mode
== raw_transfer
) {
906 /* FIXME - assumes that all registers are simple integers */
907 switch (description
.size
) {
909 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
912 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
915 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
918 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
922 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
924 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
925 memcpy(&h
.v
/*dest*/, cooked_buf
/*src*/, description
.size
);
926 { _SWAP_8(t
.d
[0] =, h
.d
[1]); }
927 { _SWAP_8(t
.d
[1] =, h
.d
[0]); }
928 memcpy(buf
/*dest*/, &t
/*src*/, description
.size
);
932 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
938 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
941 return description
.size
;
948 psim_write_register(psim
*system
,
955 register_descriptions description
;
958 /* find our processor */
959 if (which_cpu
== MAX_NR_PROCESSORS
) {
960 if (system
->last_cpu
== system
->nr_cpus
961 || system
->last_cpu
== -1)
964 which_cpu
= system
->last_cpu
;
967 /* find the description of the register */
968 description
= register_description(reg
);
969 if (description
.type
== reg_invalid
)
971 cooked_buf
= alloca (description
.size
);
973 if (which_cpu
== -1) {
975 for (i
= 0; i
< system
->nr_cpus
; i
++)
976 psim_write_register(system
, i
, buf
, reg
, mode
);
977 return description
.size
;
979 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
981 processor
= system
->processors
[which_cpu
];
983 /* If the data is comming in raw (target order), need to cook it
984 into host order before putting it into PSIM's internal structures */
985 if (mode
== raw_transfer
) {
986 switch (description
.size
) {
988 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
991 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
994 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
997 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
1001 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
1003 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
1004 memcpy(&t
.v
/*dest*/, buf
/*src*/, description
.size
);
1005 { _SWAP_8(h
.d
[0] =, t
.d
[1]); }
1006 { _SWAP_8(h
.d
[1] =, t
.d
[0]); }
1007 memcpy(cooked_buf
/*dest*/, &h
/*src*/, description
.size
);
1011 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1016 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1019 /* put the cooked value into the register */
1020 switch (description
.type
) {
1023 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
1027 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
1031 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
1035 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
1039 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
1043 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
1047 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
1051 cpu_registers(processor
)->fpscr
= *(fpscreg
*)cooked_buf
;
1056 cpu_registers(processor
)->e500
.gprh
[description
.index
] = *(gpreg
*)cooked_buf
;
1062 v
= *(unsigned64
*)cooked_buf
;
1063 cpu_registers(processor
)->e500
.gprh
[description
.index
] = v
>> 32;
1064 cpu_registers(processor
)->gpr
[description
.index
] = v
;
1069 cpu_registers(processor
)->e500
.acc
= *(accreg
*)cooked_buf
;
1075 cpu_registers(processor
)->altivec
.vr
[description
.index
] = *(vreg
*)cooked_buf
;
1079 cpu_registers(processor
)->altivec
.vscr
= *(vscreg
*)cooked_buf
;
1084 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1085 (unsigned long)processor
, (unsigned long)cooked_buf
, reg
,
1086 "read of this register unimplemented");
1091 return description
.size
;
1098 psim_read_memory(psim
*system
,
1101 unsigned_word vaddr
,
1105 if (which_cpu
== MAX_NR_PROCESSORS
) {
1106 if (system
->last_cpu
== system
->nr_cpus
1107 || system
->last_cpu
== -1)
1110 which_cpu
= system
->last_cpu
;
1112 processor
= system
->processors
[which_cpu
];
1113 return vm_data_map_read_buffer(cpu_data_map(processor
),
1114 buffer
, vaddr
, nr_bytes
,
1121 psim_write_memory(psim
*system
,
1124 unsigned_word vaddr
,
1126 int violate_read_only_section
)
1129 if (which_cpu
== MAX_NR_PROCESSORS
) {
1130 if (system
->last_cpu
== system
->nr_cpus
1131 || system
->last_cpu
== -1)
1134 which_cpu
= system
->last_cpu
;
1136 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
1137 processor
= system
->processors
[which_cpu
];
1138 return vm_data_map_write_buffer(cpu_data_map(processor
),
1139 buffer
, vaddr
, nr_bytes
, 1/*violate-read-only*/,
1146 psim_print_info(psim
*system
,
1149 mon_print_info(system
, system
->monitor
, verbose
);
1153 /* Merge a device tree and a device file. */
1157 psim_merge_device_file(device
*root
,
1158 const char *file_name
)
1162 char device_path
[1000];
1165 /* try opening the file */
1166 description
= fopen(file_name
, "r");
1167 if (description
== NULL
) {
1169 error("Invalid file %s specified", file_name
);
1174 while (fgets(device_path
, sizeof(device_path
), description
)) {
1176 /* check that the full line was read */
1177 if (strchr(device_path
, '\n') == NULL
) {
1178 fclose(description
);
1179 error("%s:%d: line to long - %s",
1180 file_name
, line_nr
, device_path
);
1183 *strchr(device_path
, '\n') = '\0';
1185 /* skip comments ("#" or ";") and blank lines lines */
1186 for (device
= device_path
;
1187 *device
!= '\0' && isspace(*device
);
1189 if (device
[0] == '#'
1191 || device
[0] == '\0')
1193 /* merge any appended lines */
1194 while (device_path
[strlen(device_path
) - 1] == '\\') {
1195 int curlen
= strlen(device_path
) - 1;
1197 device_path
[curlen
] = '\0';
1198 /* append the next line */
1199 if (!fgets(device_path
+ curlen
, sizeof(device_path
) - curlen
, description
)) {
1200 fclose(description
);
1201 error("%s:%s: unexpected eof in line continuation - %s",
1202 file_name
, line_nr
, device_path
);
1204 if (strchr(device_path
, '\n') == NULL
) {
1205 fclose(description
);
1206 error("%s:%d: line to long - %s",
1207 file_name
, line_nr
, device_path
);
1210 *strchr(device_path
, '\n') = '\0';
1213 /* parse this line */
1214 current
= tree_parse(current
, "%s", device
);
1216 fclose(description
);
1220 #endif /* _PSIM_C_ */