o Update GDB to match changes to d10v abi (ARG1 in r0 instead of r2).
authorAndrew Cagney <cagney@redhat.com>
Fri, 6 Feb 1998 04:09:35 +0000 (04:09 +0000)
committerAndrew Cagney <cagney@redhat.com>
Fri, 6 Feb 1998 04:09:35 +0000 (04:09 +0000)
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.

gdb/ChangeLog
gdb/config/d10v/tm-d10v.h
gdb/d10v-tdep.c

index 7cca88f9df2f8ae42a452a08d8e2e5e8f3b58b60..3ba4250f1a5c61163b837738415b74af73bae510 100644 (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
index ca1ef07eecbab0f698b24f8fd371228b413bd47a..bbcd182c63a79c9cad5919be22f0704ff1ecad20 100644 (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)
 \f
 
 /* 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
index 5b9e980e8be4de271ed9feed179b9d6ffe9c2f2f..fa7956bbd270c0520f0c290947ea9c08846a1426 100644 (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)
+           {
+             write_register (regnum++, val & 0xff);
+           }
+         if (regnum <= ARGN_REGNUM && len == 2)
            {
-             if (len == 4)
-               write_register (regnum++, val>>16);
+             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 = 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 =  (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_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);
     }
 }