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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [sim/] [ppc/] [psim.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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