New revision from Andrew
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
CommitLineData
8b3797aa
MM
1/* This file is part of the program psim.
2
eada1efc 3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
8b3797aa
MM
4
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 2 of the License, or
8 (at your option) any later version.
9
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.
14
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.
18
19 */
20
21
22#ifndef _PSIM_C_
23#define _PSIM_C_
24
30c87b55
MM
25#include "cpu.h" /* includes psim.h */
26#include "idecode.h"
27#include "options.h"
28
eada1efc 29
a983c8f0
MM
30#include <stdio.h>
31#include <ctype.h>
a983c8f0 32
c494cadd
MM
33#ifdef HAVE_STDLIB_H
34#include <stdlib.h>
35#endif
36
8b3797aa
MM
37#include <setjmp.h>
38
c494cadd
MM
39#ifdef HAVE_STRING_H
40#include <string.h>
41#else
42#ifdef HAVE_STRINGS_H
43#include <strings.h>
44#endif
45#endif
46
30c87b55 47
a983c8f0
MM
48#include "bfd.h"
49
50
8b3797aa
MM
51/* system structure, actual size of processor array determined at
52 runtime */
53
54struct _psim {
55 event_queue *events;
eada1efc 56 device *devices;
a983c8f0 57 mon *monitor;
eada1efc 58 os_emul *os_emulation;
8b3797aa 59 core *memory;
eada1efc 60
8b3797aa
MM
61 /* escape routine for inner functions */
62 void *path_to_halt;
63 void *path_to_restart;
eada1efc 64
8b3797aa
MM
65 /* status from last halt */
66 psim_status halt_status;
eada1efc
MM
67
68 /* the processors proper */
8b3797aa
MM
69 int nr_cpus;
70 int last_cpu; /* CPU that last (tried to) execute an instruction */
a983c8f0 71 cpu *processors[MAX_NR_PROCESSORS];
8b3797aa
MM
72};
73
74
75int current_target_byte_order;
76int current_host_byte_order;
77int current_environment;
78int current_alignment;
a983c8f0 79int current_floating_point;
290ad14a 80int current_model_issue = MODEL_ISSUE_IGNORE;
28816f45 81model_enum current_model = WITH_DEFAULT_MODEL;
a983c8f0
MM
82
83
eada1efc 84/* create the device tree */
a983c8f0 85
eada1efc
MM
86INLINE_PSIM\
87(device *)
88psim_tree(void)
a983c8f0 89{
30c87b55 90 device *root = device_tree_add_parsed(NULL, "core");
eada1efc
MM
91 device_tree_add_parsed(root, "/aliases");
92 device_tree_add_parsed(root, "/options");
93 device_tree_add_parsed(root, "/chosen");
94 device_tree_add_parsed(root, "/packages");
95 device_tree_add_parsed(root, "/cpus");
96 device_tree_add_parsed(root, "/openprom");
97 device_tree_add_parsed(root, "/openprom/init");
98 device_tree_add_parsed(root, "/openprom/trace");
99 device_tree_add_parsed(root, "/openprom/options");
100 return root;
a983c8f0
MM
101}
102
eada1efc
MM
103STATIC_INLINE_PSIM\
104(char *)
105find_arg(char *err_msg,
106 int *ptr_to_argp,
107 char **argv)
a983c8f0 108{
eada1efc
MM
109 *ptr_to_argp += 1;
110 if (argv[*ptr_to_argp] == NULL)
111 error(err_msg);
112 return argv[*ptr_to_argp];
a983c8f0
MM
113}
114
eada1efc
MM
115INLINE_PSIM\
116(void)
117psim_usage(int verbose)
a983c8f0 118{
eada1efc
MM
119 printf_filtered("Usage:\n");
120 printf_filtered("\n");
121 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
122 printf_filtered("\n");
123 printf_filtered("Where\n");
124 printf_filtered("\n");
125 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
126 if (verbose) {
127 printf_filtered("\t This can either be a PowerPC binary or\n");
128 printf_filtered("\t a text file containing a device tree\n");
129 printf_filtered("\t specification.\n");
130 printf_filtered("\t PSIM will attempt to determine from the\n");
131 printf_filtered("\t specified <image> the intended emulation\n");
132 printf_filtered("\t environment.\n");
133 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
134 printf_filtered("\t environment can be specified using the\n");
135 printf_filtered("\t `-e' option (described below).\n");
136 printf_filtered("\n"); }
137 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
138 if (verbose) {
139 printf_filtered("\t These arguments will be passed to\n");
140 printf_filtered("\t <image> (as standard C argv, argc)\n");
141 printf_filtered("\t when <image> is started.\n");
142 printf_filtered("\n"); }
143 printf_filtered("\t<psim-option> See below\n");
144 printf_filtered("\n");
145 printf_filtered("The following are valid <psim-option>s:\n");
146 printf_filtered("\n");
147 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
148 if (verbose) {
149 printf_filtered("\t Selects the processor to use when\n");
150 printf_filtered("\t modeling execution units. Includes:\n");
151 printf_filtered("\t 604, 603 and 603e\n");
152 printf_filtered("\n"); }
153 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
154 if (verbose) {
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");
88f1eac4
MM
158 printf_filtered("\t solaris - UEA + Solaris system calls\n");
159 printf_filtered("\t linux - UEA + Linux system calls\n");
eada1efc
MM
160 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
161 printf_filtered("\n"); }
162 printf_filtered("\t-i Print instruction counting statistics\n");
163 if (verbose) { printf_filtered("\n"); }
164 printf_filtered("\t-I Print execution unit statistics\n");
165 if (verbose) { printf_filtered("\n"); }
166 printf_filtered("\t-r <size> Set RAM size in bytes (OEA environments)\n");
167 if (verbose) { printf_filtered("\n"); }
168 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
169 if (verbose) { printf_filtered("\n"); }
170 printf_filtered("\t-o <spec> add device <spec> to the device tree\n");
171 if (verbose) { printf_filtered("\n"); }
172 printf_filtered("\t-h -? -H give more detailed usage\n");
173 if (verbose) { printf_filtered("\n"); }
174 printf_filtered("\n");
175 trace_usage(verbose);
176 device_usage(verbose);
177 if (verbose > 1) {
178 printf_filtered("\n");
179 print_options();
a983c8f0 180 }
eada1efc 181 error("");
a983c8f0
MM
182}
183
eada1efc
MM
184INLINE_PSIM\
185(char **)
186psim_options(device *root,
187 char **argv)
a983c8f0 188{
eada1efc
MM
189 device *current = root;
190 int argp;
191 if (argv == NULL)
192 return NULL;
193 argp = 0;
194 while (argv[argp] != NULL && argv[argp][0] == '-') {
195 char *p = argv[argp] + 1;
196 char *param;
197 while (*p != '\0') {
198 switch (*p) {
199 default:
200 psim_usage(0);
201 error ("");
202 break;
203 case 'e':
204 param = find_arg("Missing <emul> option for -e\n", &argp, argv);
205 device_tree_add_parsed(root, "/openprom/options/os-emul %s", param);
206 break;
207 case 'h':
208 case '?':
209 psim_usage(1);
210 break;
211 case 'H':
212 psim_usage(2);
213 break;
214 case 'i':
215 device_tree_add_parsed(root, "/openprom/trace/print-info 1");
216 break;
217 case 'I':
218 device_tree_add_parsed(root, "/openprom/trace/print-info 2");
219 device_tree_add_parsed(root, "/openprom/options/model-issue %d",
220 MODEL_ISSUE_PROCESS);
221 break;
222 case 'm':
223 param = find_arg("Missing <model> option for -m\n", &argp, argv);
7a543ca4 224 device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
eada1efc
MM
225 break;
226 case 'o':
227 param = find_arg("Missing <device> option for -o\n", &argp, argv);
228 current = device_tree_add_parsed(current, "%s", param);
229 break;
230 case 'r':
231 param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
232 device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx",
233 atol(param));
234 break;
235 case 't':
236 param = find_arg("Missing <trace> option for -t\n", &argp, argv);
237 if (param[0] == '!')
238 device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1);
239 else
240 device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
241 break;
a983c8f0 242 }
eada1efc 243 p += 1;
a983c8f0 244 }
eada1efc 245 argp += 1;
a983c8f0 246 }
eada1efc 247 /* force the trace node to (re)process its options */
30c87b55
MM
248 device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0);
249
eada1efc
MM
250 /* return where the options end */
251 return argv + argp;
a983c8f0
MM
252}
253
254
eada1efc 255/* create the simulator proper from the device tree and executable */
8b3797aa 256
eada1efc
MM
257INLINE_PSIM\
258(psim *)
259psim_create(const char *file_name,
260 device *root)
8b3797aa
MM
261{
262 int cpu_nr;
a983c8f0 263 const char *env;
8b3797aa 264 psim *system;
eada1efc
MM
265 os_emul *os_emulation;
266 int nr_cpus;
8b3797aa 267
eada1efc
MM
268 /* given this partially populated device tree, os_emul_create() uses
269 it and file_name to determine the selected emulation and hence
270 further populate the tree with any other required nodes. */
271
272 os_emulation = os_emul_create(file_name, root);
273 if (os_emulation == NULL)
274 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
8b3797aa 275
a983c8f0 276 /* fill in the missing real number of CPU's */
eada1efc
MM
277 nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
278 if (MAX_NR_PROCESSORS < nr_cpus)
279 error("target and configured number of cpus conflict\n");
a983c8f0
MM
280
281 /* fill in the missing TARGET BYTE ORDER information */
eada1efc
MM
282 current_target_byte_order
283 = (device_find_boolean_property(root, "/options/little-endian?")
284 ? LITTLE_ENDIAN
285 : BIG_ENDIAN);
a983c8f0 286 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
eada1efc 287 error("target and configured byte order conflict\n");
8b3797aa 288
a983c8f0
MM
289 /* fill in the missing HOST BYTE ORDER information */
290 current_host_byte_order = (current_host_byte_order = 1,
291 (*(char*)(&current_host_byte_order)
292 ? LITTLE_ENDIAN
293 : BIG_ENDIAN));
294 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
eada1efc 295 error("host and configured byte order conflict\n");
8b3797aa
MM
296
297 /* fill in the missing OEA/VEA information */
eada1efc 298 env = device_find_string_property(root, "/openprom/options/env");
4dcb0cdd
MM
299 current_environment = ((strcmp(env, "user") == 0
300 || strcmp(env, "uea") == 0)
a983c8f0 301 ? USER_ENVIRONMENT
4dcb0cdd
MM
302 : (strcmp(env, "virtual") == 0
303 || strcmp(env, "vea") == 0)
8b3797aa 304 ? VIRTUAL_ENVIRONMENT
4dcb0cdd
MM
305 : (strcmp(env, "operating") == 0
306 || strcmp(env, "oea") == 0)
a983c8f0
MM
307 ? OPERATING_ENVIRONMENT
308 : 0);
309 if (current_environment == 0)
eada1efc 310 error("unreconized /options env property\n");
a983c8f0 311 if (CURRENT_ENVIRONMENT != current_environment)
eada1efc 312 error("target and configured environment conflict\n");
8b3797aa
MM
313
314 /* fill in the missing ALLIGNMENT information */
eada1efc
MM
315 current_alignment
316 = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
317 ? STRICT_ALIGNMENT
318 : NONSTRICT_ALIGNMENT);
a983c8f0 319 if (CURRENT_ALIGNMENT != current_alignment)
eada1efc 320 error("target and configured alignment conflict\n");
a983c8f0
MM
321
322 /* fill in the missing FLOATING POINT information */
eada1efc
MM
323 current_floating_point
324 = (device_find_boolean_property(root, "/openprom/options/floating-point?")
325 ? HARD_FLOATING_POINT
326 : SOFT_FLOATING_POINT);
a983c8f0 327 if (CURRENT_FLOATING_POINT != current_floating_point)
eada1efc
MM
328 error("target and configured floating-point conflict\n");
329
330 /* sort out the level of detail for issue modeling */
331 current_model_issue
332 = device_find_integer_property(root, "/openprom/options/model-issue");
333 if (CURRENT_MODEL_ISSUE != current_model_issue)
334 error("target and configured model-issue conflict\n");
335
336 /* sort out our model architecture - wrong.
337
338 FIXME: this should be obtaining the required information from the
339 device tree via the "/chosen" property "cpu" which is an instance
340 (ihandle) for the only executing processor. By converting that
341 ihandle into the corresponding cpu's phandle and then querying
342 the "name" property, the cpu type can be determined. Ok? */
343
344 model_set(device_find_string_property(root, "/openprom/options/model"));
345
346 /* create things */
347 system = ZALLOC(psim);
348 system->events = event_queue_create();
30c87b55 349 system->memory = core_from_device(root);
eada1efc
MM
350 system->monitor = mon_create();
351 system->nr_cpus = nr_cpus;
352 system->os_emulation = os_emulation;
353 system->devices = root;
354
355 /* now all the processors attaching to each their per-cpu information */
356 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
357 system->processors[cpu_nr] = cpu_create(system,
358 system->memory,
eada1efc
MM
359 mon_cpu(system->monitor,
360 cpu_nr),
361 system->os_emulation,
362 cpu_nr);
363 }
364
365 /* dump out the contents of the device tree */
366 if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
367 device_tree_traverse(root, device_tree_print_device, NULL, NULL);
368 if (ppc_trace[trace_dump_device_tree])
369 error("");
8b3797aa
MM
370
371 return system;
372}
373
374
375/* allow the simulation to stop/restart abnormaly */
376
30c87b55 377INLINE_PSIM\
eada1efc 378(void)
8b3797aa
MM
379psim_set_halt_and_restart(psim *system,
380 void *halt_jmp_buf,
381 void *restart_jmp_buf)
382{
383 system->path_to_halt = halt_jmp_buf;
384 system->path_to_restart = restart_jmp_buf;
385}
386
30c87b55 387INLINE_PSIM\
eada1efc 388(void)
8b3797aa
MM
389psim_clear_halt_and_restart(psim *system)
390{
391 system->path_to_halt = NULL;
392 system->path_to_restart = NULL;
393}
394
eada1efc
MM
395INLINE_PSIM\
396(void)
8b3797aa
MM
397psim_restart(psim *system,
398 int current_cpu)
399{
400 system->last_cpu = current_cpu;
401 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
402}
403
404
eada1efc
MM
405INLINE_PSIM\
406(void)
8b3797aa
MM
407psim_halt(psim *system,
408 int current_cpu,
8b3797aa
MM
409 stop_reason reason,
410 int signal)
411{
88f1eac4 412 ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
8b3797aa
MM
413 system->last_cpu = current_cpu;
414 system->halt_status.cpu_nr = current_cpu;
415 system->halt_status.reason = reason;
416 system->halt_status.signal = signal;
88f1eac4
MM
417 system->halt_status.program_counter =
418 cpu_get_program_counter(system->processors[current_cpu]);
8b3797aa
MM
419 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
420}
421
30c87b55
MM
422INLINE_PSIM\
423(int)
424psim_last_cpu(psim *system)
425{
426 return system->last_cpu;
427}
428
429INLINE_PSIM\
430(int)
431psim_nr_cpus(psim *system)
432{
433 return system->nr_cpus;
434}
435
eada1efc
MM
436INLINE_PSIM\
437(psim_status)
8b3797aa
MM
438psim_get_status(psim *system)
439{
440 return system->halt_status;
441}
442
443
eada1efc
MM
444INLINE_PSIM\
445(cpu *)
8b3797aa
MM
446psim_cpu(psim *system,
447 int cpu_nr)
448{
449 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
450 return NULL;
451 else
452 return system->processors[cpu_nr];
453}
454
455
eada1efc
MM
456INLINE_PSIM\
457(device *)
a983c8f0
MM
458psim_device(psim *system,
459 const char *path)
8b3797aa 460{
a983c8f0 461 return device_tree_find_device(system->devices, path);
8b3797aa
MM
462}
463
88f1eac4
MM
464INLINE_PSIM\
465(event_queue *)
466psim_event_queue(psim *system)
467{
468 return system->events;
469}
470
8b3797aa 471
8b3797aa 472
eada1efc
MM
473INLINE_PSIM\
474(void)
a983c8f0 475psim_init(psim *system)
8b3797aa 476{
a983c8f0 477 int cpu_nr;
8b3797aa 478
a983c8f0
MM
479 /* scrub the monitor */
480 mon_init(system->monitor, system->nr_cpus);
30c87b55
MM
481
482 /* trash any pending events */
eada1efc 483 event_queue_init(system->events);
8b3797aa 484
a983c8f0
MM
485 /* scrub all the cpus */
486 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
487 cpu_init(system->processors[cpu_nr]);
8b3797aa 488
eada1efc 489 /* init all the devices (which updates the cpus) */
a983c8f0 490 device_tree_init(system->devices, system);
8b3797aa 491
30c87b55
MM
492 /* and the emulation (which needs an initialized device tree) */
493 os_emul_init(system->os_emulation, system->nr_cpus);
494
eada1efc
MM
495 /* now sync each cpu against the initialized state of its registers */
496 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
497 cpu_synchronize_context(system->processors[cpu_nr]);
498 cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
499 }
500
a983c8f0 501 /* force loop to restart */
30c87b55 502 system->last_cpu = -1; /* when incremented will become 0 - first CPU */
8b3797aa
MM
503}
504
eada1efc
MM
505INLINE_PSIM\
506(void)
8b3797aa
MM
507psim_stack(psim *system,
508 char **argv,
509 char **envp)
510{
a983c8f0
MM
511 /* pass the stack device the argv/envp and let it work out what to
512 do with it */
eada1efc
MM
513 device *stack_device = device_tree_find_device(system->devices,
514 "/openprom/init/stack");
515 if (stack_device != (device*)0) {
516 unsigned_word stack_pointer;
517 psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
518 device_ioctl(stack_device,
eada1efc
MM
519 NULL, /*cpu*/
520 0, /*cia*/
521 stack_pointer,
522 argv,
523 envp);
524 }
8b3797aa
MM
525}
526
527
528
8b3797aa
MM
529/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
530 thing */
531
eada1efc
MM
532INLINE_PSIM\
533(void)
8b3797aa
MM
534psim_step(psim *system)
535{
536 volatile int keep_running = 0;
30c87b55
MM
537 idecode_run_until_stop(system, &keep_running,
538 system->events, system->processors, system->nr_cpus);
8b3797aa
MM
539}
540
eada1efc
MM
541INLINE_PSIM\
542(void)
8b3797aa
MM
543psim_run(psim *system)
544{
30c87b55
MM
545 idecode_run(system,
546 system->events, system->processors, system->nr_cpus);
8b3797aa
MM
547}
548
eada1efc
MM
549INLINE_PSIM\
550(void)
8b3797aa
MM
551psim_run_until_stop(psim *system,
552 volatile int *keep_running)
553{
30c87b55
MM
554 idecode_run_until_stop(system, keep_running,
555 system->events, system->processors, system->nr_cpus);
8b3797aa
MM
556}
557
558
559
560/* storage manipulation functions */
561
eada1efc
MM
562INLINE_PSIM\
563(void)
8b3797aa
MM
564psim_read_register(psim *system,
565 int which_cpu,
566 void *buf,
567 const char reg[],
568 transfer_mode mode)
569{
570 register_descriptions description;
7a543ca4 571 char cooked_buf[sizeof(unsigned_8)];
8b3797aa
MM
572 cpu *processor;
573
574 /* find our processor */
a983c8f0 575 if (which_cpu == MAX_NR_PROCESSORS)
8b3797aa 576 which_cpu = system->last_cpu;
a983c8f0
MM
577 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
578 error("psim_read_register() - invalid processor %d\n", which_cpu);
8b3797aa
MM
579 processor = system->processors[which_cpu];
580
581 /* find the register description */
582 description = register_description(reg);
583 if (description.type == reg_invalid)
584 error("psim_read_register() invalid register name `%s'\n", reg);
585
586 /* get the cooked value */
587 switch (description.type) {
588
589 case reg_gpr:
590 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
591 break;
592
593 case reg_spr:
594 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
595 break;
596
597 case reg_sr:
598 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
599 break;
600
601 case reg_fpr:
602 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
603 break;
604
605 case reg_pc:
606 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
607 break;
608
609 case reg_cr:
610 *(creg*)cooked_buf = cpu_registers(processor)->cr;
611 break;
612
613 case reg_msr:
614 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
615 break;
616
30c87b55
MM
617 case reg_insns:
618 *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
619 which_cpu);
620 break;
621
622 case reg_stalls:
623 if (cpu_model(processor) == NULL)
624 error("$stalls only valid if processor unit model enabled (-I)\n");
625 *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
626 break;
627
628 case reg_cycles:
629 if (cpu_model(processor) == NULL)
630 error("$cycles only valid if processor unit model enabled (-I)\n");
631 *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
632 break;
633
8b3797aa 634 default:
45525d8d
MM
635 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
636 (unsigned long)processor, (unsigned long)buf, reg,
8b3797aa
MM
637 "read of this register unimplemented");
638 break;
639
640 }
641
642 /* the PSIM internal values are in host order. To fetch raw data,
643 they need to be converted into target order and then returned */
644 if (mode == raw_transfer) {
645 /* FIXME - assumes that all registers are simple integers */
646 switch (description.size) {
647 case 1:
648 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
649 break;
650 case 2:
651 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
652 break;
653 case 4:
654 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
655 break;
656 case 8:
657 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
658 break;
659 }
660 }
661 else {
45525d8d 662 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
8b3797aa
MM
663 }
664
665}
666
667
668
eada1efc
MM
669INLINE_PSIM\
670(void)
8b3797aa
MM
671psim_write_register(psim *system,
672 int which_cpu,
673 const void *buf,
674 const char reg[],
675 transfer_mode mode)
676{
677 cpu *processor;
678 register_descriptions description;
7a543ca4 679 char cooked_buf[sizeof(unsigned_8)];
8b3797aa
MM
680
681 /* find our processor */
a983c8f0
MM
682 if (which_cpu == MAX_NR_PROCESSORS)
683 which_cpu = system->last_cpu;
8b3797aa
MM
684 if (which_cpu == -1) {
685 int i;
686 for (i = 0; i < system->nr_cpus; i++)
687 psim_write_register(system, i, buf, reg, mode);
688 return;
689 }
8b3797aa
MM
690 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
691 error("psim_read_register() - invalid processor %d\n", which_cpu);
692 }
693
694 processor = system->processors[which_cpu];
695
696 /* find the description of the register */
697 description = register_description(reg);
698 if (description.type == reg_invalid)
699 error("psim_write_register() invalid register name %s\n", reg);
700
701 /* If the data is comming in raw (target order), need to cook it
702 into host order before putting it into PSIM's internal structures */
703 if (mode == raw_transfer) {
704 switch (description.size) {
705 case 1:
706 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
707 break;
708 case 2:
709 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
710 break;
711 case 4:
712 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
713 break;
714 case 8:
715 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
716 break;
717 }
718 }
719 else {
45525d8d 720 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
8b3797aa
MM
721 }
722
723 /* put the cooked value into the register */
724 switch (description.type) {
725
726 case reg_gpr:
727 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
728 break;
729
730 case reg_fpr:
731 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
732 break;
733
734 case reg_pc:
735 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
736 break;
737
738 case reg_spr:
739 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
740 break;
741
742 case reg_sr:
743 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
744 break;
745
746 case reg_cr:
747 cpu_registers(processor)->cr = *(creg*)cooked_buf;
748 break;
749
750 case reg_msr:
751 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
752 break;
753
754 default:
45525d8d
MM
755 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
756 (unsigned long)processor, (unsigned long)cooked_buf, reg,
8b3797aa
MM
757 "read of this register unimplemented");
758 break;
759
760 }
761
762}
763
764
765
eada1efc
MM
766INLINE_PSIM\
767(unsigned)
8b3797aa
MM
768psim_read_memory(psim *system,
769 int which_cpu,
770 void *buffer,
771 unsigned_word vaddr,
a983c8f0 772 unsigned nr_bytes)
8b3797aa
MM
773{
774 cpu *processor;
a983c8f0 775 if (which_cpu == MAX_NR_PROCESSORS)
8b3797aa 776 which_cpu = system->last_cpu;
a983c8f0
MM
777 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
778 error("psim_read_memory() invalid cpu\n");
8b3797aa
MM
779 processor = system->processors[which_cpu];
780 return vm_data_map_read_buffer(cpu_data_map(processor),
a983c8f0 781 buffer, vaddr, nr_bytes);
8b3797aa
MM
782}
783
784
eada1efc
MM
785INLINE_PSIM\
786(unsigned)
8b3797aa
MM
787psim_write_memory(psim *system,
788 int which_cpu,
789 const void *buffer,
790 unsigned_word vaddr,
a983c8f0 791 unsigned nr_bytes,
8b3797aa
MM
792 int violate_read_only_section)
793{
794 cpu *processor;
a983c8f0 795 if (which_cpu == MAX_NR_PROCESSORS)
8b3797aa 796 which_cpu = system->last_cpu;
a983c8f0
MM
797 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
798 error("psim_read_memory() invalid cpu\n");
8b3797aa
MM
799 processor = system->processors[which_cpu];
800 return vm_data_map_write_buffer(cpu_data_map(processor),
a983c8f0 801 buffer, vaddr, nr_bytes, 1);
8b3797aa
MM
802}
803
804
eada1efc
MM
805INLINE_PSIM\
806(void)
a983c8f0
MM
807psim_print_info(psim *system,
808 int verbose)
83d96c6e 809{
73c4941b 810 mon_print_info(system, system->monitor, verbose);
83d96c6e
MM
811}
812
a983c8f0 813
eada1efc
MM
814/* Merge a device tree and a device file. */
815
816INLINE_PSIM\
817(void)
818psim_merge_device_file(device *root,
819 const char *file_name)
820{
821 FILE *description = fopen(file_name, "r");
822 int line_nr = 0;
823 char device_path[1000];
824 device *current = root;
825 while (fgets(device_path, sizeof(device_path), description)) {
826 /* check all of line was read */
827 if (strchr(device_path, '\n') == NULL) {
828 fclose(description);
829 error("create_filed_device_tree() line %d to long: %s\n",
830 line_nr, device_path);
831 }
832 line_nr++;
833 /* parse this line */
834 current = device_tree_add_parsed(current, "%s", device_path);
835 }
836 fclose(description);
837}
838
839
8b3797aa 840#endif /* _PSIM_C_ */
This page took 0.114855 seconds and 4 git commands to generate.