~ubuntu-branches/debian/jessie/gdb/jessie

« back to all changes in this revision

Viewing changes to sim/microblaze/interp.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Jacobowitz
  • Date: 2010-03-20 01:21:29 UTC
  • mfrom: (1.3.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20100320012129-t7h25y8zgr8c2369
Tags: 7.1-1
* New upstream release, including:
  - PIE support (Closes: #346409).
  - C++ improvements, including static_cast<> et al, namespace imports,
    and bug fixes in printing virtual base classes.
  - Multi-program debugging.  One GDB can now debug multiple programs
    at the same time.
  - Python scripting improvements, including gdb.parse_and_eval.
  - Updated MIPS Linux signal frame layout (Closes: #570875).
  - No internal error stepping over _dl_debug_state (Closes: #569551).
* Update to Standards-Version: 3.8.4 (no changes required).
* Include more relevant (and smaller) docs in the gdbserver package
  (Closes: #571132).
* Do not duplicate documentation in gdb64, gdb-source, and libgdb-dev.
* Fix crash when switching into TUI mode (Closes: #568489).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Simulator for Xilinx MicroBlaze processor
 
2
   Copyright 2009, 2010 Free Software Foundation, Inc.
 
3
 
 
4
   This file is part of GDB, the GNU debugger.
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 2 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
 
19
   02110-1301, USA.  */
 
20
 
 
21
#include <signal.h>
 
22
#include "sysdep.h"
 
23
#include <sys/times.h>
 
24
#include <sys/param.h>
 
25
#include <netinet/in.h> /* for byte ordering macros */
 
26
#include "bfd.h"
 
27
#include "gdb/callback.h"
 
28
#include "libiberty.h"
 
29
#include "gdb/remote-sim.h"
 
30
#include "sim-main.h"
 
31
#include "sim-utils.h"
 
32
#include "microblaze-dis.h"
 
33
 
 
34
 
 
35
#ifndef NUM_ELEM
 
36
#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
 
37
#endif
 
38
 
 
39
static int target_big_endian = 1;
 
40
static unsigned long heap_ptr = 0;
 
41
static unsigned long stack_ptr = 0;
 
42
host_callback *callback;
 
43
 
 
44
unsigned long
 
45
microblaze_extract_unsigned_integer (unsigned char *addr, int len)
 
46
{
 
47
  unsigned long retval;
 
48
  unsigned char *p;
 
49
  unsigned char *startaddr = (unsigned char *)addr;
 
50
  unsigned char *endaddr = startaddr + len;
 
51
 
 
52
  if (len > (int) sizeof (unsigned long))
 
53
    printf ("That operation is not available on integers of more than "
 
54
            "%d bytes.", sizeof (unsigned long));
 
55
 
 
56
  /* Start at the most significant end of the integer, and work towards
 
57
     the least significant.  */
 
58
  retval = 0;
 
59
 
 
60
  if (!target_big_endian)
 
61
    {
 
62
      for (p = endaddr; p > startaddr;)
 
63
        retval = (retval << 8) | * -- p;
 
64
    }
 
65
  else
 
66
    {
 
67
      for (p = startaddr; p < endaddr;)
 
68
        retval = (retval << 8) | * p ++;
 
69
    }
 
70
 
 
71
  return retval;
 
72
}
 
73
 
 
74
void
 
75
microblaze_store_unsigned_integer (unsigned char *addr, int len,
 
76
                                   unsigned long val)
 
77
{
 
78
  unsigned char *p;
 
79
  unsigned char *startaddr = (unsigned char *)addr;
 
80
  unsigned char *endaddr = startaddr + len;
 
81
 
 
82
  if (!target_big_endian)
 
83
    {
 
84
      for (p = startaddr; p < endaddr;)
 
85
        {
 
86
          *p++ = val & 0xff;
 
87
          val >>= 8;
 
88
        }
 
89
    }
 
90
  else
 
91
    {
 
92
      for (p = endaddr; p > startaddr;)
 
93
        {
 
94
          *--p = val & 0xff;
 
95
          val >>= 8;
 
96
        }
 
97
    }
 
98
}
 
99
 
 
100
struct sim_state microblaze_state;
 
101
 
 
102
int memcycles = 1;
 
103
 
 
104
static SIM_OPEN_KIND sim_kind;
 
105
static char *myname;
 
106
 
 
107
static int issue_messages = 0;
 
108
 
 
109
long
 
110
int_sbrk (int inc_bytes)
 
111
{
 
112
  long addr;
 
113
 
 
114
  addr = heap_ptr;
 
115
 
 
116
  heap_ptr += inc_bytes;
 
117
 
 
118
  if (issue_messages && heap_ptr > SP)
 
119
    fprintf (stderr, "Warning: heap_ptr overlaps stack!\n");
 
120
 
 
121
  return addr;
 
122
}
 
123
 
 
124
static void /* INLINE */
 
125
wbat (word x, word v)
 
126
{
 
127
  if (((uword)x) >= CPU.msize)
 
128
    {
 
129
      if (issue_messages)
 
130
        fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
 
131
 
 
132
      CPU.exception = SIGSEGV;
 
133
    }
 
134
  else
 
135
    {
 
136
      unsigned char *p = CPU.memory + x;
 
137
      p[0] = v;
 
138
    }
 
139
}
 
140
 
 
141
static void /* INLINE */
 
142
wlat (word x, word v)
 
143
{
 
144
  if (((uword)x) >= CPU.msize)
 
145
    {
 
146
      if (issue_messages)
 
147
        fprintf (stderr, "word write to 0x%x outside memory range\n", x);
 
148
 
 
149
      CPU.exception = SIGSEGV;
 
150
    }
 
151
  else
 
152
    {
 
153
      if ((x & 3) != 0)
 
154
        {
 
155
          if (issue_messages)
 
156
            fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
 
157
 
 
158
          CPU.exception = SIGBUS;
 
159
        }
 
160
      else if (!target_big_endian)
 
161
        {
 
162
          unsigned char *p = CPU.memory + x;
 
163
          p[3] = v >> 24;
 
164
          p[2] = v >> 16;
 
165
          p[1] = v >> 8;
 
166
          p[0] = v;
 
167
        }
 
168
      else
 
169
        {
 
170
          unsigned char *p = CPU.memory + x;
 
171
          p[0] = v >> 24;
 
172
          p[1] = v >> 16;
 
173
          p[2] = v >> 8;
 
174
          p[3] = v;
 
175
        }
 
176
    }
 
177
}
 
178
 
 
179
static void /* INLINE */
 
180
what (word x, word v)
 
181
{
 
182
  if (((uword)x) >= CPU.msize)
 
183
    {
 
184
      if (issue_messages)
 
185
        fprintf (stderr, "short write to 0x%x outside memory range\n", x);
 
186
 
 
187
      CPU.exception = SIGSEGV;
 
188
    }
 
189
  else
 
190
    {
 
191
      if ((x & 1) != 0)
 
192
        {
 
193
          if (issue_messages)
 
194
            fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
 
195
                     x);
 
196
 
 
197
          CPU.exception = SIGBUS;
 
198
        }
 
199
      else if (!target_big_endian)
 
200
        {
 
201
          unsigned char *p = CPU.memory + x;
 
202
          p[1] = v >> 8;
 
203
          p[0] = v;
 
204
        }
 
205
      else
 
206
        {
 
207
          unsigned char *p = CPU.memory + x;
 
208
          p[0] = v >> 8;
 
209
          p[1] = v;
 
210
        }
 
211
    }
 
212
}
 
213
 
 
214
/* Read functions.  */
 
215
static int /* INLINE */
 
216
rbat (word x)
 
217
{
 
218
  if (((uword)x) >= CPU.msize)
 
219
    {
 
220
      if (issue_messages)
 
221
        fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
 
222
 
 
223
      CPU.exception = SIGSEGV;
 
224
      return 0;
 
225
    }
 
226
  else
 
227
    {
 
228
      unsigned char *p = CPU.memory + x;
 
229
      return p[0];
 
230
    }
 
231
}
 
232
 
 
233
static int /* INLINE */
 
234
rlat (word x)
 
235
{
 
236
  if (((uword) x) >= CPU.msize)
 
237
    {
 
238
      if (issue_messages)
 
239
        fprintf (stderr, "word read from 0x%x outside memory range\n", x);
 
240
 
 
241
      CPU.exception = SIGSEGV;
 
242
      return 0;
 
243
    }
 
244
  else
 
245
    {
 
246
      if ((x & 3) != 0)
 
247
        {
 
248
          if (issue_messages)
 
249
            fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
 
250
 
 
251
          CPU.exception = SIGBUS;
 
252
          return 0;
 
253
        }
 
254
      else if (! target_big_endian)
 
255
        {
 
256
          unsigned char *p = CPU.memory + x;
 
257
          return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
 
258
        }
 
259
      else
 
260
        {
 
261
          unsigned char *p = CPU.memory + x;
 
262
          return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
 
263
        }
 
264
    }
 
265
}
 
266
 
 
267
static int /* INLINE */
 
268
rhat (word x)
 
269
{
 
270
  if (((uword)x) >= CPU.msize)
 
271
    {
 
272
      if (issue_messages)
 
273
        fprintf (stderr, "short read from 0x%x outside memory range\n", x);
 
274
 
 
275
      CPU.exception = SIGSEGV;
 
276
      return 0;
 
277
    }
 
278
  else
 
279
    {
 
280
      if ((x & 1) != 0)
 
281
        {
 
282
          if (issue_messages)
 
283
            fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
 
284
 
 
285
          CPU.exception = SIGBUS;
 
286
          return 0;
 
287
        }
 
288
      else if (!target_big_endian)
 
289
        {
 
290
          unsigned char *p = CPU.memory + x;
 
291
          return (p[1] << 8) | p[0];
 
292
        }
 
293
      else
 
294
        {
 
295
          unsigned char *p = CPU.memory + x;
 
296
          return (p[0] << 8) | p[1];
 
297
        }
 
298
    }
 
299
}
 
300
 
 
301
 
 
302
#define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
 
303
#define SEXTW(y) ((int)((short)y))
 
304
 
 
305
static int
 
306
IOMEM (int addr, int write, int value)
 
307
{
 
308
}
 
309
 
 
310
/* Default to a 8 Mbyte (== 2^23) memory space.  */
 
311
static int sim_memory_size = 1 << 23;
 
312
 
 
313
#define MEM_SIZE_FLOOR  64
 
314
void
 
315
sim_size (int size)
 
316
{
 
317
  sim_memory_size = size;
 
318
  CPU.msize = sim_memory_size;
 
319
 
 
320
  if (CPU.memory)
 
321
    free (CPU.memory);
 
322
 
 
323
  CPU.memory = (unsigned char *) calloc (1, CPU.msize);
 
324
 
 
325
  if (!CPU.memory)
 
326
    {
 
327
      if (issue_messages)
 
328
        fprintf (stderr,
 
329
                 "Not enough VM for simulation of %d bytes of RAM\n",
 
330
                 CPU.msize);
 
331
 
 
332
      CPU.msize = 1;
 
333
      CPU.memory = (unsigned char *) calloc (1, 1);
 
334
    }
 
335
}
 
336
 
 
337
static void
 
338
init_pointers ()
 
339
{
 
340
  if (CPU.msize != (sim_memory_size))
 
341
    sim_size (sim_memory_size);
 
342
}
 
343
 
 
344
static void
 
345
set_initial_gprs ()
 
346
{
 
347
  int i;
 
348
  long space;
 
349
  unsigned long memsize;
 
350
 
 
351
  init_pointers ();
 
352
 
 
353
  /* Set up machine just out of reset.  */
 
354
  PC = 0;
 
355
  MSR = 0;
 
356
 
 
357
  memsize = CPU.msize / (1024 * 1024);
 
358
 
 
359
  if (issue_messages > 1)
 
360
    fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
 
361
             memsize, CPU.msize - 1);
 
362
 
 
363
  /* Clean out the GPRs */
 
364
  for (i = 0; i < 32; i++)
 
365
    CPU.regs[i] = 0;
 
366
  CPU.insts = 0;
 
367
  CPU.cycles = 0;
 
368
  CPU.imm_enable = 0;
 
369
 
 
370
}
 
371
 
 
372
static void
 
373
interrupt ()
 
374
{
 
375
  CPU.exception = SIGINT;
 
376
}
 
377
 
 
378
/* Functions so that trapped open/close don't interfere with the
 
379
   parent's functions.  We say that we can't close the descriptors
 
380
   that we didn't open.  exit() and cleanup() get in trouble here,
 
381
   to some extent.  That's the price of emulation.  */
 
382
 
 
383
unsigned char opened[100];
 
384
 
 
385
static void
 
386
log_open (int fd)
 
387
{
 
388
  if (fd < 0 || fd > NUM_ELEM (opened))
 
389
    return;
 
390
 
 
391
  opened[fd] = 1;
 
392
}
 
393
 
 
394
static void
 
395
log_close (int fd)
 
396
{
 
397
  if (fd < 0 || fd > NUM_ELEM (opened))
 
398
    return;
 
399
 
 
400
  opened[fd] = 0;
 
401
}
 
402
 
 
403
static int
 
404
is_opened (int fd)
 
405
{
 
406
  if (fd < 0 || fd > NUM_ELEM (opened))
 
407
    return 0;
 
408
 
 
409
  return opened[fd];
 
410
}
 
411
 
 
412
static void
 
413
handle_trap1 ()
 
414
{
 
415
}
 
416
 
 
417
static void
 
418
process_stub (int what)
 
419
{
 
420
  /* These values should match those in libgloss/microblaze/syscalls.s.  */
 
421
  switch (what)
 
422
    {
 
423
    case 3:  /* _read */
 
424
    case 4:  /* _write */
 
425
    case 5:  /* _open */
 
426
    case 6:  /* _close */
 
427
    case 10: /* _unlink */
 
428
    case 19: /* _lseek */
 
429
    case 43: /* _times */
 
430
      handle_trap1 ();
 
431
      break;
 
432
 
 
433
    default:
 
434
      if (issue_messages)
 
435
        fprintf (stderr, "Unhandled stub opcode: %d\n", what);
 
436
      break;
 
437
    }
 
438
}
 
439
 
 
440
static void
 
441
util (unsigned what)
 
442
{
 
443
  switch (what)
 
444
    {
 
445
    case 0:     /* exit */
 
446
      CPU.exception = SIGQUIT;
 
447
      break;
 
448
 
 
449
    case 1:     /* printf */
 
450
      {
 
451
        unsigned long a[6];
 
452
        unsigned char *s;
 
453
        int i;
 
454
 
 
455
        for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++)
 
456
          if (*s == '%')
 
457
            i++;
 
458
      }
 
459
      break;
 
460
 
 
461
    case 2:     /* scanf */
 
462
      if (issue_messages)
 
463
        fprintf (stderr, "WARNING: scanf unimplemented\n");
 
464
      break;
 
465
 
 
466
    case 3:     /* utime */
 
467
      break;
 
468
 
 
469
    case 0xFF:
 
470
      process_stub (CPU.regs[1]);
 
471
      break;
 
472
 
 
473
    default:
 
474
      if (issue_messages)
 
475
        fprintf (stderr, "Unhandled util code: %x\n", what);
 
476
      break;
 
477
    }
 
478
}
 
479
 
 
480
/* For figuring out whether we carried; addc/subc use this. */
 
481
static int
 
482
iu_carry (unsigned long a, unsigned long b, int cin)
 
483
{
 
484
  unsigned long x;
 
485
 
 
486
  x = (a & 0xffff) + (b & 0xffff) + cin;
 
487
  x = (x >> 16) + (a >> 16) + (b >> 16);
 
488
  x >>= 16;
 
489
 
 
490
  return (x != 0);
 
491
}
 
492
 
 
493
#define WATCHFUNCTIONS 1
 
494
#ifdef WATCHFUNCTIONS
 
495
 
 
496
#define MAXWL 80
 
497
word WL[MAXWL];
 
498
char *WLstr[MAXWL];
 
499
 
 
500
int ENDWL=0;
 
501
int WLincyc;
 
502
int WLcyc[MAXWL];
 
503
int WLcnts[MAXWL];
 
504
int WLmax[MAXWL];
 
505
int WLmin[MAXWL];
 
506
word WLendpc;
 
507
int WLbcyc;
 
508
int WLW;
 
509
#endif
 
510
 
 
511
static int tracing = 0;
 
512
 
 
513
void
 
514
sim_resume (SIM_DESC sd, int step, int siggnal)
 
515
{
 
516
  int needfetch;
 
517
  word inst;
 
518
  enum microblaze_instr op;
 
519
  void (*sigsave)();
 
520
  int memops;
 
521
  int bonus_cycles;
 
522
  int insts;
 
523
  int w;
 
524
  int cycs;
 
525
  word WLhash;
 
526
  ubyte carry;
 
527
  int imm_unsigned;
 
528
  short ra, rb, rd;
 
529
  long immword;
 
530
  uword oldpc, newpc;
 
531
  short delay_slot_enable;
 
532
  short branch_taken;
 
533
  short num_delay_slot; /* UNUSED except as reqd parameter */
 
534
  enum microblaze_instr_type insn_type;
 
535
 
 
536
  sigsave = signal (SIGINT, interrupt);
 
537
  CPU.exception = step ? SIGTRAP : 0;
 
538
 
 
539
  memops = 0;
 
540
  bonus_cycles = 0;
 
541
  insts = 0;
 
542
  
 
543
  do
 
544
    {
 
545
      /* Fetch the initial instructions that we'll decode. */
 
546
      inst = rlat (PC & 0xFFFFFFFC);
 
547
 
 
548
      op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, 
 
549
                                &num_delay_slot);
 
550
 
 
551
      if (op == invalid_inst)
 
552
        fprintf (stderr, "Unknown instruction 0x%04x", inst);
 
553
 
 
554
      if (tracing)
 
555
        fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
 
556
 
 
557
      rd = GET_RD;
 
558
      rb = GET_RB;
 
559
      ra = GET_RA;
 
560
      /*      immword = IMM_W; */
 
561
 
 
562
      oldpc = PC;
 
563
      delay_slot_enable = 0;
 
564
      branch_taken = 0;
 
565
      if (op == microblaze_brk)
 
566
        CPU.exception = SIGTRAP;
 
567
      else if (inst == MICROBLAZE_HALT_INST)
 
568
        {
 
569
          CPU.exception = SIGQUIT;
 
570
          insts += 1;
 
571
          bonus_cycles++;
 
572
        }
 
573
      else
 
574
        {
 
575
          switch(op)
 
576
            {
 
577
#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION)         \
 
578
            case NAME:                                  \
 
579
              ACTION;                                   \
 
580
              break;
 
581
#include "microblaze.isa"
 
582
#undef INSTRUCTION
 
583
 
 
584
            default:
 
585
              CPU.exception = SIGILL;
 
586
              fprintf (stderr, "ERROR: Unknown opcode\n");
 
587
            }
 
588
          /* Make R0 consistent */
 
589
          CPU.regs[0] = 0;
 
590
 
 
591
          /* Check for imm instr */
 
592
          if (op == imm)
 
593
            IMM_ENABLE = 1;
 
594
          else
 
595
            IMM_ENABLE = 0;
 
596
 
 
597
          /* Update cycle counts */
 
598
          insts ++;
 
599
          if (insn_type == memory_store_inst || insn_type == memory_load_inst)
 
600
            memops++;
 
601
          if (insn_type == mult_inst)
 
602
            bonus_cycles++;
 
603
          if (insn_type == barrel_shift_inst)
 
604
            bonus_cycles++;
 
605
          if (insn_type == anyware_inst)
 
606
            bonus_cycles++;
 
607
          if (insn_type == div_inst)
 
608
            bonus_cycles += 33;
 
609
 
 
610
          if ((insn_type == branch_inst || insn_type == return_inst)
 
611
              && branch_taken) 
 
612
            {
 
613
              /* Add an extra cycle for taken branches */
 
614
              bonus_cycles++;
 
615
              /* For branch instructions handle the instruction in the delay slot */
 
616
              if (delay_slot_enable) 
 
617
                {
 
618
                  newpc = PC;
 
619
                  PC = oldpc + INST_SIZE;
 
620
                  inst = rlat (PC & 0xFFFFFFFC);
 
621
                  op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
 
622
                                            &num_delay_slot);
 
623
                  if (op == invalid_inst)
 
624
                    fprintf (stderr, "Unknown instruction 0x%04x", inst);
 
625
                  if (tracing)
 
626
                    fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
 
627
                  rd = GET_RD;
 
628
                  rb = GET_RB;
 
629
                  ra = GET_RA;
 
630
                  /*          immword = IMM_W; */
 
631
                  if (op == microblaze_brk)
 
632
                    {
 
633
                      if (issue_messages)
 
634
                        fprintf (stderr, "Breakpoint set in delay slot "
 
635
                                 "(at address 0x%x) will not be honored\n", PC);
 
636
                      /* ignore the breakpoint */
 
637
                    }
 
638
                  else if (insn_type == branch_inst || insn_type == return_inst)
 
639
                    {
 
640
                      if (issue_messages)
 
641
                        fprintf (stderr, "Cannot have branch or return instructions "
 
642
                                 "in delay slot (at address 0x%x)\n", PC);
 
643
                      CPU.exception = SIGILL;
 
644
                    }
 
645
                  else
 
646
                    {
 
647
                      switch(op)
 
648
                        {
 
649
#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION)         \
 
650
                        case NAME:                      \
 
651
                          ACTION;                       \
 
652
                          break;
 
653
#include "microblaze.isa"
 
654
#undef INSTRUCTION
 
655
 
 
656
                        default:
 
657
                          CPU.exception = SIGILL;
 
658
                          fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
 
659
                        }
 
660
                      /* Update cycle counts */
 
661
                      insts++;
 
662
                      if (insn_type == memory_store_inst
 
663
                          || insn_type == memory_load_inst) 
 
664
                        memops++;
 
665
                      if (insn_type == mult_inst)
 
666
                        bonus_cycles++;
 
667
                      if (insn_type == barrel_shift_inst)
 
668
                        bonus_cycles++;
 
669
                      if (insn_type == anyware_inst)
 
670
                        bonus_cycles++;
 
671
                      if (insn_type == div_inst)
 
672
                        bonus_cycles += 33;
 
673
                    }
 
674
                  /* Restore the PC */
 
675
                  PC = newpc;
 
676
                  /* Make R0 consistent */
 
677
                  CPU.regs[0] = 0;
 
678
                  /* Check for imm instr */
 
679
                  if (op == imm)
 
680
                    IMM_ENABLE = 1;
 
681
                  else
 
682
                    IMM_ENABLE = 0;
 
683
                }
 
684
              else
 
685
                /* no delay slot: increment cycle count */
 
686
                bonus_cycles++;
 
687
            }
 
688
        }
 
689
 
 
690
      if (tracing)
 
691
        fprintf (stderr, "\n");
 
692
    }
 
693
  while (!CPU.exception);
 
694
 
 
695
  /* Hide away the things we've cached while executing.  */
 
696
  /*  CPU.pc = pc; */
 
697
  CPU.insts += insts;           /* instructions done ... */
 
698
  CPU.cycles += insts;          /* and each takes a cycle */
 
699
  CPU.cycles += bonus_cycles;   /* and extra cycles for branches */
 
700
  CPU.cycles += memops;         /* and memop cycle delays */
 
701
 
 
702
  signal (SIGINT, sigsave);
 
703
}
 
704
 
 
705
 
 
706
int
 
707
sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
 
708
{
 
709
  int i;
 
710
  init_pointers ();
 
711
 
 
712
  memcpy (&CPU.memory[addr], buffer, size);
 
713
 
 
714
  return size;
 
715
}
 
716
 
 
717
int
 
718
sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
 
719
{
 
720
  int i;
 
721
  init_pointers ();
 
722
 
 
723
  memcpy (buffer, &CPU.memory[addr], size);
 
724
 
 
725
  return size;
 
726
}
 
727
 
 
728
 
 
729
int
 
730
sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
 
731
{
 
732
  init_pointers ();
 
733
 
 
734
  if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
 
735
    {
 
736
      if (length == 4)
 
737
        {
 
738
          /* misalignment safe */
 
739
          long ival = microblaze_extract_unsigned_integer (memory, 4);
 
740
          if (rn < NUM_REGS)
 
741
            CPU.regs[rn] = ival;
 
742
          else
 
743
            CPU.spregs[rn-NUM_REGS] = ival;
 
744
          return 4;
 
745
        }
 
746
      else
 
747
        return 0;
 
748
    }
 
749
  else
 
750
    return 0;
 
751
}
 
752
 
 
753
int
 
754
sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
 
755
{
 
756
  long ival;
 
757
  init_pointers ();
 
758
 
 
759
  if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
 
760
    {
 
761
      if (length == 4)
 
762
        {
 
763
          if (rn < NUM_REGS)
 
764
            ival = CPU.regs[rn];
 
765
          else
 
766
            ival = CPU.spregs[rn-NUM_REGS];
 
767
 
 
768
          /* misalignment-safe */
 
769
          microblaze_store_unsigned_integer (memory, 4, ival);
 
770
          return 4;
 
771
        }
 
772
      else
 
773
        return 0;
 
774
    }
 
775
  else
 
776
    return 0;
 
777
}
 
778
 
 
779
 
 
780
int
 
781
sim_trace (SIM_DESC sd)
 
782
{
 
783
  tracing = 1;
 
784
 
 
785
  sim_resume (sd, 0, 0);
 
786
 
 
787
  tracing = 0;
 
788
 
 
789
  return 1;
 
790
}
 
791
 
 
792
void
 
793
sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
 
794
{
 
795
  if (CPU.exception == SIGQUIT)
 
796
    {
 
797
      *reason = sim_exited;
 
798
      *sigrc = RETREG;
 
799
    }
 
800
  else
 
801
    {
 
802
      *reason = sim_stopped;
 
803
      *sigrc = CPU.exception;
 
804
    }
 
805
}
 
806
 
 
807
 
 
808
int
 
809
sim_stop (SIM_DESC sd)
 
810
{
 
811
  CPU.exception = SIGINT;
 
812
  return 1;
 
813
}
 
814
 
 
815
 
 
816
void
 
817
sim_info (SIM_DESC sd, int verbose)
 
818
{
 
819
#ifdef WATCHFUNCTIONS
 
820
  int w, wcyc;
 
821
#endif
 
822
 
 
823
  callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n",
 
824
                             CPU.insts);
 
825
  callback->printf_filtered (callback, "# cycles                 %10d\n",
 
826
                             (CPU.cycles) ? CPU.cycles+2 : 0);
 
827
 
 
828
#ifdef WATCHFUNCTIONS
 
829
  callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
 
830
                             ENDWL);
 
