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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [gdbtk/] [generic/] [gdbtk-register.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Tcl/Tk command definitions for Insight - Registers
2
   Copyright 2001 Free Software Foundation, Inc.
3
 
4
   This file is part of GDB.
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., 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
20
 
21
#include "defs.h"
22
#include "frame.h"
23
#include "value.h"
24
 
25
#include <tcl.h>
26
#include "gdbtk.h"
27
#include "gdbtk-cmds.h"
28
 
29
/* This contains the previous values of the registers, since the last call to
30
   gdb_changed_register_list.  */
31
 
32
static char *old_regs;
33
 
34
static int gdb_changed_register_list (ClientData, Tcl_Interp *, int,
35
                                      Tcl_Obj * CONST[]);
36
static int gdb_fetch_registers (ClientData, Tcl_Interp *, int,
37
                                Tcl_Obj * CONST[]);
38
static int gdb_regnames (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
39
static int get_pc_register (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]);
40
static void get_register (int, void *);
41
static void get_register_name (int, void *);
42
static int map_arg_registers (int, Tcl_Obj * CONST[],
43
                              void (*)(int, void *), void *);
44
static void register_changed_p (int, void *);
45
static void setup_architecture_data (void);
46
 
47
int
48
Gdbtk_Register_Init (Tcl_Interp *interp)
49
{
50
  Tcl_CreateObjCommand (interp, "gdb_changed_register_list", gdbtk_call_wrapper,
51
                        gdb_changed_register_list, NULL);
52
  Tcl_CreateObjCommand (interp, "gdb_fetch_registers", gdbtk_call_wrapper,
53
                        gdb_fetch_registers, NULL);
54
  Tcl_CreateObjCommand (interp, "gdb_regnames", gdbtk_call_wrapper, gdb_regnames,
55
                        NULL);
56
  Tcl_CreateObjCommand (interp, "gdb_pc_reg", gdbtk_call_wrapper, get_pc_register,
57
                        NULL);
58
 
59
  /* Register/initialize any architecture specific data */
60
  setup_architecture_data ();
61
  register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL);
62
  register_gdbarch_swap (NULL, 0, setup_architecture_data);
63
 
64
  return TCL_OK;
65
}
66
 
67
/* This implements the tcl command "gdb_changed_register_list"
68
 * It takes a list of registers, and returns a list of
69
 * the registers on that list that have changed since the last
70
 * time the proc was called.
71
 *
72
 * Tcl Arguments:
73
 *    A list of registers.
74
 * Tcl Result:
75
 *    A list of changed registers.
76
 */
77
static int
78
gdb_changed_register_list (clientData, interp, objc, objv)
79
     ClientData clientData;
80
     Tcl_Interp *interp;
81
     int objc;
82
     Tcl_Obj *CONST objv[];
83
{
84
  objc--;
85
  objv++;
86
 
87
  return map_arg_registers (objc, objv, register_changed_p, NULL);
88
}
89
 
90
/* This implements the tcl command gdb_fetch_registers
91
 * Pass it a list of register names, and it will
92
 * return their values as a list.
93
 *
94
 * Tcl Arguments:
95
 *    format: The format string for printing the values
96
 *    args: the registers to look for
97
 * Tcl Result:
98
 *    A list of their values.
99
 */
100
static int
101
gdb_fetch_registers (clientData, interp, objc, objv)
102
     ClientData clientData;
103
     Tcl_Interp *interp;
104
     int objc;
105
     Tcl_Obj *CONST objv[];
106
{
107
  int format, result;
108
 
109
  if (objc < 2)
110
    {
111
      Tcl_WrongNumArgs (interp, 1, objv, "format ?register1 register2 ...?");
112
      return TCL_ERROR;
113
    }
114
  objc -= 2;
115
  objv++;
116
  format = *(Tcl_GetStringFromObj (objv[0], NULL));
117
  objv++;
118
 
119
  if (objc != 1)
120
    result_ptr->flags |= GDBTK_MAKES_LIST;    /* Output the results as a list */
121
  result = map_arg_registers (objc, objv, get_register, (void *) format);
122
  if (objc != 1)
123
    result_ptr->flags &= ~GDBTK_MAKES_LIST;
124
 
125
  return result;
126
}
127
 
