/* Target-dependent code for Renesas Super-H, for GDB.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004 Free Software Foundation, Inc.
+
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GDB.
r15-4-->r15, PR-->(r15) */
#define IS_STS(x) ((x) == 0x4f22)
+/* STS.L MACL,@-r15 0100111100010010
+ r15-4-->r15, MACL-->(r15) */
+#define IS_MACL_STS(x) ((x) == 0x4f12)
+
/* MOV.L Rm,@-r15 00101111mmmm0110
r15-4-->r15, Rm-->(R15) */
#define IS_PUSH(x) (((x) & 0xff0f) == 0x2f06)
#define IS_MOVW_PCREL_TO_REG(x) (((x) & 0xf000) == 0x9000)
/* MOV.L @(disp*4,PC),Rn 1101nnnndddddddd */
#define IS_MOVL_PCREL_TO_REG(x) (((x) & 0xf000) == 0xd000)
+/* MOVI20 #imm20,Rn 0000nnnniiii0000 */
+#define IS_MOVI20(x) (((x) & 0xf00f) == 0x0000)
/* SUB Rn,R15 00111111nnnn1000 */
#define IS_SUB_REG_FROM_SP(x) (((x) & 0xff0f) == 0x3f08)
#define IS_RESTORE_FP(x) ((x) == 0x6ef6)
#define IS_RTS(x) ((x) == 0x000b)
#define IS_LDS(x) ((x) == 0x4f26)
+#define IS_MACL_LDS(x) ((x) == 0x4f16)
#define IS_MOV_FP_SP(x) ((x) == 0x6fe3)
#define IS_ADD_REG_TO_FP(x) (((x) & 0xff0f) == 0x3e0c)
#define IS_ADD_IMM_FP(x) (((x) & 0xff00) == 0x7e00)
cache->saved_regs[PR_REGNUM] = cache->sp_offset;
cache->sp_offset += 4;
}
+ else if (IS_MACL_STS (inst))
+ {
+ cache->saved_regs[MACL_REGNUM] = cache->sp_offset;
+ cache->sp_offset += 4;
+ }
else if (IS_MOV_R3 (inst))
{
r3_val = ((inst & 0xff) ^ 0x80) - 0x80;
}
}
}
+ else if (IS_MOVI20 (inst))
+ {
+ if (sav_reg < 0)
+ {
+ reg = GET_TARGET_REG (inst);
+ if (reg < 14)
+ {
+ sav_reg = reg;
+ sav_offset = GET_SOURCE_REG (inst) << 16;
+ /* MOVI20 is a 32 bit instruction! */
+ pc += 2;
+ sav_offset |= read_memory_unsigned_integer (pc, 2);
+ /* Now sav_offset contains an unsigned 20 bit value.
+ It must still get sign extended. */
+ if (sav_offset & 0x00080000)
+ sav_offset |= 0xfff00000;
+ }
+ }
+ }
else if (IS_SUB_REG_FROM_SP (inst))
{
reg = GET_SOURCE_REG (inst);
{
/* value gets right-justified in the register or stack word */
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- memcpy (valbuf + (4 - len), (char *) VALUE_CONTENTS (val), len);
+ memcpy (valbuf + (4 - len), (char *) value_contents (val), len);
else
- memcpy (valbuf, (char *) VALUE_CONTENTS (val), len);
+ memcpy (valbuf, (char *) value_contents (val), len);
return valbuf;
}
- return (char *) VALUE_CONTENTS (val);
+ return (char *) value_contents (val);
}
/* Helper function to eval number of bytes to allocate on stack. */
{
int stack_alloc = 0;
while (nargs-- > 0)
- stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[nargs])) + 3) & ~3);
+ stack_alloc += ((TYPE_LENGTH (value_type (args[nargs])) + 3) & ~3);
return stack_alloc;
}
in four registers available. Loop thru args from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
- type = VALUE_TYPE (args[argnum]);
+ type = value_type (args[argnum]);
len = TYPE_LENGTH (type);
val = sh_justify_value_in_reg (args[argnum], len);
in four registers available. Loop thru args from first to last. */
for (argnum = 0; argnum < nargs; argnum++)
{
- type = VALUE_TYPE (args[argnum]);
+ type = value_type (args[argnum]);
len = TYPE_LENGTH (type);
val = sh_justify_value_in_reg (args[argnum], len);
containing the (raw) register state a function return value of type
TYPE, and copy that, in virtual format, into VALBUF. */
static void
-sh_default_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+sh_extract_return_value_nofpu (struct type *type, struct regcache *regcache,
+ void *valbuf)
{
int len = TYPE_LENGTH (type);
int return_register = R0_REGNUM;
regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
}
else
- error ("bad size for return value");
+ error (_("bad size for return value"));
}
static void
-sh3e_sh4_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+sh_extract_return_value_fpu (struct type *type, struct regcache *regcache,
+ void *valbuf)
{
if (sh_treat_as_flt_p (type))
{
regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
}
else
- sh_default_extract_return_value (type, regcache, valbuf);
+ sh_extract_return_value_nofpu (type, regcache, valbuf);
}
/* Write into appropriate registers a function return value
depending on the type of the return value. In all the other cases
the result is stored in r0, left-justified. */
static void
-sh_default_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+sh_store_return_value_nofpu (struct type *type, struct regcache *regcache,
+ const void *valbuf)
{
ULONGEST val;
int len = TYPE_LENGTH (type);
}
static void
-sh3e_sh4_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+sh_store_return_value_fpu (struct type *type, struct regcache *regcache,
+ const void *valbuf)
{
if (sh_treat_as_flt_p (type))
{
regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
}
else
- sh_default_store_return_value (type, regcache, valbuf);
+ sh_store_return_value_nofpu (type, regcache, valbuf);
+}
+
+static enum return_value_convention
+sh_return_value_nofpu (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache,
+ void *readbuf, const void *writebuf)
+{
+ if (sh_use_struct_convention (0, type))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ if (writebuf)
+ sh_store_return_value_nofpu (type, regcache, writebuf);
+ else if (readbuf)
+ sh_extract_return_value_nofpu (type, regcache, readbuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+static enum return_value_convention
+sh_return_value_fpu (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache,
+ void *readbuf, const void *writebuf)
+{
+ if (sh_use_struct_convention (0, type))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ if (writebuf)
+ sh_store_return_value_fpu (type, regcache, writebuf);
+ else if (readbuf)
+ sh_extract_return_value_fpu (type, regcache, readbuf);
+ return RETURN_VALUE_REGISTER_CONVENTION;
}
/* Print the registers in a form similar to the E7000 */
&val, to);
}
else
- error ("sh_register_convert_to_raw called with non DR register number");
+ error (_("sh_register_convert_to_raw called with non DR register number"));
}
/* For vectors of 4 floating point registers. */
int base_regnum, portion;
char temp_buffer[MAX_REGISTER_SIZE];
+ if (reg_nr == PSEUDO_BANK_REGNUM)
+ regcache_raw_read (regcache, BANK_REGNUM, buffer);
+ else
if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
{
base_regnum = dr_reg_base_num (reg_nr);
int base_regnum, portion;
char temp_buffer[MAX_REGISTER_SIZE];
- if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
+ if (reg_nr == PSEUDO_BANK_REGNUM)
+ {
+ /* When the bank register is written to, the whole register bank
+ is switched and all values in the bank registers must be read
+ from the target/sim again. We're just invalidating the regcache
+ so that a re-read happens next time it's necessary. */
+ int bregnum;
+
+ regcache_raw_write (regcache, BANK_REGNUM, buffer);
+ for (bregnum = R0_BANK0_REGNUM; bregnum < MACLB_REGNUM; ++bregnum)
+ set_register_cached (bregnum, 0);
+ }
+ else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
{
base_regnum = dr_reg_base_num (reg_nr);
{
if (regnum < NUM_REGS || regnum >= NUM_REGS + NUM_PSEUDO_REGS)
internal_error (__FILE__, __LINE__,
- "Invalid pseudo register number %d\n", regnum);
+ _("Invalid pseudo register number %d\n"), regnum);
else if (regnum == PSEUDO_BANK_REGNUM)
do_bank_register_info (gdbarch, file);
else if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
raw_buffer = (char *) alloca (register_size (gdbarch, FP0_REGNUM));
/* Get the data in raw format. */
- if (!frame_register_read (get_selected_frame (), regnum, raw_buffer))
- error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
+ if (!frame_register_read (get_selected_frame (NULL), regnum, raw_buffer))
+ error (_("can't read register %d (%s)"), regnum, REGISTER_NAME (regnum));
/* Get the register as a number */
flt = unpack_double (builtin_type_float, raw_buffer, &inv);
print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
/* Get the data in raw format. */
- if (!frame_register_read (get_selected_frame (), regnum, raw_buffer))
+ if (!frame_register_read (get_selected_frame (NULL), regnum, raw_buffer))
fprintf_filtered (file, "*value not available*\n");
val_print (gdbarch_register_type (gdbarch, regnum), raw_buffer, 0, 0,
{
if (regnum < 0 || regnum >= NUM_REGS + NUM_PSEUDO_REGS)
internal_error (__FILE__, __LINE__,
- "Invalid register number %d\n", regnum);
+ _("Invalid register number %d\n"), regnum);
else if (regnum >= 0 && regnum < NUM_REGS)
{
if (regnum != -1) /* do one specified register */
{
if (*(REGISTER_NAME (regnum)) == '\0')
- error ("Not a valid register for the current processor type");
+ error (_("Not a valid register for the current processor type"));
sh_print_register (gdbarch, file, regnum);
}
return;
}
- frame_register_unwind (next_frame, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ *optimizedp = 0;
+ *lvalp = lval_register;
+ *addrp = 0;
+ *realnump = regnum;
+ if (valuep)
+ frame_unwind_register (next_frame, (*realnump), valuep);
}
static void
else if (!IS_RESTORE_FP (read_memory_unsigned_integer (addr + 2, 2)))
return 0;
- /* Step over possible lds.l @r15+,pr. */
inst = read_memory_unsigned_integer (addr - 2, 2);
+
+ /* Step over possible lds.l @r15+,macl. */
+ if (IS_MACL_LDS (inst))
+ {
+ addr -= 2;
+ inst = read_memory_unsigned_integer (addr - 2, 2);
+ }
+
+ /* Step over possible lds.l @r15+,pr. */
if (IS_LDS (inst))
{
addr -= 2;
inst = read_memory_unsigned_integer (addr - 2, 2);
}
+ /* On SH2a check if the previous instruction was perhaps a MOVI20.
+ That's allowed for the epilogue. */
+ if ((gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a
+ || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a_nofpu)
+ && addr > func_addr + 6
+ && IS_MOVI20 (read_memory_unsigned_integer (addr - 4, 2)))
+ addr -= 4;
+
if (pc >= addr)
return 1;
}
set_gdbarch_print_registers_info (gdbarch, sh_print_registers_info);
set_gdbarch_breakpoint_from_pc (gdbarch, sh_breakpoint_from_pc);
- set_gdbarch_deprecated_use_struct_convention (gdbarch, sh_use_struct_convention);
set_gdbarch_print_insn (gdbarch, gdb_print_insn_sh);
set_gdbarch_register_sim_regno (gdbarch, legacy_register_sim_regno);
set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
- set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
- set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
- set_gdbarch_deprecated_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
+ set_gdbarch_return_value (gdbarch, sh_return_value_nofpu);
+ set_gdbarch_deprecated_extract_struct_value_address (gdbarch,
+ sh_extract_struct_value_address);
set_gdbarch_skip_prologue (gdbarch, sh_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_register_name (gdbarch, sh_sh2e_register_name);
set_gdbarch_register_type (gdbarch, sh_sh3e_register_type);
set_gdbarch_fp0_regnum (gdbarch, 25);
- set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
- set_gdbarch_extract_return_value (gdbarch,
- sh3e_sh4_extract_return_value);
+ set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
break;
set_gdbarch_num_pseudo_regs (gdbarch, 9);
set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
- set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
- set_gdbarch_extract_return_value (gdbarch, sh3e_sh4_extract_return_value);
+ set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
break;
set_gdbarch_register_name (gdbarch, sh_sh3e_register_name);
set_gdbarch_register_type (gdbarch, sh_sh3e_register_type);
set_gdbarch_fp0_regnum (gdbarch, 25);
- set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
- set_gdbarch_extract_return_value (gdbarch,
- sh3e_sh4_extract_return_value);
+ set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
break;
set_gdbarch_num_pseudo_regs (gdbarch, 13);
set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
- set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
- set_gdbarch_extract_return_value (gdbarch,
- sh3e_sh4_extract_return_value);
+ set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
break;
gdbarch_register (bfd_arch_sh, sh_gdbarch_init, NULL);
- add_com ("regs", class_vars, sh_show_regs_command, "Print all registers");
+ add_com ("regs", class_vars, sh_show_regs_command, _("Print all registers"));
}