Andrew's latest changes & print all instruction counts if -I
[external/binutils.git] / sim / ppc / psim.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1995, 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 <stdio.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28
29 #include "config.h"
30 #include "ppc-config.h"
31 #include "inline.h"
32
33 #ifndef STATIC_INLINE_PSIM
34 #define STATIC_INLINE_PSIM STATIC_INLINE
35 #endif
36
37 #include <string.h>
38 #include <setjmp.h>
39
40 #include "cpu.h" /* includes psim.h */
41 #include "idecode.h"
42
43 #include "bfd.h"
44
45
46 #include "inline.c"
47
48 /* Any starting address less than this is assumed to be an OEA program
49    rather than VEA.  */
50 #ifndef OEA_START_ADDRESS
51 #define OEA_START_ADDRESS 4096
52 #endif
53
54 /* Any starting address greater than this is assumed to be an OpenBoot
55    rather than VEA */
56 #ifndef OPENBOOT_START_ADDRESS
57 #define OPENBOOT_START_ADDRESS 0x80000000
58 #endif
59
60 #ifndef OEA_MEMORY_SIZE
61 #define OEA_MEMORY_SIZE 0x100000
62 #endif
63
64
65 /* system structure, actual size of processor array determined at
66    runtime */
67
68 struct _psim {
69   event_queue *events;
70   device_tree *devices;
71   mon *monitor;
72   core *memory;
73   /* escape routine for inner functions */
74   void *path_to_halt;
75   void *path_to_restart;
76   /* status from last halt */
77   psim_status halt_status;
78   /* the processes proper */
79   int nr_cpus;
80   int last_cpu; /* CPU that last (tried to) execute an instruction */
81   cpu *processors[MAX_NR_PROCESSORS];
82 };
83
84
85 int current_target_byte_order;
86 int current_host_byte_order;
87 int current_environment;
88 int current_alignment;
89 int current_floating_point;
90
91
92 /* create a device tree from the image */
93
94
95
96 /* Raw hardware tree:
97
98    A small default set of devices are configured.  Each section of the
99    image is loaded directly into physical memory. */
100
101 STATIC_INLINE_PSIM void
102 create_hardware_device_tree(bfd *image,
103                             device_tree *root)
104 {
105   char *name;
106   const memory_size = OEA_MEMORY_SIZE;
107
108   /* options */
109   device_tree_add_passthrough(root, "/options");
110   device_tree_add_integer(root, "/options/smp",
111                           MAX_NR_PROCESSORS);
112   device_tree_add_boolean(root, "/options/little-endian?",
113                           !image->xvec->byteorder_big_p);
114   device_tree_add_string(root, "/options/environment-architecture",
115                          "operating");
116   device_tree_add_boolean(root, "/options/strict-alignment?",
117                           (WITH_ALIGNMENT == STRICT_ALIGNMENT
118                            || !image->xvec->byteorder_big_p));
119   device_tree_add_boolean(root, "/options/floating-point?",
120                           WITH_FLOATING_POINT);
121
122   /* hardware */
123   name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec);
124   device_tree_add_found_device(root, name);
125   zfree(name);
126   device_tree_add_found_device(root, "/iobus@0x400000");
127   device_tree_add_found_device(root, "/iobus/console@0x000000,16");
128   device_tree_add_found_device(root, "/iobus/halt@0x100000,4");
129   device_tree_add_found_device(root, "/iobus/icu@0x200000,4");
130
131   /* initialization */
132   device_tree_add_passthrough(root, "/init");
133   device_tree_add_found_device(root, "/init/register@pc,0x0");
134   name = printd_c_uw("/init/register", "sp", memory_size);
135   device_tree_add_found_device(root, name);
136   zfree(name);
137   name = printd_c_uw("/init/register", "msr",
138                      (image->xvec->byteorder_big_p
139                       ? 0
140                       : msr_little_endian_mode));
141   device_tree_add_found_device(root, name);
142   zfree(name);
143   /* AJC puts the PC at zero and wants a stack while MM puts it above
144      zero and doesn't. Really there should be no stack *but* this
145      makes testing easier */
146   device_tree_add_found_device(root,
147                                (bfd_get_start_address(image) == 0
148                                 ? "/init/stack@elf"
149                                 : "/init/stack@none"));
150   name = printd_c("/init/load-binary", bfd_get_filename(image));
151   device_tree_add_found_device(root, name);
152   zfree(name);
153 }
154
155
156 /* Openboot model (under development):
157
158    An extension of the hardware model.  The image is read into memory
159    as a single block.  Sections of the image are then mapped as
160    required using a HTAB. */
161
162 STATIC_INLINE_PSIM void
163 create_openboot_device_tree(bfd *image,
164                             device_tree *root)
165 {
166   create_hardware_device_tree(image, root);
167 }
168
169
170 /* User mode model:
171
172    Image sections loaded into virtual addresses as specified.  A
173    (large) stack is reserved (but only allocated as needed). System
174    calls that include suport for heap growth are attached. */
175
176 STATIC_INLINE_PSIM void
177 create_vea_device_tree(bfd *image,
178                        device_tree *root)
179 {
180   unsigned_word top_of_stack;
181   unsigned stack_size;
182   int elf_binary;
183   char *name;
184
185   /* establish a few defaults */
186   if (image->xvec->flavour == bfd_target_elf_flavour) {
187     elf_binary = 1;
188     top_of_stack = 0xe0000000;
189     stack_size =   0x00100000;
190   }
191   else {
192     elf_binary = 0;
193     top_of_stack = 0x20000000;
194     stack_size =   0x00100000;
195   }
196
197   /* options */
198   device_tree_add_passthrough(root, "/options");
199   device_tree_add_integer(root, "/options/smp", 1); /* always */
200   device_tree_add_boolean(root, "/options/little-endian?",
201                           !image->xvec->byteorder_big_p);
202   device_tree_add_string(root, "/options/environment-architecture",
203                          (WITH_ENVIRONMENT == USER_ENVIRONMENT
204                           ? "user" : "virtual"));
205   device_tree_add_boolean(root, "/options/strict-alignment?",
206                           (WITH_ALIGNMENT == STRICT_ALIGNMENT
207                             || !image->xvec->byteorder_big_p));
208   device_tree_add_boolean(root, "/options/floating-point?",
209                           WITH_FLOATING_POINT);
210
211   /* virtual memory - handles growth of stack/heap */
212   name = printd_uw_u("/vm", top_of_stack - stack_size, stack_size);
213   device_tree_add_found_device(root, name);
214   zfree(name);
215   name = printd_c("/vm/map-binary", bfd_get_filename(image));
216   device_tree_add_found_device(root, name);
217   zfree(name);
218
219   /* finish the init */
220   device_tree_add_passthrough(root, "/init");
221   name = printd_c_uw("/init/register", "pc", bfd_get_start_address(image));
222   device_tree_add_found_device(root, name); /*pc*/
223   zfree(name);
224   name = printd_c_uw("/init/register", "sp", top_of_stack);
225   device_tree_add_found_device(root, name);
226   zfree(name);
227   name = printd_c_uw("/init/register", "msr",
228                      (image->xvec->byteorder_big_p
229                       ? 0
230                       : msr_little_endian_mode));
231   device_tree_add_found_device(root, name);
232   zfree(name);
233   device_tree_add_found_device(root, (elf_binary
234                                       ? "/init/stack@elf"
235                                       : "/init/stack@xcoff"));
236 }
237
238
239 /* File device:
240
241    The file contains lines that specify the describe the device tree
242    to be created, read them in and load them into the tree */
243
244 STATIC_INLINE_PSIM void
245 create_filed_device_tree(const char *file_name,
246                          device_tree *root)
247 {
248   FILE *description = fopen(file_name, "r");
249   int line_nr = 0;
250   char device_path[1000];
251   while (fgets(device_path, sizeof(device_path), description)) {
252     /* check all of line was read */
253     {
254       char *end = strchr(device_path, '\n');
255       if (end == NULL) {
256         fclose(description);
257         error("create_filed_device_tree() line %d to long: %s\n",
258               line_nr, device_path);
259       }
260       line_nr++;
261       *end = '\0';
262     }
263     /* check for leading comment */
264     if (device_path[0] != '/')
265       continue;
266     /* enter it in varying ways */
267     if (strchr(device_path, '@') != NULL) {
268       device_tree_add_found_device(root, device_path);
269     }
270     else {
271       char *space = strchr(device_path, ' ');
272       if (space == NULL) {
273         /* intermediate node */
274         device_tree_add_passthrough(root, device_path);
275       }
276       else if (space[-1] == '?') {
277         /* boolean */
278         *space = '\0';
279         device_tree_add_boolean(root, device_path, space[1] != '0');
280       }
281       else if (isdigit(space[1])) {
282         /* integer */
283         *space = '\0';
284         device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0));
285       }
286       else if (space[1] == '"') {
287         /* quoted string */
288         char *end = strchr(space+2, '\0');
289         if (end[-1] == '"')
290           end[-1] = '\0';
291         *space = '\0';
292         device_tree_add_string(root, device_path, space + 2);
293       }
294       else {
295         /* any thing else */
296         space = '\0';
297         device_tree_add_string(root, device_path, space + 1);
298       }
299     }
300   }
301   fclose(description);
302 }
303
304
305 /* Given the file containing the `image', create a device tree that
306    defines the machine to be modeled */
307
308 STATIC_INLINE_PSIM device_tree *
309 create_device_tree(const char *file_name,
310                    core *memory)
311 {
312   bfd *image;
313   const device *core_device = core_device_create(memory);
314   device_tree *root = device_tree_add_device(NULL, "/", core_device);
315
316   bfd_init(); /* could be redundant but ... */
317
318   /* open the file */
319   image = bfd_openr(file_name, NULL);
320   if (image == NULL) {
321     bfd_perror("open failed:");
322     error("nothing loaded\n");
323   }
324
325   /* check it is valid */
326   if (!bfd_check_format(image, bfd_object)) {
327     printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
328     printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name);
329     bfd_close(image);
330     image = NULL;
331   }
332
333   /* depending on what was found about the file, load it */
334   if (image != NULL) {
335     if (bfd_get_start_address(image) < OEA_START_ADDRESS) {
336       TRACE(trace_device_tree, ("create_device_tree() - hardware image\n"));
337       create_hardware_device_tree(image, root);
338     }
339     else if (bfd_get_start_address(image) < OPENBOOT_START_ADDRESS) {
340       TRACE(trace_device_tree, ("create_device_tree() - vea image\n"));
341       create_vea_device_tree(image, root);
342     }
343     else {
344       TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n"));
345       create_openboot_device_tree(image, root);
346     }
347     bfd_close(image);
348   }
349   else {
350     TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
351     create_filed_device_tree(file_name, root);
352   }
353
354   return root;
355 }
356
357
358
359 INLINE_PSIM psim *
360 psim_create(const char *file_name)
361 {
362   int cpu_nr;
363   const char *env;
364   psim *system;
365
366   /* create things */
367   system = ZALLOC(psim);
368   system->events = event_queue_create();
369   system->memory = core_create();
370   system->monitor = mon_create();
371   system->devices = create_device_tree(file_name, system->memory);
372   for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
373     system->processors[cpu_nr] = cpu_create(system,
374                                             system->memory,
375                                             system->events,
376                                             mon_cpu(system->monitor,
377                                                     cpu_nr),
378                                             cpu_nr);
379   }
380
381   /* fill in the missing real number of CPU's */
382   system->nr_cpus = device_tree_find_integer(system->devices,
383                                              "/options/smp");
384
385   /* fill in the missing TARGET BYTE ORDER information */
386   current_target_byte_order = (device_tree_find_boolean(system->devices,
387                                                         "/options/little-endian?")
388                                ? LITTLE_ENDIAN
389                                : BIG_ENDIAN);
390   if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
391     error("target byte order conflict\n");
392
393   /* fill in the missing HOST BYTE ORDER information */
394   current_host_byte_order = (current_host_byte_order = 1,
395                              (*(char*)(&current_host_byte_order)
396                               ? LITTLE_ENDIAN
397                               : BIG_ENDIAN));
398   if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
399     error("host byte order conflict\n");
400
401   /* fill in the missing OEA/VEA information */
402   env = device_tree_find_string(system->devices,
403                                 "/options/environment-architecture");
404   current_environment = (strcmp(env, "user") == 0
405                          ? USER_ENVIRONMENT
406                          : strcmp(env, "virtual") == 0
407                          ? VIRTUAL_ENVIRONMENT
408                          : strcmp(env, "operating") == 0
409                          ? OPERATING_ENVIRONMENT
410                          : 0);
411   if (current_environment == 0)
412     error("unreconized /options/environment-architecture\n");
413   if (CURRENT_ENVIRONMENT != current_environment)
414     error("target environment conflict\n");
415
416   /* fill in the missing ALLIGNMENT information */
417   current_alignment = (device_tree_find_boolean(system->devices,
418                                                 "/options/strict-alignment?")
419                        ? STRICT_ALIGNMENT
420                        : NONSTRICT_ALIGNMENT);
421   if (CURRENT_ALIGNMENT != current_alignment)
422     error("target alignment conflict\n");
423
424   /* fill in the missing FLOATING POINT information */
425   current_floating_point = (device_tree_find_boolean(system->devices,
426                                                      "/options/floating-point?")
427                             ? HARD_FLOATING_POINT
428                             : SOFT_FLOATING_POINT);
429   if (CURRENT_FLOATING_POINT != current_floating_point)
430     error("target floating-point conflict\n");
431
432   return system;
433 }
434
435
436 /* allow the simulation to stop/restart abnormaly */
437
438 STATIC_INLINE_PSIM void
439 psim_set_halt_and_restart(psim *system,
440                           void *halt_jmp_buf,
441                           void *restart_jmp_buf)
442 {
443   system->path_to_halt = halt_jmp_buf;
444   system->path_to_restart = restart_jmp_buf;
445 }
446
447 STATIC_INLINE_PSIM void
448 psim_clear_halt_and_restart(psim *system)
449 {
450   system->path_to_halt = NULL;
451   system->path_to_restart = NULL;
452 }
453
454 INLINE_PSIM void
455 psim_restart(psim *system,
456              int current_cpu)
457 {
458   system->last_cpu = current_cpu;
459   longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
460 }
461
462
463 INLINE_PSIM void
464 psim_halt(psim *system,
465           int current_cpu,
466           unsigned_word cia,
467           stop_reason reason,
468           int signal)
469 {
470   system->last_cpu = current_cpu;
471   system->halt_status.cpu_nr = current_cpu;
472   system->halt_status.reason = reason;
473   system->halt_status.signal = signal;
474   system->halt_status.program_counter = cia;
475   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
476 }
477
478 INLINE_PSIM psim_status
479 psim_get_status(psim *system)
480 {
481   return system->halt_status;
482 }
483
484
485 cpu *
486 psim_cpu(psim *system,
487          int cpu_nr)
488 {
489   if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
490     return NULL;
491   else
492     return system->processors[cpu_nr];
493 }
494
495
496 const device *
497 psim_device(psim *system,
498             const char *path)
499 {
500   return device_tree_find_device(system->devices, path);
501 }
502
503
504
505 INLINE_PSIM void
506 psim_init(psim *system)
507 {
508   int cpu_nr;
509
510   /* scrub the monitor */
511   mon_init(system->monitor, system->nr_cpus);
512
513   /* scrub all the cpus */
514   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
515     cpu_init(system->processors[cpu_nr]);
516
517   /* init all the devices */
518   device_tree_init(system->devices, system);
519
520   /* force loop to restart */
521   system->last_cpu = system->nr_cpus - 1;
522 }
523
524 INLINE_PSIM void
525 psim_stack(psim *system,
526            char **argv,
527            char **envp)
528 {
529   /* pass the stack device the argv/envp and let it work out what to
530      do with it */
531   const device *stack_device = device_tree_find_device(system->devices,
532                                                        "/init/stack");
533   unsigned_word stack_pointer;
534   psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
535   stack_device->callback->ioctl(stack_device,
536                                 system,
537                                 NULL, /*cpu*/
538                                 0, /*cia*/
539                                 stack_pointer,
540                                 argv,
541                                 envp);
542 }
543
544
545
546 /* EXECUTE REAL CODE: 
547
548    Unfortunatly, there are multiple cases to consider vis:
549
550         <icache> X <smp> X <events> X <keep-running-flag> X ...
551
552    Consequently this function is written in multiple different ways */
553
554 STATIC_INLINE_PSIM void
555 run_until_stop(psim *system,
556                volatile int *keep_running)
557 {
558   jmp_buf halt;
559   jmp_buf restart;
560   int cpu_nr;
561 #if WITH_IDECODE_CACHE_SIZE
562   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
563     cpu_flush_icache(system->processors[cpu_nr]);
564 #endif
565   psim_set_halt_and_restart(system, &halt, &restart);
566
567 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
568
569   /* CASE 1: No instruction cache and no SMP.
570
571      In this case, we can take advantage of the fact that the current
572      instruction address does not need to be returned to the cpu
573      object after every execution of an instruction.  Instead it only
574      needs to be saved when either A. the main loop exits or B. a
575      cpu-{halt,restart} call forces the loop to be re-entered.  The
576      later functions always save the current cpu instruction
577      address. */
578
579   if (!setjmp(halt)) {
580     do {
581       if (!setjmp(restart)) {
582         cpu *const processor = system->processors[0];
583         unsigned_word cia = cpu_get_program_counter(processor);
584         do {
585           if (WITH_EVENTS) {
586             if (event_queue_tick(system->events)) {
587               cpu_set_program_counter(processor, cia);
588               event_queue_process(system->events);
589               cia = cpu_get_program_counter(processor);
590             }
591           }
592           {
593             instruction_word const instruction
594               = vm_instruction_map_read(cpu_instruction_map(processor),
595                                         processor, cia);
596             cia = idecode_issue(processor, instruction, cia);
597           }
598         } while (keep_running == NULL || *keep_running);
599         cpu_set_program_counter(processor, cia);
600       }
601     } while(keep_running == NULL || *keep_running);
602   }
603 #endif
604
605
606 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
607
608   /* CASE 2: Instruction case but no SMP
609
610      Here, the additional complexity comes from there being two
611      different cache implementations.  A simple function address cache
612      or a full cracked instruction cache */
613
614   if (!setjmp(halt)) {
615     do {
616       if (!setjmp(restart)) {
617         cpu *const processor = system->processors[0];
618         unsigned_word cia = cpu_get_program_counter(processor);
619         do {
620           if (WITH_EVENTS)
621             if (event_queue_tick(system->events)) {
622               cpu_set_program_counter(processor, cia);
623               event_queue_process(system->events);
624               cia = cpu_get_program_counter(processor);
625             }
626           { 
627             idecode_cache *const cache_entry = cpu_icache_entry(processor,
628                                                                 cia);
629             if (cache_entry->address == cia) {
630               idecode_semantic *const semantic = cache_entry->semantic;
631               cia = semantic(processor, cache_entry, cia);
632             }
633             else {
634               instruction_word const instruction
635                 = vm_instruction_map_read(cpu_instruction_map(processor),
636                                           processor,
637                                           cia);
638               idecode_semantic *const semantic = idecode(processor,
639                                                          instruction,
640                                                          cia,
641                                                          cache_entry);
642               cache_entry->address = cia;
643               cache_entry->semantic = semantic;
644               cia = semantic(processor, cache_entry, cia);
645             }
646           }
647         } while (keep_running == NULL || *keep_running);
648         cpu_set_program_counter(processor, cia);
649       }
650     } while(keep_running == NULL || *keep_running);
651   }
652 #endif
653
654
655 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
656
657   /* CASE 3: No ICACHE but SMP
658
659      The complexity here comes from needing to correctly restart the
660      system when it is aborted.  In particular if cpu0 requests a
661      restart, the next cpu is still cpu1.  Cpu0 being restarted after
662      all the other CPU's and the event queue have been processed */
663
664   if (!setjmp(halt)) {
665     int first_cpu = setjmp(restart);
666     if (first_cpu == 0)
667       first_cpu = system->last_cpu + 1;
668     do {
669       int current_cpu;
670       for (current_cpu = first_cpu, first_cpu = 0;
671            current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
672            current_cpu++) {
673         if (WITH_EVENTS && current_cpu == system->nr_cpus) {
674           if (event_queue_tick(system->events))
675             event_queue_process(system->events);
676         }
677         else {
678           cpu *const processor = system->processors[current_cpu];
679           unsigned_word const cia = cpu_get_program_counter(processor);
680           instruction_word instruction =
681             vm_instruction_map_read(cpu_instruction_map(processor),
682                                     processor,
683                                     cia);
684           cpu_set_program_counter(processor,
685                                   idecode_issue(processor, instruction, cia));
686         }
687         if (!(keep_running == NULL || *keep_running)) {
688           system->last_cpu = current_cpu;
689           break;
690         }
691       }
692     } while (keep_running == NULL || *keep_running);
693   }
694 #endif
695
696 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
697
698   /* CASE 4: ICACHE and SMP ...
699
700      This time, everything goes wrong.  Need to restart loops
701      correctly, need to save the program counter and finally need to
702      keep track of each processors current address! */
703
704   if (!setjmp(halt)) {
705     int first_cpu = setjmp(restart);
706     if (!first_cpu)
707       first_cpu = system->last_cpu + 1;
708     do {
709       int current_cpu;
710       for (current_cpu = first_cpu, first_cpu = 0;
711            current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
712            current_cpu++) {
713         if (WITH_EVENTS && current_cpu == system->nr_cpus) {
714           if (event_queue_tick(system->events))
715             event_queue_process(system->events);
716         }
717         else {
718           cpu *processor = system->processors[current_cpu];
719           unsigned_word const cia = cpu_get_program_counter(processor);
720           idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
721           if (cache_entry->address == cia) {
722             idecode_semantic *semantic = cache_entry->semantic;
723             cpu_set_program_counter(processor,
724                                     semantic(processor, cache_entry, cia));
725           }
726           else {
727             instruction_word instruction =
728               vm_instruction_map_read(cpu_instruction_map(processor),
729                                       processor,
730                                       cia);
731             idecode_semantic *semantic = idecode(processor,
732                                                  instruction,
733                                                  cia,
734                                                  cache_entry);
735             cache_entry->address = cia;
736             cache_entry->semantic = semantic;
737             cpu_set_program_counter(processor,
738                                     semantic(processor, cache_entry, cia));
739           }
740         }
741         if (!(keep_running == NULL || *keep_running))
742           break;
743       }
744     } while (keep_running == NULL || *keep_running);
745   }
746 #endif
747
748   psim_clear_halt_and_restart(system);
749 }
750
751
752 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
753    thing */
754
755 INLINE_PSIM void
756 psim_step(psim *system)
757 {
758   volatile int keep_running = 0;
759   run_until_stop(system, &keep_running);
760 }
761
762 INLINE_PSIM void
763 psim_run(psim *system)
764 {
765   run_until_stop(system, NULL);
766 }
767
768 INLINE_PSIM void
769 psim_run_until_stop(psim *system,
770                     volatile int *keep_running)
771 {
772   run_until_stop(system, keep_running);
773 }
774
775
776
777 /* storage manipulation functions */
778
779 INLINE_PSIM void
780 psim_read_register(psim *system,
781                    int which_cpu,
782                    void *buf,
783                    const char reg[],
784                    transfer_mode mode)
785 {
786   register_descriptions description;
787   char cooked_buf[sizeof(natural_word)];
788   cpu *processor;
789
790   /* find our processor */
791   if (which_cpu == MAX_NR_PROCESSORS)
792     which_cpu = system->last_cpu;
793   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
794     error("psim_read_register() - invalid processor %d\n", which_cpu);
795   processor = system->processors[which_cpu];
796
797   /* find the register description */
798   description = register_description(reg);
799   if (description.type == reg_invalid)
800     error("psim_read_register() invalid register name `%s'\n", reg);
801
802   /* get the cooked value */
803   switch (description.type) {
804
805   case reg_gpr:
806     *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
807     break;
808
809   case reg_spr:
810     *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
811     break;
812     
813   case reg_sr:
814     *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
815     break;
816
817   case reg_fpr:
818     *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
819     break;
820
821   case reg_pc:
822     *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
823     break;
824
825   case reg_cr:
826     *(creg*)cooked_buf = cpu_registers(processor)->cr;
827     break;
828
829   case reg_msr:
830     *(msreg*)cooked_buf = cpu_registers(processor)->msr;
831     break;
832
833   default:
834     printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
835                     processor, buf, reg,
836                     "read of this register unimplemented");
837     break;
838
839   }
840
841   /* the PSIM internal values are in host order.  To fetch raw data,
842      they need to be converted into target order and then returned */
843   if (mode == raw_transfer) {
844     /* FIXME - assumes that all registers are simple integers */
845     switch (description.size) {
846     case 1: 
847       *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
848       break;
849     case 2:
850       *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
851       break;
852     case 4:
853       *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
854       break;
855     case 8:
856       *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
857       break;
858     }
859   }
860   else {
861     bcopy(cooked_buf, buf, description.size);
862   }
863
864 }
865
866
867
868 INLINE_PSIM void
869 psim_write_register(psim *system,
870                     int which_cpu,
871                     const void *buf,
872                     const char reg[],
873                     transfer_mode mode)
874 {
875   cpu *processor;
876   register_descriptions description;
877   char cooked_buf[sizeof(natural_word)];
878
879   /* find our processor */
880   if (which_cpu == MAX_NR_PROCESSORS)
881     which_cpu = system->last_cpu;
882   if (which_cpu == -1) {
883     int i;
884     for (i = 0; i < system->nr_cpus; i++)
885       psim_write_register(system, i, buf, reg, mode);
886     return;
887   }
888   else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
889     error("psim_read_register() - invalid processor %d\n", which_cpu);
890   }
891
892   processor = system->processors[which_cpu];
893
894   /* find the description of the register */
895   description = register_description(reg);
896   if (description.type == reg_invalid)
897     error("psim_write_register() invalid register name %s\n", reg);
898
899   /* If the data is comming in raw (target order), need to cook it
900      into host order before putting it into PSIM's internal structures */
901   if (mode == raw_transfer) {
902     switch (description.size) {
903     case 1: 
904       *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
905       break;
906     case 2:
907       *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
908       break;
909     case 4:
910       *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
911       break;
912     case 8:
913       *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
914       break;
915     }
916   }
917   else {
918     bcopy(buf, cooked_buf, description.size);
919   }
920
921   /* put the cooked value into the register */
922   switch (description.type) {
923
924   case reg_gpr:
925     cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
926     break;
927
928   case reg_fpr:
929     cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
930     break;
931
932   case reg_pc:
933     cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
934     break;
935
936   case reg_spr:
937     cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
938     break;
939
940   case reg_sr:
941     cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
942     break;
943
944   case reg_cr:
945     cpu_registers(processor)->cr = *(creg*)cooked_buf;
946     break;
947
948   case reg_msr:
949     cpu_registers(processor)->msr = *(msreg*)cooked_buf;
950     break;
951
952   default:
953     printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
954                     processor, cooked_buf, reg,
955                     "read of this register unimplemented");
956     break;
957
958   }
959
960 }
961
962
963
964 INLINE_PSIM unsigned
965 psim_read_memory(psim *system,
966                  int which_cpu,
967                  void *buffer,
968                  unsigned_word vaddr,
969                  unsigned nr_bytes)
970 {
971   cpu *processor;
972   if (which_cpu == MAX_NR_PROCESSORS)
973     which_cpu = system->last_cpu;
974   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
975     error("psim_read_memory() invalid cpu\n");
976   processor = system->processors[which_cpu];
977   return vm_data_map_read_buffer(cpu_data_map(processor),
978                                  buffer, vaddr, nr_bytes);
979 }
980
981
982 INLINE_PSIM unsigned
983 psim_write_memory(psim *system,
984                   int which_cpu,
985                   const void *buffer,
986                   unsigned_word vaddr,
987                   unsigned nr_bytes,
988                   int violate_read_only_section)
989 {
990   cpu *processor;
991   if (which_cpu == MAX_NR_PROCESSORS)
992     which_cpu = system->last_cpu;
993   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
994     error("psim_read_memory() invalid cpu\n");
995   processor = system->processors[which_cpu];
996   return vm_data_map_write_buffer(cpu_data_map(processor),
997                                   buffer, vaddr, nr_bytes, 1);
998 }
999
1000
1001 INLINE_PSIM void
1002 psim_print_info(psim *system,
1003                 int verbose)
1004 {
1005   mon_print_info(system->monitor, verbose);
1006 }
1007
1008
1009 #endif /* _PSIM_C_ */