Add support to count the number of instructions issued.
[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 "config.h"
26 #include "ppc-config.h"
27 #include "inline.h"
28
29 #ifndef STATIC_INLINE_PSIM
30 #define STATIC_INLINE_PSIM STATIC_INLINE
31 #endif
32
33 #include <string.h>
34 #include <setjmp.h>
35
36 #include "cpu.h" /* includes psim.h */
37 #include "idecode.h"
38
39 #include "inline.c"
40
41
42 /* system structure, actual size of processor array determined at
43 runtime */
44
45 struct _psim {
46 event_queue *events;
47 device_node *devices;
48 core *memory;
49 /* escape routine for inner functions */
50 void *path_to_halt;
51 void *path_to_restart;
52 /* status from last halt */
53 psim_status halt_status;
54 /* the processes proper */
55 int nr_cpus;
56 int last_cpu; /* CPU that last (tried to) execute an instruction */
57 cpu *processors[0];
58 };
59
60
61 int current_target_byte_order;
62 int current_host_byte_order;
63 int current_environment;
64 int current_alignment;
65
66 INLINE_PSIM psim *
67 psim_create(const char *file_name,
68 int nr_processors)
69 {
70 int cpu_nr;
71 psim *system;
72
73 /* sanity check */
74 if (nr_processors <= 0
75 || (!WITH_SMP && nr_processors != 1))
76 error("psim_create() invalid number of cpus\n");
77
78 /* create things */
79 system = (psim*)zalloc(sizeof(psim)
80 + sizeof(cpu*) * (nr_processors + 1));
81 system->nr_cpus = nr_processors;
82 system->events = event_queue_create();
83 system->devices = device_tree_create(file_name);
84 system->memory = core_create(system->devices, 0);
85 for (cpu_nr = 0; cpu_nr < nr_processors; cpu_nr++) {
86 system->processors[cpu_nr] = cpu_create(system,
87 system->memory,
88 system->events,
89 cpu_nr);
90 }
91
92 /* fill in the missing endian information */
93 current_target_byte_order
94 = (device_tree_find_boolean(system->devices, "/options/little-endian?")
95 ? LITTLE_ENDIAN
96 : BIG_ENDIAN);
97 if (WITH_TARGET_BYTE_ORDER
98 && WITH_TARGET_BYTE_ORDER != current_target_byte_order)
99 error("target byte order conflict\n");
100
101 current_host_byte_order = 1;
102 current_host_byte_order = (*(char*)(&current_host_byte_order)
103 ? LITTLE_ENDIAN
104 : BIG_ENDIAN);
105 if (WITH_HOST_BYTE_ORDER
106 && WITH_HOST_BYTE_ORDER != current_host_byte_order)
107 error("host byte order conflict\n");
108
109 /* fill in the missing OEA/VEA information */
110 current_environment = (device_tree_find_boolean(system->devices,
111 "/options/vea?")
112 ? VIRTUAL_ENVIRONMENT
113 : OPERATING_ENVIRONMENT);
114
115 /* fill in the missing ALLIGNMENT information */
116 current_alignment = (device_tree_find_boolean(system->devices,
117 "/options/aligned?")
118 ? STRICT_ALIGNMENT
119 : NONSTRICT_ALIGNMENT);
120 if (WITH_ALIGNMENT
121 && CURRENT_ALIGNMENT != WITH_ALIGNMENT)
122 error("target alignment support conflict\n");
123
124 return system;
125 }
126
127
128 /* allow the simulation to stop/restart abnormaly */
129
130 STATIC_INLINE_PSIM void
131 psim_set_halt_and_restart(psim *system,
132 void *halt_jmp_buf,
133 void *restart_jmp_buf)
134 {
135 system->path_to_halt = halt_jmp_buf;
136 system->path_to_restart = restart_jmp_buf;
137 }
138
139 STATIC_INLINE_PSIM void
140 psim_clear_halt_and_restart(psim *system)
141 {
142 system->path_to_halt = NULL;
143 system->path_to_restart = NULL;
144 }
145
146 INLINE_PSIM void
147 psim_restart(psim *system,
148 int current_cpu)
149 {
150 system->last_cpu = current_cpu;
151 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
152 }
153
154
155 INLINE_PSIM void
156 psim_halt(psim *system,
157 int current_cpu,
158 unsigned_word cia,
159 stop_reason reason,
160 int signal)
161 {
162 system->last_cpu = current_cpu;
163 system->halt_status.cpu_nr = current_cpu;
164 system->halt_status.reason = reason;
165 system->halt_status.signal = signal;
166 system->halt_status.program_counter = cia;
167 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
168 }
169
170 INLINE_PSIM psim_status
171 psim_get_status(psim *system)
172 {
173 return system->halt_status;
174 }
175
176
177 cpu *
178 psim_cpu(psim *system,
179 int cpu_nr)
180 {
181 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
182 return NULL;
183 else
184 return system->processors[cpu_nr];
185 }
186
187
188
189 STATIC_INLINE_PSIM int
190 sizeof_argument_strings(char **arg)
191 {
192 int sizeof_strings = 0;
193
194 /* robust */
195 if (arg == NULL)
196 return 0;
197
198 /* add up all the string sizes (padding as we go) */
199 for (; *arg != NULL; arg++) {
200 int len = strlen(*arg) + 1;
201 sizeof_strings += ALIGN_8(len);
202 }
203
204 return sizeof_strings;
205 }
206
207 STATIC_INLINE_PSIM int
208 number_of_arguments(char **arg)
209 {
210 int nr;
211 if (arg == NULL)
212 return 0;
213 for (nr = 0; *arg != NULL; arg++, nr++);
214 return nr;
215 }
216
217 STATIC_INLINE_PSIM int
218 sizeof_arguments(char **arg)
219 {
220 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
221 }
222
223 STATIC_INLINE_PSIM void
224 write_stack_arguments(psim *system,
225 char **arg,
226 unsigned_word start_block,
227 unsigned_word start_arg)
228 {
229 if (CURRENT_ENVIRONMENT != VIRTUAL_ENVIRONMENT)
230 {
231 TRACE(trace_create_stack, ("write_stack_arguments() - skipping, OEA program\n"));
232 return;
233 }
234
235 TRACE(trace_create_stack,
236 ("write_stack_arguments() - %s=0x%x %s=0x%x %s=0x%x %s=0x%x\n",
237 "system", system, "arg", arg,
238 "start_block", start_block, "start_arg", start_arg));
239 if (arg == NULL)
240 error("write_arguments: character array NULL\n");
241 /* only copy in arguments, memory is already zero */
242 for (; *arg != NULL; arg++) {
243 int len = strlen(*arg)+1;
244 TRACE(trace_create_stack,
245 ("write_stack_arguments - write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
246 "**arg", *arg, "start_block", start_block,
247 "len", len, "start_arg", start_arg));
248 if (psim_write_memory(system, 0, *arg,
249 start_block, len,
250 raw_transfer, 0) != len)
251 error("write_arguments() - write of **arg (%s) at 0x%x failed\n",
252 *arg, start_block);
253 if (psim_write_memory(system, 0, &start_block,
254 start_arg, sizeof(start_block),
255 cooked_transfer, 0) != sizeof(start_block))
256 error("write_arguments() - write of *arg failed\n");
257 start_block += ALIGN_8(len);
258 start_arg += sizeof(start_block);
259 }
260 }
261
262 STATIC_INLINE_PSIM void
263 create_elf_stack_frame(psim *system,
264 unsigned_word bottom_of_stack,
265 char **argv,
266 char **envp)
267 {
268 /* fixme - this is over aligned */
269
270 /* information block */
271 const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
272 const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
273 const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
274 const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
275
276 /* auxiliary vector - contains only one entry */
277 const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
278 const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
279
280 /* environment points (including null sentinal) */
281 const unsigned sizeof_envp = sizeof_arguments(envp);
282 const unsigned_word start_envp = start_aux - sizeof_envp;
283
284 /* argument pointers (including null sentinal) */
285 const int argc = number_of_arguments(argv);
286 const unsigned sizeof_argv = sizeof_arguments(argv);
287 const unsigned_word start_argv = start_envp - sizeof_argv;
288
289 /* link register save address - alligned to a 16byte boundary */
290 const unsigned_word top_of_stack = ((start_argv
291 - 2 * sizeof(unsigned_word))
292 & ~0xf);
293
294 /* force some stack space */
295 if (CURRENT_ENVIRONMENT == VIRTUAL_ENVIRONMENT
296 && core_stack_lower_bound(system->memory) > top_of_stack) {
297 unsigned_word extra_stack_space = (core_stack_lower_bound(system->memory)
298 - FLOOR_PAGE(top_of_stack));
299 TRACE(trace_create_stack,
300 ("create_elf_stack_frame() - growing stack by 0x%x\n",
301 extra_stack_space));
302 core_add_stack(system->memory, extra_stack_space);
303 }
304
305 /* install arguments on stack */
306 write_stack_arguments(system, envp, start_envp_block, start_envp);
307 write_stack_arguments(system, argv, start_argv_block, start_argv);
308
309 /* set up the registers */
310 psim_write_register(system, -1,
311 &top_of_stack, "r1", cooked_transfer);
312 psim_write_register(system, -1,
313 &argc, "r3", cooked_transfer);
314 psim_write_register(system, -1,
315 &start_argv, "r4", cooked_transfer);
316 psim_write_register(system, -1,
317 &start_envp, "r5", cooked_transfer);
318 psim_write_register(system, -1,
319 &start_aux, "r6", cooked_transfer);
320 }
321
322 STATIC_INLINE_PSIM void
323 create_aix_stack_frame(psim *system,
324 unsigned_word bottom_of_stack,
325 char **argv,
326 char **envp)
327 {
328 unsigned_word core_envp;
329 unsigned_word core_argv;
330 unsigned_word core_argc;
331 unsigned_word core_aux;
332 unsigned_word top_of_stack;
333
334 /* cheat - create an elf stack frame */
335 create_elf_stack_frame(system, bottom_of_stack, argv, envp);
336
337 /* extract argument addresses from registers */
338 psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
339 psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
340 psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
341 psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
342 psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
343
344 /* check stack fits at least this much */
345 if (CURRENT_ENVIRONMENT == VIRTUAL_ENVIRONMENT
346 && core_stack_lower_bound(system->memory) > top_of_stack) {
347 unsigned_word extra_stack_space = (core_stack_lower_bound(system->memory)
348 - FLOOR_PAGE(top_of_stack));
349 TRACE(trace_create_stack,
350 ("create_aix_stack_frame() - growing stack by 0x%x\n",
351 extra_stack_space));
352 core_add_stack(system->memory, extra_stack_space);
353 }
354
355 /* extract arguments from registers */
356 error("create_aix_stack_frame() - what happens next?\n");
357 }
358
359
360 INLINE_PSIM void
361 psim_load(psim *system)
362 {
363 unsigned_word program_counter;
364 msreg msr;
365
366 /* load in core data */
367 core_init(system->memory);
368
369 /* set up all processor entry points (to same thing). Maybe
370 someday, the device tree could include information specifying the
371 entry point for each processor, one day */
372 TRACE(trace_tbd,
373 ("TBD - device tree specifying entry point of each processor\n"));
374 program_counter = device_tree_find_int(system->devices,
375 "/options/program-counter");
376 psim_write_register(system, -1,
377 &program_counter,
378 "pc", cooked_transfer);
379 system->last_cpu = system->nr_cpus - 1; /* force loop to restart */
380
381 /* set up the MSR for at least be/le mode */
382 msr = (device_tree_find_boolean(system->devices,
383 "/options/little-endian?")
384 ? msr_little_endian_mode
385 : 0);
386 psim_write_register(system, -1,
387 &msr,
388 "msr", cooked_transfer);
389 }
390
391 INLINE_PSIM void
392 psim_stack(psim *system,
393 char **argv,
394 char **envp)
395 {
396 unsigned_word stack_pointer = device_tree_find_int(system->devices,
397 "/options/stack-pointer");
398 if (device_tree_find_boolean(system->devices,
399 "/options/elf?"))
400 create_elf_stack_frame(system, stack_pointer, argv, envp);
401 else
402 create_aix_stack_frame(system, stack_pointer, argv, envp);
403 }
404
405
406
407 /* EXECUTE REAL CODE:
408
409 Unfortunatly, there are multiple cases to consider vis:
410
411 <icache> X <smp> X <events> X <keep-running-flag> X ...
412
413 Consequently this function is written in multiple different ways */
414
415 STATIC_INLINE_PSIM void
416 run_until_stop(psim *system,
417 volatile int *keep_running)
418 {
419
420 #if (WITH_IDECODE_CACHE == 0 && WITH_SMP == 0)
421
422 /* CASE 1: No instruction cache and no SMP.
423
424 In this case, we can take advantage of the fact that the current
425 instruction address does not need to be returned to the cpu
426 object after every execution of an instruction. Instead it only
427 needs to be saved when either A. the main loop exits or B. a
428 cpu-{halt,restart} call forces the loop to be re-entered. The
429 later functions always save the current cpu instruction
430 address. */
431
432 jmp_buf halt;
433 jmp_buf restart;
434 psim_set_halt_and_restart(system, &halt, &restart);
435 if (!setjmp(halt)) {
436 do {
437 if (!setjmp(restart)) {
438 cpu *const processor = system->processors[0];
439 unsigned_word cia = cpu_get_program_counter(processor);
440 do {
441 if (WITH_EVENTS) {
442 if (event_queue_tick(system->events)) {
443 cpu_set_program_counter(processor, cia);
444 event_queue_process(system->events);
445 cia = cpu_get_program_counter(processor);
446 }
447 }
448 {
449 instruction_word const instruction
450 = vm_instruction_map_read(cpu_instruction_map(processor),
451 processor, cia);
452 cia = idecode_issue(processor, instruction, cia);
453 }
454 } while (keep_running == NULL || *keep_running);
455 cpu_set_program_counter(processor, cia);
456 }
457 } while(keep_running == NULL || *keep_running);
458 }
459 psim_clear_halt_and_restart(system);
460 #endif
461
462
463 #if (WITH_IDECODE_CACHE > 0 && WITH_SMP == 0)
464
465 /* CASE 2: Instruction case but no SMP
466
467 Here, the additional complexity comes from there being two
468 different cache implementations. A simple function address cache
469 or a full cracked instruction cache */
470
471 jmp_buf halt;
472 jmp_buf restart;
473 psim_set_halt_and_restart(system, &halt, &restart);
474 if (!setjmp(halt)) {
475 do {
476 if (!setjmp(restart)) {
477 cpu *const processor = system->processors[0];
478 unsigned_word cia = cpu_get_program_counter(processor);
479 do {
480 if (WITH_EVENTS)
481 if (event_queue_tick(system->events)) {
482 cpu_set_program_counter(processor, cia);
483 event_queue_process(system->events);
484 cia = cpu_get_program_counter(processor);
485 }
486 {
487 idecode_cache *const cache_entry
488 = cpu_icache(processor) + (cia / 4 % IDECODE_CACHE_SIZE);
489 if (cache_entry->address == cia) {
490 idecode_semantic *const semantic = cache_entry->semantic;
491 #if WITH_IDECODE_CACHE == 1
492 cia = semantic(processor, cache_entry->instruction, cia);
493 #else
494 cia = semantic(processor, cache_entry, cia);
495 #endif
496 }
497 else {
498 instruction_word const instruction
499 = vm_instruction_map_read(cpu_instruction_map(processor),
500 processor,
501 cia);
502 #if WITH_IDECODE_CACHE == 1
503 idecode_semantic *const semantic = idecode(processor,
504 instruction,
505 cia);
506 #else
507 idecode_semantic *const semantic = idecode(processor,
508 instruction,
509 cia,
510 cache_entry);
511 #endif
512 cache_entry->address = cia;
513 cache_entry->semantic = semantic;
514 #if WITH_IDECODE_CACHE == 1
515 cache_entry->instruction = instruction;
516 cia = semantic(processor, instruction, cia);
517 #else
518 cia = semantic(processor, cache_entry, cia);
519 #endif
520 }
521 }
522 } while (keep_running == NULL || *keep_running);
523 cpu_set_program_counter(processor, cia);
524 }
525 } while(keep_running == NULL || *keep_running);
526 }
527 psim_clear_halt_and_restart(system);
528 #endif
529
530
531 #if (WITH_IDECODE_CACHE == 0 && WITH_SMP > 0)
532
533 /* CASE 3: No ICACHE but SMP
534
535 The complexity here comes from needing to correctly restart the
536 system when it is aborted. In particular if cpu0 requests a
537 restart, the next cpu is still cpu1. Cpu0 being restarted after
538 all the other CPU's and the event queue have been processed */
539
540 jmp_buf halt;
541 jmp_buf restart;
542 psim_set_halt_and_restart(system, &halt, &restart);
543
544 if (!setjmp(halt)) {
545 int first_cpu = setjmp(restart);
546 if (first_cpu == 0)
547 first_cpu = system->last_cpu + 1;
548 do {
549 int current_cpu;
550 for (current_cpu = first_cpu, first_cpu = 0;
551 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
552 current_cpu++) {
553 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
554 if (event_queue_tick(system->events))
555 event_queue_process(system->events);
556 }
557 else {
558 cpu *const processor = system->processors[current_cpu];
559 unsigned_word const cia = cpu_get_program_counter(processor);
560 instruction_word instruction =
561 vm_instruction_map_read(cpu_instruction_map(processor),
562 processor,
563 cia);
564 cpu_set_program_counter(processor,
565 idecode_issue(processor, instruction, cia));
566 }
567 if (!(keep_running == NULL || *keep_running)) {
568 system->last_cpu = current_cpu;
569 break;
570 }
571 }
572 } while (keep_running == NULL || *keep_running);
573 }
574 psim_clear_halt_and_restart(system);
575 #endif
576
577 #if (WITH_IDECODE_CACHE > 0 && WITH_SMP > 0)
578
579 /* CASE 4: ICACHE and SMP ...
580
581 This time, everything goes wrong. Need to restart loops
582 correctly, need to save the program counter and finally need to
583 keep track of each processors current address! */
584
585 jmp_buf halt;
586 jmp_buf restart;
587 psim_set_halt_and_restart(system, &halt, &restart);
588
589 if (!setjmp(halt)) {
590 int first_cpu = setjmp(restart);
591 if (!first_cpu)
592 first_cpu = system->last_cpu + 1;
593 do {
594 int current_cpu;
595 for (current_cpu = first_cpu, first_cpu = 0;
596 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
597 current_cpu++) {
598 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
599 if (event_queue_tick(system->events))
600 event_queue_process(system->events);
601 }
602 else {
603 cpu *processor = system->processors[current_cpu];
604 unsigned_word const cia = cpu_get_program_counter(processor);
605 idecode_cache *cache_entry
606 = (cpu_icache(processor) + (cia / 4 % IDECODE_CACHE_SIZE));
607 if (cache_entry->address == cia) {
608 idecode_semantic *semantic = cache_entry->semantic;
609 #if WITH_IDECODE_CACHE == 1
610 cpu_set_program_counter(processor,
611 semantic(processor,
612 cache_entry->instruction,
613 cia);
614 #else
615 cpu_set_program_counter(processor,
616 semantic(processor,
617 cache_entry,
618 cia);
619 #endif
620 }
621 else {
622 instruction_word instruction =
623 vm_instruction_map_read(cpu_instruction_map(processor),
624 processor,
625 cia);
626 #if WITH_IDECODE_CACHE == 1
627 idecode_semantic *semantic = idecode(processor,
628 instruction,
629 cia);
630 #else
631 idecode_semantic *semantic = idecode(processor,
632 instruction,
633 cia,
634 cache_entry);
635 #endif
636 cache_entry->address = cia;
637 cache_entry->semantic = semantic;
638 #if WITH_IDECODE_CACHE == 1
639 cache_entry->instruction = instruction;
640 cpu_set_program_counter(processor,
641 semantic(processor, instruction, cia));
642 #else
643 cpu_set_program_counter(processor,
644 semantic(processor, cache_entry, cia);
645 #endif
646 }
647 }
648 if (!(keep_running == NULL || *keep_running))
649 break;
650 }
651 } while (keep_running == NULL || *keep_running);
652 }
653 psim_clear_halt_and_restart(system);
654 #endif
655 }
656
657
658 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
659 thing */
660
661 INLINE_PSIM void
662 psim_step(psim *system)
663 {
664 volatile int keep_running = 0;
665 psim_run_until_stop(system, &keep_running);
666 }
667
668 INLINE_PSIM void
669 psim_run(psim *system)
670 {
671 run_until_stop(system, NULL);
672 }
673
674 INLINE_PSIM void
675 psim_run_until_stop(psim *system,
676 volatile int *keep_running)
677 {
678 run_until_stop(system, keep_running);
679 }
680
681
682
683 /* storage manipulation functions */
684
685 INLINE_PSIM void
686 psim_read_register(psim *system,
687 int which_cpu,
688 void *buf,
689 const char reg[],
690 transfer_mode mode)
691 {
692 register_descriptions description;
693 char cooked_buf[sizeof(natural_word)];
694 cpu *processor;
695
696 /* find our processor */
697 if (which_cpu < 0 || which_cpu > system->nr_cpus)
698 error("psim_read_register() - invalid processor %d\n", which_cpu);
699 if (which_cpu == system->nr_cpus)
700 which_cpu = system->last_cpu;
701 processor = system->processors[which_cpu];
702
703 /* find the register description */
704 description = register_description(reg);
705 if (description.type == reg_invalid)
706 error("psim_read_register() invalid register name `%s'\n", reg);
707
708 /* get the cooked value */
709 switch (description.type) {
710
711 case reg_gpr:
712 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
713 break;
714
715 case reg_spr:
716 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
717 break;
718
719 case reg_sr:
720 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
721 break;
722
723 case reg_fpr:
724 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
725 break;
726
727 case reg_pc:
728 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
729 break;
730
731 case reg_cr:
732 *(creg*)cooked_buf = cpu_registers(processor)->cr;
733 break;
734
735 case reg_msr:
736 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
737 break;
738
739 default:
740 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
741 processor, buf, reg,
742 "read of this register unimplemented");
743 break;
744
745 }
746
747 /* the PSIM internal values are in host order. To fetch raw data,
748 they need to be converted into target order and then returned */
749 if (mode == raw_transfer) {
750 /* FIXME - assumes that all registers are simple integers */
751 switch (description.size) {
752 case 1:
753 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
754 break;
755 case 2:
756 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
757 break;
758 case 4:
759 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
760 break;
761 case 8:
762 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
763 break;
764 }
765 }
766 else {
767 bcopy(cooked_buf, buf, description.size);
768 }
769
770 }
771
772
773
774 INLINE_PSIM void
775 psim_write_register(psim *system,
776 int which_cpu,
777 const void *buf,
778 const char reg[],
779 transfer_mode mode)
780 {
781 cpu *processor;
782 register_descriptions description;
783 char cooked_buf[sizeof(natural_word)];
784
785 /* find our processor */
786 if (which_cpu == -1) {
787 int i;
788 for (i = 0; i < system->nr_cpus; i++)
789 psim_write_register(system, i, buf, reg, mode);
790 return;
791 }
792 else if (which_cpu == system->nr_cpus) {
793 which_cpu = system->last_cpu;
794 }
795 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
796 error("psim_read_register() - invalid processor %d\n", which_cpu);
797 }
798
799 processor = system->processors[which_cpu];
800
801 /* find the description of the register */
802 description = register_description(reg);
803 if (description.type == reg_invalid)
804 error("psim_write_register() invalid register name %s\n", reg);
805
806 /* If the data is comming in raw (target order), need to cook it
807 into host order before putting it into PSIM's internal structures */
808 if (mode == raw_transfer) {
809 switch (description.size) {
810 case 1:
811 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
812 break;
813 case 2:
814 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
815 break;
816 case 4:
817 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
818 break;
819 case 8:
820 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
821 break;
822 }
823 }
824 else {
825 bcopy(buf, cooked_buf, description.size);
826 }
827
828 /* put the cooked value into the register */
829 switch (description.type) {
830
831 case reg_gpr:
832 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
833 break;
834
835 case reg_fpr:
836 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
837 break;
838
839 case reg_pc:
840 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
841 break;
842
843 case reg_spr:
844 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
845 break;
846
847 case reg_sr:
848 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
849 break;
850
851 case reg_cr:
852 cpu_registers(processor)->cr = *(creg*)cooked_buf;
853 break;
854
855 case reg_msr:
856 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
857 break;
858
859 default:
860 printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
861 processor, cooked_buf, reg,
862 "read of this register unimplemented");
863 break;
864
865 }
866
867 }
868
869
870
871 INLINE_PSIM unsigned
872 psim_read_memory(psim *system,
873 int which_cpu,
874 void *buffer,
875 unsigned_word vaddr,
876 unsigned len,
877 transfer_mode mode)
878 {
879 cpu *processor;
880 if (which_cpu < 0 || which_cpu > system->nr_cpus)
881 error("psim_read_memory() invalid cpu\n");
882 if (which_cpu == system->nr_cpus)
883 which_cpu = system->last_cpu;
884 processor = system->processors[which_cpu];
885 return vm_data_map_read_buffer(cpu_data_map(processor),
886 buffer, vaddr, len, mode);
887 }
888
889
890 INLINE_PSIM unsigned
891 psim_write_memory(psim *system,
892 int which_cpu,
893 const void *buffer,
894 unsigned_word vaddr,
895 unsigned len,
896 transfer_mode mode,
897 int violate_read_only_section)
898 {
899 cpu *processor;
900 if (which_cpu < 0 || which_cpu > system->nr_cpus)
901 error("psim_read_memory() invalid cpu\n");
902 if (which_cpu == system->nr_cpus)
903 which_cpu = system->last_cpu;
904 processor = system->processors[which_cpu];
905 return vm_data_map_write_buffer(cpu_data_map(processor),
906 buffer, vaddr, len, mode, 1);
907 }
908
909
910 INLINE_PSIM void
911 psim_print_info(psim *system, int verbose)
912 {
913 int i;
914 for (i = 0; i < system->nr_cpus; i++)
915 cpu_print_info (system->processors[i], verbose);
916 }
917
918 #endif /* _PSIM_C_ */
This page took 0.049136 seconds and 4 git commands to generate.