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 int 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
)
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 if (kind
== SIM_OPEN_STANDALONE
)
369 printf_filtered ("Invalid option: %s\n", argv
[argp
]);
370 psim_usage (0, 0, kind
);
379 /* force the trace node to process its options now *before* the tree
380 initialization occures */
381 device_ioctl(tree_find_device(root
, "/openprom/trace"),
383 device_ioctl_set_trace
);
386 void semantic_init(device
* root
);
390 /* return where the options end */
396 psim_command(device
*root
,
400 if (argv
[argp
] == NULL
) {
403 else if (strcmp(argv
[argp
], "trace") == 0) {
404 const char *opt
= find_arg("Missing <trace> option", &argp
, argv
);
406 trace_option(opt
+ 1, 0);
408 trace_option(opt
, 1);
410 else if (strcmp(*argv
, "change-media") == 0) {
411 const char *device
= find_arg("Missing device name", &argp
, argv
);
412 const char *media
= argv
[++argp
];
413 device_ioctl(tree_find_device(root
, device
), NULL
, 0,
414 device_ioctl_change_media
, media
);
417 printf_filtered("Unknown PSIM command %s, try\n", argv
[argp
]);
418 printf_filtered(" trace <trace-option>\n");
419 printf_filtered(" change-media <device> [ <new-image> ]\n");
424 /* create the simulator proper from the device tree and executable */
428 psim_create(const char *file_name
,
434 os_emul
*os_emulation
;
437 /* given this partially populated device tree, os_emul_create() uses
438 it and file_name to determine the selected emulation and hence
439 further populate the tree with any other required nodes. */
441 os_emulation
= os_emul_create(file_name
, root
);
442 if (os_emulation
== NULL
)
443 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name
);
445 /* fill in the missing real number of CPU's */
446 nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
447 if (MAX_NR_PROCESSORS
< nr_cpus
)
448 error("target and configured number of cpus conflict\n");
450 /* fill in the missing TARGET BYTE ORDER information */
451 current_target_byte_order
452 = (tree_find_boolean_property(root
, "/options/little-endian?")
455 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
456 error("target and configured byte order conflict\n");
458 /* fill in the missing OEA/VEA information */
459 env
= tree_find_string_property(root
, "/openprom/options/env");
460 current_environment
= ((strcmp(env
, "user") == 0
461 || strcmp(env
, "uea") == 0)
463 : (strcmp(env
, "virtual") == 0
464 || strcmp(env
, "vea") == 0)
465 ? VIRTUAL_ENVIRONMENT
466 : (strcmp(env
, "operating") == 0
467 || strcmp(env
, "oea") == 0)
468 ? OPERATING_ENVIRONMENT
470 if (current_environment
== 0)
471 error("unreconized /options env property\n");
472 if (CURRENT_ENVIRONMENT
!= current_environment
)
473 error("target and configured environment conflict\n");
475 /* fill in the missing ALLIGNMENT information */
477 = (tree_find_boolean_property(root
, "/openprom/options/strict-alignment?")
479 : NONSTRICT_ALIGNMENT
);
480 if (CURRENT_ALIGNMENT
!= current_alignment
)
481 error("target and configured alignment conflict\n");
483 /* fill in the missing FLOATING POINT information */
484 current_floating_point
485 = (tree_find_boolean_property(root
, "/openprom/options/floating-point?")
486 ? HARD_FLOATING_POINT
487 : SOFT_FLOATING_POINT
);
488 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
489 error("target and configured floating-point conflict\n");
491 /* fill in the missing STDIO information */
493 = (tree_find_boolean_property(root
, "/openprom/options/use-stdio?")
496 if (CURRENT_STDIO
!= current_stdio
)
497 error("target and configured stdio interface conflict\n");
499 /* sort out the level of detail for issue modeling */
501 = tree_find_integer_property(root
, "/openprom/options/model-issue");
502 if (CURRENT_MODEL_ISSUE
!= current_model_issue
)
503 error("target and configured model-issue conflict\n");
505 /* sort out our model architecture - wrong.
507 FIXME: this should be obtaining the required information from the
508 device tree via the "/chosen" property "cpu" which is an instance
509 (ihandle) for the only executing processor. By converting that
510 ihandle into the corresponding cpu's phandle and then querying
511 the "name" property, the cpu type can be determined. Ok? */
513 model_set(tree_find_string_property(root
, "/openprom/options/model"));
516 system
= ZALLOC(psim
);
517 system
->events
= event_queue_create();
518 system
->memory
= core_from_device(root
);
519 system
->monitor
= mon_create();
520 system
->nr_cpus
= nr_cpus
;
521 system
->os_emulation
= os_emulation
;
522 system
->devices
= root
;
524 /* now all the processors attaching to each their per-cpu information */
525 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
526 system
->processors
[cpu_nr
] = cpu_create(system
,
528 mon_cpu(system
->monitor
,
530 system
->os_emulation
,
534 /* dump out the contents of the device tree */
535 if (ppc_trace
[trace_print_device_tree
] || ppc_trace
[trace_dump_device_tree
])
537 if (ppc_trace
[trace_dump_device_tree
])
544 /* allow the simulation to stop/restart abnormaly */
548 psim_set_halt_and_restart(psim
*system
,
550 void *restart_jmp_buf
)
552 system
->path_to_halt
= halt_jmp_buf
;
553 system
->path_to_restart
= restart_jmp_buf
;
558 psim_clear_halt_and_restart(psim
*system
)
560 system
->path_to_halt
= NULL
;
561 system
->path_to_restart
= NULL
;
566 psim_restart(psim
*system
,
569 ASSERT(current_cpu
>= 0 && current_cpu
< system
->nr_cpus
);
570 ASSERT(system
->path_to_restart
!= NULL
);
571 system
->last_cpu
= current_cpu
;
572 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
577 cntrl_c_simulation(void *data
)
581 psim_nr_cpus(system
),
588 psim_stop(psim
*system
)
590 event_queue_schedule_after_signal(psim_event_queue(system
),
598 psim_halt(psim
*system
,
603 ASSERT(current_cpu
>= 0 && current_cpu
<= system
->nr_cpus
);
604 ASSERT(system
->path_to_halt
!= NULL
);
605 system
->last_cpu
= current_cpu
;
606 system
->halt_status
.reason
= reason
;
607 system
->halt_status
.signal
= signal
;
608 if (current_cpu
== system
->nr_cpus
) {
609 system
->halt_status
.cpu_nr
= 0;
610 system
->halt_status
.program_counter
=
611 cpu_get_program_counter(system
->processors
[0]);
614 system
->halt_status
.cpu_nr
= current_cpu
;
615 system
->halt_status
.program_counter
=
616 cpu_get_program_counter(system
->processors
[current_cpu
]);
618 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
624 psim_last_cpu(psim
*system
)
626 return system
->last_cpu
;
631 psim_nr_cpus(psim
*system
)
633 return system
->nr_cpus
;
638 psim_get_status(psim
*system
)
640 return system
->halt_status
;
646 psim_cpu(psim
*system
,
649 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
652 return system
->processors
[cpu_nr
];
658 psim_device(psim
*system
,
661 return tree_find_device(system
->devices
, path
);
666 psim_event_queue(psim
*system
)
668 return system
->events
;
675 psim_max_iterations_exceeded(void *data
)
679 system
->nr_cpus
, /* halted during an event */
687 psim_init(psim
*system
)
691 /* scrub the monitor */
692 mon_init(system
->monitor
, system
->nr_cpus
);
694 /* trash any pending events */
695 event_queue_init(system
->events
);
697 /* if needed, schedule a halt event. FIXME - In the future this
698 will be replaced by a more generic change to psim_command(). A
699 new command `schedule NNN halt' being added. */
700 if (tree_find_property(system
->devices
, "/openprom/options/max-iterations")) {
701 event_queue_schedule(system
->events
,
702 tree_find_integer_property(system
->devices
,
703 "/openprom/options/max-iterations") - 2,
704 psim_max_iterations_exceeded
,
708 /* scrub all the cpus */
709 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
710 cpu_init(system
->processors
[cpu_nr
]);
712 /* init all the devices (which updates the cpus) */
713 tree_init(system
->devices
, system
);
715 /* and the emulation (which needs an initialized device tree) */
716 os_emul_init(system
->os_emulation
, system
->nr_cpus
);
718 /* now sync each cpu against the initialized state of its registers */
719 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++) {
720 cpu
*processor
= system
->processors
[cpu_nr
];
721 cpu_synchronize_context(processor
, cpu_get_program_counter(processor
));
722 cpu_page_tlb_invalidate_all(processor
);
725 /* force loop to start with first cpu */
726 system
->last_cpu
= -1;
731 psim_stack(psim
*system
,
735 /* pass the stack device the argv/envp and let it work out what to
737 device
*stack_device
= tree_find_device(system
->devices
,
738 "/openprom/init/stack");
739 if (stack_device
!= (device
*)0) {
740 unsigned_word stack_pointer
;
741 ASSERT (psim_read_register(system
, 0, &stack_pointer
, "sp",
742 cooked_transfer
) > 0);
743 device_ioctl(stack_device
,
746 device_ioctl_create_stack
,
755 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
760 psim_step(psim
*system
)
762 volatile int keep_running
= 0;
763 idecode_run_until_stop(system
, &keep_running
,
764 system
->events
, system
->processors
, system
->nr_cpus
);
769 psim_run(psim
*system
)
772 system
->events
, system
->processors
, system
->nr_cpus
);
776 /* storage manipulation functions */
780 psim_read_register(psim
*system
,
786 register_descriptions description
;
790 /* find our processor */
791 if (which_cpu
== MAX_NR_PROCESSORS
) {
792 if (system
->last_cpu
== system
->nr_cpus
793 || system
->last_cpu
== -1)
796 which_cpu
= system
->last_cpu
;
798 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
800 processor
= system
->processors
[which_cpu
];
802 /* find the register description */
803 description
= register_description(reg
);
804 if (description
.type
== reg_invalid
)
806 cooked_buf
= alloca (description
.size
);
808 /* get the cooked value */
809 switch (description
.type
) {
812 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
816 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
820 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
824 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
828 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
832 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
836 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
840 *(fpscreg
*)cooked_buf
= cpu_registers(processor
)->fpscr
;
844 *(unsigned_word
*)cooked_buf
= mon_get_number_of_insns(system
->monitor
,
849 if (cpu_model(processor
) == NULL
)
850 error("$stalls only valid if processor unit model enabled (-I)\n");
851 *(unsigned_word
*)cooked_buf
= model_get_number_of_stalls(cpu_model(processor
));
855 if (cpu_model(processor
) == NULL
)
856 error("$cycles only valid if processor unit model enabled (-I)\n");
857 *(unsigned_word
*)cooked_buf
= model_get_number_of_cycles(cpu_model(processor
));
862 *(vreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vr
[description
.index
];
866 *(vscreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vscr
;
872 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->e500
.gprh
[description
.index
];
876 *(unsigned64
*)cooked_buf
= EVR(description
.index
);
880 *(accreg
*)cooked_buf
= cpu_registers(processor
)->e500
.acc
;
885 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
886 (unsigned long)processor
, (unsigned long)buf
, reg
,
887 "read of this register unimplemented");
892 /* the PSIM internal values are in host order. To fetch raw data,
893 they need to be converted into target order and then returned */
894 if (mode
== raw_transfer
) {
895 /* FIXME - assumes that all registers are simple integers */
896 switch (description
.size
) {
898 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
901 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
904 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
907 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
911 if (HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
913 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
914 memcpy(&h
.v
/*dest*/, cooked_buf
/*src*/, description
.size
);
915 { _SWAP_8(t
.d
[0] =, h
.d
[1]); }
916 { _SWAP_8(t
.d
[1] =, h
.d
[0]); }
917 memcpy(buf
/*dest*/, &t
/*src*/, description
.size
);
921 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
927 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
930 return description
.size
;
937 psim_write_register(psim
*system
,
944 register_descriptions description
;
947 /* find our processor */
948 if (which_cpu
== MAX_NR_PROCESSORS
) {
949 if (system
->last_cpu
== system
->nr_cpus
950 || system
->last_cpu
== -1)
953 which_cpu
= system
->last_cpu
;
956 /* find the description of the register */
957 description
= register_description(reg
);
958 if (description
.type
== reg_invalid
)
960 cooked_buf
= alloca (description
.size
);
962 if (which_cpu
== -1) {
964 for (i
= 0; i
< system
->nr_cpus
; i
++)
965 psim_write_register(system
, i
, buf
, reg
, mode
);
966 return description
.size
;
968 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
970 processor
= system
->processors
[which_cpu
];
972 /* If the data is comming in raw (target order), need to cook it
973 into host order before putting it into PSIM's internal structures */
974 if (mode
== raw_transfer
) {
975 switch (description
.size
) {
977 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
980 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
983 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
986 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
990 if (HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
992 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
993 memcpy(&t
.v
/*dest*/, buf
/*src*/, description
.size
);
994 { _SWAP_8(h
.d
[0] =, t
.d
[1]); }
995 { _SWAP_8(h
.d
[1] =, t
.d
[0]); }
996 memcpy(cooked_buf
/*dest*/, &h
/*src*/, description
.size
);
1000 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1005 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1008 /* put the cooked value into the register */
1009 switch (description
.type
) {
1012 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
1016 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
1020 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
1024 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
1028 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
1032 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
1036 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
1040 cpu_registers(processor
)->fpscr
= *(fpscreg
*)cooked_buf
;
1045 cpu_registers(processor
)->e500
.gprh
[description
.index
] = *(gpreg
*)cooked_buf
;
1051 v
= *(unsigned64
*)cooked_buf
;
1052 cpu_registers(processor
)->e500
.gprh
[description
.index
] = v
>> 32;
1053 cpu_registers(processor
)->gpr
[description
.index
] = v
;
1058 cpu_registers(processor
)->e500
.acc
= *(accreg
*)cooked_buf
;
1064 cpu_registers(processor
)->altivec
.vr
[description
.index
] = *(vreg
*)cooked_buf
;
1068 cpu_registers(processor
)->altivec
.vscr
= *(vscreg
*)cooked_buf
;
1073 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1074 (unsigned long)processor
, (unsigned long)cooked_buf
, reg
,
1075 "read of this register unimplemented");
1080 return description
.size
;
1087 psim_read_memory(psim
*system
,
1090 unsigned_word vaddr
,
1094 if (which_cpu
== MAX_NR_PROCESSORS
) {
1095 if (system
->last_cpu
== system
->nr_cpus
1096 || system
->last_cpu
== -1)
1099 which_cpu
= system
->last_cpu
;
1101 processor
= system
->processors
[which_cpu
];
1102 return vm_data_map_read_buffer(cpu_data_map(processor
),
1103 buffer
, vaddr
, nr_bytes
,
1110 psim_write_memory(psim
*system
,
1113 unsigned_word vaddr
,
1115 int violate_read_only_section
)
1118 if (which_cpu
== MAX_NR_PROCESSORS
) {
1119 if (system
->last_cpu
== system
->nr_cpus
1120 || system
->last_cpu
== -1)
1123 which_cpu
= system
->last_cpu
;
1125 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
1126 processor
= system
->processors
[which_cpu
];
1127 return vm_data_map_write_buffer(cpu_data_map(processor
),
1128 buffer
, vaddr
, nr_bytes
, 1/*violate-read-only*/,
1135 psim_print_info(psim
*system
,
1138 mon_print_info(system
, system
->monitor
, verbose
);
1142 /* Merge a device tree and a device file. */
1146 psim_merge_device_file(device
*root
,
1147 const char *file_name
)
1151 char device_path
[1000];
1154 /* try opening the file */
1155 description
= fopen(file_name
, "r");
1156 if (description
== NULL
) {
1158 error("Invalid file %s specified", file_name
);
1163 while (fgets(device_path
, sizeof(device_path
), description
)) {
1165 /* check that the full line was read */
1166 if (strchr(device_path
, '\n') == NULL
) {
1167 fclose(description
);
1168 error("%s:%d: line to long - %s",
1169 file_name
, line_nr
, device_path
);
1172 *strchr(device_path
, '\n') = '\0';
1174 /* skip comments ("#" or ";") and blank lines lines */
1175 for (device
= device_path
;
1176 *device
!= '\0' && isspace(*device
);
1178 if (device
[0] == '#'
1180 || device
[0] == '\0')
1182 /* merge any appended lines */
1183 while (device_path
[strlen(device_path
) - 1] == '\\') {
1184 int curlen
= strlen(device_path
) - 1;
1186 device_path
[curlen
] = '\0';
1187 /* append the next line */
1188 if (!fgets(device_path
+ curlen
, sizeof(device_path
) - curlen
, description
)) {
1189 fclose(description
);
1190 error("%s:%s: unexpected eof in line continuation - %s",
1191 file_name
, line_nr
, device_path
);
1193 if (strchr(device_path
, '\n') == NULL
) {
1194 fclose(description
);
1195 error("%s:%d: line to long - %s",
1196 file_name
, line_nr
, device_path
);
1199 *strchr(device_path
, '\n') = '\0';
1202 /* parse this line */
1203 current
= tree_parse(current
, "%s", device
);
1205 fclose(description
);
1209 #endif /* _PSIM_C_ */