This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] mn10300: Add am33 support


Kevin Buettner wrote:
The following patch adds am33 support to mn10300-tdep.c.

This code has various authors.  I believe that Andrew Cagney, Jackie
Smith Cashion, Alex Oliva, and myself all had a hand in writing bits
of it.  All of the above authors are (or were at the time the code was
written) covered by Red Hat's copyright assignment.

Comments?

Looks great! Thanks for pulling this together. Michael

	* mn10300-tdep.c (am33_2_register_name): New function.
	(my_frame_is_in_sp, my_frame_is_in_fp, my_frame_is_last)
	(set_my_stack_size): Delete.
	(set_movm_offsets, set_reg_offsets): Rename the former to the
	latter.  Update for handling am33.
	(mn10300_analyze_prologue): Update for handling am33.  Also, make
	minor improvements in quality of prologue analysis.
	(mn10300_gdbarch_init):  Add am33 support.
	* mn10300-tdep.h (E_NUM_REGS): Delete.

Index: mn10300-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mn10300-tdep.c,v
retrieving revision 1.129
diff -u -p -r1.129 mn10300-tdep.c
--- mn10300-tdep.c 3 Sep 2005 01:12:21 -0000 1.129
+++ mn10300-tdep.c 3 Sep 2005 01:20:45 -0000
@@ -245,6 +245,22 @@ am33_register_name (int reg)
return register_name (reg, regs, sizeof regs);
}
+static const char *
+am33_2_register_name (int reg)
+{
+ static char *regs[] =
+ {
+ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3",
+ "sp", "pc", "mdr", "psw", "lir", "lar", "mdrq", "r0",
+ "r1", "r2", "r3", "r4", "r5", "r6", "r7", "ssp",
+ "msp", "usp", "mcrh", "mcrl", "mcvf", "fpcr", "", "",
+ "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
+ "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
+ "fs16", "fs17", "fs18", "fs19", "fs20", "fs21", "fs22", "fs23",
+ "fs24", "fs25", "fs26", "fs27", "fs28", "fs29", "fs30", "fs31"
+ };
+ return register_name (reg, regs, sizeof regs);
+}
static struct type *
mn10300_register_type (struct gdbarch *gdbarch, int reg)
@@ -279,54 +295,16 @@ mn10300_breakpoint_from_pc (CORE_ADDR *b
return breakpoint;
}
-/* - * Frame Extra Info:
- *
- * status -- actually frame type (SP, FP, or last frame)
- * stack size -- offset to the next frame
- * - * The former might ultimately be stored in the frame_base.
- * Seems like there'd be a way to store the later too.
- *
- * Temporarily supply empty stub functions as place holders.
- */
-
-static void
-my_frame_is_in_sp (struct frame_info *fi, void **this_cache)
-{
- struct trad_frame_cache *cache = mn10300_frame_unwind_cache (fi, this_cache);
- trad_frame_set_this_base (cache, - frame_unwind_register_unsigned (fi, - E_SP_REGNUM));
-}
-
-static void
-my_frame_is_in_fp (struct frame_info *fi, void **this_cache)
-{
- struct trad_frame_cache *cache = mn10300_frame_unwind_cache (fi, this_cache);
- trad_frame_set_this_base (cache, - frame_unwind_register_unsigned (fi, - E_A3_REGNUM));
-}
-
-static void
-my_frame_is_last (struct frame_info *fi)
-{
-}
-
-static void
-set_my_stack_size (struct frame_info *fi, CORE_ADDR size)
-{
-}
-
-
-/* Set offsets of registers saved by movm instruction.
+/* Set offsets of saved registers.
This is a helper function for mn10300_analyze_prologue. */
static void
-set_movm_offsets (struct frame_info *fi, +set_reg_offsets (struct frame_info *fi, void **this_cache, - int movm_args)
+ int movm_args,
+ int fpregmask,
+ int stack_extra_size,
+ int frame_in_fp)
{
struct trad_frame_cache *cache;
int offset = 0;
@@ -339,7 +317,38 @@ set_movm_offsets (struct frame_info *fi,
if (cache == NULL)
return;
- base = trad_frame_get_this_base (cache);
+ if (frame_in_fp)
+ {
+ base = frame_unwind_register_unsigned (fi, E_A3_REGNUM);
+ }
+ else
+ {
+ base = frame_unwind_register_unsigned (fi, E_SP_REGNUM) + stack_extra_size;
+ }
+
+ trad_frame_set_this_base (cache, base);
+
+ if (AM33_MODE == 2)
+ {
+ /* If bit N is set in fpregmask, fsN is saved on the stack.
+ The floating point registers are saved in ascending order.
+ For example: fs16 <- Frame Pointer
+ fs17 Frame Pointer + 4 */
+ if (fpregmask != 0)
+ {
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ if (fpregmask & (1 << i))
+ {
+ trad_frame_set_reg_addr (cache, E_FS0_REGNUM + i, base + offset);
+ offset += 4;
+ }
+ }
+ }
+ }
+
+
if (movm_args & movm_other_bit)
{
/* The `other' bit leaves a blank area of four bytes at the
@@ -510,11 +519,14 @@ mn10300_analyze_prologue (struct frame_i
CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end, addr, stop;
- long stack_size;
+ long stack_extra_size = 0;
int imm_size;
unsigned char buf[4];
- int status, movm_args = 0;
+ int status;
+ int movm_args = 0;
+ int fpregmask = 0;
char *name;
+ int frame_in_fp = 0;
/* Use the PC in the frame if it's provided to look up the
start of this function.
@@ -526,8 +538,6 @@ mn10300_analyze_prologue (struct frame_i
if (fi)
{
pc = (pc ? pc : get_frame_pc (fi));
- /* At the start of a function our frame is in the stack pointer. */
- my_frame_is_in_sp (fi, this_cache);
}
/* Find the start of this function. */
@@ -540,15 +550,15 @@ mn10300_analyze_prologue (struct frame_i
and I don't want to do that anyway. */
if (status == 0)
{
- return pc;
+ addr = pc;
+ goto finish_prologue;
}
/* If we're in start, then give up. */
if (strcmp (name, "start") == 0)
{
- if (fi != NULL)
- my_frame_is_last (fi);
- return pc;
+ addr = pc;
+ goto finish_prologue;
}
#if 0
@@ -582,10 +592,6 @@ mn10300_analyze_prologue (struct frame_i
}
#endif
- /* NOTE: from here on, we don't want to return without jumping to
- finish_prologue. */
-
-
/* Figure out where to stop scanning. */
stop = fi ? pc : func_end;
@@ -596,7 +602,7 @@ mn10300_analyze_prologue (struct frame_i
addr = func_addr;
/* Suck in two bytes. */
- if (addr + 2 >= stop
+ if (addr + 2 > stop
|| (status = deprecated_read_memory_nobpt (addr, buf, 2)) != 0)
goto finish_prologue;
@@ -605,8 +611,6 @@ mn10300_analyze_prologue (struct frame_i
so mark this as the bottom-most frame. */
if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0)
{
- if (fi)
- my_frame_is_last (fi);
goto finish_prologue;
}
@@ -632,6 +636,136 @@ mn10300_analyze_prologue (struct frame_i
goto finish_prologue;
}
+ if (AM33_MODE == 2)
+ {
+ /* Determine if any floating point registers are to be saved.
+ Look for one of the following three prologue formats:
+
+ [movm [regs],(sp)] [movm [regs],(sp)] [movm [regs],(sp)]
+
+ add -SIZE,sp add -SIZE,sp add -SIZE,sp
+ fmov fs#,(sp) mov sp,a0/a1 mov sp,a0/a1
+ fmov fs#,(#,sp) fmov fs#,(a0/a1+) add SIZE2,a0/a1
+ ... ... fmov fs#,(a0/a1+)
+ ... ... ...
+ fmov fs#,(#,sp) fmov fs#,(a0/a1+) fmov fs#,(a0/a1+)
+
+ [mov sp,a3] [mov sp,a3]
+ [add -SIZE2,sp] [add -SIZE2,sp] */
+
+ /* First, look for add -SIZE,sp (i.e. add imm8,sp (0xf8feXX)
+ or add imm16,sp (0xfafeXXXX)
+ or add imm32,sp (0xfcfeXXXXXXXX)) */
+ imm_size = 0;
+ if (buf[0] == 0xf8 && buf[1] == 0xfe)
+ imm_size = 1;
+ else if (buf[0] == 0xfa && buf[1] == 0xfe)
+ imm_size = 2;
+ else if (buf[0] == 0xfc && buf[1] == 0xfe)
+ imm_size = 4;
+ if (imm_size != 0)
+ {
+ /* An "add -#,sp" instruction has been found. "addr + 2 + imm_size"
+ is the address of the next instruction. Don't modify "addr" until
+ the next "floating point prologue" instruction is found. If this
+ is not a prologue that saves floating point registers we need to
+ be able to back out of this bit of code and continue with the
+ prologue analysis. */
+ if (addr + 2 + imm_size < stop)
+ {
+ status = deprecated_read_memory_nobpt (addr + 2 + imm_size, buf, 3);
+ if (status != 0)
+ goto finish_prologue;
+ if ((buf[0] & 0xfc) == 0x3c)
+ {
+ /* Occasionally, especially with C++ code, the "fmov"
+ instructions will be preceded by "mov sp,aN"
+ (aN => a0, a1, a2, or a3).
+
+ This is a one byte instruction: mov sp,aN = 0011 11XX
+ where XX is the register number.
+
+ Skip this instruction by incrementing addr. (We're
+ committed now.) The "fmov" instructions will have the
+ form "fmov fs#,(aN+)" in this case, but that will not
+ necessitate a change in the "fmov" parsing logic below. */
+
+ addr++;
+
+ if ((buf[1] & 0xfc) == 0x20)
+ {
+ /* Occasionally, especially with C++ code compiled with
+ the -fomit-frame-pointer or -O3 options, the
+ "mov sp,aN" instruction will be followed by an
+ "add #,aN" instruction. This indicates the
+ "stack_size", the size of the portion of the stack
+ containing the arguments. This instruction format is:
+ add #,aN = 0010 00XX YYYY YYYY
+ where XX is the register number
+ YYYY YYYY is the constant.
+ Note the size of the stack (as a negative number) in
+ the frame info structure. */
+ if (fi)
+ stack_extra_size += -buf[2];
+
+ addr += 2;
+ }
+ }
+
+ if ((buf[0] & 0xfc) == 0x3c ||
+ buf[0] == 0xf9 || buf[0] == 0xfb)
+ {
+ /* An "fmov" instruction has been found indicating that this
+ prologue saves floating point registers (or, as described
+ above, a "mov sp,aN" and possible "add #,aN" have been
+ found and we will assume an "fmov" follows). Process the
+ consecutive "fmov" instructions. */
+ for (addr += 2 + imm_size;;addr += imm_size)
+ {
+ int regnum;
+
+ /* Read the "fmov" instruction. */
+ if (addr >= stop ||
+ (status = deprecated_read_memory_nobpt (addr, buf, 4)) != 0)
+ goto finish_prologue;
+
+ if (buf[0] != 0xf9 && buf[0] != 0xfb)
+ break;
+
+ /* Get the floating point register number from the + 2nd and 3rd bytes of the "fmov" instruction:
+ Machine Code: 0000 00X0 YYYY 0000 =>
+ Regnum: 000X YYYY */
+ regnum = (buf[1] & 0x02) << 3;
+ regnum |= ((buf[2] & 0xf0) >> 4) & 0x0f;
+
+ /* Add this register number to the bit mask of floating
+ point registers that have been saved. */
+ fpregmask |= 1 << regnum;
+ + /* Determine the length of this "fmov" instruction.
+ fmov fs#,(sp) => 3 byte instruction
+ fmov fs#,(#,sp) => 4 byte instruction */
+ imm_size = (buf[0] == 0xf9) ? 3 : 4;
+ }
+ }
+ else
+ {
+ /* No "fmov" was found. Reread the two bytes at the original
+ "addr" to reset the state. */
+ status = deprecated_read_memory_nobpt (addr, buf, 2);
+ if (status != 0)
+ goto finish_prologue;
+ }
+ }
+ /* else the prologue consists entirely of an "add -SIZE,sp"
+ instruction. Handle this below. */
+ }
+ /* else no "add -SIZE,sp" was found indicating no floating point
+ registers are saved in this prologue. Do not increment addr. Pretend
+ this bit of code never happened. */
+ }
+
/* Now see if we set up a frame pointer via "mov sp,a3" */
if (buf[0] == 0x3f)
{
@@ -640,7 +774,7 @@ mn10300_analyze_prologue (struct frame_i
/* The frame pointer is now valid. */
if (fi)
{
- my_frame_is_in_fp (fi, this_cache);
+ frame_in_fp = 1;
}
/* Quit now if we're beyond the stop point. */
@@ -679,10 +813,8 @@ mn10300_analyze_prologue (struct frame_i
if (status != 0)
goto finish_prologue;
- /* Note the size of the stack in the frame info structure. */
- stack_size = extract_signed_integer (buf, imm_size);
- if (fi)
- set_my_stack_size (fi, stack_size);
+ /* Note the size of the stack. */
+ stack_extra_size += extract_signed_integer (buf, imm_size);
/* We just consumed 2 + imm_size bytes. */
addr += 2 + imm_size;
@@ -694,7 +826,7 @@ mn10300_analyze_prologue (struct frame_i
finish_prologue:
/* Note if/where callee saved registers were saved. */
if (fi)
- set_movm_offsets (fi, this_cache, movm_args);
+ set_reg_offsets (fi, this_cache, movm_args, fpregmask, stack_extra_size, frame_in_fp);
return addr;
}
@@ -975,6 +1107,7 @@ mn10300_gdbarch_init (struct gdbarch_inf
{
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
+ int num_regs;
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
@@ -989,10 +1122,18 @@ mn10300_gdbarch_init (struct gdbarch_inf
case bfd_mach_mn10300:
set_gdbarch_register_name (gdbarch, mn10300_generic_register_name);
tdep->am33_mode = 0;
+ num_regs = 32;
break;
case bfd_mach_am33:
set_gdbarch_register_name (gdbarch, am33_register_name);
tdep->am33_mode = 1;
+ num_regs = 32;
+ break;
+ case bfd_mach_am33_2:
+ set_gdbarch_register_name (gdbarch, am33_2_register_name);
+ tdep->am33_mode = 2;
+ num_regs = 64;
+ set_gdbarch_fp0_regnum (gdbarch, 32);
break;
default:
internal_error (__FILE__, __LINE__,
@@ -1001,7 +1142,7 @@ mn10300_gdbarch_init (struct gdbarch_inf
}
/* Registers. */
- set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
+ set_gdbarch_num_regs (gdbarch, num_regs);
set_gdbarch_register_type (gdbarch, mn10300_register_type);
set_gdbarch_skip_prologue (gdbarch, mn10300_skip_prologue);
set_gdbarch_read_pc (gdbarch, mn10300_read_pc);
Index: mn10300-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/mn10300-tdep.h,v
retrieving revision 1.5
diff -u -p -r1.5 mn10300-tdep.h
--- mn10300-tdep.h 2 Sep 2005 22:53:34 -0000 1.5
+++ mn10300-tdep.h 3 Sep 2005 01:20:45 -0000
@@ -51,8 +51,7 @@ enum {
E_MCRL_REGNUM = 27,
E_MCVF_REGNUM = 28,
E_FPCR_REGNUM = 29,
- E_FS0_REGNUM = 32,
- E_NUM_REGS = 32
+ E_FS0_REGNUM = 32
};
enum movm_register_bits {





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]