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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [ppc/] [psim.c] - Blame information for rev 438

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

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

powered by: WebSVN 2.1.0

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