xref: /dragonfly/contrib/gdb-7/gdb/tui/tui-regs.c (revision 52f9f0d9)
1 /* TUI display registers in window.
2 
3    Copyright (C) 1998-2004, 2007-2012 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 "gdb_string.h"
34 #include "tui/tui-layout.h"
35 #include "tui/tui-win.h"
36 #include "tui/tui-windata.h"
37 #include "tui/tui-wingeneral.h"
38 #include "tui/tui-file.h"
39 #include "tui/tui-regs.h"
40 #include "reggroups.h"
41 #include "valprint.h"
42 
43 #include "gdb_curses.h"
44 
45 
46 /*****************************************
47 ** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
48 ******************************************/
49 static void
50 tui_display_register (struct tui_data_element *data,
51                       struct tui_gen_win_info *win_info);
52 
53 static enum tui_status tui_show_register_group (struct reggroup *group,
54 						struct frame_info *frame,
55 						int refresh_values_only);
56 
57 static enum tui_status tui_get_register (struct frame_info *frame,
58 					 struct tui_data_element *data,
59 					 int regnum, int *changedp);
60 
61 static void tui_register_format (struct frame_info *,
62 				 struct tui_data_element*, int);
63 
64 static void tui_scroll_regs_forward_command (char *, int);
65 static void tui_scroll_regs_backward_command (char *, int);
66 
67 
68 
69 /*****************************************
70 ** PUBLIC FUNCTIONS                     **
71 ******************************************/
72 
73 /* Answer the number of the last line in the regs display.  If there
74    are no registers (-1) is returned.  */
75 int
76 tui_last_regs_line_no (void)
77 {
78   int num_lines = (-1);
79 
80   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
81     {
82       num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
83 		  TUI_DATA_WIN->detail.data_display_info.regs_column_count);
84       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
85 	  TUI_DATA_WIN->detail.data_display_info.regs_column_count)
86 	num_lines++;
87     }
88   return num_lines;
89 }
90 
91 
92 /* Answer the line number that the register element at element_no is
93    on.  If element_no is greater than the number of register elements
94    there are, -1 is returned.  */
95 int
96 tui_line_from_reg_element_no (int element_no)
97 {
98   if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
99     {
100       int i, line = (-1);
101 
102       i = 1;
103       while (line == (-1))
104 	{
105 	  if (element_no <
106 	      (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
107 	    line = i - 1;
108 	  else
109 	    i++;
110 	}
111 
112       return line;
113     }
114   else
115     return (-1);
116 }
117 
118 
119 /* Answer the index of the first element in line_no.  If line_no is
120    past the register area (-1) is returned.  */
121 int
122 tui_first_reg_element_no_inline (int line_no)
123 {
124   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
125       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
126     return ((line_no + 1) *
127 	    TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
128       TUI_DATA_WIN->detail.data_display_info.regs_column_count;
129   else
130     return (-1);
131 }
132 
133 
134 /* Answer the index of the last element in line_no.  If line_no is
135    past the register area (-1) is returned.  */
136 int
137 tui_last_reg_element_no_in_line (int line_no)
138 {
139   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
140       TUI_DATA_WIN->detail.data_display_info.regs_content_count)
141     return ((line_no + 1) *
142 	    TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
143   else
144     return (-1);
145 }
146 
147 /* Show the registers of the given group in the data window
148    and refresh the window.  */
149 void
150 tui_show_registers (struct reggroup *group)
151 {
152   enum tui_status ret = TUI_FAILURE;
153   struct tui_data_info *display_info;
154 
155   /* Make sure the curses mode is enabled.  */
156   tui_enable ();
157 
158   /* Make sure the register window is visible.  If not, select an
159      appropriate layout.  */
160   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
161     tui_set_layout_for_display_command (DATA_NAME);
162 
163   display_info = &TUI_DATA_WIN->detail.data_display_info;
164   if (group == 0)
165     group = general_reggroup;
166 
167   /* Say that registers should be displayed, even if there is a
168      problem.  */
169   display_info->display_regs = TRUE;
170 
171   if (target_has_registers && target_has_stack && target_has_memory)
172     {
173       ret = tui_show_register_group (group, get_current_frame (),
174                                      group == display_info->current_group);
175     }
176   if (ret == TUI_FAILURE)
177     {
178       display_info->current_group = 0;
179       tui_erase_data_content (NO_REGS_STRING);
180     }
181   else
182     {
183       int i;
184 
185       /* Clear all notation of changed values.  */
186       for (i = 0; i < display_info->regs_content_count; i++)
187 	{
188 	  struct tui_gen_win_info *data_item_win;
189           struct tui_win_element *win;
190 
191 	  data_item_win = &display_info->regs_content[i]
192             ->which_element.data_window;
193           win = (struct tui_win_element *) data_item_win->content[0];
194           win->which_element.data.highlight = FALSE;
195 	}
196       display_info->current_group = group;
197       tui_display_all_data ();
198     }
199 }
200 
201 
202 /* Set the data window to display the registers of the register group
203    using the given frame.  Values are refreshed only when
204    refresh_values_only is TRUE.  */
205 
206 static enum tui_status
207 tui_show_register_group (struct reggroup *group,
208                          struct frame_info *frame,
209 			 int refresh_values_only)
210 {
211   struct gdbarch *gdbarch = get_frame_arch (frame);
212   enum tui_status ret = TUI_FAILURE;
213   int nr_regs;
214   int allocated_here = FALSE;
215   int regnum, pos;
216   char title[80];
217   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
218 
219   /* Make a new title showing which group we display.  */
220   snprintf (title, sizeof (title) - 1, "Register group: %s",
221             reggroup_name (group));
222   xfree (TUI_DATA_WIN->generic.title);
223   TUI_DATA_WIN->generic.title = xstrdup (title);
224 
225   /* See how many registers must be displayed.  */
226   nr_regs = 0;
227   for (regnum = 0;
228        regnum < gdbarch_num_regs (gdbarch)
229 		+ gdbarch_num_pseudo_regs (gdbarch);
230        regnum++)
231     {
232       const char *name;
233 
234       /* Must be in the group.  */
235       if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
236 	continue;
237 
238       /* If the register name is empty, it is undefined for this
239 	 processor, so don't display anything.  */
240       name = gdbarch_register_name (gdbarch, regnum);
241       if (name == 0 || *name == '\0')
242 	continue;
243 
244       nr_regs++;
245     }
246 
247   if (display_info->regs_content_count > 0 && !refresh_values_only)
248     {
249       tui_free_data_content (display_info->regs_content,
250                              display_info->regs_content_count);
251       display_info->regs_content_count = 0;
252     }
253 
254   if (display_info->regs_content_count <= 0)
255     {
256       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
257       allocated_here = TRUE;
258       refresh_values_only = FALSE;
259     }
260 
261   if (display_info->regs_content != (tui_win_content) NULL)
262     {
263       if (!refresh_values_only || allocated_here)
264 	{
265 	  TUI_DATA_WIN->generic.content = (void*) NULL;
266 	  TUI_DATA_WIN->generic.content_size = 0;
267 	  tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
268 	  display_info->regs_content
269             = (tui_win_content) TUI_DATA_WIN->generic.content;
270 	  display_info->regs_content_count = nr_regs;
271 	}
272 
273       /* Now set the register names and values.  */
274       pos = 0;
275       for (regnum = 0;
276 	   regnum < gdbarch_num_regs (gdbarch)
277 		    + gdbarch_num_pseudo_regs (gdbarch);
278 	   regnum++)
279         {
280 	  struct tui_gen_win_info *data_item_win;
281           struct tui_data_element *data;
282           const char *name;
283 
284           /* Must be in the group.  */
285           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
286             continue;
287 
288 	  /* If the register name is empty, it is undefined for this
289 	     processor, so don't display anything.  */
290 	  name = gdbarch_register_name (gdbarch, regnum);
291 	  if (name == 0 || *name == '\0')
292 	    continue;
293 
294 	  data_item_win =
295             &display_info->regs_content[pos]->which_element.data_window;
296           data = &((struct tui_win_element *)
297 		   data_item_win->content[0])->which_element.data;
298           if (data)
299             {
300               if (!refresh_values_only)
301                 {
302                   data->item_no = regnum;
303                   data->name = name;
304                   data->highlight = FALSE;
305                 }
306               tui_get_register (frame, data, regnum, 0);
307             }
308           pos++;
309 	}
310 
311       TUI_DATA_WIN->generic.content_size =
312 	display_info->regs_content_count + display_info->data_content_count;
313       ret = TUI_SUCCESS;
314     }
315 
316   return ret;
317 }
318 
319 /* Function to display the registers in the content from
320    'start_element_no' until the end of the register content or the end
321    of the display height.  No checking for displaying past the end of
322    the registers is done here.  */
323 void
324 tui_display_registers_from (int start_element_no)
325 {
326   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
327 
328   if (display_info->regs_content != (tui_win_content) NULL
329       && display_info->regs_content_count > 0)
330     {
331       int i = start_element_no;
332       int j, item_win_width, cur_y;
333 
334       int max_len = 0;
335       for (i = 0; i < display_info->regs_content_count; i++)
336         {
337           struct tui_data_element *data;
338           struct tui_gen_win_info *data_item_win;
339           char *p;
340           int len;
341 
342           data_item_win
343 	    = &display_info->regs_content[i]->which_element.data_window;
344           data = &((struct tui_win_element *)
345                    data_item_win->content[0])->which_element.data;
346           len = 0;
347           p = data->content;
348           if (p != 0)
349             while (*p)
350               {
351                 if (*p++ == '\t')
352                   len = 8 * ((len / 8) + 1);
353                 else
354                   len++;
355               }
356 
357           if (len > max_len)
358             max_len = len;
359         }
360       item_win_width = max_len + 1;
361       i = start_element_no;
362 
363       display_info->regs_column_count =
364         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
365       if (display_info->regs_column_count == 0)
366         display_info->regs_column_count = 1;
367       item_win_width =
368         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
369 
370       /* Now create each data "sub" window, and write the display into
371 	 it.  */
372       cur_y = 1;
373       while (i < display_info->regs_content_count
374 	     && cur_y <= TUI_DATA_WIN->generic.viewport_height)
375 	{
376 	  for (j = 0;
377 	       j < display_info->regs_column_count
378 		 && i < display_info->regs_content_count;
379 	       j++)
380 	    {
381 	      struct tui_gen_win_info *data_item_win;
382 	      struct tui_data_element *data_element_ptr;
383 
384 	      /* Create the window if necessary.  */
385 	      data_item_win = &display_info->regs_content[i]
386                 ->which_element.data_window;
387 	      data_element_ptr = &((struct tui_win_element *)
388 				   data_item_win->content[0])->which_element.data;
389               if (data_item_win->handle != (WINDOW*) NULL
390                   && (data_item_win->height != 1
391                       || data_item_win->width != item_win_width
392                       || data_item_win->origin.x != (item_win_width * j) + 1
393                       || data_item_win->origin.y != cur_y))
394                 {
395                   tui_delete_win (data_item_win->handle);
396                   data_item_win->handle = 0;
397                 }
398 
399 	      if (data_item_win->handle == (WINDOW *) NULL)
400 		{
401 		  data_item_win->height = 1;
402 		  data_item_win->width = item_win_width;
403 		  data_item_win->origin.x = (item_win_width * j) + 1;
404 		  data_item_win->origin.y = cur_y;
405 		  tui_make_window (data_item_win, DONT_BOX_WINDOW);
406                   scrollok (data_item_win->handle, FALSE);
407 		}
408               touchwin (data_item_win->handle);
409 
410 	      /* Get the printable representation of the register
411                  and display it.  */
412               tui_display_register (data_element_ptr, data_item_win);
413 	      i++;		/* Next register.  */
414 	    }
415 	  cur_y++;		/* Next row.  */
416 	}
417     }
418 }
419 
420 
421 /* Function to display the registers in the content from
422    'start_element_no' on 'start_line_no' until the end of the register
423    content or the end of the display height.  This function checks
424    that we won't display off the end of the register display.  */
425 static void
426 tui_display_reg_element_at_line (int start_element_no,
427 				 int start_line_no)
428 {
429   if (TUI_DATA_WIN->detail.data_display_info.regs_content
430       != (tui_win_content) NULL
431       && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
432     {
433       int element_no = start_element_no;
434 
435       if (start_element_no != 0 && start_line_no != 0)
436 	{
437 	  int last_line_no, first_line_on_last_page;
438 
439 	  last_line_no = tui_last_regs_line_no ();
440 	  first_line_on_last_page
441 	    = last_line_no - (TUI_DATA_WIN->generic.height - 2);
442 	  if (first_line_on_last_page < 0)
443 	    first_line_on_last_page = 0;
444 
445 	  /* If there is no other data displayed except registers, and
446 	     the element_no causes us to scroll past the end of the
447 	     registers, adjust what element to really start the
448 	     display at.  */
449 	  if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
450 	      && start_line_no > first_line_on_last_page)
451 	    element_no
452 	      = tui_first_reg_element_no_inline (first_line_on_last_page);
453 	}
454       tui_display_registers_from (element_no);
455     }
456 }
457 
458 
459 
460 /* Function to display the registers starting at line line_no in the
461    data window.  Answers the line number that the display actually
462    started from.  If nothing is displayed (-1) is returned.  */
463 int
464 tui_display_registers_from_line (int line_no,
465 				 int force_display)
466 {
467   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
468     {
469       int line, element_no;
470 
471       if (line_no < 0)
472 	line = 0;
473       else if (force_display)
474 	{ /* If we must display regs (force_display is true), then
475 	     make sure that we don't display off the end of the
476 	     registers.  */
477 	  if (line_no >= tui_last_regs_line_no ())
478 	    {
479 	      if ((line = tui_line_from_reg_element_no (
480 		 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
481 		line = 0;
482 	    }
483 	  else
484 	    line = line_no;
485 	}
486       else
487 	line = line_no;
488 
489       element_no = tui_first_reg_element_no_inline (line);
490       if (element_no
491 	  < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
492 	tui_display_reg_element_at_line (element_no, line);
493       else
494 	line = (-1);
495 
496       return line;
497     }
498 
499   return (-1);			/* Nothing was displayed.  */
500 }
501 
502 
503 /* This function check all displayed registers for changes in values,
504    given a particular frame.  If the values have changed, they are
505    updated with the new value and highlighted.  */
506 void
507 tui_check_register_values (struct frame_info *frame)
508 {
509   if (TUI_DATA_WIN != NULL
510       && TUI_DATA_WIN->generic.is_visible)
511     {
512       struct tui_data_info *display_info
513         = &TUI_DATA_WIN->detail.data_display_info;
514 
515       if (display_info->regs_content_count <= 0
516 	  && display_info->display_regs)
517 	tui_show_registers (display_info->current_group);
518       else
519 	{
520 	  int i;
521 
522 	  for (i = 0; (i < display_info->regs_content_count); i++)
523 	    {
524 	      struct tui_data_element *data;
525 	      struct tui_gen_win_info *data_item_win_ptr;
526 	      int was_hilighted;
527 
528 	      data_item_win_ptr = &display_info->regs_content[i]->
529                 which_element.data_window;
530 	      data = &((struct tui_win_element *)
531                        data_item_win_ptr->content[0])->which_element.data;
532 	      was_hilighted = data->highlight;
533 
534               tui_get_register (frame, data,
535                                 data->item_no, &data->highlight);
536 
537 	      if (data->highlight || was_hilighted)
538 		{
539                   tui_display_register (data, data_item_win_ptr);
540 		}
541 	    }
542 	}
543     }
544 }
545 
546 /* Display a register in a window.  If hilite is TRUE, then the value
547    will be displayed in reverse video.  */
548 static void
549 tui_display_register (struct tui_data_element *data,
550                       struct tui_gen_win_info *win_info)
551 {
552   if (win_info->handle != (WINDOW *) NULL)
553     {
554       int i;
555 
556       if (data->highlight)
557 	/* We ignore the return value, casting it to void in order to avoid
558 	   a compiler warning.  The warning itself was introduced by a patch
559 	   to ncurses 5.7 dated 2009-08-29, changing this macro to expand
560 	   to code that causes the compiler to generate an unused-value
561 	   warning.  */
562 	(void) wstandout (win_info->handle);
563 
564       wmove (win_info->handle, 0, 0);
565       for (i = 1; i < win_info->width; i++)
566         waddch (win_info->handle, ' ');
567       wmove (win_info->handle, 0, 0);
568       if (data->content)
569         waddstr (win_info->handle, data->content);
570 
571       if (data->highlight)
572 	/* We ignore the return value, casting it to void in order to avoid
573 	   a compiler warning.  The warning itself was introduced by a patch
574 	   to ncurses 5.7 dated 2009-08-29, changing this macro to expand
575 	   to code that causes the compiler to generate an unused-value
576 	   warning.  */
577 	(void) wstandend (win_info->handle);
578       tui_refresh_win (win_info);
579     }
580 }
581 
582 static void
583 tui_reg_next_command (char *arg, int from_tty)
584 {
585   struct gdbarch *gdbarch = get_current_arch ();
586 
587   if (TUI_DATA_WIN != 0)
588     {
589       struct reggroup *group
590         = TUI_DATA_WIN->detail.data_display_info.current_group;
591 
592       group = reggroup_next (gdbarch, group);
593       if (group == 0)
594         group = reggroup_next (gdbarch, 0);
595 
596       if (group)
597         tui_show_registers (group);
598     }
599 }
600 
601 static void
602 tui_reg_float_command (char *arg, int from_tty)
603 {
604   tui_show_registers (float_reggroup);
605 }
606 
607 static void
608 tui_reg_general_command (char *arg, int from_tty)
609 {
610   tui_show_registers (general_reggroup);
611 }
612 
613 static void
614 tui_reg_system_command (char *arg, int from_tty)
615 {
616   tui_show_registers (system_reggroup);
617 }
618 
619 static struct cmd_list_element *tuireglist;
620 
621 static void
622 tui_reg_command (char *args, int from_tty)
623 {
624   printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
625                      "tui reg command.\n"));
626   help_list (tuireglist, "tui reg ", -1, gdb_stdout);
627 }
628 
629 /* Provide a prototype to silence -Wmissing-prototypes.  */
630 extern initialize_file_ftype _initialize_tui_regs;
631 
632 void
633 _initialize_tui_regs (void)
634 {
635   struct cmd_list_element **tuicmd;
636 
637   tuicmd = tui_get_cmd_list ();
638 
639   add_prefix_cmd ("reg", class_tui, tui_reg_command,
640                   _("TUI commands to control the register window."),
641                   &tuireglist, "tui reg ", 0,
642                   tuicmd);
643 
644   add_cmd ("float", class_tui, tui_reg_float_command,
645            _("Display only floating point registers."),
646            &tuireglist);
647   add_cmd ("general", class_tui, tui_reg_general_command,
648            _("Display only general registers."),
649            &tuireglist);
650   add_cmd ("system", class_tui, tui_reg_system_command,
651            _("Display only system registers."),
652            &tuireglist);
653   add_cmd ("next", class_tui, tui_reg_next_command,
654            _("Display next register group."),
655            &tuireglist);
656 
657   if (xdb_commands)
658     {
659       add_com ("fr", class_tui, tui_reg_float_command,
660 	       _("Display only floating point registers\n"));
661       add_com ("gr", class_tui, tui_reg_general_command,
662 	       _("Display only general registers\n"));
663       add_com ("sr", class_tui, tui_reg_system_command,
664 	       _("Display only special registers\n"));
665       add_com ("+r", class_tui, tui_scroll_regs_forward_command,
666 	       _("Scroll the registers window forward\n"));
667       add_com ("-r", class_tui, tui_scroll_regs_backward_command,
668 	       _("Scroll the register window backward\n"));
669     }
670 }
671 
672 
673 /*****************************************
674 ** STATIC LOCAL FUNCTIONS                 **
675 ******************************************/
676 
677 extern int pagination_enabled;
678 
679 static void
680 tui_restore_gdbout (void *ui)
681 {
682   ui_file_delete (gdb_stdout);
683   gdb_stdout = (struct ui_file*) ui;
684   pagination_enabled = 1;
685 }
686 
687 /* Get the register from the frame and make a printable representation
688    of it in the data element.  */
689 static void
690 tui_register_format (struct frame_info *frame,
691                      struct tui_data_element *data_element,
692 		     int regnum)
693 {
694   struct gdbarch *gdbarch = get_frame_arch (frame);
695   struct ui_file *stream;
696   struct ui_file *old_stdout;
697   const char *name;
698   struct cleanup *cleanups;
699   char *p, *s;
700 
701   name = gdbarch_register_name (gdbarch, regnum);
702   if (name == 0 || *name == '\0')
703     return;
704 
705   pagination_enabled = 0;
706   old_stdout = gdb_stdout;
707   stream = tui_sfileopen (256);
708   gdb_stdout = stream;
709   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
710   gdbarch_print_registers_info (gdbarch, stream, frame, regnum, 1);
711 
712   /* Save formatted output in the buffer.  */
713   p = tui_file_get_strbuf (stream);
714 
715   /* Remove the possible \n.  */
716   s = strrchr (p, '\n');
717   if (s && s[1] == 0)
718     *s = 0;
719 
720   xfree (data_element->content);
721   data_element->content = xstrdup (p);
722   do_cleanups (cleanups);
723 }
724 
725 /* Get the register value from the given frame and format it for the
726    display.  When changep is set, check if the new register value has
727    changed with respect to the previous call.  */
728 static enum tui_status
729 tui_get_register (struct frame_info *frame,
730                   struct tui_data_element *data,
731 		  int regnum, int *changedp)
732 {
733   enum tui_status ret = TUI_FAILURE;
734 
735   if (changedp)
736     *changedp = FALSE;
737   if (target_has_registers)
738     {
739       struct value *old_val = data->value;
740 
741       data->value = get_frame_register_value (frame, regnum);
742       release_value (data->value);
743       if (changedp)
744 	{
745 	  struct gdbarch *gdbarch = get_frame_arch (frame);
746 	  int size = register_size (gdbarch, regnum);
747 
748 	  if (value_optimized_out (data->value) != value_optimized_out (old_val)
749 	      || !value_available_contents_eq (data->value, 0,
750 					       old_val, 0, size))
751 	    *changedp = TRUE;
752 	}
753 
754       value_free (old_val);
755 
756       /* Reformat the data content if the value changed.  */
757       if (changedp == 0 || *changedp == TRUE)
758 	tui_register_format (frame, data, regnum);
759 
760       ret = TUI_SUCCESS;
761     }
762   return ret;
763 }
764 
765 static void
766 tui_scroll_regs_forward_command (char *arg, int from_tty)
767 {
768   tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
769 }
770 
771 
772 static void
773 tui_scroll_regs_backward_command (char *arg, int from_tty)
774 {
775   tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
776 }
777