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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [common/] [sim-utils.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 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
  bfd_cache_close (prog_bfd);
291
 
292
  return SIM_RC_OK;
293
}
294
 
295
/* Simulator timing support.  */
296
 
297
/* Called before sim_elapsed_time_since to get a reference point.  */
298
 
299
SIM_ELAPSED_TIME
300
sim_elapsed_time_get ()
301
{
302
#ifdef HAVE_GETRUSAGE
303
  struct rusage mytime;
304
  if (getrusage (RUSAGE_SELF, &mytime) == 0)
305
    return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000));
306
  return 1;
307
#else
308
#ifdef HAVE_TIME
309
  return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0);
310
#else
311
  return 1;
312
#endif
313
#endif
314
}
315
 
316
/* Return the elapsed time in milliseconds since START.
317
   The actual time may be cpu usage (prefered) or wall clock.  */
318
 
319
unsigned long
320
sim_elapsed_time_since (start)
321
     SIM_ELAPSED_TIME start;
322
{
323
#ifdef HAVE_GETRUSAGE
324
  return sim_elapsed_time_get () - start;
325
#else
326
#ifdef HAVE_TIME
327
  return (sim_elapsed_time_get () - start) * 1000;
328
#else
329
  return 0;
330
#endif
331
#endif
332
}
333
 
334
 
335
 
336
/* do_command but with printf style formatting of the arguments */
337
void
338
sim_do_commandf (SIM_DESC sd,
339
                 const char *fmt,
340
                 ...)
341
{
342
  va_list ap;
343
  char *buf;
344
  va_start (ap, fmt);
345
  vasprintf (&buf, fmt, ap);
346
  sim_do_command (sd, buf);
347
  va_end (ap);
348
  free (buf);
349
}
350
 
351
 
352
/* sim-basics.h defines a number of enumerations, convert each of them
353
   to a string representation */
354
const char *
355
map_to_str (unsigned map)
356
{
357
  switch (map)
358
    {
359
    case read_map: return "read";
360
    case write_map: return "write";
361
    case exec_map: return "exec";
362
    case io_map: return "io";
363
    default:
364
      {
365
        static char str[10];
366
        sprintf (str, "(%ld)", (long) map);
367
        return str;
368
      }
369
    }
370
}
371
 
372
const char *
373
access_to_str (unsigned access)
374
{
375
  switch (access)
376
    {
377
    case access_invalid: return "invalid";
378
    case access_read: return "read";
379
    case access_write: return "write";
380
    case access_exec: return "exec";
381
    case access_io: return "io";
382
    case access_read_write: return "read_write";
383
    case access_read_exec: return "read_exec";
384
    case access_write_exec: return "write_exec";
385
    case access_read_write_exec: return "read_write_exec";
386
    case access_read_io: return "read_io";
387
    case access_write_io: return "write_io";
388
    case access_read_write_io: return "read_write_io";
389
    case access_exec_io: return "exec_io";
390
    case access_read_exec_io: return "read_exec_io";
391
    case access_write_exec_io: return "write_exec_io";
392
    case access_read_write_exec_io: return "read_write_exec_io";
393
    default:
394
      {
395
        static char str[10];
396
        sprintf (str, "(%ld)", (long) access);
397
        return str;
398
      }
399
    }
400
}
401
 
402
const char *
403
transfer_to_str (unsigned transfer)
404
{
405
  switch (transfer)
406
    {
407
    case read_transfer: return "read";
408
    case write_transfer: return "write";
409
    default: return "(error)";
410
    }
411
}
412
 
413
 

powered by: WebSVN 2.1.0

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