831
 
 
832
  wcyc = 0;
 
833
 
 
834
  for (w = 1; w <= ENDWL; w++)
 
835
    {
 
836
      callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
 
837
      callback->printf_filtered (callback, "  calls = %d, cycles = %d\n",
 
838
                                 WLcnts[w],WLcyc[w]);
 
839
 
 
840
      if (WLcnts[w] != 0)
 
841
        callback->printf_filtered (callback,
 
842
                                   "  maxcpc = %d, mincpc = %d, avecpc = %d\n",
 
843
                                   WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
 
844
      wcyc += WLcyc[w];
 
845
    }
 
846
 
 
847
  callback->printf_filtered (callback,
 
848
                             "Total cycles for watched functions: %d\n",wcyc);
 
849
#endif
 
850
}
 
851
 
 
852
struct  aout
 
853
{
 
854
  unsigned char  sa_machtype[2];
 
855
  unsigned char  sa_magic[2];
 
856
  unsigned char  sa_tsize[4];
 
857
  unsigned char  sa_dsize[4];
 
858
  unsigned char  sa_bsize[4];
 
859
  unsigned char  sa_syms[4];
 
860
  unsigned char  sa_entry[4];
 
861
  unsigned char  sa_trelo[4];
 
862
  unsigned char  sa_drelo[4];
 
863
} aout;
 
