o Update GDB to match changes to d10v abi (ARG1 in r0 instead of r2).

o Fix code assuming that host/target were both bigendian.
o Replace d10v push dummy frame code with version using new common
  generic generic version.
o Find/fix more cases where a value needs to be translated to/from
  instruction (IMAP) or data (DMAP) spaces.
This commit is contained in:
Andrew Cagney 1998-02-06 04:09:35 +00:00
parent ffd652c313
commit 9961ca7ab5
3 changed files with 182 additions and 140 deletions

View File

@ -1,3 +1,49 @@
Thu Feb 5 13:16:36 1998 Andrew Cagney <cagney@b1.cygnus.com>
* d10v-tdep.c (d10v_extract_return_value): For function pointers
translate address to IMAP area.
* config/d10v/tm-d10v.h (EXTRA_FRAME_INFO): Delete dummy from
struct.
(POP_FRAME): Point at generic_pop_current_frame.
* d10v-tdep.c (d10v_pop_frame): Delete code handling dummy frames,
handled earlier.
(d10v_push_return_address): New function.
(d10v_pop_dummy_frame): Delete.
(d10v_fix_call_dummy): Delete.
(d10v_call_dummy_address): Delete.
* d10v-tdep.c (d10v_init_extra_frame_info): Clear dummy and
frameless.
* d10v-tdep.c (d10v_push_arguments): Keep stack word aligned.
* config/d10v/tm-d10v.h (EXTRACT_STRUCT_VALUE_ADDRESS): Extract
address of structure from first ARG1_REGNUM.
* d10v-tdep.c (d10v_push_arguments): Force 4 byte args into
even-odd register pair. Store 1 and 2 byte args in registers.
* valops.c (value_fetch_lazy): Ensure that a D10V function pointer
is fetched in the correct byte order.
(value_at): Ditto. Also ensure data pointers are mapped to data
segment.
* config/d10v/tm-d10v.h (D10V_DADDR_P, D10V_IADDR_P):
* d10v-tdep.c: Replace 2 with REGISTER_RAW_SIZE.
(d10v_pop_frame): Replace R13 with LR_REGNUM.
(d10v_push_arguments): Replace R2 with ARG1_REGNUM.
(d10v_push_arguments): Replace 6 with ARGN_REGNUM.
(d10v_extract_return_value): Access return value with RET1_REGNUM.
* config/d10v/tm-d10v.h (ARG1_REGNUM, ARGN_REGNUM, RET1_REGNUM):
Define.
(STORE_RETURN_VALUE): Specify return register using RET1_REGNUM.
(STORE_STRUCT_RETURN): Specify ARG1_REGNUM as the struct ptr
location.
Thu Feb 5 13:16:36 1998 Andrew Cagney <cagney@b1.cygnus.com>
* blockframe.c (generic_pop_dummy_frame): Flush the frame, no

View File

