45fb821bcafcdc5051f6a749144b675b6dc56317
[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 TRACE(trace_create_stack,
230 ("write_stack_arguments() - %s=0x%x %s=0x%x %s=0x%x %s=0x%x\n",
231 "system", system, "arg", arg,
232 "start_block", start_block, "start_arg", start_arg));
233 if (arg == NULL)
234 error("write_arguments: character array NULL\n");
235 /* only copy in arguments, memory is already zero */
236 for (; *arg != NULL; arg++) {
237 int len = strlen(*arg)+1;
238 TRACE(trace_create_stack,
239 ("write_stack_arguments - write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
240 "**arg", *arg, "start_block", start_block,
241 "len", len, "start_arg", start_arg));
242 if (psim_write_memory(system, 0, *arg,
243 start_block, len,
244 raw_transfer, 0) != len)
245 error("write_arguments() - write of **arg (%s) at 0x%x failed\n",
246 *arg, start_block);
247 if (psim_write_memory(system, 0, &start_block,
248 start_arg, sizeof(start_block),
249 cooked_transfer, 0) != sizeof(start_block))
250 error("write_arguments() - write of *arg failed\n");
251 start_block += ALIGN_8(len);
252 start_arg += sizeof(start_block);
253 }
254 }
255
256 STATIC_INLINE_PSIM void
257 create_elf_stack_frame(psim *system,
258 unsigned_word bottom_of_stack,
259 char **argv,
260 char **envp)
261 {
262 /* fixme - this is over aligned */
263
264 /* information block */
265 const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
266 const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
267 const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
268 const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
269
270 /* auxiliary vector - contains only one entry */
271 const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
272 const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
273
274 /* environment points (including null sentinal) */
275 const unsigned sizeof_envp = sizeof_arguments(envp);
276 const unsigned_word start_envp = start_aux - sizeof_envp;
277
278 /* argument pointers (including null sentinal) */
279 const int argc = number_of_arguments(argv);
280 const unsigned sizeof_argv = sizeof_arguments(argv);
281 const unsigned_word start_argv = start_envp - sizeof_argv;
282
283 /* link register save address - alligned to a 16byte boundary */
284 const unsigned_word top_of_stack = ((start_argv
285 - 2 * sizeof(unsigned_word))
286 & ~0xf);
287
288 /* force some stack space */
289 if (CURRENT_ENVIRONMENT == VIRTUAL_ENVIRONMENT
290 && core_stack_lower_bound(system->memory) > top_of_stack) {
291 unsigned_word extra_stack_space = (core_stack_lower_bound(system->memory)
292 - FLOOR_PAGE(top_of_stack));
293 TRACE(trace_create_stack,
294 ("create_elf_stack_frame() - growing stack by 0x%x\n",
295 extra_stack_space));
296 core_add_stack(system->memory, extra_stack_space);
297 }
298
299 /* install arguments on stack */
300 write_stack_arguments(system, envp, start_envp_block, start_envp);
301 write_stack_arguments(system, argv, start_argv_block, start_argv);
302
303 /* set up the registers */
304 psim_write_register(system, -1,
305 &top_of_stack, "r1", cooked_transfer);
306 psim_write_register(system, -1,
307 &argc, "r3", cooked_transfer);
308 psim_write_register(system, -1,
309 &start_argv, "r4", cooked_transfer);
310 psim_write_register(system, -1,
311 &start_envp, "r5", cooked_transfer);
312 psim_write_register(system, -1,
313 &start_aux, "r6", cooked_transfer);
314 }
315
316 STATIC_INLINE_PSIM void
317 create_aix_stack_frame(psim *system,
318 unsigned_word bottom_of_stack,
319 char **argv,
320 char **envp)
321 {
322 unsigned_word core_envp;
323 unsigned_word core_argv;
324 unsigned_word core_argc;
325 unsigned_word core_aux;
326 unsigned_word top_of_stack;
327
328 /* cheat - create an elf stack frame */
329 create_elf_stack_frame(system, bottom_of_stack, argv, envp);
330
331 /* extract argument addresses from registers */
332 psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
333 psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
334 psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
335 psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
336 psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
337
338 /* check stack fits at least this much */
339 if (CURRENT_ENVIRONMENT == VIRTUAL_ENVIRONMENT
340 && core_stack_lower_bound(system->memory) > top_of_stack) {
341 unsigned_word extra_stack_space = (core_stack_lower_bound(system->memory)
342 - FLOOR_PAGE(top_of_stack));
343 TRACE(trace_create_stack,
344 ("create_aix_stack_frame() - growing stack by 0x%x\n",
345 extra_stack_space));
346 core_add_stack(system->memory, extra_stack_space);
347 }
348
349 /* extract arguments from registers */
350 error("create_aix_stack_frame() - what happens next?\n");
351 }
352
353
354 INLINE_PSIM void
355 psim_load(psim *system)
356 {
357 unsigned_word program_counter;
358 msreg msr;
359
360 /* load in core data */
361 core_init(system->memory);
362
363 /* set up all processor entry points (to same thing). Maybe
364 someday, the device tree could include information specifying the
365 entry point for each processor, one day */
366 TRACE(trace_tbd,
367 ("TBD - device tree specifying entry point of each processor\n"));
368 program_counter = device_tree_find_int(system->devices,
369 "/options/program-counter");
370 psim_write_register(system, -1,
371 &program_counter,
372 "pc", cooked_transfer);
373 system->last_cpu = system->nr_cpus - 1; /* force loop to restart */
374
375 /* set up the MSR for at least be/le mode */
376 msr = (device_tree_find_boolean(system->devices,
377 "/options/little-endian?")
378 ? msr_little_endian_mode
379 : 0);
380 psim_write_register(system, -1,
381 &msr,
382 "msr", cooked_transfer);
383 }
384
385 INLINE_PSIM void
386 psim_stack(psim *system,
387 char **argv,
388 char **envp)
389 {
390 unsigned_word stack_pointer = device_tree_find_int(system->devices,
391 "/options/stack-pointer");
392 if (device_tree_find_boolean(system->devices,
393 "/options/elf?"))
394 create_elf_stack_frame(system, stack_pointer, argv, envp);
395 else
396 create_aix_stack_frame(system, stack_pointer, argv, envp);
397 }
398
399
400
401 /* EXECUTE REAL CODE:
402
403 Unfortunatly, there are multiple cases to consider vis:
404
405 <icache> X <smp> X <events> X <keep-running-flag> X ...
406
407 Consequently this function is written in multiple different ways */
408
409 STATIC_INLINE_PSIM void
410 run_until_stop(psim *system,
411 volatile int *keep_running)
412 {
413
414 #if (WITH_IDECODE_CACHE == 0 && WITH_SMP == 0)
415
416 /* CASE 1: No instruction cache and no SMP.
417
418 In this case, we can take advantage of the fact that the current
419 instruction address does not need to be returned to the cpu
420 object after every execution of an instruction. Instead it only
421 needs to be saved when either A. the main loop exits or B. a
422 cpu-{halt,restart} call forces the loop to be re-entered. The
423 later functions always save the current cpu instruction
424 address. */
425
426 jmp_buf halt;
427 jmp_buf restart;
428 psim_set_halt_and_restart(system, &halt, &restart);
429 if (!setjmp(halt)) {
430 do {
431 if (!setjmp(restart)) {
432 cpu *const processor = system->processors[0];
433 unsigned_word cia = cpu_get_program_counter(processor);
434 do {
435 if (WITH_EVENTS) {
436 if (event_queue_tick(system->events)) {
437 cpu_set_program_counter(processor, cia);
438 event_queue_process(system->events);
439 cia = cpu_get_program_counter(processor);
440 }
441 }
442 {
443 instruction_word const instruction
444 = vm_instruction_map_read(cpu_instruction_map(processor),
445 processor, cia);
446 cia = idecode_issue(processor, instruction, cia);
447 }
448 } while (keep_running == NULL || *keep_running);
449 cpu_set_program_counter(processor, cia);
450 }
451 } while(keep_running == NULL || *keep_running);
452 }
453 psim_clear_halt_and_restart(system);
454 #endif
455
456
457 #if (WITH_IDECODE_CACHE > 0 && WITH_SMP == 0)
458
459 /* CASE 2: Instruction case but no SMP
460
461 Here, the additional complexity comes from there being two
462 different cache implementations. A simple function address cache
463 or a full cracked instruction cache */
464
465 jmp_buf halt;
466 jmp_buf restart;
467 psim_set_halt_and_restart(system, &halt, &restart);
468 if (!setjmp(halt)) {
469 do {
470 if (!setjmp(restart)) {
471 cpu *const processor = system->processors[0];
472 unsigned_word cia = cpu_get_program_counter(processor);
473 do {
474 if (WITH_EVENTS)
475 if (event_queue_tick(system->events)) {
476 cpu_set_program_counter(processor, cia);
477 event_queue_process(system->events);
478 cia = cpu_get_program_counter(processor);
479 }
480 {
481 idecode_cache *const cache_entry
482 = cpu_icache(processor) + (cia / 4 % IDECODE_CACHE_SIZE);
483 if (cache_entry->address == cia) {
484 idecode_semantic *const semantic = cache_entry->semantic;
485 #if WITH_IDECODE_CACHE == 1
486 cia = semantic(processor, cache_entry->instruction, cia);
487 #else
488 cia = semantic(processor, cache_entry, cia);
489 #endif
490 }
491 else {
492 instruction_word const instruction
493 = vm_instruction_map_read(cpu_instruction_map(processor),
494 processor,
495 cia);
496 #if WITH_IDECODE_CACHE == 1
497 idecode_semantic *const semantic = idecode(processor,
498 instruction,
499 cia);
500 #else
501 idecode_semantic *const semantic = idecode(processor,
502 instruction,
503 cia,
504 cache_entry);
505 #endif
506 cache_entry->address = cia;
507 cache_entry->semantic = semantic;
508 #if WITH_IDECODE_CACHE == 1
509 cache_entry->instruction = instruction;
510 cia = semantic(processor, instruction, cia);
511 #else
512 cia = semantic(processor, cache_entry, cia);
513 #endif
514 }
515 }
516 } while (keep_running == NULL || *keep_running);
517 cpu_set_program_counter(processor, cia);
518 }
519 } while(keep_running == NULL || *keep_running);
520 }
521 psim_clear_halt_and_restart(system);
522 #endif
523
524
525 #if (WITH_IDECODE_CACHE == 0 && WITH_SMP > 0)
526
527 /* CASE 3: No ICACHE but SMP
528
529 The complexity here comes from needing to correctly restart the
530 system when it is aborted. In particular if cpu0 requests a
531 restart, the next cpu is still cpu1. Cpu0 being restarted after
532 all the other CPU's and the event queue have been processed */
533
534 jmp_buf halt;
535 jmp_buf restart;
536 psim_set_halt_and_restart(system, &halt, &restart);
537
538 if (!setjmp(halt)) {
539 int first_cpu = setjmp(restart);
540 if (first_cpu == 0)
541 first_cpu = system->last_cpu + 1;
542 do {
543 int current_cpu;
544 for (current_cpu = first_cpu, first_cpu = 0;
545 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
546 current_cpu++) {
547 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
548 if (event_queue_tick(system->events))
549 event_queue_process(system->events);
550 }
551 else {
552 cpu *const processor = system->processors[current_cpu];
553 unsigned_word const cia = cpu_get_program_counter(processor);
554 instruction_word instruction =
555 vm_instruction_map_read(cpu_instruction_map(processor),
556 processor,
557 cia);
558 cpu_set_program_counter(processor,
559 idecode_issue(processor, instruction, cia));
560 }
561 if (!(keep_running == NULL || *keep_running)) {
562 system->last_cpu = current_cpu;
563 break;
564 }
565 }
566 } while (keep_running == NULL || *keep_running);
567 }
568 psim_clear_halt_and_restart(system);
569 #endif
570
571 #if (WITH_IDECODE_CACHE > 0 && WITH_SMP > 0)
572
573 /* CASE 4: ICACHE and SMP ...
574
575 This time, everything goes wrong. Need to restart loops
576 correctly, need to save the program counter and finally need to
577 keep track of each processors current address! */
578
579 jmp_buf halt;
580 jmp_buf restart;
581 psim_set_halt_and_restart(system, &halt, &restart);
582
583 if (!setjmp(halt)) {
584 int first_cpu = setjmp(restart);
585 if (!first_cpu)
586 first_cpu = system->last_cpu + 1;
587 do {
588 int current_cpu;
589 for (current_cpu = first_cpu, first_cpu = 0;
590 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
591 current_cpu++) {
592 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
593 if (event_queue_tick(system->events))
594 event_queue_process(system->events);
595 }
596 else {
597 cpu *processor = system->processors[current_cpu];
598 unsigned_word const cia = cpu_get_program_counter(processor);
599 idecode_cache *cache_entry
600 = (cpu_icache(processor) + (cia / 4 % IDECODE_CACHE_SIZE));
601 if (cache_entry->address == cia) {
602 idecode_semantic *semantic = cache_entry->semantic;
603 #if WITH_IDECODE_CACHE == 1
604 cpu_set_program_counter(processor,
605 semantic(processor,
606 cache_entry->instruction,
607 cia);
608 #else
609 cpu_set_program_counter(processor,
610 semantic(processor,
611 cache_entry,
612 cia);
613 #endif
614 }
615 else {
616 instruction_word instruction =
617 vm_instruction_map_read(cpu_instruction_map(processor),
618 processor,
619 cia);
620 #if WITH_IDECODE_CACHE == 1
621 idecode_semantic *semantic = idecode(processor,
622 instruction,
623 cia);
624 #else
625 idecode_semantic *semantic = idecode(processor,
626 instruction,
627 cia,
628 cache_entry);
629 #endif
630 cache_entry->address = cia;
631 cache_entry->semantic = semantic;
632 #if WITH_IDECODE_CACHE == 1
633 cache_entry->instruction = instruction;
634 cpu_set_program_counter(processor,
635 semantic(processor, instruction, cia));
636 #else
637 cpu_set_program_counter(processor,
638 semantic(processor, cache_entry, cia);
639 #endif
640 }
641 }
642 if (!(keep_running == NULL || *keep_running))
643 break;
644 }
645 } while (keep_running == NULL || *keep_running);
646 }
647 psim_clear_halt_and_restart(system);
648 #endif
649 }
650
651
652 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
653 thing */
654
655 INLINE_PSIM void
656 psim_step(psim *system)
657 {
658 volatile int keep_running = 0;
659 psim_run_until_stop(system, &keep_running);
660 }
661
662 INLINE_PSIM void
663 psim_run(psim *system)
664 {
665 run_until_stop(system, NULL);
666 }
667
668 INLINE_PSIM void
669 psim_run_until_stop(psim *system,
670 volatile int *keep_running)
671 {
672 run_until_stop(system, keep_running);
673 }
674
675
676
677 /* storage manipulation functions */
678
679 INLINE_PSIM void
680 psim_read_register(psim *system,
681 int which_cpu,
682 void *buf,
683 const char reg[],
684 transfer_mode mode)
685 {
686 register_descriptions description;
687 char cooked_buf[sizeof(natural_word)];
688 cpu *processor;
689
690 /* find our processor */
691 if (which_cpu < 0 || which_cpu > system->nr_cpus)
692 error("psim_read_register() - invalid processor %d\n", which_cpu);
693 if (which_cpu == system->nr_cpus)
694 which_cpu = system->last_cpu;
695 processor = system->processors[which_cpu];
696
697 /* find the register description */
698 description = register_description(reg);
699 if (description.type == reg_invalid)
700 error("psim_read_register() invalid register name `%s'\n", reg);
701
702 /* get the cooked value */
703 switch (description.type) {
704
705 case reg_gpr:
706 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
707 break;
708
709 case reg_spr:
710 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
711 break;
712
713 case reg_sr:
714 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
715 break;
716
717 case reg_fpr:
718 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
719 break;
720
721 case reg_pc:
722 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
723 break;
724
725 case reg_cr:
726 *(creg*)cooked_buf = cpu_registers(processor)->cr;
727 break;
728
729 case reg_msr:
730 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
731 break;
732
733 default:
734 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
735 processor, buf, reg,
736 "read of this register unimplemented");
737 break;
738
739 }
740
741 /* the PSIM internal values are in host order. To fetch raw data,
742 they need to be converted into target order and then returned */
743 if (mode == raw_transfer) {
744 /* FIXME - assumes that all registers are simple integers */
745 switch (description.size) {
746 case 1:
747 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
748 break;
749 case 2:
750 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
751 break;
752 case 4:
753 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
754 break;
755 case 8:
756 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
757 break;
758 }
759 }
760 else {
761 bcopy(cooked_buf, buf, description.size);
762 }
763
764 }
765
766
767
768 INLINE_PSIM void
769 psim_write_register(psim *system,
770 int which_cpu,
771 const void *buf,
772 const char reg[],
773 transfer_mode mode)
774 {
775 cpu *processor;
776 register_descriptions description;
777 char cooked_buf[sizeof(natural_word)];
778
779 /* find our processor */
780 if (which_cpu == -1) {
781 int i;
782 for (i = 0; i < system->nr_cpus; i++)
783 psim_write_register(system, i, buf, reg, mode);
784 return;
785 }
786 else if (which_cpu == system->nr_cpus) {
787 which_cpu = system->last_cpu;
788 }
789 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
790 error("psim_read_register() - invalid processor %d\n", which_cpu);
791 }
792
793 processor = system->processors[which_cpu];
794
795 /* find the description of the register */
796 description = register_description(reg);
797 if (description.type == reg_invalid)
798 error("psim_write_register() invalid register name %s\n", reg);
799
800 /* If the data is comming in raw (target order), need to cook it
801 into host order before putting it into PSIM's internal structures */
802 if (mode == raw_transfer) {
803 switch (description.size) {
804 case 1:
805 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
806 break;
807 case 2:
808 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
809 break;
810 case 4:
811 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
812 break;
813 case 8:
814 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
815 break;
816 }
817 }
818 else {
819 bcopy(buf, cooked_buf, description.size);
820 }
821
822 /* put the cooked value into the register */
823 switch (description.type) {
824
825 case reg_gpr:
826 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
827 break;
828
829 case reg_fpr:
830 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
831 break;
832
833 case reg_pc:
834 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
835 break;
836
837 case reg_spr:
838 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
839 break;
840
841 case reg_sr:
842 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
843 break;
844
845 case reg_cr:
846 cpu_registers(processor)->cr = *(creg*)cooked_buf;
847 break;
848
849 case reg_msr:
850 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
851 break;
852
853 default:
854 printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
855 processor, cooked_buf, reg,
856 "read of this register unimplemented");
857 break;
858
859 }
860
861 }
862
863
864
865 INLINE_PSIM unsigned
866 psim_read_memory(psim *system,
867 int which_cpu,
868 void *buffer,
869 unsigned_word vaddr,
870 unsigned len,
871 transfer_mode mode)
872 {
873 cpu *processor;
874 if (which_cpu < 0 || which_cpu > system->nr_cpus)
875 error("psim_read_memory() invalid cpu\n");
876 if (which_cpu == system->nr_cpus)
877 which_cpu = system->last_cpu;
878 processor = system->processors[which_cpu];
879 return vm_data_map_read_buffer(cpu_data_map(processor),
880 buffer, vaddr, len, mode);
881 }
882
883
884 INLINE_PSIM unsigned
885 psim_write_memory(psim *system,
886 int which_cpu,
887 const void *buffer,
888 unsigned_word vaddr,
889 unsigned len,
890 transfer_mode mode,
891 int violate_read_only_section)
892 {
893 cpu *processor;
894 if (which_cpu < 0 || which_cpu > system->nr_cpus)
895 error("psim_read_memory() invalid cpu\n");
896 if (which_cpu == system->nr_cpus)
897 which_cpu = system->last_cpu;
898 processor = system->processors[which_cpu];
899 return vm_data_map_write_buffer(cpu_data_map(processor),
900 buffer, vaddr, len, mode, 1);
901 }
902
903
904 #endif /* _PSIM_C_ */
This page took 0.048276 seconds and 4 git commands to generate.