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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [common/] [sim-watch.c] - Blame information for rev 816

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

Line No. Rev Author Line
1 24 jeremybenn
/* Generic simulator watchpoint support.
2
   Copyright (C) 1997, 2007, 2008 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 3 of the License, or
10
(at your option) 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
18
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "sim-main.h"
21
#include "sim-options.h"
22
 
23
#include "sim-assert.h"
24
 
25
#include <ctype.h>
26
 
27
#ifdef HAVE_STRING_H
28
#include <string.h>
29
#else
30
#ifdef HAVE_STRINGS_H
31
#include <strings.h>
32
#endif
33
#endif
34
 
35
#ifdef HAVE_STDLIB_H
36
#include <stdlib.h>
37
#endif
38
 
39
enum {
40
  OPTION_WATCH_DELETE                      = OPTION_START,
41
 
42
  OPTION_WATCH_INFO,
43
  OPTION_WATCH_CLOCK,
44
  OPTION_WATCH_CYCLES,
45
  OPTION_WATCH_PC,
46
 
47
  OPTION_WATCH_OP,
48
};
49
 
50
 
51
/* Break an option number into its op/int-nr */
52
static watchpoint_type
53
option_to_type (SIM_DESC sd,
54
                int option)
55
{
56
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
57
  watchpoint_type type = ((option - OPTION_WATCH_OP)
58
                          / (watch->nr_interrupts + 1));
59
  SIM_ASSERT (type >= 0 && type < nr_watchpoint_types);
60
  return type;
61
}
62
 
63
static int
64
option_to_interrupt_nr (SIM_DESC sd,
65
                        int option)
66
{
67
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
68
  int interrupt_nr = ((option - OPTION_WATCH_OP)
69
                      % (watch->nr_interrupts + 1));
70
  return interrupt_nr;
71
}
72
 
73
static int
74
type_to_option (SIM_DESC sd,
75
                watchpoint_type type,
76
                int interrupt_nr)
77
{
78
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
79
  return ((type * (watch->nr_interrupts + 1))
80
          + interrupt_nr
81
          + OPTION_WATCH_OP);
82
}
83
 
84
 
85
/* Delete one or more watchpoints.  Fail if no watchpoints were found */
86
 
87
static SIM_RC
88
do_watchpoint_delete (SIM_DESC sd,
89
                      int ident,
90
                      watchpoint_type type)
91
{
92
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
93
  sim_watch_point **entry = &watch->points;
94
  SIM_RC status = SIM_RC_FAIL;
95
  while ((*entry) != NULL)
96
    {
97
      if ((*entry)->ident == ident
98
          || (*entry)->type == type)
99
        {
100
          sim_watch_point *dead = (*entry);
101
          (*entry) = (*entry)->next;
102
          sim_events_deschedule (sd, dead->event);
103
          zfree (dead);
104
          status = SIM_RC_OK;
105
        }
106
      else
107
        entry = &(*entry)->next;
108
    }
109
  return status;
110
}
111
 
112
static char *
113
watchpoint_type_to_str (SIM_DESC sd,
114
                        watchpoint_type type)
115
{
116
  switch (type)
117
    {
118
    case  pc_watchpoint:
119
      return "pc";
120
    case clock_watchpoint:
121
      return "clock";
122
    case cycles_watchpoint:
123
      return "cycles";
124
    case invalid_watchpoint:
125
    case nr_watchpoint_types:
126
      return "(invalid-type)";
127
    }
128
  return NULL;
129
}
130
 
131
static char *
132
interrupt_nr_to_str (SIM_DESC sd,
133
                     int interrupt_nr)
134
{
135
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
136
  if (interrupt_nr < 0)
137
    return "(invalid-interrupt)";
138
  else if (interrupt_nr >= watch->nr_interrupts)
139
    return "breakpoint";
140
  else
141
    return watch->interrupt_names[interrupt_nr];
142
}
143
 
