OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [ppc/] [psim.c] - Blame information for rev 866

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/*  This file is part of the program psim.
2
 
3
    Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
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 "cpu.h" /* includes psim.h */
26
#include "idecode.h"
27
#include "options.h"
28
 
29
#include "tree.h"
30
 
31
#include <signal.h>
32
 
33
#include <stdio.h>
34
#include <ctype.h>
35
 
36
#ifdef HAVE_STDLIB_H
37
#include <stdlib.h>
38
#endif
39
 
40
#include <setjmp.h>
41
 
42
#ifdef HAVE_STRING_H
43
#include <string.h>
44
#else
45
#ifdef HAVE_STRINGS_H
46
#include <strings.h>
47
#endif
48
#endif
49
 
50
 
51
#include "bfd.h"
52
#include "libiberty.h"
53
#include "gdb/signals.h"
54
 
55
/* system structure, actual size of processor array determined at
56
   runtime */
57
 
58
struct _psim {
59
  event_queue *events;
60
  device *devices;
61
  mon *monitor;
62
  os_emul *os_emulation;
63
  core *memory;
64
 
65
  /* escape routine for inner functions */
66
  void *path_to_halt;
67
  void *path_to_restart;
68
 
69
  /* status from last halt */
70
  psim_status halt_status;
71
 
72
  /* the processors proper */
73
  int nr_cpus;
74
  int last_cpu; /* CPU that last (tried to) execute an instruction */
75
  cpu *processors[MAX_NR_PROCESSORS];
76
};
77
 
78
 
79
int current_target_byte_order;
80
int current_host_byte_order;
81
int current_environment;
82
int current_alignment;
83
int current_floating_point;
84
int current_model_issue = MODEL_ISSUE_IGNORE;
85
int current_stdio = DO_USE_STDIO;
86
model_enum current_model = WITH_DEFAULT_MODEL;
87
 
88
 
89
/* create the device tree */
90
 
91
INLINE_PSIM\
92
(device *)
93
psim_tree(void)
94
{
95
  device *root = tree_parse(NULL, "core");
96
  tree_parse(root, "/aliases");
97
  tree_parse(root, "/options");
98
  tree_parse(root, "/chosen");
99
  tree_parse(root, "/packages");
100
  tree_parse(root, "/cpus");
101
  tree_parse(root, "/openprom");
102
  tree_parse(root, "/openprom/init");
103
  tree_parse(root, "/openprom/trace");
104
  tree_parse(root, "/openprom/options");
105
  return root;
106
}
107
 
108
STATIC_INLINE_PSIM\
109
(char *)
110
find_arg(char *err_msg,
111
         int *ptr_to_argp,
112
         char **argv)
113
{
114
  *ptr_to_argp += 1;
115
  if (argv[*ptr_to_argp] == NULL)
116
    error(err_msg);
117
  return argv[*ptr_to_argp];
118
}
119
 
