diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 15 | ||||
-rw-r--r-- | gdb/Makefile.in | 4 | ||||
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/arc-tdep.c | 1281 | ||||
-rw-r--r-- | gdb/arc-tdep.h | 101 | ||||
-rw-r--r-- | gdb/configure.tgt | 5 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 65 | ||||
-rw-r--r-- | gdb/features/Makefile | 2 | ||||
-rw-r--r-- | gdb/features/arc-arcompact.c | 75 | ||||
-rw-r--r-- | gdb/features/arc-arcompact.xml | 85 | ||||
-rw-r--r-- | gdb/features/arc-v2.c | 79 | ||||
-rw-r--r-- | gdb/features/arc-v2.xml | 92 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.xml/tdesc-regs.exp | 4 |
15 files changed, 1822 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4ee67fb..4a5b12c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2016-09-21 Anton Kolesov <anton.kolesov@synopsys.com> + + * Makefile.in (ALL_TARGET_OBS): Add arc-tdep.o. + (HFILES_NO_SRCDIR): Add arc-tdep.h. + (ALLDEPFILES): Add arc-tdep.c. + * NEWS: Mention new ARC port. + * configure.tgt: Add ARC. + * arc-tdep.c: New file. + * arc-tdep.h: New file. + * features/Makefile (XMLTOC): Add arc-v2.xml and arc-arcompact.xml. + * features/arc-v2.xml: New file. + * features/arc-v2.c: New file (generated). + * features/arc-arcompact.xml: New file. + * features/arc-arcompact.c: New file (generated). + 2016-09-21 Edjunior Barbosa Machado <emachado@linux.vnet.ibm.com> * rs6000-tdep.c (ppc_process_record_op63): Fix return of instruction diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 354705e..00de162 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -652,6 +652,7 @@ ALL_64_TARGET_OBS = \ # All other target-dependent objects files (used with --enable-targets=all). ALL_TARGET_OBS = \ + arc-tdep.o \ armbsd-tdep.o arm.o arm-linux.o arm-linux-tdep.o \ arm-get-next-pcs.o arm-symbian-tdep.o \ armnbsd-tdep.o armobsd-tdep.o \ @@ -906,7 +907,7 @@ LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c HFILES_NO_SRCDIR = \ common/gdb_signals.h nat/gdb_thread_db.h common/gdb_vecs.h \ common/x86-xstate.h nat/linux-ptrace.h nat/mips-linux-watch.h \ -proc-utils.h aarch64-tdep.h arm-tdep.h ax-gdb.h ppcfbsd-tdep.h \ +proc-utils.h aarch64-tdep.h arc-tdep.h arm-tdep.h ax-gdb.h ppcfbsd-tdep.h \ ppcnbsd-tdep.h cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \ exec.h m32r-tdep.h osabi.h gdbcore.h x86bsd-nat.h \ i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \ @@ -1664,6 +1665,7 @@ ALLDEPFILES = \ alpha-tdep.c alpha-mdebug-tdep.c \ alpha-linux-tdep.c \ alphabsd-tdep.c alphafbsd-tdep.c alphanbsd-tdep.c alphaobsd-tdep.c \ + arc-tdep.c \ amd64-nat.c amd64-tdep.c \ amd64bsd-nat.c amd64fbsd-nat.c amd64fbsd-tdep.c \ amd64nbsd-nat.c amd64nbsd-tdep.c \ @@ -15,6 +15,10 @@ running on MS-Windows use to assign names to threads in the debugger. +* New targets + +Synopsys ARC arc*-*-elf32 + *** Changes in GDB 7.12 * GDB and GDBserver now build with a C++ compiler by default. diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c new file mode 100644 index 0000000..6048ad6 --- /dev/null +++ b/gdb/arc-tdep.c @@ -0,0 +1,1281 @@ +/* Target dependent code for ARC arhitecture, for GDB. + + Copyright 2005-2016 Free Software Foundation, Inc. + Contributed by Synopsys 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/>. */ + +/* GDB header files. */ +#include "defs.h" +#include "arch-utils.h" +#include "disasm.h" +#include "dwarf2-frame.h" +#include "frame-base.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "gdbcmd.h" +#include "objfiles.h" +#include "trad-frame.h" + +/* ARC header files. */ +#include "opcode/arc.h" +#include "arc-tdep.h" + +/* Standard headers. */ +#include <algorithm> + +/* Default target descriptions. */ +#include "features/arc-v2.c" +#include "features/arc-arcompact.c" + +/* The frame unwind cache for the ARC. Current structure is a stub, because + it should be filled in during the prologue analysis. */ + +struct arc_frame_cache +{ + /* The stack pointer at the time this frame was created; i.e. the caller's + stack pointer when this function was called. It is used to identify this + frame. */ + CORE_ADDR prev_sp; + + /* Store addresses for registers saved in prologue. */ + struct trad_frame_saved_reg *saved_regs; +}; + +/* Global debug flag. */ + +int arc_debug; + +/* XML target description features. */ + +static const char core_v2_feature_name[] = "org.gnu.gdb.arc.core.v2"; +static const char + core_reduced_v2_feature_name[] = "org.gnu.gdb.arc.core-reduced.v2"; +static const char + core_arcompact_feature_name[] = "org.gnu.gdb.arc.core.arcompact"; +static const char aux_minimal_feature_name[] = "org.gnu.gdb.arc.aux-minimal"; + +/* XML target description known registers. */ + +static const char *const core_v2_register_names[] = { + "r0", "r1", "r2", "r3", + "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", + "r24", "r25", "gp", "fp", + "sp", "ilink", "r30", "blink", + "r32", "r33", "r34", "r35", + "r36", "r37", "r38", "r39", + "r40", "r41", "r42", "r43", + "r44", "r45", "r46", "r47", + "r48", "r49", "r50", "r51", + "r52", "r53", "r54", "r55", + "r56", "r57", "accl", "acch", + "lp_count", "pcl", +}; + +static const char *const aux_minimal_register_names[] = { + "pc", "status32", +}; + +static const char *const core_arcompact_register_names[] = { + "r0", "r1", "r2", "r3", + "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", + "r24", "r25", "gp", "fp", + "sp", "ilink1", "ilink2", "blink", + "r32", "r33", "r34", "r35", + "r36", "r37", "r38", "r39", + "r40", "r41", "r42", "r43", + "r44", "r45", "r46", "r47", + "r48", "r49", "r50", "r51", + "r52", "r53", "r54", "r55", + "r56", "r57", "r58", "r59", + "lp_count", "pcl", +}; + +/* Implement the "write_pc" gdbarch method. + + In ARC PC register is a normal register so in most cases setting PC value + is a straightforward process: debugger just writes PC value. However it + gets trickier in case when current instruction is an instruction in delay + slot. In this case CPU will execute instruction at current PC value, then + will set PC to the current value of BTA register; also current instruction + cannot be branch/jump and some of the other instruction types. Thus if + debugger would try to just change PC value in this case, this instruction + will get executed, but then core will "jump" to the original branch target. + + Whether current instruction is a delay-slot instruction or not is indicated + by DE bit in STATUS32 register indicates if current instruction is a delay + slot instruction. This bit is writable by debug host, which allows debug + host to prevent core from jumping after the delay slot instruction. It + also works in another direction: setting this bit will make core to treat + any current instructions as a delay slot instruction and to set PC to the + current value of BTA register. + + To workaround issues with changing PC register while in delay slot + instruction, debugger should check for the STATUS32.DE bit and reset it if + it is set. No other change is required in this function. Most common + case, where this function might be required is calling inferior functions + from debugger. Generic GDB logic handles this pretty well: current values + of registers are stored, value of PC is changed (that is the job of this + function), and after inferior function is executed, GDB restores all + registers, include BTA and STATUS32, which also means that core is returned + to its original state of being halted on delay slot instructions. + + This method is useless for ARC 600, because it doesn't have externally + exposed BTA register. In the case of ARC 600 it is impossible to restore + core to its state in all occasions thus core should never be halted (from + the perspective of debugger host) in the delay slot. */ + +static void +arc_write_pc (struct regcache *regcache, CORE_ADDR new_pc) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + if (arc_debug) + debug_printf ("arc: Writing PC, new value=%s\n", + paddress (gdbarch, new_pc)); + + regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch), + new_pc); + + ULONGEST status32; + regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch), + &status32); + + /* Mask for DE bit is 0x40. */ + if (status32 & 0x40) + { + if (arc_debug) + { + debug_printf ("arc: Changing PC while in delay slot. Will " + "reset STATUS32.DE bit to zero. Value of STATUS32 " + "register is 0x%s\n", + phex (status32, ARC_REGISTER_SIZE)); + } + + /* Reset bit and write to the cache. */ + status32 &= ~0x40; + regcache_cooked_write_unsigned (regcache, gdbarch_ps_regnum (gdbarch), + status32); + } +} + +/* Implement the "virtual_frame_pointer" gdbarch method. + + According to ABI the FP (r27) is used to point to the middle of the current + stack frame, just below the saved FP and before local variables, register + spill area and outgoing args. However for optimization levels above O2 and + in any case in leaf functions, the frame pointer is usually not set at all. + The exception being when handling nested functions. + + We use this function to return a "virtual" frame pointer, marking the start + of the current stack frame as a register-offset pair. If the FP is not + being used, then it should return SP, with an offset of the frame size. + + The current implementation doesn't actually know the frame size, nor + whether the FP is actually being used, so for now we just return SP and an + offset of zero. This is no worse than other architectures, but is needed + to avoid assertion failures. + + TODO: Can we determine the frame size to get a correct offset? + + PC is a program counter where we need the virtual FP. REG_PTR is the base + register used for the virtual FP. OFFSET_PTR is the offset used for the + virtual FP. */ + +static void +arc_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc, + int *reg_ptr, LONGEST *offset_ptr) +{ + *reg_ptr = gdbarch_sp_regnum (gdbarch); + *offset_ptr = 0; +} + +/* Implement the "dummy_id" gdbarch method. + + Tear down a dummy frame created by arc_push_dummy_call (). This data has + to be constructed manually from the data in our hand. The stack pointer + and program counter can be obtained from the frame info. */ + +static struct frame_id +arc_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) +{ + return frame_id_build (get_frame_sp (this_frame), + get_frame_pc (this_frame)); +} + +/* Implement the "push_dummy_call" gdbarch method. + + Stack Frame Layout + + This shows the layout of the stack frame for the general case of a + function call; a given function might not have a variable number of + arguments or local variables, or might not save any registers, so it would + not have the corresponding frame areas. Additionally, a leaf function + (i.e. one which calls no other functions) does not need to save the + contents of the BLINK register (which holds its return address), and a + function might not have a frame pointer. + + The stack grows downward, so SP points below FP in memory; SP always + points to the last used word on the stack, not the first one. + + | | | + | arg word N | | caller's + | : | | frame + | arg word 10 | | + | arg word 9 | | + old SP ---> +-----------------------+ --+ + | | | + | callee-saved | | + | registers | | + | including fp, blink | | + | | | callee's + new FP ---> +-----------------------+ | frame + | | | + | local | | + | variables | | + | | | + | register | | + | spill area | | + | | | + | outgoing args | | + | | | + new SP ---> +-----------------------+ --+ + | | + | unused | + | | + | + | + V + downwards + + The list of arguments to be passed to a function is considered to be a + sequence of _N_ words (as though all the parameters were stored in order in + memory with each parameter occupying an integral number of words). Words + 1..8 are passed in registers 0..7; if the function has more than 8 words of + arguments then words 9..@em N are passed on the stack in the caller's frame. + + If the function has a variable number of arguments, e.g. it has a form such + as `function (p1, p2, ...);' and _P_ words are required to hold the values + of the named parameters (which are passed in registers 0..@em P -1), then + the remaining 8 - _P_ words passed in registers _P_..7 are spilled into the + top of the frame so that the anonymous parameter words occupy a continuous + region. + + Any arguments are already in target byte order. We just need to store + them! + + BP_ADDR is the return address where breakpoint must be placed. NARGS is + the number of arguments to the function. ARGS is the arguments values (in + target byte order). SP is the Current value of SP register. STRUCT_RETURN + is TRUE if structures are returned by the function. STRUCT_ADDR is the + hidden address for returning a struct. Returns SP of a new frame. */ + +static CORE_ADDR +arc_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) +{ + if (arc_debug) + debug_printf ("arc: push_dummy_call (nargs = %d)\n", nargs); + + int arg_reg = ARC_FIRST_ARG_REGNUM; + + /* Push the return address. */ + regcache_cooked_write_unsigned (regcache, ARC_BLINK_REGNUM, bp_addr); + + /* Are we returning a value using a structure return instead of a normal + value return? If so, struct_addr is the address of the reserved space for + the return structure to be written on the stack, and that address is + passed to that function as a hidden first argument. */ + if (struct_return) + { + /* Pass the return address in the first argument register. */ + regcache_cooked_write_unsigned (regcache, arg_reg, struct_addr); + + if (arc_debug) + debug_printf ("arc: struct return address %s passed in R%d", + print_core_address (gdbarch, struct_addr), arg_reg); + + arg_reg++; + } + + if (nargs > 0) + { + unsigned int total_space = 0; + + /* How much space do the arguments occupy in total? Must round each + argument's size up to an integral number of words. */ + for (int i = 0; i < nargs; i++) + { + unsigned int len = TYPE_LENGTH (value_type (args[i])); + unsigned int space = align_up (len, 4); + + total_space += space; + + if (arc_debug) + debug_printf ("arc: arg %d: %u bytes -> %u\n", i, len, space); + } + + /* Allocate a buffer to hold a memory image of the arguments. */ + gdb_byte *memory_image = XCNEWVEC (gdb_byte, total_space); + + /* Now copy all of the arguments into the buffer, correctly aligned. */ + gdb_byte *data = memory_image; + for (int i = 0; i < nargs; i++) + { + unsigned int len = TYPE_LENGTH (value_type (args[i])); + unsigned int space = align_up (len, 4); + + memcpy (data, value_contents (args[i]), (size_t) len); + if (arc_debug) + debug_printf ("arc: copying arg %d, val 0x%08x, len %d to mem\n", + i, *((int *) value_contents (args[i])), len); + + data += space; + } + + /* Now load as much as possible of the memory image into registers. */ + data = memory_image; + while (arg_reg <= ARC_LAST_ARG_REGNUM) + { + if (arc_debug) + debug_printf ("arc: passing 0x%02x%02x%02x%02x in register R%d\n", + data[0], data[1], data[2], data[3], arg_reg); + + /* Note we don't use write_unsigned here, since that would convert + the byte order, but we are already in the correct byte order. */ + regcache_cooked_write (regcache, arg_reg, data); + + data += ARC_REGISTER_SIZE; + total_space -= ARC_REGISTER_SIZE; + + /* All the data is now in registers. */ + if (total_space == 0) + break; + + arg_reg++; + } + + /* If there is any data left, push it onto the stack (in a single write + operation). */ + if (total_space > 0) + { + if (arc_debug) + debug_printf ("arc: passing %d bytes on stack\n", total_space); + + sp -= total_space; + write_memory (sp, data, (int) total_space); + } + + xfree (memory_image); + } + + /* Finally, update the SP register. */ + regcache_cooked_write_unsigned (regcache, gdbarch_sp_regnum (gdbarch), sp); + + return sp; +} + +/* Implement the "push_dummy_code" gdbarch method. + + We don't actually push any code. We just identify where a breakpoint can + be inserted to which we are can return and the resume address where we + should be called. + + ARC does not necessarily have an executable stack, so we can't put the + return breakpoint there. Instead we put it at the entry point of the + function. This means the SP is unchanged. + + SP is a current stack pointer FUNADDR is an address of the function to be + called. ARGS is arguments to pass. NARGS is a number of args to pass. + VALUE_TYPE is a type of value returned. REAL_PC is a resume address when + the function is called. BP_ADDR is an address where breakpoint should be + set. Returns the updated stack pointer. */ + +static CORE_ADDR +arc_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr, + struct value **args, int nargs, struct type *value_type, + CORE_ADDR *real_pc, CORE_ADDR *bp_addr, + struct regcache *regcache) +{ + *real_pc = funaddr; + *bp_addr = entry_point_address (); + return sp; +} + +/* Implement the "cannot_fetch_register" gdbarch method. */ + +static int +arc_cannot_fetch_register (struct gdbarch *gdbarch, int regnum) +{ + /* Assume that register is readable if it is unknown. */ + return FALSE; +} + +/* Implement the "cannot_store_register" gdbarch method. */ + +static int +arc_cannot_store_register (struct gdbarch *gdbarch, int regnum) +{ + /* Assume that register is writable if it is unknown. */ + switch (regnum) + { + case ARC_PCL_REGNUM: + return TRUE; + default: + return FALSE; + } +} + +/* Get the return value of a function from the registers/memory used to + return it, according to the convention used by the ABI - 4-bytes values are + in the R0, while 8-byte values are in the R0-R1. + + TODO: This implementation ignores the case of "complex double", where + according to ABI, value is returned in the R0-R3 registers. + + TYPE is a returned value's type. VALBUF is a buffer for the returned + value. */ + +static void +arc_extract_return_value (struct gdbarch *gdbarch, struct type *type, + struct regcache *regcache, gdb_byte *valbuf) +{ + unsigned int len = TYPE_LENGTH (type); + + if (arc_debug) + debug_printf ("arc: extract_return_value\n"); + + if (len <= ARC_REGISTER_SIZE) + { + ULONGEST val; + + /* Get the return value from one register. */ + regcache_cooked_read_unsigned (regcache, ARC_R0_REGNUM, &val); + store_unsigned_integer (valbuf, (int) len, + gdbarch_byte_order (gdbarch), val); + + if (arc_debug) + debug_printf ("arc: returning 0x%s\n", phex (val, ARC_REGISTER_SIZE)); + } + else if (len <= ARC_REGISTER_SIZE * 2) + { + ULONGEST low, high; + + /* Get the return value from two registers. */ + regcache_cooked_read_unsigned (regcache, ARC_R0_REGNUM, &low); + regcache_cooked_read_unsigned (regcache, ARC_R1_REGNUM, &high); + + store_unsigned_integer (valbuf, ARC_REGISTER_SIZE, + gdbarch_byte_order (gdbarch), low); + store_unsigned_integer (valbuf + ARC_REGISTER_SIZE, + (int) len - ARC_REGISTER_SIZE, + gdbarch_byte_order (gdbarch), high); + + if (arc_debug) + debug_printf ("arc: returning 0x%s%s\n", + phex (high, ARC_REGISTER_SIZE), + phex (low, ARC_REGISTER_SIZE)); + } + else + error (_("arc: extract_return_value: type length %u too large"), len); +} + + +/* Store the return value of a function into the registers/memory used to + return it, according to the convention used by the ABI. + + TODO: This implementation ignores the case of "complex double", where + according to ABI, value is returned in the R0-R3 registers. + + TYPE is a returned value's type. VALBUF is a buffer with the value to + return. */ + +static void +arc_store_return_value (struct gdbarch *gdbarch, struct type *type, + struct regcache *regcache, const gdb_byte *valbuf) +{ + unsigned int len = TYPE_LENGTH (type); + + if (arc_debug) + debug_printf ("arc: store_return_value\n"); + + if (len <= ARC_REGISTER_SIZE) + { + ULONGEST val; + + /* Put the return value into one register. */ + val = extract_unsigned_integer (valbuf, (int) len, + gdbarch_byte_order (gdbarch)); + regcache_cooked_write_unsigned (regcache, ARC_R0_REGNUM, val); + + if (arc_debug) + debug_printf ("arc: storing 0x%s\n", phex (val, ARC_REGISTER_SIZE)); + } + else if (len <= ARC_REGISTER_SIZE * 2) + { + ULONGEST low, high; + + /* Put the return value into two registers. */ + low = extract_unsigned_integer (valbuf, ARC_REGISTER_SIZE, + gdbarch_byte_order (gdbarch)); + high = extract_unsigned_integer (valbuf + ARC_REGISTER_SIZE, + (int) len - ARC_REGISTER_SIZE, + gdbarch_byte_order (gdbarch)); + + regcache_cooked_write_unsigned (regcache, ARC_R0_REGNUM, low); + regcache_cooked_write_unsigned (regcache, ARC_R1_REGNUM, high); + + if (arc_debug) + debug_printf ("arc: storing 0x%s%s\n", + phex (high, ARC_REGISTER_SIZE), + phex (low, ARC_REGISTER_SIZE)); + } + else + error (_("arc_store_return_value: type length too large.")); +} + +/* Implement the "return_value" gdbarch method. */ + +static enum return_value_convention +arc_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + /* If the return type is a struct, or a union, or would occupy more than two + registers, the ABI uses the "struct return convention": the calling + function passes a hidden first parameter to the callee (in R0). That + parameter is the address at which the value being returned should be + stored. Otherwise, the result is returned in registers. */ + int is_struct_return = (TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || TYPE_LENGTH (valtype) > 2 * ARC_REGISTER_SIZE); + + if (arc_debug) + debug_printf ("arc: return_value (readbuf = %p, writebuf = %p)\n", + readbuf, writebuf); + + if (writebuf != NULL) + { + /* Case 1. GDB should not ask us to set a struct return value: it + should know the struct return location and write the value there + itself. */ + gdb_assert (!is_struct_return); + arc_store_return_value (gdbarch, valtype, regcache, writebuf); + } + else if (readbuf != NULL) + { + /* Case 2. GDB should not ask us to get a struct return value: it + should know the struct return location and read the value from there + itself. */ + gdb_assert (!is_struct_return); + arc_extract_return_value (gdbarch, valtype, regcache, readbuf); + } + + return (is_struct_return + ? RETURN_VALUE_STRUCT_CONVENTION + : RETURN_VALUE_REGISTER_CONVENTION); +} + +/* Return the base address of the frame. For ARC, the base address is the + frame pointer. */ + +static CORE_ADDR +arc_frame_base_address (struct frame_info *this_frame, void **prologue_cache) +{ + return (CORE_ADDR) get_frame_register_unsigned (this_frame, ARC_FP_REGNUM); +} + +/* Implement the "skip_prologue" gdbarch method. + + Skip the prologue for the function at PC. This is done by checking from + the line information read from the DWARF, if possible; otherwise, we scan + the function prologue to find its end. */ + +static CORE_ADDR +arc_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + if (arc_debug) + debug_printf ("arc: skip_prologue\n"); + + CORE_ADDR func_addr; + const char *func_name; + + /* See what the symbol table says. */ + if (find_pc_partial_function (pc, &func_name, &func_addr, NULL)) + { + /* Found a function. */ + CORE_ADDR postprologue_pc + = skip_prologue_using_sal (gdbarch, func_addr); + + if (postprologue_pc != 0) + return std::max (pc, postprologue_pc); + } + + /* No prologue info in symbol table, have to analyze prologue. */ + + /* Find an upper limit on the function prologue using the debug + information. If the debug information could not be used to provide that + bound, then pass 0 and arc_scan_prologue will estimate value itself. */ + CORE_ADDR limit_pc = skip_prologue_using_sal (gdbarch, pc); + /* We don't have a proper analyze_prologue function yet, but its result + should be returned here. Currently GDB will just stop at the first + instruction of function if debug information doesn't have prologue info; + and if there is a debug info about prologue - this code path will not be + taken at all. */ + return (limit_pc == 0 ? pc : limit_pc); +} + +/* Implement the "print_insn" gdbarch method. + + arc_get_disassembler () may return different functions depending on bfd + type, so it is not possible to pass print_insn directly to + set_gdbarch_print_insn (). Instead this wrapper function is used. It also + may be used by other functions to get disassemble_info for address. It is + important to note, that those print_insn from opcodes always print + instruction to the stream specified in the INFO. If this is not desired, + then either `print_insn` function in INFO should be set to some function + that will not print, or `stream` should be different from standard + gdb_stdlog. */ + +static int +arc_delayed_print_insn (bfd_vma addr, struct disassemble_info *info) +{ + int (*print_insn) (bfd_vma, struct disassemble_info *); + /* exec_bfd may be null, if GDB is run without a target BFD file. Opcodes + will handle NULL value gracefully. */ + print_insn = arc_get_disassembler (exec_bfd); + gdb_assert (print_insn != NULL); + return print_insn (addr, info); +} + +/* Baremetal breakpoint instructions. + + ARC supports both big- and little-endian. However, instructions for + little-endian processors are encoded in the middle-endian: half-words are + in big-endian, while bytes inside the half-words are in little-endian; data + is represented in the "normal" little-endian. Big-endian processors treat + data and code identically. + + Assuming the number 0x01020304, it will be presented this way: + + Address : N N+1 N+2 N+3 + little-endian : 0x04 0x03 0x02 0x01 + big-endian : 0x01 0x02 0x03 0x04 + ARC middle-endian : 0x02 0x01 0x04 0x03 + */ + +static const gdb_byte arc_brk_s_be[] = { 0x7f, 0xff }; +static const gdb_byte arc_brk_s_le[] = { 0xff, 0x7f }; +static const gdb_byte arc_brk_be[] = { 0x25, 0x6f, 0x00, 0x3f }; +static const gdb_byte arc_brk_le[] = { 0x6f, 0x25, 0x3f, 0x00 }; + +/* Implement the "breakpoint_from_pc" gdbarch method. + + For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff + (little endian) or 0xff7f (big endian). We used to insert BRK_S even + instead of 32-bit instructions, which works mostly ok, unless breakpoint is + inserted into delay slot instruction. In this case if branch is taken + BLINK value will be set to address of instruction after delay slot, however + if we replaced 32-bit instruction in delay slot with 16-bit long BRK_S, + then BLINK value will have an invalid value - it will point to the address + after the BRK_S (which was there at the moment of branch execution) while + it should point to the address after the 32-bit long instruction. To avoid + such issues this function disassembles instruction at target location and + evaluates it value. + + ARC 600 supports only 16-bit BRK_S. + + NB: Baremetal GDB uses BRK[_S], while user-space GDB uses TRAP_S. BRK[_S] + is much better because it doesn't commit unlike TRAP_S, so it can be set in + delay slots; however it cannot be used in user-mode, hence usage of TRAP_S + in GDB for user-space. + + PCPTR is a pointer to the PC where we want to place a breakpoint. LENPTR + is a number of bytes used by the breakpoint. Returns the byte sequence of + a breakpoint instruction. */ + +static const gdb_byte * +arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, + int *lenptr) +{ + size_t length_with_limm = gdb_insn_length (gdbarch, *pcptr); + + /* Replace 16-bit instruction with BRK_S, replace 32-bit instructions with + BRK. LIMM is part of instruction length, so it can be either 4 or 8 + bytes for 32-bit instructions. */ + if ((length_with_limm == 4 || length_with_limm == 8) + && !arc_mach_is_arc600 (gdbarch)) + { + *lenptr = sizeof (arc_brk_le); + return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + ? arc_brk_be + : arc_brk_le); + } + else + { + *lenptr = sizeof (arc_brk_s_le); + return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + ? arc_brk_s_be + : arc_brk_s_le); + } +} + +/* Implement the "unwind_pc" gdbarch method. */ + +static CORE_ADDR +arc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + int pc_regnum = gdbarch_pc_regnum (gdbarch); + CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum); + + if (arc_debug) + debug_printf ("arc: unwind PC: %s\n", paddress (gdbarch, pc)); + + return pc; +} + +/* Implement the "unwind_sp" gdbarch method. */ + +static CORE_ADDR +arc_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + int sp_regnum = gdbarch_sp_regnum (gdbarch); + CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, sp_regnum); + + if (arc_debug) + debug_printf ("arc: unwind SP: %s\n", paddress (gdbarch, sp)); + + return sp; +} + +/* Implement the "frame_align" gdbarch method. */ + +static CORE_ADDR +arc_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) +{ + return align_down (sp, 4); +} + +/* Frame unwinder for normal frames. */ + +static struct arc_frame_cache * +arc_make_frame_cache (struct frame_info *this_frame) +{ + if (arc_debug) + debug_printf ("arc: frame_cache\n"); + + struct gdbarch *gdbarch = get_frame_arch (this_frame); + + CORE_ADDR block_addr = get_frame_address_in_block (this_frame); + CORE_ADDR prev_pc = get_frame_pc (this_frame); + + CORE_ADDR entrypoint, prologue_end; + if (find_pc_partial_function (block_addr, NULL, &entrypoint, &prologue_end)) + { + struct symtab_and_line sal = find_pc_line (entrypoint, 0); + if (sal.line == 0) + /* No line info so use current PC. */ + prologue_end = prev_pc; + else if (sal.end < prologue_end) + /* The next line begins after the function end. */ + prologue_end = sal.end; + + prologue_end = std::min (prologue_end, prev_pc); + } + else + { + entrypoint = get_frame_register_unsigned (this_frame, + gdbarch_pc_regnum (gdbarch)); + prologue_end = 0; + } + + /* Allocate new frame cache instance and space for saved register info. + * FRAME_OBSTACK_ZALLOC will initialize fields to zeroes. */ + struct arc_frame_cache *cache + = FRAME_OBSTACK_ZALLOC (struct arc_frame_cache); + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + /* Should call analyze_prologue here, when it will be implemented. */ + + return cache; +} + +/* Implement the "this_id" frame_unwind method. */ + +static void +arc_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id) +{ + if (arc_debug) + debug_printf ("arc: frame_this_id\n"); + + struct gdbarch *gdbarch = get_frame_arch (this_frame); + + if (*this_cache == NULL) + *this_cache = arc_make_frame_cache (this_frame); + struct arc_frame_cache *cache = (struct arc_frame_cache *) (*this_cache); + + CORE_ADDR stack_addr = cache->prev_sp; + + /* There are 4 possible situation which decide how frame_id->code_addr is + evaluated: + + 1) Function is compiled with option -g. Then frame_id will be created + in dwarf_* function and not in this function. NB: even if target + binary is compiled with -g, some std functions like __start and _init + are not, so they still will follow one of the following choices. + + 2) Function is compiled without -g and binary hasn't been stripped in + any way. In this case GDB still has enough information to evaluate + frame code_addr properly. This case is covered by call to + get_frame_func (). + + 3) Binary has been striped with option -g (strip debug symbols). In + this case there is still enough symbols for get_frame_func () to work + properly, so this case is also covered by it. + + 4) Binary has been striped with option -s (strip all symbols). In this + case GDB cannot get function start address properly, so we return current + PC value instead. + */ + CORE_ADDR code_addr = get_frame_func (this_frame); + if (code_addr == 0) + code_addr = get_frame_register_unsigned (this_frame, + gdbarch_pc_regnum (gdbarch)); + + *this_id = frame_id_build (stack_addr, code_addr); +} + +/* Implement the "prev_register" frame_unwind method. */ + +static struct value * +arc_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + if (arc_debug) + debug_printf ("arc: frame_prev_register (regnum = %d)\n", regnum); + + if (*this_cache == NULL) + *this_cache = arc_make_frame_cache (this_frame); + struct arc_frame_cache *cache = (struct arc_frame_cache *) (*this_cache); + + struct gdbarch *gdbarch = get_frame_arch (this_frame); + + /* If we are asked to unwind the PC, then we need to return BLINK instead: + the saved value of PC points into this frame's function's prologue, not + the next frame's function's resume location. */ + if (regnum == gdbarch_pc_regnum (gdbarch)) + regnum = ARC_BLINK_REGNUM; + + /* SP is a special case - we should return prev_sp, because + trad_frame_get_prev_register will return _current_ SP value. + Alternatively we could have stored cache->prev_sp in the cache->saved + regs, but here we follow the lead of AArch64, ARM and Xtensa and will + leave that logic in this function, instead of prologue analyzers. That I + think is a bit more clear as `saved_regs` should contain saved regs, not + computable. + + Because value has been computed, "got_constant" should be used, so that + returned value will be a "not_lval" - immutable. */ + + if (regnum == gdbarch_sp_regnum (gdbarch)) + return frame_unwind_got_constant (this_frame, regnum, cache->prev_sp); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +/* Implement the "init_reg" dwarf2_frame method. */ + +static void +arc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, + struct dwarf2_frame_state_reg *reg, + struct frame_info *info) +{ + if (regnum == gdbarch_pc_regnum (gdbarch)) + /* The return address column. */ + reg->how = DWARF2_FRAME_REG_RA; + else if (regnum == gdbarch_sp_regnum (gdbarch)) + /* The call frame address. */ + reg->how = DWARF2_FRAME_REG_CFA; +} + +/* Structure defining the ARC ordinary frame unwind functions. Since we are + the fallback unwinder, we use the default frame sniffer, which always + accepts the frame. */ + +static const struct frame_unwind arc_frame_unwind = { + NORMAL_FRAME, + default_frame_unwind_stop_reason, + arc_frame_this_id, + arc_frame_prev_register, + NULL, + default_frame_sniffer, + NULL, + NULL +}; + + +static const struct frame_base arc_normal_base = { + &arc_frame_unwind, + arc_frame_base_address, + arc_frame_base_address, + arc_frame_base_address +}; + +/* Initialize target description for the ARC. + + Returns TRUE if input tdesc was valid and in this case it will assign TDESC + and TDESC_DATA output parameters. */ + +static int +arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc, + struct tdesc_arch_data **tdesc_data) +{ + if (arc_debug) + debug_printf ("arc: Target description initialization.\n"); + + const struct target_desc *tdesc_loc = info.target_desc; + + /* Depending on whether this is ARCompact or ARCv2 we will assign + different default registers sets (which will differ in exactly two core + registers). GDB will also refuse to accept register feature from invalid + ISA - v2 features can be used only with v2 ARChitecture. We read + bfd_arch_info, which looks like to be a safe bet here, as it looks like it + is always initialized even when we don't pass any elf file to GDB at all + (it uses default arch in this case). Also GDB will call this function + multiple times, and if XML target description file contains architecture + specifications, then GDB will set this architecture to info.bfd_arch_info, + overriding value from ELF file if they are different. That means that, + where matters, this value is always our best guess on what CPU we are + debugging. It has been noted that architecture specified in tdesc file + has higher precedence over ELF and even "set architecture" - that is, + using "set architecture" command will have no effect when tdesc has "arch" + tag. */ + /* Cannot use arc_mach_is_arcv2 (), because gdbarch is not created yet. */ + const int is_arcv2 = (info.bfd_arch_info->mach == bfd_mach_arc_arcv2); + int is_reduced_rf; + const char *const *core_regs; + const char *core_feature_name; + + /* If target doesn't provide a description - use default one. */ + if (!tdesc_has_registers (tdesc_loc)) + { + if (is_arcv2) + { + tdesc_loc = tdesc_arc_v2; + if (arc_debug) + debug_printf ("arc: Using default register set for ARC v2.\n"); + } + else + { + tdesc_loc = tdesc_arc_arcompact; + if (arc_debug) + debug_printf ("arc: Using default register set for ARCompact.\n"); + } + } + else + { + if (arc_debug) + debug_printf ("arc: Using provided register set.\n"); + } + gdb_assert (tdesc_loc != NULL); + + /* Now we can search for base registers. Core registers can be either full + or reduced. Summary: + + - core.v2 + aux-minimal + - core-reduced.v2 + aux-minimal + - core.arcompact + aux-minimal + + NB: It is entirely feasible to have ARCompact with reduced core regs, but + we ignore that because GCC doesn't support that and at the same time + ARCompact is considered obsolete, so there is not much reason to support + that. */ + const struct tdesc_feature *feature + = tdesc_find_feature (tdesc_loc, core_v2_feature_name); + if (feature != NULL) + { + /* Confirm that register and architecture match, to prevent accidents in + some situations. This code will trigger an error if: + + 1. XML tdesc doesn't specify arch explicitly, registers are for arch + X, but ELF specifies arch Y. + + 2. XML tdesc specifies arch X, but contains registers for arch Y. + + It will not protect from case where XML or ELF specify arch X, + registers are for the same arch X, but the real target is arch Y. To + detect this case we need to check IDENTITY register. */ + if (!is_arcv2) + { + arc_print (_("Error: ARC v2 target description supplied for " + "non-ARCv2 target.\n")); + return FALSE; + } + + is_reduced_rf = FALSE; + core_feature_name = core_v2_feature_name; + core_regs = core_v2_register_names; + } + else + { + feature = tdesc_find_feature (tdesc_loc, core_reduced_v2_feature_name); + if (feature != NULL) + { + if (!is_arcv2) + { + arc_print (_("Error: ARC v2 target description supplied for " + "non-ARCv2 target.\n")); + return FALSE; + } + + is_reduced_rf = TRUE; + core_feature_name = core_reduced_v2_feature_name; + core_regs = core_v2_register_names; + } + else + { + feature = tdesc_find_feature (tdesc_loc, + core_arcompact_feature_name); + if (feature != NULL) + { + if (is_arcv2) + { + arc_print (_("Error: ARCompact target description supplied " + "for non-ARCompact target.\n")); + return FALSE; + } + + is_reduced_rf = FALSE; + core_feature_name = core_arcompact_feature_name; + core_regs = core_arcompact_register_names; + } + else + { + arc_print (_("Error: Couldn't find core register feature in " + "supplied target description.")); + return FALSE; + } + } + } + + struct tdesc_arch_data *tdesc_data_loc = tdesc_data_alloc (); + + gdb_assert (feature != NULL); + int valid_p = 1; + + for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++) + { + /* If rf16, then skip extra registers. */ + if (is_reduced_rf && ((i >= ARC_R4_REGNUM && i <= ARC_R9_REGNUM) + || (i >= ARC_R16_REGNUM && i <= ARC_R25_REGNUM))) + continue; + + valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, + core_regs[i]); + + /* - Ignore errors in extension registers - they are optional. + - Ignore missing ILINK because it doesn't make sense for Linux. + - Ignore missing ILINK2 when architecture is ARCompact, because it + doesn't make sense for Linux targets. + + In theory those optional registers should be in separate features, but + that would create numerous but tiny features, which looks like an + overengineering of a rather simple task. */ + if (!valid_p && (i <= ARC_SP_REGNUM || i == ARC_BLINK_REGNUM + || i == ARC_LP_COUNT_REGNUM || i == ARC_PCL_REGNUM + || (i == ARC_R30_REGNUM && is_arcv2))) + { + arc_print (_("Error: Cannot find required register `%s' in " + "feature `%s'.\n"), core_regs[i], core_feature_name); + tdesc_data_cleanup (tdesc_data_loc); + return FALSE; + } + } + + /* Mandatory AUX registeres are intentionally few and are common between + ARCompact and ARC v2, so same code can be used for both. */ + feature = tdesc_find_feature (tdesc_loc, aux_minimal_feature_name); + if (feature == NULL) + { + arc_print (_("Error: Cannot find required feature `%s' in supplied " + "target description.\n"), aux_minimal_feature_name); + tdesc_data_cleanup (tdesc_data_loc); + return FALSE; + } + + for (int i = ARC_FIRST_AUX_REGNUM; i <= ARC_LAST_AUX_REGNUM; i++) + { + const char *name = aux_minimal_register_names[i - ARC_FIRST_AUX_REGNUM]; + valid_p = tdesc_numbered_register (feature, tdesc_data_loc, i, name); + if (!valid_p) + { + arc_print (_("Error: Cannot find required register `%s' " + "in feature `%s'.\n"), + name, tdesc_feature_name (feature)); + tdesc_data_cleanup (tdesc_data_loc); + return FALSE; + } + } + + *tdesc = tdesc_loc; + *tdesc_data = tdesc_data_loc; + + return TRUE; +} + +/* Implement the "init" gdbarch method. */ + +static struct gdbarch * +arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) +{ + const struct target_desc *tdesc; + struct tdesc_arch_data *tdesc_data; + + if (arc_debug) + debug_printf ("arc: Architecture initialization.\n"); + + if (!arc_tdesc_init (info, &tdesc, &tdesc_data)) + return NULL; + + struct gdbarch *gdbarch = gdbarch_alloc (&info, NULL); + + /* Data types. */ + set_gdbarch_short_bit (gdbarch, 16); + set_gdbarch_int_bit (gdbarch, 32); + set_gdbarch_long_bit (gdbarch, 32); + set_gdbarch_long_long_bit (gdbarch, 64); + set_gdbarch_long_long_align_bit (gdbarch, 32); + set_gdbarch_float_bit (gdbarch, 32); + set_gdbarch_float_format (gdbarch, floatformats_ieee_single); + set_gdbarch_double_bit (gdbarch, 64); + set_gdbarch_double_format (gdbarch, floatformats_ieee_double); + set_gdbarch_ptr_bit (gdbarch, 32); + set_gdbarch_addr_bit (gdbarch, 32); + set_gdbarch_char_signed (gdbarch, 0); + + set_gdbarch_write_pc (gdbarch, arc_write_pc); + + set_gdbarch_virtual_frame_pointer (gdbarch, arc_virtual_frame_pointer); + + /* tdesc_use_registers expects gdbarch_num_regs to return number of registers + parsed by gdbarch_init, and then it will add all of the remaining + registers and will increase number of registers. */ + set_gdbarch_num_regs (gdbarch, ARC_LAST_REGNUM + 1); + set_gdbarch_num_pseudo_regs (gdbarch, 0); + set_gdbarch_sp_regnum (gdbarch, ARC_SP_REGNUM); + set_gdbarch_pc_regnum (gdbarch, ARC_PC_REGNUM); + set_gdbarch_ps_regnum (gdbarch, ARC_STATUS32_REGNUM); + set_gdbarch_fp0_regnum (gdbarch, -1); /* No FPU registers. */ + + set_gdbarch_dummy_id (gdbarch, arc_dummy_id); + set_gdbarch_push_dummy_call (gdbarch, arc_push_dummy_call); + set_gdbarch_push_dummy_code (gdbarch, arc_push_dummy_code); + + set_gdbarch_cannot_fetch_register (gdbarch, arc_cannot_fetch_register); + set_gdbarch_cannot_store_register (gdbarch, arc_cannot_store_register); + + set_gdbarch_believe_pcc_promotion (gdbarch, 1); + + set_gdbarch_return_value (gdbarch, arc_return_value); + + set_gdbarch_skip_prologue (gdbarch, arc_skip_prologue); + set_gdbarch_inner_than (gdbarch, core_addr_lessthan); + + set_gdbarch_breakpoint_from_pc (gdbarch, arc_breakpoint_from_pc); + + /* On ARC 600 BRK_S instruction advances PC, unlike other ARC cores. */ + if (!arc_mach_is_arc600 (gdbarch)) + set_gdbarch_decr_pc_after_break (gdbarch, 0); + else + set_gdbarch_decr_pc_after_break (gdbarch, 2); + + set_gdbarch_unwind_pc (gdbarch, arc_unwind_pc); + set_gdbarch_unwind_sp (gdbarch, arc_unwind_sp); + + set_gdbarch_frame_align (gdbarch, arc_frame_align); + + set_gdbarch_print_insn (gdbarch, arc_delayed_print_insn); + + set_gdbarch_cannot_step_breakpoint (gdbarch, 1); + + /* "nonsteppable" watchpoint means that watchpoint triggers before + instruction is committed, therefore it is required to remove watchpoint + to step though instruction that triggers it. ARC watchpoints trigger + only after instruction is committed, thus there is no need to remove + them. In fact on ARC watchpoint for memory writes may trigger with more + significant delay, like one or two instructions, depending on type of + memory where write is performed (CCM or external) and next instruction + after the memory write. */ + set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 0); + + /* This doesn't include possible long-immediate value. */ + set_gdbarch_max_insn_length (gdbarch, 4); + + /* Frame unwinders and sniffers. */ + dwarf2_frame_set_init_reg (gdbarch, arc_dwarf2_frame_init_reg); + dwarf2_append_unwinders (gdbarch); + frame_unwind_append_unwinder (gdbarch, &arc_frame_unwind); + frame_base_set_default (gdbarch, &arc_normal_base); + + /* Setup stuff specific to a particular environment (baremetal or Linux). + It can override functions set earlier. */ + gdbarch_init_osabi (info, gdbarch); + + tdesc_use_registers (gdbarch, tdesc, tdesc_data); + + return gdbarch; +} + +/* Implement the "dump_tdep" gdbarch method. */ + +static void +arc_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file) +{ + /* Empty for now. */ +} + +/* Suppress warning from -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_arc_tdep; + +void +_initialize_arc_tdep (void) +{ + gdbarch_register (bfd_arch_arc, arc_gdbarch_init, arc_dump_tdep); + + initialize_tdesc_arc_v2 (); + initialize_tdesc_arc_arcompact (); + + /* Register ARC-specific commands with gdb. */ + + /* Debug internals for ARC GDB. */ + add_setshow_zinteger_cmd ("arc", class_maintenance, + &arc_debug, + _("Set ARC specific debugging."), + _("Show ARC specific debugging."), + _("Non-zero enables ARC specific debugging."), + NULL, NULL, &setdebuglist, &showdebuglist); +} diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h new file mode 100644 index 0000000..1b2694b --- /dev/null +++ b/gdb/arc-tdep.h @@ -0,0 +1,101 @@ +/* Target dependent code for ARC arhitecture, for GDB. + + Copyright 2005-2016 Free Software Foundation, Inc. + Contributed by Synopsys 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/>. */ + +#ifndef ARC_TDEP_H +#define ARC_TDEP_H + +/* Need disassemble_info. */ +#include "dis-asm.h" + +enum arc_regnum + { + /* Core registers. */ + ARC_R0_REGNUM = 0, + ARC_FIRST_CORE_REGNUM = ARC_R0_REGNUM, + ARC_R1_REGNUM = 1, + ARC_R4_REGNUM = 4, + ARC_R7_REGNUM = 7, + ARC_R9_REGNUM = 9, + ARC_R13_REGNUM = 13, + ARC_R16_REGNUM = 16, + ARC_R25_REGNUM = 25, + /* Global data pointer. */ + ARC_GP_REGNUM, + /* Frame pointer. */ + ARC_FP_REGNUM, + /* Stack pointer. */ + ARC_SP_REGNUM, + /* Return address from interrupt. */ + ARC_ILINK_REGNUM, + ARC_R30_REGNUM, + /* Return address from function. */ + ARC_BLINK_REGNUM, + /* Zero-delay loop counter. */ + ARC_LP_COUNT_REGNUM = 60, + /* Program counter, aligned to 4-bytes, read-only. */ + ARC_PCL_REGNUM, + ARC_LAST_CORE_REGNUM = ARC_PCL_REGNUM, + /* AUX registers. */ + /* Actual program counter. */ + ARC_PC_REGNUM, + ARC_FIRST_AUX_REGNUM = ARC_PC_REGNUM, + /* Status register. */ + ARC_STATUS32_REGNUM, + ARC_LAST_REGNUM = ARC_STATUS32_REGNUM, + ARC_LAST_AUX_REGNUM = ARC_STATUS32_REGNUM, + + /* Additional ABI constants. */ + ARC_FIRST_ARG_REGNUM = ARC_R0_REGNUM, + ARC_LAST_ARG_REGNUM = ARC_R7_REGNUM, + ARC_FIRST_CALLEE_SAVED_REGNUM = ARC_R13_REGNUM, + ARC_LAST_CALLEE_SAVED_REGNUM = ARC_R25_REGNUM, + }; + +/* Number of bytes in ARC register. All ARC registers are considered 32-bit. + Those registers, which are actually shorter has zero-on-read for extra bits. + Longer registers are represented as pairs of 32-bit registers. */ +#define ARC_REGISTER_SIZE 4 + +#define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args) + +extern int arc_debug; + +/* Utility functions used by other ARC-specific modules. */ + +static inline int +arc_mach_is_arc600 (struct gdbarch *gdbarch) +{ + return (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc600 + || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601); +} + +static inline int +arc_mach_is_arc700 (struct gdbarch *gdbarch) +{ + return gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc700; +} + +static inline int +arc_mach_is_arcv2 (struct gdbarch *gdbarch) +{ + return gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arcv2; +} + +#endif /* ARC_TDEP_H */ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 7f1aac3..ef041de 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -83,6 +83,11 @@ am33_2.0*-*-linux*) solib-svr4.o" ;; +arc*-*-*) + # Target: baremetal ARC elf32 target + gdb_target_obs="arc-tdep.o" + ;; + arm*-wince-pe | arm*-*-mingw32ce*) # Target: ARM based machine running Windows CE (win32) gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o \ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index d13cf86..4fff1de 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2016-09-21 Anton Kolesov <anton.kolesov@synopsys.com> + + * gdb.texinfo (Embedded Processors): Document ARC. + (Synopsys ARC): New section. + (Standard Target Features): Document ARC features. + (ARC Features): New section. + 2016-09-21 Simon Marchi <simon.marchi@ericsson.com> * .gitignore: New file. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d1a5e7c..4bbe79e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -22017,6 +22017,7 @@ acceptable commands. @menu +* ARC:: Synopsys ARC * ARM:: ARM * M68K:: Motorola M68K * MicroBlaze:: Xilinx MicroBlaze @@ -22027,6 +22028,30 @@ acceptable commands. * Super-H:: Renesas Super-H @end menu +@node ARC +@subsection Synopsys ARC +@cindex Synopsys ARC +@cindex ARC specific commands +@cindex ARC600 +@cindex ARC700 +@cindex ARC EM +@cindex ARC HS + +@value{GDBN} provides the following ARC-specific commands: + +@table @code +@item set debug arc +@kindex set debug arc +Control the level of ARC specific debug messages. Use 0 for no messages (the +default) and 1 for debug messages. At present higher values offer no further +messages. + +@item show debug arc +@kindex show debug arc +Show the level of ARC specific debugging in operation. + +@end table + @node ARM @subsection ARM @@ -40907,6 +40932,7 @@ registers using the capitalization used in the description. @menu * AArch64 Features:: +* ARC Features:: * ARM Features:: * i386 Features:: * MicroBlaze Features:: @@ -40932,6 +40958,45 @@ The @samp{org.gnu.gdb.aarch64.fpu} feature is optional. If present, it should contain registers @samp{v0} through @samp{v31}, @samp{fpsr}, and @samp{fpcr}. +@node ARC Features +@subsection ARC Features +@cindex target descriptions, ARC Features + +ARC processors are highly configurable, so even core registers and their number +are not completely predetermined. In addition flags and PC registers which are +important to @value{GDBN} are not ``core'' registers in ARC. It is required +that one of the core registers features is present. +@samp{org.gnu.gdb.arc.aux-minimal} feature is mandatory. + +The @samp{org.gnu.gdb.arc.core.v2} feature is required for ARC EM and ARC HS +targets with a normal register file. It should contain registers @samp{r0} +through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink}, +@samp{lp_count} and @samp{pcl}. This feature may contain register @samp{ilink} +and any of extension core registers @samp{r32} through @samp{r59/acch}. +@samp{ilink} and extension core registers are not available to read/write, when +debugging GNU/Linux applications, thus @samp{ilink} is made optional. + +The @samp{org.gnu.gdb.arc.core-reduced.v2} feature is required for ARC EM and +ARC HS targets with a reduced register file. It should contain registers +@samp{r0} through @samp{r3}, @samp{r10} through @samp{r15}, @samp{gp}, +@samp{fp}, @samp{sp}, @samp{r30}, @samp{blink}, @samp{lp_count} and @samp{pcl}. +This feature may contain register @samp{ilink} and any of extension core +registers @samp{r32} through @samp{r59/acch}. + +The @samp{org.gnu.gdb.arc.core.arcompact} feature is required for ARCompact +targets with a normal register file. It should contain registers @samp{r0} +through @samp{r25}, @samp{gp}, @samp{fp}, @samp{sp}, @samp{r30}, @samp{blink}, +@samp{lp_count} and @samp{pcl}. This feature may contain registers +@samp{ilink1}, @samp{ilink2} and any of extension core registers @samp{r32} +through @samp{r59/acch}. @samp{ilink1} and @samp{ilink2} and extension core +registers are not available when debugging GNU/Linux applications. The only +difference with @samp{org.gnu.gdb.arc.core.v2} feature is in the names of +@samp{ilink1} and @samp{ilink2} registers and that @samp{r30} is mandatory in +ARC v2, but @samp{ilink2} is optional on ARCompact. + +The @samp{org.gnu.gdb.arc.aux-minimal} feature is required for all ARC +targets. It should contain registers @samp{pc} and @samp{status32}. + @node ARM Features @subsection ARM Features @cindex target descriptions, ARM features diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 809c811..4efb1a5 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -148,6 +148,8 @@ OUTPUTS = $(patsubst %,$(outdir)/%.dat,$(WHICH)) # to make on the command line. XMLTOC = \ aarch64.xml \ + arc-v2.xml \ + arc-arcompact.xml \ arm-with-iwmmxt.xml \ arm-with-m-fpa-layout.xml \ arm-with-m-vfp-d16.xml \ diff --git a/gdb/features/arc-arcompact.c b/gdb/features/arc-arcompact.c new file mode 100644 index 0000000..d1fa4fe --- /dev/null +++ b/gdb/features/arc-arcompact.c @@ -0,0 +1,75 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: arc-arcompact.xml */ + +#include "defs.h" +#include "osabi.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_arc_arcompact; +static void +initialize_tdesc_arc_arcompact (void) +{ + struct target_desc *result = allocate_target_description (); + struct tdesc_feature *feature; + struct tdesc_type *field_type; + struct tdesc_type *type; + + set_tdesc_architecture (result, bfd_scan_arch ("ARC700")); + + feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.arcompact"); + tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "gp", 26, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "fp", 27, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "sp", 28, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "ilink1", 29, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "ilink2", 30, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "blink", 31, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "lp_count", 32, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "pcl", 33, 1, "", 32, "code_ptr"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal"); + type = tdesc_create_flags (feature, "status32_type", 4); + tdesc_add_bitfield (type, "H", 0, 0); + tdesc_add_bitfield (type, "E", 1, 2); + tdesc_add_bitfield (type, "A", 3, 4); + tdesc_add_bitfield (type, "AE", 5, 5); + tdesc_add_bitfield (type, "DE", 6, 6); + tdesc_add_bitfield (type, "U", 7, 7); + tdesc_add_bitfield (type, "V", 8, 8); + tdesc_add_bitfield (type, "C", 9, 9); + tdesc_add_bitfield (type, "N", 10, 10); + tdesc_add_bitfield (type, "Z", 11, 11); + tdesc_add_bitfield (type, "L", 12, 12); + tdesc_add_bitfield (type, "R", 13, 13); + tdesc_add_bitfield (type, "SE", 14, 14); + + tdesc_create_reg (feature, "pc", 34, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "status32", 35, 1, NULL, 32, "status32_type"); + + tdesc_arc_arcompact = result; +} diff --git a/gdb/features/arc-arcompact.xml b/gdb/features/arc-arcompact.xml new file mode 100644 index 0000000..e66bb45 --- /dev/null +++ b/gdb/features/arc-arcompact.xml @@ -0,0 +1,85 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2015-2016 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<target> + <architecture>arc:ARC700</architecture> + <!-- No OSABI for bare metal. --> + <!-- No compatibility for ARC. --> + + <feature name="org.gnu.gdb.arc.core.arcompact"> + <reg name="r0" bitsize="32"/> + <reg name="r1" bitsize="32"/> + <reg name="r2" bitsize="32"/> + <reg name="r3" bitsize="32"/> + <reg name="r4" bitsize="32"/> + <reg name="r5" bitsize="32"/> + <reg name="r6" bitsize="32"/> + <reg name="r7" bitsize="32"/> + <reg name="r8" bitsize="32"/> + <reg name="r9" bitsize="32"/> + <reg name="r10" bitsize="32"/> + <reg name="r11" bitsize="32"/> + <reg name="r12" bitsize="32"/> + <reg name="r13" bitsize="32"/> + <reg name="r14" bitsize="32"/> + <reg name="r15" bitsize="32"/> + <reg name="r16" bitsize="32"/> + <reg name="r17" bitsize="32"/> + <reg name="r18" bitsize="32"/> + <reg name="r19" bitsize="32"/> + <reg name="r20" bitsize="32"/> + <reg name="r21" bitsize="32"/> + <reg name="r22" bitsize="32"/> + <reg name="r23" bitsize="32"/> + <reg name="r24" bitsize="32"/> + <reg name="r25" bitsize="32"/> + + <!-- ARC core data pointer registers. --> + <reg name="gp" bitsize="32" type="data_ptr"/> + <reg name="fp" bitsize="32" type="data_ptr"/> + <reg name="sp" bitsize="32" type="data_ptr"/> + + <!-- Code pointers. --> + <reg name="ilink1" bitsize="32" type="code_ptr"/> + <reg name="ilink2" bitsize="32" type="code_ptr"/> + <reg name="blink" bitsize="32" type="code_ptr"/> + + <!-- Here goes extension core registers: r32 - r59 --> + + <!-- Loop counter. --> + <reg name="lp_count" bitsize="32" type="uint32"/> + + <!-- r61 is a reserved register address. --> + + <!-- r62 is a long immediate value, not a real register. --> + + <!-- 4-byte aligned read-only program counter. --> + <reg name="pcl" bitsize="32" type="code_ptr" group=""/> + </feature> + + <feature name="org.gnu.gdb.arc.aux-minimal"> + <flags id="status32_type" size="4"> + <field name="H" start="0" end="0"/> + <field name="E" start="1" end="2"/> + <field name="A" start="3" end="4"/> + <field name="AE" start="5" end="5"/> + <field name="DE" start="6" end="6"/> + <field name="U" start="7" end="7"/> + <field name="V" start="8" end="8"/> + <field name="C" start="9" end="9"/> + <field name="N" start="10" end="10"/> + <field name="Z" start="11" end="11"/> + <field name="L" start="12" end="12"/> + <field name="R" start="13" end="13"/> + <field name="SE" start="14" end="14"/> + </flags> + + <reg name="pc" bitsize="32" type="code_ptr"/> + <reg name="status32" bitsize="32" type="status32_type"/> + </feature> +</target> diff --git a/gdb/features/arc-v2.c b/gdb/features/arc-v2.c new file mode 100644 index 0000000..c963410 --- /dev/null +++ b/gdb/features/arc-v2.c @@ -0,0 +1,79 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: arc-v2.xml */ + +#include "defs.h" +#include "osabi.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_arc_v2; +static void +initialize_tdesc_arc_v2 (void) +{ + struct target_desc *result = allocate_target_description (); + struct tdesc_feature *feature; + struct tdesc_type *field_type; + struct tdesc_type *type; + + set_tdesc_architecture (result, bfd_scan_arch ("ARCv2")); + + feature = tdesc_create_feature (result, "org.gnu.gdb.arc.core.v2"); + tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "gp", 26, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "fp", 27, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "sp", 28, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "ilink", 29, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "r30", 30, 1, "", 32, "int"); + tdesc_create_reg (feature, "blink", 31, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "lp_count", 32, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "pcl", 33, 1, "", 32, "code_ptr"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.arc.aux-minimal"); + type = tdesc_create_flags (feature, "status32_type", 4); + tdesc_add_bitfield (type, "H", 0, 0); + tdesc_add_bitfield (type, "E", 1, 4); + tdesc_add_bitfield (type, "AE", 5, 5); + tdesc_add_bitfield (type, "DE", 6, 6); + tdesc_add_bitfield (type, "U", 7, 7); + tdesc_add_bitfield (type, "V", 8, 8); + tdesc_add_bitfield (type, "C", 9, 9); + tdesc_add_bitfield (type, "N", 10, 10); + tdesc_add_bitfield (type, "Z", 11, 11); + tdesc_add_bitfield (type, "L", 12, 12); + tdesc_add_bitfield (type, "DZ", 13, 13); + tdesc_add_bitfield (type, "SC", 14, 14); + tdesc_add_bitfield (type, "ES", 15, 15); + tdesc_add_bitfield (type, "RB", 16, 18); + tdesc_add_bitfield (type, "AD", 19, 19); + tdesc_add_bitfield (type, "US", 20, 20); + tdesc_add_bitfield (type, "IE", 31, 31); + + tdesc_create_reg (feature, "pc", 34, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "status32", 35, 1, NULL, 32, "status32_type"); + + tdesc_arc_v2 = result; +} diff --git a/gdb/features/arc-v2.xml b/gdb/features/arc-v2.xml new file mode 100644 index 0000000..7f06dde --- /dev/null +++ b/gdb/features/arc-v2.xml @@ -0,0 +1,92 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2015-2016 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<target> + <architecture>arc:ARCv2</architecture> + <!-- No OSABI for bare metal. --> + <!-- No compatibility for ARC. --> + + <feature name="org.gnu.gdb.arc.core.v2"> + <reg name="r0" bitsize="32"/> + <reg name="r1" bitsize="32"/> + <reg name="r2" bitsize="32"/> + <reg name="r3" bitsize="32"/> + <reg name="r4" bitsize="32"/> + <reg name="r5" bitsize="32"/> + <reg name="r6" bitsize="32"/> + <reg name="r7" bitsize="32"/> + <reg name="r8" bitsize="32"/> + <reg name="r9" bitsize="32"/> + <reg name="r10" bitsize="32"/> + <reg name="r11" bitsize="32"/> + <reg name="r12" bitsize="32"/> + <reg name="r13" bitsize="32"/> + <reg name="r14" bitsize="32"/> + <reg name="r15" bitsize="32"/> + <reg name="r16" bitsize="32"/> + <reg name="r17" bitsize="32"/> + <reg name="r18" bitsize="32"/> + <reg name="r19" bitsize="32"/> + <reg name="r20" bitsize="32"/> + <reg name="r21" bitsize="32"/> + <reg name="r22" bitsize="32"/> + <reg name="r23" bitsize="32"/> + <reg name="r24" bitsize="32"/> + <reg name="r25" bitsize="32"/> + + <!-- ARC core data pointer registers. --> + <reg name="gp" bitsize="32" type="data_ptr"/> + <reg name="fp" bitsize="32" type="data_ptr"/> + <reg name="sp" bitsize="32" type="data_ptr"/> + + <!-- Code pointers. R30 is general purpose, but it used to be ILINK2 in + ARCompact, thus its odd position in between of special purpose registers. + GCC does't use this register, so it isn't a member of a general group. --> + <reg name="ilink" bitsize="32" type="code_ptr"/> + <reg name="r30" bitsize="32" group=""/> + <reg name="blink" bitsize="32" type="code_ptr"/> + + <!-- Here goes extension core registers: r32 - r57. --> + <!-- Here goes ACCL/ACCH registers, r58, r59. --> + + <!-- Loop counter. --> + <reg name="lp_count" bitsize="32" type="uint32"/> + + <!-- r61 is a reserved register address. --> + + <!-- r62 is a long immediate value, not a real register. --> + + <!-- 4-byte aligned read-only program counter. --> + <reg name="pcl" bitsize="32" type="code_ptr" group=""/> + </feature> + + <feature name="org.gnu.gdb.arc.aux-minimal"> + <flags id="status32_type" size="4"> + <field name="H" start="0" end="0"/> + <field name="E" start="1" end="4"/> + <field name="AE" start="5" end="5"/> + <field name="DE" start="6" end="6"/> + <field name="U" start="7" end="7"/> + <field name="V" start="8" end="8"/> + <field name="C" start="9" end="9"/> + <field name="N" start="10" end="10"/> + <field name="Z" start="11" end="11"/> + <field name="L" start="12" end="12"/> + <field name="DZ" start="13" end="13"/> + <field name="SC" start="14" end="14"/> + <field name="ES" start="15" end="15"/> + <field name="RB" start="16" end="18"/> + <field name="AD" start="19" end="19"/> + <field name="US" start="20" end="20"/> + <field name="IE" start="31" end="31"/> + </flags> + + <reg name="pc" bitsize="32" type="code_ptr"/> + <reg name="status32" bitsize="32" type="status32_type"/> + </feature> +</target> diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 1b8bc1a..5d0669d 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-09-21 Anton Kolesov <anton.kolesov@synopsys.com> + + * gdb.xml/tdesc-regs.exp: set core-regs for arc*-*-elf32. + 2016-09-21 Tom Tromey <tom@tromey.com> PR gdb/20604: diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp index c197e28..311917f 100644 --- a/gdb/testsuite/gdb.xml/tdesc-regs.exp +++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp @@ -30,6 +30,10 @@ switch -glob -- [istarget] { "aarch64*-*-*" { set core-regs {aarch64-core.xml} } + "arc*-*-*" { + set architecture "arc:ARCv2" + set core-regs {arc-v2.xml} + } "arm*-*-*" { set core-regs {arm-core.xml} } |