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
, SIM_OPEN_KIND kind
)
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 (kind
== SIM_OPEN_STANDALONE
)
222 if (REPORT_BUGS_TO
[0])
223 printf ("Report bugs to %s\n", REPORT_BUGS_TO
);
228 /* Test "string" for containing a string of digits that form a number
229 between "min" and "max". The return value is the number or "err". */
231 int is_num( char *string
, int min
, int max
, int err
)
235 for ( ; *string
; ++string
)
237 if (!isdigit(*string
))
242 result
= result
* 10 + (*string
- '0');
244 if (result
< min
|| result
> max
)
252 psim_options(device
*root
,
256 device
*current
= root
;
261 while (argv
[argp
] != NULL
&& argv
[argp
][0] == '-') {
262 char *p
= argv
[argp
] + 1;
267 printf_filtered ("Invalid Option: %s\n", argv
[argp
]);
268 psim_usage (0, 0, kind
);
271 param
= find_arg("Missing <count> option for -c (max-iterations)\n", &argp
, argv
);
272 tree_parse(root
, "/openprom/options/max-iterations %s", param
);
275 param
= find_arg("Missing <emul> option for -e (os-emul)\n", &argp
, argv
);
276 tree_parse(root
, "/openprom/options/os-emul %s", param
);
279 /* endian spec, ignored for now */
280 param
= find_arg("Missing <endian> option for -E (target-endian)\n", &argp
, argv
);
281 if (strcmp (param
, "big") == 0)
282 tree_parse (root
, "/options/little-endian? false");
283 else if (strcmp (param
, "little") == 0)
284 tree_parse (root
, "/options/little-endian? true");
287 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
288 psim_usage (0, 0, kind
);
293 param
= find_arg("Missing <file> option for -f\n", &argp
, argv
);
294 psim_merge_device_file(root
, param
);
298 psim_usage (1, 1, kind
);
301 psim_usage (2, 1, kind
);
305 tree_parse(root
, "/openprom/trace/print-info %c", p
[1]);
309 tree_parse(root
, "/openprom/trace/print-info 1");
313 tree_parse(root
, "/openprom/trace/print-info 2");
314 tree_parse(root
, "/openprom/options/model-issue %d",
315 MODEL_ISSUE_PROCESS
);
318 param
= find_arg("Missing <model> option for -m (model)\n", &argp
, argv
);
319 tree_parse(root
, "/openprom/options/model \"%s", param
);
322 param
= find_arg("Missing <nr-smp> option for -n (smp)\n", &argp
, argv
);
323 tree_parse(root
, "/openprom/options/smp %s", param
);
326 param
= find_arg("Missing <dev-spec> option for -o\n", &argp
, argv
);
327 if (memcmp(param
, "mpc860c0", 8) == 0)
329 if (param
[8] == '\0')
330 tree_parse(root
, "/options/mpc860c0 5");
331 else if (param
[8] == '=' && is_num(param
+9, 1, 10, 0))
333 tree_parse(root
, "/options/mpc860c0 %s", param
+9);
335 else error("Invalid mpc860c0 option for -o\n");
338 current
= tree_parse(current
, "%s", param
);
341 param
= find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp
, argv
);
342 tree_parse(root
, "/openprom/options/oea-memory-size %s",
346 param
= find_arg("Missing <trace> option for -t (trace/*)\n", &argp
, argv
);
348 tree_parse(root
, "/openprom/trace/%s 0", param
+1);
350 tree_parse(root
, "/openprom/trace/%s 1", param
);
353 /* it's a long option of the form --optionname=optionvalue.
354 Such options can be passed through if we are invoked by
356 if (strstr(argv
[argp
], "architecture") != NULL
) {
357 /* we must consume the argument here, so that we get out
359 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
360 printf_filtered("Warning - architecture parameter ignored\n");
362 else if (strcmp (argv
[argp
], "--help") == 0)
364 psim_usage (0, 1, kind
);
367 else if (strncmp (argv
[argp
], "--sysroot=",
368 sizeof ("--sysroot=") - 1) == 0)
369 /* Ignore this option. */
370 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
371 else if (strcmp (argv
[argp
], "--version") == 0)
373 extern const char version
[];
374 printf ("GNU simulator %s%s\n", PKGVERSION
, version
);
375 if (kind
== SIM_OPEN_STANDALONE
)
382 printf_filtered ("Invalid option: %s\n", argv
[argp
]);
383 psim_usage (0, 0, kind
);
392 /* force the trace node to process its options now *before* the tree
393 initialization occures */
394 device_ioctl(tree_find_device(root
, "/openprom/trace"),
396 device_ioctl_set_trace
);
399 void semantic_init(device
* root
);
403 /* return where the options end */
409 psim_command(device
*root
,
413 if (argv
[argp
] == NULL
) {
416 else if (strcmp(argv
[argp
], "trace") == 0) {
417 const char *opt
= find_arg("Missing <trace> option", &argp
, argv
);
419 trace_option(opt
+ 1, 0);
421 trace_option(opt
, 1);
423 else if (strcmp(*argv
, "change-media") == 0) {
424 char *device
= find_arg("Missing device name", &argp
, argv
);
425 char *media
= argv
[++argp
];
426 device_ioctl(tree_find_device(root
, device
), NULL
, 0,
427 device_ioctl_change_media
, media
);
430 printf_filtered("Unknown PSIM command %s, try\n", argv
[argp
]);
431 printf_filtered(" trace <trace-option>\n");
432 printf_filtered(" change-media <device> [ <new-image> ]\n");
437 /* create the simulator proper from the device tree and executable */
441 psim_create(const char *file_name
,
447 os_emul
*os_emulation
;
450 /* given this partially populated device tree, os_emul_create() uses
451 it and file_name to determine the selected emulation and hence
452 further populate the tree with any other required nodes. */
454 os_emulation
= os_emul_create(file_name
, root
);
455 if (os_emulation
== NULL
)
456 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name
);
458 /* fill in the missing real number of CPU's */
459 nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
460 if (MAX_NR_PROCESSORS
< nr_cpus
)
461 error("target and configured number of cpus conflict\n");
463 /* fill in the missing TARGET BYTE ORDER information */
464 current_target_byte_order
465 = (tree_find_boolean_property(root
, "/options/little-endian?")
468 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
469 error("target and configured byte order conflict\n");
471 /* fill in the missing HOST BYTE ORDER information */
472 current_host_byte_order
= (current_host_byte_order
= 1,
473 (*(char*)(¤t_host_byte_order
)
476 if (CURRENT_HOST_BYTE_ORDER
!= current_host_byte_order
)
477 error("host and configured byte order conflict\n");
479 /* fill in the missing OEA/VEA information */
480 env
= tree_find_string_property(root
, "/openprom/options/env");
481 current_environment
= ((strcmp(env
, "user") == 0
482 || strcmp(env
, "uea") == 0)
484 : (strcmp(env
, "virtual") == 0
485 || strcmp(env
, "vea") == 0)
486 ? VIRTUAL_ENVIRONMENT
487 : (strcmp(env
, "operating") == 0
488 || strcmp(env
, "oea") == 0)
489 ? OPERATING_ENVIRONMENT
491 if (current_environment
== 0)
492 error("unreconized /options env property\n");
493 if (CURRENT_ENVIRONMENT
!= current_environment
)
494 error("target and configured environment conflict\n");
496 /* fill in the missing ALLIGNMENT information */
498 = (tree_find_boolean_property(root
, "/openprom/options/strict-alignment?")
500 : NONSTRICT_ALIGNMENT
);
501 if (CURRENT_ALIGNMENT
!= current_alignment
)
502 error("target and configured alignment conflict\n");
504 /* fill in the missing FLOATING POINT information */
505 current_floating_point
506 = (tree_find_boolean_property(root
, "/openprom/options/floating-point?")
507 ? HARD_FLOATING_POINT
508 : SOFT_FLOATING_POINT
);
509 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
510 error("target and configured floating-point conflict\n");
512 /* fill in the missing STDIO information */
514 = (tree_find_boolean_property(root
, "/openprom/options/use-stdio?")
517 if (CURRENT_STDIO
!= current_stdio
)
518 error("target and configured stdio interface conflict\n");
520 /* sort out the level of detail for issue modeling */
522 = tree_find_integer_property(root
, "/openprom/options/model-issue");
523 if (CURRENT_MODEL_ISSUE
!= current_model_issue
)
524 error("target and configured model-issue conflict\n");
526 /* sort out our model architecture - wrong.
528 FIXME: this should be obtaining the required information from the
529 device tree via the "/chosen" property "cpu" which is an instance
530 (ihandle) for the only executing processor. By converting that
531 ihandle into the corresponding cpu's phandle and then querying
532 the "name" property, the cpu type can be determined. Ok? */
534 model_set(tree_find_string_property(root
, "/openprom/options/model"));
537 system
= ZALLOC(psim
);
538 system
->events
= event_queue_create();
539 system
->memory
= core_from_device(root
);
540 system
->monitor
= mon_create();
541 system
->nr_cpus
= nr_cpus
;
542 system
->os_emulation
= os_emulation
;
543 system
->devices
= root
;
545 /* now all the processors attaching to each their per-cpu information */
546 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
547 system
->processors
[cpu_nr
] = cpu_create(system
,
549 mon_cpu(system
->monitor
,
551 system
->os_emulation
,
555 /* dump out the contents of the device tree */
556 if (ppc_trace
[trace_print_device_tree
] || ppc_trace
[trace_dump_device_tree
])
558 if (ppc_trace
[trace_dump_device_tree
])
565 /* allow the simulation to stop/restart abnormaly */
569 psim_set_halt_and_restart(psim
*system
,
571 void *restart_jmp_buf
)
573 system
->path_to_halt
= halt_jmp_buf
;
574 system
->path_to_restart
= restart_jmp_buf
;
579 psim_clear_halt_and_restart(psim
*system
)
581 system
->path_to_halt
= NULL
;
582 system
->path_to_restart
= NULL
;
587 psim_restart(psim
*system
,
590 ASSERT(current_cpu
>= 0 && current_cpu
< system
->nr_cpus
);
591 ASSERT(system
->path_to_restart
!= NULL
);
592 system
->last_cpu
= current_cpu
;
593 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
598 cntrl_c_simulation(void *data
)
602 psim_nr_cpus(system
),
609 psim_stop(psim
*system
)
611 event_queue_schedule_after_signal(psim_event_queue(system
),
619 psim_halt(psim
*system
,
624 ASSERT(current_cpu
>= 0 && current_cpu
<= system
->nr_cpus
);
625 ASSERT(system
->path_to_halt
!= NULL
);
626 system
->last_cpu
= current_cpu
;
627 system
->halt_status
.reason
= reason
;
628 system
->halt_status
.signal
= signal
;
629 if (current_cpu
== system
->nr_cpus
) {
630 system
->halt_status
.cpu_nr
= 0;
631 system
->halt_status
.program_counter
=
632 cpu_get_program_counter(system
->processors
[0]);
635 system
->halt_status
.cpu_nr
= current_cpu
;
636 system
->halt_status
.program_counter
=
637 cpu_get_program_counter(system
->processors
[current_cpu
]);
639 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
645 psim_last_cpu(psim
*system
)
647 return system
->last_cpu
;
652 psim_nr_cpus(psim
*system
)
654 return system
->nr_cpus
;
659 psim_get_status(psim
*system
)
661 return system
->halt_status
;
667 psim_cpu(psim
*system
,
670 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
673 return system
->processors
[cpu_nr
];
679 psim_device(psim
*system
,
682 return tree_find_device(system
->devices
, path
);
687 psim_event_queue(psim
*system
)
689 return system
->events
;
696 psim_max_iterations_exceeded(void *data
)
700 system
->nr_cpus
, /* halted during an event */
708 psim_init(psim
*system
)
712 /* scrub the monitor */
713 mon_init(system
->monitor
, system
->nr_cpus
);
715 /* trash any pending events */
716 event_queue_init(system
->events
);
718 /* if needed, schedule a halt event. FIXME - In the future this
719 will be replaced by a more generic change to psim_command(). A
720 new command `schedule NNN halt' being added. */
721 if (tree_find_property(system
->devices
, "/openprom/options/max-iterations")) {
722 event_queue_schedule(system
->events
,
723 tree_find_integer_property(system
->devices
,
724 "/openprom/options/max-iterations") - 2,
725 psim_max_iterations_exceeded
,
729 /* scrub all the cpus */
730 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
731 cpu_init(system
->processors
[cpu_nr
]);
733 /* init all the devices (which updates the cpus) */
734 tree_init(system
->devices
, system
);
736 /* and the emulation (which needs an initialized device tree) */
737 os_emul_init(system
->os_emulation
, system
->nr_cpus
);
739 /* now sync each cpu against the initialized state of its registers */
740 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++) {
741 cpu
*processor
= system
->processors
[cpu_nr
];
742 cpu_synchronize_context(processor
, cpu_get_program_counter(processor
));
743 cpu_page_tlb_invalidate_all(processor
);
746 /* force loop to start with first cpu */
747 system
->last_cpu
= -1;
752 psim_stack(psim
*system
,
756 /* pass the stack device the argv/envp and let it work out what to
758 device
*stack_device
= tree_find_device(system
->devices
,
759 "/openprom/init/stack");
760 if (stack_device
!= (device
*)0) {
761 unsigned_word stack_pointer
;
762 ASSERT (psim_read_register(system
, 0, &stack_pointer
, "sp",
763 cooked_transfer
) > 0);
764 device_ioctl(stack_device
,
767 device_ioctl_create_stack
,
776 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
781 psim_step(psim
*system
)
783 volatile int keep_running
= 0;
784 idecode_run_until_stop(system
, &keep_running
,
785 system
->events
, system
->processors
, system
->nr_cpus
);
790 psim_run(psim
*system
)
793 system
->events
, system
->processors
, system
->nr_cpus
);
797 /* storage manipulation functions */
801 psim_read_register(psim
*system
,
807 register_descriptions description
;
811 /* find our processor */
812 if (which_cpu
== MAX_NR_PROCESSORS
) {
813 if (system
->last_cpu
== system
->nr_cpus
814 || system
->last_cpu
== -1)
817 which_cpu
= system
->last_cpu
;
819 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
821 processor
= system
->processors
[which_cpu
];
823 /* find the register description */
824 description
= register_description(reg
);
825 if (description
.type
== reg_invalid
)
827 cooked_buf
= alloca (description
.size
);
829 /* get the cooked value */
830 switch (description
.type
) {
833 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
837 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
841 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
845 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
849 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
853 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
857 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
861 *(fpscreg
*)cooked_buf
= cpu_registers(processor
)->fpscr
;
865 *(unsigned_word
*)cooked_buf
= mon_get_number_of_insns(system
->monitor
,
870 if (cpu_model(processor
) == NULL
)
871 error("$stalls only valid if processor unit model enabled (-I)\n");
872 *(unsigned_word
*)cooked_buf
= model_get_number_of_stalls(cpu_model(processor
));
876 if (cpu_model(processor
) == NULL
)
877 error("$cycles only valid if processor unit model enabled (-I)\n");
878 *(unsigned_word
*)cooked_buf
= model_get_number_of_cycles(cpu_model(processor
));
883 *(vreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vr
[description
.index
];
887 *(vscreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vscr
;
893 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->e500
.gprh
[description
.index
];
897 *(unsigned64
*)cooked_buf
= EVR(description
.index
);
901 *(accreg
*)cooked_buf
= cpu_registers(processor
)->e500
.acc
;
906 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
907 (unsigned long)processor
, (unsigned long)buf
, reg
,
908 "read of this register unimplemented");
913 /* the PSIM internal values are in host order. To fetch raw data,
914 they need to be converted into target order and then returned */
915 if (mode
== raw_transfer
) {
916 /* FIXME - assumes that all registers are simple integers */
917 switch (description
.size
) {
919 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
922 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
925 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
928 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
932 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
934 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
935 memcpy(&h
.v
/*dest*/, cooked_buf
/*src*/, description
.size
);
936 { _SWAP_8(t
.d
[0] =, h
.d
[1]); }
937 { _SWAP_8(t
.d
[1] =, h
.d
[0]); }
938 memcpy(buf
/*dest*/, &t
/*src*/, description
.size
);
942 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
948 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
951 return description
.size
;
958 psim_write_register(psim
*system
,
965 register_descriptions description
;
968 /* find our processor */
969 if (which_cpu
== MAX_NR_PROCESSORS
) {
970 if (system
->last_cpu
== system
->nr_cpus
971 || system
->last_cpu
== -1)
974 which_cpu
= system
->last_cpu
;
977 /* find the description of the register */
978 description
= register_description(reg
);
979 if (description
.type
== reg_invalid
)
981 cooked_buf
= alloca (description
.size
);
983 if (which_cpu
== -1) {
985 for (i
= 0; i
< system
->nr_cpus
; i
++)
986 psim_write_register(system
, i
, buf
, reg
, mode
);
987 return description
.size
;
989 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
991 processor
= system
->processors
[which_cpu
];
993 /* If the data is comming in raw (target order), need to cook it
994 into host order before putting it into PSIM's internal structures */
995 if (mode
== raw_transfer
) {
996 switch (description
.size
) {
998 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
1001 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
1004 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
1007 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
1011 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
1013 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
1014 memcpy(&t
.v
/*dest*/, buf
/*src*/, description
.size
);
1015 { _SWAP_8(h
.d
[0] =, t
.d
[1]); }
1016 { _SWAP_8(h
.d
[1] =, t
.d
[0]); }
1017 memcpy(cooked_buf
/*dest*/, &h
/*src*/, description
.size
);
1021 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1026 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1029 /* put the cooked value into the register */
1030 switch (description
.type
) {
1033 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
1037 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
1041 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
1045 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
1049 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
1053 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
1057 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
1061 cpu_registers(processor
)->fpscr
= *(fpscreg
*)cooked_buf
;
1066 cpu_registers(processor
)->e500
.gprh
[description
.index
] = *(gpreg
*)cooked_buf
;
1072 v
= *(unsigned64
*)cooked_buf
;
1073 cpu_registers(processor
)->e500
.gprh
[description
.index
] = v
>> 32;
1074 cpu_registers(processor
)->gpr
[description
.index
] = v
;
1079 cpu_registers(processor
)->e500
.acc
= *(accreg
*)cooked_buf
;
1085 cpu_registers(processor
)->altivec
.vr
[description
.index
] = *(vreg
*)cooked_buf
;
1089 cpu_registers(processor
)->altivec
.vscr
= *(vscreg
*)cooked_buf
;
1094 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1095 (unsigned long)processor
, (unsigned long)cooked_buf
, reg
,
1096 "read of this register unimplemented");
1101 return description
.size
;
1108 psim_read_memory(psim
*system
,
1111 unsigned_word vaddr
,
1115 if (which_cpu
== MAX_NR_PROCESSORS
) {
1116 if (system
->last_cpu
== system
->nr_cpus
1117 || system
->last_cpu
== -1)
1120 which_cpu
= system
->last_cpu
;
1122 processor
= system
->processors
[which_cpu
];
1123 return vm_data_map_read_buffer(cpu_data_map(processor
),
1124 buffer
, vaddr
, nr_bytes
,
1131 psim_write_memory(psim
*system
,
1134 unsigned_word vaddr
,
1136 int violate_read_only_section
)
1139 if (which_cpu
== MAX_NR_PROCESSORS
) {
1140 if (system
->last_cpu
== system
->nr_cpus
1141 || system
->last_cpu
== -1)
1144 which_cpu
= system
->last_cpu
;
1146 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
1147 processor
= system
->processors
[which_cpu
];
1148 return vm_data_map_write_buffer(cpu_data_map(processor
),
1149 buffer
, vaddr
, nr_bytes
, 1/*violate-read-only*/,
1156 psim_print_info(psim
*system
,
1159 mon_print_info(system
, system
->monitor
, verbose
);
1163 /* Merge a device tree and a device file. */
1167 psim_merge_device_file(device
*root
,
1168 const char *file_name
)
1172 char device_path
[1000];
1175 /* try opening the file */
1176 description
= fopen(file_name
, "r");
1177 if (description
== NULL
) {
1179 error("Invalid file %s specified", file_name
);
1184 while (fgets(device_path
, sizeof(device_path
), description
)) {
1186 /* check that the full line was read */
1187 if (strchr(device_path
, '\n') == NULL
) {
1188 fclose(description
);
1189 error("%s:%d: line to long - %s",
1190 file_name
, line_nr
, device_path
);
1193 *strchr(device_path
, '\n') = '\0';
1195 /* skip comments ("#" or ";") and blank lines lines */
1196 for (device
= device_path
;
1197 *device
!= '\0' && isspace(*device
);
1199 if (device
[0] == '#'
1201 || device
[0] == '\0')
1203 /* merge any appended lines */
1204 while (device_path
[strlen(device_path
) - 1] == '\\') {
1205 int curlen
= strlen(device_path
) - 1;
1207 device_path
[curlen
] = '\0';
1208 /* append the next line */
1209 if (!fgets(device_path
+ curlen
, sizeof(device_path
) - curlen
, description
)) {
1210 fclose(description
);
1211 error("%s:%s: unexpected eof in line continuation - %s",
1212 file_name
, line_nr
, device_path
);
1214 if (strchr(device_path
, '\n') == NULL
) {
1215 fclose(description
);
1216 error("%s:%d: line to long - %s",
1217 file_name
, line_nr
, device_path
);
1220 *strchr(device_path
, '\n') = '\0';
1223 /* parse this line */
1224 current
= tree_parse(current
, "%s", device
);
1226 fclose(description
);
1230 #endif /* _PSIM_C_ */