/* Target dependent code for GDB on TI C6x systems.
- Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ Copyright (C) 2010-2015 Free Software Foundation, Inc.
Contributed by Andrew Jenner <andrew@codesourcery.com>
Contributed by Yao Qi <yao@codesourcery.com>
#include "linux-tdep.h"
#include "solib.h"
#include "objfiles.h"
-#include "gdb_assert.h"
#include "osabi.h"
#include "tic6x-tdep.h"
#include "language.h"
Bail out early if CURRENT_PC is reached. Returns the address of the first
instruction after the prologue. */
-CORE_ADDR
+static CORE_ADDR
tic6x_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
const CORE_ADDR current_pc,
struct tic6x_unwind_cache *cache,
/* This is the implementation of gdbarch method skip_prologue. */
-CORE_ADDR
+static CORE_ADDR
tic6x_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
- CORE_ADDR limit_pc;
CORE_ADDR func_addr;
struct tic6x_unwind_cache cache;
/* This is the implementation of gdbarch method breakpiont_from_pc. */
-const unsigned char*
+static const gdb_byte *
tic6x_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
int *bp_size)
{
/* Frame base handling. */
-struct tic6x_unwind_cache*
+static struct tic6x_unwind_cache*
tic6x_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
CORE_ADDR current_pc;
struct tic6x_unwind_cache *cache;
- int i;
if (*this_prologue_cache)
- return *this_prologue_cache;
+ return (struct tic6x_unwind_cache *) *this_prologue_cache;
cache = FRAME_OBSTACK_ZALLOC (struct tic6x_unwind_cache);
(*this_prologue_cache) = cache;
if (*this_cache == NULL)
*this_cache = tic6x_make_stub_cache (this_frame);
- cache = *this_cache;
+ cache = (struct tic6x_unwind_cache *) *this_cache;
*this_id = frame_id_build (cache->cfa, get_frame_pc (this_frame));
}
CORE_ADDR addr_in_block;
addr_in_block = get_frame_address_in_block (this_frame);
- if (in_plt_section (addr_in_block, NULL))
+ if (in_plt_section (addr_in_block))
return 1;
return 0;
{
struct gdbarch *gdbarch = get_frame_arch (frame);
unsigned long inst;
- int offset;
int register_number;
int last = 0;
/* This is the implementation of gdbarch method software_single_step. */
-int
+static int
tic6x_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
return align_down (addr, 8);
}
-/* This is the implementation of gdbarch method register_to_value. */
-
-static int
-tic6x_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, gdb_byte * to,
- int *optimizedp, int *unavailablep)
-{
- get_frame_register (frame, regnum, (char *) to);
- *optimizedp = *unavailablep = 0;
- return 1;
-}
-
-/* This is the implementation of gdbarch method value_to_register. */
-
-static void
-tic6x_value_to_register (struct frame_info *frame, int regnum,
- struct type *type, const gdb_byte *from)
-{
- put_frame_register (frame, regnum, from);
-}
-
/* Given a return value in REGCACHE with a type VALTYPE, extract and copy its
value into VALBUF. */
/* This is the implementation of gdbarch method return_value. */
static enum return_value_convention
-tic6x_return_value (struct gdbarch *gdbarch, struct type *func_type,
+tic6x_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
+ /* In C++, when function returns an object, even its size is small
+ enough, it stii has to be passed via reference, pointed by register
+ A3. */
+ if (current_language->la_language == language_cplus)
+ {
+ if (type != NULL)
+ {
+ type = check_typedef (type);
+ if (language_pass_by_reference (type))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ }
+ }
+
if (TYPE_LENGTH (type) > 8)
return RETURN_VALUE_STRUCT_CONVENTION;
{
int argreg = 0;
int argnum;
- int len = 0;
int stack_offset = 4;
int references_offset = 4;
CORE_ADDR func_addr = find_function_addr (function, NULL);
/* The first arg passed on stack. Mostly the first 10 args are passed by
registers. */
int first_arg_on_stack = 10;
- /* If this inf-call is a cpp method call, and return value is passed by
- reference, this flag is set to 1, otherwise set to 0. We need this flag
- because computation of the return location in
- infcall.c:call_function_by_hand is wrong for C6000 ELF ABI. In
- call_function_by_hand, the language is considered first, and then
- target ABI is considered. If language_pass_by_reference returns true,
- the return location is passed as the first parameter to the function,
- which is conflict with C6000 ELF ABI. If this flag is true, we should
- adjust args and return locations accordingly to comply with C6000 ELF
- ABI. */
- int cplus_return_struct_by_reference = 0;
-
- if (current_language->la_language == language_cplus)
- {
- struct type *values_type;
-
- find_function_addr (function, &values_type);
- if (values_type)
- {
- CHECK_TYPEDEF (values_type);
- if (language_pass_by_reference (values_type))
- cplus_return_struct_by_reference = 1;
- }
-
- }
/* Set the return address register to point to the entry point of
the program, where a breakpoint lies in wait. */
regcache_cooked_write_unsigned (regcache, TIC6X_RA_REGNUM, bp_addr);
the address in A3. */
if (struct_return)
regcache_cooked_write_unsigned (regcache, 3, struct_addr);
- else if (cplus_return_struct_by_reference)
- /* When cplus_return_struct_by_reference is 1, means local variable
- lang_struct_return in call_function_by_hand is 1, so struct is
- returned by reference, even STRUCT_RETURN is 0. Note that STRUCT_ADDR
- is still valid in this case. */
- regcache_cooked_write_unsigned (regcache, 3, struct_addr);
/* Determine the type of this function. */
func_type = check_typedef (func_type);
if (TYPE_VARARGS (func_type))
first_arg_on_stack = TYPE_NFIELDS (func_type) - 1;
- /* Now make space on the stack for the args. If
- cplus_return_struct_by_reference is 1, means GDB pass an extra parameter
- in ARGS, which is useless here, skip it. */
- for (argnum = cplus_return_struct_by_reference; argnum < nargs; argnum++)
+ /* Now make space on the stack for the args. */
+ for (argnum = 0; argnum < nargs; argnum++)
{
int len = align_up (TYPE_LENGTH (value_type (args[argnum])), 4);
if (argnum >= 10 - argreg)
/* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. Loop through args
from first to last. */
- for (argnum = cplus_return_struct_by_reference; argnum < nargs; argnum++)
+ for (argnum = 0; argnum < nargs; argnum++)
{
const gdb_byte *val;
struct value *arg = args[argnum];
return sp;
}
-/* This is the implementation of gdbarch method in_function_epilogue_p. */
+/* This is the implementation of gdbarch method stack_frame_destroyed_p. */
static int
-tic6x_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+tic6x_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
unsigned long inst = tic6x_fetch_instruction (gdbarch, pc);
/* Normally, the epilogue is composed by instruction `b .S2 b3'. */
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR jb_addr;
- char buf[4];
+ gdb_byte buf[4];
/* JMP_BUF is passed by reference in A4. */
jb_addr = get_frame_register_unsigned (frame, 4);
return 1;
}
+/* This is the implementation of gdbarch method
+ return_in_first_hidden_param_p. */
+
+static int
+tic6x_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
+ struct type *type)
+{
+ return 0;
+}
+
static struct gdbarch *
tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
return arches->gdbarch;
}
- tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
+ tdep = XCNEW (struct gdbarch_tdep);
tdep->has_gp = has_gp;
gdbarch = gdbarch_alloc (&info, tdep);
frame_unwind_append_unwinder (gdbarch, &tic6x_stub_unwind);
frame_unwind_append_unwinder (gdbarch, &tic6x_frame_unwind);
+ frame_base_set_default (gdbarch, &tic6x_frame_base);
dwarf2_frame_set_init_reg (gdbarch, tic6x_dwarf2_frame_init_reg);
/* Call dummy code. */
set_gdbarch_frame_align (gdbarch, tic6x_frame_align);
- set_gdbarch_register_to_value (gdbarch, tic6x_register_to_value);
- set_gdbarch_value_to_register (gdbarch, tic6x_value_to_register);
-
set_gdbarch_return_value (gdbarch, tic6x_return_value);
set_gdbarch_dummy_id (gdbarch, tic6x_dummy_id);
set_gdbarch_get_longjmp_target (gdbarch, tic6x_get_longjmp_target);
- set_gdbarch_in_function_epilogue_p (gdbarch, tic6x_in_function_epilogue_p);
+ set_gdbarch_stack_frame_destroyed_p (gdbarch, tic6x_stack_frame_destroyed_p);
+
+ set_gdbarch_return_in_first_hidden_param_p (gdbarch,
+ tic6x_return_in_first_hidden_param_p);
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
return gdbarch;
}
+/* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_tic6x_tdep;
+
void
_initialize_tic6x_tdep (void)
{