864
 
 
865
#define LONG(x)         (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
 
866
#define SHORT(x)        (((x)[0]<<8)|(x)[1])
 
867
 
 
868
SIM_DESC
 
869
sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
 
870
{
 
871
  /*  SIM_DESC sd = sim_state_alloc(kind, alloc);*/
 
872
 
 
873
  int osize = sim_memory_size;
 
874
  myname = argv[0];
 
875
  callback = cb;
 
876
 
 
877
  if (kind == SIM_OPEN_STANDALONE)
 
878
    issue_messages = 1;
 
879
 
 
880
  /* Discard and reacquire memory -- start with a clean slate.  */
 
881
  sim_size (1);         /* small */
 
882
  sim_size (osize);     /* and back again */
 
883
 
 
884
  set_initial_gprs ();  /* Reset the GPR registers.  */
 
885
 
 
886
  return ((SIM_DESC) 1);
 
887
}
 
888
 
 
889
void
 
890
sim_close (SIM_DESC sd, int quitting)
 
891
{
 
892
  if (CPU.memory)
 
893
    {
 
894
      free(CPU.memory);
 
895
      CPU.memory = NULL;
 
896
      CPU.msize = 0;
 
897
    }
 
898
}
 
899
 
 
900
SIM_RC
 
901
sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
 