120
INLINE_PSIM\
121
(void)
122
psim_usage(int verbose, int help)
123
{
124
  printf_filtered("Usage:\n");
125
  printf_filtered("\n");
126
  printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
127
  printf_filtered("\n");
128
  printf_filtered("Where\n");
129
  printf_filtered("\n");
130
  printf_filtered("\t<image>         Name of the PowerPC program to run.\n");
131
  if (verbose) {
132
  printf_filtered("\t                This can either be a PowerPC binary or\n");
133
  printf_filtered("\t                a text file containing a device tree\n");
134
  printf_filtered("\t                specification.\n");
135
  printf_filtered("\t                PSIM will attempt to determine from the\n");
136
  printf_filtered("\t                specified <image> the intended emulation\n");
137
  printf_filtered("\t                environment.\n");
138
  printf_filtered("\t                If PSIM gets it wrong, the emulation\n");
139
  printf_filtered("\t                environment can be specified using the\n");
140
  printf_filtered("\t                `-e' option (described below).\n");
141
  printf_filtered("\n"); }
142
  printf_filtered("\t<image-arg>     Argument to be passed to <image>\n");
143
  if (verbose) {
144
  printf_filtered("\t                These arguments will be passed to\n");
145
  printf_filtered("\t                <image> (as standard C argv, argc)\n");
146
  printf_filtered("\t                when <image> is started.\n");
147
  printf_filtered("\n"); }
148
  printf_filtered("\t<psim-option>   See below\n");
149
  printf_filtered("\n");
150
  printf_filtered("The following are valid <psim-option>s:\n");
151
  printf_filtered("\n");
152
 
153
  printf_filtered("\t-c <count>      Limit the simulation to <count> iterations\n");
154
  if (verbose) {
155
  printf_filtered("\n");
156
  }
157
 
158
  printf_filtered("\t-i or -i2       Print instruction counting statistics\n");
159
  if (verbose) {
160
  printf_filtered("\t                Specify -i2 for a more detailed display\n");
161
  printf_filtered("\n");
162
  }
163
 
164
  printf_filtered("\t-I              Print execution unit statistics\n");
165
  if (verbose) { printf_filtered("\n"); }
166
 
167
  printf_filtered("\t-e <os-emul>    specify an OS or platform to model\n");
168
  if (verbose) {
169
  printf_filtered("\t                Can be any of the following:\n");
170
  printf_filtered("\t                bug - OEA + MOTO BUG ROM calls\n");
171
  printf_filtered("\t                netbsd - UEA + NetBSD system calls\n");
172
  printf_filtered("\t                solaris - UEA + Solaris system calls\n");
173
  printf_filtered("\t                linux - UEA + Linux system calls\n");
174
  printf_filtered("\t                chirp - OEA + a few OpenBoot calls\n");
175
  printf_filtered("\n"); }
176
 
177
  printf_filtered("\t-E <endian>     Specify the endianness of the target\n");
178
  if (verbose) {
179
  printf_filtered("\t                Can be any of the following:\n");
180
  printf_filtered("\t                big - big endian target\n");
181
  printf_filtered("\t                little - little endian target\n");
182
  printf_filtered("\n"); }
183
 
184
  printf_filtered("\t-f <file>       Merge <file> into the device tree\n");
185
  if (verbose) { printf_filtered("\n"); }
186
 
187
  printf_filtered("\t-h -? -H        give more detailed usage\n");
188
  if (verbose) { printf_filtered("\n"); }
189
 
190
  printf_filtered("\t-m <model>      Specify the processor to model (604)\n");
191
  if (verbose) {
192
  printf_filtered("\t                Selects the processor to use when\n");
193
  printf_filtered("\t                modeling execution units.  Includes:\n");
194
  printf_filtered("\t                604, 603 and 603e\n");
195
  printf_filtered("\n"); }
196
 
197
  printf_filtered("\t-n <nr-smp>     Specify the number of processors in SMP simulations\n");
198
  if (verbose) {
199
  printf_filtered("\t                Specifies the number of processors that are\n");
200
  printf_filtered("\t                to be modeled in a symetric multi-processor (SMP)\n");
201
  printf_filtered("\t                simulation\n");
202
  printf_filtered("\n"); }
203
 
204
  printf_filtered("\t-o <dev-spec>   Add device <dev-spec> to the device tree\n");
205
  if (verbose) { printf_filtered("\n"); }
206
 
207
  printf_filtered("\t-r <ram-size>   Set RAM size in bytes (OEA environments)\n");
208
  if (verbose) { printf_filtered("\n"); }
209
 
210
  printf_filtered("\t-t [!]<trace>   Enable (disable) <trace> option\n");
211
  if (verbose) { printf_filtered("\n"); }
212
 
213
  printf_filtered("\n");
214
  trace_usage(verbose);
215
  device_usage(verbose);
216
  if (verbose > 1) {
217
    printf_filtered("\n");
218
    print_options();
219
  }
220
 
221
  if (REPORT_BUGS_TO[0])
222
    printf ("Report bugs to %s\n", REPORT_BUGS_TO);
223
  exit (help ? 0 : 1);
224
}
225
 
226
/* Test "string" for containing a string of digits that form a number
227
between "min" and "max".  The return value is the number or "err". */
228
static
229
int is_num( char *string, int min, int max, int err)
230
{
231
  int result = 0;
232
 
233
  for ( ; *string; ++string)
234
  {
235
    if (!isdigit(*string))
236
    {
237
      result = err;
238
      break;
239
    }
240
    result = result * 10 + (*string - '0');
241
  }
242
  if (result < min || result > max)
243
    result = err;
244
 
245
  return result;
246
}
247
 
248
INLINE_PSIM\
249
(char **)
250
psim_options(device *root,
251
             char **argv)
