New simulator changes from Andrew
[external/binutils.git] / sim / ppc / psim.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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
25 #include "cpu.h" /* includes psim.h */
26 #include "idecode.h"
27 #include "options.h"
28
29
30 #include <stdio.h>
31 #include <ctype.h>
32
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36
37 #include <setjmp.h>
38
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
47
48 #include "bfd.h"
49
50
51 /* system structure, actual size of processor array determined at
52    runtime */
53
54 struct _psim {
55   event_queue *events;
56   device *devices;
57   mon *monitor;
58   os_emul *os_emulation;
59   core *memory;
60
61   /* escape routine for inner functions */
62   void *path_to_halt;
63   void *path_to_restart;
64
65   /* status from last halt */
66   psim_status halt_status;
67
68   /* the processors proper */
69   int nr_cpus;
70   int last_cpu; /* CPU that last (tried to) execute an instruction */
71   cpu *processors[MAX_NR_PROCESSORS];
72 };
73
74
75 int current_target_byte_order;
76 int current_host_byte_order;
77 int current_environment;
78 int current_alignment;
79 int current_floating_point;
80 int current_model_issue = MODEL_ISSUE_IGNORE;
81 model_enum current_model = WITH_DEFAULT_MODEL;
82
83
84 /* create the device tree */
85
86 INLINE_PSIM\
87 (device *)
88 psim_tree(void)
89 {
90   device *root = device_tree_add_parsed(NULL, "core");
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;
101 }
102
103 STATIC_INLINE_PSIM\
104 (char *)
105 find_arg(char *err_msg,
106          int *ptr_to_argp,
107          char **argv)
108 {
109   *ptr_to_argp += 1;
110   if (argv[*ptr_to_argp] == NULL)
111     error(err_msg);
112   return argv[*ptr_to_argp];
113 }
114
115 INLINE_PSIM\
116 (void)
117 psim_usage(int verbose)
118 {
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");
158   printf_filtered("\t              solaris - UEA + Solaris system calls\n");
159   printf_filtered("\t              linux - UEA + Linux system calls\n");
160   printf_filtered("\t              chirp - OEA + a few OpenBoot calls\n");
161   printf_filtered("\n"); }
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();
180   }
181   error("");
182 }
183
184 INLINE_PSIM\
185 (char **)
186 psim_options(device *root,
187              char **argv)
188 {
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);
224         device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
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;
242       }
243       p += 1;
244     }
245     argp += 1;
246   }
247   /* force the trace node to (re)process its options */
248   device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0);
249
250   /* return where the options end */
251   return argv + argp;
252 }
253
254
255 /* create the simulator proper from the device tree and executable */
256
257 INLINE_PSIM\
258 (psim *)
259 psim_create(const char *file_name,
260             device *root)
261 {
262   int cpu_nr;
263   const char *env;
264   psim *system;
265   os_emul *os_emulation;
266   int nr_cpus;
267
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);
275
276   /* fill in the missing real number of CPU's */
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");
280
281   /* fill in the missing TARGET BYTE ORDER information */
282   current_target_byte_order
283     = (device_find_boolean_property(root, "/options/little-endian?")
284        ? LITTLE_ENDIAN
285        : BIG_ENDIAN);
286   if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
287     error("target and configured byte order conflict\n");
288
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)
295     error("host and configured byte order conflict\n");
296
297   /* fill in the missing OEA/VEA information */
298   env = device_find_string_property(root, "/openprom/options/env");
299   current_environment = ((strcmp(env, "user") == 0
300                           || strcmp(env, "uea") == 0)
301                          ? USER_ENVIRONMENT
302                          : (strcmp(env, "virtual") == 0
303                             || strcmp(env, "vea") == 0)
304                          ? VIRTUAL_ENVIRONMENT
305                          : (strcmp(env, "operating") == 0
306                             || strcmp(env, "oea") == 0)
307                          ? OPERATING_ENVIRONMENT
308                          : 0);
309   if (current_environment == 0)
310     error("unreconized /options env property\n");
311   if (CURRENT_ENVIRONMENT != current_environment)
312     error("target and configured environment conflict\n");
313
314   /* fill in the missing ALLIGNMENT information */
315   current_alignment
316     = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
317        ? STRICT_ALIGNMENT
318        : NONSTRICT_ALIGNMENT);
319   if (CURRENT_ALIGNMENT != current_alignment)
320     error("target and configured alignment conflict\n");
321
322   /* fill in the missing FLOATING POINT information */
323   current_floating_point
324     = (device_find_boolean_property(root, "/openprom/options/floating-point?")
325        ? HARD_FLOATING_POINT
326        : SOFT_FLOATING_POINT);
327   if (CURRENT_FLOATING_POINT != current_floating_point)
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();
349   system->memory = core_from_device(root);
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,
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("");
370
371   return system;
372 }
373
374
375 /* allow the simulation to stop/restart abnormaly */
376
377 INLINE_PSIM\
378 (void)
379 psim_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
387 INLINE_PSIM\
388 (void)
389 psim_clear_halt_and_restart(psim *system)
390 {
391   system->path_to_halt = NULL;
392   system->path_to_restart = NULL;
393 }
394
395 INLINE_PSIM\
396 (void)
397 psim_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
405 INLINE_PSIM\
406 (void)
407 psim_halt(psim *system,
408           int current_cpu,
409           stop_reason reason,
410           int signal)
411 {
412   ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
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;
417   system->halt_status.program_counter =
418     cpu_get_program_counter(system->processors[current_cpu]);
419   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
420 }
421
422 INLINE_PSIM\
423 (int)
424 psim_last_cpu(psim *system)
425 {
426   return system->last_cpu;
427 }
428
429 INLINE_PSIM\
430 (int)
431 psim_nr_cpus(psim *system)
432 {
433   return system->nr_cpus;
434 }
435
436 INLINE_PSIM\
437 (psim_status)
438 psim_get_status(psim *system)
439 {
440   return system->halt_status;
441 }
442
443
444 INLINE_PSIM\
445 (cpu *)
446 psim_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
456 INLINE_PSIM\
457 (device *)
458 psim_device(psim *system,
459             const char *path)
460 {
461   return device_tree_find_device(system->devices, path);
462 }
463
464 INLINE_PSIM\
465 (event_queue *)
466 psim_event_queue(psim *system)
467 {
468   return system->events;
469 }
470
471
472
473 INLINE_PSIM\
474 (void)
475 psim_init(psim *system)
476 {
477   int cpu_nr;
478
479   /* scrub the monitor */
480   mon_init(system->monitor, system->nr_cpus);
481
482   /* trash any pending events */
483   event_queue_init(system->events);
484
485   /* scrub all the cpus */
486   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
487     cpu_init(system->processors[cpu_nr]);
488
489   /* init all the devices (which updates the cpus) */
490   device_tree_init(system->devices, system);
491
492   /* and the emulation (which needs an initialized device tree) */
493   os_emul_init(system->os_emulation, system->nr_cpus);
494
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
501   /* force loop to restart */
502   system->last_cpu = -1; /* when incremented will become 0 - first CPU */
503 }
504
505 INLINE_PSIM\
506 (void)
507 psim_stack(psim *system,
508            char **argv,
509            char **envp)
510 {
511   /* pass the stack device the argv/envp and let it work out what to
512      do with it */
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,
519                  NULL, /*cpu*/
520                  0, /*cia*/
521                  stack_pointer,
522                  argv,
523                  envp);
524   }
525 }
526
527
528
529 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
530    thing */
531
532 INLINE_PSIM\
533 (void)
534 psim_step(psim *system)
535 {
536   volatile int keep_running = 0;
537   idecode_run_until_stop(system, &keep_running,
538                          system->events, system->processors, system->nr_cpus);
539 }
540
541 INLINE_PSIM\
542 (void)
543 psim_run(psim *system)
544 {
545   idecode_run(system,
546               system->events, system->processors, system->nr_cpus);
547 }
548
549 INLINE_PSIM\
550 (void)
551 psim_run_until_stop(psim *system,
552                     volatile int *keep_running)
553 {
554   idecode_run_until_stop(system, keep_running,
555                          system->events, system->processors, system->nr_cpus);
556 }
557
558
559
560 /* storage manipulation functions */
561
562 INLINE_PSIM\
563 (void)
564 psim_read_register(psim *system,
565                    int which_cpu,
566                    void *buf,
567                    const char reg[],
568                    transfer_mode mode)
569 {
570   register_descriptions description;
571   char cooked_buf[sizeof(unsigned_8)];
572   cpu *processor;
573
574   /* find our processor */
575   if (which_cpu == MAX_NR_PROCESSORS)
576     which_cpu = system->last_cpu;
577   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
578     error("psim_read_register() - invalid processor %d\n", which_cpu);
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
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
634   default:
635     printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
636                     (unsigned long)processor, (unsigned long)buf, reg,
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 {
662     memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
663   }
664
665 }
666
667
668
669 INLINE_PSIM\
670 (void)
671 psim_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;
679   char cooked_buf[sizeof(unsigned_8)];
680
681   /* find our processor */
682   if (which_cpu == MAX_NR_PROCESSORS)
683     which_cpu = system->last_cpu;
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   }
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 {
720     memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
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:
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,
757                     "read of this register unimplemented");
758     break;
759
760   }
761
762 }
763
764
765
766 INLINE_PSIM\
767 (unsigned)
768 psim_read_memory(psim *system,
769                  int which_cpu,
770                  void *buffer,
771                  unsigned_word vaddr,
772                  unsigned nr_bytes)
773 {
774   cpu *processor;
775   if (which_cpu == MAX_NR_PROCESSORS)
776     which_cpu = system->last_cpu;
777   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
778     error("psim_read_memory() invalid cpu\n");
779   processor = system->processors[which_cpu];
780   return vm_data_map_read_buffer(cpu_data_map(processor),
781                                  buffer, vaddr, nr_bytes);
782 }
783
784
785 INLINE_PSIM\
786 (unsigned)
787 psim_write_memory(psim *system,
788                   int which_cpu,
789                   const void *buffer,
790                   unsigned_word vaddr,
791                   unsigned nr_bytes,
792                   int violate_read_only_section)
793 {
794   cpu *processor;
795   if (which_cpu == MAX_NR_PROCESSORS)
796     which_cpu = system->last_cpu;
797   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
798     error("psim_read_memory() invalid cpu\n");
799   processor = system->processors[which_cpu];
800   return vm_data_map_write_buffer(cpu_data_map(processor),
801                                   buffer, vaddr, nr_bytes, 1);
802 }
803
804
805 INLINE_PSIM\
806 (void)
807 psim_print_info(psim *system,
808                 int verbose)
809 {
810   mon_print_info(system, system->monitor, verbose);
811 }
812
813
814 /* Merge a device tree and a device file. */
815
816 INLINE_PSIM\
817 (void)
818 psim_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
840 #endif /* _PSIM_C_ */