902
{
 
903
  /* Do the right thing for ELF executables; this turns out to be
 
904
     just about the right thing for any object format that:
 
905
       - we crack using BFD routines
 
906
       - follows the traditional UNIX text/data/bss layout
 
907
       - calls the bss section ".bss".   */
 
908
 
 
909
  extern bfd *sim_load_file (); /* ??? Don't know where this should live.  */
 
910
  bfd *prog_bfd;
 
911
 
 
912
  {
 
913
    bfd *handle;
 
914
    asection *s;
 
915
    int found_loadable_section = 0;
 
916
    bfd_vma max_addr = 0;
 
917
    handle = bfd_openr (prog, 0);
 
918
 
 
919
    if (!handle)
 
920
      {
 
921
        printf("``%s'' could not be opened.\n", prog);
 
922
        return SIM_RC_FAIL;
 
923
      }
 
924
 
 
925
    /* Makes sure that we have an object file, also cleans gets the
 
926
       section headers in place.  */
 
927
    if (!bfd_check_format (handle, bfd_object))
 
928
      {
 
929
        /* wasn't an object file */
 
930
        bfd_close (handle);
 
931
        printf ("``%s'' is not appropriate object file.\n", prog);
 
932
        return SIM_RC_FAIL;
 
933
      }
 
934
 
 
935
    for (s = handle->sections; s; s = s->next)
 
936
      {
 
937
        if (s->flags & SEC_ALLOC)
 
938
          {
 
939
            bfd_vma vma = 0;
 
940
            int size = bfd_get_section_size (s);
 
941
            if (size > 0)
 
942
              {
 
943
                vma = bfd_section_vma (handle, s);
 
944
                if (vma >= max_addr)
 
945
                  {
 
946
                    max_addr = vma + size;
 
947
                  }
 
948
              }
 
949
            if (s->flags & SEC_LOAD)
 
950
              found_loadable_section = 1;
 
951
          }
 
952
      }
 
953
 
 
954
    if (!found_loadable_section)
 
955
      {
 
956
        /* No loadable sections */
 
957
        bfd_close(handle);
 
958
        printf("No loadable sections in file %s\n", prog);
 
959
        return SIM_RC_FAIL;
 
960
      }
 
961
 
 
962
    sim_memory_size = (unsigned long) max_addr;
 
963
 
 
964
    /* Clean up after ourselves.  */
 
965
    bfd_close (handle);
 
966
 
 
967
  }
 
968
 
 
969
  /* from sh -- dac */
 
970
  prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
 
971
                            /* sim_kind == SIM_OPEN_DEBUG, */
 
972
                            1,
 
973
                            0, sim_write);
 