144
 
145
static void
146
do_watchpoint_info (SIM_DESC sd)
147
{
148
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
149
  sim_watch_point *point;
150
  sim_io_printf (sd, "Watchpoints:\n");
151
  for (point = watch->points; point != NULL; point = point->next)
152
    {
153
      sim_io_printf (sd, "%3d: watch %s %s ",
154
                     point->ident,
155
                     watchpoint_type_to_str (sd, point->type),
156
                     interrupt_nr_to_str (sd, point->interrupt_nr));
157
      if (point->is_periodic)
158
        sim_io_printf (sd, "+");
159
      if (!point->is_within)
160
        sim_io_printf (sd, "!");
161
      sim_io_printf (sd, "0x%lx", point->arg0);
162
      if (point->arg1 != point->arg0)
163
        sim_io_printf (sd, ",0x%lx", point->arg1);
164
      sim_io_printf (sd, "\n");
165
    }
166
}
167
 
168
 
169
 
170
static sim_event_handler handle_watchpoint;
171
 
172
static SIM_RC
173
schedule_watchpoint (SIM_DESC sd,
174
                     sim_watch_point *point)
175
{
176
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
177
  switch (point->type)
178
    {
179
    case pc_watchpoint:
180
      point->event = sim_events_watch_sim (sd,
181
                                           watch->pc,
182
                                           watch->sizeof_pc,
183
                                           0/* host-endian */,
184
                                           point->is_within,
185
                                           point->arg0, point->arg1,
186
                                           /* PC in arg0..arg1 */
187
                                           handle_watchpoint,
188
                                           point);
189
      return SIM_RC_OK;
190
    case clock_watchpoint:
191
      point->event = sim_events_watch_clock (sd,
192
                                             point->arg0, /* ms time */
193
                                             handle_watchpoint,
194
                                             point);
195
      return SIM_RC_OK;
196
    case cycles_watchpoint:
197
      point->event = sim_events_schedule (sd,
198
                                          point->arg0, /* time */
199
                                          handle_watchpoint,
200
                                          point);
201
      return SIM_RC_OK;
202
    default:
203
      sim_engine_abort (sd, NULL, NULL_CIA,
204
                        "handle_watchpoint - internal error - bad switch");
205
      return SIM_RC_FAIL;
206
    }
207
  return SIM_RC_OK;
208
}
209
 
210
 
211
static void
212
handle_watchpoint (SIM_DESC sd, void *data)
213
{
214
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
215
  sim_watch_point *point = (sim_watch_point *) data;
216
  int interrupt_nr = point->interrupt_nr;
217
 
218
  if (point->is_periodic)
219
    /* reschedule this event before processing it */
220
    schedule_watchpoint (sd, point);
221
  else
222
    do_watchpoint_delete (sd, point->ident, invalid_watchpoint);
223
 
224
  if (point->interrupt_nr == watch->nr_interrupts)
225
    sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
226
  else
227
    watch->interrupt_handler (sd, &watch->interrupt_names[interrupt_nr]);
228
}
229
 
230
 
231
static SIM_RC
232
do_watchpoint_create (SIM_DESC sd,
233
                      watchpoint_type type,
234
                      int opt,
235
                      char *arg)
