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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [sim/] [common/] [sim-utils.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* Miscellaneous simulator utilities.
2
   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3
   Contributed by Cygnus Support.
4
 
5
This file is part of GDB, the GNU debugger.
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License along
18
with this program; if not, write to the Free Software Foundation, Inc.,
19
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include "sim-main.h"
22
#include "sim-assert.h"
23
 
24
#ifdef HAVE_STDLIB_H
25
#include <stdlib.h>
26
#endif
27
 
28
#ifdef HAVE_TIME_H
29
#include <time.h>
30
#endif
31
 
32
#ifdef HAVE_SYS_TIME_H
33
#include <sys/time.h> /* needed by sys/resource.h */
34
#endif
35
 
36
#ifdef HAVE_SYS_RESOURCE_H
37
#include <sys/resource.h>
38
#endif
39
 
40
#ifdef HAVE_STRING_H
41
#include <string.h>
42
#else
43
#ifdef HAVE_STRINGS_H
44
#include <strings.h>
45
#endif
46
#endif
47
 
48
#include "libiberty.h"
49
#include "bfd.h"
50
#include "sim-utils.h"
51
 
52
/* Global pointer to all state data.
53
   Set by sim_resume.  */
54
struct sim_state *current_state;
55
 
56
/* Allocate zero filled memory with xmalloc - xmalloc aborts of the
57
   allocation fails.  */
58
 
59
void *
60
zalloc (unsigned long size)
61
{
62
  void *memory = (void *) xmalloc (size);
63
  memset (memory, 0, size);
64
  return memory;
65
}
66
 
67
void
68
zfree (void *data)
69
{
70
  free (data);
71
}
72
 
73
/* Allocate a sim_state struct.  */
74
 
75
SIM_DESC
76
sim_state_alloc (SIM_OPEN_KIND kind,
77
                 host_callback *callback)
78
{
79
  SIM_DESC sd = ZALLOC (struct sim_state);
80
 
81
  STATE_MAGIC (sd) = SIM_MAGIC_NUMBER;
82
  STATE_CALLBACK (sd) = callback;
83
  STATE_OPEN_KIND (sd) = kind;
84
 
85
#if 0
86
  {
87
    int cpu_nr;
88
 
89
    /* Initialize the back link from the cpu struct to the state struct.  */
90
    /* ??? I can envision a design where the state struct contains an array
91
       of pointers to cpu structs, rather than an array of structs themselves.
92
       Implementing this is trickier as one may not know what to allocate until
93
       one has parsed the args.  Parsing the args twice wouldn't be unreasonable,
94
       IMHO.  If the state struct ever does contain an array of pointers then we
95
       can't do this here.
96
       ??? See also sim_post_argv_init*/
97
    for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
98
      {
99
        CPU_STATE (STATE_CPU (sd, cpu_nr)) = sd;
100
        CPU_INDEX (STATE_CPU (sd, cpu_nr)) = cpu_nr;
101
      }
102
  }
103
#endif
104
 
105
#ifdef SIM_STATE_INIT
106
  SIM_STATE_INIT (sd);
107
#endif
108
 
109
  return sd;
110
}
111
 
112
/* Free a sim_state struct.  */
113
 
114
void
115
sim_state_free (SIM_DESC sd)
116
{
117
  ASSERT (sd->base.magic == SIM_MAGIC_NUMBER);
118
 
119
#ifdef SIM_STATE_FREE
120
  SIM_STATE_FREE (sd);
121
#endif
122
 
123
  zfree (sd);
124
}
125
 
126
/* Return a pointer to the cpu data for CPU_NAME, or NULL if not found.  */
127
 
128
sim_cpu *
129
sim_cpu_lookup (SIM_DESC sd, const char *cpu_name)
130
{
131
  int i;
132
 
133
  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
134
    if (strcmp (cpu_name, CPU_NAME (STATE_CPU (sd, i))) == 0)
135
      return STATE_CPU (sd, i);
136
  return NULL;
137
}
138
 
139
/* Return the prefix to use for a CPU specific message (typically an
140
   error message).  */
141
 
142
const char *
143
sim_cpu_msg_prefix (sim_cpu *cpu)
144
{
145
#if MAX_NR_PROCESSORS == 1
146
  return "";
147
#else
148
  static char *prefix;
149
 
150
  if (prefix == NULL)
151
    {
152
      int maxlen = 0;
153
      for (i = 0; i < MAX_NR_PROCESSORS; ++i)
154
        {
155
          int len = strlen (CPU_NAME (STATE_CPU (sd, i)));
156
          if (len > maxlen)
157
            maxlen = len;
158
        }
159
      prefix = (char *) xmalloc (maxlen + 5);
160
    }
161
  sprintf (prefix, "%s: ", CPU_NAME (cpu));
162
  return prefix;
163
#endif
164
}
165
 
166
/* Cover fn to sim_io_eprintf.  */
167
 
168
void
169
sim_io_eprintf_cpu (sim_cpu *cpu, const char *fmt, ...)
170
{
171
  SIM_DESC sd = CPU_STATE (cpu);
172
  va_list ap;
173
 
174
  va_start (ap, fmt);
175
  sim_io_eprintf (sd, sim_cpu_msg_prefix (cpu));
176
  sim_io_evprintf (sd, fmt, ap);
177
  va_end (ap);
178
}
179
 
180
/* Turn VALUE into a string with commas.  */
181
 
182
char *
183
sim_add_commas (char *buf, int sizeof_buf, unsigned long value)
184
{
185
  int comma = 3;
186
  char *endbuf = buf + sizeof_buf - 1;
187
 
188
  *--endbuf = '\0';
189
  do {
190
    if (comma-- == 0)
191
      {
192
        *--endbuf = ',';
193
        comma = 2;
194
      }
195
 
196
    *--endbuf = (value % 10) + '0';
197
  } while ((value /= 10) != 0);
198
 
199
  return endbuf;
200
}
201
 
202
/* Analyze PROG_NAME/PROG_BFD and set these fields in the state struct:
203
   STATE_ARCHITECTURE, if not set already and can be determined from the bfd
204
   STATE_PROG_BFD
205
   STATE_START_ADDR
206
   STATE_TEXT_SECTION
207
   STATE_TEXT_START
208
   STATE_TEXT_END
209
 
210
   PROG_NAME is the file name of the executable or NULL.
211
   PROG_BFD is its bfd or NULL.
212
 
213
   If both PROG_NAME and PROG_BFD are NULL, this function returns immediately.
214
   If PROG_BFD is not NULL, PROG_NAME is ignored.
215
 
216
   Implicit inputs: STATE_MY_NAME(sd), STATE_TARGET(sd),
217
                    STATE_ARCHITECTURE(sd).
218
 
219
   A new bfd is created so the app isn't required to keep its copy of the
220
   bfd open.  */
221
 
222
SIM_RC
223
sim_analyze_program (sd, prog_name, prog_bfd)
224
     SIM_DESC sd;
225
     char *prog_name;
226
     bfd *prog_bfd;
227
{
228
  asection *s;
229
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
230
 
231
  if (prog_bfd != NULL)
232
    {
233
      if (prog_bfd == STATE_PROG_BFD (sd))
234
        /* already analyzed */
235
        return SIM_RC_OK;
236
      else
237
        /* duplicate needed, save the name of the file to be re-opened */
238
        prog_name = bfd_get_filename (prog_bfd);
239
    }
240
 
241
  /* do we need to duplicate anything? */
242
  if (prog_name == NULL)
243
    return SIM_RC_OK;
244
 
245
  /* open a new copy of the prog_bfd */
246
  prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd));
