15796c8dcSSimon Schubert /* Disassembly display.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 1998-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert Contributed by Hewlett-Packard Company.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This file is part of GDB.
85796c8dcSSimon Schubert
95796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert (at your option) any later version.
135796c8dcSSimon Schubert
145796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175796c8dcSSimon Schubert GNU General Public License for more details.
185796c8dcSSimon Schubert
195796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
215796c8dcSSimon Schubert
225796c8dcSSimon Schubert #include "defs.h"
23cf7f2e2dSJohn Marino #include "arch-utils.h"
245796c8dcSSimon Schubert #include "symtab.h"
255796c8dcSSimon Schubert #include "breakpoint.h"
265796c8dcSSimon Schubert #include "frame.h"
275796c8dcSSimon Schubert #include "value.h"
285796c8dcSSimon Schubert #include "source.h"
295796c8dcSSimon Schubert #include "disasm.h"
305796c8dcSSimon Schubert #include "gdb_string.h"
315796c8dcSSimon Schubert #include "tui/tui.h"
325796c8dcSSimon Schubert #include "tui/tui-data.h"
335796c8dcSSimon Schubert #include "tui/tui-win.h"
345796c8dcSSimon Schubert #include "tui/tui-layout.h"
355796c8dcSSimon Schubert #include "tui/tui-winsource.h"
365796c8dcSSimon Schubert #include "tui/tui-stack.h"
375796c8dcSSimon Schubert #include "tui/tui-file.h"
385796c8dcSSimon Schubert #include "tui/tui-disasm.h"
39cf7f2e2dSJohn Marino #include "progspace.h"
405796c8dcSSimon Schubert
415796c8dcSSimon Schubert #include "gdb_curses.h"
425796c8dcSSimon Schubert
435796c8dcSSimon Schubert struct tui_asm_line
445796c8dcSSimon Schubert {
455796c8dcSSimon Schubert CORE_ADDR addr;
465796c8dcSSimon Schubert char *addr_string;
475796c8dcSSimon Schubert char *insn;
485796c8dcSSimon Schubert };
495796c8dcSSimon Schubert
505796c8dcSSimon Schubert /* Function to set the disassembly window's content.
515796c8dcSSimon Schubert Disassemble count lines starting at pc.
525796c8dcSSimon Schubert Return address of the count'th instruction after pc. */
535796c8dcSSimon Schubert static CORE_ADDR
tui_disassemble(struct gdbarch * gdbarch,struct tui_asm_line * asm_lines,CORE_ADDR pc,int count)545796c8dcSSimon Schubert tui_disassemble (struct gdbarch *gdbarch, struct tui_asm_line *asm_lines,
555796c8dcSSimon Schubert CORE_ADDR pc, int count)
565796c8dcSSimon Schubert {
575796c8dcSSimon Schubert struct ui_file *gdb_dis_out;
585796c8dcSSimon Schubert
595796c8dcSSimon Schubert /* Now init the ui_file structure. */
605796c8dcSSimon Schubert gdb_dis_out = tui_sfileopen (256);
615796c8dcSSimon Schubert
625796c8dcSSimon Schubert /* Now construct each line. */
635796c8dcSSimon Schubert for (; count > 0; count--, asm_lines++)
645796c8dcSSimon Schubert {
655796c8dcSSimon Schubert if (asm_lines->addr_string)
665796c8dcSSimon Schubert xfree (asm_lines->addr_string);
675796c8dcSSimon Schubert if (asm_lines->insn)
685796c8dcSSimon Schubert xfree (asm_lines->insn);
695796c8dcSSimon Schubert
705796c8dcSSimon Schubert print_address (gdbarch, pc, gdb_dis_out);
715796c8dcSSimon Schubert asm_lines->addr = pc;
725796c8dcSSimon Schubert asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out));
735796c8dcSSimon Schubert
745796c8dcSSimon Schubert ui_file_rewind (gdb_dis_out);
755796c8dcSSimon Schubert
765796c8dcSSimon Schubert pc = pc + gdb_print_insn (gdbarch, pc, gdb_dis_out, NULL);
775796c8dcSSimon Schubert
785796c8dcSSimon Schubert asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out));
795796c8dcSSimon Schubert
805796c8dcSSimon Schubert /* Reset the buffer to empty. */
815796c8dcSSimon Schubert ui_file_rewind (gdb_dis_out);
825796c8dcSSimon Schubert }
835796c8dcSSimon Schubert ui_file_delete (gdb_dis_out);
845796c8dcSSimon Schubert return pc;
855796c8dcSSimon Schubert }
865796c8dcSSimon Schubert
875796c8dcSSimon Schubert /* Find the disassembly address that corresponds to FROM lines above
885796c8dcSSimon Schubert or below the PC. Variable sized instructions are taken into
895796c8dcSSimon Schubert account by the algorithm. */
905796c8dcSSimon Schubert static CORE_ADDR
tui_find_disassembly_address(struct gdbarch * gdbarch,CORE_ADDR pc,int from)915796c8dcSSimon Schubert tui_find_disassembly_address (struct gdbarch *gdbarch, CORE_ADDR pc, int from)
925796c8dcSSimon Schubert {
935796c8dcSSimon Schubert CORE_ADDR new_low;
945796c8dcSSimon Schubert int max_lines;
955796c8dcSSimon Schubert int i;
965796c8dcSSimon Schubert struct tui_asm_line *asm_lines;
975796c8dcSSimon Schubert
985796c8dcSSimon Schubert max_lines = (from > 0) ? from : - from;
995796c8dcSSimon Schubert if (max_lines <= 1)
1005796c8dcSSimon Schubert return pc;
1015796c8dcSSimon Schubert
1025796c8dcSSimon Schubert asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
1035796c8dcSSimon Schubert * max_lines);
1045796c8dcSSimon Schubert memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
1055796c8dcSSimon Schubert
1065796c8dcSSimon Schubert new_low = pc;
1075796c8dcSSimon Schubert if (from > 0)
1085796c8dcSSimon Schubert {
1095796c8dcSSimon Schubert tui_disassemble (gdbarch, asm_lines, pc, max_lines);
1105796c8dcSSimon Schubert new_low = asm_lines[max_lines - 1].addr;
1115796c8dcSSimon Schubert }
1125796c8dcSSimon Schubert else
1135796c8dcSSimon Schubert {
1145796c8dcSSimon Schubert CORE_ADDR last_addr;
1155796c8dcSSimon Schubert int pos;
1165796c8dcSSimon Schubert struct minimal_symbol *msymbol;
1175796c8dcSSimon Schubert
1185796c8dcSSimon Schubert /* Find backward an address which is a symbol and for which
1195796c8dcSSimon Schubert disassembling from that address will fill completely the
1205796c8dcSSimon Schubert window. */
1215796c8dcSSimon Schubert pos = max_lines - 1;
1225796c8dcSSimon Schubert do {
1235796c8dcSSimon Schubert new_low -= 1 * max_lines;
1245796c8dcSSimon Schubert msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
1255796c8dcSSimon Schubert
1265796c8dcSSimon Schubert if (msymbol)
1275796c8dcSSimon Schubert new_low = SYMBOL_VALUE_ADDRESS (msymbol);
1285796c8dcSSimon Schubert else
1295796c8dcSSimon Schubert new_low += 1 * max_lines;
1305796c8dcSSimon Schubert
1315796c8dcSSimon Schubert tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
1325796c8dcSSimon Schubert last_addr = asm_lines[pos].addr;
1335796c8dcSSimon Schubert } while (last_addr > pc && msymbol);
1345796c8dcSSimon Schubert
1355796c8dcSSimon Schubert /* Scan forward disassembling one instruction at a time until
1365796c8dcSSimon Schubert the last visible instruction of the window matches the pc.
1375796c8dcSSimon Schubert We keep the disassembled instructions in the 'lines' window
1385796c8dcSSimon Schubert and shift it downward (increasing its addresses). */
1395796c8dcSSimon Schubert if (last_addr < pc)
1405796c8dcSSimon Schubert do
1415796c8dcSSimon Schubert {
1425796c8dcSSimon Schubert CORE_ADDR next_addr;
1435796c8dcSSimon Schubert
1445796c8dcSSimon Schubert pos++;
1455796c8dcSSimon Schubert if (pos >= max_lines)
1465796c8dcSSimon Schubert pos = 0;
1475796c8dcSSimon Schubert
1485796c8dcSSimon Schubert next_addr = tui_disassemble (gdbarch, &asm_lines[pos],
1495796c8dcSSimon Schubert last_addr, 1);
1505796c8dcSSimon Schubert
1515796c8dcSSimon Schubert /* If there are some problems while disassembling exit. */
1525796c8dcSSimon Schubert if (next_addr <= last_addr)
1535796c8dcSSimon Schubert break;
1545796c8dcSSimon Schubert last_addr = next_addr;
1555796c8dcSSimon Schubert } while (last_addr <= pc);
1565796c8dcSSimon Schubert pos++;
1575796c8dcSSimon Schubert if (pos >= max_lines)
1585796c8dcSSimon Schubert pos = 0;
1595796c8dcSSimon Schubert new_low = asm_lines[pos].addr;
1605796c8dcSSimon Schubert }
1615796c8dcSSimon Schubert for (i = 0; i < max_lines; i++)
1625796c8dcSSimon Schubert {
1635796c8dcSSimon Schubert xfree (asm_lines[i].addr_string);
1645796c8dcSSimon Schubert xfree (asm_lines[i].insn);
1655796c8dcSSimon Schubert }
1665796c8dcSSimon Schubert return new_low;
1675796c8dcSSimon Schubert }
1685796c8dcSSimon Schubert
1695796c8dcSSimon Schubert /* Function to set the disassembly window's content. */
1705796c8dcSSimon Schubert enum tui_status
tui_set_disassem_content(struct gdbarch * gdbarch,CORE_ADDR pc)1715796c8dcSSimon Schubert tui_set_disassem_content (struct gdbarch *gdbarch, CORE_ADDR pc)
1725796c8dcSSimon Schubert {
1735796c8dcSSimon Schubert enum tui_status ret = TUI_FAILURE;
1745796c8dcSSimon Schubert int i;
1755796c8dcSSimon Schubert int offset = TUI_DISASM_WIN->detail.source_info.horizontal_offset;
176*ef5ccd6cSJohn Marino int max_lines;
1775796c8dcSSimon Schubert CORE_ADDR cur_pc;
1785796c8dcSSimon Schubert struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
1795796c8dcSSimon Schubert int tab_len = tui_default_tab_len ();
1805796c8dcSSimon Schubert struct tui_asm_line *asm_lines;
1815796c8dcSSimon Schubert int insn_pos;
1825796c8dcSSimon Schubert int addr_size, max_size;
1835796c8dcSSimon Schubert char *line;
1845796c8dcSSimon Schubert
1855796c8dcSSimon Schubert if (pc == 0)
1865796c8dcSSimon Schubert return TUI_FAILURE;
1875796c8dcSSimon Schubert
1885796c8dcSSimon Schubert ret = tui_alloc_source_buffer (TUI_DISASM_WIN);
1895796c8dcSSimon Schubert if (ret != TUI_SUCCESS)
1905796c8dcSSimon Schubert return ret;
1915796c8dcSSimon Schubert
1925796c8dcSSimon Schubert TUI_DISASM_WIN->detail.source_info.gdbarch = gdbarch;
1935796c8dcSSimon Schubert TUI_DISASM_WIN->detail.source_info.start_line_or_addr.loa = LOA_ADDRESS;
1945796c8dcSSimon Schubert TUI_DISASM_WIN->detail.source_info.start_line_or_addr.u.addr = pc;
195c50c785cSJohn Marino cur_pc = (CORE_ADDR) (((struct tui_win_element *)
196c50c785cSJohn Marino locator->content[0])->which_element.locator.addr);
1975796c8dcSSimon Schubert
1985796c8dcSSimon Schubert max_lines = TUI_DISASM_WIN->generic.height - 2; /* Account for
1995796c8dcSSimon Schubert hilite. */
2005796c8dcSSimon Schubert
2015796c8dcSSimon Schubert /* Get temporary table that will hold all strings (addr & insn). */
2025796c8dcSSimon Schubert asm_lines = (struct tui_asm_line*) alloca (sizeof (struct tui_asm_line)
2035796c8dcSSimon Schubert * max_lines);
2045796c8dcSSimon Schubert memset (asm_lines, 0, sizeof (struct tui_asm_line) * max_lines);
2055796c8dcSSimon Schubert
2065796c8dcSSimon Schubert tui_disassemble (gdbarch, asm_lines, pc, max_lines);
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert /* See what is the maximum length of an address and of a line. */
2095796c8dcSSimon Schubert addr_size = 0;
2105796c8dcSSimon Schubert max_size = 0;
2115796c8dcSSimon Schubert for (i = 0; i < max_lines; i++)
2125796c8dcSSimon Schubert {
2135796c8dcSSimon Schubert size_t len = strlen (asm_lines[i].addr_string);
214cf7f2e2dSJohn Marino
2155796c8dcSSimon Schubert if (len > addr_size)
2165796c8dcSSimon Schubert addr_size = len;
2175796c8dcSSimon Schubert
2185796c8dcSSimon Schubert len = strlen (asm_lines[i].insn) + tab_len;
2195796c8dcSSimon Schubert if (len > max_size)
2205796c8dcSSimon Schubert max_size = len;
2215796c8dcSSimon Schubert }
2225796c8dcSSimon Schubert max_size += addr_size + tab_len;
2235796c8dcSSimon Schubert
2245796c8dcSSimon Schubert /* Allocate memory to create each line. */
2255796c8dcSSimon Schubert line = (char*) alloca (max_size);
2265796c8dcSSimon Schubert insn_pos = (1 + (addr_size / tab_len)) * tab_len;
2275796c8dcSSimon Schubert
2285796c8dcSSimon Schubert /* Now construct each line. */
2295796c8dcSSimon Schubert for (i = 0; i < max_lines; i++)
2305796c8dcSSimon Schubert {
2315796c8dcSSimon Schubert struct tui_win_element *element;
2325796c8dcSSimon Schubert struct tui_source_element *src;
2335796c8dcSSimon Schubert int cur_len;
2345796c8dcSSimon Schubert
2355796c8dcSSimon Schubert element = (struct tui_win_element *) TUI_DISASM_WIN->generic.content[i];
2365796c8dcSSimon Schubert src = &element->which_element.source;
2375796c8dcSSimon Schubert strcpy (line, asm_lines[i].addr_string);
2385796c8dcSSimon Schubert cur_len = strlen (line);
2395796c8dcSSimon Schubert
2405796c8dcSSimon Schubert /* Add spaces to make the instructions start on the same
2415796c8dcSSimon Schubert column. */
2425796c8dcSSimon Schubert while (cur_len < insn_pos)
2435796c8dcSSimon Schubert {
2445796c8dcSSimon Schubert strcat (line, " ");
2455796c8dcSSimon Schubert cur_len++;
2465796c8dcSSimon Schubert }
2475796c8dcSSimon Schubert
2485796c8dcSSimon Schubert strcat (line, asm_lines[i].insn);
2495796c8dcSSimon Schubert
2505796c8dcSSimon Schubert /* Now copy the line taking the offset into account. */
2515796c8dcSSimon Schubert if (strlen (line) > offset)
2525796c8dcSSimon Schubert strcpy (src->line, &line[offset]);
2535796c8dcSSimon Schubert else
2545796c8dcSSimon Schubert src->line[0] = '\0';
2555796c8dcSSimon Schubert
2565796c8dcSSimon Schubert src->line_or_addr.loa = LOA_ADDRESS;
2575796c8dcSSimon Schubert src->line_or_addr.u.addr = asm_lines[i].addr;
2585796c8dcSSimon Schubert src->is_exec_point = asm_lines[i].addr == cur_pc;
2595796c8dcSSimon Schubert
2605796c8dcSSimon Schubert /* See whether there is a breakpoint installed. */
2615796c8dcSSimon Schubert src->has_break = (!src->is_exec_point
262c50c785cSJohn Marino && breakpoint_here_p (current_program_space->aspace,
263c50c785cSJohn Marino pc)
264cf7f2e2dSJohn Marino != no_breakpoint_here);
2655796c8dcSSimon Schubert
2665796c8dcSSimon Schubert xfree (asm_lines[i].addr_string);
2675796c8dcSSimon Schubert xfree (asm_lines[i].insn);
2685796c8dcSSimon Schubert }
2695796c8dcSSimon Schubert TUI_DISASM_WIN->generic.content_size = i;
2705796c8dcSSimon Schubert return TUI_SUCCESS;
2715796c8dcSSimon Schubert }
2725796c8dcSSimon Schubert
2735796c8dcSSimon Schubert
2745796c8dcSSimon Schubert /* Function to display the disassembly window with disassembled code. */
2755796c8dcSSimon Schubert void
tui_show_disassem(struct gdbarch * gdbarch,CORE_ADDR start_addr)2765796c8dcSSimon Schubert tui_show_disassem (struct gdbarch *gdbarch, CORE_ADDR start_addr)
2775796c8dcSSimon Schubert {
2785796c8dcSSimon Schubert struct symtab *s = find_pc_symtab (start_addr);
2795796c8dcSSimon Schubert struct tui_win_info *win_with_focus = tui_win_with_focus ();
2805796c8dcSSimon Schubert struct tui_line_or_address val;
2815796c8dcSSimon Schubert
2825796c8dcSSimon Schubert val.loa = LOA_ADDRESS;
2835796c8dcSSimon Schubert val.u.addr = start_addr;
2845796c8dcSSimon Schubert tui_add_win_to_layout (DISASSEM_WIN);
2855796c8dcSSimon Schubert tui_update_source_window (TUI_DISASM_WIN, gdbarch, s, val, FALSE);
2865796c8dcSSimon Schubert
2875796c8dcSSimon Schubert /* If the focus was in the src win, put it in the asm win, if the
2885796c8dcSSimon Schubert source view isn't split. */
2895796c8dcSSimon Schubert if (tui_current_layout () != SRC_DISASSEM_COMMAND
2905796c8dcSSimon Schubert && win_with_focus == TUI_SRC_WIN)
2915796c8dcSSimon Schubert tui_set_win_focus_to (TUI_DISASM_WIN);
2925796c8dcSSimon Schubert
2935796c8dcSSimon Schubert return;
2945796c8dcSSimon Schubert }
2955796c8dcSSimon Schubert
2965796c8dcSSimon Schubert
2975796c8dcSSimon Schubert /* Function to display the disassembly window. */
2985796c8dcSSimon Schubert void
tui_show_disassem_and_update_source(struct gdbarch * gdbarch,CORE_ADDR start_addr)2995796c8dcSSimon Schubert tui_show_disassem_and_update_source (struct gdbarch *gdbarch,
3005796c8dcSSimon Schubert CORE_ADDR start_addr)
3015796c8dcSSimon Schubert {
3025796c8dcSSimon Schubert struct symtab_and_line sal;
3035796c8dcSSimon Schubert
3045796c8dcSSimon Schubert tui_show_disassem (gdbarch, start_addr);
3055796c8dcSSimon Schubert if (tui_current_layout () == SRC_DISASSEM_COMMAND)
3065796c8dcSSimon Schubert {
3075796c8dcSSimon Schubert struct tui_line_or_address val;
3085796c8dcSSimon Schubert
3095796c8dcSSimon Schubert /* Update what is in the source window if it is displayed too,
3105796c8dcSSimon Schubert note that it follows what is in the disassembly window and
3115796c8dcSSimon Schubert visa-versa. */
3125796c8dcSSimon Schubert sal = find_pc_line (start_addr, 0);
3135796c8dcSSimon Schubert val.loa = LOA_LINE;
3145796c8dcSSimon Schubert val.u.line_no = sal.line;
3155796c8dcSSimon Schubert tui_update_source_window (TUI_SRC_WIN, gdbarch, sal.symtab, val, TRUE);
3165796c8dcSSimon Schubert if (sal.symtab)
3175796c8dcSSimon Schubert {
3185796c8dcSSimon Schubert set_current_source_symtab_and_line (&sal);
319*ef5ccd6cSJohn Marino tui_update_locator_fullname (symtab_to_fullname (sal.symtab));
3205796c8dcSSimon Schubert }
3215796c8dcSSimon Schubert else
322*ef5ccd6cSJohn Marino tui_update_locator_fullname ("?");
3235796c8dcSSimon Schubert }
3245796c8dcSSimon Schubert
3255796c8dcSSimon Schubert return;
3265796c8dcSSimon Schubert }
3275796c8dcSSimon Schubert
3285796c8dcSSimon Schubert void
tui_get_begin_asm_address(struct gdbarch ** gdbarch_p,CORE_ADDR * addr_p)3295796c8dcSSimon Schubert tui_get_begin_asm_address (struct gdbarch **gdbarch_p, CORE_ADDR *addr_p)
3305796c8dcSSimon Schubert {
3315796c8dcSSimon Schubert struct tui_gen_win_info *locator;
3325796c8dcSSimon Schubert struct tui_locator_element *element;
333cf7f2e2dSJohn Marino struct gdbarch *gdbarch = get_current_arch ();
3345796c8dcSSimon Schubert CORE_ADDR addr;
3355796c8dcSSimon Schubert
3365796c8dcSSimon Schubert locator = tui_locator_win_info_ptr ();
337c50c785cSJohn Marino element = &((struct tui_win_element *)
338c50c785cSJohn Marino locator->content[0])->which_element.locator;
3395796c8dcSSimon Schubert
3405796c8dcSSimon Schubert if (element->addr == 0)
3415796c8dcSSimon Schubert {
3425796c8dcSSimon Schubert struct minimal_symbol *main_symbol;
3435796c8dcSSimon Schubert
3445796c8dcSSimon Schubert /* Find address of the start of program.
3455796c8dcSSimon Schubert Note: this should be language specific. */
3465796c8dcSSimon Schubert main_symbol = lookup_minimal_symbol ("main", NULL, NULL);
3475796c8dcSSimon Schubert if (main_symbol == 0)
3485796c8dcSSimon Schubert main_symbol = lookup_minimal_symbol ("MAIN", NULL, NULL);
3495796c8dcSSimon Schubert if (main_symbol == 0)
3505796c8dcSSimon Schubert main_symbol = lookup_minimal_symbol ("_start", NULL, NULL);
3515796c8dcSSimon Schubert if (main_symbol)
3525796c8dcSSimon Schubert addr = SYMBOL_VALUE_ADDRESS (main_symbol);
3535796c8dcSSimon Schubert else
3545796c8dcSSimon Schubert addr = 0;
3555796c8dcSSimon Schubert }
3565796c8dcSSimon Schubert else /* The target is executing. */
3575796c8dcSSimon Schubert {
3585796c8dcSSimon Schubert gdbarch = element->gdbarch;
3595796c8dcSSimon Schubert addr = element->addr;
3605796c8dcSSimon Schubert }
3615796c8dcSSimon Schubert
3625796c8dcSSimon Schubert *gdbarch_p = gdbarch;
3635796c8dcSSimon Schubert *addr_p = addr;
3645796c8dcSSimon Schubert }
3655796c8dcSSimon Schubert
3665796c8dcSSimon Schubert /* Determine what the low address will be to display in the TUI's
3675796c8dcSSimon Schubert disassembly window. This may or may not be the same as the low
3685796c8dcSSimon Schubert address input. */
3695796c8dcSSimon Schubert CORE_ADDR
tui_get_low_disassembly_address(struct gdbarch * gdbarch,CORE_ADDR low,CORE_ADDR pc)3705796c8dcSSimon Schubert tui_get_low_disassembly_address (struct gdbarch *gdbarch,
3715796c8dcSSimon Schubert CORE_ADDR low, CORE_ADDR pc)
3725796c8dcSSimon Schubert {
3735796c8dcSSimon Schubert int pos;
3745796c8dcSSimon Schubert
3755796c8dcSSimon Schubert /* Determine where to start the disassembly so that the pc is about
3765796c8dcSSimon Schubert in the middle of the viewport. */
3775796c8dcSSimon Schubert pos = tui_default_win_viewport_height (DISASSEM_WIN, DISASSEM_COMMAND) / 2;
3785796c8dcSSimon Schubert pc = tui_find_disassembly_address (gdbarch, pc, -pos);
3795796c8dcSSimon Schubert
3805796c8dcSSimon Schubert if (pc < low)
3815796c8dcSSimon Schubert pc = low;
3825796c8dcSSimon Schubert return pc;
3835796c8dcSSimon Schubert }
3845796c8dcSSimon Schubert
3855796c8dcSSimon Schubert /* Scroll the disassembly forward or backward vertically. */
3865796c8dcSSimon Schubert void
tui_vertical_disassem_scroll(enum tui_scroll_direction scroll_direction,int num_to_scroll)3875796c8dcSSimon Schubert tui_vertical_disassem_scroll (enum tui_scroll_direction scroll_direction,
3885796c8dcSSimon Schubert int num_to_scroll)
3895796c8dcSSimon Schubert {
3905796c8dcSSimon Schubert if (TUI_DISASM_WIN->generic.content != NULL)
3915796c8dcSSimon Schubert {
3925796c8dcSSimon Schubert struct gdbarch *gdbarch = TUI_DISASM_WIN->detail.source_info.gdbarch;
3935796c8dcSSimon Schubert CORE_ADDR pc;
3945796c8dcSSimon Schubert tui_win_content content;
3955796c8dcSSimon Schubert struct tui_line_or_address val;
3965796c8dcSSimon Schubert int dir;
3975796c8dcSSimon Schubert
3985796c8dcSSimon Schubert content = (tui_win_content) TUI_DISASM_WIN->generic.content;
3995796c8dcSSimon Schubert
4005796c8dcSSimon Schubert pc = content[0]->which_element.source.line_or_addr.u.addr;
4015796c8dcSSimon Schubert num_to_scroll++;
402c50c785cSJohn Marino dir = (scroll_direction == FORWARD_SCROLL)
403c50c785cSJohn Marino ? num_to_scroll : -num_to_scroll;
4045796c8dcSSimon Schubert
4055796c8dcSSimon Schubert val.loa = LOA_ADDRESS;
4065796c8dcSSimon Schubert val.u.addr = tui_find_disassembly_address (gdbarch, pc, dir);
407c50c785cSJohn Marino tui_update_source_window_as_is (TUI_DISASM_WIN, gdbarch,
408c50c785cSJohn Marino NULL, val, FALSE);
4095796c8dcSSimon Schubert }
4105796c8dcSSimon Schubert }
411