Small changes from Andrew
[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/env",
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/env",
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/env");
414   current_environment = ((strcmp(env, "user") == 0
415                           || strcmp(env, "uea") == 0)
416                          ? USER_ENVIRONMENT
417                          : (strcmp(env, "virtual") == 0
418                             || strcmp(env, "vea") == 0)
419                          ? VIRTUAL_ENVIRONMENT
420                          : (strcmp(env, "operating") == 0
421                             || strcmp(env, "oea") == 0)
422                          ? OPERATING_ENVIRONMENT
423                          : 0);
424   if (current_environment == 0)
425     error("unreconized /options/env\n");
426   if (CURRENT_ENVIRONMENT != current_environment)
427     error("target environment conflict\n");
428
429   /* fill in the missing ALLIGNMENT information */
430   current_alignment = (device_tree_find_boolean(system->devices,
431                                                 "/options/strict-alignment?")
432                        ? STRICT_ALIGNMENT
433                        : NONSTRICT_ALIGNMENT);
434   if (CURRENT_ALIGNMENT != current_alignment)
435     error("target alignment conflict\n");
436
437   /* fill in the missing FLOATING POINT information */
438   current_floating_point = (device_tree_find_boolean(system->devices,
439                                                      "/options/floating-point?")
440                             ? HARD_FLOATING_POINT
441                             : SOFT_FLOATING_POINT);
442   if (CURRENT_FLOATING_POINT != current_floating_point)
443     error("target floating-point conflict\n");
444
445   return system;
446 }
447
448
449 /* allow the simulation to stop/restart abnormaly */
450
451 STATIC_INLINE_PSIM void
452 psim_set_halt_and_restart(psim *system,
453                           void *halt_jmp_buf,
454                           void *restart_jmp_buf)
455 {
456   system->path_to_halt = halt_jmp_buf;
457   system->path_to_restart = restart_jmp_buf;
458 }
459
460 STATIC_INLINE_PSIM void
461 psim_clear_halt_and_restart(psim *system)
462 {
463   system->path_to_halt = NULL;
464   system->path_to_restart = NULL;
465 }
466
467 INLINE_PSIM void
468 psim_restart(psim *system,
469              int current_cpu)
470 {
471   system->last_cpu = current_cpu;
472   longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
473 }
474
475
476 INLINE_PSIM void
477 psim_halt(psim *system,
478           int current_cpu,
479           unsigned_word cia,
480           stop_reason reason,
481           int signal)
482 {
483   system->last_cpu = current_cpu;
484   system->halt_status.cpu_nr = current_cpu;
485   system->halt_status.reason = reason;
486   system->halt_status.signal = signal;
487   system->halt_status.program_counter = cia;
488   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
489 }
490
491 INLINE_PSIM psim_status
492 psim_get_status(psim *system)
493 {
494   return system->halt_status;
495 }
496
497
498 cpu *
499 psim_cpu(psim *system,
500          int cpu_nr)
501 {
502   if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
503     return NULL;
504   else
505     return system->processors[cpu_nr];
506 }
507
508
509 const device *
510 psim_device(psim *system,
511             const char *path)
512 {
513   return device_tree_find_device(system->devices, path);
514 }
515
516
517
518 INLINE_PSIM void
519 psim_init(psim *system)
520 {
521   int cpu_nr;
522
523   /* scrub the monitor */
524   mon_init(system->monitor, system->nr_cpus);
525
526   /* scrub all the cpus */
527   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
528     cpu_init(system->processors[cpu_nr]);
529
530   /* init all the devices */
531   device_tree_init(system->devices, system);
532
533   /* force loop to restart */
534   system->last_cpu = system->nr_cpus - 1;
535 }
536
537 INLINE_PSIM void
538 psim_stack(psim *system,
539            char **argv,
540            char **envp)
541 {
542   /* pass the stack device the argv/envp and let it work out what to
543      do with it */
544   const device *stack_device = device_tree_find_device(system->devices,
545                                                        "/init/stack");
546   unsigned_word stack_pointer;
547   psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
548   stack_device->callback->ioctl(stack_device,
549                                 system,
550                                 NULL, /*cpu*/
551                                 0, /*cia*/
552                                 stack_pointer,
553                                 argv,
554                                 envp);
555 }
556
557
558
559 /* EXECUTE REAL CODE: 
560
561    Unfortunatly, there are multiple cases to consider vis:
562
563         <icache> X <smp> X <events> X <keep-running-flag> X ...
564
565    Consequently this function is written in multiple different ways */
566
567 STATIC_INLINE_PSIM void
568 run_until_stop(psim *system,
569                volatile int *keep_running)
570 {
571   jmp_buf halt;
572   jmp_buf restart;
573   int cpu_nr;
574 #if WITH_IDECODE_CACHE_SIZE
575   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
576     cpu_flush_icache(system->processors[cpu_nr]);
577 #endif
578   psim_set_halt_and_restart(system, &halt, &restart);
579
580 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
581
582   /* CASE 1: No instruction cache and no SMP.
583
584      In this case, we can take advantage of the fact that the current
585      instruction address does not need to be returned to the cpu
586      object after every execution of an instruction.  Instead it only
587      needs to be saved when either A. the main loop exits or B. a
588      cpu-{halt,restart} call forces the loop to be re-entered.  The
589      later functions always save the current cpu instruction
590      address. */
591
592   if (!setjmp(halt)) {
593     do {
594       if (!setjmp(restart)) {
595         cpu *const processor = system->processors[0];
596         unsigned_word cia = cpu_get_program_counter(processor);
597         do {
598           if (WITH_EVENTS) {
599             if (event_queue_tick(system->events)) {
600               cpu_set_program_counter(processor, cia);
601               event_queue_process(system->events);
602               cia = cpu_get_program_counter(processor);
603             }
604           }
605           {
606             instruction_word const instruction
607               = vm_instruction_map_read(cpu_instruction_map(processor),
608                                         processor, cia);
609             cia = idecode_issue(processor, instruction, cia);
610           }
611         } while (keep_running == NULL || *keep_running);
612         cpu_set_program_counter(processor, cia);
613       }
614     } while(keep_running == NULL || *keep_running);
615   }
616 #endif
617
618
619 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
620
621   /* CASE 2: Instruction case but no SMP
622
623      Here, the additional complexity comes from there being two
624      different cache implementations.  A simple function address cache
625      or a full cracked instruction cache */
626
627   if (!setjmp(halt)) {
628     do {
629       if (!setjmp(restart)) {
630         cpu *const processor = system->processors[0];
631         unsigned_word cia = cpu_get_program_counter(processor);
632         do {
633           if (WITH_EVENTS)
634             if (event_queue_tick(system->events)) {
635               cpu_set_program_counter(processor, cia);
636               event_queue_process(system->events);
637               cia = cpu_get_program_counter(processor);
638             }
639           { 
640             idecode_cache *const cache_entry = cpu_icache_entry(processor,
641                                                                 cia);
642             if (cache_entry->address == cia) {
643               idecode_semantic *const semantic = cache_entry->semantic;
644               cia = semantic(processor, cache_entry, cia);
645             }
646             else {
647               instruction_word const instruction
648                 = vm_instruction_map_read(cpu_instruction_map(processor),
649                                           processor,
650                                           cia);
651               idecode_semantic *const semantic = idecode(processor,
652                                                          instruction,
653                                                          cia,
654                                                          cache_entry);
655               cache_entry->address = cia;
656               cache_entry->semantic = semantic;
657               cia = semantic(processor, cache_entry, cia);
658             }
659           }
660         } while (keep_running == NULL || *keep_running);
661         cpu_set_program_counter(processor, cia);
662       }
663     } while(keep_running == NULL || *keep_running);
664   }
665 #endif
666
667
668 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
669
670   /* CASE 3: No ICACHE but SMP
671
672      The complexity here comes from needing to correctly restart the
673      system when it is aborted.  In particular if cpu0 requests a
674      restart, the next cpu is still cpu1.  Cpu0 being restarted after
675      all the other CPU's and the event queue have been processed */
676
677   if (!setjmp(halt)) {
678     int first_cpu = setjmp(restart);
679     if (first_cpu == 0)
680       first_cpu = system->last_cpu + 1;
681     do {
682       int current_cpu;
683       for (current_cpu = first_cpu, first_cpu = 0;
684            current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
685            current_cpu++) {
686         if (WITH_EVENTS && current_cpu == system->nr_cpus) {
687           if (event_queue_tick(system->events))
688             event_queue_process(system->events);
689         }
690         else {
691           cpu *const processor = system->processors[current_cpu];
692           unsigned_word const cia = cpu_get_program_counter(processor);
693           instruction_word instruction =
694             vm_instruction_map_read(cpu_instruction_map(processor),
695                                     processor,
696                                     cia);
697           cpu_set_program_counter(processor,
698                                   idecode_issue(processor, instruction, cia));
699         }
700         if (!(keep_running == NULL || *keep_running)) {
701           system->last_cpu = current_cpu;
702           break;
703         }
704       }
705     } while (keep_running == NULL || *keep_running);
706   }
707 #endif
708
709 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
710
711   /* CASE 4: ICACHE and SMP ...
712
713      This time, everything goes wrong.  Need to restart loops
714      correctly, need to save the program counter and finally need to
715      keep track of each processors current address! */
716
717   if (!setjmp(halt)) {
718     int first_cpu = setjmp(restart);
719     if (!first_cpu)
720       first_cpu = system->last_cpu + 1;
721     do {
722       int current_cpu;
723       for (current_cpu = first_cpu, first_cpu = 0;
724            current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
725            current_cpu++) {
726         if (WITH_EVENTS && current_cpu == system->nr_cpus) {
727           if (event_queue_tick(system->events))
728             event_queue_process(system->events);
729         }
730         else {
731           cpu *processor = system->processors[current_cpu];
732           unsigned_word const cia = cpu_get_program_counter(processor);
733           idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
734           if (cache_entry->address == cia) {
735             idecode_semantic *semantic = cache_entry->semantic;
736             cpu_set_program_counter(processor,
737                                     semantic(processor, cache_entry, cia));
738           }
739           else {
740             instruction_word instruction =
741               vm_instruction_map_read(cpu_instruction_map(processor),
742                                       processor,
743                                       cia);
744             idecode_semantic *semantic = idecode(processor,
745                                                  instruction,
746                                                  cia,
747                                                  cache_entry);
748             cache_entry->address = cia;
749             cache_entry->semantic = semantic;
750             cpu_set_program_counter(processor,
751                                     semantic(processor, cache_entry, cia));
752           }
753         }
754         if (!(keep_running == NULL || *keep_running))
755           break;
756       }
757     } while (keep_running == NULL || *keep_running);
758   }
759 #endif
760
761   psim_clear_halt_and_restart(system);
762 }
763
764
765 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
766    thing */
767
768 INLINE_PSIM void
769 psim_step(psim *system)
770 {
771   volatile int keep_running = 0;
772   run_until_stop(system, &keep_running);
773 }
774
775 INLINE_PSIM void
776 psim_run(psim *system)
777 {
778   run_until_stop(system, NULL);
779 }
780
781 INLINE_PSIM void
782 psim_run_until_stop(psim *system,
783                     volatile int *keep_running)
784 {
785   run_until_stop(system, keep_running);
786 }
787
788
789
790 /* storage manipulation functions */
791
792 INLINE_PSIM void
793 psim_read_register(psim *system,
794                    int which_cpu,
795                    void *buf,
796                    const char reg[],
797                    transfer_mode mode)
798 {
799   register_descriptions description;
800   char cooked_buf[sizeof(natural_word)];
801   cpu *processor;
802
803   /* find our processor */
804   if (which_cpu == MAX_NR_PROCESSORS)
805     which_cpu = system->last_cpu;
806   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
807     error("psim_read_register() - invalid processor %d\n", which_cpu);
808   processor = system->processors[which_cpu];
809
810   /* find the register description */
811   description = register_description(reg);
812   if (description.type == reg_invalid)
813     error("psim_read_register() invalid register name `%s'\n", reg);
814
815   /* get the cooked value */
816   switch (description.type) {
817
818   case reg_gpr:
819     *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
820     break;
821
822   case reg_spr:
823     *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
824     break;
825     
826   case reg_sr:
827     *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
828     break;
829
830   case reg_fpr:
831     *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
832     break;
833
834   case reg_pc:
835     *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
836     break;
837
838   case reg_cr:
839     *(creg*)cooked_buf = cpu_registers(processor)->cr;
840     break;
841
842   case reg_msr:
843     *(msreg*)cooked_buf = cpu_registers(processor)->msr;
844     break;
845
846   default:
847     printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
848                     processor, buf, reg,
849                     "read of this register unimplemented");
850     break;
851
852   }
853
854   /* the PSIM internal values are in host order.  To fetch raw data,
855      they need to be converted into target order and then returned */
856   if (mode == raw_transfer) {
857     /* FIXME - assumes that all registers are simple integers */
858     switch (description.size) {
859     case 1: 
860       *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
861       break;
862     case 2:
863       *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
864       break;
865     case 4:
866       *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
867       break;
868     case 8:
869       *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
870       break;
871     }
872   }
873   else {
874     bcopy(cooked_buf, buf, description.size);
875   }
876
877 }
878
879
880
881 INLINE_PSIM void
882 psim_write_register(psim *system,
883                     int which_cpu,
884                     const void *buf,
885                     const char reg[],
886                     transfer_mode mode)
887 {
888   cpu *processor;
889   register_descriptions description;
890   char cooked_buf[sizeof(natural_word)];
891
892   /* find our processor */
893   if (which_cpu == MAX_NR_PROCESSORS)
894     which_cpu = system->last_cpu;
895   if (which_cpu == -1) {
896     int i;
897     for (i = 0; i < system->nr_cpus; i++)
898       psim_write_register(system, i, buf, reg, mode);
899     return;
900   }
901   else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
902     error("psim_read_register() - invalid processor %d\n", which_cpu);
903   }
904
905   processor = system->processors[which_cpu];
906
907   /* find the description of the register */
908   description = register_description(reg);
909   if (description.type == reg_invalid)
910     error("psim_write_register() invalid register name %s\n", reg);
911
912   /* If the data is comming in raw (target order), need to cook it
913      into host order before putting it into PSIM's internal structures */
914   if (mode == raw_transfer) {
915     switch (description.size) {
916     case 1: 
917       *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
918       break;
919     case 2:
920       *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
921       break;
922     case 4:
923       *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
924       break;
925     case 8:
926       *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
927       break;
928     }
929   }
930   else {
931     bcopy(buf, cooked_buf, description.size);
932   }
933
934   /* put the cooked value into the register */
935   switch (description.type) {
936
937   case reg_gpr:
938     cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
939     break;
940
941   case reg_fpr:
942     cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
943     break;
944
945   case reg_pc:
946     cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
947     break;
948
949   case reg_spr:
950     cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
951     break;
952
953   case reg_sr:
954     cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
955     break;
956
957   case reg_cr:
958     cpu_registers(processor)->cr = *(creg*)cooked_buf;
959     break;
960
961   case reg_msr:
962     cpu_registers(processor)->msr = *(msreg*)cooked_buf;
963     break;
964
965   default:
966     printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
967                     processor, cooked_buf, reg,
968                     "read of this register unimplemented");
969     break;
970
971   }
972
973 }
974
975
976
977 INLINE_PSIM unsigned
978 psim_read_memory(psim *system,
979                  int which_cpu,
980                  void *buffer,
981                  unsigned_word vaddr,
982                  unsigned nr_bytes)
983 {
984   cpu *processor;
985   if (which_cpu == MAX_NR_PROCESSORS)
986     which_cpu = system->last_cpu;
987   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
988     error("psim_read_memory() invalid cpu\n");
989   processor = system->processors[which_cpu];
990   return vm_data_map_read_buffer(cpu_data_map(processor),
991                                  buffer, vaddr, nr_bytes);
992 }
993
994
995 INLINE_PSIM unsigned
996 psim_write_memory(psim *system,
997                   int which_cpu,
998                   const void *buffer,
999                   unsigned_word vaddr,
1000                   unsigned nr_bytes,
1001                   int violate_read_only_section)
1002 {
1003   cpu *processor;
1004   if (which_cpu == MAX_NR_PROCESSORS)
1005     which_cpu = system->last_cpu;
1006   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
1007     error("psim_read_memory() invalid cpu\n");
1008   processor = system->processors[which_cpu];
1009   return vm_data_map_write_buffer(cpu_data_map(processor),
1010                                   buffer, vaddr, nr_bytes, 1);
1011 }
1012
1013
1014 INLINE_PSIM void
1015 psim_print_info(psim *system,
1016                 int verbose)
1017 {
1018   mon_print_info(system->monitor, verbose);
1019 }
1020
1021
1022 #endif /* _PSIM_C_ */