This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[committed] avr: introduce pc pseudo-register
- From: Tristan Gingold <gingold at adacore dot com>
- To: gdb-patches ml <gdb-patches at sourceware dot org>
- Date: Tue, 10 Nov 2009 12:14:18 +0100
- Subject: [committed] avr: introduce pc pseudo-register
Hi,
it is not possible to define a type for the pc register:
* it must be a pointer to function so that 'x /i $pc' reads bytes from
the instruction set
* but if it is a pointer to function, it should be a word index (as
are avr pointers to function). But in
this case it is not anymore an address which makes gdb wrong.
To solve this issue, we create a pc pseudo register, which is a
pointer to function. This pseudo register
doesn't need to be an address and is purely for the user.
Tristan.
2009-11-10 Tristan Gingold <gingold@adacore.com>
* avr-tdep.c: Add AVR_PSEUDO_PC_REGNUM and AVR_NUM_PSEUDO_REGS.
(struct gdbarch_tdep): Add void_type, func_void_type and pc_type
fields.
(avr_register_name): Add "pc" name, renames "PC" to "PC2".
(avr_register_type): Handle AVR_PSEUDO_PC_REGNUM.
(avr_write_pc): Fix indentation.
(avr_pseudo_register_read): New function.
(avr_pseudo_register_write): New function.
(avr_frame_prev_register): Handle AVR_PSEUDO_PC_REGNUM.
(avr_gdbarch_init): Create types for pc. Register pseudo regs.
*** avr-tdep.c 10 Nov 2009 10:48:51 -0000 1.121
--- avr-tdep.c 10 Nov 2009 11:13:55 -0000
***************
*** 89,94 ****
--- 89,98 ----
AVR_NUM_REGS = 32 + 1 /*SREG*/ + 1 /*SP*/ + 1 /*PC*/,
AVR_NUM_REG_BYTES = 32 + 1 /*SREG*/ + 2 /*SP*/ + 4 /*PC*/,
+ /* Pseudo registers. */
+ AVR_PSEUDO_PC_REGNUM = 35,
+ AVR_NUM_PSEUDO_REGS = 1,
+
AVR_PC_REG_INDEX = 35, /* index into array of registers */
AVR_MAX_PROLOGUE_SIZE = 64, /* bytes */
***************
*** 181,186 ****
--- 185,197 ----
/* Number of bytes stored to the stack by call instructions.
2 bytes for avr1-5, 3 bytes for avr6. */
int call_length;
+
+ /* Type for void. */
+ struct type *void_type;
+ /* Type for a function returning void. */
+ struct type *func_void_type;
+ /* Type for a pointer to a function. Used for the type of PC. */
+ struct type *pc_type;
};
/* Lookup the name of a register given it's number. */
***************
*** 193,199 ****
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
! "SREG", "SP", "PC"
};
if (regnum < 0)
return NULL;
--- 204,211 ----
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
! "SREG", "SP", "PC2",
! "pc"
};
if (regnum < 0)
return NULL;
***************
*** 210,219 ****
{
if (reg_nr == AVR_PC_REGNUM)
return builtin_type (gdbarch)->builtin_uint32;
if (reg_nr == AVR_SP_REGNUM)
return builtin_type (gdbarch)->builtin_data_ptr;
! else
! return builtin_type (gdbarch)->builtin_uint8;
}
/* Instruction address checks and convertions. */
--- 222,232 ----
{
if (reg_nr == AVR_PC_REGNUM)
return builtin_type (gdbarch)->builtin_uint32;
+ if (reg_nr == AVR_PSEUDO_PC_REGNUM)
+ return gdbarch_tdep (gdbarch)->pc_type;
if (reg_nr == AVR_SP_REGNUM)
return builtin_type (gdbarch)->builtin_data_ptr;
! return builtin_type (gdbarch)->builtin_uint8;
}
/* Instruction address checks and convertions. */
***************
*** 338,344 ****
avr_write_pc (struct regcache *regcache, CORE_ADDR val)
{
regcache_cooked_write_unsigned (regcache, AVR_PC_REGNUM,
! avr_convert_iaddr_to_raw (val));
}
/* Function: avr_scan_prologue
--- 351,393 ----
avr_write_pc (struct regcache *regcache, CORE_ADDR val)
{
regcache_cooked_write_unsigned (regcache, AVR_PC_REGNUM,
! avr_convert_iaddr_to_raw (val));
! }
!
! static void
! avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache
*regcache,
! int regnum, gdb_byte *buf)
! {
! ULONGEST val;
!
! switch (regnum)
! {
! case AVR_PSEUDO_PC_REGNUM:
! regcache_raw_read_unsigned (regcache, AVR_PC_REGNUM, &val);
! val >>= 1;
! store_unsigned_integer (buf, 4, gdbarch_byte_order (gdbarch),
val);
! break;
! default:
! internal_error (__FILE__, __LINE__, _("invalid regnum"));
! }
! }
!
! static void
! avr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache
*regcache,
! int regnum, const gdb_byte *buf)
! {
! ULONGEST val;
!
! switch (regnum)
! {
! case AVR_PSEUDO_PC_REGNUM:
! val = extract_unsigned_integer (buf, 4, gdbarch_byte_order
(gdbarch));
! val <<= 1;
! regcache_raw_write_unsigned (regcache, AVR_PC_REGNUM, val);
! break;
! default:
! internal_error (__FILE__, __LINE__, _("invalid regnum"));
! }
}
/* Function: avr_scan_prologue
***************
*** 1036,1044 ****
struct avr_unwind_cache *info
= avr_frame_unwind_cache (this_frame, this_prologue_cache);
! if (regnum == AVR_PC_REGNUM)
{
! if (trad_frame_addr_p (info->saved_regs, regnum))
{
/* Reading the return PC from the PC register is slightly
abnormal. register_size(AVR_PC_REGNUM) says it is 4 bytes,
--- 1085,1093 ----
struct avr_unwind_cache *info
= avr_frame_unwind_cache (this_frame, this_prologue_cache);
! if (regnum == AVR_PC_REGNUM || regnum == AVR_PSEUDO_PC_REGNUM)
{
! if (trad_frame_addr_p (info->saved_regs, AVR_PC_REGNUM))
{
/* Reading the return PC from the PC register is slightly
abnormal. register_size(AVR_PC_REGNUM) says it is 4 bytes,
***************
*** 1058,1071 ****
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
! read_memory (info->saved_regs[regnum].addr, buf, tdep-
>call_length);
/* Extract the PC read from memory as a big-endian. */
pc = 0;
for (i = 0; i < tdep->call_length; i++)
pc = (pc << 8) | buf[i];
! return frame_unwind_got_constant (this_frame, regnum, pc << 1);
}
return frame_unwind_got_optimized (this_frame, regnum);
--- 1107,1124 ----
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
! read_memory (info->saved_regs[AVR_PC_REGNUM].addr,
! buf, tdep->call_length);
/* Extract the PC read from memory as a big-endian. */
pc = 0;
for (i = 0; i < tdep->call_length; i++)
pc = (pc << 8) | buf[i];
! if (regnum == AVR_PC_REGNUM)
! pc <<= 1;
!
! return frame_unwind_got_constant (this_frame, regnum, pc);
}
return frame_unwind_got_optimized (this_frame, regnum);
***************
*** 1327,1332 ****
--- 1380,1393 ----
tdep->call_length = call_length;
+ /* Create a type for PC. We can't use builtin types here, as they
may not
+ be defined. */
+ tdep->void_type = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+ tdep->func_void_type = make_function_type (tdep->void_type, NULL);
+ tdep->pc_type = arch_type (gdbarch, TYPE_CODE_PTR, 4, NULL);
+ TYPE_TARGET_TYPE (tdep->pc_type) = tdep->func_void_type;
+ TYPE_UNSIGNED (tdep->pc_type) = 1;
+
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
***************
*** 1353,1358 ****
--- 1414,1423 ----
set_gdbarch_register_name (gdbarch, avr_register_name);
set_gdbarch_register_type (gdbarch, avr_register_type);
+ set_gdbarch_num_pseudo_regs (gdbarch, AVR_NUM_PSEUDO_REGS);
+ set_gdbarch_pseudo_register_read (gdbarch,
avr_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch,
avr_pseudo_register_write);
+
set_gdbarch_return_value (gdbarch, avr_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_avr);