Fix warnings to everything can be compiled with -Wall; Redo model specific changes...
[deliverable/binutils-gdb.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_ */
This page took 0.050601 seconds and 5 git commands to generate.