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