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