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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "cpu.h" /* includes psim.h */
52 #include "libiberty.h"
53 #include "gdb/signals.h"
55 /* system structure, actual size of processor array determined at
62 os_emul
*os_emulation
;
65 /* escape routine for inner functions */
67 void *path_to_restart
;
69 /* status from last halt */
70 psim_status halt_status
;
72 /* the processors proper */
74 int last_cpu
; /* CPU that last (tried to) execute an instruction */
75 cpu
*processors
[MAX_NR_PROCESSORS
];
79 int current_target_byte_order
;
80 int current_host_byte_order
;
81 int current_environment
;
82 int current_alignment
;
83 int current_floating_point
;
84 int current_model_issue
= MODEL_ISSUE_IGNORE
;
85 int current_stdio
= DO_USE_STDIO
;
86 model_enum current_model
= WITH_DEFAULT_MODEL
;
89 /* create the device tree */
95 device
*root
= tree_parse(NULL
, "core");
96 tree_parse(root
, "/aliases");
97 tree_parse(root
, "/options");
98 tree_parse(root
, "/chosen");
99 tree_parse(root
, "/packages");
100 tree_parse(root
, "/cpus");
101 tree_parse(root
, "/openprom");
102 tree_parse(root
, "/openprom/init");
103 tree_parse(root
, "/openprom/trace");
104 tree_parse(root
, "/openprom/options");
110 find_arg(char *err_msg
,
115 if (argv
[*ptr_to_argp
] == NULL
)
117 return argv
[*ptr_to_argp
];
122 psim_usage(int verbose
, int help
)
124 printf_filtered("Usage:\n");
125 printf_filtered("\n");
126 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
127 printf_filtered("\n");
128 printf_filtered("Where\n");
129 printf_filtered("\n");
130 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
132 printf_filtered("\t This can either be a PowerPC binary or\n");
133 printf_filtered("\t a text file containing a device tree\n");
134 printf_filtered("\t specification.\n");
135 printf_filtered("\t PSIM will attempt to determine from the\n");
136 printf_filtered("\t specified <image> the intended emulation\n");
137 printf_filtered("\t environment.\n");
138 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
139 printf_filtered("\t environment can be specified using the\n");
140 printf_filtered("\t `-e' option (described below).\n");
141 printf_filtered("\n"); }
142 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
144 printf_filtered("\t These arguments will be passed to\n");
145 printf_filtered("\t <image> (as standard C argv, argc)\n");
146 printf_filtered("\t when <image> is started.\n");
147 printf_filtered("\n"); }
148 printf_filtered("\t<psim-option> See below\n");
149 printf_filtered("\n");
150 printf_filtered("The following are valid <psim-option>s:\n");
151 printf_filtered("\n");
153 printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
155 printf_filtered("\n");
158 printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
160 printf_filtered("\t Specify -i2 for a more detailed display\n");
161 printf_filtered("\n");
164 printf_filtered("\t-I Print execution unit statistics\n");
165 if (verbose
) { printf_filtered("\n"); }
167 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
169 printf_filtered("\t Can be any of the following:\n");
170 printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
171 printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
172 printf_filtered("\t solaris - UEA + Solaris system calls\n");
173 printf_filtered("\t linux - UEA + Linux system calls\n");
174 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
175 printf_filtered("\n"); }
177 printf_filtered("\t-E <endian> Specify the endianness of the target\n");
179 printf_filtered("\t Can be any of the following:\n");
180 printf_filtered("\t big - big endian target\n");
181 printf_filtered("\t little - little endian target\n");
182 printf_filtered("\n"); }
184 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
185 if (verbose
) { printf_filtered("\n"); }
187 printf_filtered("\t-h -? -H give more detailed usage\n");
188 if (verbose
) { printf_filtered("\n"); }
190 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
192 printf_filtered("\t Selects the processor to use when\n");
193 printf_filtered("\t modeling execution units. Includes:\n");
194 printf_filtered("\t 604, 603 and 603e\n");
195 printf_filtered("\n"); }
197 printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
199 printf_filtered("\t Specifies the number of processors that are\n");
200 printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
201 printf_filtered("\t simulation\n");
202 printf_filtered("\n"); }
204 printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
205 if (verbose
) { printf_filtered("\n"); }
207 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
208 if (verbose
) { printf_filtered("\n"); }
210 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
211 if (verbose
) { printf_filtered("\n"); }
213 printf_filtered("\n");
214 trace_usage(verbose
);
215 device_usage(verbose
);
217 printf_filtered("\n");
221 if (REPORT_BUGS_TO
[0])
222 printf ("Report bugs to %s\n", REPORT_BUGS_TO
);
226 /* Test "string" for containing a string of digits that form a number
227 between "min" and "max". The return value is the number or "err". */
229 int is_num( char *string
, int min
, int max
, int err
)
233 for ( ; *string
; ++string
)
235 if (!isdigit(*string
))
240 result
= result
* 10 + (*string
- '0');
242 if (result
< min
|| result
> max
)
250 psim_options(device
*root
,
253 device
*current
= root
;
258 while (argv
[argp
] != NULL
&& argv
[argp
][0] == '-') {
259 char *p
= argv
[argp
] + 1;
264 printf_filtered ("Invalid Option: %s\n", argv
[argp
]);
269 param
= find_arg("Missing <count> option for -c (max-iterations)\n", &argp
, argv
);
270 tree_parse(root
, "/openprom/options/max-iterations %s", param
);
273 param
= find_arg("Missing <emul> option for -e (os-emul)\n", &argp
, argv
);
274 tree_parse(root
, "/openprom/options/os-emul %s", param
);
277 /* endian spec, ignored for now */
278 param
= find_arg("Missing <endian> option for -E (target-endian)\n", &argp
, argv
);
279 if (strcmp (param
, "big") == 0)
280 tree_parse (root
, "/options/little-endian? false");
281 else if (strcmp (param
, "little") == 0)
282 tree_parse (root
, "/options/little-endian? true");
285 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
290 param
= find_arg("Missing <file> option for -f\n", &argp
, argv
);
291 psim_merge_device_file(root
, param
);
302 tree_parse(root
, "/openprom/trace/print-info %c", p
[1]);
306 tree_parse(root
, "/openprom/trace/print-info 1");
310 tree_parse(root
, "/openprom/trace/print-info 2");
311 tree_parse(root
, "/openprom/options/model-issue %d",
312 MODEL_ISSUE_PROCESS
);
315 param
= find_arg("Missing <model> option for -m (model)\n", &argp
, argv
);
316 tree_parse(root
, "/openprom/options/model \"%s", param
);
319 param
= find_arg("Missing <nr-smp> option for -n (smp)\n", &argp
, argv
);
320 tree_parse(root
, "/openprom/options/smp %s", param
);
323 param
= find_arg("Missing <dev-spec> option for -o\n", &argp
, argv
);
324 if (memcmp(param
, "mpc860c0", 8) == 0)
326 if (param
[8] == '\0')
327 tree_parse(root
, "/options/mpc860c0 5");
328 else if (param
[8] == '=' && is_num(param
+9, 1, 10, 0))
330 tree_parse(root
, "/options/mpc860c0 %s", param
+9);
332 else error("Invalid mpc860c0 option for -o\n");
335 current
= tree_parse(current
, "%s", param
);
338 param
= find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp
, argv
);
339 tree_parse(root
, "/openprom/options/oea-memory-size %s",
343 param
= find_arg("Missing <trace> option for -t (trace/*)\n", &argp
, argv
);
345 tree_parse(root
, "/openprom/trace/%s 0", param
+1);
347 tree_parse(root
, "/openprom/trace/%s 1", param
);
350 /* it's a long option of the form --optionname=optionvalue.
351 Such options can be passed through if we are invoked by
353 if (strstr(argv
[argp
], "architecture") != NULL
) {
354 /* we must consume the argument here, so that we get out
356 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
357 printf_filtered("Warning - architecture parameter ignored\n");
359 else if (strcmp (argv
[argp
], "--help") == 0)
361 else if (strncmp (argv
[argp
], "--sysroot=",
362 sizeof ("--sysroot=") - 1) == 0)
363 /* Ignore this option. */
364 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
365 else if (strcmp (argv
[argp
], "--version") == 0)
367 extern const char version
[];
368 printf ("GNU simulator %s%s\n", PKGVERSION
, version
);
373 printf_filtered ("Invalid option: %s\n", argv
[argp
]);
383 /* force the trace node to process its options now *before* the tree
384 initialization occures */
385 device_ioctl(tree_find_device(root
, "/openprom/trace"),
387 device_ioctl_set_trace
);
390 void semantic_init(device
* root
);
394 /* return where the options end */
400 psim_command(device
*root
,
404 if (argv
[argp
] == NULL
) {
407 else if (strcmp(argv
[argp
], "trace") == 0) {
408 const char *opt
= find_arg("Missing <trace> option", &argp
, argv
);
410 trace_option(opt
+ 1, 0);
412 trace_option(opt
, 1);
414 else if (strcmp(*argv
, "change-media") == 0) {
415 char *device
= find_arg("Missing device name", &argp
, argv
);
416 char *media
= argv
[++argp
];
417 device_ioctl(tree_find_device(root
, device
), NULL
, 0,
418 device_ioctl_change_media
, media
);
421 printf_filtered("Unknown PSIM command %s, try\n", argv
[argp
]);
422 printf_filtered(" trace <trace-option>\n");
423 printf_filtered(" change-media <device> [ <new-image> ]\n");
428 /* create the simulator proper from the device tree and executable */
432 psim_create(const char *file_name
,
438 os_emul
*os_emulation
;
441 /* given this partially populated device tree, os_emul_create() uses
442 it and file_name to determine the selected emulation and hence
443 further populate the tree with any other required nodes. */
445 os_emulation
= os_emul_create(file_name
, root
);
446 if (os_emulation
== NULL
)
447 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name
);
449 /* fill in the missing real number of CPU's */
450 nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
451 if (MAX_NR_PROCESSORS
< nr_cpus
)
452 error("target and configured number of cpus conflict\n");
454 /* fill in the missing TARGET BYTE ORDER information */
455 current_target_byte_order
456 = (tree_find_boolean_property(root
, "/options/little-endian?")
459 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
460 error("target and configured byte order conflict\n");
462 /* fill in the missing HOST BYTE ORDER information */
463 current_host_byte_order
= (current_host_byte_order
= 1,
464 (*(char*)(¤t_host_byte_order
)
467 if (CURRENT_HOST_BYTE_ORDER
!= current_host_byte_order
)
468 error("host and configured byte order conflict\n");
470 /* fill in the missing OEA/VEA information */
471 env
= tree_find_string_property(root
, "/openprom/options/env");
472 current_environment
= ((strcmp(env
, "user") == 0
473 || strcmp(env
, "uea") == 0)
475 : (strcmp(env
, "virtual") == 0
476 || strcmp(env
, "vea") == 0)
477 ? VIRTUAL_ENVIRONMENT
478 : (strcmp(env
, "operating") == 0
479 || strcmp(env
, "oea") == 0)
480 ? OPERATING_ENVIRONMENT
482 if (current_environment
== 0)
483 error("unreconized /options env property\n");
484 if (CURRENT_ENVIRONMENT
!= current_environment
)
485 error("target and configured environment conflict\n");
487 /* fill in the missing ALLIGNMENT information */
489 = (tree_find_boolean_property(root
, "/openprom/options/strict-alignment?")
491 : NONSTRICT_ALIGNMENT
);
492 if (CURRENT_ALIGNMENT
!= current_alignment
)
493 error("target and configured alignment conflict\n");
495 /* fill in the missing FLOATING POINT information */
496 current_floating_point
497 = (tree_find_boolean_property(root
, "/openprom/options/floating-point?")
498 ? HARD_FLOATING_POINT
499 : SOFT_FLOATING_POINT
);
500 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
501 error("target and configured floating-point conflict\n");
503 /* fill in the missing STDIO information */
505 = (tree_find_boolean_property(root
, "/openprom/options/use-stdio?")
508 if (CURRENT_STDIO
!= current_stdio
)
509 error("target and configured stdio interface conflict\n");
511 /* sort out the level of detail for issue modeling */
513 = tree_find_integer_property(root
, "/openprom/options/model-issue");
514 if (CURRENT_MODEL_ISSUE
!= current_model_issue
)
515 error("target and configured model-issue conflict\n");
517 /* sort out our model architecture - wrong.
519 FIXME: this should be obtaining the required information from the
520 device tree via the "/chosen" property "cpu" which is an instance
521 (ihandle) for the only executing processor. By converting that
522 ihandle into the corresponding cpu's phandle and then querying
523 the "name" property, the cpu type can be determined. Ok? */
525 model_set(tree_find_string_property(root
, "/openprom/options/model"));
528 system
= ZALLOC(psim
);
529 system
->events
= event_queue_create();
530 system
->memory
= core_from_device(root
);
531 system
->monitor
= mon_create();
532 system
->nr_cpus
= nr_cpus
;
533 system
->os_emulation
= os_emulation
;
534 system
->devices
= root
;
536 /* now all the processors attaching to each their per-cpu information */
537 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
538 system
->processors
[cpu_nr
] = cpu_create(system
,
540 mon_cpu(system
->monitor
,
542 system
->os_emulation
,
546 /* dump out the contents of the device tree */
547 if (ppc_trace
[trace_print_device_tree
] || ppc_trace
[trace_dump_device_tree
])
549 if (ppc_trace
[trace_dump_device_tree
])
556 /* allow the simulation to stop/restart abnormaly */
560 psim_set_halt_and_restart(psim
*system
,
562 void *restart_jmp_buf
)
564 system
->path_to_halt
= halt_jmp_buf
;
565 system
->path_to_restart
= restart_jmp_buf
;
570 psim_clear_halt_and_restart(psim
*system
)
572 system
->path_to_halt
= NULL
;
573 system
->path_to_restart
= NULL
;
578 psim_restart(psim
*system
,
581 ASSERT(current_cpu
>= 0 && current_cpu
< system
->nr_cpus
);
582 ASSERT(system
->path_to_restart
!= NULL
);
583 system
->last_cpu
= current_cpu
;
584 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
589 cntrl_c_simulation(void *data
)
593 psim_nr_cpus(system
),
600 psim_stop(psim
*system
)
602 event_queue_schedule_after_signal(psim_event_queue(system
),
610 psim_halt(psim
*system
,
615 ASSERT(current_cpu
>= 0 && current_cpu
<= system
->nr_cpus
);
616 ASSERT(system
->path_to_halt
!= NULL
);
617 system
->last_cpu
= current_cpu
;
618 system
->halt_status
.reason
= reason
;
619 system
->halt_status
.signal
= signal
;
620 if (current_cpu
== system
->nr_cpus
) {
621 system
->halt_status
.cpu_nr
= 0;
622 system
->halt_status
.program_counter
=
623 cpu_get_program_counter(system
->processors
[0]);
626 system
->halt_status
.cpu_nr
= current_cpu
;
627 system
->halt_status
.program_counter
=
628 cpu_get_program_counter(system
->processors
[current_cpu
]);
630 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
636 psim_last_cpu(psim
*system
)
638 return system
->last_cpu
;
643 psim_nr_cpus(psim
*system
)
645 return system
->nr_cpus
;
650 psim_get_status(psim
*system
)
652 return system
->halt_status
;
658 psim_cpu(psim
*system
,
661 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
664 return system
->processors
[cpu_nr
];
670 psim_device(psim
*system
,
673 return tree_find_device(system
->devices
, path
);
678 psim_event_queue(psim
*system
)
680 return system
->events
;
687 psim_max_iterations_exceeded(void *data
)
691 system
->nr_cpus
, /* halted during an event */
699 psim_init(psim
*system
)
703 /* scrub the monitor */
704 mon_init(system
->monitor
, system
->nr_cpus
);
706 /* trash any pending events */
707 event_queue_init(system
->events
);
709 /* if needed, schedule a halt event. FIXME - In the future this
710 will be replaced by a more generic change to psim_command(). A
711 new command `schedule NNN halt' being added. */
712 if (tree_find_property(system
->devices
, "/openprom/options/max-iterations")) {
713 event_queue_schedule(system
->events
,
714 tree_find_integer_property(system
->devices
,
715 "/openprom/options/max-iterations") - 2,
716 psim_max_iterations_exceeded
,
720 /* scrub all the cpus */
721 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
722 cpu_init(system
->processors
[cpu_nr
]);
724 /* init all the devices (which updates the cpus) */
725 tree_init(system
->devices
, system
);
727 /* and the emulation (which needs an initialized device tree) */
728 os_emul_init(system
->os_emulation
, system
->nr_cpus
);
730 /* now sync each cpu against the initialized state of its registers */
731 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++) {
732 cpu
*processor
= system
->processors
[cpu_nr
];
733 cpu_synchronize_context(processor
, cpu_get_program_counter(processor
));
734 cpu_page_tlb_invalidate_all(processor
);
737 /* force loop to start with first cpu */
738 system
->last_cpu
= -1;
743 psim_stack(psim
*system
,
747 /* pass the stack device the argv/envp and let it work out what to
749 device
*stack_device
= tree_find_device(system
->devices
,
750 "/openprom/init/stack");
751 if (stack_device
!= (device
*)0) {
752 unsigned_word stack_pointer
;
753 ASSERT (psim_read_register(system
, 0, &stack_pointer
, "sp",
754 cooked_transfer
) > 0);
755 device_ioctl(stack_device
,
758 device_ioctl_create_stack
,
767 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
772 psim_step(psim
*system
)
774 volatile int keep_running
= 0;
775 idecode_run_until_stop(system
, &keep_running
,
776 system
->events
, system
->processors
, system
->nr_cpus
);
781 psim_run(psim
*system
)
784 system
->events
, system
->processors
, system
->nr_cpus
);
788 /* storage manipulation functions */
792 psim_read_register(psim
*system
,
798 register_descriptions description
;
802 /* find our processor */
803 if (which_cpu
== MAX_NR_PROCESSORS
) {
804 if (system
->last_cpu
== system
->nr_cpus
805 || system
->last_cpu
== -1)
808 which_cpu
= system
->last_cpu
;
810 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
812 processor
= system
->processors
[which_cpu
];
814 /* find the register description */
815 description
= register_description(reg
);
816 if (description
.type
== reg_invalid
)
818 cooked_buf
= alloca (description
.size
);
820 /* get the cooked value */
821 switch (description
.type
) {
824 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
828 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
832 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
836 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
840 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
844 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
848 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
852 *(fpscreg
*)cooked_buf
= cpu_registers(processor
)->fpscr
;
856 *(unsigned_word
*)cooked_buf
= mon_get_number_of_insns(system
->monitor
,
861 if (cpu_model(processor
) == NULL
)
862 error("$stalls only valid if processor unit model enabled (-I)\n");
863 *(unsigned_word
*)cooked_buf
= model_get_number_of_stalls(cpu_model(processor
));
867 if (cpu_model(processor
) == NULL
)
868 error("$cycles only valid if processor unit model enabled (-I)\n");
869 *(unsigned_word
*)cooked_buf
= model_get_number_of_cycles(cpu_model(processor
));
874 *(vreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vr
[description
.index
];
878 *(vscreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vscr
;
884 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->e500
.gprh
[description
.index
];
888 *(unsigned64
*)cooked_buf
= EVR(description
.index
);
892 *(accreg
*)cooked_buf
= cpu_registers(processor
)->e500
.acc
;
897 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
898 (unsigned long)processor
, (unsigned long)buf
, reg
,
899 "read of this register unimplemented");
904 /* the PSIM internal values are in host order. To fetch raw data,
905 they need to be converted into target order and then returned */
906 if (mode
== raw_transfer
) {
907 /* FIXME - assumes that all registers are simple integers */
908 switch (description
.size
) {
910 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
913 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
916 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
919 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
923 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
925 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
926 memcpy(&h
.v
/*dest*/, cooked_buf
/*src*/, description
.size
);
927 { _SWAP_8(t
.d
[0] =, h
.d
[1]); }
928 { _SWAP_8(t
.d
[1] =, h
.d
[0]); }
929 memcpy(buf
/*dest*/, &t
/*src*/, description
.size
);
933 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
939 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
942 return description
.size
;
949 psim_write_register(psim
*system
,
956 register_descriptions description
;
959 /* find our processor */
960 if (which_cpu
== MAX_NR_PROCESSORS
) {
961 if (system
->last_cpu
== system
->nr_cpus
962 || system
->last_cpu
== -1)
965 which_cpu
= system
->last_cpu
;
968 /* find the description of the register */
969 description
= register_description(reg
);
970 if (description
.type
== reg_invalid
)
972 cooked_buf
= alloca (description
.size
);
974 if (which_cpu
== -1) {
976 for (i
= 0; i
< system
->nr_cpus
; i
++)
977 psim_write_register(system
, i
, buf
, reg
, mode
);
978 return description
.size
;
980 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
982 processor
= system
->processors
[which_cpu
];
984 /* If the data is comming in raw (target order), need to cook it
985 into host order before putting it into PSIM's internal structures */
986 if (mode
== raw_transfer
) {
987 switch (description
.size
) {
989 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
992 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
995 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
998 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
1002 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
1004 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
1005 memcpy(&t
.v
/*dest*/, buf
/*src*/, description
.size
);
1006 { _SWAP_8(h
.d
[0] =, t
.d
[1]); }
1007 { _SWAP_8(h
.d
[1] =, t
.d
[0]); }
1008 memcpy(cooked_buf
/*dest*/, &h
/*src*/, description
.size
);
1012 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1017 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1020 /* put the cooked value into the register */
1021 switch (description
.type
) {
1024 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
1028 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
1032 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
1036 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
1040 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
1044 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
1048 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
1052 cpu_registers(processor
)->fpscr
= *(fpscreg
*)cooked_buf
;
1057 cpu_registers(processor
)->e500
.gprh
[description
.index
] = *(gpreg
*)cooked_buf
;
1063 v
= *(unsigned64
*)cooked_buf
;
1064 cpu_registers(processor
)->e500
.gprh
[description
.index
] = v
>> 32;
1065 cpu_registers(processor
)->gpr
[description
.index
] = v
;
1070 cpu_registers(processor
)->e500
.acc
= *(accreg
*)cooked_buf
;
1076 cpu_registers(processor
)->altivec
.vr
[description
.index
] = *(vreg
*)cooked_buf
;
1080 cpu_registers(processor
)->altivec
.vscr
= *(vscreg
*)cooked_buf
;
1085 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1086 (unsigned long)processor
, (unsigned long)cooked_buf
, reg
,
1087 "read of this register unimplemented");
1092 return description
.size
;
1099 psim_read_memory(psim
*system
,
1102 unsigned_word vaddr
,
1106 if (which_cpu
== MAX_NR_PROCESSORS
) {
1107 if (system
->last_cpu
== system
->nr_cpus
1108 || system
->last_cpu
== -1)
1111 which_cpu
= system
->last_cpu
;
1113 processor
= system
->processors
[which_cpu
];
1114 return vm_data_map_read_buffer(cpu_data_map(processor
),
1115 buffer
, vaddr
, nr_bytes
,
1122 psim_write_memory(psim
*system
,
1125 unsigned_word vaddr
,
1127 int violate_read_only_section
)
1130 if (which_cpu
== MAX_NR_PROCESSORS
) {
1131 if (system
->last_cpu
== system
->nr_cpus
1132 || system
->last_cpu
== -1)
1135 which_cpu
= system
->last_cpu
;
1137 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
1138 processor
= system
->processors
[which_cpu
];
1139 return vm_data_map_write_buffer(cpu_data_map(processor
),
1140 buffer
, vaddr
, nr_bytes
, 1/*violate-read-only*/,
1147 psim_print_info(psim
*system
,
1150 mon_print_info(system
, system
->monitor
, verbose
);
1154 /* Merge a device tree and a device file. */
1158 psim_merge_device_file(device
*root
,
1159 const char *file_name
)
1163 char device_path
[1000];
1166 /* try opening the file */
1167 description
= fopen(file_name
, "r");
1168 if (description
== NULL
) {
1170 error("Invalid file %s specified", file_name
);
1175 while (fgets(device_path
, sizeof(device_path
), description
)) {
1177 /* check that the full line was read */
1178 if (strchr(device_path
, '\n') == NULL
) {
1179 fclose(description
);
1180 error("%s:%d: line to long - %s",
1181 file_name
, line_nr
, device_path
);
1184 *strchr(device_path
, '\n') = '\0';
1186 /* skip comments ("#" or ";") and blank lines lines */
1187 for (device
= device_path
;
1188 *device
!= '\0' && isspace(*device
);
1190 if (device
[0] == '#'
1192 || device
[0] == '\0')
1194 /* merge any appended lines */
1195 while (device_path
[strlen(device_path
) - 1] == '\\') {
1196 int curlen
= strlen(device_path
) - 1;
1198 device_path
[curlen
] = '\0';
1199 /* append the next line */
1200 if (!fgets(device_path
+ curlen
, sizeof(device_path
) - curlen
, description
)) {
1201 fclose(description
);
1202 error("%s:%s: unexpected eof in line continuation - %s",
1203 file_name
, line_nr
, device_path
);
1205 if (strchr(device_path
, '\n') == NULL
) {
1206 fclose(description
);
1207 error("%s:%d: line to long - %s",
1208 file_name
, line_nr
, device_path
);
1211 *strchr(device_path
, '\n') = '\0';
1214 /* parse this line */
1215 current
= tree_parse(current
, "%s", device
);
1217 fclose(description
);
1221 #endif /* _PSIM_C_ */