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_host_byte_order
;
68 int current_environment
;
69 int current_alignment
;
70 int current_floating_point
;
71 int current_model_issue
= MODEL_ISSUE_IGNORE
;
72 int current_stdio
= DO_USE_STDIO
;
73 model_enum current_model
= WITH_DEFAULT_MODEL
;
76 /* create the device tree */
82 device
*root
= tree_parse(NULL
, "core");
83 tree_parse(root
, "/aliases");
84 tree_parse(root
, "/options");
85 tree_parse(root
, "/chosen");
86 tree_parse(root
, "/packages");
87 tree_parse(root
, "/cpus");
88 tree_parse(root
, "/openprom");
89 tree_parse(root
, "/openprom/init");
90 tree_parse(root
, "/openprom/trace");
91 tree_parse(root
, "/openprom/options");
97 find_arg(char *err_msg
,
102 if (argv
[*ptr_to_argp
] == NULL
)
104 return argv
[*ptr_to_argp
];
109 psim_usage (int verbose
, int help
, SIM_OPEN_KIND kind
)
111 printf_filtered("Usage:\n");
112 printf_filtered("\n");
113 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
114 printf_filtered("\n");
115 printf_filtered("Where\n");
116 printf_filtered("\n");
117 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
119 printf_filtered("\t This can either be a PowerPC binary or\n");
120 printf_filtered("\t a text file containing a device tree\n");
121 printf_filtered("\t specification.\n");
122 printf_filtered("\t PSIM will attempt to determine from the\n");
123 printf_filtered("\t specified <image> the intended emulation\n");
124 printf_filtered("\t environment.\n");
125 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
126 printf_filtered("\t environment can be specified using the\n");
127 printf_filtered("\t `-e' option (described below).\n");
128 printf_filtered("\n"); }
129 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
131 printf_filtered("\t These arguments will be passed to\n");
132 printf_filtered("\t <image> (as standard C argv, argc)\n");
133 printf_filtered("\t when <image> is started.\n");
134 printf_filtered("\n"); }
135 printf_filtered("\t<psim-option> See below\n");
136 printf_filtered("\n");
137 printf_filtered("The following are valid <psim-option>s:\n");
138 printf_filtered("\n");
140 printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
142 printf_filtered("\n");
145 printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
147 printf_filtered("\t Specify -i2 for a more detailed display\n");
148 printf_filtered("\n");
151 printf_filtered("\t-I Print execution unit statistics\n");
152 if (verbose
) { printf_filtered("\n"); }
154 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
156 printf_filtered("\t Can be any of the following:\n");
157 printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
158 printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
159 printf_filtered("\t solaris - UEA + Solaris system calls\n");
160 printf_filtered("\t linux - UEA + Linux system calls\n");
161 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
162 printf_filtered("\n"); }
164 printf_filtered("\t-E <endian> Specify the endianness of the target\n");
166 printf_filtered("\t Can be any of the following:\n");
167 printf_filtered("\t big - big endian target\n");
168 printf_filtered("\t little - little endian target\n");
169 printf_filtered("\n"); }
171 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
172 if (verbose
) { printf_filtered("\n"); }
174 printf_filtered("\t-h -? -H give more detailed usage\n");
175 if (verbose
) { printf_filtered("\n"); }
177 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
179 printf_filtered("\t Selects the processor to use when\n");
180 printf_filtered("\t modeling execution units. Includes:\n");
181 printf_filtered("\t 604, 603 and 603e\n");
182 printf_filtered("\n"); }
184 printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
186 printf_filtered("\t Specifies the number of processors that are\n");
187 printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
188 printf_filtered("\t simulation\n");
189 printf_filtered("\n"); }
191 printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
192 if (verbose
) { printf_filtered("\n"); }
194 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
195 if (verbose
) { printf_filtered("\n"); }
197 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
198 if (verbose
) { printf_filtered("\n"); }
200 printf_filtered("\n");
201 trace_usage(verbose
);
202 device_usage(verbose
);
204 printf_filtered("\n");
208 if (kind
== SIM_OPEN_STANDALONE
)
210 if (REPORT_BUGS_TO
[0])
211 printf ("Report bugs to %s\n", REPORT_BUGS_TO
);
216 /* Test "string" for containing a string of digits that form a number
217 between "min" and "max". The return value is the number or "err". */
219 int is_num( char *string
, int min
, int max
, int err
)
223 for ( ; *string
; ++string
)
225 if (!isdigit(*string
))
230 result
= result
* 10 + (*string
- '0');
232 if (result
< min
|| result
> max
)
240 psim_options(device
*root
,
244 device
*current
= root
;
249 while (argv
[argp
] != NULL
&& argv
[argp
][0] == '-') {
250 char *p
= argv
[argp
] + 1;
255 printf_filtered ("Invalid Option: %s\n", argv
[argp
]);
256 psim_usage (0, 0, kind
);
259 param
= find_arg("Missing <count> option for -c (max-iterations)\n", &argp
, argv
);
260 tree_parse(root
, "/openprom/options/max-iterations %s", param
);
263 param
= find_arg("Missing <emul> option for -e (os-emul)\n", &argp
, argv
);
264 tree_parse(root
, "/openprom/options/os-emul %s", param
);
267 /* endian spec, ignored for now */
268 param
= find_arg("Missing <endian> option for -E (target-endian)\n", &argp
, argv
);
269 if (strcmp (param
, "big") == 0)
270 tree_parse (root
, "/options/little-endian? false");
271 else if (strcmp (param
, "little") == 0)
272 tree_parse (root
, "/options/little-endian? true");
275 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
276 psim_usage (0, 0, kind
);
281 param
= find_arg("Missing <file> option for -f\n", &argp
, argv
);
282 psim_merge_device_file(root
, param
);
286 psim_usage (1, 1, kind
);
289 psim_usage (2, 1, kind
);
293 tree_parse(root
, "/openprom/trace/print-info %c", p
[1]);
297 tree_parse(root
, "/openprom/trace/print-info 1");
301 tree_parse(root
, "/openprom/trace/print-info 2");
302 tree_parse(root
, "/openprom/options/model-issue %d",
303 MODEL_ISSUE_PROCESS
);
306 param
= find_arg("Missing <model> option for -m (model)\n", &argp
, argv
);
307 tree_parse(root
, "/openprom/options/model \"%s", param
);
310 param
= find_arg("Missing <nr-smp> option for -n (smp)\n", &argp
, argv
);
311 tree_parse(root
, "/openprom/options/smp %s", param
);
314 param
= find_arg("Missing <dev-spec> option for -o\n", &argp
, argv
);
315 if (memcmp(param
, "mpc860c0", 8) == 0)
317 if (param
[8] == '\0')
318 tree_parse(root
, "/options/mpc860c0 5");
319 else if (param
[8] == '=' && is_num(param
+9, 1, 10, 0))
321 tree_parse(root
, "/options/mpc860c0 %s", param
+9);
323 else error("Invalid mpc860c0 option for -o\n");
326 current
= tree_parse(current
, "%s", param
);
329 param
= find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp
, argv
);
330 tree_parse(root
, "/openprom/options/oea-memory-size %s",
334 param
= find_arg("Missing <trace> option for -t (trace/*)\n", &argp
, argv
);
336 tree_parse(root
, "/openprom/trace/%s 0", param
+1);
338 tree_parse(root
, "/openprom/trace/%s 1", param
);
341 /* it's a long option of the form --optionname=optionvalue.
342 Such options can be passed through if we are invoked by
344 if (strstr(argv
[argp
], "architecture") != NULL
) {
345 /* we must consume the argument here, so that we get out
347 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
348 printf_filtered("Warning - architecture parameter ignored\n");
350 else if (strcmp (argv
[argp
], "--help") == 0)
352 psim_usage (0, 1, kind
);
355 else if (strncmp (argv
[argp
], "--sysroot=",
356 sizeof ("--sysroot=") - 1) == 0)
357 /* Ignore this option. */
358 p
= argv
[argp
] + strlen(argv
[argp
]) - 1;
359 else if (strcmp (argv
[argp
], "--version") == 0)
361 extern const char version
[];
362 printf ("GNU simulator %s%s\n", PKGVERSION
, version
);
363 if (kind
== SIM_OPEN_STANDALONE
)
370 printf_filtered ("Invalid option: %s\n", argv
[argp
]);
371 psim_usage (0, 0, kind
);
380 /* force the trace node to process its options now *before* the tree
381 initialization occures */
382 device_ioctl(tree_find_device(root
, "/openprom/trace"),
384 device_ioctl_set_trace
);
387 void semantic_init(device
* root
);
391 /* return where the options end */
397 psim_command(device
*root
,
401 if (argv
[argp
] == NULL
) {
404 else if (strcmp(argv
[argp
], "trace") == 0) {
405 const char *opt
= find_arg("Missing <trace> option", &argp
, argv
);
407 trace_option(opt
+ 1, 0);
409 trace_option(opt
, 1);
411 else if (strcmp(*argv
, "change-media") == 0) {
412 char *device
= find_arg("Missing device name", &argp
, argv
);
413 char *media
= argv
[++argp
];
414 device_ioctl(tree_find_device(root
, device
), NULL
, 0,
415 device_ioctl_change_media
, media
);
418 printf_filtered("Unknown PSIM command %s, try\n", argv
[argp
]);
419 printf_filtered(" trace <trace-option>\n");
420 printf_filtered(" change-media <device> [ <new-image> ]\n");
425 /* create the simulator proper from the device tree and executable */
429 psim_create(const char *file_name
,
435 os_emul
*os_emulation
;
438 /* given this partially populated device tree, os_emul_create() uses
439 it and file_name to determine the selected emulation and hence
440 further populate the tree with any other required nodes. */
442 os_emulation
= os_emul_create(file_name
, root
);
443 if (os_emulation
== NULL
)
444 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name
);
446 /* fill in the missing real number of CPU's */
447 nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
448 if (MAX_NR_PROCESSORS
< nr_cpus
)
449 error("target and configured number of cpus conflict\n");
451 /* fill in the missing TARGET BYTE ORDER information */
452 current_target_byte_order
453 = (tree_find_boolean_property(root
, "/options/little-endian?")
456 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
457 error("target and configured byte order conflict\n");
459 /* fill in the missing HOST BYTE ORDER information */
460 current_host_byte_order
= (current_host_byte_order
= 1,
461 (*(char*)(¤t_host_byte_order
)
464 if (CURRENT_HOST_BYTE_ORDER
!= current_host_byte_order
)
465 error("host and configured byte order conflict\n");
467 /* fill in the missing OEA/VEA information */
468 env
= tree_find_string_property(root
, "/openprom/options/env");
469 current_environment
= ((strcmp(env
, "user") == 0
470 || strcmp(env
, "uea") == 0)
472 : (strcmp(env
, "virtual") == 0
473 || strcmp(env
, "vea") == 0)
474 ? VIRTUAL_ENVIRONMENT
475 : (strcmp(env
, "operating") == 0
476 || strcmp(env
, "oea") == 0)
477 ? OPERATING_ENVIRONMENT
479 if (current_environment
== 0)
480 error("unreconized /options env property\n");
481 if (CURRENT_ENVIRONMENT
!= current_environment
)
482 error("target and configured environment conflict\n");
484 /* fill in the missing ALLIGNMENT information */
486 = (tree_find_boolean_property(root
, "/openprom/options/strict-alignment?")
488 : NONSTRICT_ALIGNMENT
);
489 if (CURRENT_ALIGNMENT
!= current_alignment
)
490 error("target and configured alignment conflict\n");
492 /* fill in the missing FLOATING POINT information */
493 current_floating_point
494 = (tree_find_boolean_property(root
, "/openprom/options/floating-point?")
495 ? HARD_FLOATING_POINT
496 : SOFT_FLOATING_POINT
);
497 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
498 error("target and configured floating-point conflict\n");
500 /* fill in the missing STDIO information */
502 = (tree_find_boolean_property(root
, "/openprom/options/use-stdio?")
505 if (CURRENT_STDIO
!= current_stdio
)
506 error("target and configured stdio interface conflict\n");
508 /* sort out the level of detail for issue modeling */
510 = tree_find_integer_property(root
, "/openprom/options/model-issue");
511 if (CURRENT_MODEL_ISSUE
!= current_model_issue
)
512 error("target and configured model-issue conflict\n");
514 /* sort out our model architecture - wrong.
516 FIXME: this should be obtaining the required information from the
517 device tree via the "/chosen" property "cpu" which is an instance
518 (ihandle) for the only executing processor. By converting that
519 ihandle into the corresponding cpu's phandle and then querying
520 the "name" property, the cpu type can be determined. Ok? */
522 model_set(tree_find_string_property(root
, "/openprom/options/model"));
525 system
= ZALLOC(psim
);
526 system
->events
= event_queue_create();
527 system
->memory
= core_from_device(root
);
528 system
->monitor
= mon_create();
529 system
->nr_cpus
= nr_cpus
;
530 system
->os_emulation
= os_emulation
;
531 system
->devices
= root
;
533 /* now all the processors attaching to each their per-cpu information */
534 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
535 system
->processors
[cpu_nr
] = cpu_create(system
,
537 mon_cpu(system
->monitor
,
539 system
->os_emulation
,
543 /* dump out the contents of the device tree */
544 if (ppc_trace
[trace_print_device_tree
] || ppc_trace
[trace_dump_device_tree
])
546 if (ppc_trace
[trace_dump_device_tree
])
553 /* allow the simulation to stop/restart abnormaly */
557 psim_set_halt_and_restart(psim
*system
,
559 void *restart_jmp_buf
)
561 system
->path_to_halt
= halt_jmp_buf
;
562 system
->path_to_restart
= restart_jmp_buf
;
567 psim_clear_halt_and_restart(psim
*system
)
569 system
->path_to_halt
= NULL
;
570 system
->path_to_restart
= NULL
;
575 psim_restart(psim
*system
,
578 ASSERT(current_cpu
>= 0 && current_cpu
< system
->nr_cpus
);
579 ASSERT(system
->path_to_restart
!= NULL
);
580 system
->last_cpu
= current_cpu
;
581 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
586 cntrl_c_simulation(void *data
)
590 psim_nr_cpus(system
),
597 psim_stop(psim
*system
)
599 event_queue_schedule_after_signal(psim_event_queue(system
),
607 psim_halt(psim
*system
,
612 ASSERT(current_cpu
>= 0 && current_cpu
<= system
->nr_cpus
);
613 ASSERT(system
->path_to_halt
!= NULL
);
614 system
->last_cpu
= current_cpu
;
615 system
->halt_status
.reason
= reason
;
616 system
->halt_status
.signal
= signal
;
617 if (current_cpu
== system
->nr_cpus
) {
618 system
->halt_status
.cpu_nr
= 0;
619 system
->halt_status
.program_counter
=
620 cpu_get_program_counter(system
->processors
[0]);
623 system
->halt_status
.cpu_nr
= current_cpu
;
624 system
->halt_status
.program_counter
=
625 cpu_get_program_counter(system
->processors
[current_cpu
]);
627 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
633 psim_last_cpu(psim
*system
)
635 return system
->last_cpu
;
640 psim_nr_cpus(psim
*system
)
642 return system
->nr_cpus
;
647 psim_get_status(psim
*system
)
649 return system
->halt_status
;
655 psim_cpu(psim
*system
,
658 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
661 return system
->processors
[cpu_nr
];
667 psim_device(psim
*system
,
670 return tree_find_device(system
->devices
, path
);
675 psim_event_queue(psim
*system
)
677 return system
->events
;
684 psim_max_iterations_exceeded(void *data
)
688 system
->nr_cpus
, /* halted during an event */
696 psim_init(psim
*system
)
700 /* scrub the monitor */
701 mon_init(system
->monitor
, system
->nr_cpus
);
703 /* trash any pending events */
704 event_queue_init(system
->events
);
706 /* if needed, schedule a halt event. FIXME - In the future this
707 will be replaced by a more generic change to psim_command(). A
708 new command `schedule NNN halt' being added. */
709 if (tree_find_property(system
->devices
, "/openprom/options/max-iterations")) {
710 event_queue_schedule(system
->events
,
711 tree_find_integer_property(system
->devices
,
712 "/openprom/options/max-iterations") - 2,
713 psim_max_iterations_exceeded
,
717 /* scrub all the cpus */
718 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
719 cpu_init(system
->processors
[cpu_nr
]);
721 /* init all the devices (which updates the cpus) */
722 tree_init(system
->devices
, system
);
724 /* and the emulation (which needs an initialized device tree) */
725 os_emul_init(system
->os_emulation
, system
->nr_cpus
);
727 /* now sync each cpu against the initialized state of its registers */
728 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++) {
729 cpu
*processor
= system
->processors
[cpu_nr
];
730 cpu_synchronize_context(processor
, cpu_get_program_counter(processor
));
731 cpu_page_tlb_invalidate_all(processor
);
734 /* force loop to start with first cpu */
735 system
->last_cpu
= -1;
740 psim_stack(psim
*system
,
744 /* pass the stack device the argv/envp and let it work out what to
746 device
*stack_device
= tree_find_device(system
->devices
,
747 "/openprom/init/stack");
748 if (stack_device
!= (device
*)0) {
749 unsigned_word stack_pointer
;
750 ASSERT (psim_read_register(system
, 0, &stack_pointer
, "sp",
751 cooked_transfer
) > 0);
752 device_ioctl(stack_device
,
755 device_ioctl_create_stack
,
764 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
769 psim_step(psim
*system
)
771 volatile int keep_running
= 0;
772 idecode_run_until_stop(system
, &keep_running
,
773 system
->events
, system
->processors
, system
->nr_cpus
);
778 psim_run(psim
*system
)
781 system
->events
, system
->processors
, system
->nr_cpus
);
785 /* storage manipulation functions */
789 psim_read_register(psim
*system
,
795 register_descriptions description
;
799 /* find our processor */
800 if (which_cpu
== MAX_NR_PROCESSORS
) {
801 if (system
->last_cpu
== system
->nr_cpus
802 || system
->last_cpu
== -1)
805 which_cpu
= system
->last_cpu
;
807 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
809 processor
= system
->processors
[which_cpu
];
811 /* find the register description */
812 description
= register_description(reg
);
813 if (description
.type
== reg_invalid
)
815 cooked_buf
= alloca (description
.size
);
817 /* get the cooked value */
818 switch (description
.type
) {
821 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
825 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
829 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
833 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
837 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
841 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
845 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
849 *(fpscreg
*)cooked_buf
= cpu_registers(processor
)->fpscr
;
853 *(unsigned_word
*)cooked_buf
= mon_get_number_of_insns(system
->monitor
,
858 if (cpu_model(processor
) == NULL
)
859 error("$stalls only valid if processor unit model enabled (-I)\n");
860 *(unsigned_word
*)cooked_buf
= model_get_number_of_stalls(cpu_model(processor
));
864 if (cpu_model(processor
) == NULL
)
865 error("$cycles only valid if processor unit model enabled (-I)\n");
866 *(unsigned_word
*)cooked_buf
= model_get_number_of_cycles(cpu_model(processor
));
871 *(vreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vr
[description
.index
];
875 *(vscreg
*)cooked_buf
= cpu_registers(processor
)->altivec
.vscr
;
881 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->e500
.gprh
[description
.index
];
885 *(unsigned64
*)cooked_buf
= EVR(description
.index
);
889 *(accreg
*)cooked_buf
= cpu_registers(processor
)->e500
.acc
;
894 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
895 (unsigned long)processor
, (unsigned long)buf
, reg
,
896 "read of this register unimplemented");
901 /* the PSIM internal values are in host order. To fetch raw data,
902 they need to be converted into target order and then returned */
903 if (mode
== raw_transfer
) {
904 /* FIXME - assumes that all registers are simple integers */
905 switch (description
.size
) {
907 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
910 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
913 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
916 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
920 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
922 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
923 memcpy(&h
.v
/*dest*/, cooked_buf
/*src*/, description
.size
);
924 { _SWAP_8(t
.d
[0] =, h
.d
[1]); }
925 { _SWAP_8(t
.d
[1] =, h
.d
[0]); }
926 memcpy(buf
/*dest*/, &t
/*src*/, description
.size
);
930 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
936 memcpy(buf
/*dest*/, cooked_buf
/*src*/, description
.size
);
939 return description
.size
;
946 psim_write_register(psim
*system
,
953 register_descriptions description
;
956 /* find our processor */
957 if (which_cpu
== MAX_NR_PROCESSORS
) {
958 if (system
->last_cpu
== system
->nr_cpus
959 || system
->last_cpu
== -1)
962 which_cpu
= system
->last_cpu
;
965 /* find the description of the register */
966 description
= register_description(reg
);
967 if (description
.type
== reg_invalid
)
969 cooked_buf
= alloca (description
.size
);
971 if (which_cpu
== -1) {
973 for (i
= 0; i
< system
->nr_cpus
; i
++)
974 psim_write_register(system
, i
, buf
, reg
, mode
);
975 return description
.size
;
977 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
979 processor
= system
->processors
[which_cpu
];
981 /* If the data is comming in raw (target order), need to cook it
982 into host order before putting it into PSIM's internal structures */
983 if (mode
== raw_transfer
) {
984 switch (description
.size
) {
986 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
989 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
992 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
995 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
999 if (CURRENT_HOST_BYTE_ORDER
!= CURRENT_TARGET_BYTE_ORDER
)
1001 union { vreg v
; unsigned_8 d
[2]; } h
, t
;
1002 memcpy(&t
.v
/*dest*/, buf
/*src*/, description
.size
);
1003 { _SWAP_8(h
.d
[0] =, t
.d
[1]); }
1004 { _SWAP_8(h
.d
[1] =, t
.d
[0]); }
1005 memcpy(cooked_buf
/*dest*/, &h
/*src*/, description
.size
);
1009 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1014 memcpy(cooked_buf
/*dest*/, buf
/*src*/, description
.size
);
1017 /* put the cooked value into the register */
1018 switch (description
.type
) {
1021 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
1025 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
1029 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
1033 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
1037 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
1041 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
1045 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
1049 cpu_registers(processor
)->fpscr
= *(fpscreg
*)cooked_buf
;
1054 cpu_registers(processor
)->e500
.gprh
[description
.index
] = *(gpreg
*)cooked_buf
;
1060 v
= *(unsigned64
*)cooked_buf
;
1061 cpu_registers(processor
)->e500
.gprh
[description
.index
] = v
>> 32;
1062 cpu_registers(processor
)->gpr
[description
.index
] = v
;
1067 cpu_registers(processor
)->e500
.acc
= *(accreg
*)cooked_buf
;
1073 cpu_registers(processor
)->altivec
.vr
[description
.index
] = *(vreg
*)cooked_buf
;
1077 cpu_registers(processor
)->altivec
.vscr
= *(vscreg
*)cooked_buf
;
1082 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1083 (unsigned long)processor
, (unsigned long)cooked_buf
, reg
,
1084 "read of this register unimplemented");
1089 return description
.size
;
1096 psim_read_memory(psim
*system
,
1099 unsigned_word vaddr
,
1103 if (which_cpu
== MAX_NR_PROCESSORS
) {
1104 if (system
->last_cpu
== system
->nr_cpus
1105 || system
->last_cpu
== -1)
1108 which_cpu
= system
->last_cpu
;
1110 processor
= system
->processors
[which_cpu
];
1111 return vm_data_map_read_buffer(cpu_data_map(processor
),
1112 buffer
, vaddr
, nr_bytes
,
1119 psim_write_memory(psim
*system
,
1122 unsigned_word vaddr
,
1124 int violate_read_only_section
)
1127 if (which_cpu
== MAX_NR_PROCESSORS
) {
1128 if (system
->last_cpu
== system
->nr_cpus
1129 || system
->last_cpu
== -1)
1132 which_cpu
= system
->last_cpu
;
1134 ASSERT(which_cpu
>= 0 && which_cpu
< system
->nr_cpus
);
1135 processor
= system
->processors
[which_cpu
];
1136 return vm_data_map_write_buffer(cpu_data_map(processor
),
1137 buffer
, vaddr
, nr_bytes
, 1/*violate-read-only*/,
1144 psim_print_info(psim
*system
,
1147 mon_print_info(system
, system
->monitor
, verbose
);
1151 /* Merge a device tree and a device file. */
1155 psim_merge_device_file(device
*root
,
1156 const char *file_name
)
1160 char device_path
[1000];
1163 /* try opening the file */
1164 description
= fopen(file_name
, "r");
1165 if (description
== NULL
) {
1167 error("Invalid file %s specified", file_name
);
1172 while (fgets(device_path
, sizeof(device_path
), description
)) {
1174 /* check that the full line was read */
1175 if (strchr(device_path
, '\n') == NULL
) {
1176 fclose(description
);
1177 error("%s:%d: line to long - %s",
1178 file_name
, line_nr
, device_path
);
1181 *strchr(device_path
, '\n') = '\0';
1183 /* skip comments ("#" or ";") and blank lines lines */
1184 for (device
= device_path
;
1185 *device
!= '\0' && isspace(*device
);
1187 if (device
[0] == '#'
1189 || device
[0] == '\0')
1191 /* merge any appended lines */
1192 while (device_path
[strlen(device_path
) - 1] == '\\') {
1193 int curlen
= strlen(device_path
) - 1;
1195 device_path
[curlen
] = '\0';
1196 /* append the next line */
1197 if (!fgets(device_path
+ curlen
, sizeof(device_path
) - curlen
, description
)) {
1198 fclose(description
);
1199 error("%s:%s: unexpected eof in line continuation - %s",
1200 file_name
, line_nr
, device_path
);
1202 if (strchr(device_path
, '\n') == NULL
) {
1203 fclose(description
);
1204 error("%s:%d: line to long - %s",
1205 file_name
, line_nr
, device_path
);
1208 *strchr(device_path
, '\n') = '\0';
1211 /* parse this line */
1212 current
= tree_parse(current
, "%s", device
);
1214 fclose(description
);
1218 #endif /* _PSIM_C_ */