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