247
  if (prog_bfd == NULL)
248
    {
249
      sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n",
250
                      STATE_MY_NAME (sd),
251
                      prog_name,
252
                      bfd_errmsg (bfd_get_error ()));
253
      return SIM_RC_FAIL;
254
    }
255
  if (!bfd_check_format (prog_bfd, bfd_object))
256
    {
257
      sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n",
258
                      STATE_MY_NAME (sd),
259
                      prog_name,
260
                      bfd_errmsg (bfd_get_error ()));
261
      bfd_close (prog_bfd);
262
      return SIM_RC_FAIL;
263
    }
264
  if (STATE_ARCHITECTURE (sd) != NULL)
265
    bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd));
266
  else
267
    {
268
      if (bfd_get_arch (prog_bfd) != bfd_arch_unknown
269
          && bfd_get_arch (prog_bfd) != bfd_arch_obscure)
270
        {
271
          STATE_ARCHITECTURE (sd) = bfd_get_arch_info (prog_bfd);
272
        }
273
    }
274
 
275
  /* update the sim structure */
276
  if (STATE_PROG_BFD (sd) != NULL)
277
    bfd_close (STATE_PROG_BFD (sd));
278
  STATE_PROG_BFD (sd) = prog_bfd;
279
  STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd);
280
 