236
{
237
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
238
  sim_watch_point **point;
239
 
240
  /* create the watchpoint */
241
  point = &watch->points;
242
  while ((*point) != NULL)
243
    point = &(*point)->next;
244
  (*point) = ZALLOC (sim_watch_point);
245
 
246
  /* fill in the details */
247
  (*point)->ident = ++(watch->last_point_nr);
248
  (*point)->type = option_to_type (sd, opt);
249
  (*point)->interrupt_nr = option_to_interrupt_nr (sd, opt);
250
  /* prefixes to arg - +== periodic, !==not or outside */
251
  (*point)->is_within = 1;
252
  while (1)
253
    {
254
      if (arg[0] == '+')
255
        (*point)->is_periodic = 1;
256
      else if (arg[0] == '!')
257
        (*point)->is_within = 0;
258
      else
259
        break;
260
      arg++;
261
    }
262
 
263
  (*point)->arg0 = strtoul (arg, &arg, 0);
264
  if (arg[0] == ',')
265
    (*point)->arg0 = strtoul (arg, NULL, 0);
266
  else
267
    (*point)->arg1 = (*point)->arg0;
268
 
269
  /* schedule it */
270
  schedule_watchpoint (sd, (*point));
271
 
272
  return SIM_RC_OK;
273
}
274
 
275
 
276
static SIM_RC
277
watchpoint_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
278
                           char *arg, int is_command)
279
{
280
  if (opt >= OPTION_WATCH_OP)
281
    return do_watchpoint_create (sd, clock_watchpoint, opt, arg);
282
  else
283
    switch (opt)
284
      {
285
 
286
      case OPTION_WATCH_DELETE:
287
        if (isdigit ((int) arg[0]))
288
          {
289
            int ident = strtol (arg, NULL, 0);
290
            if (do_watchpoint_delete (sd, ident, invalid_watchpoint)
291
                != SIM_RC_OK)
292
              {
293
                sim_io_eprintf (sd, "Watchpoint %d not found\n", ident);
294
                return SIM_RC_FAIL;
295
              }
296
            return SIM_RC_OK;
297
          }
298
        else if (strcasecmp (arg, "all") == 0)
299
          {
300
            watchpoint_type type;
301
            for (type = invalid_watchpoint + 1;
302
                 type < nr_watchpoint_types;
303
                 type++)
304
              {
305
                do_watchpoint_delete (sd, 0, type);
306
              }
307
            return SIM_RC_OK;
308
          }
309
        else if (strcasecmp (arg, "pc") == 0)
310
          {
311
            if (do_watchpoint_delete (sd, 0, pc_watchpoint)
312
                != SIM_RC_OK)
313
              {
314
                sim_io_eprintf (sd, "No PC watchpoints found\n");
315
                return SIM_RC_FAIL;
316
              }
317
            return SIM_RC_OK;
318
          }
319
        else if (strcasecmp (arg, "clock") == 0)
320
          {
321
            if (do_watchpoint_delete (sd, 0, clock_watchpoint) != SIM_RC_OK)
322
              {
323
                sim_io_eprintf (sd, "No CLOCK watchpoints found\n");
324
                return SIM_RC_FAIL;
325
              }
326
            return SIM_RC_OK;
327
          }
328
        else if (strcasecmp (arg, "cycles") == 0)
329
          {
330
            if (do_watchpoint_delete (sd, 0, cycles_watchpoint) != SIM_RC_OK)
331
              {
332
                sim_io_eprintf (sd, "No CYCLES watchpoints found\n");
333
                return SIM_RC_FAIL;
334
              }
335
            return SIM_RC_OK;
336
          }
337
        sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg);
338
        return SIM_RC_FAIL;
339
 
340
      case OPTION_WATCH_INFO:
341
        {
342
          do_watchpoint_info (sd);
343
          return SIM_RC_OK;
344
        }
345
 
346
      default:
347
        sim_io_eprintf (sd, "Unknown watch option %d\n", opt);
348
        return SIM_RC_FAIL;
349
 
350
      }
351
 
352
}
353
 
354
 
355
static SIM_RC
356
sim_watchpoint_init (SIM_DESC sd)
357
{
358
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
359
  sim_watch_point *point;
360
  /* NOTE: Do not need to de-schedule any previous watchpoints as
361
     sim-events has already done this */
362
  /* schedule any watchpoints enabled by command line options */
363
  for (point = watch->points; point != NULL; point = point->next)
364
    {
365
      schedule_watchpoint (sd, point);
366
    }
367
  return SIM_RC_OK;
368
}
369
 
