From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1719 invoked by alias); 23 May 2012 17:34:23 -0000 Received: (qmail 344 invoked by uid 22791); 23 May 2012 17:34:14 -0000 X-SWARE-Spam-Status: No, hits=-7.2 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,SPF_HELO_PASS,TW_CN,TW_CP,TW_EG,TW_XB,TW_XN,TW_YM,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 23 May 2012 17:33:53 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4NHXUSW012975 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 23 May 2012 13:33:30 -0400 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4NHXStp029112; Wed, 23 May 2012 13:33:28 -0400 Message-ID: <4FBD1F67.9090609@redhat.com> Date: Wed, 23 May 2012 17:34:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20120430 Thunderbird/12.0.1 MIME-Version: 1.0 To: Jeff Kenton CC: Joel Brobecker , gdb-patches@sourceware.org Subject: Re: [PATCH] Add support for Tilera TILE-Gx processor (part 1/3: gdb) References: <4FAD39A1.1000209@tilera.com> <20120514162046.GI10253@adacore.com> <4FBA4FD2.9090108@tilera.com> In-Reply-To: <4FBA4FD2.9090108@tilera.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00905.txt.bz2 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 . */ > + > +#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 > +#include 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 . */ > + > +#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< 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< + dest_regs[i] = operands[0]; > + break; > + case TILEGX_OPC_MOVE: > + new_reverse_frame[i] = reverse_frame[operands[1]]; > + reverse_frame_valid |= 1< + 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< + 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< + 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< + 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< + 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< + 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< + && 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