From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 45977 invoked by alias); 5 Apr 2017 09:22:48 -0000 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 Received: (qmail 45953 invoked by uid 89); 5 Apr 2017 09:22:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=supervisor, Supervisor, magnitude, baton X-HELO: mail-wm0-f45.google.com Received: from mail-wm0-f45.google.com (HELO mail-wm0-f45.google.com) (74.125.82.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 05 Apr 2017 09:22:42 +0000 Received: by mail-wm0-f45.google.com with SMTP id w204so8851014wmd.1 for ; Wed, 05 Apr 2017 02:22:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:message-id :user-agent:mime-version:content-transfer-encoding; bh=WTG5W16vHxUKZ7C7Sa+kv3QL17YOPHpmduJ11uBWROg=; b=LshxfQC87QH1gDswuukI/zKPXIpJWxOGOEAX2xksjDShPAHmTicRJnBXY4sKvM2XRR JS/dMRtE5wF9QhQC5VqbXDnXgt9dEMc4+ONF42i2KYqVu7MiKhes4gxOmkDzcQXzW9bW V4A58CYVGguBokVcHnCfHnBlORafI5gKU+gCyilP460iPF8FG+ck07uOe+8s727YLB/T d4c2i3zZbYMt3+Di8l5lWo5djDDn3049WVbOoBW7C5Id0cswRFJDogU9+qhroC8mJycQ J2SPVAPHJQYYZb2C80hcs08pi5YBIZ3yDYpeTcn/NPC9IpazRmW2ruvBRaUYWtpAr3g3 0BFQ== X-Gm-Message-State: AFeK/H3ye6zAv/OUUeaL4mrb5HrTJfSYhKVPU3sfhy2CZAxBmeiw+jCt 9JV1W9bTj0xFzDSw X-Received: by 10.28.105.8 with SMTP id e8mr18505941wmc.122.1491384159707; Wed, 05 Apr 2017 02:22:39 -0700 (PDT) Received: from E107787-LIN ([194.214.185.158]) by smtp.gmail.com with ESMTPSA id n5sm21549101wmf.14.2017.04.05.02.22.37 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 05 Apr 2017 02:22:39 -0700 (PDT) From: Yao Qi To: Palmer Dabbelt Cc: gdb-patches@sourceware.org Subject: Re: [PATCH 1/2] RISC-V GDB Port References: <20170307043029.3672-1-palmer@dabbelt.com> <20170307043029.3672-2-palmer@dabbelt.com> Date: Wed, 05 Apr 2017 09:22:00 -0000 Message-ID: <86d1crqkdh.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2017-04/txt/msg00084.txt.bz2 Palmer Dabbelt writes: > diff --git a/gdb/config/riscv/linux.mh b/gdb/config/riscv/linux.mh > new file mode 100644 > index 0000000..4ec9f47 > --- /dev/null > +++ b/gdb/config/riscv/linux.mh > @@ -0,0 +1,30 @@ > +# Host: RISC-V based machine running GNU/Linux > +# > +# Copyright (C) 2016 Free Software Foundation, Inc. 2016 - 2017 > +# Contributed by Albert Ou . Remove this line, because of https://sourceware.org/gdb/wiki/ContributionChecklist#Attribution > diff --git a/gdb/features/riscv.xml b/gdb/features/riscv.xml > new file mode 100644 > index 0000000..94e630c > --- /dev/null > +++ b/gdb/features/riscv.xml > @@ -0,0 +1,81 @@ > + > + > + > + > + > + riscv:rv64 > + > + You defined this feature, but this feature is not used else where. > + > +static struct regset_info riscv_regsets[] =3D > +{ > + { PTRACE_GETREGS, PTRACE_SETREGS, 0, riscv_num_regs * 8, https://github.com/riscv/riscv-linux/blob/master/arch/riscv/kernel/ptrace.c tells that riscv kernel support regset, so why don't you do { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, ..... > + GENERAL_REGS, riscv_fill_gregset, riscv_store_gregset }, > + NULL_REGSET > +}; > diff --git a/gdb/riscv-linux-nat.c b/gdb/riscv-linux-nat.c > new file mode 100644 > index 0000000..6accb7a > --- /dev/null > +++ b/gdb/riscv-linux-nat.c > @@ -0,0 +1,77 @@ > +/* Native-dependent code for GNU/Linux RISC-V. > + > + Copyright (C) 2015 Free Software Foundation, Inc. 2015 - 2017 > + Contributed by Albert Ou . Please remove this line. > + > + 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 .= */ > + > + > +#define DECLARE_INSN(INSN_NAME, INSN_MATCH, INSN_MASK) \ > +static inline bool is_ ## INSN_NAME ## _insn (long insn) \ > +{ \ > + return (insn & INSN_MASK) =3D=3D INSN_MATCH; \ > +} > +#include "opcode/riscv-opc.h" > +#undef DECLARE_INSN > + > +struct riscv_frame_cache > +{ > + CORE_ADDR base; > + struct trad_frame_saved_reg *saved_regs; > +}; > + > +static const char * const riscv_gdb_reg_names[RISCV_LAST_FP_REGNUM + 1] = =3D > +{ > + "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", > + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", > + "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", > + "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", > + "pc", > + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", > + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", > + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", > + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", > +}; > + > +struct register_alias > +{ > + const char *name; > + int regnum; > +}; > + > +static const struct register_alias riscv_register_aliases[] =3D > +{ > + { "zero", 0 }, > + { "ra", 1 }, > + { "sp", 2 }, > + { "gp", 3 }, > + { "tp", 4 }, > + { "t0", 5 }, > + { "t1", 6 }, > + { "t2", 7 }, > + { "fp", 8 }, > + { "s0", 8 }, > + { "s1", 9 }, > + { "a0", 10 }, > + { "a1", 11 }, > + { "a2", 12 }, > + { "a3", 13 }, > + { "a4", 14 }, > + { "a5", 15 }, > + { "a6", 16 }, > + { "a7", 17 }, > + { "s2", 18 }, > + { "s3", 19 }, > + { "s4", 20 }, > + { "s5", 21 }, > + { "s6", 22 }, > + { "s7", 23 }, > + { "s8", 24 }, > + { "s9", 25 }, > + { "s10", 26 }, > + { "s11", 27 }, > + { "t3", 28 }, > + { "t4", 29 }, > + { "t5", 30 }, > + { "t6", 31 }, > + /* pc is 32. */ > + { "ft0", 33 }, > + { "ft1", 34 }, > + { "ft2", 35 }, > + { "ft3", 36 }, > + { "ft4", 37 }, > + { "ft5", 38 }, > + { "ft6", 39 }, > + { "ft7", 40 }, > + { "fs0", 41 }, > + { "fs1", 42 }, > + { "fa0", 43 }, > + { "fa1", 44 }, > + { "fa2", 45 }, > + { "fa3", 46 }, > + { "fa4", 47 }, > + { "fa5", 48 }, > + { "fa6", 49 }, > + { "fa7", 50 }, > + { "fs2", 51 }, > + { "fs3", 52 }, > + { "fs4", 53 }, > + { "fs5", 54 }, > + { "fs6", 55 }, > + { "fs7", 56 }, > + { "fs8", 57 }, > + { "fs9", 58 }, > + { "fs10", 59 }, > + { "fs11", 60 }, > + { "ft8", 61 }, > + { "ft9", 62 }, > + { "ft10", 63 }, > + { "ft11", 64 }, > +#define DECLARE_CSR(name, num) { #name, (num) + 65 }, > +#include "opcode/riscv-opc.h" > +#undef DECLARE_CSR > +}; > + > +static enum auto_boolean use_compressed_breakpoints; > +/* > +static void > +show_use_compressed_breakpoints (struct ui_file *file, int from_tty, > + struct cmd_list_element *c, > + const char *value) > +{ > + fprintf_filtered (file, > + _("Debugger's behavior regarding " > + "compressed breakpoints is %s.\n"), > + value); > +} > +*/ Remove it. > + > +static struct cmd_list_element *setriscvcmdlist =3D NULL; > +static struct cmd_list_element *showriscvcmdlist =3D NULL; > + > +static void > +show_riscv_command (char *args, int from_tty) > +{ > + help_list (showriscvcmdlist, "show riscv ", all_commands, gdb_stdout); > +} > + > +static void > +set_riscv_command (char *args, int from_tty) > +{ > + printf_unfiltered > + ("\"set riscv\" must be followed by an appropriate subcommand.\n"); > + help_list (setriscvcmdlist, "set riscv ", all_commands, gdb_stdout); > +} > + > +/* Implement the breakpoint_kind_from_pc gdbarch method. */ > + > +static int > +riscv_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) > +{ > + if (use_compressed_breakpoints =3D=3D AUTO_BOOLEAN_AUTO) { "{" should be in the new line. > + if (gdbarch_tdep (gdbarch)->supports_compressed_isa =3D=3D AUTO_BOOL= EAN_AUTO) supports_compressed_isa's type can be "enum tribool". > + { > + /* TODO: Because we try to read misa, it is not possible to set a > + breakpoint before connecting to a live target. A suggested work= around is > + to look at the ELF file in this case. */ > + struct frame_info *frame =3D get_current_frame (); The information of using compressed isa should be saved in ELF, and GDB read it from ELF. > + uint32_t misa =3D get_frame_register_unsigned (frame, RISCV_CSR_MI= SA_REGNUM); > + if (misa & (1<<2)) > + gdbarch_tdep (gdbarch)->supports_compressed_isa =3D AUTO_BOOLEAN= _TRUE; > + else > + gdbarch_tdep (gdbarch)->supports_compressed_isa =3D AUTO_BOOLEAN= _FALSE; > + } > + > + if (gdbarch_tdep (gdbarch)->supports_compressed_isa =3D=3D AUTO_BOOL= EAN_TRUE) > + return 2; > + else > + return 4; > + } else if (use_compressed_breakpoints =3D=3D AUTO_BOOLEAN_TRUE) { > + return 2; > + } else { > + return 4; > + } > +} > + > +/* Implement the sw_breakpoint_from_kind gdbarch method. */ > + > +static const gdb_byte * > +riscv_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *s= ize) > +{ > + static const gdb_byte ebreak[] =3D { 0x73, 0x00, 0x10, 0x00, }; > + static const gdb_byte c_ebreak[] =3D { 0x02, 0x90 }; > + > + *size =3D kind; > + switch (kind) > + { > + case 2: > + return c_ebreak; > + case 4: > + return ebreak; > + default: > + gdb_assert(0); gdb_assert_not_reached? > + } > +} > + > +static struct value * > +value_of_riscv_user_reg (struct frame_info *frame, const void *baton) > +{ > + const int *reg_p =3D (const int *)baton; > + > + return value_of_register (*reg_p, frame); > +} > + > +static const char * > +register_name (struct gdbarch *gdbarch, > + int regnum, > + int prefer_alias) > +{ > + int i; > + static char buf[20]; > + > + if (tdesc_has_registers (gdbarch_target_desc (gdbarch))) > + return tdesc_register_name (gdbarch, regnum); > + /* Prefer to use the alias. */ > + if (prefer_alias && > + regnum >=3D RISCV_ZERO_REGNUM && regnum <=3D RISCV_LAST_REGNUM) > + { > + for (i =3D 0; i < ARRAY_SIZE (riscv_register_aliases); ++i) > + if (regnum =3D=3D riscv_register_aliases[i].regnum) > + return riscv_register_aliases[i].name; > + } If you prefer alias over the tdesc register name, put this block in front of tdesc_register_name. > + > + if (regnum >=3D RISCV_ZERO_REGNUM && regnum <=3D RISCV_LAST_FP_REGNUM) > + return riscv_gdb_reg_names[regnum]; If target description is always available, this is not needed. > + > + if (regnum >=3D RISCV_FIRST_CSR_REGNUM && regnum <=3D RISCV_LAST_CSR_R= EGNUM) > + { > + sprintf(buf, "csr%d", regnum - RISCV_FIRST_CSR_REGNUM); > + return buf; > + } > + > + if (regnum =3D=3D RISCV_PRIV_REGNUM) > + { > + return "priv"; > + } > + > + return NULL; > +} > + > +/* Implement the register_name gdbarch method. */ > + > +static const char * > +riscv_register_name (struct gdbarch *gdbarch, > + int regnum) > +{ > + return register_name(gdbarch, regnum, 0); space before "(". > +} > + > +/* Reads a function return value of type TYPE. */ > + > +static void > +riscv_extract_return_value (struct type *type, > + struct regcache *regs, > + gdb_byte *dst, > + int regnum) > +{ > + struct gdbarch *gdbarch =3D get_regcache_arch (regs); > + enum bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); > + int regsize =3D riscv_isa_regsize (gdbarch); > + bfd_byte *valbuf =3D dst; > + int len =3D TYPE_LENGTH (type); > + int st_len =3D std::min (regsize, len); > + ULONGEST tmp; > + > + gdb_assert (len <=3D 2 * regsize); > + > + while (len > 0) > + { > + regcache_cooked_read_unsigned (regs, regnum++, &tmp); > + store_unsigned_integer (valbuf, st_len, byte_order, tmp); > + len -=3D regsize; > + valbuf +=3D regsize; > + } > +} > + > +/* Write into appropriate registers a function return value of type > + TYPE, given in virtual format. */ > + > +static void > +riscv_store_return_value (struct type *type, > + struct regcache *regs, > + const gdb_byte *src, > + int regnum) > +{ > + struct gdbarch *gdbarch =3D get_regcache_arch (regs); > + int regsize =3D riscv_isa_regsize (gdbarch); > + const bfd_byte *valbuf =3D src; > + > + /* Integral values greater than one word are stored in consecutive > + registers starting with R0. This will always be a multiple of > + the register size. */ > + > + int len =3D TYPE_LENGTH (type); > + > + gdb_assert (len <=3D 2 * regsize); > + > + while (len > 0) > + { > + regcache_cooked_write (regs, regnum++, valbuf); > + len -=3D regsize; > + valbuf +=3D regsize; > + } > +} > + > +/* Implement the return_value gdbarch method. */ > + > +static enum return_value_convention > +riscv_return_value (struct gdbarch *gdbarch, > + struct value *function, > + struct type *type, > + struct regcache *regcache, > + gdb_byte *readbuf, > + const gdb_byte *writebuf) > +{ > + enum type_code rv_type =3D TYPE_CODE (type); > + unsigned int rv_size =3D TYPE_LENGTH (type); > + int fp, regnum; > + ULONGEST tmp; > + > + /* Paragraph on return values taken from RISC-V specification (post v2= .0): > + > + Values are returned from functions in integer registers a0 and a1 a= nd > + floating-point registers fa0 and fa1. Floating-point values are re= turned > + in floating-point registers only if they are primitives or members = of a > + struct consisting of only one or two floating-point values. Other = return > + values that fit into two pointer-words are returned in a0 and a1. = Larger > + return values are passed entirely in memory; the caller allocates t= his > + memory region and passes a pointer to it as an implicit first param= eter > + to the callee. */ > + > + /* Deal with struct/unions first that are passed via memory. */ > + if (rv_size > 2 * riscv_isa_regsize (gdbarch)) > + { > + if (readbuf || writebuf) > + regcache_cooked_read_unsigned (regcache, RISCV_A0_REGNUM, &tmp); > + if (readbuf) > + read_memory (tmp, readbuf, rv_size); > + if (writebuf) > + write_memory (tmp, writebuf, rv_size); > + return RETURN_VALUE_ABI_RETURNS_ADDRESS; > + } > + > + /* Are we dealing with a floating point value? */ > + fp =3D 0; pass_arg_in_fp =3D false; > + if (rv_type =3D=3D TYPE_CODE_FLT) > + fp =3D 1; > + else if (rv_type =3D=3D TYPE_CODE_STRUCT || rv_type =3D=3D TYPE_CODE_U= NION) > + { > + unsigned int rv_fields =3D TYPE_NFIELDS (type); > + > + if (rv_fields =3D=3D 1) > + { > + struct type *fieldtype =3D TYPE_FIELD_TYPE (type, 0); > + if (TYPE_CODE (check_typedef (fieldtype)) =3D=3D TYPE_CODE_FLT) > + fp =3D 1; > + } > + else if (rv_fields =3D=3D 2) > + { > + struct type *fieldtype0 =3D TYPE_FIELD_TYPE (type, 0); > + struct type *fieldtype1 =3D TYPE_FIELD_TYPE (type, 1); > + > + if (TYPE_CODE (check_typedef (fieldtype0)) =3D=3D TYPE_CODE_FLT > + && TYPE_CODE (check_typedef (fieldtype1)) =3D=3D TYPE_CODE_FLT) > + fp =3D 1; > + } > + } > + > + /* Handle return value in a register. */ > + regnum =3D fp ? RISCV_FA0_REGNUM : RISCV_A0_REGNUM; > + > + if (readbuf) > + riscv_extract_return_value (type, regcache, readbuf, regnum); > + > + if (writebuf) > + riscv_store_return_value (type, regcache, writebuf, regnum); > + > + return RETURN_VALUE_REGISTER_CONVENTION; > +} > + > +/* Implement the pseudo_register_read gdbarch method. */ > + > +static enum register_status > +riscv_pseudo_register_read (struct gdbarch *gdbarch, > + struct regcache *regcache, > + int regnum, > + gdb_byte *buf) > +{ > + return regcache_raw_read (regcache, regnum, buf); > +} > + > +/* Implement the pseudo_register_write gdbarch method. */ > + > +static void > +riscv_pseudo_register_write (struct gdbarch *gdbarch, > + struct regcache *regcache, > + int cookednum, > + const gdb_byte *buf) > +{ > + regcache_raw_write (regcache, cookednum, buf); > +} I don't see riscv has pseudo registers. > + > +static void > +riscv_print_register_formatted (struct ui_file *file, struct frame_info = *frame, > + int regnum) > +{ > + struct gdbarch *gdbarch =3D get_frame_arch (frame); > + gdb_byte raw_buffer[MAX_REGISTER_SIZE]; > + struct value_print_options opts; > + > + if (regnum >=3D RISCV_FIRST_FP_REGNUM && regnum <=3D RISCV_LAST_FP_REG= NUM) > + riscv_print_fp_register (file, frame, regnum); > + else > + { > + /* Integer type. */ > + int offset, size; > + unsigned long long d; > + > + if (!deprecated_frame_register_read (frame, regnum, raw_buffer)) Don't use deprecated_frame_register_read, use other frame apis. > + { > + fprintf_filtered (file, "%-15s[Invalid]\n", > + register_name (gdbarch, regnum, 1)); > + return; > + } > + > + fprintf_filtered (file, "%-15s", register_name (gdbarch, regnum, 1= )); > + if (gdbarch_byte_order (gdbarch) =3D=3D BFD_ENDIAN_BIG) > + offset =3D register_size (gdbarch, regnum) - register_size (gdbarch, re= gnum); offset is zero. > + else > + offset =3D 0; > + > + size =3D register_size (gdbarch, regnum); > + get_formatted_print_options (&opts, 'x'); > + print_scalar_formatted (raw_buffer + offset, > + register_type (gdbarch, regnum), &opts, > + size =3D=3D 8 ? 'g' : 'w', file); > + fprintf_filtered (file, "\t"); > + if (size =3D=3D 4 && riscv_isa_regsize (gdbarch) =3D=3D 8) > + fprintf_filtered (file, "\t"); > + > + if (regnum =3D=3D RISCV_CSR_MSTATUS_REGNUM) > + { > + if (size =3D=3D 4) > + d =3D unpack_long (builtin_type (gdbarch)->builtin_uint32, raw_buff= er); > + else if (size =3D=3D 8) > + d =3D unpack_long (builtin_type (gdbarch)->builtin_uint64, raw_buff= er); > + else > + internal_error (__FILE__, __LINE__, _("unknown size for mstatus")); > + unsigned xlen =3D size * 4; > + fprintf_filtered (file, > + "SD:%X VM:%02X MXR:%X PUM:%X MPRV:%X XS:%X " > + "FS:%X MPP:%x HPP:%X SPP:%X MPIE:%X HPIE:%X " > + "SPIE:%X UPIE:%X MIE:%X HIE:%X SIE:%X UIE:%X", > + (int)((d >> (xlen-1)) & 0x1), > + (int)((d >> 24) & 0x1f), > + (int)((d >> 19) & 0x1), > + (int)((d >> 18) & 0x1), > + (int)((d >> 17) & 0x1), > + (int)((d >> 15) & 0x3), > + (int)((d >> 13) & 0x3), > + (int)((d >> 11) & 0x3), > + (int)((d >> 9) & 0x3), > + (int)((d >> 8) & 0x1), > + (int)((d >> 7) & 0x1), > + (int)((d >> 6) & 0x1), > + (int)((d >> 5) & 0x1), > + (int)((d >> 4) & 0x1), > + (int)((d >> 3) & 0x1), > + (int)((d >> 2) & 0x1), > + (int)((d >> 1) & 0x1), > + (int)((d >> 0) & 0x1)); > + } > + else if (regnum =3D=3D RISCV_CSR_MISA_REGNUM) > + { > + int base; > + if (size =3D=3D 4) { > + d =3D unpack_long (builtin_type (gdbarch)->builtin_uint32, r= aw_buffer); > + base =3D d >> 30; > + } else if (size =3D=3D 8) { > + d =3D unpack_long (builtin_type (gdbarch)->builtin_uint64, r= aw_buffer); > + base =3D d >> 62; > + } else { > + internal_error (__FILE__, __LINE__, _("unknown size for misa= ")); > + } > + unsigned xlen =3D 16; > + for (; base > 0; base--) { > + xlen *=3D 2; > + } > + fprintf_filtered (file, "RV%d", xlen); > + > + for (unsigned i =3D 0; i < 26; i++) { > + if (d & (1< + fprintf_filtered (file, "%c", 'A' + i); > + } > + } > + } > + else if (regnum =3D=3D RISCV_CSR_FCSR_REGNUM > + || regnum =3D=3D RISCV_CSR_FFLAGS_REGNUM > + || regnum =3D=3D RISCV_CSR_FRM_REGNUM) > + { > + d =3D unpack_long (builtin_type (gdbarch)->builtin_int32, raw_buffer); > + > + if (regnum !=3D RISCV_CSR_FRM_REGNUM) > + fprintf_filtered (file, "RD:%01X NV:%d DZ:%d OF:%d UF:%d NX:%d ", > + (int)((d >> 5) & 0x7), > + (int)((d >> 4) & 0x1), > + (int)((d >> 3) & 0x1), > + (int)((d >> 2) & 0x1), > + (int)((d >> 1) & 0x1), > + (int)((d >> 0) & 0x1)); > + > + if (regnum !=3D RISCV_CSR_FFLAGS_REGNUM) > + { > + static const char * const sfrm[] =3D { > + "RNE (round to nearest; ties to even)", > + "RTZ (Round towards zero)", > + "RDN (Round down towards -=E2=88=9E)", > + "RUP (Round up towards +=E2=88=9E)", > + "RMM (Round to nearest; tiest to max magnitude)", > + "INVALID[5]", > + "INVALID[6]", > + "dynamic rounding mode", > + }; > + int frm =3D ((regnum =3D=3D RISCV_CSR_FCSR_REGNUM) ? (d >> 5) : d= ) & 0x3; > + > + fprintf_filtered (file, "FRM:%i [%s]", frm, sfrm[frm]); > + } > + } > + else if (regnum =3D=3D RISCV_PRIV_REGNUM) > + { > + uint8_t priv =3D raw_buffer[0]; > + if (priv >=3D 0 && priv < 4) > + { > + static const char * const sprv[] =3D { > + "User/Application", > + "Supervisor", > + "Hypervisor", > + "Machine" > + }; > + fprintf_filtered (file, "prv:%d [%s]", priv, sprv[priv]); > + } > + else > + { > + fprintf_filtered (file, "prv:%d [INVALID]", priv); > + } > + } > + else > + { > + get_formatted_print_options (&opts, 'd'); > + print_scalar_formatted (raw_buffer + offset, > + register_type (gdbarch, regnum), > + &opts, 0, file); > + } > + } > + fprintf_filtered (file, "\n"); > +} > + > +/* Implement the register_reggroup_p gdbarch method. */ > + > +static int > +riscv_register_reggroup_p (struct gdbarch *gdbarch, > + int regnum, > + struct reggroup *reggroup) > +{ > + int float_p; > + int raw_p; > + unsigned int i; > + > + /* Used by 'info registers' and 'info registers '. */ > + > + if (gdbarch_register_name (gdbarch, regnum) =3D=3D NULL > + || gdbarch_register_name (gdbarch, regnum)[0] =3D=3D '\0') > + return 0; > + > + if (reggroup =3D=3D all_reggroup) { "{" should be put to next line. Many instances of this style problems. > + > +static ULONGEST > +riscv_fetch_instruction (struct gdbarch *gdbarch, CORE_ADDR addr) > +{ > + enum bfd_endian byte_order =3D gdbarch_byte_order_for_code (gdbarch); > + gdb_byte buf[8]; > + int instlen, status; > + > + /* All insns are at least 16 bits. */ > + status =3D target_read_memory (addr, buf, 2); Use target_read_code. > + if (status) > + memory_error (TARGET_XFER_E_IO, addr); > + > + /* If we need more, grab it now. */ > + instlen =3D riscv_insn_length (buf[0]); > + if (instlen > sizeof (buf)) > + internal_error (__FILE__, __LINE__, _("%s: riscv_insn_length returne= d %i"), > + __func__, instlen); > + else if (instlen > 2) > + { > + status =3D target_read_memory (addr + 2, buf + 2, instlen - 2); Likewise. > + if (status) > + memory_error (TARGET_XFER_E_IO, addr + 2); > + } > + > + return extract_unsigned_integer (buf, instlen, byte_order); > +} > + > +static void > +set_reg_offset (struct gdbarch *gdbarch, struct riscv_frame_cache *this_= cache, > + int regnum, CORE_ADDR offset) Comments of this function is missing. Some instances of this problem. > +{ > + if (this_cache !=3D NULL && this_cache->saved_regs[regnum].addr =3D=3D= -1) > + this_cache->saved_regs[regnum].addr =3D offset; > +} > + > + > +static CORE_ADDR > +riscv_scan_prologue (struct gdbarch *gdbarch, > + CORE_ADDR start_pc, CORE_ADDR limit_pc, > + struct frame_info *this_frame, > + struct riscv_frame_cache *this_cache) > +{ > + CORE_ADDR cur_pc; > + CORE_ADDR frame_addr =3D 0; > + CORE_ADDR sp; > + long frame_offset; > + int frame_reg =3D RISCV_SP_REGNUM; > + > + CORE_ADDR end_prologue_addr =3D 0; > + int seen_sp_adjust =3D 0; s/int/bool/ > + int load_immediate_bytes =3D 0; > + > + /* Can be called when there's no process, and hence when there's no TH= IS_FRAME. */ > + if (this_frame !=3D NULL) > + sp =3D get_frame_register_signed (this_frame, RISCV_SP_REGNUM); > + else > + sp =3D 0; > + > + if (limit_pc > start_pc + 200) > + limit_pc =3D start_pc + 200; > + > + restart: > + > + frame_offset =3D 0; > + /* TODO: Handle compressed extensions. */ Is compressed extension handled? > + for (cur_pc =3D start_pc; cur_pc < limit_pc; cur_pc +=3D 4) looks not, because cur_pc is increased by 4. > + > +static struct trad_frame_cache * > +riscv_frame_cache (struct frame_info *this_frame, void **this_cache) > +{ > + CORE_ADDR pc; > + CORE_ADDR start_addr; > + CORE_ADDR stack_addr; > + struct trad_frame_cache *this_trad_cache; > + struct gdbarch *gdbarch =3D get_frame_arch (this_frame); > + > + if ((*this_cache) !=3D NULL) > + return (struct trad_frame_cache *) *this_cache; > + this_trad_cache =3D trad_frame_cache_zalloc (this_frame); > + (*this_cache) =3D this_trad_cache; > + > + trad_frame_set_reg_realreg (this_trad_cache, gdbarch_pc_regnum (gdbarc= h), > + RISCV_RA_REGNUM); > + > + pc =3D get_frame_pc (this_frame); > + find_pc_partial_function (pc, NULL, &start_addr, NULL); > + stack_addr =3D get_frame_register_signed (this_frame, RISCV_SP_REGNUM); get_frame_register_unsiged? > + trad_frame_set_id (this_trad_cache, frame_id_build (stack_addr, start_= addr)); > + > + trad_frame_set_this_base (this_trad_cache, stack_addr); > + > + return this_trad_cache; > +} > + > + > +static const struct frame_unwind riscv_frame_unwind =3D > +{ > + /*.type =3D*/ NORMAL_FRAME, Usually, we put such comment at the end of each statement, like NORMAL_FRAME, /* type */ > + /*.stop_reason =3D*/ default_frame_unwind_stop_reason, > + /*.this_id =3D*/ riscv_frame_this_id, > + /*.prev_register =3D*/ riscv_frame_prev_register, > + /*.unwind_data =3D*/ NULL, > + /*.sniffer =3D*/ default_frame_sniffer, > + /*.dealloc_cache =3D*/ NULL, > + /*.prev_arch =3D*/ NULL, > +}; > + > +static struct gdbarch * > +riscv_gdbarch_init (struct gdbarch_info info, > + struct gdbarch_list *arches) > +{ > + struct gdbarch *gdbarch; > + struct gdbarch_tdep *tdep; > + const struct bfd_arch_info *binfo =3D info.bfd_arch_info; > + > + int abi, i; > + > + /* For now, base the abi on the elf class. */ > + /* Allow the ELF class to override the register size. Ideally the targ= et > + * (OpenOCD/spike/...) would communicate the register size to gdb inst= ead. */ > + abi =3D RISCV_ABI_FLAG_RV32I; > + if (info.abfd && bfd_get_flavour (info.abfd) =3D=3D bfd_target_elf_fla= vour) > + { > + unsigned char eclass =3D elf_elfheader (info.abfd)->e_ident[EI_CLA= SS]; > + > + if (eclass =3D=3D ELFCLASS32) > + abi =3D RISCV_ABI_FLAG_RV32I; > + else if (eclass =3D=3D ELFCLASS64) > + abi =3D RISCV_ABI_FLAG_RV64I; > + else > + internal_error (__FILE__, __LINE__, _("unknown ELF header class = %d"), eclass); > + } > + else > + { > + if (binfo->bits_per_word =3D=3D 32) > + abi =3D RISCV_ABI_FLAG_RV32I; > + else if (binfo->bits_per_word =3D=3D 64) > + abi =3D RISCV_ABI_FLAG_RV64I; > + else > + internal_error (__FILE__, __LINE__, _("unknown bits_per_word %d"= ), > + binfo->bits_per_word); Do you support object file format other than ELF? > + } > + > + /* Find a candidate among the list of pre-declared architectures. */ > + for (arches =3D gdbarch_list_lookup_by_info (arches, &info); > + arches !=3D NULL; > + arches =3D gdbarch_list_lookup_by_info (arches->next, &info)) > + if (gdbarch_tdep (arches->gdbarch)->riscv_abi =3D=3D abi) > + return arches->gdbarch; > + > + /* None found, so create a new architecture from the information provi= ded. > + Can't initialize all the target dependencies until we actually know= which > + target we are talking to, but put in some defaults for now. */ > + > + tdep =3D (struct gdbarch_tdep *) xmalloc (sizeof *tdep); > + gdbarch =3D gdbarch_alloc (&info, tdep); > + > + tdep->riscv_abi =3D abi; > + tdep->supports_compressed_isa =3D AUTO_BOOLEAN_AUTO; > + > + /* Target data types. */ > + set_gdbarch_short_bit (gdbarch, 16); > + set_gdbarch_int_bit (gdbarch, 32); > + set_gdbarch_long_bit (gdbarch, riscv_isa_regsize (gdbarch) * 8); > + set_gdbarch_float_bit (gdbarch, 32); > + set_gdbarch_double_bit (gdbarch, 64); > + set_gdbarch_long_double_bit (gdbarch, 128); > + set_gdbarch_ptr_bit (gdbarch, riscv_isa_regsize (gdbarch) * 8); > + set_gdbarch_char_signed (gdbarch, 1); > + > + /* Information about the target architecture. */ > + set_gdbarch_return_value (gdbarch, riscv_return_value); > + set_gdbarch_breakpoint_kind_from_pc (gdbarch, riscv_breakpoint_kind_fr= om_pc); > + set_gdbarch_sw_breakpoint_from_kind (gdbarch, riscv_sw_breakpoint_from= _kind); > + set_gdbarch_print_insn (gdbarch, print_insn_riscv); > + > + /* Register architecture. */ > + set_gdbarch_pseudo_register_read (gdbarch, riscv_pseudo_register_read); > + set_gdbarch_pseudo_register_write (gdbarch, riscv_pseudo_register_writ= e); > + set_gdbarch_num_regs (gdbarch, RISCV_NUM_REGS); > + set_gdbarch_num_pseudo_regs (gdbarch, RISCV_NUM_REGS); > + set_gdbarch_sp_regnum (gdbarch, RISCV_SP_REGNUM); > + set_gdbarch_pc_regnum (gdbarch, RISCV_PC_REGNUM); > + set_gdbarch_ps_regnum (gdbarch, RISCV_FP_REGNUM); > + set_gdbarch_deprecated_fp_regnum (gdbarch, RISCV_FP_REGNUM); > + > + /* Functions to supply register information. */ > + set_gdbarch_register_name (gdbarch, riscv_register_name); > + set_gdbarch_register_type (gdbarch, riscv_register_type); > + set_gdbarch_print_registers_info (gdbarch, riscv_print_registers_info); > + set_gdbarch_register_reggroup_p (gdbarch, riscv_register_reggroup_p); > + > + /* Functions to analyze frames. */ > + set_gdbarch_skip_prologue (gdbarch, riscv_skip_prologue); > + set_gdbarch_inner_than (gdbarch, core_addr_lessthan); > + set_gdbarch_frame_align (gdbarch, riscv_frame_align); > + > + /* Functions to access frame data. */ > + set_gdbarch_unwind_pc (gdbarch, riscv_unwind_pc); > + set_gdbarch_unwind_sp (gdbarch, riscv_unwind_sp); > + > + /* Functions handling dummy frames. */ > + set_gdbarch_call_dummy_location (gdbarch, ON_STACK); > + set_gdbarch_push_dummy_code (gdbarch, riscv_push_dummy_code); > + set_gdbarch_push_dummy_call (gdbarch, riscv_push_dummy_call); > + set_gdbarch_dummy_id (gdbarch, riscv_dummy_id); > + > + /* Frame unwinders. Use DWARF debug info if available, otherwise use = our own > + unwinder. */ > + dwarf2_append_unwinders (gdbarch); > + frame_unwind_append_unwinder (gdbarch, &riscv_frame_unwind); > + > + /* Check any target description for validity. */ > + if (tdesc_has_registers (info.target_desc)) > + { > + const struct tdesc_feature *feature; > + struct tdesc_arch_data *tdesc_data; > + int valid_p; > + > + feature =3D tdesc_find_feature (info.target_desc, "org.gnu.gdb.ris= cv.cpu"); > + if (feature =3D=3D NULL) > + goto no_tdata; > + Don't use "goto". > + tdesc_data =3D tdesc_data_alloc (); > + > + valid_p =3D 1; > + for (i =3D RISCV_ZERO_REGNUM; i <=3D RISCV_LAST_FP_REGNUM; ++i) > + valid_p &=3D tdesc_numbered_register (feature, tdesc_data, i, > + riscv_gdb_reg_names[i]); > + for (i =3D RISCV_FIRST_CSR_REGNUM; i <=3D RISCV_LAST_CSR_REGNUM; += +i) > + { > + char buf[20]; > + sprintf (buf, "csr%d", i - RISCV_FIRST_CSR_REGNUM); > + valid_p &=3D tdesc_numbered_register (feature, tdesc_data, i, = buf); > + } > + > + valid_p &=3D tdesc_numbered_register (feature, tdesc_data, i++, "p= riv"); > + > + if (!valid_p) > + tdesc_data_cleanup (tdesc_data); > + else > + tdesc_use_registers (gdbarch, info.target_desc, tdesc_data); > + } > + no_tdata: > + > + for (i =3D 0; i < ARRAY_SIZE (riscv_register_aliases); ++i) > + user_reg_add (gdbarch, riscv_register_aliases[i].name, > + value_of_riscv_user_reg, &riscv_register_aliases[i].regnum); > + > + return gdbarch; > +} > + > + > +/* All the official RISC-V ABIs. These mostly line up with mcpuid purel= y for > + convenience. */ > +#define RISCV_ABI_FLAG_RV32I (0x00000000) /* 32-bit Integer GPRs. */ > +#define RISCV_ABI_FLAG_RV64I (0x40000000) /* 64-bit Integer GPRs. */ > +#define RISCV_ABI_FLAG_D (1 << 3) /* Double-Precision Floating-Point. */ > +#define RISCV_ABI_FLAG_F (1 << 5) /* Single-Precision Floating-Point. */ > + > +#define IS_RV32I(x) (((x) & 0xF0000000) =3D=3D RISCV_ABI_FLAG_RV32I) > +#define IS_RV64I(x) (((x) & 0xF0000000) =3D=3D RISCV_ABI_FLAG_RV64I) > + > +#define HAS_FPU(x) ((x) & (RISCV_ABI_FLAG_D | RISCV_ABI_FLAG_F)) > + > +enum { > + RISCV_ZERO_REGNUM =3D 0, /* Read-only register, always 0. */ > + RISCV_RA_REGNUM =3D 1, /* Return Address. */ > + RISCV_SP_REGNUM =3D 2, /* Stack Pointer. */ > + RISCV_GP_REGNUM =3D 3, /* Global Pointer. */ > + RISCV_TP_REGNUM =3D 4, /* Thread Pointer. */ > + RISCV_FP_REGNUM =3D 8, /* Frame Pointer. */ > + RISCV_A0_REGNUM =3D 10, /* First argument. */ > + RISCV_A1_REGNUM =3D 11, /* Second argument. */ > + RISCV_PC_REGNUM =3D 32, /* Program Counter. */ > + > + RISCV_FIRST_FP_REGNUM =3D 33, /* First Floating Point Register */ > + RISCV_FA0_REGNUM =3D 49, > + RISCV_FA1_REGNUM =3D 50, > + RISCV_LAST_FP_REGNUM =3D 64, /* Last Floating Point Register */ > + > + RISCV_FIRST_CSR_REGNUM =3D 65, /* First CSR */ > +#define DECLARE_CSR(name, num) RISCV_ ## num ## _REGNUM =3D RISCV_LAST_F= P_REGNUM + 1 + num, > +#include "opcode/riscv-opc.h" > +#undef DECLARE_CSR > + RISCV_LAST_CSR_REGNUM =3D 4160, > + > + RISCV_PRIV_REGNUM =3D 4161, > + > + /* Leave this as the last enum. */ > + RISCV_NUM_REGS > +}; > + > +#define RISCV_LAST_REGNUM (RISCV_NUM_REGS - 1) > + > +/* RISC-V specific per-architecture information. */ > +struct gdbarch_tdep > +{ > + int riscv_abi; > + enum auto_boolean supports_compressed_isa; > +}; > + > +static inline int > +riscv_isa_regsize (struct gdbarch *gdbarch) Can you move it to tdep.c file? > +{ > + int abi =3D gdbarch_tdep (gdbarch)->riscv_abi; > + > + switch (abi) > + { > + case RISCV_ABI_FLAG_RV32I: > + return 4; > + case RISCV_ABI_FLAG_RV64I: > + return 8; > + default: > + internal_error (__FILE__, __LINE__, _("unknown abi %i"), abi); > + return 4; > + } > +} > + --=20 Yao (=E9=BD=90=E5=B0=A7)