This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Add support for Tilera TILE-Gx processor (part 1/3: gdb)
Hi Jeff,
On 05/21/2012 03:23 PM, Jeff Kenton wrote:
> gdb/
> * Makefile.in (ALL_TARGET_OBJS): Add tilegx-tdep.o, tilegx-linux-tdep.o.
> (ALLDEPFILES): tilegx-linux-nat.c tilegx-tdep.c tilegx-linux-tdep.c.
^
"Add " missing.
> * configure.tgt: Add tilegx target.
> * tilegx-tdep.c: New file
Missing period.
> * tilegx-linux-tdep.c: New file
Missing period.
> * regformats/reg-tilegx.dat: New file.
>
> diff -r -u -N /home/packages/gdb-7.4x/gdb/configure.tgt ./gdb/configure.tgt
> --- /home/packages/gdb-7.4x/gdb/configure.tgt 2012-03-05 06:41:51.000000000 -0500
> +++ ./gdb/configure.tgt 2012-05-18 14:00:31.387177000 -0400
> @@ -551,6 +551,13 @@
> gdb_target_obs="tic6x-tdep.o"
> ;;
>
> +tilegx-*-linux*)
> + # Target: TILE-Gx
> + gdb_target_obs="tilegx-tdep.o tilegx-linux-tdep.o solib-svr4.o \
> + symfile-mem.o glibc-tdep.o linux-tdep.o"
> + ;;
> +
> +
> xstormy16-*-*)
> # Target: Sanyo Xstormy16a processor
> gdb_target_obs="xstormy16-tdep.o"
> diff -r -u -N /home/packages/gdb-7.4x/gdb/Makefile.in ./gdb/Makefile.in
> --- /home/packages/gdb-7.4x/gdb/Makefile.in 2012-03-28 17:31:18.000000000 -0400
> +++ ./gdb/Makefile.in 2012-05-18 14:00:31.295201000 -0400
> @@ -565,6 +565,7 @@
> sparc-sol2-tdep.o sparc-tdep.o \
> spu-tdep.o spu-multiarch.o solib-spu.o \
> tic6x-tdep.o tic6x-linux-tdep.o \
> + tilegx-tdep.o tilegx-linux-tdep.o \
> v850-tdep.o \
> vaxnbsd-tdep.o vaxobsd-tdep.o vax-tdep.o \
> xstormy16-tdep.o \
> @@ -1510,6 +1511,8 @@
> sparc64nbsd-nat.c sparc64nbsd-tdep.c sparc64obsd-tdep.c \
> sparcnbsd-nat.c sparcnbsd-tdep.c sparcobsd-tdep.c \
> spu-linux-nat.c spu-tdep.c spu-multiarch.c solib-spu.c \
> + tilegx-linux-nat.c tilegx-tdep.c tilegx-linux-tdep.c \
> + config/tilegx/nm-linux.h \
"config/tilegx/nm-linux.h" shouldn't be here.
> v850-tdep.c \
> vax-nat.c vax-tdep.c vaxbsd-nat.c vaxnbsd-tdep.c \
> windows-nat.c windows-tdep.c \
> diff -r -u -N /home/packages/gdb-7.4x/gdb/regformats/reg-tilegx.dat ./gdb/regformats/reg-tilegx.dat
> --- /home/packages/gdb-7.4x/gdb/regformats/reg-tilegx.dat 1969-12-31 19:00:00.000000000 -0500
> +++ ./gdb/regformats/reg-tilegx.dat 2012-05-18 14:00:31.508189000 -0400
> @@ -0,0 +1,67 @@
> +name:tile
> +expedite:sp,lr,pc
> +64:r0
> +64:r1
> +64:r2
> +64:r3
> +64:r4
> +64:r5
> +64:r6
> +64:r7
> +64:r8
> +64:r9
> +64:r10
> +64:r11
> +64:r12
> +64:r13
> +64:r14
> +64:r15
> +64:r16
> +64:r17
> +64:r18
> +64:r19
> +64:r20
> +64:r21
> +64:r22
> +64:r23
> +64:r24
> +64:r25
> +64:r26
> +64:r27
> +64:r28
> +64:r29
> +64:r30
> +64:r31
> +64:r32
> +64:r33
> +64:r34
> +64:r35
> +64:r36
> +64:r37
> +64:r38
> +64:r39
> +64:r40
> +64:r41
> +64:r42
> +64:r43
> +64:r44
> +64:r45
> +64:r46
> +64:r47
> +64:r48
> +64:r49
> +64:r50
> +64:r51
> +64:r52
> +64:tp
> +64:sp
> +64:lr
> +64:sn
> +64:io0
> +64:io1
> +64:us0
> +64:us1
> +64:us2
> +64:us3
> +64:zero
> +64:pc
> diff -r -u -N /home/packages/gdb-7.4x/gdb/tilegx-linux-tdep.c ./gdb/tilegx-linux-tdep.c
> --- /home/packages/gdb-7.4x/gdb/tilegx-linux-tdep.c 1969-12-31 19:00:00.000000000 -0500
> +++ ./gdb/tilegx-linux-tdep.c 2012-05-18 16:06:18.990217000 -0400
> @@ -0,0 +1,77 @@
> +/* Target-dependent code for GNU/Linux on Xtensa processors.
> +
> + Copyright 2012 Free Software Foundation, Inc.
> +
> + This file is part of GDB.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include "defs.h"
> +#include "osabi.h"
> +#include "linux-tdep.h"
> +#include "glibc-tdep.h"
> +#include "solib-svr4.h"
> +#include "symtab.h"
> +#include "tramp-frame.h"
> +#include <signal.h>
> +#include <sys/ucontext.h>
These last two system includes are a sign of something not being host
independent here. But I don't think you need them?
> +
> +/* Signal trampoline support. */
> +
> +static void
> +tilegx_linux_sigframe_init (const struct tramp_frame *self,
> + struct frame_info *this_frame,
> + struct trad_frame_cache *this_cache,
> + CORE_ADDR func)
> +{
> + /* Stub. */
> +}
> +
> +static const struct tramp_frame tilegx_linux_rt_sigframe =
> +{
> + SIGTRAMP_FRAME,
> + 4,
> + {
> + { 0x00045fe551483000, -1 }, /* { moveli r10, 139 } */
> + { 0x286b180051485000, -1 }, /* { swint1 } */
> + { TRAMP_SENTINEL_INSN, -1 }
> + },
> + tilegx_linux_sigframe_init
> +};
> +
> +/* OS specific initialization of gdbarch. */
> +
> +static void
> +tilegx_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> +{
> + linux_init_abi (info, gdbarch);
> +
> + tramp_frame_prepend_unwinder (gdbarch, &tilegx_linux_rt_sigframe);
> +
> + /* Shared library handling. */
> + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> + set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
> +
> + set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
> +}
> +
> +/* Provide a prototype to silence -Wmissing-prototypes. */
> +extern initialize_file_ftype _initialize_tilegx_linux_tdep;
> +
> +void
> +_initialize_tilegx_linux_tdep (void)
> +{
> + gdbarch_register_osabi (bfd_arch_tilegx, bfd_mach_tilegx, GDB_OSABI_LINUX,
> + tilegx_linux_init_abi);
> +}
> diff -r -u -N /home/packages/gdb-7.4x/gdb/tilegx-tdep.c ./gdb/tilegx-tdep.c
> --- /home/packages/gdb-7.4x/gdb/tilegx-tdep.c 1969-12-31 19:00:00.000000000 -0500
> +++ ./gdb/tilegx-tdep.c 2012-05-21 08:09:54.479718000 -0400
> @@ -0,0 +1,1164 @@
> +/* Target-dependent code for the Tilera TILE-Gx processor.
> +
> + Copyright (C) 2012 Free Software Foundation, Inc.
> +
> + This file is part of GDB.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include "defs.h"
> +#include "frame.h"
> +#include "frame-base.h"
> +#include "frame-unwind.h"
> +#include "dwarf2-frame.h"
> +#include "trad-frame.h"
> +#include "symtab.h"
> +#include "gdbtypes.h"
> +#include "gdbcmd.h"
> +#include "gdbcore.h"
> +#include "value.h"
> +#include "dis-asm.h"
> +#include "inferior.h"
> +#include "gdb_string.h"
> +#include "gdb_assert.h"
> +#include "arch-utils.h"
> +#include "floatformat.h"
> +#include "regcache.h"
> +#include "regset.h"
> +#include "doublest.h"
> +#include "osabi.h"
> +#include "linux-tdep.h"
> +#include "objfiles.h"
> +#include "solib-svr4.h"
> +#include "symtab.h"
> +
> +#include "opcode/tilegx.h"
> +
> +/* TILE-Gx has 56 general purpose registers (R0 - R52, TP, SP, LR),
> + plus 8 special general purpose registers (network and ZERO),
> + plus 1 magic register (PC).
> +
> + TP (aka R53) is the thread specific data pointer.
> + SP (aka R54) is the stack pointer.
> + LR (aka R55) is the link register.
> + */
> +enum {
> +
> + E_R0_REGNUM,
Correct formatting is:
enum
{
E_R0_REGNUM,
> + E_R1_REGNUM,
> + E_R2_REGNUM,
> + E_R3_REGNUM,
> + E_R4_REGNUM,
> + E_R5_REGNUM,
> + E_R6_REGNUM,
> + E_R7_REGNUM,
> + E_R8_REGNUM,
> + E_R9_REGNUM,
> + E_R10_REGNUM,
> + E_R11_REGNUM,
> + E_R12_REGNUM,
> + E_R13_REGNUM,
> + E_R14_REGNUM,
> + E_R15_REGNUM,
> + E_R16_REGNUM,
> + E_R17_REGNUM,
> + E_R18_REGNUM,
> + E_R19_REGNUM,
> + E_R20_REGNUM,
> + E_R21_REGNUM,
> + E_R22_REGNUM,
> + E_R23_REGNUM,
> + E_R24_REGNUM,
> + E_R25_REGNUM,
> + E_R26_REGNUM,
> + E_R27_REGNUM,
> + E_R28_REGNUM,
> + E_R29_REGNUM,
> + E_R30_REGNUM,
> + E_R31_REGNUM,
> + E_R32_REGNUM,
> + E_R33_REGNUM,
> + E_R34_REGNUM,
> + E_R35_REGNUM,
> + E_R36_REGNUM,
> + E_R37_REGNUM,
> + E_R38_REGNUM,
> + E_R39_REGNUM,
> + E_R40_REGNUM,
> + E_R41_REGNUM,
> + E_R42_REGNUM,
> + E_R43_REGNUM,
> + E_R44_REGNUM,
> + E_R45_REGNUM,
> + E_R46_REGNUM,
> + E_R47_REGNUM,
> + E_R48_REGNUM,
> + E_R49_REGNUM,
> + E_R50_REGNUM,
> + E_R51_REGNUM,
> + E_R52_REGNUM,
> + E_TP_REGNUM,
> + E_SP_REGNUM,
> + E_LR_REGNUM,
> +
> + E_SN_REGNUM, E_NUM_EASY_REGS = E_SN_REGNUM, /* 56 */
> + E_IO0_REGNUM,
> + E_IO1_REGNUM,
> + E_US0_REGNUM,
> + E_US1_REGNUM,
> + E_US2_REGNUM,
> + E_US3_REGNUM,
> + E_ZERO_REGNUM,
> +
> + E_PC_REGNUM, E_NUM_PHYS_REGS = E_PC_REGNUM, /* 64 */
> +
> + E_NUM_REGS /* 65 */
> +};
> +
> +
> +struct tilegx_frame_cache
> +{
> + /* Base address. */
> + CORE_ADDR base;
> + CORE_ADDR start_pc;
Missing comment on this field.
> +
> + /* Table of saved registers. */
> + struct trad_frame_saved_reg *saved_regs;
> +};
> +
> +/* Register state values used by analyze_prologue(). */
> +enum reverse_state {
> + REVERSE_STATE_REGISTER,
enum reverse_state
{
REVERSE_STATE_REGISTER,
> +/* Register state used by analyze_prologue(). */
Don't write "analyze_prologue()" when referring to a function.
Just write "analyze_prologue".
> +struct tilegx_reverse_regs
> +{
> + LONGEST value;
> + enum reverse_state state;
> +};
> +
> +static const struct tilegx_reverse_regs
> +template_reverse_regs[E_NUM_PHYS_REGS] =
> + {
> + { E_R0_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R1_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R2_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R3_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R4_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R5_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R6_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R7_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R8_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R9_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R10_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R11_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R12_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R13_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R14_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R15_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R16_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R17_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R18_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R19_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R20_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R21_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R22_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R23_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R24_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R25_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R26_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R27_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R28_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R29_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R30_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R31_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R32_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R33_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R34_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R35_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R36_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R37_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R38_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R39_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R40_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R41_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R42_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R43_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R44_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R45_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R46_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R47_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R48_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R49_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R50_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R51_REGNUM, REVERSE_STATE_REGISTER },
> + { E_R52_REGNUM, REVERSE_STATE_REGISTER },
> + { E_TP_REGNUM, REVERSE_STATE_REGISTER },
> + { E_SP_REGNUM, REVERSE_STATE_REGISTER },
> + { E_LR_REGNUM, REVERSE_STATE_REGISTER },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { 0, REVERSE_STATE_UNKNOWN },
> + { E_ZERO_REGNUM, REVERSE_STATE_VALUE }
> + };
> +
> +
> +enum { tilegx_reg_size = 8 };
> +
> +/* Returns non-zero if the given struct type will be returned using
> + a special convention, rather than the normal function return method.
> + Used in the context of the "return" command, and target function
> + calls from the debugger. */
> +
> +static int
> +tilegx_use_struct_convention (struct type *type)
> +{
> + /* Only scalars which fit in R0 - R9 can be returned in registers.
> + Otherwise, they are returned via a pointer passed in R0. */
> + return !tilegx_type_is_scalar (type)
> + && (TYPE_LENGTH (type) > (1 + E_R9_REGNUM - E_R0_REGNUM)
> + * tilegx_reg_size);
> +}
> +
> +/* Find a function's return value in the appropriate registers (in
> + regbuf), and copy it into valbuf. */
> +
> +static void
> +tilegx_extract_return_value (struct type *type, struct regcache *regcache,
> + gdb_byte *valbuf)
> +{
> + int len = TYPE_LENGTH (type);
> + int i, regnum = E_R0_REGNUM;
> +
> + for (i = 0; i < len; i += tilegx_reg_size)
> + regcache_raw_read (regcache, regnum++, valbuf + i);
> +}
> +
> +/* Copy the function return value from VALBUF into the proper
> + location for a function return.
> + Called only in the context of the "return" command. */
> +
> +static void
> +tilegx_store_return_value (struct type *type, struct regcache *regcache,
> + const void *valbuf)
> +{
> + if (TYPE_LENGTH (type) < tilegx_reg_size)
> + {
> + /* Add leading zeros to the value. */
You say "leading", but zeros are added at the end? Or this an endian thing?
> + gdb_byte buf[tilegx_reg_size];
> +
> + memset (buf, 0, tilegx_reg_size);
You can just write:
gdb_byte buf[tilegx_reg_size] = { 0 };
> + memcpy (buf, valbuf, TYPE_LENGTH (type));
> + regcache_raw_write (regcache, E_R0_REGNUM, buf);
> + }
> + else
> + {
> + int len = TYPE_LENGTH (type);
> + int i, regnum = E_R0_REGNUM;
> +
> + for (i = 0; i < len; i += tilegx_reg_size)
> + regcache_raw_write (regcache, regnum++, (gdb_byte *) valbuf + i);
> + }
> +}
> +
> +/* This is the implementation of gdbarch method return_value. */
> +
> +static enum return_value_convention
> +tilegx_return_value (struct gdbarch *gdbarch, struct type *func_type,
> + struct type *type, struct regcache *regcache,
> + gdb_byte *readbuf, const gdb_byte *writebuf)
> +{
> + if (tilegx_use_struct_convention (type))
> + return RETURN_VALUE_STRUCT_CONVENTION;
> + if (writebuf)
> + tilegx_store_return_value (type, regcache, writebuf);
> + else if (readbuf)
> + tilegx_extract_return_value (type, regcache, readbuf);
> + return RETURN_VALUE_REGISTER_CONVENTION;
> +}
> +
> +/* This is the implementation of gdbarch method frame_align. */
> +
> +static CORE_ADDR
> +tilegx_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
> +{
> + return addr & -8;
> +}
> +
> +
> +/* Implement the "push_dummy_call" gdbarch method. */
> +
> +static CORE_ADDR
> +tilegx_push_dummy_call (struct gdbarch *gdbarch,
> + struct value *function,
> + struct regcache *regcache,
> + CORE_ADDR bp_addr, int nargs,
> + struct value **args,
> + CORE_ADDR sp, int struct_return,
> + CORE_ADDR struct_addr)
> +{
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + CORE_ADDR stack_dest = sp;
> + int argreg = E_R0_REGNUM;
> + int i, j;
> + int typelen, slacklen, alignlen;
> + static const gdb_byte two_zero_words[8] = { 0 };
> +
> + /* If struct_return is 1, then the struct return address will
> + consume one argument-passing register. */
> + if (struct_return)
> + regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
> +
> + /* Arguments are passed in R0 - R9, and as soon as an argument
> + will not fit completely in the remaining registers, then it,
> + and all remaining arguments, are put on the stack. */
> + for (i = 0; i < nargs && argreg <= E_R9_REGNUM; i++)
> + {
> + const char *val;
gdb_byte
> + typelen = TYPE_LENGTH (value_enclosing_type (args[i]));
> +
> + if (typelen > (E_R9_REGNUM - argreg + 1) * tilegx_reg_size)
> + break;
> +
> + /* Put argument into registers wordwise. */
> + val = value_contents (args[i]);
> + for (j = 0; j < typelen; j += tilegx_reg_size)
> + {
> + /* ISSUE: Why special handling for "typelen = 4x + 1"?
> + I don't ever see "typelen" values except 4 and 8. */
> + int n = (typelen - j == 1) ? 1 : tilegx_reg_size;
> + ULONGEST w = extract_unsigned_integer (val + j, n, byte_order);
> +
> + regcache_cooked_write_unsigned (regcache, argreg++, w);
> + }
> + }
> +
> + /* Align SP. */
> + stack_dest = tilegx_frame_align (gdbarch, stack_dest);
> +
> + /* Loop backwards through arguments to determine stack alignment. */
> + alignlen = 0;
> +
> + for (j = nargs - 1; j >= i; j--)
> + {
> + typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
> + alignlen += (typelen + 3) & (~3);
> + }
> +
> + if (alignlen & 0x4)
> + stack_dest -= 4;
> +
> + /* Loop backwards through remaining arguments and push them on
> + the stack, word aligned. */
> + for (j = nargs - 1; j >= i; j--)
> + {
> + gdb_byte *val;
> +
> + typelen = TYPE_LENGTH (value_enclosing_type (args[j]));
> + slacklen = ((typelen + 3) & (~3)) - typelen;
> + val = alloca (typelen + slacklen);
> + memcpy (val, value_contents (args[j]), typelen);
> + memset (val + typelen, 0, slacklen);
> +
> + /* Now write data to the stack. The stack grows downwards. */
> + stack_dest -= typelen + slacklen;
> + write_memory (stack_dest, val, typelen + slacklen);
> + }
> +
> + /* Add 2 words for linkage space to the stack. */
> + stack_dest = stack_dest - 8;
> + write_memory (stack_dest, two_zero_words, 8);
> +
> + /* Update stack pointer. */
> + regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, stack_dest);
> +
> + /* 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, E_LR_REGNUM, bp_addr);
> +
> + return stack_dest;
> +}
> +
> +
> +/* Decode the instructions within the given address range.
> + Decide when we must have reached the end of the function prologue.
> + If a frame_info pointer is provided, fill in its saved_regs etc.
> + Returns the address of the first instruction after the prologue.
> + NOTE: This is often called with start_addr being the start of some
> + function, and end_addr being the current PC. */
> +
> +static CORE_ADDR
> +tilegx_analyze_prologue (struct gdbarch* gdbarch,
> + CORE_ADDR start_addr, CORE_ADDR end_addr,
> + struct tilegx_frame_cache *cache,
> + struct frame_info *next_frame)
> +{
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + CORE_ADDR next_addr;
> + CORE_ADDR prolog_end = end_addr;
> + ULONGEST inst, inst2;
> + LONGEST offset;
> + int regnum;
> + gdb_byte instbuf[32 * TILEGX_BUNDLE_SIZE_IN_BYTES];
> + CORE_ADDR instbuf_start;
> + unsigned int instbuf_size;
> + int status;
> + bfd_uint64_t bundle;
> + struct tilegx_decoded_instruction
> + decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
> + int num_insns;
> + struct tilegx_reverse_regs reverse_frame[E_NUM_PHYS_REGS];
> + struct tilegx_reverse_regs
> + new_reverse_frame[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
> + int dest_regs[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
> + int reverse_frame_valid, prolog_done, branch_seen;
> + LONGEST prev_sp_value;
> + int i, j;
> +
> + if (start_addr >= end_addr
> + || (start_addr % TILEGX_BUNDLE_ALIGNMENT_IN_BYTES) != 0)
> + return end_addr;
> +
> + /* Initialize the reverse frame. This maps the CURRENT frame's
> + registers to the outer frame's registers (the frame on the
> + stack goes the other way). */
> + memcpy (&reverse_frame, &template_reverse_regs,
> + sizeof (reverse_frame));
> +
> + prolog_done = 0;
> + branch_seen = 0;
> + prev_sp_value = 0;
> +
> + /* To cut down on round-trip overhead, we fetch multiple bundles
> + at once. These variables describe the range of memory we have
> + prefetched. */
> + instbuf_start = 0;
> + instbuf_size = 0;
> +
> + for (next_addr = start_addr; next_addr < end_addr;
> + next_addr += TILEGX_BUNDLE_SIZE_IN_BYTES)
> + {
> + /* Retrieve the next instruction. */
> + if (next_addr - instbuf_start >= instbuf_size)
> + {
> + /* Figure out how many bytes to fetch. Don't span a page
> + boundary since that might cause an unnecessary memory
> + error. */
> + unsigned int size_on_same_page = 4096 - (next_addr & 4095);
> + instbuf_size = sizeof instbuf;
> +
> + if (instbuf_size > size_on_same_page)
> + instbuf_size = size_on_same_page;
> + instbuf_start = next_addr;
> +
> + status = safe_frame_unwind_memory (next_frame, instbuf_start,
> + instbuf, instbuf_size);
> + if (status == 0)
> + memory_error (status, next_addr);
> + }
> +
> + reverse_frame_valid = 0;
> +
> + bundle = extract_unsigned_integer (&instbuf[next_addr
> + - instbuf_start],
> + 8, byte_order);
> +
> + num_insns = parse_insn_tilegx (bundle, next_addr, decoded);
> +
> + for (i = 0; i < num_insns; i++)
> + {
> + struct tilegx_decoded_instruction *this_insn = &decoded[i];
> + int64_t *operands = (int64_t *) this_insn->operand_values;
> + const struct tilegx_opcode *opcode = this_insn->opcode;
> +
> + switch (opcode->mnemonic)
> + {
> + case TILEGX_OPC_ST:
> + if (cache &&
> + reverse_frame[operands[0]].state == REVERSE_STATE_VALUE
Operator at the beginning of the next line:
if (cache
&& reverse_frame[operands[0]].state == REVERSE_STATE_VALUE
> + && reverse_frame[operands[1]].state
> + == REVERSE_STATE_REGISTER)
> + {
> + LONGEST saved_address = reverse_frame[operands[0]].value;
> + unsigned saved_register =
> + (unsigned) reverse_frame[operands[1]].value;
Likewise:
unsigned saved_register
= (unsigned) reverse_frame[operands[1]].value;
> +
> + /* realreg >= 0 and addr != -1 indicates that the
> + value of saved_register is in memory location
> + saved_address. The value of realreg is not
> + meaningful in this case but it must be >= 0.
> + See trad-frame.h. */
> + cache->saved_regs[saved_register].realreg =
> + saved_register;
> + cache->saved_regs[saved_register].addr =
> + saved_address;
Likewise. Though it looks like it could fit a single line.
> + }
> + break;
> + case TILEGX_OPC_ADDI:
> + case TILEGX_OPC_ADDLI:
> + if (cache
> + && operands[0] == E_SP_REGNUM
> + && operands[1] == E_SP_REGNUM
> + && reverse_frame[operands[1]].state ==
> + REVERSE_STATE_REGISTER)
> + {
> + /* Special case. We're fixing up the stack frame. */
> + uint64_t hopefully_sp =
> + (unsigned) reverse_frame[operands[1]].value;
Likewise. Many more instances.
> + short op2_as_short = (short) operands[2];
> + signed char op2_as_char = (signed char) operands[2];
> +
> + /* Fix up the sign-extension. */
> + if (opcode->mnemonic == TILEGX_OPC_ADDI)
> + op2_as_short = op2_as_char;
> + prev_sp_value = cache->saved_regs[hopefully_sp].addr
> + - op2_as_short;
Wrap multiline expressions in in ()'s and reindent:
prev_sp_value = (cache->saved_regs[hopefully_sp].addr
- op2_as_short);
> +
> + new_reverse_frame[i].state = REVERSE_STATE_VALUE;
> + new_reverse_frame[i].value =
> + cache->saved_regs[hopefully_sp].addr;
> + trad_frame_set_value (cache->saved_regs,
> + hopefully_sp, prev_sp_value);
> + }
> + else
> + {
> + short op2_as_short = (short) operands[2];
> + signed char op2_as_char = (signed char) operands[2];
> +
> + /* Fix up the sign-extension. */
> + if (opcode->mnemonic == TILEGX_OPC_ADDI)
> + op2_as_short = op2_as_char;
> +
> + new_reverse_frame[i] = reverse_frame[operands[1]];
> + if (new_reverse_frame[i].state == REVERSE_STATE_VALUE)
> + new_reverse_frame[i].value += op2_as_short;
> + else
> + new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
> + }
> + reverse_frame_valid |= 1<<i;
Missing spaces around "<<". Can i be > 31? If so, this is undefined. More instances of this.
> + dest_regs[i] = operands[0];
> + break;
> + case TILEGX_OPC_ADD:
> + if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE
> + && reverse_frame[operands[2]].state == REVERSE_STATE_VALUE)
> + {
> + /* We have values -- we can do this. */
> + new_reverse_frame[i] = reverse_frame[operands[2]];
> + new_reverse_frame[i].value +=
> + reverse_frame[operands[i]].value;
> + }
> + else
> + {
> + /* We don't know anything about the values. Punt. */
> + new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
> + }
> + reverse_frame_valid |= 1<<i;
> + dest_regs[i] = operands[0];
> + break;
> + case TILEGX_OPC_MOVE:
> + new_reverse_frame[i] = reverse_frame[operands[1]];
> + reverse_frame_valid |= 1<<i;
> + dest_regs[i] = operands[0];
> + break;
> + case TILEGX_OPC_MOVEI:
> + case TILEGX_OPC_MOVELI:
> + new_reverse_frame[i].state = REVERSE_STATE_VALUE;
> + new_reverse_frame[i].value = operands[1];
> + reverse_frame_valid |= 1<<i;
> + dest_regs[i] = operands[0];
> + break;
> + case TILEGX_OPC_ORI:
> + if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE)
> + {
> + /* We have a value in A -- we can do this. */
> + new_reverse_frame[i] = reverse_frame[operands[1]];
> + new_reverse_frame[i].value =
> + reverse_frame[operands[1]].value | operands[2];
> + }
> + else if (operands[2] == 0)
> + {
> + /* This is a move. */
> + new_reverse_frame[i] = reverse_frame[operands[1]];
> + }
> + else
> + {
> + /* We don't know anything about the values. Punt. */
> + new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
> + }
> + reverse_frame_valid |= 1<<i;
> + dest_regs[i] = operands[0];
> + break;
> + case TILEGX_OPC_OR:
> + if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE
> + && reverse_frame[operands[1]].value == 0)
> + {
> + /* This is a move. */
> + new_reverse_frame[i] = reverse_frame[operands[2]];
> + }
> + else if (reverse_frame[operands[2]].state == REVERSE_STATE_VALUE
> + && reverse_frame[operands[2]].value == 0)
> + {
> + /* This is a move. */
> + new_reverse_frame[i] = reverse_frame[operands[1]];
> + }
> + else
> + {
> + /* We don't know anything about the values. Punt. */
> + new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
> + }
> + reverse_frame_valid |= 1<<i;
> + dest_regs[i] = operands[0];
> + break;
> + case TILEGX_OPC_SUB:
> + if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE
> + && reverse_frame[operands[2]].state == REVERSE_STATE_VALUE)
> + {
> + /* We have values -- we can do this. */
> + new_reverse_frame[i] = reverse_frame[operands[1]];
> + new_reverse_frame[i].value -=
> + reverse_frame[operands[2]].value;
> + }
> + else
> + {
> + /* We don't know anything about the values. Punt. */
> + new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
> + }
> + reverse_frame_valid |= 1<<i;
> + dest_regs[i] = operands[0];
> + break;
> +
> + case TILEGX_OPC_FNOP:
> + case TILEGX_OPC_INFO:
> + case TILEGX_OPC_INFOL:
> + /* Nothing to see here, move on.
> + Note that real NOP is treated as a 'real' instruction
> + because someone must have intended that it be there.
> + It therefore terminates the prolog.
> + */
> + break;
> +
> + case TILEGX_OPC_J:
> + case TILEGX_OPC_JAL:
> +
> + case TILEGX_OPC_BEQZ:
> + case TILEGX_OPC_BEQZT:
> + case TILEGX_OPC_BGEZ:
> + case TILEGX_OPC_BGEZT:
> + case TILEGX_OPC_BGTZ:
> + case TILEGX_OPC_BGTZT:
> + case TILEGX_OPC_BLBC:
> + case TILEGX_OPC_BLBCT:
> + case TILEGX_OPC_BLBS:
> + case TILEGX_OPC_BLBST:
> + case TILEGX_OPC_BLEZ:
> + case TILEGX_OPC_BLEZT:
> + case TILEGX_OPC_BLTZ:
> + case TILEGX_OPC_BLTZT:
> + case TILEGX_OPC_BNEZ:
> + case TILEGX_OPC_BNEZT:
> +
> + case TILEGX_OPC_IRET:
> + case TILEGX_OPC_JALR:
> + case TILEGX_OPC_JALRP:
> + case TILEGX_OPC_JR:
> + case TILEGX_OPC_JRP:
> + case TILEGX_OPC_SWINT0:
> + case TILEGX_OPC_SWINT1:
> + case TILEGX_OPC_SWINT2:
> + case TILEGX_OPC_SWINT3:
> + /* We're really done -- this is a branch. */
> + branch_seen = 1;
> + prolog_done = 1;
> + break;
> + default:
> + /* We don't know or care what this instruction is.
> + All we know is that it isn't part of a prolog, and if
> + there's a destination register, we're trashing it. */
> + prolog_done = 1;
> + for (j = 0; j < opcode->num_operands; j++)
> + {
> + if (this_insn->operands[j]->is_dest_reg)
> + {
> + dest_regs[i] = operands[j];
> + new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
> + reverse_frame_valid |= 1<<i;
> + break;
> + }
> + }
> + break;
> + }
> + }
> +
> + /* Now update the reverse frames. */
> + for (i = 0; i < num_insns; i++)
> + {
> + /* ISSUE: Does this properly handle "network" registers? */
> + if ((reverse_frame_valid & (1<<i))
> + && dest_regs[i] != E_ZERO_REGNUM)
> + reverse_frame[dest_regs[i]] = new_reverse_frame[i];
> + }
> +
> + if (prev_sp_value != 0)
> + {
> + /* GCC uses R52 as a frame pointer. Have we seen "move r52, sp"? */
> + if (reverse_frame[E_R52_REGNUM].state == REVERSE_STATE_REGISTER
> + && reverse_frame[E_R52_REGNUM].value == E_SP_REGNUM)
> + {
> + reverse_frame[E_R52_REGNUM].state = REVERSE_STATE_VALUE;
> + reverse_frame[E_R52_REGNUM].value = prev_sp_value;
> + }
> +
> + prev_sp_value = 0;
> + }
> +
> + if (prolog_done && prolog_end == end_addr)
> + {
> + /* We found non-prolog code. As such, _this_ instruction
> + is the one after the prolog. We keep processing, because
> + there may be more prolog code in there, but this is what
> + we'll return. */
> + /* ISSUE: There may not have actually been a prologue, and
> + we may have simply skipped some random instructions. */
> + prolog_end = next_addr;
> + }
> + if (branch_seen)
> + {
> + /* We saw a branch. The prolog absolutely must be over. */
> + break;
> + }
> + }
> +
> + if (prolog_end == end_addr && cache)
> + {
> + /* We may have terminated the prolog early, and we're certainly
> + at THIS point right now. It's possible that the values of
> + registers we need are currently actually in other registers
> + (and haven't been written to memory yet). Go find them. */
> + for (i = 0; i < E_NUM_PHYS_REGS; i++)
> + {
> + if (reverse_frame[i].state == REVERSE_STATE_REGISTER
> + && reverse_frame[i].value != i)
> + {
> + unsigned saved_register = (unsigned) reverse_frame[i].value;
> +
> + cache->saved_regs[saved_register].realreg = i;
> + cache->saved_regs[saved_register].addr = (LONGEST) -1;
> + }
> + }
> + }
> +
> + return prolog_end;
> +}
> +
> +/* This is the implementation of gdbarch method skip_prologue. */
> +
> +static CORE_ADDR
> +tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
> +{
> + struct symtab_and_line sal;
> + CORE_ADDR func_start, func_end;
> +
> + /* This is the preferred method, find the end of the prologue by
> + using the debugging information. */
> + if (find_pc_partial_function (pc, NULL, &func_start, &func_end))
> + {
> + sal = find_pc_line (func_start, 0);
> +
> + if (sal.end < func_end && pc <= sal.end)
> + return sal.end;
> + }
> +
> + /* Otherwise, try to skip prologue the hard way. */
> + return tilegx_analyze_prologue (gdbarch,
> + pc, pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES,
> + NULL, NULL);
> +}
> +
> +/* This is the implementation of gdbarch method in_function_epilogue_p. */
> +
> +static int
> +tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
> +{
> + CORE_ADDR func_addr = 0, func_end = 0;
> +
> + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
> + {
> + ULONGEST inst, inst2;
> + CORE_ADDR addr = func_end - TILEGX_BUNDLE_SIZE_IN_BYTES;
> +
> + /* FIXME: Find the actual epilogue. */
> + /* HACK: Just assume the final bundle is the "ret" instruction". */
> + if (pc > addr)
> + return 1;
> + }
> + return 0;
> +}
> +
> +/* This is the implementation of gdbarch method breakpoint_from_pc. */
> +
> +static const unsigned char *
> +tilegx_breakpoint_from_pc (struct gdbarch *gdbarch,
> + CORE_ADDR *pcptr, int *lenptr)
> +{
> + /* 64-bit pattern for a { bpt ; nop } bundle. */
> + static unsigned char breakpoint[] =
> + { 0x00, 0x50, 0x48, 0x51, 0xae, 0x44, 0x6a, 0x28 };
> +
> + *lenptr = sizeof (breakpoint);
> + return breakpoint;
> +}
> +
> +/* Normal frames. */
> +
> +static struct tilegx_frame_cache *
> +tilegx_frame_cache (struct frame_info *this_frame, void **this_cache)
> +{
> + struct gdbarch *gdbarch = get_frame_arch (this_frame);
> + struct tilegx_frame_cache *cache;
> + CORE_ADDR current_pc;
> + int i;
> +
> + if (*this_cache)
> + return *this_cache;
> +
> + cache = FRAME_OBSTACK_ZALLOC (struct tilegx_frame_cache);
> + *this_cache = cache;
> + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
> + cache->base = 0;
> + cache->start_pc = get_frame_func (this_frame);
> + current_pc = get_frame_pc (this_frame);
> +
> + cache->base = get_frame_register_unsigned (this_frame, E_SP_REGNUM);
> + trad_frame_set_value (cache->saved_regs, E_SP_REGNUM, cache->base);
> +
> + cache->saved_regs[E_PC_REGNUM] = cache->saved_regs[E_LR_REGNUM];
> +
> + if (cache->start_pc)
> + tilegx_analyze_prologue (gdbarch, cache->start_pc, current_pc,
> + cache, this_frame);
> +
> + return cache;
> +}
> +
> +/* Retrieve the value of REGNUM in FRAME. */
> +
> +static struct value*
> +tilegx_frame_prev_register (struct frame_info *this_frame,
> + void **this_cache,
> + int regnum)
> +{
> + struct tilegx_frame_cache *info =
> + tilegx_frame_cache (this_frame, this_cache);
> +
> + return trad_frame_get_prev_register (this_frame, info->saved_regs,
> + regnum);
> +}
> +
> +/* Build frame id. */
> +static void
Missing empty line.
> +tilegx_frame_this_id (struct frame_info *this_frame, void **this_cache,
> + struct frame_id *this_id)
> +{
> + struct tilegx_frame_cache *info =
> + tilegx_frame_cache (this_frame, this_cache);
> +
> + /* This marks the outermost frame. */
> + if (info->base == 0)
> + return;
> +
> + (*this_id) = frame_id_build (info->base, info->start_pc);
> +}
> +
> +static CORE_ADDR
> +tilegx_frame_base_address (struct frame_info *this_frame, void **this_cache)
> +{
> + struct tilegx_frame_cache *cache =
> + tilegx_frame_cache (this_frame, this_cache);
> +
> + return cache->base;
> +}
> +
> +static const struct frame_unwind tilegx_frame_unwind = {
> + NORMAL_FRAME,
> + default_frame_unwind_stop_reason,
> + tilegx_frame_this_id,
> + tilegx_frame_prev_register,
> + NULL, /* const struct frame_data *unwind_data */
> + default_frame_sniffer, /* frame_sniffer_ftype *sniffer */
> + NULL /* frame_prev_pc_ftype *prev_pc */
> +};
> +
> +static const struct frame_base tilegx_frame_base = {
> + &tilegx_frame_unwind,
> + tilegx_frame_base_address,
> + tilegx_frame_base_address,
> + tilegx_frame_base_address
> +};
> +
> +static CORE_ADDR
> +tilegx_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
> +{
> + return frame_unwind_register_unsigned (next_frame, E_SP_REGNUM);
> +}
> +
> +static CORE_ADDR
> +tilegx_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
> +{
> + return frame_unwind_register_unsigned (next_frame, E_PC_REGNUM);
> +}
> +
> +static struct frame_id
> +tilegx_unwind_dummy_id (struct gdbarch *gdbarch,
> + struct frame_info *this_frame)
> +{
> + CORE_ADDR sp;
> +
> + sp = get_frame_register_unsigned (this_frame, E_SP_REGNUM);
> + return frame_id_build (sp, get_frame_pc (this_frame));
> +}
> +
> +
> +/* We cannot read/write the "special" registers. */
> +
> +static int
> +tilegx_cannot_reference_register (struct gdbarch *gdbarch, int regno)
> +{
> + if (regno >= 0 && regno < E_NUM_EASY_REGS)
> + return 0;
> + else if (regno == E_PC_REGNUM)
> + return 0;
> + else
> + return 1;
> +}
> +
> +/* Supply raw registers from REGCACHE to REGS. */
> +
> +static void
> +tilegx_linux_supply_regset (const struct regset *regset,
> + struct regcache *regcache,
> + int regnum, const void *regs, size_t len)
> +{
> + struct gdbarch *arch = get_regcache_arch (regcache);
> + const char *ptr = regs;
> + int i;
> +
> + /* This logic must match that of struct pt_regs in "ptrace.h". */
> + for (i = 0; i < E_NUM_EASY_REGS + 1; i++, ptr += tilegx_reg_size)
> + {
> + int gri = (i < E_NUM_EASY_REGS) ? i : E_PC_REGNUM;
> +
> + if (regnum == gri || regnum == -1)
> + regcache_raw_supply (regcache, gri, ptr);
> + }
> +}
> +
> +
> +/* TILE-Gx Linux kernal register set. */
Typo, "kernel".
> +static struct regset tilegx_linux_regset =
> +{
> + NULL,
> + tilegx_linux_supply_regset
> +};
> +
> +static const struct regset *
> +tilegx_regset_from_core_section (struct gdbarch *gdbarch,
> + const char *sect_name,
> + size_t sect_size)
> +{
> + if (strcmp (sect_name, ".reg") == 0)
> + return &tilegx_linux_regset;
> +
> + return NULL;
> +}
> +
Any reason these Linux specific things aren't in the linux tdep file?
If no good reason, please move them.
> +static struct gdbarch *
> +tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> +{
> + struct gdbarch *gdbarch;
> + int arch_size = 64;
> +
> + /* Handle arch_size == 32 or 64. Default to 64. */
> + if (info.abfd)
> + arch_size = bfd_get_arch_size (info.abfd);
> +
> + if (arch_size != 32)
> + arch_size = 64;
> +
> + /* Try to find a pre-existing architecture. */
> + for (arches = gdbarch_list_lookup_by_info (arches, &info);
> + arches != NULL;
> + arches = gdbarch_list_lookup_by_info (arches->next, &info))
> + {
> + /* We only have two flavors -- just make sure arch_size matches. */
> + if (gdbarch_ptr_bit (arches->gdbarch) == arch_size)
> + return (arches->gdbarch);
> + }
> +
> + gdbarch = gdbarch_alloc (&info, NULL);
> +
> + /* Basic register fields and methods, datatype sizes and stuff. */
> +
> + /* There are 64 physical registers which can be referenced by
> + instructions (although only 56 of them can actually be
> + debugged) and 1 magic register (the PC). The other three
> + magic registers (ex1, syscall, orig_r0) which are known to
> + "ptrace" are ignored by "gdb". Note that we simply pretend
> + that there are 65 registers, and no "pseudo registers". */
> + set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
> + set_gdbarch_num_pseudo_regs (gdbarch, 0);
> +
> + set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
> + set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
> +
> + set_gdbarch_register_name (gdbarch, tilegx_register_name);
> + set_gdbarch_register_type (gdbarch, tilegx_register_type);
> +
> + set_gdbarch_char_signed (gdbarch, 0);
> + set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
> + set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
> + set_gdbarch_long_bit (gdbarch, arch_size);
> + set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
> +
> + set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
> + set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
> + set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
> +
> + set_gdbarch_ptr_bit (gdbarch, arch_size);
> + set_gdbarch_addr_bit (gdbarch, arch_size);
> +
> + set_gdbarch_cannot_fetch_register (gdbarch,
> + tilegx_cannot_reference_register);
> + set_gdbarch_cannot_store_register (gdbarch,
> + tilegx_cannot_reference_register);
> +
> + set_gdbarch_regset_from_core_section (gdbarch,
> + tilegx_regset_from_core_section);
> +
> + /* Stack grows down. */
> + set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
> +
> + /* Frame Info. */
> + set_gdbarch_unwind_sp (gdbarch, tilegx_unwind_sp);
> + set_gdbarch_unwind_pc (gdbarch, tilegx_unwind_pc);
> + set_gdbarch_dummy_id (gdbarch, tilegx_unwind_dummy_id);
> + set_gdbarch_frame_align (gdbarch, tilegx_frame_align);
> + frame_base_set_default (gdbarch, &tilegx_frame_base);
> +
> + set_gdbarch_skip_prologue (gdbarch, tilegx_skip_prologue);
> +
> + set_gdbarch_in_function_epilogue_p (gdbarch,
> + tilegx_in_function_epilogue_p);
> +
> + /* Map debug registers into internal register numbers. */
> + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, tilegx_dwarf2_reg_to_regnum);
> +
> + /* These values and methods are used when gdb calls a target function. */
> + set_gdbarch_push_dummy_call (gdbarch, tilegx_push_dummy_call);
> + set_gdbarch_breakpoint_from_pc (gdbarch, tilegx_breakpoint_from_pc);
> + set_gdbarch_return_value (gdbarch, tilegx_return_value);
> +
> + set_gdbarch_print_insn (gdbarch, print_insn_tilegx);
> +
> + /* GNU/Linux uses SVR4-style shared libraries. */
> + if (arch_size == 32)
> + set_solib_svr4_fetch_link_map_offsets (gdbarch,
> + svr4_ilp32_fetch_link_map_offsets);
> + else
> + set_solib_svr4_fetch_link_map_offsets (gdbarch,
> + svr4_lp64_fetch_link_map_offsets);
> +
> + /* Enable TLS support. */
> + set_gdbarch_fetch_tls_load_module_address (gdbarch,
> + svr4_fetch_objfile_link_map);
More GNU/Linux things.
> +
> + gdbarch_init_osabi (info, gdbarch);
> +
> + dwarf2_append_unwinders (gdbarch);
> + frame_unwind_append_unwinder (gdbarch, &tilegx_frame_unwind);
> +
> + return gdbarch;
> +}
> +
> +/* Provide a prototype to silence -Wmissing-prototypes. */
> +extern initialize_file_ftype _initialize_tilegx_tdep;
> +
> +void
> +_initialize_tilegx_tdep (void)
> +{
> + register_gdbarch_init (bfd_arch_tilegx, tilegx_gdbarch_init);
> +}
--
Pedro Alves