252
{
253
  device *current = root;
254
  int argp;
255
  if (argv == NULL)
256
    return NULL;
257
  argp = 0;
258
  while (argv[argp] != NULL && argv[argp][0] == '-') {
259
    char *p = argv[argp] + 1;
260
    char *param;
261
    while (*p != '\0') {
262
      switch (*p) {
263
      default:
264
        psim_usage(0, 0);
265
        error ("");
266
        break;
267
      case 'c':
268
        param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
269
        tree_parse(root, "/openprom/options/max-iterations %s", param);
270
        break;
271
      case 'e':
272
        param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
273
        tree_parse(root, "/openprom/options/os-emul %s", param);
274
        break;
275
      case 'E':
276
        /* endian spec, ignored for now */
277
        param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
278
        if (strcmp (param, "big") == 0)
279
          tree_parse (root, "/options/little-endian? false");
280
        else if (strcmp (param, "little") == 0)
281
          tree_parse (root, "/options/little-endian? true");
282
        else
283
          {
284
            printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
285
            psim_usage (0, 0);
286
          }
287
        break;
288
      case 'f':
289
        param = find_arg("Missing <file> option for -f\n", &argp, argv);
290
        psim_merge_device_file(root, param);
291
        break;
292
      case 'h':
293
      case '?':
294
        psim_usage(1, 1);
295
        break;
296
      case 'H':
297
        psim_usage(2, 1);
298
        break;
299
      case 'i':
300
        if (isdigit(p[1])) {
301
          tree_parse(root, "/openprom/trace/print-info %c", p[1]);
302
          p++;
303
        }
304
        else {
305
          tree_parse(root, "/openprom/trace/print-info 1");
306
        }
307
        break;
308
      case 'I':
309
        tree_parse(root, "/openprom/trace/print-info 2");
310
        tree_parse(root, "/openprom/options/model-issue %d",
311
                   MODEL_ISSUE_PROCESS);
312
        break;
313
      case 'm':
314
        param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
315
        tree_parse(root, "/openprom/options/model \"%s", param);
316
        break;
317
      case 'n':
318
        param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
319
        tree_parse(root, "/openprom/options/smp %s", param);
320
        break;
321
      case 'o':
322
        param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
323
        if (memcmp(param, "mpc860c0", 8) == 0)
324
        {
325
          if (param[8] == '\0')
326
            tree_parse(root, "/options/mpc860c0 5");
327
          else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
328
          {
329
            tree_parse(root, "/options/mpc860c0 %s", param+9);
330
          }
331
          else error("Invalid mpc860c0 option for -o\n");
332
        }
333
        else
334
          current = tree_parse(current, "%s", param);
335
        break;
336
      case 'r':
337
        param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
338
        tree_parse(root, "/openprom/options/oea-memory-size %s",
339
                               param);
340
        break;
341
      case 't':
342
        param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
343
        if (param[0] == '!')
344
          tree_parse(root, "/openprom/trace/%s 0", param+1);
345
        else
346
          tree_parse(root, "/openprom/trace/%s 1", param);
347
        break;
348
      case '-':
349
        /* it's a long option of the form --optionname=optionvalue.
350
           Such options can be passed through if we are invoked by
351
           gdb.  */
352
        if (strstr(argv[argp], "architecture") != NULL) {
353
          /* we must consume the argument here, so that we get out
354
             of the loop.  */
355
          p = argv[argp] + strlen(argv[argp]) - 1;
356
          printf_filtered("Warning - architecture parameter ignored\n");
357
        }
358
        else if (strcmp (argv[argp], "--help") == 0)
359
          psim_usage (0, 1);
360
        else if (strcmp (argv[argp], "--version") == 0)
361
          {
362
            extern const char version[];
363
            printf ("GNU simulator %s%s\n", PKGVERSION, version);
364
            exit (0);
365
          }
366
        else
367
          error("Unrecognized option");
368
        break;
369
      }
370
      p += 1;
371
    }
372
    argp += 1;
373
  }
374
  /* force the trace node to process its options now *before* the tree
375
     initialization occures */
376
  device_ioctl(tree_find_device(root, "/openprom/trace"),
377
               NULL, 0,
378
               device_ioctl_set_trace);
379
 
380
  {
381
    void semantic_init(device* root);
382
    semantic_init(root);
383
  }
384
 
385
  /* return where the options end */
386
  return argv + argp;
387
}
388
 
389
INLINE_PSIM\
390
(void)
391
psim_command(device *root,
392
             char **argv)
393
{
394
  int argp = 0;
395
  if (argv[argp] == NULL) {
396
    return;
397
  }
398
  else if (strcmp(argv[argp], "trace") == 0) {
399
    const char *opt = find_arg("Missing <trace> option", &argp, argv);
400
    if (opt[0] == '!')
401
      trace_option(opt + 1, 0);
402
    else
403
      trace_option(opt, 1);
404
  }
405
  else if (strcmp(*argv, "change-media") == 0) {
406
    char *device = find_arg("Missing device name", &argp, argv);
407
    char *media = argv[++argp];
408
    device_ioctl(tree_find_device(root, device), NULL, 0,
409
                 device_ioctl_change_media, media);
410
  }
411
  else {
412
    printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
413
    printf_filtered("    trace <trace-option>\n");
414
    printf_filtered("    change-media <device> [ <new-image> ]\n");
415
  }
416
}
417
 
