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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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