128
/* This implements the TCL command `gdb_regnames'.  Its syntax is:
129
 
130
   gdb_regnames [-numbers] [REGNUM ...]
131
 
132
   Return a list containing the names of the registers whose numbers
133
   are given by REGNUM ... .  If no register numbers are given, return
134
   all the registers' names.
135
 
136
   Note that some processors have gaps in the register numberings:
137
   even if there is no register numbered N, there may still be a
138
   register numbered N+1.  So if you call gdb_regnames with no
139
   arguments, you can't assume that the N'th element of the result is
140
   register number N.
141
 
142
   Given the -numbers option, gdb_regnames returns, not a list of names,
143
   but a list of pairs {NAME NUMBER}, where NAME is the register name,
144
   and NUMBER is its number.  */
145
static int
146
gdb_regnames (clientData, interp, objc, objv)
147
     ClientData clientData;
148
     Tcl_Interp *interp;
149
     int objc;
150
     Tcl_Obj *CONST objv[];
151
{
152
  int numbers = 0;
153
 
154
  objc--;
155
  objv++;
156
 
157
  if (objc >= 1)
158
    {
159
      char *s = Tcl_GetStringFromObj (objv[0], NULL);
160
      if (STREQ (s, "-numbers"))
161
        numbers = 1;
162
      objc--;
163
      objv++;
164
    }
165
 
166
  return map_arg_registers (objc, objv, get_register_name, &numbers);
167
}
168
 
169
/* This implements the tcl command get_pc_reg
170
 * It returns the value of the PC register
171
 *
172
 * Tcl Arguments:
173
 *    None
174
 * Tcl Result:
175
 *    The value of the pc register.
176
 */
177
static int
178
get_pc_register (clientData, interp, objc, objv)
179
     ClientData clientData;
180
     Tcl_Interp *interp;
181
     int objc;
182
     Tcl_Obj *CONST objv[];
183
{
184
  char *buff;
185
 
186
  xasprintf (&buff, "0x%llx", (long long) read_register (PC_REGNUM));
187
  Tcl_SetStringObj (result_ptr->obj_ptr, buff, -1);
188
  free(buff);
189
  return TCL_OK;
190
}
191
 
192
static void
193
get_register (regnum, fp)
194
     int regnum;
195
     void *fp;
196
{
197
  struct type *reg_vtype;
198
  char raw_buffer[MAX_REGISTER_RAW_SIZE];
199
  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
200
  int format = (int) fp;
201
  int optim;
202
 
203
  if (format == 'N')
204
    format = 0;
205
 
206
  /* read_relative_register_raw_bytes returns a virtual frame pointer
207
     (FRAME_FP (selected_frame)) if regnum == FP_REGNUM instead
208
     of the real contents of the register. To get around this,
209
     use get_saved_register instead. */
210
  get_saved_register (raw_buffer, &optim, (CORE_ADDR *) NULL, selected_frame,
211
                      regnum, (enum lval_type *) NULL);
212
  if (optim)
213
    {
214
      Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
215
                                Tcl_NewStringObj ("Optimized out", -1));
216
      return;
217
    }
218
 
219
  /* Convert raw data to virtual format if necessary.  */
220
 
221
  reg_vtype = REGISTER_VIRTUAL_TYPE (regnum);
222
  if (REGISTER_CONVERTIBLE (regnum))
223
    {
224
      REGISTER_CONVERT_TO_VIRTUAL (regnum, reg_vtype,
225
                                   raw_buffer, virtual_buffer);
226
    }
227
  else
228
    memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
229
 
230
  if (format == 'r')
231
    {
232
      int j;
233
      char *ptr, buf[1024];
234
 
235
      strcpy (buf, "0x");
236
      ptr = buf + 2;
237
      for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++)
238
        {
239
          register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
240
          : REGISTER_RAW_SIZE (regnum) - 1 - j;
241
          sprintf (ptr, "%02x", (unsigned char) raw_buffer[idx]);
242
          ptr += 2;
243
        }
244
      fputs_filtered (buf, gdb_stdout);
245
    }
246
  else
247
    if ((TYPE_CODE (reg_vtype) == TYPE_CODE_UNION)
248
        && (strcmp (FIELD_NAME (TYPE_FIELD (reg_vtype, 0)), REGISTER_NAME (regnum)) == 0))
