/* Common target dependent code for GDB on ARM systems.
Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
- 2001, 2002 Free Software Foundation, Inc.
+ 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcore.h"
#include "symfile.h"
#include "gdb_string.h"
-#include "dis-asm.h" /* For register flavors. */
+#include "dis-asm.h" /* For register styles. */
#include "regcache.h"
#include "doublest.h"
#include "value.h"
#include "arch-utils.h"
#include "solib-svr4.h"
+#include "osabi.h"
#include "arm-tdep.h"
#include "gdb/sim-arm.h"
#define MSYMBOL_SIZE(msym) \
((long) MSYMBOL_INFO (msym) & 0x7fffffff)
+/* The list of available "set arm ..." and "show arm ..." commands. */
+static struct cmd_list_element *setarmcmdlist = NULL;
+static struct cmd_list_element *showarmcmdlist = NULL;
+
+/* The type of floating-point to use. Keep this in sync with enum
+ arm_float_model, and the help string in _initialize_arm_tdep. */
+static const char *fp_model_strings[] =
+{
+ "auto",
+ "softfpa",
+ "fpa",
+ "softvfp",
+ "vfp"
+};
+
+/* A variable that can be configured by the user. */
+static enum arm_float_model arm_fp_model = ARM_FLOAT_AUTO;
+static const char *current_fp_model = "auto";
+
/* Number of different reg name sets (options). */
-static int num_flavor_options;
+static int num_disassembly_options;
/* We have more registers than the disassembler as gdb can print the value
of special registers as well.
"fps", "cpsr" }; /* 24 25 */
static char **arm_register_names = arm_register_name_strings;
-/* Valid register name flavors. */
-static const char **valid_flavors;
+/* Valid register name styles. */
+static const char **valid_disassembly_styles;
-/* Disassembly flavor to use. Default to "std" register names. */
-static const char *disassembly_flavor;
+/* Disassembly style to use. Default to "std" register names. */
+static const char *disassembly_style;
/* Index to that option in the opcodes table. */
static int current_option;
/* This is used to keep the bfd arch_info in sync with the disassembly
- flavor. */
-static void set_disassembly_flavor_sfunc(char *, int,
+ style. */
+static void set_disassembly_style_sfunc(char *, int,
struct cmd_list_element *);
-static void set_disassembly_flavor (void);
+static void set_disassembly_style (void);
-static void convert_from_extended (void *ptr, void *dbl);
+static void convert_from_extended (const struct floatformat *, const void *,
+ void *);
+static void convert_to_extended (const struct floatformat *, void *,
+ const void *);
/* Define other aspects of the stack frame. We keep the offsets of
all saved registers, 'cause we need 'em a lot! We also keep the
static int
arm_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
{
- return (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC));
+ return (DEPRECATED_FRAME_SAVED_PC (thisframe) >= LOWEST_PC);
}
/* Set to true if the 32-bit mode is in use. */
stmdb sp!, {}
sub sp, ip, #4. */
- func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
+ func_start = (get_frame_func (fi) + FUNCTION_START_OFFSET);
after_prologue = SKIP_PROLOGUE (func_start);
/* There are some frameless functions whose first two instructions
static CORE_ADDR
arm_frame_args_address (struct frame_info *fi)
{
- return fi->frame;
+ return get_frame_base (fi);
}
/* The address of the local variables in the frame. */
static CORE_ADDR
arm_frame_locals_address (struct frame_info *fi)
{
- return fi->frame;
+ return get_frame_base (fi);
}
/* The number of arguments being passed in the frame. */
struct symbol *sym;
/* Found a function. */
- sym = lookup_symbol (func_name, NULL, VAR_NAMESPACE, NULL, NULL);
+ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL, NULL);
if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
{
/* Don't use this trick for assembly source files. */
/* Don't try to scan dummy frames. */
if (fi != NULL
- && DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
+ && DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
return;
- if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+ if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
{
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use current PC */
- prologue_end = fi->pc;
+ prologue_end = get_frame_pc (fi);
else if (sal.end < prologue_end) /* next line begins after fn end */
prologue_end = sal.end; /* (probably means no prologue) */
}
16 pushes, an add, and "mv fp,sp". */
prologue_end = prologue_start + 40;
- prologue_end = min (prologue_end, fi->pc);
+ prologue_end = min (prologue_end, get_frame_pc (fi));
/* Initialize the saved register map. When register H is copied to
register L, we will put H in saved_reg[L]. */
frame pointer, adjust the stack pointer, and save registers.
Do this until all basic prolog instructions are found. */
- fi->extra_info->framesize = 0;
+ get_frame_extra_info (fi)->framesize = 0;
for (current_pc = prologue_start;
(current_pc < prologue_end) && ((findmask & 7) != 7);
current_pc += 2)
for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
if (mask & (1 << regno))
{
- fi->extra_info->framesize += 4;
- fi->saved_regs[saved_reg[regno]] =
- -(fi->extra_info->framesize);
+ get_frame_extra_info (fi)->framesize += 4;
+ get_frame_saved_regs (fi)[saved_reg[regno]] =
+ -(get_frame_extra_info (fi)->framesize);
/* Reset saved register map. */
saved_reg[regno] = regno;
}
offset = (insn & 0x7f) << 2; /* get scaled offset */
if (insn & 0x80) /* is it signed? (==subtracting) */
{
- fi->extra_info->frameoffset += offset;
+ get_frame_extra_info (fi)->frameoffset += offset;
offset = -offset;
}
- fi->extra_info->framesize -= offset;
+ get_frame_extra_info (fi)->framesize -= offset;
}
else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
{
findmask |= 2; /* setting of r7 found */
- fi->extra_info->framereg = THUMB_FP_REGNUM;
+ get_frame_extra_info (fi)->framereg = THUMB_FP_REGNUM;
/* get scaled offset */
- fi->extra_info->frameoffset = (insn & 0xff) << 2;
+ get_frame_extra_info (fi)->frameoffset = (insn & 0xff) << 2;
}
else if (insn == 0x466f) /* mov r7, sp */
{
findmask |= 2; /* setting of r7 found */
- fi->extra_info->framereg = THUMB_FP_REGNUM;
- fi->extra_info->frameoffset = 0;
+ get_frame_extra_info (fi)->framereg = THUMB_FP_REGNUM;
+ get_frame_extra_info (fi)->frameoffset = 0;
saved_reg[THUMB_FP_REGNUM] = ARM_SP_REGNUM;
}
else if ((insn & 0xffc0) == 0x4640) /* mov r0-r7, r8-r15 */
}
}
-/* Check if prologue for this frame's PC has already been scanned. If
- it has, copy the relevant information about that prologue and
- return non-zero. Otherwise do not copy anything and return zero.
-
- The information saved in the cache includes:
- * the frame register number;
- * the size of the stack frame;
- * the offsets of saved regs (relative to the old SP); and
- * the offset from the stack pointer to the frame pointer
-
- The cache contains only one entry, since this is adequate for the
- typical sequence of prologue scan requests we get. When performing
- a backtrace, GDB will usually ask to scan the same function twice
- in a row (once to get the frame chain, and once to fill in the
- extra frame information). */
-
-static struct frame_info prologue_cache;
-
-static int
-check_prologue_cache (struct frame_info *fi)
-{
- int i;
-
- if (fi->pc == prologue_cache.pc)
- {
- fi->extra_info->framereg = prologue_cache.extra_info->framereg;
- fi->extra_info->framesize = prologue_cache.extra_info->framesize;
- fi->extra_info->frameoffset = prologue_cache.extra_info->frameoffset;
- for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
- fi->saved_regs[i] = prologue_cache.saved_regs[i];
- return 1;
- }
- else
- return 0;
-}
-
-
-/* Copy the prologue information from fi to the prologue cache. */
-
-static void
-save_prologue_cache (struct frame_info *fi)
-{
- int i;
-
- prologue_cache.pc = fi->pc;
- prologue_cache.extra_info->framereg = fi->extra_info->framereg;
- prologue_cache.extra_info->framesize = fi->extra_info->framesize;
- prologue_cache.extra_info->frameoffset = fi->extra_info->frameoffset;
-
- for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
- prologue_cache.saved_regs[i] = fi->saved_regs[i];
-}
-
-
/* This function decodes an ARM function prologue to determine:
1) the size of the stack frame
2) which registers are saved on it
LONGEST return_value;
CORE_ADDR prologue_start, prologue_end, current_pc;
- /* Check if this function is already in the cache of frame information. */
- if (check_prologue_cache (fi))
- return;
-
/* Assume there is no frame until proven otherwise. */
- fi->extra_info->framereg = ARM_SP_REGNUM;
- fi->extra_info->framesize = 0;
- fi->extra_info->frameoffset = 0;
+ get_frame_extra_info (fi)->framereg = ARM_SP_REGNUM;
+ get_frame_extra_info (fi)->framesize = 0;
+ get_frame_extra_info (fi)->frameoffset = 0;
/* Check for Thumb prologue. */
- if (arm_pc_is_thumb (fi->pc))
+ if (arm_pc_is_thumb (get_frame_pc (fi)))
{
thumb_scan_prologue (fi);
- save_prologue_cache (fi);
return;
}
/* Find the function prologue. If we can't find the function in
the symbol table, peek in the stack frame to find the PC. */
- if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
+ if (find_pc_partial_function (get_frame_pc (fi), NULL, &prologue_start, &prologue_end))
{
/* One way to find the end of the prologue (which works well
for unoptimized code) is to do the following:
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0)
- prologue_end = fi->pc;
+ prologue_end = get_frame_pc (fi);
else if (sal.end < prologue_end)
prologue_end = sal.end;
{
/* Get address of the stmfd in the prologue of the callee;
the saved PC is the address of the stmfd + 8. */
- if (!safe_read_memory_integer (fi->frame, 4, &return_value))
+ if (!safe_read_memory_integer (get_frame_base (fi), 4, &return_value))
return;
else
{
if (mask & (1 << regno))
{
sp_offset -= 4;
- fi->saved_regs[regno] = sp_offset;
+ get_frame_saved_regs (fi)[regno] = sp_offset;
}
}
else if ((insn & 0xffffc000) == 0xe54b0000 || /* strb rx,[r11,#-n] */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
fp_offset = -imm;
- fi->extra_info->framereg = ARM_FP_REGNUM;
+ get_frame_extra_info (fi)->framereg = ARM_FP_REGNUM;
}
else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
{
{
sp_offset -= 12;
regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
- fi->saved_regs[regno] = sp_offset;
+ get_frame_saved_regs (fi)[regno] = sp_offset;
}
else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
{
for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{
sp_offset -= 12;
- fi->saved_regs[fp_start_reg++] = sp_offset;
+ get_frame_saved_regs (fi)[fp_start_reg++] = sp_offset;
}
}
else if ((insn & 0xf0000000) != 0xe0000000)
/* The frame size is just the negative of the offset (from the
original SP) of the last thing thing we pushed on the stack.
The frame offset is [new FP] - [new SP]. */
- fi->extra_info->framesize = -sp_offset;
- if (fi->extra_info->framereg == ARM_FP_REGNUM)
- fi->extra_info->frameoffset = fp_offset - sp_offset;
+ get_frame_extra_info (fi)->framesize = -sp_offset;
+ if (get_frame_extra_info (fi)->framereg == ARM_FP_REGNUM)
+ get_frame_extra_info (fi)->frameoffset = fp_offset - sp_offset;
else
- fi->extra_info->frameoffset = 0;
-
- save_prologue_cache (fi);
+ get_frame_extra_info (fi)->frameoffset = 0;
}
/* Find REGNUM on the stack. Otherwise, it's in an active register.
/* NOTE: cagney/2002-05-03: This function really shouldn't be
needed. Instead the (still being written) register unwind
function could be called directly. */
- for (; fi; fi = fi->next)
+ for (; fi; fi = get_next_frame (fi))
{
- if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
{
- return deprecated_read_register_dummy (fi->pc, fi->frame, regnum);
+ return deprecated_read_register_dummy (get_frame_pc (fi),
+ get_frame_base (fi), regnum);
}
- else if (fi->saved_regs[regnum] != 0)
+ else if (get_frame_saved_regs (fi)[regnum] != 0)
{
/* NOTE: cagney/2002-05-03: This would normally need to
handle ARM_SP_REGNUM as a special case as, according to
the frame.h comments, saved_regs[SP_REGNUM] contains the
SP value not its address. It appears that the ARM isn't
doing this though. */
- return read_memory_integer (fi->saved_regs[regnum],
+ return read_memory_integer (get_frame_saved_regs (fi)[regnum],
REGISTER_RAW_SIZE (regnum));
}
}
}
/* Function: frame_chain Given a GDB frame, determine the address of
the calling function's frame. This will be used to create a new
- GDB frame struct, and then INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC
- will be called for the new frame. For ARM, we save the frame size
- when we initialize the frame_info. */
+ GDB frame struct, and then DEPRECATED_INIT_EXTRA_FRAME_INFO and
+ DEPRECATED_INIT_FRAME_PC will be called for the new frame. For
+ ARM, we save the frame size when we initialize the frame_info. */
static CORE_ADDR
arm_frame_chain (struct frame_info *fi)
{
CORE_ADDR caller_pc;
- int framereg = fi->extra_info->framereg;
+ int framereg = get_frame_extra_info (fi)->framereg;
- if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
/* A generic call dummy's frame is the same as caller's. */
- return fi->frame;
+ return get_frame_base (fi);
- if (fi->pc < LOWEST_PC)
+ if (get_frame_pc (fi) < LOWEST_PC)
return 0;
/* If the caller is the startup code, we're at the end of the chain. */
- caller_pc = FRAME_SAVED_PC (fi);
+ caller_pc = DEPRECATED_FRAME_SAVED_PC (fi);
/* If the caller is Thumb and the caller is ARM, or vice versa,
the frame register of the caller is different from ours.
frame register number. */
/* XXX Fixme, we should try to do this without creating a temporary
caller_fi. */
- if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (fi->pc))
+ if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (get_frame_pc (fi)))
{
- struct frame_info caller_fi;
- struct cleanup *old_chain;
-
- /* Create a temporary frame suitable for scanning the caller's
- prologue. (Ugh.) */
- memset (&caller_fi, 0, sizeof (caller_fi));
- caller_fi.extra_info = (struct frame_extra_info *)
- xcalloc (1, sizeof (struct frame_extra_info));
- old_chain = make_cleanup (xfree, caller_fi.extra_info);
- caller_fi.saved_regs = (CORE_ADDR *)
- xcalloc (1, SIZEOF_FRAME_SAVED_REGS);
- make_cleanup (xfree, caller_fi.saved_regs);
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+ struct frame_info *caller_fi =
+ deprecated_frame_xmalloc_with_cleanup (SIZEOF_FRAME_SAVED_REGS,
+ sizeof (struct frame_extra_info));
/* Now, scan the prologue and obtain the frame register. */
- caller_fi.pc = caller_pc;
- arm_scan_prologue (&caller_fi);
- framereg = caller_fi.extra_info->framereg;
+ deprecated_update_frame_pc_hack (caller_fi, caller_pc);
+ arm_scan_prologue (caller_fi);
+ framereg = get_frame_extra_info (caller_fi)->framereg;
/* Deallocate the storage associated with the temporary frame
created above. */
if (framereg == ARM_FP_REGNUM || framereg == THUMB_FP_REGNUM)
return arm_find_callers_reg (fi, framereg);
else
- return fi->frame + fi->extra_info->framesize;
+ return get_frame_base (fi) + get_frame_extra_info (fi)->framesize;
}
/* This function actually figures out the frame address for a given pc
int reg;
CORE_ADDR sp;
- if (fi->saved_regs == NULL)
+ if (get_frame_saved_regs (fi) == NULL)
frame_saved_regs_zalloc (fi);
- fi->extra_info = (struct frame_extra_info *)
- frame_obstack_alloc (sizeof (struct frame_extra_info));
+ frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
- fi->extra_info->framesize = 0;
- fi->extra_info->frameoffset = 0;
- fi->extra_info->framereg = 0;
+ get_frame_extra_info (fi)->framesize = 0;
+ get_frame_extra_info (fi)->frameoffset = 0;
+ get_frame_extra_info (fi)->framereg = 0;
- if (fi->next)
- fi->pc = FRAME_SAVED_PC (fi->next);
+ if (get_next_frame (fi))
+ deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
- memset (fi->saved_regs, '\000', sizeof fi->saved_regs);
+ memset (get_frame_saved_regs (fi), '\000', sizeof get_frame_saved_regs (fi));
/* Compute stack pointer for this frame. We use this value for both
the sigtramp and call dummy cases. */
- if (!fi->next)
+ if (!get_next_frame (fi))
sp = read_sp();
- else if (DEPRECATED_PC_IN_CALL_DUMMY (fi->next->pc, 0, 0))
+ else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
/* For generic dummy frames, pull the value direct from the frame.
Having an unwind function to do this would be nice. */
- sp = deprecated_read_register_dummy (fi->next->pc, fi->next->frame,
+ sp = deprecated_read_register_dummy (get_frame_pc (get_next_frame (fi)),
+ get_frame_base (get_next_frame (fi)),
ARM_SP_REGNUM);
else
- sp = (fi->next->frame - fi->next->extra_info->frameoffset
- + fi->next->extra_info->framesize);
+ sp = (get_frame_base (get_next_frame (fi))
+ - get_frame_extra_info (get_next_frame (fi))->frameoffset
+ + get_frame_extra_info (get_next_frame (fi))->framesize);
/* Determine whether or not we're in a sigtramp frame.
Unfortunately, it isn't sufficient to test (get_frame_type (fi)
== SIGTRAMP_FRAME) because this value is sometimes set after
- invoking INIT_EXTRA_FRAME_INFO. So we test *both*
+ invoking DEPRECATED_INIT_EXTRA_FRAME_INFO. So we test *both*
(get_frame_type (fi) == SIGTRAMP_FRAME) and PC_IN_SIGTRAMP to
determine if we need to use the sigcontext addresses for the
saved registers.
before calling functions like this. */
if (SIGCONTEXT_REGISTER_ADDRESS_P ()
- && ((get_frame_type (fi) == SIGTRAMP_FRAME) || PC_IN_SIGTRAMP (fi->pc, (char *)0)))
+ && ((get_frame_type (fi) == SIGTRAMP_FRAME) || PC_IN_SIGTRAMP (get_frame_pc (fi), (char *)0)))
{
for (reg = 0; reg < NUM_REGS; reg++)
- fi->saved_regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, fi->pc, reg);
+ get_frame_saved_regs (fi)[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, get_frame_pc (fi), reg);
/* FIXME: What about thumb mode? */
- fi->extra_info->framereg = ARM_SP_REGNUM;
- fi->frame =
- read_memory_integer (fi->saved_regs[fi->extra_info->framereg],
- REGISTER_RAW_SIZE (fi->extra_info->framereg));
- fi->extra_info->framesize = 0;
- fi->extra_info->frameoffset = 0;
+ get_frame_extra_info (fi)->framereg = ARM_SP_REGNUM;
+ deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (fi)[get_frame_extra_info (fi)->framereg], REGISTER_RAW_SIZE (get_frame_extra_info (fi)->framereg)));
+ get_frame_extra_info (fi)->framesize = 0;
+ get_frame_extra_info (fi)->frameoffset = 0;
}
else
{
arm_scan_prologue (fi);
- if (!fi->next)
+ if (!get_next_frame (fi))
/* This is the innermost frame? */
- fi->frame = read_register (fi->extra_info->framereg);
- else if (DEPRECATED_PC_IN_CALL_DUMMY (fi->next->pc, 0, 0))
+ deprecated_update_frame_base_hack (fi, read_register (get_frame_extra_info (fi)->framereg));
+ else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (get_next_frame (fi)), 0, 0))
/* Next inner most frame is a dummy, just grab its frame.
Dummy frames always have the same FP as their caller. */
- fi->frame = fi->next->frame;
- else if (fi->extra_info->framereg == ARM_FP_REGNUM
- || fi->extra_info->framereg == THUMB_FP_REGNUM)
+ deprecated_update_frame_base_hack (fi, get_frame_base (get_next_frame (fi)));
+ else if (get_frame_extra_info (fi)->framereg == ARM_FP_REGNUM
+ || get_frame_extra_info (fi)->framereg == THUMB_FP_REGNUM)
{
/* not the innermost frame */
/* If we have an FP, the callee saved it. */
- if (fi->next->saved_regs[fi->extra_info->framereg] != 0)
- fi->frame =
- read_memory_integer (fi->next
- ->saved_regs[fi->extra_info->framereg], 4);
+ if (get_frame_saved_regs (get_next_frame (fi))[get_frame_extra_info (fi)->framereg] != 0)
+ deprecated_update_frame_base_hack (fi, read_memory_integer (get_frame_saved_regs (get_next_frame (fi))[get_frame_extra_info (fi)->framereg], 4));
else if (fromleaf)
/* If we were called by a frameless fn. then our frame is
still in the frame pointer register on the board... */
- fi->frame = read_fp ();
+ deprecated_update_frame_base_hack (fi, deprecated_read_fp ());
}
/* Calculate actual addresses of saved registers using offsets
determined by arm_scan_prologue. */
for (reg = 0; reg < NUM_REGS; reg++)
- if (fi->saved_regs[reg] != 0)
- fi->saved_regs[reg] += (fi->frame + fi->extra_info->framesize
- - fi->extra_info->frameoffset);
+ if (get_frame_saved_regs (fi)[reg] != 0)
+ get_frame_saved_regs (fi)[reg]
+ += (get_frame_base (fi)
+ + get_frame_extra_info (fi)->framesize
+ - get_frame_extra_info (fi)->frameoffset);
}
}
arm_frame_saved_pc (struct frame_info *fi)
{
/* If a dummy frame, pull the PC out of the frame's register buffer. */
- if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, 0, 0))
- return deprecated_read_register_dummy (fi->pc, fi->frame, ARM_PC_REGNUM);
-
- if (DEPRECATED_PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->extra_info->frameoffset,
- fi->frame))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
+ return deprecated_read_register_dummy (get_frame_pc (fi),
+ get_frame_base (fi), ARM_PC_REGNUM);
+
+ if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi),
+ (get_frame_base (fi)
+ - get_frame_extra_info (fi)->frameoffset),
+ get_frame_base (fi)))
{
- return read_memory_integer (fi->saved_regs[ARM_PC_REGNUM],
+ return read_memory_integer (get_frame_saved_regs (fi)[ARM_PC_REGNUM],
REGISTER_RAW_SIZE (ARM_PC_REGNUM));
}
else
arm_frame_init_saved_regs (struct frame_info *fip)
{
- if (fip->saved_regs)
+ if (get_frame_saved_regs (fip))
return;
arm_init_extra_frame_info (0, fip);
write_register (ARM_SP_REGNUM, sp);
}
-/* CALL_DUMMY_WORDS:
+/* DEPRECATED_CALL_DUMMY_WORDS:
This sequence of words is the instructions
mov lr,pc
FIXME rearnsha 2002-02018: Tweeking current_gdbarch is not an
optimal solution, but the call to arm_fix_call_dummy is immediately
- followed by a call to run_stack_dummy, which is the only function
- where call_dummy_breakpoint_offset is actually used. */
+ followed by a call to call_function_by_hand, which is the only
+ function where call_dummy_breakpoint_offset is actually used. */
static void
arm_set_call_dummy_breakpoint_offset (void)
{
if (caller_is_thumb)
- set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 4);
+ set_gdbarch_deprecated_call_dummy_breakpoint_offset (current_gdbarch, 4);
else
- set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 8);
+ set_gdbarch_deprecated_call_dummy_breakpoint_offset (current_gdbarch, 8);
}
/* Fix up the call dummy, based on whether the processor is currently
write_register (4, fun);
}
-/* Note: ScottB
+/* Pop the current frame. So long as the frame info has been
+ initialized properly (see arm_init_extra_frame_info), this code
+ works for dummy frames as well as regular frames. I.e, there's no
+ need to have a special case for dummy frames. */
+static void
+arm_pop_frame (void)
+{
+ int regnum;
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR old_SP = (get_frame_base (frame)
+ - get_frame_extra_info (frame)->frameoffset
+ + get_frame_extra_info (frame)->framesize);
+
+ if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
+ get_frame_base (frame),
+ get_frame_base (frame)))
+ {
+ generic_pop_dummy_frame ();
+ flush_cached_frames ();
+ return;
+ }
+
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (get_frame_saved_regs (frame)[regnum] != 0)
+ write_register (regnum,
+ read_memory_integer (get_frame_saved_regs (frame)[regnum],
+ REGISTER_RAW_SIZE (regnum)));
- This function does not support passing parameters using the FPA
- variant of the APCS. It passes any floating point arguments in the
- general registers and/or on the stack. */
+ write_register (ARM_PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
+ write_register (ARM_SP_REGNUM, old_SP);
+
+ flush_cached_frames ();
+}
+
+/* When arguments must be pushed onto the stack, they go on in reverse
+ order. The code below implements a FILO (stack) to do this. */
+
+struct stack_item
+{
+ int len;
+ struct stack_item *prev;
+ void *data;
+};
+
+static struct stack_item *
+push_stack_item (struct stack_item *prev, void *contents, int len)
+{
+ struct stack_item *si;
+ si = xmalloc (sizeof (struct stack_item));
+ si->data = xmalloc (len);
+ si->len = len;
+ si->prev = prev;
+ memcpy (si->data, contents, len);
+ return si;
+}
+
+static struct stack_item *
+pop_stack_item (struct stack_item *si)
+{
+ struct stack_item *dead = si;
+ si = si->prev;
+ xfree (dead->data);
+ xfree (dead);
+ return si;
+}
+
+/* We currently only support passing parameters in integer registers. This
+ conforms with GCC's default model. Several other variants exist and
+ we should probably support some of them based on the selected ABI. */
static CORE_ADDR
-arm_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+arm_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+ struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
+ struct value **args, CORE_ADDR sp, int struct_return,
+ CORE_ADDR struct_addr)
{
- CORE_ADDR fp;
int argnum;
int argreg;
int nstack;
- int simd_argreg;
- int second_pass;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct stack_item *si = NULL;
+
+ /* Set the return address. For the ARM, the return breakpoint is
+ always at BP_ADDR. */
+ /* XXX Fix for Thumb. */
+ regcache_cooked_write_unsigned (regcache, ARM_LR_REGNUM, bp_addr);
/* Walk through the list of args and determine how large a temporary
stack is required. Need to take care here as structs may be
- passed on the stack, and we have to to push them. On the second
- pass, do the store. */
+ passed on the stack, and we have to to push them. */
+ nstack = 0;
+
+ argreg = ARM_A1_REGNUM;
nstack = 0;
- fp = sp;
- for (second_pass = 0; second_pass < 2; second_pass++)
+
+ /* Some platforms require a double-word aligned stack. Make sure sp
+ is correctly aligned before we start. We always do this even if
+ it isn't really needed -- it can never hurt things. */
+ sp &= ~(CORE_ADDR)(2 * DEPRECATED_REGISTER_SIZE - 1);
+
+ /* The struct_return pointer occupies the first parameter
+ passing register. */
+ if (struct_return)
{
- /* Compute the FP using the information computed during the
- first pass. */
- if (second_pass)
- fp = sp - nstack;
-
- simd_argreg = 0;
- argreg = ARM_A1_REGNUM;
- nstack = 0;
-
- /* The struct_return pointer occupies the first parameter
- passing register. */
- if (struct_return)
+ if (arm_debug)
+ fprintf_unfiltered (gdb_stdlog, "struct return in %s = 0x%s\n",
+ REGISTER_NAME (argreg), paddr (struct_addr));
+ regcache_cooked_write_unsigned (regcache, argreg, struct_addr);
+ argreg++;
+ }
+
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ int len;
+ struct type *arg_type;
+ struct type *target_type;
+ enum type_code typecode;
+ char *val;
+
+ arg_type = check_typedef (VALUE_TYPE (args[argnum]));
+ len = TYPE_LENGTH (arg_type);
+ target_type = TYPE_TARGET_TYPE (arg_type);
+ typecode = TYPE_CODE (arg_type);
+ val = VALUE_CONTENTS (args[argnum]);
+
+ /* If the argument is a pointer to a function, and it is a
+ Thumb function, create a LOCAL copy of the value and set
+ the THUMB bit in it. */
+ if (TYPE_CODE_PTR == typecode
+ && target_type != NULL
+ && TYPE_CODE_FUNC == TYPE_CODE (target_type))
{
- if (second_pass)
+ CORE_ADDR regval = extract_unsigned_integer (val, len);
+ if (arm_pc_is_thumb (regval))
{
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog,
- "struct return in %s = 0x%s\n",
- REGISTER_NAME (argreg),
- paddr (struct_addr));
- write_register (argreg, struct_addr);
+ val = alloca (len);
+ store_unsigned_integer (val, len, MAKE_THUMB_ADDR (regval));
}
- argreg++;
}
- for (argnum = 0; argnum < nargs; argnum++)
+ /* Copy the argument to general registers or the stack in
+ register-sized pieces. Large arguments are split between
+ registers and stack. */
+ while (len > 0)
{
- int len;
- struct type *arg_type;
- struct type *target_type;
- enum type_code typecode;
- char *val;
-
- arg_type = check_typedef (VALUE_TYPE (args[argnum]));
- len = TYPE_LENGTH (arg_type);
- target_type = TYPE_TARGET_TYPE (arg_type);
- typecode = TYPE_CODE (arg_type);
- val = VALUE_CONTENTS (args[argnum]);
-
- /* If the argument is a pointer to a function, and it is a
- Thumb function, create a LOCAL copy of the value and set
- the THUMB bit in it. */
- if (second_pass
- && TYPE_CODE_PTR == typecode
- && target_type != NULL
- && TYPE_CODE_FUNC == TYPE_CODE (target_type))
+ int partial_len = len < DEPRECATED_REGISTER_SIZE ? len : DEPRECATED_REGISTER_SIZE;
+
+ if (argreg <= ARM_LAST_ARG_REGNUM)
{
- CORE_ADDR regval = extract_address (val, len);
- if (arm_pc_is_thumb (regval))
- {
- val = alloca (len);
- store_address (val, len, MAKE_THUMB_ADDR (regval));
- }
+ /* The argument is being passed in a general purpose
+ register. */
+ CORE_ADDR regval = extract_unsigned_integer (val, partial_len);
+ if (arm_debug)
+ fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
+ argnum, REGISTER_NAME (argreg),
+ phex (regval, DEPRECATED_REGISTER_SIZE));
+ regcache_cooked_write_unsigned (regcache, argreg, regval);
+ argreg++;
}
-
- /* Copy the argument to general registers or the stack in
- register-sized pieces. Large arguments are split between
- registers and stack. */
- while (len > 0)
+ else
{
- int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
-
- if (argreg <= ARM_LAST_ARG_REGNUM)
- {
- /* The argument is being passed in a general purpose
- register. */
- if (second_pass)
- {
- CORE_ADDR regval = extract_address (val,
- partial_len);
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog,
- "arg %d in %s = 0x%s\n",
- argnum,
- REGISTER_NAME (argreg),
- phex (regval, REGISTER_SIZE));
- write_register (argreg, regval);
- }
- argreg++;
- }
- else
- {
- if (second_pass)
- {
- /* Push the arguments onto the stack. */
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog,
- "arg %d @ 0x%s + %d\n",
- argnum, paddr (fp), nstack);
- write_memory (fp + nstack, val, REGISTER_SIZE);
- }
- nstack += REGISTER_SIZE;
- }
-
- len -= partial_len;
- val += partial_len;
+ /* Push the arguments onto the stack. */
+ if (arm_debug)
+ fprintf_unfiltered (gdb_stdlog, "arg %d @ sp + %d\n",
+ argnum, nstack);
+ si = push_stack_item (si, val, DEPRECATED_REGISTER_SIZE);
+ nstack += DEPRECATED_REGISTER_SIZE;
}
-
+
+ len -= partial_len;
+ val += partial_len;
}
}
+ /* If we have an odd number of words to push, then decrement the stack
+ by one word now, so first stack argument will be dword aligned. */
+ if (nstack & 4)
+ sp -= 4;
- /* Return the botom of the argument list (pointed to by fp). */
- return fp;
-}
-
-/* Pop the current frame. So long as the frame info has been
- initialized properly (see arm_init_extra_frame_info), this code
- works for dummy frames as well as regular frames. I.e, there's no
- need to have a special case for dummy frames. */
-static void
-arm_pop_frame (void)
-{
- int regnum;
- struct frame_info *frame = get_current_frame ();
- CORE_ADDR old_SP = (frame->frame - frame->extra_info->frameoffset
- + frame->extra_info->framesize);
-
- if (DEPRECATED_PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+ while (si)
{
- generic_pop_dummy_frame ();
- flush_cached_frames ();
- return;
+ sp -= si->len;
+ write_memory (sp, si->data, si->len);
+ si = pop_stack_item (si);
}
- for (regnum = 0; regnum < NUM_REGS; regnum++)
- if (frame->saved_regs[regnum] != 0)
- write_register (regnum,
- read_memory_integer (frame->saved_regs[regnum],
- REGISTER_RAW_SIZE (regnum)));
-
- write_register (ARM_PC_REGNUM, FRAME_SAVED_PC (frame));
- write_register (ARM_SP_REGNUM, old_SP);
+ /* Finally, update teh SP register. */
+ regcache_cooked_write_unsigned (regcache, ARM_SP_REGNUM, sp);
- flush_cached_frames ();
+ return sp;
}
static void
little-endian systems. */
static void
-convert_from_extended (void *ptr, void *dbl)
+convert_from_extended (const struct floatformat *fmt, const void *ptr,
+ void *dbl)
{
DOUBLEST d;
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
else
floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
ptr, &d);
- floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
+ floatformat_from_doublest (fmt, &d, dbl);
}
static void
-convert_to_extended (void *dbl, void *ptr)
+convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr)
{
DOUBLEST d;
- floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
+ floatformat_to_doublest (fmt, ptr, &d);
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
else
/* Fetch the saved PC from the stack. It's stored above
all of the other registers. */
- offset = bitcount (bits (inst1, 0, 7)) * REGISTER_SIZE;
+ offset = bitcount (bits (inst1, 0, 7)) * DEPRECATED_REGISTER_SIZE;
sp = read_register (ARM_SP_REGNUM);
nextpc = (CORE_ADDR) read_memory_integer (sp + offset, 4);
nextpc = ADDR_BITS_REMOVE (nextpc);
static asymbol *asym;
static combined_entry_type ce;
static struct coff_symbol_struct csym;
- static struct _bfd fake_bfd;
+ static struct bfd fake_bfd;
static bfd_target fake_target;
if (csym.native == NULL)
static void
arm_extract_return_value (struct type *type,
- char regbuf[REGISTER_BYTES],
- char *valbuf)
+ struct regcache *regs,
+ void *dst)
{
+ bfd_byte *valbuf = dst;
+
if (TYPE_CODE_FLT == TYPE_CODE (type))
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- switch (tdep->fp_model)
+ switch (arm_get_fp_model (current_gdbarch))
{
case ARM_FLOAT_FPA:
- convert_from_extended (®buf[REGISTER_BYTE (ARM_F0_REGNUM)],
- valbuf);
+ {
+ /* The value is in register F0 in internal format. We need to
+ extract the raw value and then convert it to the desired
+ internal type. */
+ bfd_byte tmpbuf[FP_REGISTER_RAW_SIZE];
+
+ regcache_cooked_read (regs, ARM_F0_REGNUM, tmpbuf);
+ convert_from_extended (floatformat_from_type (type), tmpbuf,
+ valbuf);
+ }
break;
- case ARM_FLOAT_SOFT:
+ case ARM_FLOAT_SOFT_FPA:
case ARM_FLOAT_SOFT_VFP:
- memcpy (valbuf, ®buf[REGISTER_BYTE (ARM_A1_REGNUM)],
- TYPE_LENGTH (type));
+ regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
+ if (TYPE_LENGTH (type) > 4)
+ regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
+ valbuf + INT_REGISTER_RAW_SIZE);
break;
default:
break;
}
}
+ else if (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF
+ || TYPE_CODE (type) == TYPE_CODE_ENUM)
+ {
+ /* If the the type is a plain integer, then the access is
+ straight-forward. Otherwise we have to play around a bit more. */
+ int len = TYPE_LENGTH (type);
+ int regno = ARM_A1_REGNUM;
+ ULONGEST tmp;
+
+ while (len > 0)
+ {
+ /* By using store_unsigned_integer we avoid having to do
+ anything special for small big-endian values. */
+ regcache_cooked_read_unsigned (regs, regno++, &tmp);
+ store_unsigned_integer (valbuf,
+ (len > INT_REGISTER_RAW_SIZE
+ ? INT_REGISTER_RAW_SIZE : len),
+ tmp);
+ len -= INT_REGISTER_RAW_SIZE;
+ valbuf += INT_REGISTER_RAW_SIZE;
+ }
+ }
else
- memcpy (valbuf, ®buf[REGISTER_BYTE (ARM_A1_REGNUM)],
- TYPE_LENGTH (type));
+ {
+ /* For a structure or union the behaviour is as if the value had
+ been stored to word-aligned memory and then loaded into
+ registers with 32-bit load instruction(s). */
+ int len = TYPE_LENGTH (type);
+ int regno = ARM_A1_REGNUM;
+ bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+
+ while (len > 0)
+ {
+ regcache_cooked_read (regs, regno++, tmpbuf);
+ memcpy (valbuf, tmpbuf,
+ len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
+ len -= INT_REGISTER_RAW_SIZE;
+ valbuf += INT_REGISTER_RAW_SIZE;
+ }
+ }
}
/* Extract from an array REGBUF containing the (raw) register state
/* In the ARM ABI, "integer" like aggregate types are returned in
registers. For an aggregate type to be integer like, its size
- must be less than or equal to REGISTER_SIZE and the offset of
- each addressable subfield must be zero. Note that bit fields are
- not addressable, and all addressable subfields of unions always
- start at offset zero.
+ must be less than or equal to DEPRECATED_REGISTER_SIZE and the
+ offset of each addressable subfield must be zero. Note that bit
+ fields are not addressable, and all addressable subfields of
+ unions always start at offset zero.
This function is based on the behaviour of GCC 2.95.1.
See: gcc/arm.c: arm_return_in_memory() for details.
/* All aggregate types that won't fit in a register must be returned
in memory. */
- if (TYPE_LENGTH (type) > REGISTER_SIZE)
+ if (TYPE_LENGTH (type) > DEPRECATED_REGISTER_SIZE)
{
return 1;
}
int i;
/* Need to check if this struct/union is "integer" like. For
this to be true, its size must be less than or equal to
- REGISTER_SIZE and the offset of each addressable subfield
- must be zero. Note that bit fields are not addressable, and
- unions always start at offset zero. If any of the subfields
- is a floating point type, the struct/union cannot be an
- integer type. */
+ DEPRECATED_REGISTER_SIZE and the offset of each addressable
+ subfield must be zero. Note that bit fields are not
+ addressable, and unions always start at offset zero. If any
+ of the subfields is a floating point type, the struct/union
+ cannot be an integer type. */
/* For each field in the object, check:
1) Is it FP? --> yes, nRc = 1;
TYPE, given in virtual format. */
static void
-arm_store_return_value (struct type *type, char *valbuf)
+arm_store_return_value (struct type *type, struct regcache *regs,
+ const void *src)
{
+ const bfd_byte *valbuf = src;
+
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
char buf[ARM_MAX_REGISTER_RAW_SIZE];
- switch (tdep->fp_model)
+ switch (arm_get_fp_model (current_gdbarch))
{
case ARM_FLOAT_FPA:
- convert_to_extended (valbuf, buf);
- deprecated_write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
- FP_REGISTER_RAW_SIZE);
+ convert_to_extended (floatformat_from_type (type), buf, valbuf);
+ regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
break;
- case ARM_FLOAT_SOFT:
+ case ARM_FLOAT_SOFT_FPA:
case ARM_FLOAT_SOFT_VFP:
- deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
- TYPE_LENGTH (type));
+ regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
+ if (TYPE_LENGTH (type) > 4)
+ regcache_cooked_write (regs, ARM_A1_REGNUM + 1,
+ valbuf + INT_REGISTER_RAW_SIZE);
break;
default:
break;
}
}
- else
- deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
- TYPE_LENGTH (type));
-}
+ else if (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF
+ || TYPE_CODE (type) == TYPE_CODE_ENUM)
+ {
+ if (TYPE_LENGTH (type) <= 4)
+ {
+ /* Values of one word or less are zero/sign-extended and
+ returned in r0. */
+ bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+ LONGEST val = unpack_long (type, valbuf);
-/* Store the address of the place in which to copy the structure the
- subroutine will return. This is called from call_function. */
+ store_signed_integer (tmpbuf, INT_REGISTER_RAW_SIZE, val);
+ regcache_cooked_write (regs, ARM_A1_REGNUM, tmpbuf);
+ }
+ else
+ {
+ /* Integral values greater than one word are stored in consecutive
+ registers starting with r0. This will always be a multiple of
+ the regiser size. */
+ int len = TYPE_LENGTH (type);
+ int regno = ARM_A1_REGNUM;
-static void
-arm_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
-{
- write_register (ARM_A1_REGNUM, addr);
+ while (len > 0)
+ {
+ regcache_cooked_write (regs, regno++, valbuf);
+ len -= INT_REGISTER_RAW_SIZE;
+ valbuf += INT_REGISTER_RAW_SIZE;
+ }
+ }
+ }
+ else
+ {
+ /* For a structure or union the behaviour is as if the value had
+ been stored to word-aligned memory and then loaded into
+ registers with 32-bit load instruction(s). */
+ int len = TYPE_LENGTH (type);
+ int regno = ARM_A1_REGNUM;
+ bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+
+ while (len > 0)
+ {
+ memcpy (tmpbuf, valbuf,
+ len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
+ regcache_cooked_write (regs, regno++, tmpbuf);
+ len -= INT_REGISTER_RAW_SIZE;
+ valbuf += INT_REGISTER_RAW_SIZE;
+ }
+ }
}
static int
INT_REGISTER_RAW_SIZE))
return 0;
- *pc = extract_address (buf, INT_REGISTER_RAW_SIZE);
+ *pc = extract_unsigned_integer (buf, INT_REGISTER_RAW_SIZE);
return 1;
}
return 0; /* not a stub */
}
-/* If the user changes the register disassembly flavor used for info
- register and other commands, we have to also switch the flavor used
- in opcodes for disassembly output. This function is run in the set
- disassembly_flavor command, and does that. */
+static void
+set_arm_command (char *args, int from_tty)
+{
+ printf_unfiltered ("\"set arm\" must be followed by an apporpriate subcommand.\n");
+ help_list (setarmcmdlist, "set arm ", all_commands, gdb_stdout);
+}
+
+static void
+show_arm_command (char *args, int from_tty)
+{
+ cmd_show_list (showarmcmdlist, from_tty, "");
+}
+
+enum arm_float_model
+arm_get_fp_model (struct gdbarch *gdbarch)
+{
+ if (arm_fp_model == ARM_FLOAT_AUTO)
+ return gdbarch_tdep (gdbarch)->fp_model;
+
+ return arm_fp_model;
+}
+
+static void
+arm_set_fp (struct gdbarch *gdbarch)
+{
+ enum arm_float_model fp_model = arm_get_fp_model (gdbarch);
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE
+ && (fp_model == ARM_FLOAT_SOFT_FPA || fp_model == ARM_FLOAT_FPA))
+ {
+ set_gdbarch_double_format (gdbarch,
+ &floatformat_ieee_double_littlebyte_bigword);
+ set_gdbarch_long_double_format
+ (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
+ }
+ else
+ {
+ set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
+ set_gdbarch_long_double_format (gdbarch,
+ &floatformat_ieee_double_little);
+ }
+}
+
+static void
+set_fp_model_sfunc (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ enum arm_float_model fp_model;
+
+ for (fp_model = ARM_FLOAT_AUTO; fp_model != ARM_FLOAT_LAST; fp_model++)
+ if (strcmp (current_fp_model, fp_model_strings[fp_model]) == 0)
+ {
+ arm_fp_model = fp_model;
+ break;
+ }
+
+ if (fp_model == ARM_FLOAT_LAST)
+ internal_error (__FILE__, __LINE__, "Invalid fp model accepted: %s.",
+ current_fp_model);
+
+ if (gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm)
+ arm_set_fp (current_gdbarch);
+}
+
+static void
+show_fp_model (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ if (arm_fp_model == ARM_FLOAT_AUTO
+ && gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_arm)
+ printf_filtered (" - the default for the current ABI is \"%s\".\n",
+ fp_model_strings[tdep->fp_model]);
+}
+
+/* If the user changes the register disassembly style used for info
+ register and other commands, we have to also switch the style used
+ in opcodes for disassembly output. This function is run in the "set
+ arm disassembly" command, and does that. */
static void
-set_disassembly_flavor_sfunc (char *args, int from_tty,
+set_disassembly_style_sfunc (char *args, int from_tty,
struct cmd_list_element *c)
{
- set_disassembly_flavor ();
+ set_disassembly_style ();
}
\f
/* Return the ARM register name corresponding to register I. */
}
static void
-set_disassembly_flavor (void)
+set_disassembly_style (void)
{
const char *setname, *setdesc, **regnames;
int numregs, j;
- /* Find the flavor that the user wants in the opcodes table. */
+ /* Find the style that the user wants in the opcodes table. */
int current = 0;
numregs = get_arm_regnames (current, &setname, &setdesc, ®names);
- while ((disassembly_flavor != setname)
- && (current < num_flavor_options))
+ while ((disassembly_style != setname)
+ && (current < num_disassembly_options))
get_arm_regnames (++current, &setname, &setdesc, ®names);
current_option = current;
set_arm_regname_option (current);
}
-/* arm_othernames implements the "othernames" command. This is kind
- of hacky, and I prefer the set-show disassembly-flavor which is
- also used for the x86 gdb. I will keep this around, however, in
- case anyone is actually using it. */
+/* arm_othernames implements the "othernames" command. This is deprecated
+ by the "set arm disassembly" command. */
static void
arm_othernames (char *names, int n)
{
/* Circle through the various flavors. */
- current_option = (current_option + 1) % num_flavor_options;
+ current_option = (current_option + 1) % num_disassembly_options;
- disassembly_flavor = valid_flavors[current_option];
- set_disassembly_flavor ();
+ disassembly_style = valid_disassembly_styles[current_option];
+ set_disassembly_style ();
}
/* Fetch, and possibly build, an appropriate link_map_offsets structure
{
struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
- enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
/* Try to deterimine the ABI of the object we are loading. */
- if (info.abfd != NULL)
+ if (info.abfd != NULL && info.osabi == GDB_OSABI_UNKNOWN)
{
- osabi = gdbarch_lookup_osabi (info.abfd);
- if (osabi == GDB_OSABI_UNKNOWN)
+ switch (bfd_get_flavour (info.abfd))
{
- switch (bfd_get_flavour (info.abfd))
- {
- case bfd_target_aout_flavour:
- /* Assume it's an old APCS-style ABI. */
- osabi = GDB_OSABI_ARM_APCS;
- break;
+ case bfd_target_aout_flavour:
+ /* Assume it's an old APCS-style ABI. */
+ info.osabi = GDB_OSABI_ARM_APCS;
+ break;
- case bfd_target_coff_flavour:
- /* Assume it's an old APCS-style ABI. */
- /* XXX WinCE? */
- osabi = GDB_OSABI_ARM_APCS;
- break;
+ case bfd_target_coff_flavour:
+ /* Assume it's an old APCS-style ABI. */
+ /* XXX WinCE? */
+ info.osabi = GDB_OSABI_ARM_APCS;
+ break;
- default:
- /* Leave it as "unknown". */
- }
+ default:
+ /* Leave it as "unknown". */
+ break;
}
}
- /* Find a candidate among extant architectures. */
- for (arches = gdbarch_list_lookup_by_info (arches, &info);
- arches != NULL;
- arches = gdbarch_list_lookup_by_info (arches->next, &info))
- {
- /* Make sure the ABI selection matches. */
- tdep = gdbarch_tdep (arches->gdbarch);
- if (tdep && tdep->osabi == osabi)
- return arches->gdbarch;
- }
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
tdep = xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
- tdep->osabi = osabi;
+ /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
+ ready to unwind the PC first (see frame.c:get_prev_frame()). */
+ set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
- /* This is the way it has always defaulted. */
- tdep->fp_model = ARM_FLOAT_FPA;
+ /* We used to default to FPA for generic ARM, but almost nobody uses that
+ now, and we now provide a way for the user to force the model. So
+ default to the most useful variant. */
+ tdep->fp_model = ARM_FLOAT_SOFT_FPA;
/* Breakpoints. */
switch (info.byte_order)
tdep->lowest_pc = 0x20;
tdep->jb_pc = -1; /* Longjump support not enabled by default. */
- set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
- set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
-
- set_gdbarch_call_dummy_p (gdbarch, 1);
- set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
-
- set_gdbarch_call_dummy_words (gdbarch, arm_call_dummy_words);
- set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
- set_gdbarch_call_dummy_start_offset (gdbarch, 0);
- set_gdbarch_call_dummy_length (gdbarch, 0);
+ set_gdbarch_deprecated_call_dummy_words (gdbarch, arm_call_dummy_words);
+ set_gdbarch_deprecated_sizeof_call_dummy_words (gdbarch, 0);
- set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
-
- set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
- set_gdbarch_push_return_address (gdbarch, arm_push_return_address);
-
- set_gdbarch_push_arguments (gdbarch, arm_push_arguments);
- set_gdbarch_coerce_float_to_double (gdbarch,
- standard_coerce_float_to_double);
+ set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call);
/* Frame handling. */
- set_gdbarch_frame_chain_valid (gdbarch, arm_frame_chain_valid);
- set_gdbarch_init_extra_frame_info (gdbarch, arm_init_extra_frame_info);
- set_gdbarch_read_fp (gdbarch, arm_read_fp);
- set_gdbarch_frame_chain (gdbarch, arm_frame_chain);
+ set_gdbarch_deprecated_frame_chain_valid (gdbarch, arm_frame_chain_valid);
+ set_gdbarch_deprecated_init_extra_frame_info (gdbarch, arm_init_extra_frame_info);
+ set_gdbarch_deprecated_target_read_fp (gdbarch, arm_read_fp);
+ set_gdbarch_deprecated_frame_chain (gdbarch, arm_frame_chain);
set_gdbarch_frameless_function_invocation
(gdbarch, arm_frameless_function_invocation);
- set_gdbarch_frame_saved_pc (gdbarch, arm_frame_saved_pc);
+ set_gdbarch_deprecated_frame_saved_pc (gdbarch, arm_frame_saved_pc);
set_gdbarch_frame_args_address (gdbarch, arm_frame_args_address);
set_gdbarch_frame_locals_address (gdbarch, arm_frame_locals_address);
set_gdbarch_frame_num_args (gdbarch, arm_frame_num_args);
set_gdbarch_frame_args_skip (gdbarch, 0);
- set_gdbarch_frame_init_saved_regs (gdbarch, arm_frame_init_saved_regs);
- set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
- set_gdbarch_pop_frame (gdbarch, arm_pop_frame);
+ set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, arm_frame_init_saved_regs);
+ set_gdbarch_deprecated_pop_frame (gdbarch, arm_pop_frame);
/* Address manipulation. */
set_gdbarch_smash_text_address (gdbarch, arm_smash_text_address);
set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
/* Get the PC when a frame might not be available. */
- set_gdbarch_saved_pc_after_call (gdbarch, arm_saved_pc_after_call);
+ set_gdbarch_deprecated_saved_pc_after_call (gdbarch, arm_saved_pc_after_call);
/* The stack grows downward. */
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
/* Information about registers, etc. */
set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
- set_gdbarch_fp_regnum (gdbarch, ARM_FP_REGNUM); /* ??? */
+ set_gdbarch_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM); /* ??? */
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
set_gdbarch_register_byte (gdbarch, arm_register_byte);
- set_gdbarch_register_bytes (gdbarch,
- (NUM_GREGS * INT_REGISTER_RAW_SIZE
- + NUM_FREGS * FP_REGISTER_RAW_SIZE
- + NUM_SREGS * STATUS_REGISTER_SIZE));
+ set_gdbarch_deprecated_register_bytes (gdbarch,
+ (NUM_GREGS * INT_REGISTER_RAW_SIZE
+ + NUM_FREGS * FP_REGISTER_RAW_SIZE
+ + NUM_SREGS * STATUS_REGISTER_SIZE));
set_gdbarch_num_regs (gdbarch, NUM_GREGS + NUM_FREGS + NUM_SREGS);
set_gdbarch_register_raw_size (gdbarch, arm_register_raw_size);
set_gdbarch_register_virtual_size (gdbarch, arm_register_virtual_size);
- set_gdbarch_max_register_raw_size (gdbarch, FP_REGISTER_RAW_SIZE);
- set_gdbarch_max_register_virtual_size (gdbarch, FP_REGISTER_VIRTUAL_SIZE);
+ set_gdbarch_deprecated_max_register_raw_size (gdbarch, FP_REGISTER_RAW_SIZE);
+ set_gdbarch_deprecated_max_register_virtual_size (gdbarch, FP_REGISTER_VIRTUAL_SIZE);
set_gdbarch_register_virtual_type (gdbarch, arm_register_type);
/* Internal <-> external register number maps. */
set_gdbarch_register_sim_regno (gdbarch, arm_register_sim_regno);
/* Integer registers are 4 bytes. */
- set_gdbarch_register_size (gdbarch, 4);
+ set_gdbarch_deprecated_register_size (gdbarch, 4);
set_gdbarch_register_name (gdbarch, arm_register_name);
/* Returning results. */
- set_gdbarch_deprecated_extract_return_value (gdbarch, arm_extract_return_value);
- set_gdbarch_deprecated_store_return_value (gdbarch, arm_store_return_value);
- set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
+ set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
set_gdbarch_extract_struct_value_address (gdbarch,
arm_extract_struct_value_address);
/* XXX For an RDI target we should ask the target if it can single-step. */
set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+ /* Disassembly. */
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_arm);
+
/* Minsymbol frobbing. */
set_gdbarch_elf_make_msymbol_special (gdbarch, arm_elf_make_msymbol_special);
set_gdbarch_coff_make_msymbol_special (gdbarch,
arm_coff_make_msymbol_special);
/* Hook in the ABI-specific overrides, if they have been registered. */
- gdbarch_init_osabi (info, gdbarch, osabi);
+ gdbarch_init_osabi (info, gdbarch);
/* Now we have tuned the configuration, set a few final things,
based on what the OS ABI has told us. */
case BFD_ENDIAN_LITTLE:
set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
- if (tdep->fp_model == ARM_FLOAT_VFP
- || tdep->fp_model == ARM_FLOAT_SOFT_VFP)
- {
- set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
- set_gdbarch_long_double_format (gdbarch,
- &floatformat_ieee_double_little);
- }
- else
- {
- set_gdbarch_double_format
- (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
- set_gdbarch_long_double_format
- (gdbarch, &floatformat_ieee_double_littlebyte_bigword);
- }
+ arm_set_fp (gdbarch);
break;
default:
"arm_gdbarch_init: bad byte order for float format");
}
- /* We can't use SIZEOF_FRAME_SAVED_REGS here, since that still
- references the old architecture vector, not the one we are
- building here. */
- if (prologue_cache.saved_regs != NULL)
- xfree (prologue_cache.saved_regs);
-
- /* We can't use NUM_REGS nor NUM_PSEUDO_REGS here, since that still
- references the old architecture vector, not the one we are
- building here. */
- prologue_cache.saved_regs = (CORE_ADDR *)
- xcalloc (1, (sizeof (CORE_ADDR)
- * (gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))));
-
return gdbarch;
}
if (tdep == NULL)
return;
- fprintf_unfiltered (file, "arm_dump_tdep: OS ABI = %s\n",
- gdbarch_osabi_name (tdep->osabi));
-
fprintf_unfiltered (file, "arm_dump_tdep: Lowest pc = 0x%lx",
(unsigned long) tdep->lowest_pc);
}
{
struct ui_file *stb;
long length;
- struct cmd_list_element *new_cmd;
+ struct cmd_list_element *new_set, *new_show;
const char *setname;
const char *setdesc;
const char **regnames;
arm_elf_osabi_sniffer);
/* Register some ABI variants for embedded systems. */
- gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_EABI_V1,
+ gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V1,
arm_init_abi_eabi_v1);
- gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_EABI_V2,
+ gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V2,
arm_init_abi_eabi_v2);
- gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_ARM_APCS,
+ gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_APCS,
arm_init_abi_apcs);
- tm_print_insn = gdb_print_insn_arm;
-
/* Get the number of possible sets of register names defined in opcodes. */
- num_flavor_options = get_arm_regname_num_options ();
+ num_disassembly_options = get_arm_regname_num_options ();
+
+ /* Add root prefix command for all "set arm"/"show arm" commands. */
+ add_prefix_cmd ("arm", no_class, set_arm_command,
+ "Various ARM-specific commands.",
+ &setarmcmdlist, "set arm ", 0, &setlist);
+
+ add_prefix_cmd ("arm", no_class, show_arm_command,
+ "Various ARM-specific commands.",
+ &showarmcmdlist, "show arm ", 0, &showlist);
/* Sync the opcode insn printer with our register viewer. */
parse_arm_disassembler_option ("reg-names-std");
/* Begin creating the help text. */
stb = mem_fileopen ();
- fprintf_unfiltered (stb, "Set the disassembly flavor.\n\
-The valid values are:\n");
+ fprintf_unfiltered (stb, "Set the disassembly style.\n"
+ "The valid values are:\n");
/* Initialize the array that will be passed to add_set_enum_cmd(). */
- valid_flavors = xmalloc ((num_flavor_options + 1) * sizeof (char *));
- for (i = 0; i < num_flavor_options; i++)
+ valid_disassembly_styles
+ = xmalloc ((num_disassembly_options + 1) * sizeof (char *));
+ for (i = 0; i < num_disassembly_options; i++)
{
numregs = get_arm_regnames (i, &setname, &setdesc, ®names);
- valid_flavors[i] = setname;
+ valid_disassembly_styles[i] = setname;
fprintf_unfiltered (stb, "%s - %s\n", setname,
setdesc);
/* Copy the default names (if found) and synchronize disassembler. */
if (!strcmp (setname, "std"))
{
- disassembly_flavor = setname;
+ disassembly_style = setname;
current_option = i;
for (j = 0; j < numregs; j++)
arm_register_names[j] = (char *) regnames[j];
}
}
/* Mark the end of valid options. */
- valid_flavors[num_flavor_options] = NULL;
+ valid_disassembly_styles[num_disassembly_options] = NULL;
/* Finish the creation of the help text. */
fprintf_unfiltered (stb, "The default is \"std\".");
helptext = ui_file_xstrdup (stb, &length);
ui_file_delete (stb);
- /* Add the disassembly-flavor command. */
- new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
- valid_flavors,
- &disassembly_flavor,
+ /* Add the deprecated disassembly-flavor command. */
+ new_set = add_set_enum_cmd ("disassembly-flavor", no_class,
+ valid_disassembly_styles,
+ &disassembly_style,
helptext,
&setlist);
- set_cmd_sfunc (new_cmd, set_disassembly_flavor_sfunc);
- add_show_from_set (new_cmd, &showlist);
-
- /* ??? Maybe this should be a boolean. */
- add_show_from_set (add_set_cmd ("apcs32", no_class,
- var_zinteger, (char *) &arm_apcs_32,
- "Set usage of ARM 32-bit mode.\n", &setlist),
- &showlist);
+ set_cmd_sfunc (new_set, set_disassembly_style_sfunc);
+ deprecate_cmd (new_set, "set arm disassembly");
+ deprecate_cmd (add_show_from_set (new_set, &showlist),
+ "show arm disassembly");
+
+ /* And now add the new interface. */
+ new_set = add_set_enum_cmd ("disassembler", no_class,
+ valid_disassembly_styles, &disassembly_style,
+ helptext, &setarmcmdlist);
+
+ set_cmd_sfunc (new_set, set_disassembly_style_sfunc);
+ add_show_from_set (new_set, &showarmcmdlist);
+
+ add_setshow_cmd_full ("apcs32", no_class,
+ var_boolean, (char *) &arm_apcs_32,
+ "Set usage of ARM 32-bit mode.",
+ "Show usage of ARM 32-bit mode.",
+ NULL, NULL,
+ &setlist, &showlist, &new_set, &new_show);
+ deprecate_cmd (new_set, "set arm apcs32");
+ deprecate_cmd (new_show, "show arm apcs32");
+
+ add_setshow_boolean_cmd ("apcs32", no_class, &arm_apcs_32,
+ "Set usage of ARM 32-bit mode. "
+ "When off, a 26-bit PC will be used.",
+ "Show usage of ARM 32-bit mode. "
+ "When off, a 26-bit PC will be used.",
+ NULL, NULL,
+ &setarmcmdlist, &showarmcmdlist);
+
+ /* Add a command to allow the user to force the FPU model. */
+ new_set = add_set_enum_cmd
+ ("fpu", no_class, fp_model_strings, ¤t_fp_model,
+ "Set the floating point type.\n"
+ "auto - Determine the FP typefrom the OS-ABI.\n"
+ "softfpa - Software FP, mixed-endian doubles on little-endian ARMs.\n"
+ "fpa - FPA co-processor (GCC compiled).\n"
+ "softvfp - Software FP with pure-endian doubles.\n"
+ "vfp - VFP co-processor.",
+ &setarmcmdlist);
+ set_cmd_sfunc (new_set, set_fp_model_sfunc);
+ set_cmd_sfunc (add_show_from_set (new_set, &showarmcmdlist), show_fp_model);
/* Add the deprecated "othernames" command. */
-
- add_com ("othernames", class_obscure, arm_othernames,
- "Switch to the next set of register names.");
-
- /* Fill in the prologue_cache fields. */
- prologue_cache.saved_regs = NULL;
- prologue_cache.extra_info = (struct frame_extra_info *)
- xcalloc (1, sizeof (struct frame_extra_info));
+ deprecate_cmd (add_com ("othernames", class_obscure, arm_othernames,
+ "Switch to the next set of register names."),
+ "set arm disassembly");
/* Debugging flag. */
- add_show_from_set (add_set_cmd ("arm", class_maintenance, var_zinteger,
- &arm_debug, "Set arm debugging.\n\
-When non-zero, arm specific debugging is enabled.", &setdebuglist),
- &showdebuglist);
+ add_setshow_boolean_cmd ("arm", class_maintenance, &arm_debug,
+ "Set ARM debugging. "
+ "When on, arm-specific debugging is enabled.",
+ "Show ARM debugging. "
+ "When on, arm-specific debugging is enabled.",
+ NULL, NULL,
+ &setdebuglist, &showdebuglist);
}