@ -143,29 +143,38 @@ extern CORE_ADDR d10v_skip_prologue ();
#define D10V_MAKE_DADDR(x) ( (x) & 0x3000000 ? (x) : ((x) | DMEM_START))
#define D10V_MAKE_IADDR(x) ( (x) & 0x3000000 ? (x) : (((x) << 2) | IMEM_START))
#define D10V_DADDR_P(x) ( ((x) & 0x3000000) == DMEM_START)
#define D10V_IADDR_P(x) ( ((x) & 0x3000000) == IMEM_START))
#define ARG1_REGNUM R0_REGNUM
#define ARGN_REGNUM 3
#define RET1_REGNUM R0_REGNUM
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function.
We store structs through a pointer passed in R2 */
We store structs through a pointer passed in the first Argument
register. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ write_register (2, (ADDR)); }
{ write_register (ARG1_REGNUM, (ADDR)); }
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format.
Things always get returned in R2/R3 */
Things always get returned in RET1_REGNUM, RET2_REGNUM, ... */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (REGISTER_BYTE(2), VALBUF, TYPE_LENGTH (TYPE))
write_register_bytes (REGISTER_BYTE(RET1_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(CORE_ADDR *)(REGBUF))
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
(extract_address ((REGBUF) + REGISTER_BYTE (ARG1_REGNUM), REGISTER_RAW_SIZE (ARG1_REGNUM)) | DMEM_START)
/* Define other aspects of the stack frame.
@ -174,7 +183,6 @@ extern CORE_ADDR d10v_skip_prologue ();
#define EXTRA_FRAME_INFO \
CORE_ADDR return_pc; \
CORE_ADDR dummy; \
int frameless; \
int size;
@ -226,33 +234,40 @@ extern void d10v_init_extra_frame_info PARAMS (( int fromleaf, struct frame_info
extern void d10v_frame_find_saved_regs PARAMS ((struct frame_info *, struct frame_saved_regs *));
#define NAMES_HAVE_UNDERSCORE
/*
DUMMY FRAMES. Need these to support inferior function calls. They work
like this on D10V: First we set a breakpoint at 0 or __start. Then we push
all the registers onto the stack. Then put the function arguments in the proper
registers and set r13 to our breakpoint address. Finally call the function directly.
When it hits the breakpoint, clear the break point and pop the old register contents
off the stack.
*/
#define CALL_DUMMY { 0 }
#define PUSH_DUMMY_FRAME
#define CALL_DUMMY_START_OFFSET 0
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
/* DUMMY FRAMES. Need these to support inferior function calls. They
work like this on D10V: First we set a breakpoint at 0 or __start.
Then we push all the registers onto the stack. Then put the
function arguments in the proper registers and set r13 to our
breakpoint address. Finally, the PC is set to the start of the
function being called (no JSR/BSR insn). When it hits the
breakpoint, clear the break point and pop the old register contents
off the stack. */
extern void d10v_pop_frame PARAMS ((struct frame_info *frame));
#define POP_FRAME generic_pop_current_frame (d10v_pop_frame)
#define USE_GENERIC_DUMMY_FRAMES
#define CALL_DUMMY {0}
#define CALL_DUMMY_START_OFFSET (0)
#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
#define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP)
#define CALL_DUMMY_ADDRESS() entry_point_address ()
extern CORE_ADDR d10v_push_return_address PARAMS ((CORE_ADDR pc, CORE_ADDR sp));
#define PUSH_RETURN_ADDRESS(PC, SP) d10v_push_return_address (PC, SP)
extern CORE_ADDR d10v_call_dummy_address PARAMS ((void));
#define CALL_DUMMY_ADDRESS() d10v_call_dummy_address()
#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP)
/* #define PC_IN_CALL_DUMMY(pc, sp, frame_address) ( pc == IMEM_START + 4 ) */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
sp = d10v_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
#define PUSH_DUMMY_FRAME generic_push_dummy_frame ()
#define PC_IN_CALL_DUMMY(pc, sp, frame_address) ( pc == IMEM_START + 4 )
/* override the default get_saved_register function with one that
takes account of generic CALL_DUMMY frames */
#define GET_SAVED_REGISTER
#define get_saved_register generic_get_saved_register
extern CORE_ADDR d10v_fix_call_dummy PARAMS ((char *, CORE_ADDR, CORE_ADDR,
int, struct value **,
struct type *, int));
#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
sp = d10v_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
extern CORE_ADDR d10v_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
@ -268,11 +283,6 @@ d10v_extract_return_value(TYPE, REGBUF, VALBUF)
d10v_extract_return_value PARAMS ((struct type *, char *, char *));
/* Discard from the stack the innermost frame,
restoring all saved registers. */
#define POP_FRAME d10v_pop_frame();
extern void d10v_pop_frame PARAMS((void));
#define REGISTER_SIZE 2
#ifdef CC_HAS_LONG_LONG

View File

@ -35,27 +35,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
void d10v_frame_find_saved_regs PARAMS ((struct frame_info *fi,
struct frame_saved_regs *fsr));
static void d10v_pop_dummy_frame PARAMS ((struct frame_info *fi));
/* Discard from the stack the innermost frame, restoring all saved
registers. */
void
d10v_pop_frame ()
d10v_pop_frame (frame)
struct frame_info *frame;
{
struct frame_info *frame = get_current_frame ();
CORE_ADDR fp;
int regnum;
struct frame_saved_regs fsr;
char raw_buffer[8];
fp = FRAME_FP (frame);
if (frame->dummy)
{
d10v_pop_dummy_frame(frame);
return;
}
/* fill out fsr with the address of where each */
/* register was stored in the frame */
get_frame_saved_regs (frame, &fsr);
@ -65,23 +58,23 @@ d10v_pop_frame ()
{
if (fsr.regs[regnum])
{
read_memory (fsr.regs[regnum], raw_buffer, 8);
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 8);
read_memory (fsr.regs[regnum], raw_buffer, REGISTER_RAW_SIZE(regnum));
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, REGISTER_RAW_SIZE(regnum));
}
}
for (regnum = 0; regnum < SP_REGNUM; regnum++)
{
if (fsr.regs[regnum])
{
write_register (regnum, read_memory_unsigned_integer (fsr.regs[regnum], 2));
write_register (regnum, read_memory_unsigned_integer (fsr.regs[regnum], REGISTER_RAW_SIZE(regnum)));
}
}
if (fsr.regs[PSW_REGNUM])
{
write_register (PSW_REGNUM, read_memory_unsigned_integer (fsr.regs[PSW_REGNUM], 2));
write_register (PSW_REGNUM, read_memory_unsigned_integer (fsr.regs[PSW_REGNUM], REGISTER_RAW_SIZE(PSW_REGNUM)));
}
write_register (PC_REGNUM, read_register(13));
write_register (PC_REGNUM, read_register (LR_REGNUM));
write_register (SP_REGNUM, fp + frame->size);
target_store_registers (-1);
flush_cached_frames ();
@ -210,10 +203,10 @@ d10v_frame_chain (frame)
return fsr.regs[SP_REGNUM];
}
if (!read_memory_unsigned_integer(fsr.regs[FP_REGNUM],2))
if (!read_memory_unsigned_integer(fsr.regs[FP_REGNUM], REGISTER_RAW_SIZE(FP_REGNUM)))
return (CORE_ADDR)0;
return read_memory_unsigned_integer(fsr.regs[FP_REGNUM],2)| DMEM_START;
return read_memory_unsigned_integer(fsr.regs[FP_REGNUM], REGISTER_RAW_SIZE(FP_REGNUM))| DMEM_START;
}
static int next_addr, uses_frame;
@ -369,7 +362,7 @@ d10v_frame_find_saved_regs (fi, fsr)
}
if (fsr->regs[LR_REGNUM])
fi->return_pc = (read_memory_unsigned_integer(fsr->regs[LR_REGNUM],2) << 2) | IMEM_START;
fi->return_pc = (read_memory_unsigned_integer(fsr->regs[LR_REGNUM], REGISTER_RAW_SIZE(LR_REGNUM)) << 2) | IMEM_START;
else
fi->return_pc = (read_register(LR_REGNUM) << 2) | IMEM_START;
@ -394,8 +387,21 @@ d10v_init_extra_frame_info (fromleaf, fi)
int fromleaf;
struct frame_info *fi;
{
struct frame_saved_regs dummy;
d10v_frame_find_saved_regs (fi, &dummy);
fi->frameless = 0;
fi->size = 0;
fi->return_pc = 0;
/* The call dummy doesn't save any registers on the stack, so we can
return now. */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
return;
}
else
{
struct frame_saved_regs dummy;
d10v_frame_find_saved_regs (fi, &dummy);
}
}
static void
@ -458,13 +464,15 @@ CORE_ADDR
d10v_read_pc (pid)
int pid;
{
int save_pid, retval;
int save_pid;
CORE_ADDR retval;
save_pid = inferior_pid;
inferior_pid = pid;
retval = (int)read_register (PC_REGNUM);
inferior_pid = save_pid;
return d10v_xlate_addr(retval << 2);
retval = d10v_xlate_addr(retval << 2);
return retval;
}
void
@ -506,51 +514,19 @@ d10v_read_fp ()
return (read_register(FP_REGNUM) | DMEM_START);
}
/* Function: push_return_address (pc)
Set up the return address for the inferior function call.
Needed for targets where we don't actually execute a JSR/BSR instruction */
CORE_ADDR
d10v_fix_call_dummy (dummyname, start_sp, fun, nargs, args, type, gcc_p)
char *dummyname;
CORE_ADDR start_sp;
CORE_ADDR fun;
int nargs;
value_ptr *args;
struct type *type;
int gcc_p;
d10v_push_return_address (pc, sp)
CORE_ADDR pc;
CORE_ADDR sp;
{
int regnum;
CORE_ADDR sp;
char buffer[MAX_REGISTER_RAW_SIZE];
struct frame_info *frame = get_current_frame ();
frame->dummy = start_sp;
start_sp |= DMEM_START;
sp = start_sp;
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
sp -= REGISTER_RAW_SIZE(regnum);
store_address (buffer, REGISTER_RAW_SIZE(regnum), read_register(regnum));
write_memory (sp, buffer, REGISTER_RAW_SIZE(regnum));
}
write_register (SP_REGNUM, (LONGEST)(sp & 0xffff));
/* now we need to load LR with the return address */
write_register (LR_REGNUM, (LONGEST)(d10v_call_dummy_address() & 0xffff) >> 2);
write_register (LR_REGNUM, (CALL_DUMMY_ADDRESS () & 0xffff) >> 2);
return sp;
}
static void
d10v_pop_dummy_frame (fi)
struct frame_info *fi;
{
CORE_ADDR sp = fi->dummy;
int regnum;
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
sp -= REGISTER_RAW_SIZE(regnum);
write_register(regnum, read_memory_unsigned_integer (sp, REGISTER_RAW_SIZE(regnum)));
}
flush_cached_frames (); /* needed? */
}
CORE_ADDR
d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
@ -560,12 +536,16 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
int struct_return;
CORE_ADDR struct_addr;
{
int i, len, index=0, regnum=2;
int i, len;
int index;
int regnum = ARG1_REGNUM;
char buffer[4], *contents;
LONGEST val;
CORE_ADDR ptrs[10];
/* Pass 1. Put all large args on stack */
/* Pass 1. Put all large args on stack, pass pointers */
index = 0;
for (i = 0; i < nargs; i++)
{
value_ptr arg = args[i];
@ -574,15 +554,15 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
contents = VALUE_CONTENTS(arg);
if (len > 4)
{
/* put on stack and pass pointers */
sp -= len;
/* put on word aligned stack and pass pointers */
sp = (sp - len) & ~1;
write_memory (sp, contents, len);
ptrs[index++] = sp;
}
}
/* Pass 2. Fill in registers and arg lists */
index = 0;
for (i = 0; i < nargs; i++)
{
value_ptr arg = args[i];
@ -590,8 +570,8 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
len = TYPE_LENGTH (arg_type);
if (len > 4)
{
/* use a pointer to previously saved data */
if (regnum < 6)
/* pass pointer to previously saved data */
if (regnum <= ARGN_REGNUM)
write_register (regnum++, ptrs[index++]);
else
{
@ -603,6 +583,7 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
}
else
{
int even_regnum = (regnum + 1) & ~1;
contents = VALUE_CONTENTS(arg);
val = extract_signed_integer (contents, len);
/* printf("push: type=%d len=%d val=0x%x\n",arg_type->code,len,val); */
@ -622,17 +603,35 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
}
}
if (regnum < 6 )
if (regnum <= ARGN_REGNUM && len == 1)
{
if (len == 4)
write_register (regnum++, val>>16);
write_register (regnum++, val & 0xff);
}
if (regnum <= ARGN_REGNUM && len == 2)
{
write_register (regnum++, val & 0xffff);
}
else if (even_regnum <= ARGN_REGNUM - 1 && len == 3)
{
/* next even reg and space for two */
/* TARGET_BYTE_ORDER == BIG_ENDIAN */
regnum = even_regnum;
write_register (regnum++, (val >> 8) & 0xffff);
write_register (regnum++, (val & 0xff) << 8);
}
else if (even_regnum <= ARGN_REGNUM - 1 && len == 4)
{
/* next even reg and space for two */
/* TARGET_BYTE_ORDER == BIG_ENDIAN */
regnum = even_regnum;
write_register (regnum++, (val >> 16) & 0xffff);
write_register (regnum++, val & 0xffff);
}
else
{
sp -= len;
store_address (buffer, len, val);
write_memory (sp, buffer, len);
regnum = ARGN_REGNUM + 1;
sp = (sp - len) & ~1;
write_memory (sp, contents, len);
}
}
}
@ -640,58 +639,45 @@ d10v_push_arguments (nargs, args, sp, struct_return, struct_addr)
}
/* pick an out-of-the-way place to set the return value */
/* for an inferior function call. The link register is set to this */
/* value and a momentary breakpoint is set there. When the breakpoint */
/* is hit, the dummy frame is popped and the previous environment is */
/* restored. */
CORE_ADDR
d10v_call_dummy_address ()
{
CORE_ADDR entry;
struct minimal_symbol *sym;
entry = entry_point_address ();
if (entry != 0)
return entry;
sym = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
if (!sym || MSYMBOL_TYPE (sym) != mst_text)
return 0;
else
return SYMBOL_VALUE_ADDRESS (sym);
}
/* Given a return value in `regbuf' with a type `valtype',
extract and copy its value into `valbuf'. */
void
d10v_extract_return_value (valtype, regbuf, valbuf)
struct type *valtype;
d10v_extract_return_value (type, regbuf, valbuf)
struct type *type;
char regbuf[REGISTER_BYTES];
char *valbuf;
{
int len;
/* printf("RET: VALTYPE=%d len=%d r2=0x%x\n",valtype->code, TYPE_LENGTH (valtype), (int)*(short *)(regbuf+REGISTER_BYTE(2))); */
if (valtype->code == TYPE_CODE_PTR)
/* printf("RET: TYPE=%d len=%d r%d=0x%x\n",type->code, TYPE_LENGTH (type), RET1_REGNUM - R0_REGNUM, (int) extract_unsigned_integer (regbuf + REGISTER_BYTE(RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM))); */
if (TYPE_CODE (type) == TYPE_CODE_PTR
&& TYPE_TARGET_TYPE (type)
&& (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
{
/* pointer to function */
int num;
short snum;
snum = (short)extract_address (regbuf + REGISTER_BYTE (2), 2);
snum = extract_address (regbuf + REGISTER_BYTE (RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM));
store_address ( valbuf, 4, D10V_MAKE_IADDR(snum));
}
else if (TYPE_CODE(type) == TYPE_CODE_PTR)
{
/* pointer to data */
int num;
short snum;
snum = extract_address (regbuf + REGISTER_BYTE (RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM));
store_address ( valbuf, 4, D10V_MAKE_DADDR(snum));
}
else
{
len = TYPE_LENGTH (valtype);
len = TYPE_LENGTH (type);
if (len == 1)
{
unsigned short c = extract_unsigned_integer (regbuf + REGISTER_BYTE (2), 2);
unsigned short c = extract_unsigned_integer (regbuf + REGISTER_BYTE (RET1_REGNUM), REGISTER_RAW_SIZE (RET1_REGNUM));
store_unsigned_integer (valbuf, 1, c);
}
else
memcpy (valbuf, regbuf + REGISTER_BYTE (2), len);
memcpy (valbuf, regbuf + REGISTER_BYTE (RET1_REGNUM), len);
}
}