418
 
419
/* create the simulator proper from the device tree and executable */
420
 
421
INLINE_PSIM\
422
(psim *)
423
psim_create(const char *file_name,
424
            device *root)
425
{
426
  int cpu_nr;
427
  const char *env;
428
  psim *system;
429
  os_emul *os_emulation;
430
  int nr_cpus;
431
 
432
  /* given this partially populated device tree, os_emul_create() uses
433
     it and file_name to determine the selected emulation and hence
434
     further populate the tree with any other required nodes. */
435
 
436
  os_emulation = os_emul_create(file_name, root);
437
  if (os_emulation == NULL)
438
    error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
439
 
440
  /* fill in the missing real number of CPU's */
441
  nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
442
  if (MAX_NR_PROCESSORS < nr_cpus)
443
    error("target and configured number of cpus conflict\n");
444
 
445
  /* fill in the missing TARGET BYTE ORDER information */
446
  current_target_byte_order
447
    = (tree_find_boolean_property(root, "/options/little-endian?")
448
       ? LITTLE_ENDIAN
449
       : BIG_ENDIAN);
450
  if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
451
    error("target and configured byte order conflict\n");
452
 
453
  /* fill in the missing HOST BYTE ORDER information */
454
  current_host_byte_order = (current_host_byte_order = 1,
455
                             (*(char*)(&current_host_byte_order)
456
                              ? LITTLE_ENDIAN
457
                              : BIG_ENDIAN));
458
  if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
459
    error("host and configured byte order conflict\n");
460
 
461
  /* fill in the missing OEA/VEA information */
462
  env = tree_find_string_property(root, "/openprom/options/env");
463
  current_environment = ((strcmp(env, "user") == 0
464
                          || strcmp(env, "uea") == 0)
465
                         ? USER_ENVIRONMENT
466
                         : (strcmp(env, "virtual") == 0
467
                            || strcmp(env, "vea") == 0)
468
                         ? VIRTUAL_ENVIRONMENT
469
                         : (strcmp(env, "operating") == 0
470
                            || strcmp(env, "oea") == 0)
471
                         ? OPERATING_ENVIRONMENT
472
                         : 0);
473
  if (current_environment == 0)
474
    error("unreconized /options env property\n");
475
  if (CURRENT_ENVIRONMENT != current_environment)
476
    error("target and configured environment conflict\n");
477
 
478
  /* fill in the missing ALLIGNMENT information */
479
  current_alignment
480
    = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
481
       ? STRICT_ALIGNMENT
482
       : NONSTRICT_ALIGNMENT);
483
  if (CURRENT_ALIGNMENT != current_alignment)
484
    error("target and configured alignment conflict\n");
485
 
486
  /* fill in the missing FLOATING POINT information */
487
  current_floating_point
488
    = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
489
       ? HARD_FLOATING_POINT
490
       : SOFT_FLOATING_POINT);
491
  if (CURRENT_FLOATING_POINT != current_floating_point)
492
    error("target and configured floating-point conflict\n");
493
 
494
  /* fill in the missing STDIO information */
495
  current_stdio
496
    = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
497
       ? DO_USE_STDIO
498
       : DONT_USE_STDIO);
499
  if (CURRENT_STDIO != current_stdio)
500
    error("target and configured stdio interface conflict\n");
501
 
502
  /* sort out the level of detail for issue modeling */
503
  current_model_issue
504
    = tree_find_integer_property(root, "/openprom/options/model-issue");
505
  if (CURRENT_MODEL_ISSUE != current_model_issue)
506
    error("target and configured model-issue conflict\n");
507
 
508
  /* sort out our model architecture - wrong.
509
 
510
     FIXME: this should be obtaining the required information from the
511
     device tree via the "/chosen" property "cpu" which is an instance
512
     (ihandle) for the only executing processor. By converting that
513
     ihandle into the corresponding cpu's phandle and then querying
514
     the "name" property, the cpu type can be determined. Ok? */
515
 
516
  model_set(tree_find_string_property(root, "/openprom/options/model"));
517
 
518
  /* create things */
519
  system = ZALLOC(psim);
520
  system->events = event_queue_create();
521
  system->memory = core_from_device(root);
522
  system->monitor = mon_create();
523
  system->nr_cpus = nr_cpus;
524
  system->os_emulation = os_emulation;
525
  system->devices = root;
526
 
527
  /* now all the processors attaching to each their per-cpu information */
528
  for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
529
    system->processors[cpu_nr] = cpu_create(system,
530
                                            system->memory,
531
                                            mon_cpu(system->monitor,
532
                                                    cpu_nr),
533
                                            system->os_emulation,
534
                                            cpu_nr);
535
  }
536
 
