aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c79
1 files changed, 67 insertions, 12 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index f10f661..c3e9b5d 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -103,6 +103,24 @@ struct frame_extra_info
int framereg;
};
+#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. */
@@ -252,8 +270,9 @@ int
arm_pc_is_thumb_dummy (bfd_vma memaddr)
{
CORE_ADDR sp = read_sp ();
+ CORE_ADDR fp = read_fp ();
- if (PC_IN_CALL_DUMMY (memaddr, sp, sp + 64))
+ if (PC_IN_CALL_DUMMY (memaddr, sp, fp))
return caller_is_thumb;
else
return 0;
@@ -1227,10 +1246,22 @@ arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
calling the function. */
if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
{
- float f = *(float *) val;
- dbl_arg = f;
- val = (char *) &dbl_arg;
+ 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;
}
#if 1
/* I don't know why this code was disable. The only logical use
@@ -1279,18 +1310,42 @@ arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
void
arm_pop_frame (void)
{
- struct frame_info *frame = get_current_frame ();
int regnum;
- CORE_ADDR old_SP;
+ struct frame_info *frame = get_current_frame ();
+
+ 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,
+ 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);
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+ write_register (SP_REGNUM, old_SP);
+ }
+ else
+ {
+ CORE_ADDR sp;
+
+ 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);
+ }
+ }
flush_cached_frames ();
}