mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-03 23:56:39 +00:00
* sparc-tdep.c (sparc_target_architecture_hook): New function to
set endianness based on machine type. (_initialize_sparc_tdep): Initialize target_architecture_hook. (sparc_print_register_hook): Print PSR and FPSR in fancy format on 32-bit machines. * config/sparc/tm-sparc.h (PRINT_REGISTER_HOOK): Redefine to call sparc_print_register_hook instead of using inline code. * config/sparc/tm-sp64.h (PRINT_REGISTER_HOOK): Remove.
This commit is contained in:
parent
7d449b448b
commit
33c65ba3b3
@ -1,3 +1,14 @@
|
|||||||
|
Tue Jun 2 02:01:56 1998 Mark Alexander <marka@cygnus.com>
|
||||||
|
|
||||||
|
* sparc-tdep.c (sparc_target_architecture_hook): New function to
|
||||||
|
set endianness based on machine type.
|
||||||
|
(_initialize_sparc_tdep): Initialize target_architecture_hook.
|
||||||
|
(sparc_print_register_hook): Print PSR and FPSR in fancy format
|
||||||
|
on 32-bit machines.
|
||||||
|
* config/sparc/tm-sparc.h (PRINT_REGISTER_HOOK): Redefine to
|
||||||
|
call sparc_print_register_hook instead of using inline code.
|
||||||
|
* config/sparc/tm-sp64.h (PRINT_REGISTER_HOOK): Remove.
|
||||||
|
|
||||||
Thu May 28 17:19:14 1998 Keith Seitz <keiths@cygnus.com>
|
Thu May 28 17:19:14 1998 Keith Seitz <keiths@cygnus.com>
|
||||||
|
|
||||||
* main.c (main): Check for NULL from getenv on CYGWIN32.
|
* main.c (main): Check for NULL from getenv on CYGWIN32.
|
||||||
|
@ -335,14 +335,6 @@ struct value;
|
|||||||
#undef FRAME_SPECIFICATION_DYADIC
|
#undef FRAME_SPECIFICATION_DYADIC
|
||||||
#define FRAME_SPECIFICATION_DYADIC
|
#define FRAME_SPECIFICATION_DYADIC
|
||||||
|
|
||||||
/* To print every pair of float registers as a double, we use this hook.
|
|
||||||
We also print the condition code registers in a readable format
|
|
||||||
(FIXME: can expand this to all control regs). */
|
|
||||||
|
|
||||||
#undef PRINT_REGISTER_HOOK
|
|
||||||
#define PRINT_REGISTER_HOOK(regno) \
|
|
||||||
sparc_print_register_hook (regno)
|
|
||||||
|
|
||||||
/* Offsets into jmp_buf.
|
/* Offsets into jmp_buf.
|
||||||
FIXME: This was borrowed from the v8 stuff and will probably have to change
|
FIXME: This was borrowed from the v8 stuff and will probably have to change
|
||||||
for v9. */
|
for v9. */
|
||||||
|
@ -542,19 +542,15 @@ void sparc_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
|
|||||||
#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
|
#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
|
||||||
extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
|
extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
|
||||||
|
|
||||||
/* To print every pair of float registers as a double, we use this hook. */
|
/* To print every pair of float registers as a double, we use this hook.
|
||||||
|
We also print the condition code registers in a readable format
|
||||||
|
(FIXME: can expand this to all control regs). */
|
||||||
|
|
||||||
|
#undef PRINT_REGISTER_HOOK
|
||||||
#define PRINT_REGISTER_HOOK(regno) \
|
#define PRINT_REGISTER_HOOK(regno) \
|
||||||
if (((regno) >= FP0_REGNUM) \
|
sparc_print_register_hook (regno)
|
||||||
&& ((regno) < FP0_REGNUM + 32) \
|
extern void sparc_print_register_hook PARAMS ((int regno));
|
||||||
&& (0 == ((regno) & 1))) { \
|
|
||||||
char doublereg[8]; /* two float regs */ \
|
|
||||||
if (!read_relative_register_raw_bytes ((regno) , doublereg ) \
|
|
||||||
&& !read_relative_register_raw_bytes ((regno)+1, doublereg+4)) { \
|
|
||||||
printf("\t"); \
|
|
||||||
print_floating (doublereg, builtin_type_double, stdout); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Optimization for storing registers to the inferior. The hook
|
/* Optimization for storing registers to the inferior. The hook
|
||||||
DO_DEFERRED_STORES
|
DO_DEFERRED_STORES
|
||||||
|
470
gdb/sparc-tdep.c
470
gdb/sparc-tdep.c
@ -35,6 +35,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||||||
|
|
||||||
#include "gdbcore.h"
|
#include "gdbcore.h"
|
||||||
|
|
||||||
|
#if defined(TARGET_SPARCLET) || defined(TARGET_SPARCLITE)
|
||||||
|
#define SPARC_HAS_FPU 0
|
||||||
|
#else
|
||||||
|
#define SPARC_HAS_FPU 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GDB_TARGET_IS_SPARC64
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
#define FP_REGISTER_BYTES (64 * 4)
|
#define FP_REGISTER_BYTES (64 * 4)
|
||||||
#else
|
#else
|
||||||
@ -59,6 +65,29 @@ extern int stop_after_trap;
|
|||||||
|
|
||||||
int deferred_stores = 0; /* Cumulates stores we want to do eventually. */
|
int deferred_stores = 0; /* Cumulates stores we want to do eventually. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Fetch a single instruction. Even on bi-endian machines
|
||||||
|
such as sparc86x, instructions are always big-endian. */
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
fetch_instruction (pc)
|
||||||
|
CORE_ADDR pc;
|
||||||
|
{
|
||||||
|
unsigned long retval;
|
||||||
|
int i;
|
||||||
|
unsigned char buf[4];
|
||||||
|
|
||||||
|
read_memory (pc, buf, sizeof (buf));
|
||||||
|
|
||||||
|
/* Start at the most significant end of the integer, and work towards
|
||||||
|
the least significant. */
|
||||||
|
retval = 0;
|
||||||
|
for (i = 0; i < sizeof (buf); ++i)
|
||||||
|
retval = (retval << 8) | buf[i];
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Branches with prediction are treated like their non-predicting cousins. */
|
/* Branches with prediction are treated like their non-predicting cousins. */
|
||||||
/* FIXME: What about floating point branches? */
|
/* FIXME: What about floating point branches? */
|
||||||
|
|
||||||
@ -136,7 +165,7 @@ single_step (ignore)
|
|||||||
/* printf_unfiltered ("set break at %x\n",next_pc); */
|
/* printf_unfiltered ("set break at %x\n",next_pc); */
|
||||||
|
|
||||||
pc = read_register (PC_REGNUM);
|
pc = read_register (PC_REGNUM);
|
||||||
pc_instruction = read_memory_integer (pc, 4);
|
pc_instruction = fetch_instruction (pc);
|
||||||
br = isbranch (pc_instruction, pc, &target);
|
br = isbranch (pc_instruction, pc, &target);
|
||||||
brknpc4 = brktrg = 0;
|
brknpc4 = brktrg = 0;
|
||||||
|
|
||||||
@ -200,7 +229,7 @@ sparc_init_extra_frame_info (fromleaf, fi)
|
|||||||
fi->bottom =
|
fi->bottom =
|
||||||
(fi->next ?
|
(fi->next ?
|
||||||
(fi->frame == fi->next->frame ? fi->next->bottom : fi->next->frame) :
|
(fi->frame == fi->next->frame ? fi->next->bottom : fi->next->frame) :
|
||||||
read_register (SP_REGNUM));
|
read_sp ());
|
||||||
|
|
||||||
/* If fi->next is NULL, then we already set ->frame by passing read_fp()
|
/* If fi->next is NULL, then we already set ->frame by passing read_fp()
|
||||||
to create_new_frame. */
|
to create_new_frame. */
|
||||||
@ -222,8 +251,14 @@ sparc_init_extra_frame_info (fromleaf, fi)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Should we adjust for stack bias here? */
|
||||||
get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
|
get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
|
||||||
fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
|
fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
|
||||||
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
|
if (fi->frame & 1)
|
||||||
|
fi->frame += 2047;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,14 +271,14 @@ sparc_init_extra_frame_info (fromleaf, fi)
|
|||||||
negative number if a flat frame) to the sp. FIXME: Does not
|
negative number if a flat frame) to the sp. FIXME: Does not
|
||||||
handle large frames which will need more than one instruction
|
handle large frames which will need more than one instruction
|
||||||
to adjust the sp. */
|
to adjust the sp. */
|
||||||
insn = read_memory_integer (addr, 4);
|
insn = fetch_instruction (addr);
|
||||||
if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0
|
if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0
|
||||||
&& X_I (insn) && X_SIMM13 (insn) < 0)
|
&& X_I (insn) && X_SIMM13 (insn) < 0)
|
||||||
{
|
{
|
||||||
int offset = X_SIMM13 (insn);
|
int offset = X_SIMM13 (insn);
|
||||||
|
|
||||||
/* Then look for a save of %i7 into the frame. */
|
/* Then look for a save of %i7 into the frame. */
|
||||||
insn = read_memory_integer (addr + 4, 4);
|
insn = fetch_instruction (addr + 4);
|
||||||
if (X_OP (insn) == 3
|
if (X_OP (insn) == 3
|
||||||
&& X_RD (insn) == 31
|
&& X_RD (insn) == 31
|
||||||
&& X_OP3 (insn) == 4
|
&& X_OP3 (insn) == 4
|
||||||
@ -259,13 +294,16 @@ sparc_init_extra_frame_info (fromleaf, fi)
|
|||||||
/* Overwrite the frame's address with the value in %i7. */
|
/* Overwrite the frame's address with the value in %i7. */
|
||||||
get_saved_register (buf, 0, 0, fi, I7_REGNUM, 0);
|
get_saved_register (buf, 0, 0, fi, I7_REGNUM, 0);
|
||||||
fi->frame = extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM));
|
fi->frame = extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM));
|
||||||
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
|
if (fi->frame & 1)
|
||||||
|
fi->frame += 2047;
|
||||||
|
#endif
|
||||||
/* Record where the fp got saved. */
|
/* Record where the fp got saved. */
|
||||||
fi->fp_addr = fi->frame + fi->sp_offset + X_SIMM13 (insn);
|
fi->fp_addr = fi->frame + fi->sp_offset + X_SIMM13 (insn);
|
||||||
|
|
||||||
/* Also try to collect where the pc got saved to. */
|
/* Also try to collect where the pc got saved to. */
|
||||||
fi->pc_addr = 0;
|
fi->pc_addr = 0;
|
||||||
insn = read_memory_integer (addr + 12, 4);
|
insn = fetch_instruction (addr + 12);
|
||||||
if (X_OP (insn) == 3
|
if (X_OP (insn) == 3
|
||||||
&& X_RD (insn) == 15
|
&& X_RD (insn) == 15
|
||||||
&& X_OP3 (insn) == 4
|
&& X_OP3 (insn) == 4
|
||||||
@ -426,14 +464,14 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
CORE_ADDR pc = start_pc;
|
CORE_ADDR pc = start_pc;
|
||||||
int is_flat = 0;
|
int is_flat = 0;
|
||||||
|
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
|
|
||||||
/* Recognize the `sethi' insn and record its destination. */
|
/* Recognize the `sethi' insn and record its destination. */
|
||||||
if (X_OP (insn) == 0 && X_OP2 (insn) == 4)
|
if (X_OP (insn) == 0 && X_OP2 (insn) == 4)
|
||||||
{
|
{
|
||||||
dest = X_RD (insn);
|
dest = X_RD (insn);
|
||||||
pc += 4;
|
pc += 4;
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recognize an add immediate value to register to either %g1 or
|
/* Recognize an add immediate value to register to either %g1 or
|
||||||
@ -447,7 +485,7 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
&& (X_RD (insn) == 1 || X_RD (insn) == dest))
|
&& (X_RD (insn) == 1 || X_RD (insn) == dest))
|
||||||
{
|
{
|
||||||
pc += 4;
|
pc += 4;
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recognize any SAVE insn. */
|
/* Recognize any SAVE insn. */
|
||||||
@ -456,7 +494,7 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
pc += 4;
|
pc += 4;
|
||||||
if (frameless_p) /* If the save is all we care about, */
|
if (frameless_p) /* If the save is all we care about, */
|
||||||
return pc; /* return before doing more work */
|
return pc; /* return before doing more work */
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
}
|
}
|
||||||
/* Recognize add to %sp. */
|
/* Recognize add to %sp. */
|
||||||
else if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0)
|
else if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0)
|
||||||
@ -465,7 +503,7 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
if (frameless_p) /* If the add is all we care about, */
|
if (frameless_p) /* If the add is all we care about, */
|
||||||
return pc; /* return before doing more work */
|
return pc; /* return before doing more work */
|
||||||
is_flat = 1;
|
is_flat = 1;
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
/* Recognize store of frame pointer (i7). */
|
/* Recognize store of frame pointer (i7). */
|
||||||
if (X_OP (insn) == 3
|
if (X_OP (insn) == 3
|
||||||
&& X_RD (insn) == 31
|
&& X_RD (insn) == 31
|
||||||
@ -473,7 +511,7 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
&& X_RS1 (insn) == 14)
|
&& X_RS1 (insn) == 14)
|
||||||
{
|
{
|
||||||
pc += 4;
|
pc += 4;
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
|
|
||||||
/* Recognize sub %sp, <anything>, %i7. */
|
/* Recognize sub %sp, <anything>, %i7. */
|
||||||
if (X_OP (insn) == 2
|
if (X_OP (insn) == 2
|
||||||
@ -482,7 +520,7 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
&& X_RD (insn) == 31)
|
&& X_RD (insn) == 31)
|
||||||
{
|
{
|
||||||
pc += 4;
|
pc += 4;
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return pc;
|
return pc;
|
||||||
@ -521,7 +559,7 @@ examine_prologue (start_pc, frameless_p, fi, saved_regs)
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
pc += 4;
|
pc += 4;
|
||||||
insn = read_memory_integer (pc, 4);
|
insn = fetch_instruction (pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pc;
|
return pc;
|
||||||
@ -670,7 +708,7 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
|
|||||||
while (frame1 != NULL)
|
while (frame1 != NULL)
|
||||||
{
|
{
|
||||||
if (frame1->pc >= (frame1->bottom ? frame1->bottom :
|
if (frame1->pc >= (frame1->bottom ? frame1->bottom :
|
||||||
read_register (SP_REGNUM))
|
read_sp ())
|
||||||
&& frame1->pc <= FRAME_FP (frame1))
|
&& frame1->pc <= FRAME_FP (frame1))
|
||||||
{
|
{
|
||||||
/* Dummy frame. All but the window regs are in there somewhere.
|
/* Dummy frame. All but the window regs are in there somewhere.
|
||||||
@ -792,7 +830,7 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
|
|||||||
/* See tm-sparc.h for how this is calculated. */
|
/* See tm-sparc.h for how this is calculated. */
|
||||||
#ifdef FP0_REGNUM
|
#ifdef FP0_REGNUM
|
||||||
#define DUMMY_STACK_REG_BUF_SIZE \
|
#define DUMMY_STACK_REG_BUF_SIZE \
|
||||||
(((8+8+8) * SPARC_INTREG_SIZE) + (32 * REGISTER_RAW_SIZE (FP0_REGNUM)))
|
(((8+8+8) * SPARC_INTREG_SIZE) + FP_REGISTER_BYTES)
|
||||||
#else
|
#else
|
||||||
#define DUMMY_STACK_REG_BUF_SIZE \
|
#define DUMMY_STACK_REG_BUF_SIZE \
|
||||||
(((8+8+8) * SPARC_INTREG_SIZE) )
|
(((8+8+8) * SPARC_INTREG_SIZE) )
|
||||||
@ -805,9 +843,14 @@ sparc_push_dummy_frame ()
|
|||||||
CORE_ADDR sp, old_sp;
|
CORE_ADDR sp, old_sp;
|
||||||
char register_temp[DUMMY_STACK_SIZE];
|
char register_temp[DUMMY_STACK_SIZE];
|
||||||
|
|
||||||
old_sp = sp = read_register (SP_REGNUM);
|
old_sp = sp = read_sp ();
|
||||||
|
|
||||||
#ifdef GDB_TARGET_IS_SPARC64
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
|
/* PC, NPC, CCR, FSR, FPRS, Y, ASI */
|
||||||
|
read_register_bytes (REGISTER_BYTE (PC_REGNUM), ®ister_temp[0],
|
||||||
|
REGISTER_RAW_SIZE (PC_REGNUM) * 7);
|
||||||
|
read_register_bytes (REGISTER_BYTE (PSTATE_REGNUM), ®ister_temp[8],
|
||||||
|
REGISTER_RAW_SIZE (PSTATE_REGNUM));
|
||||||
/* FIXME: not sure what needs to be saved here. */
|
/* FIXME: not sure what needs to be saved here. */
|
||||||
#else
|
#else
|
||||||
/* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
|
/* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
|
||||||
@ -831,15 +874,37 @@ sparc_push_dummy_frame ()
|
|||||||
|
|
||||||
sp -= DUMMY_STACK_SIZE;
|
sp -= DUMMY_STACK_SIZE;
|
||||||
|
|
||||||
write_register (SP_REGNUM, sp);
|
write_sp (sp);
|
||||||
|
|
||||||
write_memory (sp + DUMMY_REG_SAVE_OFFSET, ®ister_temp[0],
|
write_memory (sp + DUMMY_REG_SAVE_OFFSET, ®ister_temp[0],
|
||||||
DUMMY_STACK_REG_BUF_SIZE);
|
DUMMY_STACK_REG_BUF_SIZE);
|
||||||
|
|
||||||
write_register (FP_REGNUM, old_sp);
|
if (strcmp (target_shortname, "sim") != 0)
|
||||||
|
{
|
||||||
|
write_fp (old_sp);
|
||||||
|
|
||||||
/* Set return address register for the call dummy to the current PC. */
|
/* Set return address register for the call dummy to the current PC. */
|
||||||
write_register (I7_REGNUM, read_pc() - 8);
|
write_register (I7_REGNUM, read_pc() - 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The call dummy will write this value to FP before executing
|
||||||
|
the 'save'. This ensures that register window flushes work
|
||||||
|
correctly in the simulator. */
|
||||||
|
write_register (G0_REGNUM+1, read_register (FP_REGNUM));
|
||||||
|
|
||||||
|
/* The call dummy will write this value to FP after executing
|
||||||
|
the 'save'. */
|
||||||
|
write_register (G0_REGNUM+2, old_sp);
|
||||||
|
|
||||||
|
/* The call dummy will write this value to the return address (%i7) after
|
||||||
|
executing the 'save'. */
|
||||||
|
write_register (G0_REGNUM+3, read_pc() - 8);
|
||||||
|
|
||||||
|
/* Set the FP that the call dummy will be using after the 'save'.
|
||||||
|
This makes backtraces from an inferior function call work properly. */
|
||||||
|
write_register (FP_REGNUM, old_sp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sparc_frame_find_saved_regs (). This function is here only because
|
/* sparc_frame_find_saved_regs (). This function is here only because
|
||||||
@ -873,7 +938,7 @@ sparc_push_dummy_frame ()
|
|||||||
is a return address minus 8.) sparc_pop_frame knows how to
|
is a return address minus 8.) sparc_pop_frame knows how to
|
||||||
deal with that. Other routines might or might not.
|
deal with that. Other routines might or might not.
|
||||||
|
|
||||||
See tm-sparc.h (PUSH_FRAME and friends) for CRITICAL information
|
See tm-sparc.h (PUSH_DUMMY_FRAME and friends) for CRITICAL information
|
||||||
about how this works. */
|
about how this works. */
|
||||||
|
|
||||||
static void sparc_frame_find_saved_regs PARAMS ((struct frame_info *,
|
static void sparc_frame_find_saved_regs PARAMS ((struct frame_info *,
|
||||||
@ -893,7 +958,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||||||
memset (saved_regs_addr, 0, sizeof (*saved_regs_addr));
|
memset (saved_regs_addr, 0, sizeof (*saved_regs_addr));
|
||||||
|
|
||||||
if (fi->pc >= (fi->bottom ? fi->bottom :
|
if (fi->pc >= (fi->bottom ? fi->bottom :
|
||||||
read_register (SP_REGNUM))
|
read_sp ())
|
||||||
&& fi->pc <= FRAME_FP(fi))
|
&& fi->pc <= FRAME_FP(fi))
|
||||||
{
|
{
|
||||||
/* Dummy frame. All but the window regs are in there somewhere. */
|
/* Dummy frame. All but the window regs are in there somewhere. */
|
||||||
@ -913,16 +978,27 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||||||
#ifdef GDB_TARGET_IS_SPARC64
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
|
for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
|
||||||
saved_regs_addr->regs[regnum] =
|
saved_regs_addr->regs[regnum] =
|
||||||
frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
|
frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 4
|
||||||
- DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
|
- DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
|
||||||
#endif
|
#endif
|
||||||
#endif /* FP0_REGNUM */
|
#endif /* FP0_REGNUM */
|
||||||
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
|
for (regnum = PC_REGNUM; regnum < PC_REGNUM + 7; regnum++)
|
||||||
|
{
|
||||||
|
saved_regs_addr->regs[regnum] =
|
||||||
|
frame_addr + (regnum - PC_REGNUM) * SPARC_INTREG_SIZE
|
||||||
|
- DUMMY_STACK_REG_BUF_SIZE;
|
||||||
|
}
|
||||||
|
saved_regs_addr->regs[PSTATE_REGNUM] =
|
||||||
|
frame_addr + 8 * SPARC_INTREG_SIZE - DUMMY_STACK_REG_BUF_SIZE;
|
||||||
|
#else
|
||||||
for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
|
for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
|
||||||
saved_regs_addr->regs[regnum] =
|
saved_regs_addr->regs[regnum] =
|
||||||
frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
|
frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
|
||||||
- DUMMY_STACK_REG_BUF_SIZE;
|
- DUMMY_STACK_REG_BUF_SIZE;
|
||||||
|
#endif
|
||||||
frame_addr = fi->bottom ?
|
frame_addr = fi->bottom ?
|
||||||
fi->bottom : read_register (SP_REGNUM);
|
fi->bottom : read_sp ();
|
||||||
}
|
}
|
||||||
else if (fi->flat)
|
else if (fi->flat)
|
||||||
{
|
{
|
||||||
@ -938,7 +1014,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||||||
{
|
{
|
||||||
/* Normal frame. Just Local and In registers */
|
/* Normal frame. Just Local and In registers */
|
||||||
frame_addr = fi->bottom ?
|
frame_addr = fi->bottom ?
|
||||||
fi->bottom : read_register (SP_REGNUM);
|
fi->bottom : read_sp ();
|
||||||
for (regnum = L0_REGNUM; regnum < L0_REGNUM+8; regnum++)
|
for (regnum = L0_REGNUM; regnum < L0_REGNUM+8; regnum++)
|
||||||
saved_regs_addr->regs[regnum] =
|
saved_regs_addr->regs[regnum] =
|
||||||
(frame_addr + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
|
(frame_addr + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
|
||||||
@ -960,7 +1036,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||||||
CORE_ADDR next_next_frame_addr =
|
CORE_ADDR next_next_frame_addr =
|
||||||
(fi->next->bottom ?
|
(fi->next->bottom ?
|
||||||
fi->next->bottom :
|
fi->next->bottom :
|
||||||
read_register (SP_REGNUM));
|
read_sp ());
|
||||||
for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
|
for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
|
||||||
saved_regs_addr->regs[regnum] =
|
saved_regs_addr->regs[regnum] =
|
||||||
(next_next_frame_addr
|
(next_next_frame_addr
|
||||||
@ -969,6 +1045,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
|
/* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
|
||||||
|
/* FIXME -- should this adjust for the sparc64 offset? */
|
||||||
saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi);
|
saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1046,7 +1123,7 @@ sparc_pop_frame ()
|
|||||||
read_memory_integer (fsr.regs[O0_REGNUM + 7],
|
read_memory_integer (fsr.regs[O0_REGNUM + 7],
|
||||||
SPARC_INTREG_SIZE));
|
SPARC_INTREG_SIZE));
|
||||||
|
|
||||||
write_register (SP_REGNUM, frame->frame);
|
write_sp (frame->frame);
|
||||||
}
|
}
|
||||||
else if (fsr.regs[I0_REGNUM])
|
else if (fsr.regs[I0_REGNUM])
|
||||||
{
|
{
|
||||||
@ -1062,6 +1139,10 @@ sparc_pop_frame ()
|
|||||||
locals from the registers array, so we need to muck with the
|
locals from the registers array, so we need to muck with the
|
||||||
registers array. */
|
registers array. */
|
||||||
sp = fsr.regs[SP_REGNUM];
|
sp = fsr.regs[SP_REGNUM];
|
||||||
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
|
if (sp & 1)
|
||||||
|
sp += 2047;
|
||||||
|
#endif
|
||||||
read_memory (sp, reg_temp, SPARC_INTREG_SIZE * 16);
|
read_memory (sp, reg_temp, SPARC_INTREG_SIZE * 16);
|
||||||
|
|
||||||
/* Restore the out registers.
|
/* Restore the out registers.
|
||||||
@ -1392,7 +1473,6 @@ sunpro_static_transform_name (name)
|
|||||||
}
|
}
|
||||||
#endif /* STATIC_TRANSFORM_NAME */
|
#endif /* STATIC_TRANSFORM_NAME */
|
||||||
|
|
||||||
#ifdef GDB_TARGET_IS_SPARC64
|
|
||||||
|
|
||||||
/* Utilities for printing registers.
|
/* Utilities for printing registers.
|
||||||
Page numbers refer to the SPARC Architecture Manual. */
|
Page numbers refer to the SPARC Architecture Manual. */
|
||||||
@ -1503,6 +1583,7 @@ sparc_print_register_hook (regno)
|
|||||||
/* pages 40 - 60 */
|
/* pages 40 - 60 */
|
||||||
switch (regno)
|
switch (regno)
|
||||||
{
|
{
|
||||||
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
case CCR_REGNUM :
|
case CCR_REGNUM :
|
||||||
printf_unfiltered("\t");
|
printf_unfiltered("\t");
|
||||||
dump_ccreg ("xcc", val >> 4);
|
dump_ccreg ("xcc", val >> 4);
|
||||||
@ -1576,12 +1657,32 @@ sparc_print_register_hook (regno)
|
|||||||
case OTHERWIN_REGNUM :
|
case OTHERWIN_REGNUM :
|
||||||
printf ("\t%d", BITS (0, 31));
|
printf ("\t%d", BITS (0, 31));
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
case PS_REGNUM:
|
||||||
|
printf ("\ticc:%c%c%c%c, pil:%d, s:%d, ps:%d, et:%d, cwp:%d",
|
||||||
|
BITS (23, 1) ? 'N' : '-', BITS (22, 1) ? 'Z' : '-',
|
||||||
|
BITS (21, 1) ? 'V' : '-', BITS (20, 1) ? 'C' : '-',
|
||||||
|
BITS (8, 15), BITS (7, 1), BITS (6, 1), BITS (5, 1),
|
||||||
|
BITS (0, 31));
|
||||||
|
break;
|
||||||
|
case FPS_REGNUM:
|
||||||
|
{
|
||||||
|
static char *fcc[4] = { "=", "<", ">", "?" };
|
||||||
|
static char *rd[4] = { "N", "0", "+", "-" };
|
||||||
|
/* Long, yes, but I'd rather leave it as is and use a wide screen. */
|
||||||
|
printf ("\trd:%s, tem:%d, ns:%d, ver:%d, ftt:%d, qne:%d, "
|
||||||
|
"fcc:%s, aexc:%d, cexc:%d",
|
||||||
|
rd[BITS (30, 3)], BITS (23, 31), BITS (22, 1), BITS (17, 7),
|
||||||
|
BITS (14, 7), BITS (13, 1), fcc[BITS (10, 3)], BITS (5, 31),
|
||||||
|
BITS (0, 31));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GDB_TARGET_IS_SPARC64 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef BITS
|
#undef BITS
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gdb_print_insn_sparc (memaddr, info)
|
gdb_print_insn_sparc (memaddr, info)
|
||||||
@ -1655,10 +1756,317 @@ sparc_push_arguments (nargs, args, sp, struct_return, struct_addr)
|
|||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Extract from an array REGBUF containing the (raw) register state
|
||||||
|
a function return value of type TYPE, and copy that, in virtual format,
|
||||||
|
into VALBUF. */
|
||||||
|
|
||||||
|
void
|
||||||
|
sparc_extract_return_value (type, regbuf, valbuf)
|
||||||
|
struct type *type;
|
||||||
|
char *regbuf;
|
||||||
|
char *valbuf;
|
||||||
|
{
|
||||||
|
int typelen = TYPE_LENGTH (type);
|
||||||
|
int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
|
||||||
|
|
||||||
|
if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
|
||||||
|
memcpy (valbuf, ®buf [REGISTER_BYTE (FP0_REGNUM)], typelen);
|
||||||
|
else
|
||||||
|
memcpy (valbuf,
|
||||||
|
®buf [O0_REGNUM * regsize +
|
||||||
|
(typelen >= regsize ? 0 : regsize - typelen)],
|
||||||
|
typelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write into appropriate registers a function return value
|
||||||
|
of type TYPE, given in virtual format. On SPARCs with FPUs,
|
||||||
|
float values are returned in %f0 (and %f1). In all other cases,
|
||||||
|
values are returned in register %o0. */
|
||||||
|
|
||||||
|
void
|
||||||
|
sparc_store_return_value (type, valbuf)
|
||||||
|
struct type *type;
|
||||||
|
char *valbuf;
|
||||||
|
{
|
||||||
|
int regno;
|
||||||
|
char buffer[MAX_REGISTER_RAW_SIZE];
|
||||||
|
|
||||||
|
if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
|
||||||
|
/* Floating-point values are returned in the register pair */
|
||||||
|
/* formed by %f0 and %f1 (doubles are, anyway). */
|
||||||
|
regno = FP0_REGNUM;
|
||||||
|
else
|
||||||
|
/* Other values are returned in register %o0. */
|
||||||
|
regno = O0_REGNUM;
|
||||||
|
|
||||||
|
/* Add leading zeros to the value. */
|
||||||
|
if (TYPE_LENGTH (type) < REGISTER_RAW_SIZE(regno))
|
||||||
|
{
|
||||||
|
bzero (buffer, REGISTER_RAW_SIZE(regno));
|
||||||
|
memcpy (buffer + REGISTER_RAW_SIZE(regno) - TYPE_LENGTH (type), valbuf,
|
||||||
|
TYPE_LENGTH (type));
|
||||||
|
write_register_bytes (REGISTER_BYTE (regno), buffer,
|
||||||
|
REGISTER_RAW_SIZE(regno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
write_register_bytes (REGISTER_BYTE (regno), valbuf, TYPE_LENGTH (type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Insert the function address into a call dummy instsruction sequence
|
||||||
|
stored at DUMMY.
|
||||||
|
|
||||||
|
For structs and unions, if the function was compiled with Sun cc,
|
||||||
|
it expects 'unimp' after the call. But gcc doesn't use that
|
||||||
|
(twisted) convention. So leave a nop there for gcc (FIX_CALL_DUMMY
|
||||||
|
can assume it is operating on a pristine CALL_DUMMY, not one that
|
||||||
|
has already been customized for a different function). */
|
||||||
|
|
||||||
|
void
|
||||||
|
sparc_fix_call_dummy (dummy, pc, fun, value_type, using_gcc)
|
||||||
|
char *dummy;
|
||||||
|
CORE_ADDR pc;
|
||||||
|
CORE_ADDR fun;
|
||||||
|
struct type *value_type;
|
||||||
|
int using_gcc;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Store the relative adddress of the target function into the
|
||||||
|
'call' instruction. */
|
||||||
|
store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET, 4,
|
||||||
|
(0x40000000
|
||||||
|
| (((fun - (pc + CALL_DUMMY_CALL_OFFSET)) >> 2)
|
||||||
|
& 0x3fffffff)));
|
||||||
|
|
||||||
|
/* Comply with strange Sun cc calling convention for struct-returning
|
||||||
|
functions. */
|
||||||
|
if (!using_gcc
|
||||||
|
&& (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
|
||||||
|
|| TYPE_CODE (value_type) == TYPE_CODE_UNION))
|
||||||
|
store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
|
||||||
|
TYPE_LENGTH (value_type) & 0x1fff);
|
||||||
|
|
||||||
|
#ifndef GDB_TARGET_IS_SPARC64
|
||||||
|
/* If this is not a simulator target, change the first four instructions
|
||||||
|
of the call dummy to NOPs. Those instructions include a 'save'
|
||||||
|
instruction and are designed to work around problems with register
|
||||||
|
window flushing in the simulator. */
|
||||||
|
if (strcmp (target_shortname, "sim") != 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
store_unsigned_integer (dummy + (i * 4), 4, 0x01000000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set target byte order based on machine type. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
sparc_target_architecture_hook (ap)
|
||||||
|
const bfd_arch_info_type *ap;
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (ap->mach == bfd_mach_sparc_sparclite_le)
|
||||||
|
target_byte_order = LITTLE_ENDIAN;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_sparc_tdep ()
|
_initialize_sparc_tdep ()
|
||||||
{
|
{
|
||||||
tm_print_insn = gdb_print_insn_sparc;
|
tm_print_insn = gdb_print_insn_sparc;
|
||||||
tm_print_insn_info.mach = TM_PRINT_INSN_MACH; /* Selects sparc/sparclite */
|
tm_print_insn_info.mach = TM_PRINT_INSN_MACH; /* Selects sparc/sparclite */
|
||||||
|
target_architecture_hook = sparc_target_architecture_hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GDB_TARGET_IS_SPARC64
|
||||||
|
|
||||||
|
/* Compensate for stack bias. Note that we currently don't handle mixed
|
||||||
|
32/64 bit code. */
|
||||||
|
CORE_ADDR
|
||||||
|
sparc64_read_sp ()
|
||||||
|
{
|
||||||
|
CORE_ADDR sp = read_register (SP_REGNUM);
|
||||||
|
|
||||||
|
if (sp & 1)
|
||||||
|
sp += 2047;
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
CORE_ADDR
|
||||||
|
sparc64_read_fp ()
|
||||||
|
{
|
||||||
|
CORE_ADDR fp = read_register (FP_REGNUM);
|
||||||
|
|
||||||
|
if (fp & 1)
|
||||||
|
fp += 2047;
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sparc64_write_sp (val)
|
||||||
|
CORE_ADDR val;
|
||||||
|
{
|
||||||
|
CORE_ADDR oldsp = read_register (SP_REGNUM);
|
||||||
|
if (oldsp & 1)
|
||||||
|
write_register (SP_REGNUM, val - 2047);
|
||||||
|
else
|
||||||
|
write_register (SP_REGNUM, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sparc64_write_fp (val)
|
||||||
|
CORE_ADDR val;
|
||||||
|
{
|
||||||
|
CORE_ADDR oldfp = read_register (FP_REGNUM);
|
||||||
|
if (oldfp & 1)
|
||||||
|
write_register (FP_REGNUM, val - 2047);
|
||||||
|
else
|
||||||
|
write_register (FP_REGNUM, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The SPARC 64 ABI passes floating-point arguments in FP0-31. They are
|
||||||
|
also copied onto the stack in the correct places. */
|
||||||
|
|
||||||
|
CORE_ADDR
|
||||||
|
sp64_push_arguments (nargs, args, sp, struct_return, struct_retaddr)
|
||||||
|
int nargs;
|
||||||
|
value_ptr *args;
|
||||||
|
CORE_ADDR sp;
|
||||||
|
unsigned char struct_return;
|
||||||
|
CORE_ADDR struct_retaddr;
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int regnum = 0;
|
||||||
|
CORE_ADDR tempsp;
|
||||||
|
|
||||||
|
sp = (sp & ~(((unsigned long)TYPE_LENGTH (builtin_type_long)) - 1UL));
|
||||||
|
|
||||||
|
/* Figure out how much space we'll need. */
|
||||||
|
for (x = nargs - 1; x >= 0; x--)
|
||||||
|
{
|
||||||
|
int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[x])));
|
||||||
|
value_ptr copyarg = args[x];
|
||||||
|
int copylen = len;
|
||||||
|
|
||||||
|
/* This code is, of course, no longer correct. */
|
||||||
|
if (copylen < TYPE_LENGTH (builtin_type_long))
|
||||||
|
{
|
||||||
|
copyarg = value_cast(builtin_type_long, copyarg);
|
||||||
|
copylen = TYPE_LENGTH (builtin_type_long);
|
||||||
|
}
|
||||||
|
sp -= copylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Round down. */
|
||||||
|
sp = sp & ~7;
|
||||||
|
tempsp = sp;
|
||||||
|
|
||||||
|
/* Now write the arguments onto the stack, while writing FP arguments
|
||||||
|
into the FP registers. */
|
||||||
|
for (x = 0; x < nargs; x++)
|
||||||
|
{
|
||||||
|
int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[x])));
|
||||||
|
value_ptr copyarg = args[x];
|
||||||
|
int copylen = len;
|
||||||
|
|
||||||
|
/* This code is, of course, no longer correct. */
|
||||||
|
if (copylen < TYPE_LENGTH (builtin_type_long))
|
||||||
|
{
|
||||||
|
copyarg = value_cast(builtin_type_long, copyarg);
|
||||||
|
copylen = TYPE_LENGTH (builtin_type_long);
|
||||||
|
}
|
||||||
|
write_memory (tempsp, VALUE_CONTENTS (copyarg), copylen);
|
||||||
|
tempsp += copylen;
|
||||||
|
if (TYPE_CODE (VALUE_TYPE (args[x])) == TYPE_CODE_FLT && regnum < 32)
|
||||||
|
{
|
||||||
|
/* This gets copied into a FP register. */
|
||||||
|
int nextreg = regnum + 2;
|
||||||
|
char *data = VALUE_CONTENTS (args[x]);
|
||||||
|
/* Floats go into the lower half of a FP register pair; quads
|
||||||
|
use 2 pairs. */
|
||||||
|
|
||||||
|
if (len == 16)
|
||||||
|
nextreg += 2;
|
||||||
|
else if (len == 4)
|
||||||
|
regnum++;
|
||||||
|
|
||||||
|
write_register_bytes (REGISTER_BYTE (FP0_REGNUM + regnum),
|
||||||
|
data,
|
||||||
|
len);
|
||||||
|
regnum = nextreg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Values <= 32 bytes are returned in o0-o3 (floating-point values are
|
||||||
|
returned in f0-f3). */
|
||||||
|
void
|
||||||
|
sparc64_extract_return_value (type, regbuf, valbuf, bitoffset)
|
||||||
|
struct type *type;
|
||||||
|
char *regbuf;
|
||||||
|
char *valbuf;
|
||||||
|
int bitoffset;
|
||||||
|
{
|
||||||
|
int typelen = TYPE_LENGTH (type);
|
||||||
|
int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
|
||||||
|
|
||||||
|
if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
|
||||||
|
{
|
||||||
|
memcpy (valbuf, ®buf [REGISTER_BYTE (FP0_REGNUM)], typelen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||||
|
|| (TYPE_LENGTH (type) > 32))
|
||||||
|
{
|
||||||
|
memcpy (valbuf,
|
||||||
|
®buf [O0_REGNUM * regsize +
|
||||||
|
(typelen >= regsize ? 0 : regsize - typelen)],
|
||||||
|
typelen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *o0 = ®buf[O0_REGNUM * regsize];
|
||||||
|
char *f0 = ®buf[FP0_REGNUM * regsize];
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (x = 0; x < TYPE_NFIELDS (type); x++)
|
||||||
|
{
|
||||||
|
struct field *f = &TYPE_FIELDS(type)[x];
|
||||||
|
/* FIXME: We may need to handle static fields here. */
|
||||||
|
int whichreg = (f->loc.bitpos + bitoffset) / 32;
|
||||||
|
int remainder = ((f->loc.bitpos + bitoffset) % 32) / 8;
|
||||||
|
int where = (f->loc.bitpos + bitoffset) / 8;
|
||||||
|
int size = TYPE_LENGTH (f->type);
|
||||||
|
int typecode = TYPE_CODE (f->type);
|
||||||
|
|
||||||
|
if (typecode == TYPE_CODE_STRUCT)
|
||||||
|
{
|
||||||
|
sparc64_extract_return_value (f->type,
|
||||||
|
regbuf,
|
||||||
|
valbuf,
|
||||||
|
bitoffset + f->loc.bitpos);
|
||||||
|
}
|
||||||
|
else if (typecode == TYPE_CODE_FLT)
|
||||||
|
{
|
||||||
|
memcpy (valbuf + where, &f0[whichreg * 4] + remainder, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (valbuf + where, &o0[whichreg * 4] + remainder, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user