537
  /* dump out the contents of the device tree */
538
  if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
539
    tree_print(root);
540
  if (ppc_trace[trace_dump_device_tree])
541
    error("");
542
 
543
  return system;
544
}
545
 
546
 
547
/* allow the simulation to stop/restart abnormaly */
548
 
549
INLINE_PSIM\
550
(void)
551
psim_set_halt_and_restart(psim *system,
552
                          void *halt_jmp_buf,
553
                          void *restart_jmp_buf)
554
{
555
  system->path_to_halt = halt_jmp_buf;
556
  system->path_to_restart = restart_jmp_buf;
557
}
558
 
559
INLINE_PSIM\
560
(void)
561
psim_clear_halt_and_restart(psim *system)
562
{
563
  system->path_to_halt = NULL;
564
  system->path_to_restart = NULL;
565
}
566
 
567
INLINE_PSIM\
568
(void)
569
psim_restart(psim *system,
570
             int current_cpu)
571
{
572
  ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
573
  ASSERT(system->path_to_restart != NULL);
574
  system->last_cpu = current_cpu;
575
  longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
576
}
577
 
578
 
579
static void
580
cntrl_c_simulation(void *data)
581
{
582
  psim *system = data;
583
  psim_halt(system,
584
            psim_nr_cpus(system),
585
            was_continuing,
586
            TARGET_SIGNAL_INT);
587
}
588
 
589
INLINE_PSIM\
590
(void)
591
psim_stop(psim *system)
592
{
593
  event_queue_schedule_after_signal(psim_event_queue(system),
594
 
595
                                    cntrl_c_simulation,
596
                                    system);
597
}
598
 
599
INLINE_PSIM\
600
(void)
601
psim_halt(psim *system,
602
          int current_cpu,
603
          stop_reason reason,
604
          int signal)
605
{
606
  ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
607
  ASSERT(system->path_to_halt != NULL);
608
  system->last_cpu = current_cpu;
609
  system->halt_status.reason = reason;
610
  system->halt_status.signal = signal;
611
  if (current_cpu == system->nr_cpus) {
612
    system->halt_status.cpu_nr = 0;
613
    system->halt_status.program_counter =
614
      cpu_get_program_counter(system->processors[0]);
615
  }
616
  else {
617
    system->halt_status.cpu_nr = current_cpu;
618
    system->halt_status.program_counter =
619
      cpu_get_program_counter(system->processors[current_cpu]);
620
  }
621
  longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
622
}
623
 
624
 
625
INLINE_PSIM\
626
(int)
627
psim_last_cpu(psim *system)
628
{
629
  return system->last_cpu;
630
}
631
 
632
INLINE_PSIM\
633
(int)
634
psim_nr_cpus(psim *system)
635
{
636
  return system->nr_cpus;
637
}
638
 
639
INLINE_PSIM\
640
(psim_status)
641
psim_get_status(psim *system)
642
{
643
  return system->halt_status;
644
}
645
 
646
 
647
INLINE_PSIM\
648
(cpu *)
649
psim_cpu(psim *system,
650
         int cpu_nr)
651
{
652
  if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
653
    return NULL;
654
  else
655
    return system->processors[cpu_nr];
656
}
657
 
658
 
659
INLINE_PSIM\
660
(device *)
661
psim_device(psim *system,
662
            const char *path)
663
{
664
  return tree_find_device(system->devices, path);
665
}
666
 
667
INLINE_PSIM\
668
(event_queue *)
669
psim_event_queue(psim *system)
670
{
671
  return system->events;
672
}
673
 
674
 
675
 
676
STATIC_INLINE_PSIM\
677
(void)
678
psim_max_iterations_exceeded(void *data)
679
{
680
  psim *system = data;
681
  psim_halt(system,
682
            system->nr_cpus, /* halted during an event */
683
            was_signalled,
684
            -1);
685
}
686
 
687
 
688
INLINE_PSIM\
689
(void)
690
psim_init(psim *system)
691
{
692
  int cpu_nr;
693
 
694
  /* scrub the monitor */
695
  mon_init(system->monitor, system->nr_cpus);
696
 
697
  /* trash any pending events */
698
  event_queue_init(system->events);
699
 
700
  /* if needed, schedule a halt event.  FIXME - In the future this
701
     will be replaced by a more generic change to psim_command().  A
702
     new command `schedule NNN halt' being added. */
703
  if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
704
    event_queue_schedule(system->events,
705
                         tree_find_integer_property(system->devices,
706
                                                    "/openprom/options/max-iterations") - 2,
707
                         psim_max_iterations_exceeded,
708
                         system);
709
  }
710
 
711
  /* scrub all the cpus */
712
  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
