xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/tui/tui-regs.c (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
1 /* TUI display registers in window.
2 
3    Copyright (C) 1998-2019 Free Software Foundation, Inc.
4 
5    Contributed by Hewlett-Packard Company.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "tui/tui.h"
25 #include "tui/tui-data.h"
26 #include "symtab.h"
27 #include "gdbtypes.h"
28 #include "gdbcmd.h"
29 #include "frame.h"
30 #include "regcache.h"
31 #include "inferior.h"
32 #include "target.h"
33 #include "tui/tui-layout.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-windata.h"
36 #include "tui/tui-wingeneral.h"
37 #include "tui/tui-file.h"
38 #include "tui/tui-regs.h"
39 #include "tui/tui-io.h"
40 #include "reggroups.h"
41 #include "valprint.h"
42 #include "completer.h"
43 
44 #include "gdb_curses.h"
45 
46 
47 /*****************************************
48 ** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
49 ******************************************/
50 static void
51 tui_display_register (struct tui_data_element *data,
52                       struct tui_gen_win_info *win_info);
53 
54 static enum tui_status tui_show_register_group (struct reggroup *group,
55 						struct frame_info *frame,
56 						int refresh_values_only);
57 
58 static enum tui_status tui_get_register (struct frame_info *frame,
59 					 struct tui_data_element *data,
60 					 int regnum, int *changedp);
61 
62 
63 
64 /*****************************************
65 ** PUBLIC FUNCTIONS                     **
66 ******************************************/
67 
68 /* Answer the number of the last line in the regs display.  If there
69    are no registers (-1) is returned.  */
70 int
71 tui_last_regs_line_no (void)
72 {
73   int num_lines = (-1);
74 
75   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
76     {
77       num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
78 		  TUI_DATA_WIN->detail.data_display_info.regs_column_count);
79       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
80 	  TUI_DATA_WIN->detail.data_display_info.regs_column_count)
81 	num_lines++;
82     }
83   return num_lines;
84 }
85 
86 
87 /* Answer the line number that the register element at element_no is
88    on.  If element_no is greater than the number of register elements
89    there are, -1 is returned.  */
90 int
91 tui_line_from_reg_element_no (int element_no)
92 {
93   if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
94     {
95       int i, line = (-1);
96 
97       i = 1;
98       while (line == (-1))
99 	{
100 	  if (element_no <
101 	      (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
102 	    line = i - 1;
103 	  else
104 	    i++;
105 	}
106 
107       return line;
108     }
109   else
110     return (-1);
111 }
112 
113 
114 /* Answer the index of the first element in line_no.  If line_no is
115    past the register area (-1) is returned.  */
116 int
117 tui_first_reg_element_no_inline (int line_no)
118 {
119   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
120       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
121     return ((line_no + 1) *
122 	    TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
123       TUI_DATA_WIN->detail.data_display_info.regs_column_count;
124   else
125     return (-1);
126 }
127 
128 
129 /* Show the registers of the given group in the data window
130    and refresh the window.  */
131 void
132 tui_show_registers (struct reggroup *group)
133 {
134   enum tui_status ret = TUI_FAILURE;
135   struct tui_data_info *display_info;
136 
137   /* Make sure the curses mode is enabled.  */
138   tui_enable ();
139 
140   /* Make sure the register window is visible.  If not, select an
141      appropriate layout.  */
142   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
143     tui_set_layout_by_name (DATA_NAME);
144 
145   display_info = &TUI_DATA_WIN->detail.data_display_info;
146   if (group == 0)
147     group = general_reggroup;
148 
149   /* Say that registers should be displayed, even if there is a
150      problem.  */
151   display_info->display_regs = TRUE;
152 
153   if (target_has_registers && target_has_stack && target_has_memory)
154     {
155       ret = tui_show_register_group (group, get_selected_frame (NULL),
156                                      group == display_info->current_group);
157     }
158   if (ret == TUI_FAILURE)
159     {
160       display_info->current_group = 0;
161       tui_erase_data_content (NO_REGS_STRING);
162     }
163   else
164     {
165       int i;
166 
167       /* Clear all notation of changed values.  */
168       for (i = 0; i < display_info->regs_content_count; i++)
169 	{
170 	  struct tui_gen_win_info *data_item_win;
171           struct tui_win_element *win;
172 
173 	  data_item_win = &display_info->regs_content[i]
174             ->which_element.data_window;
175           win = data_item_win->content[0];
176           win->which_element.data.highlight = FALSE;
177 	}
178       display_info->current_group = group;
179       tui_display_all_data ();
180     }
181 }
182 
183 
184 /* Set the data window to display the registers of the register group
185    using the given frame.  Values are refreshed only when
186    refresh_values_only is TRUE.  */
187 
188 static enum tui_status
189 tui_show_register_group (struct reggroup *group,
190                          struct frame_info *frame,
191 			 int refresh_values_only)
192 {
193   struct gdbarch *gdbarch = get_frame_arch (frame);
194   enum tui_status ret = TUI_FAILURE;
195   int nr_regs;
196   int allocated_here = FALSE;
197   int regnum, pos;
198   char title[80];
199   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
200 
201   /* Make a new title showing which group we display.  */
202   snprintf (title, sizeof (title) - 1, "Register group: %s",
203             reggroup_name (group));
204   xfree (TUI_DATA_WIN->generic.title);
205   TUI_DATA_WIN->generic.title = xstrdup (title);
206 
207   /* See how many registers must be displayed.  */
208   nr_regs = 0;
209   for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
210     {
211       const char *name;
212 
213       /* Must be in the group.  */
214       if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
215 	continue;
216 
217       /* If the register name is empty, it is undefined for this
218 	 processor, so don't display anything.  */
219       name = gdbarch_register_name (gdbarch, regnum);
220       if (name == 0 || *name == '\0')
221 	continue;
222 
223       nr_regs++;
224     }
225 
226   if (display_info->regs_content_count > 0 && !refresh_values_only)
227     {
228       tui_free_data_content (display_info->regs_content,
229                              display_info->regs_content_count);
230       display_info->regs_content_count = 0;
231     }
232 
233   if (display_info->regs_content_count <= 0)
234     {
235       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
236       allocated_here = TRUE;
237       refresh_values_only = FALSE;
238     }
239 
240   if (display_info->regs_content != (tui_win_content) NULL)
241     {
242       if (!refresh_values_only || allocated_here)
243 	{
244 	  TUI_DATA_WIN->generic.content = NULL;
245 	  TUI_DATA_WIN->generic.content_size = 0;
246 	  tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
247 	  display_info->regs_content = TUI_DATA_WIN->generic.content;
248 	  display_info->regs_content_count = nr_regs;
249 	}
250 
251       /* Now set the register names and values.  */
252       pos = 0;
253       for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
254         {
255 	  struct tui_gen_win_info *data_item_win;
256           struct tui_data_element *data;
257           const char *name;
258 
259           /* Must be in the group.  */
260           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
261             continue;
262 
263 	  /* If the register name is empty, it is undefined for this
264 	     processor, so don't display anything.  */
265 	  name = gdbarch_register_name (gdbarch, regnum);
266 	  if (name == 0 || *name == '\0')
267 	    continue;
268 
269 	  data_item_win =
270             &display_info->regs_content[pos]->which_element.data_window;
271           data = &data_item_win->content[0]->which_element.data;
272           if (data)
273             {
274               if (!refresh_values_only)
275                 {
276                   data->item_no = regnum;
277                   data->name = name;
278                   data->highlight = FALSE;
279                 }
280               tui_get_register (frame, data, regnum, 0);
281             }
282           pos++;
283 	}
284 
285       TUI_DATA_WIN->generic.content_size =
286 	display_info->regs_content_count + display_info->data_content_count;
287       ret = TUI_SUCCESS;
288     }
289 
290   return ret;
291 }
292 
293 /* Function to display the registers in the content from
294    'start_element_no' until the end of the register content or the end
295    of the display height.  No checking for displaying past the end of
296    the registers is done here.  */
297 void
298 tui_display_registers_from (int start_element_no)
299 {
300   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
301 
302   if (display_info->regs_content != (tui_win_content) NULL
303       && display_info->regs_content_count > 0)
304     {
305       int i = start_element_no;
306       int j, item_win_width, cur_y;
307 
308       int max_len = 0;
309       for (i = 0; i < display_info->regs_content_count; i++)
310         {
311           struct tui_data_element *data;
312           struct tui_gen_win_info *data_item_win;
313           char *p;
314           int len;
315 
316           data_item_win
317 	    = &display_info->regs_content[i]->which_element.data_window;
318           data = &data_item_win->content[0]->which_element.data;
319           len = 0;
320           p = data->content;
321           if (p != 0)
322             while (*p)
323               {
324                 if (*p++ == '\t')
325                   len = 8 * ((len / 8) + 1);
326                 else
327                   len++;
328               }
329 
330           if (len > max_len)
331             max_len = len;
332         }
333       item_win_width = max_len + 1;
334       i = start_element_no;
335 
336       display_info->regs_column_count =
337         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
338       if (display_info->regs_column_count == 0)
339         display_info->regs_column_count = 1;
340       item_win_width =
341         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
342 
343       /* Now create each data "sub" window, and write the display into
344 	 it.  */
345       cur_y = 1;
346       while (i < display_info->regs_content_count
347 	     && cur_y <= TUI_DATA_WIN->generic.viewport_height)
348 	{
349 	  for (j = 0;
350 	       j < display_info->regs_column_count
351 		 && i < display_info->regs_content_count;
352 	       j++)
353 	    {
354 	      struct tui_gen_win_info *data_item_win;
355 	      struct tui_data_element *data_element_ptr;
356 
357 	      /* Create the window if necessary.  */
358 	      data_item_win = &display_info->regs_content[i]
359                 ->which_element.data_window;
360 	      data_element_ptr = &data_item_win->content[0]->which_element.data;
361               if (data_item_win->handle != (WINDOW*) NULL
362                   && (data_item_win->height != 1
363                       || data_item_win->width != item_win_width
364                       || data_item_win->origin.x != (item_win_width * j) + 1
365                       || data_item_win->origin.y != cur_y))
366                 {
367                   tui_delete_win (data_item_win->handle);
368                   data_item_win->handle = 0;
369                 }
370 
371 	      if (data_item_win->handle == (WINDOW *) NULL)
372 		{
373 		  data_item_win->height = 1;
374 		  data_item_win->width = item_win_width;
375 		  data_item_win->origin.x = (item_win_width * j) + 1;
376 		  data_item_win->origin.y = cur_y;
377 		  tui_make_window (data_item_win, DONT_BOX_WINDOW);
378                   scrollok (data_item_win->handle, FALSE);
379 		}
380               touchwin (data_item_win->handle);
381 
382 	      /* Get the printable representation of the register
383                  and display it.  */
384               tui_display_register (data_element_ptr, data_item_win);
385 	      i++;		/* Next register.  */
386 	    }
387 	  cur_y++;		/* Next row.  */
388 	}
389     }
390 }
391 
392 
393 /* Function to display the registers in the content from
394    'start_element_no' on 'start_line_no' until the end of the register
395    content or the end of the display height.  This function checks
396    that we won't display off the end of the register display.  */
397 static void
398 tui_display_reg_element_at_line (int start_element_no,
399 				 int start_line_no)
400 {
401   if (TUI_DATA_WIN->detail.data_display_info.regs_content
402       != (tui_win_content) NULL
403       && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
404     {
405       int element_no = start_element_no;
406 
407       if (start_element_no != 0 && start_line_no != 0)
408 	{
409 	  int last_line_no, first_line_on_last_page;
410 
411 	  last_line_no = tui_last_regs_line_no ();
412 	  first_line_on_last_page
413 	    = last_line_no - (TUI_DATA_WIN->generic.height - 2);
414 	  if (first_line_on_last_page < 0)
415 	    first_line_on_last_page = 0;
416 
417 	  /* If there is no other data displayed except registers, and
418 	     the element_no causes us to scroll past the end of the
419 	     registers, adjust what element to really start the
420 	     display at.  */
421 	  if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
422 	      && start_line_no > first_line_on_last_page)
423 	    element_no
424 	      = tui_first_reg_element_no_inline (first_line_on_last_page);
425 	}
426       tui_display_registers_from (element_no);
427     }
428 }
429 
430 
431 
432 /* Function to display the registers starting at line line_no in the
433    data window.  Answers the line number that the display actually
434    started from.  If nothing is displayed (-1) is returned.  */
435 int
436 tui_display_registers_from_line (int line_no,
437 				 int force_display)
438 {
439   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
440     {
441       int line, element_no;
442 
443       if (line_no < 0)
444 	line = 0;
445       else if (force_display)
446 	{ /* If we must display regs (force_display is true), then
447 	     make sure that we don't display off the end of the
448 	     registers.  */
449 	  if (line_no >= tui_last_regs_line_no ())
450 	    {
451 	      if ((line = tui_line_from_reg_element_no (
452 		 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
453 		line = 0;
454 	    }
455 	  else
456 	    line = line_no;
457 	}
458       else
459 	line = line_no;
460 
461       element_no = tui_first_reg_element_no_inline (line);
462       if (element_no
463 	  < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
464 	tui_display_reg_element_at_line (element_no, line);
465       else
466 	line = (-1);
467 
468       return line;
469     }
470 
471   return (-1);			/* Nothing was displayed.  */
472 }
473 
474 
475 /* This function check all displayed registers for changes in values,
476    given a particular frame.  If the values have changed, they are
477    updated with the new value and highlighted.  */
478 void
479 tui_check_register_values (struct frame_info *frame)
480 {
481   if (TUI_DATA_WIN != NULL
482       && TUI_DATA_WIN->generic.is_visible)
483     {
484       struct tui_data_info *display_info
485         = &TUI_DATA_WIN->detail.data_display_info;
486 
487       if (display_info->regs_content_count <= 0
488 	  && display_info->display_regs)
489 	tui_show_registers (display_info->current_group);
490       else
491 	{
492 	  int i;
493 
494 	  for (i = 0; (i < display_info->regs_content_count); i++)
495 	    {
496 	      struct tui_data_element *data;
497 	      struct tui_gen_win_info *data_item_win_ptr;
498 	      int was_hilighted;
499 
500 	      data_item_win_ptr = &display_info->regs_content[i]->
501                 which_element.data_window;
502 	      data = &data_item_win_ptr->content[0]->which_element.data;
503 	      was_hilighted = data->highlight;
504 
505               tui_get_register (frame, data,
506                                 data->item_no, &data->highlight);
507 
508 	      if (data->highlight || was_hilighted)
509 		{
510                   tui_display_register (data, data_item_win_ptr);
511 		}
512 	    }
513 	}
514     }
515 }
516 
517 /* Display a register in a window.  If hilite is TRUE, then the value
518    will be displayed in reverse video.  */
519 static void
520 tui_display_register (struct tui_data_element *data,
521                       struct tui_gen_win_info *win_info)
522 {
523   if (win_info->handle != (WINDOW *) NULL)
524     {
525       int i;
526 
527       if (data->highlight)
528 	/* We ignore the return value, casting it to void in order to avoid
529 	   a compiler warning.  The warning itself was introduced by a patch
530 	   to ncurses 5.7 dated 2009-08-29, changing this macro to expand
531 	   to code that causes the compiler to generate an unused-value
532 	   warning.  */
533 	(void) wstandout (win_info->handle);
534 
535       wmove (win_info->handle, 0, 0);
536       for (i = 1; i < win_info->width; i++)
537         waddch (win_info->handle, ' ');
538       wmove (win_info->handle, 0, 0);
539       if (data->content)
540         waddstr (win_info->handle, data->content);
541 
542       if (data->highlight)
543 	/* We ignore the return value, casting it to void in order to avoid
544 	   a compiler warning.  The warning itself was introduced by a patch
545 	   to ncurses 5.7 dated 2009-08-29, changing this macro to expand
546 	   to code that causes the compiler to generate an unused-value
547 	   warning.  */
548 	(void) wstandend (win_info->handle);
549       tui_refresh_win (win_info);
550     }
551 }
552 
553 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
554    around behaviour.  Returns the next register group, or NULL if the
555    register window is not currently being displayed.  */
556 
557 static struct reggroup *
558 tui_reg_next (struct gdbarch *gdbarch)
559 {
560   struct reggroup *group = NULL;
561 
562   if (TUI_DATA_WIN != NULL)
563     {
564       group = TUI_DATA_WIN->detail.data_display_info.current_group;
565       group = reggroup_next (gdbarch, group);
566       if (group == NULL)
567         group = reggroup_next (gdbarch, NULL);
568     }
569   return group;
570 }
571 
572 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
573    around behaviour.  Returns the previous register group, or NULL if the
574    register window is not currently being displayed.  */
575 
576 static struct reggroup *
577 tui_reg_prev (struct gdbarch *gdbarch)
578 {
579   struct reggroup *group = NULL;
580 
581   if (TUI_DATA_WIN != NULL)
582     {
583       group = TUI_DATA_WIN->detail.data_display_info.current_group;
584       group = reggroup_prev (gdbarch, group);
585       if (group == NULL)
586 	group = reggroup_prev (gdbarch, NULL);
587     }
588   return group;
589 }
590 
591 /* Implement the 'tui reg' command.  Changes the register group displayed
592    in the tui register window.  Displays the tui register window if it is
593    not already on display.  */
594 
595 static void
596 tui_reg_command (const char *args, int from_tty)
597 {
598   struct gdbarch *gdbarch = get_current_arch ();
599 
600   if (args != NULL)
601     {
602       struct reggroup *group, *match = NULL;
603       size_t len = strlen (args);
604 
605       /* Make sure the curses mode is enabled.  */
606       tui_enable ();
607 
608       /* Make sure the register window is visible.  If not, select an
609 	 appropriate layout.  We need to do this before trying to run the
610 	 'next' or 'prev' commands.  */
611       if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
612 	tui_set_layout_by_name (DATA_NAME);
613 
614       if (strncmp (args, "next", len) == 0)
615 	match = tui_reg_next (gdbarch);
616       else if (strncmp (args, "prev", len) == 0)
617 	match = tui_reg_prev (gdbarch);
618 
619       /* This loop matches on the initial part of a register group
620 	 name.  If this initial part in ARGS matches only one register
621 	 group then the switch is made.  */
622       for (group = reggroup_next (gdbarch, NULL);
623 	   group != NULL;
624 	   group = reggroup_next (gdbarch, group))
625 	{
626 	  if (strncmp (reggroup_name (group), args, len) == 0)
627 	    {
628 	      if (match != NULL)
629 		error (_("ambiguous register group name '%s'"), args);
630 	      match = group;
631 	    }
632 	}
633 
634       if (match == NULL)
635 	error (_("unknown register group '%s'"), args);
636 
637       tui_show_registers (match);
638     }
639   else
640     {
641       struct reggroup *group;
642       int first;
643 
644       printf_unfiltered (_("\"tui reg\" must be followed by the name of "
645 			   "either a register group,\nor one of 'next' "
646 			   "or 'prev'.  Known register groups are:\n"));
647 
648       for (first = 1, group = reggroup_next (gdbarch, NULL);
649 	   group != NULL;
650 	   first = 0, group = reggroup_next (gdbarch, group))
651 	{
652 	  if (!first)
653 	    printf_unfiltered (", ");
654 	  printf_unfiltered ("%s", reggroup_name (group));
655 	}
656 
657       printf_unfiltered ("\n");
658     }
659 }
660 
661 /* Complete names of register groups, and add the special "prev" and "next"
662    names.  */
663 
664 static void
665 tui_reggroup_completer (struct cmd_list_element *ignore,
666 			completion_tracker &tracker,
667 			const char *text, const char *word)
668 {
669   static const char *extra[] = { "next", "prev", NULL };
670   size_t len = strlen (word);
671   const char **tmp;
672 
673   reggroup_completer (ignore, tracker, text, word);
674 
675   /* XXXX use complete_on_enum instead?  */
676   for (tmp = extra; *tmp != NULL; ++tmp)
677     {
678       if (strncmp (word, *tmp, len) == 0)
679 	tracker.add_completion (gdb::unique_xmalloc_ptr<char> (xstrdup (*tmp)));
680     }
681 }
682 
683 void
684 _initialize_tui_regs (void)
685 {
686   struct cmd_list_element **tuicmd, *cmd;
687 
688   tuicmd = tui_get_cmd_list ();
689 
690   cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
691 TUI command to control the register window."), tuicmd);
692   set_cmd_completer (cmd, tui_reggroup_completer);
693 }
694 
695 
696 /*****************************************
697 ** STATIC LOCAL FUNCTIONS                 **
698 ******************************************/
699 
700 /* Get the register from the frame and return a printable
701    representation of it.  */
702 
703 static char *
704 tui_register_format (struct frame_info *frame, int regnum)
705 {
706   struct gdbarch *gdbarch = get_frame_arch (frame);
707 
708   string_file stream;
709 
710   scoped_restore save_pagination
711     = make_scoped_restore (&pagination_enabled, 0);
712   scoped_restore save_stdout
713     = make_scoped_restore (&gdb_stdout, &stream);
714 
715   gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
716 
717   /* Remove the possible \n.  */
718   std::string &str = stream.string ();
719   if (!str.empty () && str.back () == '\n')
720     str.resize (str.size () - 1);
721 
722   /* Expand tabs into spaces, since ncurses on MS-Windows doesn't.  */
723   return tui_expand_tabs (str.c_str (), 0);
724 }
725 
726 /* Get the register value from the given frame and format it for the
727    display.  When changep is set, check if the new register value has
728    changed with respect to the previous call.  */
729 static enum tui_status
730 tui_get_register (struct frame_info *frame,
731                   struct tui_data_element *data,
732 		  int regnum, int *changedp)
733 {
734   enum tui_status ret = TUI_FAILURE;
735 
736   if (changedp)
737     *changedp = FALSE;
738   if (target_has_registers)
739     {
740       char *prev_content = data->content;
741 
742       data->content = tui_register_format (frame, regnum);
743 
744       if (changedp != NULL
745 	  && strcmp (prev_content, data->content) != 0)
746 	*changedp = 1;
747 
748       xfree (prev_content);
749 
750       ret = TUI_SUCCESS;
751     }
752   return ret;
753 }
754