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