281
  for (s = prog_bfd->sections; s; s = s->next)
282
    if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0)
283
      {
284
        STATE_TEXT_SECTION (sd) = s;
285
        STATE_TEXT_START (sd) = bfd_get_section_vma (prog_bfd, s);
286
        STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (prog_bfd, s);
287
        break;
288
      }
289
 
290
  return SIM_RC_OK;
291
}
292
 
293
/* Simulator timing support.  */
294
 
295
/* Called before sim_elapsed_time_since to get a reference point.  */
296
 
297
SIM_ELAPSED_TIME
298
sim_elapsed_time_get ()
299
{
300
#ifdef HAVE_GETRUSAGE
301
  struct rusage mytime;
302
  if (getrusage (RUSAGE_SELF, &mytime) == 0)
303
    return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000));
304
  return 1;
305
#else
306
#ifdef HAVE_TIME
307
  return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0);
308
#else
309
  return 1;
310
#endif
311
#endif
312
}
313
 
314
/* Return the elapsed time in milliseconds since START.
315
   The actual time may be cpu usage (prefered) or wall clock.  */
316
 
317
unsigned long
318
sim_elapsed_time_since (start)
319
     SIM_ELAPSED_TIME start;
320
{
321
#ifdef HAVE_GETRUSAGE
322
  return sim_elapsed_time_get () - start;
323
#else
324
#ifdef HAVE_TIME
325
  return (sim_elapsed_time_get () - start) * 1000;
326
#else
327
  return 0;
328
#endif
329
#endif
330
}
331
 
332
 
333
 
334
/* do_command but with printf style formatting of the arguments */
335
void
336
sim_do_commandf (SIM_DESC sd,
337
                 const char *fmt,
338
                 ...)
339
{
340
  va_list ap;
341
  char *buf;
342
  va_start (ap, fmt);
343
  vasprintf (&buf, fmt, ap);
344
  sim_do_command (sd, buf);
345
  va_end (ap);
346
  free (buf);
347
}
348
 
349
 
350
/* sim-basics.h defines a number of enumerations, convert each of them
351
   to a string representation */
352
const char *
353
map_to_str (unsigned map)
354
{
355
  switch (map)
356
    {
357
    case read_map: return "read";
358
    case write_map: return "write";
359
    case exec_map: return "exec";
360
    case io_map: return "io";
361
    default:
362
      {
363
        static char str[10];
364
        sprintf (str, "(%ld)", (long) map);
365
        return str;
366
      }
367
    }
368
}
369
 
370
const char *
371
access_to_str (unsigned access)
372
{
373
  switch (access)
374
    {
375
    case access_invalid: return "invalid";
376
    case access_read: return "read";
377
    case access_write: return "write";
378
    case access_exec: return "exec";
379
    case access_io: return "io";
380
    case access_read_write: return "read_write";
381
    case access_read_exec: return "read_exec";
382
    case access_write_exec: return "write_exec";
383
    case access_read_write_exec: return "read_write_exec";
384
    case access_read_io: return "read_io";
385
    case access_write_io: return "write_io";
386
    case access_read_write_io: return "read_write_io";
387
    case access_exec_io: return "exec_io";
388
    case access_read_exec_io: return "read_exec_io";
389
    case access_write_exec_io: return "write_exec_io";
390
    case access_read_write_exec_io: return "read_write_exec_io";
391
    default:
392
      {
393
        static char str[10];
394
        sprintf (str, "(%ld)", (long) access);
395
        return str;
396
      }
397
    }
398
}
399
 
400
const char *
401
transfer_to_str (unsigned transfer)
402
{
403
  switch (transfer)
404
    {
405
    case read_transfer: return "read";
406
    case write_transfer: return "write";
407
    default: return "(error)";
408
    }
409
}
410
 
411
 

powered by: WebSVN 2.1.0

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