/* 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.
+
+ SIGCONTEXT_REGISTER_ADDRESS should be defined to the name (or
+ function pointer) which may be used to determine the addresses
+ of the various saved registers in the sigcontext structure.
+
+ For the ARM target, there are three parameters to this function.
+ The first is the pc value of the frame under consideration, the
+ second the stack pointer of this frame, and the last is the
+ register number to fetch.
+
+ If the tm.h file does not define this macro, then it's assumed that
+ no mechanism is needed and we define SIGCONTEXT_REGISTER_ADDRESS to
+ be 0.
+
+ When it comes time to multi-arching this code, see the identically
+ named machinery in ia64-tdep.c for an example of how it could be
+ done. It should not be necessary to modify the code below where
+ this macro is used. */
+
+#ifdef SIGCONTEXT_REGISTER_ADDRESS
+#ifndef SIGCONTEXT_REGISTER_ADDRESS_P
+#define SIGCONTEXT_REGISTER_ADDRESS_P() 1
+#endif
+#else
+#define SIGCONTEXT_REGISTER_ADDRESS(SP,PC,REG) 0
+#define SIGCONTEXT_REGISTER_ADDRESS_P() 0
+#endif
extern void _initialize_arm_tdep (void);
#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. */
function. */
int
-arm_pc_is_thumb (bfd_vma memaddr)
+arm_pc_is_thumb (CORE_ADDR memaddr)
{
struct minimal_symbol *sym;
dummy being called from a Thumb function. */
int
-arm_pc_is_thumb_dummy (bfd_vma memaddr)
+arm_pc_is_thumb_dummy (CORE_ADDR memaddr)
{
CORE_ADDR sp = read_sp ();
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. */
fi->framereg = prologue_cache.framereg;
fi->framesize = prologue_cache.framesize;
fi->frameoffset = prologue_cache.frameoffset;
- for (i = 0; i <= NUM_REGS; i++)
+ for (i = 0; i < NUM_REGS; i++)
fi->fsr.regs[i] = prologue_cache.fsr.regs[i];
return 1;
}
prologue_cache.framesize = fi->framesize;
prologue_cache.frameoffset = fi->frameoffset;
- for (i = 0; i <= NUM_REGS; i++)
+ for (i = 0; i < NUM_REGS; i++)
prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
}
arm_scan_prologue (struct frame_info *fi)
{
int regno, sp_offset, fp_offset;
+ LONGEST return_value;
CORE_ADDR prologue_start, prologue_end, current_pc;
/* Check if this function is already in the cache of frame information. */
the symbol table, peek in the stack frame to find the PC. */
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{
- /* Assume the prologue is everything between the first instruction
- in the function and the first source line. */
- 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;
- else if (sal.end < prologue_end) /* next line begins after fn end */
- prologue_end = sal.end; /* (probably means no prologue) */
+ /* 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;
+ else if (sal.end < prologue_end)
+ prologue_end = sal.end;
+
+ This mechanism is very accurate so long as the optimizer
+ doesn't move any instructions from the function body into the
+ prologue. If this happens, sal.end will be the last
+ instruction in the first hunk of prologue code just before
+ the first instruction that the scheduler has moved from
+ the body to the prologue.
+
+ In order to make sure that we scan all of the prologue
+ instructions, we use a slightly less accurate mechanism which
+ may scan more than necessary. To help compensate for this
+ lack of accuracy, the prologue scanning loop below contains
+ several clauses which'll cause the loop to terminate early if
+ an implausible prologue instruction is encountered.
+
+ The expression
+
+ prologue_start + 64
+
+ is a suitable endpoint since it accounts for the largest
+ possible prologue plus up to five instructions inserted by
+ the scheduler. */
+
+ if (prologue_end > prologue_start + 64)
+ {
+ prologue_end = prologue_start + 64; /* See above. */
+ }
}
else
{
/* Get address of the stmfd in the prologue of the callee; the saved
PC is the address of the stmfd + 8. */
- prologue_start = ADDR_BITS_REMOVE (read_memory_integer (fi->frame, 4))
- - 8;
- prologue_end = prologue_start + 64; /* This is all the insn's
- that could be in the prologue,
- plus room for 5 insn's inserted
- by the scheduler. */
+ if (!safe_read_memory_integer (fi->frame, 4, &return_value))
+ return;
+ else
+ {
+ prologue_start = ADDR_BITS_REMOVE (return_value) - 8;
+ prologue_end = prologue_start + 64; /* See above. */
+ }
}
/* Now search the prologue looking for instructions that set up the
traceback.
In the APCS, the prologue should start with "mov ip, sp" so
- if we don't see this as the first insn, we will stop. */
+ if we don't see this as the first insn, we will stop. [Note:
+ This doesn't seem to be true any longer, so it's now an optional
+ part of the prologue. - Kevin Buettner, 2001-11-20] */
sp_offset = fp_offset = 0;
if (read_memory_unsigned_integer (prologue_start, 4)
== 0xe1a0c00d) /* mov ip, sp */
+ current_pc = prologue_start + 4;
+ else
+ current_pc = prologue_start;
+
+ for (; current_pc < prologue_end; current_pc += 4)
{
- for (current_pc = prologue_start + 4; current_pc < prologue_end;
- current_pc += 4)
+ unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+
+ if ((insn & 0xffff0000) == 0xe92d0000)
+ /* stmfd sp!, {..., fp, ip, lr, pc}
+ or
+ stmfd sp!, {a1, a2, a3, a4} */
{
- unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
+ int mask = insn & 0xffff;
- if ((insn & 0xffff0000) == 0xe92d0000)
- /* stmfd sp!, {..., fp, ip, lr, pc}
- or
- stmfd sp!, {a1, a2, a3, a4} */
- {
- int mask = insn & 0xffff;
+ /* Calculate offsets of saved registers. */
+ for (regno = PC_REGNUM; regno >= 0; regno--)
+ if (mask & (1 << regno))
+ {
+ sp_offset -= 4;
+ fi->fsr.regs[regno] = sp_offset;
+ }
+ }
+ else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
+ {
+ unsigned imm = insn & 0xff; /* immediate value */
+ unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
+ imm = (imm >> rot) | (imm << (32 - rot));
+ fp_offset = -imm;
+ fi->framereg = FP_REGNUM;
+ }
+ else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
+ {
+ unsigned imm = insn & 0xff; /* immediate value */
+ unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
+ imm = (imm >> rot) | (imm << (32 - rot));
+ sp_offset -= imm;
+ }
+ else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
+ {
+ sp_offset -= 12;
+ regno = F0_REGNUM + ((insn >> 12) & 0x07);
+ fi->fsr.regs[regno] = sp_offset;
+ }
+ else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
+ {
+ int n_saved_fp_regs;
+ unsigned int fp_start_reg, fp_bound_reg;
- /* Calculate offsets of saved registers. */
- for (regno = PC_REGNUM; regno >= 0; regno--)
- if (mask & (1 << regno))
- {
- sp_offset -= 4;
- fi->fsr.regs[regno] = sp_offset;
- }
- }
- else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
+ if ((insn & 0x800) == 0x800) /* N0 is set */
{
- unsigned imm = insn & 0xff; /* immediate value */
- unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
- imm = (imm >> rot) | (imm << (32 - rot));
- fp_offset = -imm;
- fi->framereg = FP_REGNUM;
+ if ((insn & 0x40000) == 0x40000) /* N1 is set */
+ n_saved_fp_regs = 3;
+ else
+ n_saved_fp_regs = 1;
}
- else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
+ else
{
- unsigned imm = insn & 0xff; /* immediate value */
- unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
- imm = (imm >> rot) | (imm << (32 - rot));
- sp_offset -= imm;
+ if ((insn & 0x40000) == 0x40000) /* N1 is set */
+ n_saved_fp_regs = 2;
+ else
+ n_saved_fp_regs = 4;
}
- else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
+
+ fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
+ fp_bound_reg = fp_start_reg + n_saved_fp_regs;
+ for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{
sp_offset -= 12;
- regno = F0_REGNUM + ((insn >> 12) & 0x07);
- fi->fsr.regs[regno] = sp_offset;
+ fi->fsr.regs[fp_start_reg++] = sp_offset;
}
- else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
- {
- int n_saved_fp_regs;
- unsigned int fp_start_reg, fp_bound_reg;
-
- if ((insn & 0x800) == 0x800) /* N0 is set */
- {
- if ((insn & 0x40000) == 0x40000) /* N1 is set */
- n_saved_fp_regs = 3;
- else
- n_saved_fp_regs = 1;
- }
- else
- {
- if ((insn & 0x40000) == 0x40000) /* N1 is set */
- n_saved_fp_regs = 2;
- else
- n_saved_fp_regs = 4;
- }
-
- fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
- fp_bound_reg = fp_start_reg + n_saved_fp_regs;
- for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
- {
- sp_offset -= 12;
- fi->fsr.regs[fp_start_reg++] = sp_offset;
- }
- }
- else
- /* The optimizer might shove anything into the prologue,
- so we just skip what we don't recognize. */
- continue;
}
+ else if ((insn & 0xf0000000) != 0xe0000000)
+ break; /* Condition not true, exit early */
+ else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
+ break; /* Don't scan past a block load */
+ else
+ /* The optimizer might shove anything into the prologue,
+ so we just skip what we don't recognize. */
+ continue;
}
/* 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->framesize = -sp_offset;
- fi->frameoffset = fp_offset - sp_offset;
+ if (fi->framereg == FP_REGNUM)
+ fi->frameoffset = fp_offset - sp_offset;
+ else
+ fi->frameoffset = 0;
save_prologue_cache (fi);
}
arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
int reg;
+ CORE_ADDR sp;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
}
else
#endif
+
+ /* Compute stack pointer for this frame. We use this value for both the
+ sigtramp and call dummy cases. */
+ if (!fi->next)
+ sp = read_sp();
+ else
+ sp = fi->next->frame - fi->next->frameoffset + fi->next->framesize;
+
+ /* Determine whether or not we're in a sigtramp frame.
+ Unfortunately, it isn't sufficient to test
+ fi->signal_handler_caller because this value is sometimes set
+ after invoking INIT_EXTRA_FRAME_INFO. So we test *both*
+ fi->signal_handler_caller and IN_SIGTRAMP to determine if we need
+ to use the sigcontext addresses for the saved registers.
+
+ Note: If an ARM IN_SIGTRAMP method ever needs to compare against
+ the name of the function, the code below will have to be changed
+ to first fetch the name of the function and then pass this name
+ to IN_SIGTRAMP. */
+
+ if (SIGCONTEXT_REGISTER_ADDRESS_P ()
+ && (fi->signal_handler_caller || IN_SIGTRAMP (fi->pc, (char *)0)))
+ {
+ for (reg = 0; reg < NUM_REGS; reg++)
+ fi->fsr.regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, fi->pc, reg);
+
+ /* FIXME: What about thumb mode? */
+ fi->framereg = SP_REGNUM;
+ fi->frame = read_memory_integer (fi->fsr.regs[fi->framereg],
+ REGISTER_RAW_SIZE (fi->framereg));
+ fi->framesize = 0;
+ fi->frameoffset = 0;
+
+ }
+ else if (PC_IN_CALL_DUMMY (fi->pc, sp, fi->frame))
+ {
+ CORE_ADDR rp;
+ CORE_ADDR callers_sp;
+
+ /* Set rp point at the high end of the saved registers. */
+ rp = fi->frame - REGISTER_SIZE;
+
+ /* Fill in addresses of saved registers. */
+ fi->fsr.regs[PS_REGNUM] = rp;
+ rp -= REGISTER_RAW_SIZE (PS_REGNUM);
+ for (reg = PC_REGNUM; reg >= 0; reg--)
+ {
+ fi->fsr.regs[reg] = rp;
+ rp -= REGISTER_RAW_SIZE (reg);
+ }
+
+ callers_sp = read_memory_integer (fi->fsr.regs[SP_REGNUM],
+ REGISTER_RAW_SIZE (SP_REGNUM));
+ fi->framereg = FP_REGNUM;
+ fi->framesize = callers_sp - sp;
+ fi->frameoffset = fi->frame - sp;
+ }
+ else
{
arm_scan_prologue (fi);
return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
else
#endif
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame - fi->frameoffset, fi->frame))
+ {
+ return read_memory_integer (fi->fsr.regs[PC_REGNUM], REGISTER_RAW_SIZE (PC_REGNUM));
+ }
+ else
{
CORE_ADDR pc = arm_find_callers_reg (fi, LR_REGNUM);
return IS_THUMB_ADDR (pc) ? UNMAKE_THUMB_ADDR (pc) : pc;
instruction stores the PC, it stores the address of the stm
instruction itself plus 12. */
fp = sp = push_word (sp, prologue_start + 12);
- sp = push_word (sp, read_register (PC_REGNUM)); /* FIXME: was PS_REGNUM */
- sp = push_word (sp, old_sp);
- sp = push_word (sp, read_register (FP_REGNUM));
- for (regnum = 10; regnum >= 0; regnum--)
+ /* Push the processor status. */
+ sp = push_word (sp, read_register (PS_REGNUM));
+
+ /* Push all 16 registers starting with r15. */
+ for (regnum = PC_REGNUM; regnum >= 0; regnum--)
sp = push_word (sp, read_register (regnum));
+ /* Update fp (for both Thumb and ARM) and sp. */
write_register (FP_REGNUM, fp);
write_register (THUMB_FP_REGNUM, fp);
write_register (SP_REGNUM, sp);
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
return sp;
}
+/* 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. */
void
arm_pop_frame (void)
{
int regnum;
struct frame_info *frame = get_current_frame ();
+ CORE_ADDR old_SP = frame->frame - frame->frameoffset + frame->framesize;
- if (!PC_IN_CALL_DUMMY(frame->pc, frame->frame, read_fp()))
- {
- CORE_ADDR old_SP;
-
- old_SP = read_register (frame->framereg);
- for (regnum = 0; regnum < NUM_REGS; regnum++)
- if (frame->fsr.regs[regnum] != 0)
- write_register (regnum,
- read_memory_integer (frame->fsr.regs[regnum], 4));
-
- write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
- write_register (SP_REGNUM, old_SP);
- }
- else
- {
- CORE_ADDR sp;
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (frame->fsr.regs[regnum] != 0)
+ write_register (regnum,
+ read_memory_integer (frame->fsr.regs[regnum],
+ REGISTER_RAW_SIZE (regnum)));
- sp = read_register (FP_REGNUM);
- sp -= sizeof(CORE_ADDR); /* we don't care about this first word */
-
- write_register (PC_REGNUM, read_memory_integer (sp, 4));
- sp -= sizeof(CORE_ADDR);
- write_register (SP_REGNUM, read_memory_integer (sp, 4));
- sp -= sizeof(CORE_ADDR);
- write_register (FP_REGNUM, read_memory_integer (sp, 4));
- sp -= sizeof(CORE_ADDR);
-
- for (regnum = 10; regnum >= 0; regnum--)
- {
- write_register (regnum, read_memory_integer (sp, 4));
- sp -= sizeof(CORE_ADDR);
- }
- }
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+ write_register (SP_REGNUM, old_SP);
flush_cached_frames ();
}
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 == BFD_ENDIAN_BIG)
+ 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 == BFD_ENDIAN_BIG)
+ 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 == BFD_ENDIAN_BIG)
+ 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"
else
info->symbols = NULL;
- if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
return print_insn_big_arm (memaddr, info);
else
return print_insn_little_arm (memaddr, info);
{
if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
{
- if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
{
static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
*pcptr = UNMAKE_THUMB_ADDR (*pcptr);
}
else
{
- if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
{
static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
*lenptr = sizeof (arm_breakpoint);
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)
{