713
    cpu_init(system->processors[cpu_nr]);
714
 
715
  /* init all the devices (which updates the cpus) */
716
  tree_init(system->devices, system);
717
 
718
  /* and the emulation (which needs an initialized device tree) */
719
  os_emul_init(system->os_emulation, system->nr_cpus);
720
 
721
  /* now sync each cpu against the initialized state of its registers */
722
  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
723
    cpu *processor = system->processors[cpu_nr];
724
    cpu_synchronize_context(processor, cpu_get_program_counter(processor));
725
    cpu_page_tlb_invalidate_all(processor);
726
  }
727
 
728
  /* force loop to start with first cpu */
729
  system->last_cpu = -1;
730
}
731
 
732
INLINE_PSIM\
733
(void)
734
psim_stack(psim *system,
735
           char **argv,
736
           char **envp)
737
{
738
  /* pass the stack device the argv/envp and let it work out what to
739
     do with it */
740
  device *stack_device = tree_find_device(system->devices,
741
                                          "/openprom/init/stack");
742
  if (stack_device != (device*)0) {
743
    unsigned_word stack_pointer;
744
    ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
745
                               cooked_transfer) > 0);
746
    device_ioctl(stack_device,
747
                 NULL, /*cpu*/
748
                 0, /*cia*/
749
                 device_ioctl_create_stack,
750
                 stack_pointer,
751
                 argv,
752
                 envp);
753
  }
754
}
755
 
756
 
757
 
758
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
759
   thing */
760
 
761
INLINE_PSIM\
762
(void)
763
psim_step(psim *system)
764
{
765
  volatile int keep_running = 0;
766
  idecode_run_until_stop(system, &keep_running,
767
                         system->events, system->processors, system->nr_cpus);
768
}
769
 
770
INLINE_PSIM\
771
(void)
772
psim_run(psim *system)
773
{
774
  idecode_run(system,
775
              system->events, system->processors, system->nr_cpus);
776
}
777
 
778
 
779
/* storage manipulation functions */
780
 
781
INLINE_PSIM\
782
(int)
783
psim_read_register(psim *system,
784
                   int which_cpu,
785
                   void *buf,
786
                   const char reg[],
787
                   transfer_mode mode)
788
{
789
  register_descriptions description;
790
  char *cooked_buf;
791
  cpu *processor;
792
 
793
  /* find our processor */
794
  if (which_cpu == MAX_NR_PROCESSORS) {
795
    if (system->last_cpu == system->nr_cpus
796
        || system->last_cpu == -1)
797
      which_cpu = 0;
798
    else
799
      which_cpu = system->last_cpu;
800
  }
801
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
802
 
803
  processor = system->processors[which_cpu];
804
 
805
  /* find the register description */
806
  description = register_description(reg);
807
  if (description.type == reg_invalid)
808
    return 0;
809
  cooked_buf = alloca (description.size);
810
 
811
  /* get the cooked value */
812
  switch (description.type) {
813
 
814
  case reg_gpr:
815
    *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
816
    break;
817
 
818
  case reg_spr:
819
    *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
820
    break;
821
 
822
  case reg_sr:
823
    *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
824
    break;
825
 
826
  case reg_fpr:
827
    *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
828
    break;
829
 
830
  case reg_pc:
831
    *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
832
    break;
833
 
834
  case reg_cr:
835
    *(creg*)cooked_buf = cpu_registers(processor)->cr;
836
    break;
837
 
838
  case reg_msr:
839
    *(msreg*)cooked_buf = cpu_registers(processor)->msr;
840
    break;
841
 
842
  case reg_fpscr:
843
    *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
844
    break;
845
 
846
  case reg_insns:
847
    *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
848
                                                          which_cpu);
849
    break;
850
 
851
  case reg_stalls:
852
    if (cpu_model(processor) == NULL)
853
      error("$stalls only valid if processor unit model enabled (-I)\n");
854
    *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
855
    break;
856
 
857
  case reg_cycles:
858
    if (cpu_model(processor) == NULL)
859
      error("$cycles only valid if processor unit model enabled (-I)\n");
860
    *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
861
    break;
862
 
863
#ifdef WITH_ALTIVEC
864
  case reg_vr:
865
    *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
866
    break;
867
 
868
  case reg_vscr:
869
    *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
870
    break;
871
#endif
872
 
873
#ifdef WITH_E500
874
  case reg_gprh:
875
    *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
876
    break;
877
 
878
  case reg_evr:
879
    *(unsigned64*)cooked_buf = EVR(description.index);
880
    break;
881
 
882
  case reg_acc:
883
    *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
884
    break;
885
#endif
886
 
887
  default:
888
    printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
889
                    (unsigned long)processor, (unsigned long)buf, reg,
890
                    "read of this register unimplemented");