974
  if (prog_bfd == NULL)
 
975
    return SIM_RC_FAIL;
 
976
 
 
977
  target_big_endian = bfd_big_endian (prog_bfd);
 
978
  PC = bfd_get_start_address (prog_bfd);
 
979
 
 
980
  if (abfd == NULL)
 
981
    bfd_close (prog_bfd);
 
982
 
 
983
  return SIM_RC_OK;
 
984
}
 
985
 
 
986
SIM_RC
 
987
sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
 
988
{
 
989
  char **avp;
 
990
  int nargs = 0;
 
991
  int nenv = 0;
 
992
  int s_length;
 
993
  int l;
 
994
  unsigned long strings;
 
995
  unsigned long pointers;
 
996
  unsigned long hi_stack;
 
997
 
 
998
 
 
999
  /* Set the initial register set.  */
 
1000
  l = issue_messages;
 
1001
  issue_messages = 0;
 
1002
  set_initial_gprs ();
 
1003
  issue_messages = l;
 
1004
 
 
1005
  hi_stack = CPU.msize - 4;
 
1006
  PC = bfd_get_start_address (prog_bfd);
 
1007
 
 
1008
  /* For now ignore all parameters to the program */
 
1009
 
 
1010
  return SIM_RC_OK;
 
1011
}
 
