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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [sim/] [ppc/] [psim.c] - Blame information for rev 106

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

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

powered by: WebSVN 2.1.0

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