891
    break;
892
 
893
  }
894
 
895
  /* the PSIM internal values are in host order.  To fetch raw data,
896
     they need to be converted into target order and then returned */
897
  if (mode == raw_transfer) {
898
    /* FIXME - assumes that all registers are simple integers */
899
    switch (description.size) {
900
    case 1:
901
      *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
902
      break;
903
    case 2:
904
      *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
905
      break;
906
    case 4:
907
      *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
908
      break;
909
    case 8:
910
      *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
911
      break;
912
#ifdef WITH_ALTIVEC
913
    case 16:
914
      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
915
        {
916
          union { vreg v; unsigned_8 d[2]; } h, t;
917
          memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
918
          { _SWAP_8(t.d[0] =, h.d[1]); }
919
          { _SWAP_8(t.d[1] =, h.d[0]); }
920
          memcpy(buf/*dest*/, &t/*src*/, description.size);
921
          break;
922
        }
923
      else
924
        memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
925
      break;
926
#endif
927
    }
928
  }
929
  else {
930
    memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
931
  }
932
 
933
  return description.size;
934
}
935
 
936
 
937
 
938
INLINE_PSIM\
939
(int)
940
psim_write_register(psim *system,
941
                    int which_cpu,
942
                    const void *buf,
943
                    const char reg[],
944
                    transfer_mode mode)
945
{
946
  cpu *processor;
947
  register_descriptions description;
948
  char *cooked_buf;
949
 
950
  /* find our processor */
951
  if (which_cpu == MAX_NR_PROCESSORS) {
952
    if (system->last_cpu == system->nr_cpus
953
        || system->last_cpu == -1)
954
      which_cpu = 0;
955
    else
956
      which_cpu = system->last_cpu;
957
  }
958
 
959
  /* find the description of the register */
960
  description = register_description(reg);
961
  if (description.type == reg_invalid)
962
    return 0;
963
  cooked_buf = alloca (description.size);
964
 
965
  if (which_cpu == -1) {
966
    int i;
967
    for (i = 0; i < system->nr_cpus; i++)
968
      psim_write_register(system, i, buf, reg, mode);
969
    return description.size;
970
  }
971
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
972
 
973
  processor = system->processors[which_cpu];
974
 
975
  /* If the data is comming in raw (target order), need to cook it
976
     into host order before putting it into PSIM's internal structures */
977
  if (mode == raw_transfer) {
978
    switch (description.size) {
979
    case 1:
980
      *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
981
      break;
982
    case 2:
983
      *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
984
      break;
985
    case 4:
986
      *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
987
      break;
988
    case 8:
989
      *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
990
      break;
991
#ifdef WITH_ALTIVEC
992
    case 16:
993
      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
994
        {
995
          union { vreg v; unsigned_8 d[2]; } h, t;
996
          memcpy(&t.v/*dest*/, buf/*src*/, description.size);
997
          { _SWAP_8(h.d[0] =, t.d[1]); }
998
          { _SWAP_8(h.d[1] =, t.d[0]); }
999
          memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
1000
          break;
1001
        }
1002
      else
1003
        memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1004
#endif
1005
    }
1006
  }
1007
  else {
1008
    memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1009
  }
1010
 
1011
  /* put the cooked value into the register */
1012
  switch (description.type) {
1013
 
1014
  case reg_gpr:
1015
    cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
1016
    break;
1017
 
1018
  case reg_fpr:
1019
    cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
1020
    break;
1021
 
1022
  case reg_pc:
1023
    cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
1024
    break;
1025
 
1026
  case reg_spr:
1027
    cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
1028
    break;
1029
 
1030
  case reg_sr:
1031
    cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
1032
    break;
1033
 
1034
  case reg_cr:
1035
    cpu_registers(processor)->cr = *(creg*)cooked_buf;
1036
    break;
1037
 
1038
  case reg_msr:
1039
    cpu_registers(processor)->msr = *(msreg*)cooked_buf;
1040
    break;
1041
 
1042
  case reg_fpscr:
1043
    cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
1044
    break;
1045
 
1046
#ifdef WITH_E500
1047
  case reg_gprh:
1048
    cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
1049
    break;
1050
 
1051
  case reg_evr:
1052
    {
1053
      unsigned64 v;
1054
      v = *(unsigned64*)cooked_buf;
1055
      cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
1056
      cpu_registers(processor)->gpr[description.index] = v;
1057
      break;
1058
    }
1059
 
1060
  case reg_acc:
1061
    cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
1062
    break;
1063
#endif
1064
 
1065
#ifdef WITH_ALTIVEC
1066
  case reg_vr:
1067
    cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
1068
    break;
1069
 
1070
  case reg_vscr:
1071
    cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
1072
    break;
1073
#endif
1074
 
1075
  default:
1076
    printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1077
                    (unsigned long)processor, (unsigned long)cooked_buf, reg,
1078
                    "read of this register unimplemented");
1079
    break;
1080
 
1081
  }