370
 
371
static const OPTION watchpoint_options[] =
372
{
373
  { {"watch-delete", required_argument, NULL, OPTION_WATCH_DELETE },
374
      '\0', "IDENT|all|pc|cycles|clock", "Delete a watchpoint",
375
      watchpoint_option_handler },
376
 
377
  { {"watch-info", no_argument, NULL, OPTION_WATCH_INFO },
378
      '\0', NULL, "List scheduled watchpoints",
379
      watchpoint_option_handler },
380
 
381
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
382
};
383
 
384
static char *default_interrupt_names[] = { "int", 0, };
385
 
386
 
387
 
388
SIM_RC
389
sim_watchpoint_install (SIM_DESC sd)
390
{
391
  sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
392
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
393
  /* the basic command set */
394
  sim_module_add_init_fn (sd, sim_watchpoint_init);
395
  sim_add_option_table (sd, NULL, watchpoint_options);
396
  /* fill in some details */
397
  if (watch->interrupt_names == NULL)
398
    watch->interrupt_names = default_interrupt_names;
399
  watch->nr_interrupts = 0;
400
  while (watch->interrupt_names[watch->nr_interrupts] != NULL)
401
    watch->nr_interrupts++;
402
  /* generate more advansed commands */
403
  {
404
    OPTION *int_options = NZALLOC (OPTION, 1 + (watch->nr_interrupts + 1) * nr_watchpoint_types);
405
    int interrupt_nr;
406
    for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++)
407
      {
408
        watchpoint_type type;
409
        for (type = 0; type < nr_watchpoint_types; type++)
410
          {
411
            char *name;
412
            int nr = interrupt_nr * nr_watchpoint_types + type;
413
            OPTION *option = &int_options[nr];
414
            asprintf (&name, "watch-%s-%s",
415
                      watchpoint_type_to_str (sd, type),
416
                      interrupt_nr_to_str (sd, interrupt_nr));
417
            option->opt.name = name;
418
            option->opt.has_arg = required_argument;
419
            option->opt.val = type_to_option (sd, type, interrupt_nr);
420
            option->doc = "";
421
            option->doc_name = "";
422
            option->handler = watchpoint_option_handler;
423
          }
424
      }
425
    /* adjust first few entries so that they contain real
426
       documentation, the first entry includes a list of actions. */
427
    {
428
      char *prefix =
429
        "Watch the simulator, take ACTION in COUNT cycles (`+' for every COUNT cycles), ACTION is";
430
      char *doc;
431
      int len = strlen (prefix) + 1;
432
      for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++)
433
        len += strlen (interrupt_nr_to_str (sd, interrupt_nr)) + 1;
434
      doc = NZALLOC (char, len);
435
      strcpy (doc, prefix);
436
      for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++)
437
        {
438
          strcat (doc, " ");
439
          strcat (doc, interrupt_nr_to_str (sd, interrupt_nr));
440
        }
441
      int_options[0].doc_name = "watch-cycles-ACTION";
442
      int_options[0].arg = "[+]COUNT";
443
      int_options[0].doc = doc;
444
    }
445
    int_options[1].doc_name = "watch-pc-ACTION";
446
    int_options[1].arg = "[!]ADDRESS";
447
    int_options[1].doc =
448
      "Watch the PC, take ACTION when matches ADDRESS (in range ADDRESS,ADDRESS), `!' negates test";
449
    int_options[2].doc_name = "watch-clock-ACTION";
450
    int_options[2].arg = "[+]MILLISECONDS";
451
    int_options[2].doc =
452
      "Watch the clock, take ACTION after MILLISECONDS (`+' for every MILLISECONDS)";
453
 
454
    sim_add_option_table (sd, NULL, int_options);
455
  }
456
  return SIM_RC_OK;
457
}

powered by: WebSVN 2.1.0

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