/* Common target dependent code for GDB on ARM systems.
- Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000
- Free Software Foundation, Inc.
+ Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
+ 2001 Free Software Foundation, Inc.
This file is part of GDB.
#include "coff/internal.h" /* Internal format of COFF symbols in BFD */
#include "dis-asm.h" /* For register flavors. */
#include <ctype.h> /* for isupper () */
+#include "regcache.h"
+#include "doublest.h"
+#include "value.h"
+#include "solib-svr4.h"
/* Each OS has a different mechanism for accessing the various
registers stored in the sigcontext structure.
#define MAKE_THUMB_ADDR(addr) ((addr) | 1)
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
-#define SWAP_TARGET_AND_HOST(buffer,len) \
- do \
- { \
- if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
- { \
- char tmp; \
- char *p = (char *)(buffer); \
- char *q = ((char *)(buffer)) + len - 1; \
- for (; p < q; p++, q--) \
- { \
- tmp = *q; \
- *q = *p; \
- *p = tmp; \
- } \
- } \
- } \
- while (0)
-
/* Will a function return an aggregate type in memory or in a
register? Return 0 if an aggregate type can be returned in a
register, 1 if it must be returned in memory. */
unsigned long inst;
CORE_ADDR skip_pc;
CORE_ADDR func_addr, func_end;
+ char *func_name;
struct symtab_and_line sal;
/* See what the symbol table says. */
- if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
{
- sal = find_pc_line (func_addr, 0);
- if ((sal.line != 0) && (sal.end < func_end))
- return sal.end;
+ struct symbol *sym;
+
+ /* Found a function. */
+ sym = lookup_symbol (func_name, NULL, VAR_NAMESPACE, NULL, NULL);
+ if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
+ {
+ /* Don't use this trick for assembly source files. */
+ sal = find_pc_line (func_addr, 0);
+ if ((sal.line != 0) && (sal.end < func_end))
+ return sal.end;
+ }
}
/* Check if this is Thumb code. */
void
arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
- value_ptr *args, struct type *type, int gcc_p)
+ struct value **args, struct type *type, int gcc_p)
{
static short thumb_dummy[4] =
{
general registers and/or on the stack. */
CORE_ADDR
-arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
+arm_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
char *fp;
{
int len;
char *val;
- double dbl_arg;
CORE_ADDR regval;
enum type_code typecode;
struct type *arg_type, *target_type;
calling the function. */
if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
{
- float f;
- double d;
- char * bufo = (char *) &d;
- char * bufd = (char *) &dbl_arg;
-
- len = sizeof (double);
- f = *(float *) val;
- SWAP_TARGET_AND_HOST (&f, sizeof (float)); /* adjust endianess */
- d = f;
- /* We must revert the longwords so they get loaded into the
- the right registers. */
- memcpy (bufd, bufo + len / 2, len / 2);
- SWAP_TARGET_AND_HOST (bufd, len / 2); /* adjust endianess */
- memcpy (bufd + len / 2, bufo, len / 2);
- SWAP_TARGET_AND_HOST (bufd + len / 2, len / 2); /* adjust endianess */
- val = (char *) &dbl_arg;
+ DOUBLEST dblval;
+ dblval = extract_floating (val, len);
+ len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
+ val = alloca (len);
+ store_floating (val, len, dblval);
}
#if 1
/* I don't know why this code was disable. The only logical use
print_fpu_flags (status);
}
-#if 0
-/* FIXME: The generated assembler works but sucks. Instead of using
- r0, r1 it pushes them on the stack, then loads them into r3, r4 and
- uses those registers. I must be missing something. ScottB */
-
-void
-convert_from_extended (void *ptr, void *dbl)
+struct type *
+arm_register_type (int regnum)
{
- __asm__ ("
- ldfe f0,[%0]
- stfd f0,[%1] "
-: /* no output */
-: "r" (ptr), "r" (dbl));
+ if (regnum >= F0_REGNUM && regnum < F0_REGNUM + NUM_FREGS)
+ {
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ return builtin_type_arm_ext_big;
+ else
+ return builtin_type_arm_ext_littlebyte_bigword;
+ }
+ else
+ return builtin_type_int32;
}
-void
-convert_to_extended (void *dbl, void *ptr)
-{
- __asm__ ("
- ldfd f0,[%0]
- stfe f0,[%1] "
-: /* no output */
-: "r" (dbl), "r" (ptr));
-}
-#else
+/* NOTE: cagney/2001-08-20: Both convert_from_extended() and
+ convert_to_extended() use floatformat_arm_ext_littlebyte_bigword.
+ It is thought that this is is the floating-point register format on
+ little-endian systems. */
+
static void
convert_from_extended (void *ptr, void *dbl)
{
- *(double *) dbl = *(double *) ptr;
+ DOUBLEST d;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ floatformat_to_doublest (&floatformat_arm_ext_big, ptr, &d);
+ else
+ floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
+ ptr, &d);
+ floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
}
void
convert_to_extended (void *dbl, void *ptr)
{
- *(double *) ptr = *(double *) dbl;
-}
-#endif
-
-/* Nonzero if register N requires conversion from raw format to
- virtual format. */
-
-int
-arm_register_convertible (unsigned int regnum)
-{
- return ((regnum - F0_REGNUM) < 8);
-}
-
-/* Convert data from raw format for register REGNUM in buffer FROM to
- virtual format with type TYPE in buffer TO. */
-
-void
-arm_register_convert_to_virtual (unsigned int regnum, struct type *type,
- void *from, void *to)
-{
- double val;
-
- convert_from_extended (from, &val);
- store_floating (to, TYPE_LENGTH (type), val);
-}
-
-/* Convert data from virtual format with type TYPE in buffer FROM to
- raw format for register REGNUM in buffer TO. */
-
-void
-arm_register_convert_to_raw (unsigned int regnum, struct type *type,
- void *from, void *to)
-{
- double val = extract_floating (from, TYPE_LENGTH (type));
-
- convert_to_extended (&val, to);
+ DOUBLEST d;
+ floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
+ else
+ floatformat_from_doublest (&floatformat_arm_ext_littlebyte_bigword,
+ &d, dbl);
}
static int
return 1;
}
+/* Support routines for single stepping. Calculate the next PC value. */
#define submask(x) ((1L << ((x) + 1)) - 1)
#define bit(obj,st) (((obj) >> (st)) & 1)
#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
return nextpc;
}
+/* single_step() is called just before we want to resume the inferior,
+ if we want to single-step it but there is no hardware or kernel
+ single-step support. We find the target of the coming instruction
+ and breakpoint it.
+
+ single_step is also called just after the inferior stops. If we had
+ set up a simulated single-step, we undo our damage. */
+
+void
+arm_software_single_step (ignore, insert_bpt)
+ int ignore; /* Signal, not needed */
+ int insert_bpt;
+{
+ static int next_pc; /* State between setting and unsetting. */
+ static char break_mem[BREAKPOINT_MAX]; /* Temporary storage for mem@bpt */
+
+ if (insert_bpt)
+ {
+ next_pc = arm_get_next_pc (read_register (PC_REGNUM));
+ target_insert_breakpoint (next_pc, break_mem);
+ }
+ else
+ target_remove_breakpoint (next_pc, break_mem);
+}
+
#include "bfd-in2.h"
#include "libcoff.h"
set_disassembly_flavor ();
}
+/* Fetch, and possibly build, an appropriate link_map_offsets structure
+ for ARM linux targets using the struct offsets defined in <link.h>.
+ Note, however, that link.h is not actually referred to in this file.
+ Instead, the relevant structs offsets were obtained from examining
+ link.h. (We can't refer to link.h from this file because the host
+ system won't necessarily have it, or if it does, the structs which
+ it defines will refer to the host system, not the target.) */
+
+struct link_map_offsets *
+arm_linux_svr4_fetch_link_map_offsets (void)
+{
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = 0;
+
+ if (lmp == 0)
+ {
+ lmp = &lmo;
+
+ lmo.r_debug_size = 8; /* Actual size is 20, but this is all we
+ need. */
+
+ lmo.r_map_offset = 4;
+ lmo.r_map_size = 4;
+
+ lmo.link_map_size = 20; /* Actual size is 552, but this is all we
+ need. */
+
+ lmo.l_addr_offset = 0;
+ lmo.l_addr_size = 4;
+
+ lmo.l_name_offset = 4;
+ lmo.l_name_size = 4;
+
+ lmo.l_next_offset = 12;
+ lmo.l_next_size = 4;
+
+ lmo.l_prev_offset = 16;
+ lmo.l_prev_size = 4;
+ }
+
+ return lmp;
+}
+
void
_initialize_arm_tdep (void)
{