1012
 
 
1013
void
 
1014
sim_kill (SIM_DESC sd)
 
1015
{
 
1016
  /* nothing to do */
 
1017
}
 
1018
 
 
1019
void
 
1020
sim_do_command (SIM_DESC sd, char * cmd)
 
1021
{
 
1022
  /* Nothing there yet; it's all an error.  */
 
1023
 
 
1024
  if (cmd != NULL)
 
1025
    {
 
1026
      char ** simargv = buildargv (cmd);
 
1027
 
 
1028
      if (strcmp (simargv[0], "watch") == 0)
 
1029
        {
 
1030
          if ((simargv[1] == NULL) || (simargv[2] == NULL))
 
1031
            {
 
1032
              fprintf (stderr, "Error: missing argument to watch cmd.\n");
 
1033
              return;
 
1034
            }
 
1035
 
 
1036
          ENDWL++;
 
1037
 
 
1038
          WL[ENDWL] = strtol (simargv[2], NULL, 0);
 
1039
          WLstr[ENDWL] = strdup (simargv[1]);
 
1040
          fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
 
1041
                   WL[ENDWL], ENDWL);
 
1042
 
 
1043
        }
 
1044
      else if (strcmp (simargv[0], "dumpmem") == 0)
 
1045
        {
 
1046
          unsigned char * p;
 
1047
          FILE * dumpfile;
 
1048
 
 
1049
          if (simargv[1] == NULL)
 
1050
            fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
 
1051
 
 
1052
          fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
 
1053
 
 
1054
          dumpfile = fopen (simargv[1], "w");
 
1055
          p = CPU.memory;
 
1056
          fwrite (p, CPU.msize-1, 1, dumpfile);
 
1057
          fclose (dumpfile);
 
1058
 
 
1059
          fprintf (stderr, "done.\n");
 
1060
        }
 
1061
      else if (strcmp (simargv[0], "clearstats") == 0)
 
1062
        {
 
1063
          CPU.cycles = 0;
 
1064
          CPU.insts = 0;
 
1065
          ENDWL = 0;
 
1066
        }
 
1067
      else if (strcmp (simargv[0], "verbose") == 0)
 
1068
        {
 
1069
          issue_messages = 2;
 
1070
        }
 
1071
      else
 
1072
        {
 
1073
          fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
 
1074
                   cmd);
 
1075
        }
 
1076
    }
 
1077
  else
 
1078
    {
 
1079
      fprintf (stderr, "M.CORE sim commands: \n");
 
1080
      fprintf (stderr, "  watch <funcname> <addr>\n");
 
1081
      fprintf (stderr, "  dumpmem <filename>\n");
 
1082
      fprintf (stderr, "  clearstats\n");
 
1083
      fprintf (stderr, "  verbose\n");
 
1084
    }
 
1085
}
 
1086
 
 
1087
void
 
1088
sim_set_callbacks (host_callback *ptr)
 
1089
{
 
1090
  callback = ptr;
 
1091
}