249
      {
250
        val_print (FIELD_TYPE (TYPE_FIELD (reg_vtype, 0)), virtual_buffer, 0, 0,
251
                   gdb_stdout, format, 1, 0, Val_pretty_default);
252
      }
253
    else
254
      val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0,
255
                 gdb_stdout, format, 1, 0, Val_pretty_default);
256
 
257
}
258
 
259
static void
260
get_register_name (regnum, argp)
261
     int regnum;
262
     void *argp;
263
{
264
  /* Non-zero if the caller wants the register numbers, too.  */
265
  int numbers = * (int *) argp;
266
  Tcl_Obj *name = Tcl_NewStringObj (REGISTER_NAME (regnum), -1);
267
  Tcl_Obj *elt;
268
 
269
  if (numbers)
270
    {
271
      /* Build a tuple of the form "{REGNAME NUMBER}", and append it to
272
         our result.  */
273
      Tcl_Obj *array[2];
274
 
275
      array[0] = name;
276
      array[1] = Tcl_NewIntObj (regnum);
277
      elt = Tcl_NewListObj (2, array);
278
    }
279
  else
280
    elt = name;
281
 
282
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, elt);
283
}
284
 
285
/* This is a sort of mapcar function for operations on registers */
286
 
287
static int
288
map_arg_registers (objc, objv, func, argp)
289
     int objc;
290
     Tcl_Obj *CONST objv[];
291
     void (*func) (int regnum, void *argp);
292
     void *argp;
293
{
294
  int regnum, numregs;
295
 
296
  /* Note that the test for a valid register must include checking the
297
     REGISTER_NAME because NUM_REGS may be allocated for the union of
298
     the register sets within a family of related processors.  In this
299
     case, some entries of REGISTER_NAME will change depending upon
300
     the particular processor being debugged.  */
301
 
302
  numregs = NUM_REGS + NUM_PSEUDO_REGS;
303
 
304
  if (objc == 0)         /* No args, just do all the regs */
305
    {
306
      for (regnum = 0;
307
           regnum < numregs;
308
           regnum++)
309
        {
310
          if (REGISTER_NAME (regnum) == NULL
311
              || *(REGISTER_NAME (regnum)) == '\0')
312
            continue;
313
 
314
          func (regnum, argp);
315
        }
316
 
317
      return TCL_OK;
318
    }
319
 
320
  /* Else, list of register #s, just do listed regs */
321
  for (; objc > 0; objc--, objv++)
322
    {
323
      if (Tcl_GetIntFromObj (NULL, *objv, &regnum) != TCL_OK)
324
        {
325
          result_ptr->flags |= GDBTK_IN_TCL_RESULT;
326
          return TCL_ERROR;
327
        }
328
 
329
      if (regnum >= 0
330
          && regnum < numregs
331
          && REGISTER_NAME (regnum) != NULL
332
          && *REGISTER_NAME (regnum) != '\000')
333
        func (regnum, argp);
334
      else
335
        {
336
          Tcl_SetStringObj (result_ptr->obj_ptr, "bad register number", -1);
337
          return TCL_ERROR;
338
        }
339
    }
340
 
341
  return TCL_OK;
342
}
343
 
344
static void
345
register_changed_p (regnum, argp)
346
     int regnum;
347
     void *argp;                /* Ignored */
348
{
349
  char raw_buffer[MAX_REGISTER_RAW_SIZE];
350
 
351
  if (read_relative_register_raw_bytes (regnum, raw_buffer))
352
    return;
353
 
354
  if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
355
              REGISTER_RAW_SIZE (regnum)) == 0)
356
    return;
357
 
358
  /* Found a changed register.  Save new value and return its number. */
359
 
360
  memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
361
          REGISTER_RAW_SIZE (regnum));
362
 
363
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, Tcl_NewIntObj (regnum));
364
}
365
 
366
static void
367
setup_architecture_data ()
368
{
369
  /* don't trust REGISTER_BYTES to be zero. */
370
  old_regs = xmalloc (REGISTER_BYTES + 1);
371
  memset (old_regs, 0, REGISTER_BYTES + 1);
372
}
373
 

powered by: WebSVN 2.1.0

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