1082
 
1083
  return description.size;
1084
}
1085
 
1086
 
1087
 
1088
INLINE_PSIM\
1089
(unsigned)
1090
psim_read_memory(psim *system,
1091
                 int which_cpu,
1092
                 void *buffer,
1093
                 unsigned_word vaddr,
1094
                 unsigned nr_bytes)
1095
{
1096
  cpu *processor;
1097
  if (which_cpu == MAX_NR_PROCESSORS) {
1098
    if (system->last_cpu == system->nr_cpus
1099
        || system->last_cpu == -1)
1100
      which_cpu = 0;
1101
    else
1102
      which_cpu = system->last_cpu;
1103
  }
1104
  processor = system->processors[which_cpu];
1105
  return vm_data_map_read_buffer(cpu_data_map(processor),
1106
                                 buffer, vaddr, nr_bytes,
1107
                                 NULL, -1);
1108
}
1109
 
1110
 
1111
INLINE_PSIM\
1112
(unsigned)
1113
psim_write_memory(psim *system,
1114
                  int which_cpu,
1115
                  const void *buffer,
1116
                  unsigned_word vaddr,
1117
                  unsigned nr_bytes,
1118
                  int violate_read_only_section)
1119
{
1120
  cpu *processor;
1121
  if (which_cpu == MAX_NR_PROCESSORS) {
1122
    if (system->last_cpu == system->nr_cpus
1123
        || system->last_cpu == -1)
1124
      which_cpu = 0;
1125
    else
1126
      which_cpu = system->last_cpu;
1127
  }
1128
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
1129
  processor = system->processors[which_cpu];
1130
  return vm_data_map_write_buffer(cpu_data_map(processor),
1131
                                  buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
1132
                                  NULL, -1);
1133
}
1134
 
1135
 
1136
INLINE_PSIM\
1137
(void)
1138
psim_print_info(psim *system,
1139
                int verbose)
1140
{
1141
  mon_print_info(system, system->monitor, verbose);
1142
}
1143
 
1144
 
1145
/* Merge a device tree and a device file. */
1146
 
1147
INLINE_PSIM\
1148
(void)
1149
psim_merge_device_file(device *root,
1150
                       const char *file_name)
1151
{
1152
  FILE *description;
1153
  int line_nr;
1154
  char device_path[1000];
1155
  device *current;
1156
 
1157
  /* try opening the file */
1158
  description = fopen(file_name, "r");
1159
  if (description == NULL) {
1160
    perror(file_name);
1161
    error("Invalid file %s specified", file_name);
1162
  }
1163
 
1164
  line_nr = 0;
1165
  current = root;
1166
  while (fgets(device_path, sizeof(device_path), description)) {
1167
    char *device;
1168
    /* check that the full line was read */
1169
    if (strchr(device_path, '\n') == NULL) {
1170
      fclose(description);
1171
      error("%s:%d: line to long - %s",
1172
            file_name, line_nr, device_path);
1173
    }
1174
    else
1175
      *strchr(device_path, '\n') = '\0';
1176
    line_nr++;
1177
    /* skip comments ("#" or ";") and blank lines lines */
1178
    for (device = device_path;
1179
         *device != '\0' && isspace(*device);
1180
         device++);
1181
    if (device[0] == '#'
1182
        || device[0] == ';'
1183
        || device[0] == '\0')
1184
      continue;
1185
    /* merge any appended lines */
1186
    while (device_path[strlen(device_path) - 1] == '\\') {
1187
      int curlen = strlen(device_path) - 1;
1188
      /* zap \ */
1189
      device_path[curlen] = '\0';
1190
      /* append the next line */
1191
      if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
1192
        fclose(description);
1193
        error("%s:%s: unexpected eof in line continuation - %s",
1194
              file_name, line_nr, device_path);
1195
      }
1196
      if (strchr(device_path, '\n') == NULL) {
1197
        fclose(description);
1198
        error("%s:%d: line to long - %s",
1199
            file_name, line_nr, device_path);
1200
      }
1201
      else
1202
        *strchr(device_path, '\n') = '\0';
1203
      line_nr++;
1204
    }
1205
    /* parse this line */
1206
    current = tree_parse(current, "%s", device);
1207
  }
1208
  fclose(description);
1209
}
1210
 
1211
 
1212
#endif /* _PSIM_C_ */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.