|  | /* Target-dependent code for Lattice Mico32 processor, for GDB. | 
|  | Contributed by Jon Beniston <jon@beniston.com> | 
|  |  | 
|  | Copyright (C) 2009-2024 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "extract-store-integer.h" | 
|  | #include "frame.h" | 
|  | #include "frame-unwind.h" | 
|  | #include "frame-base.h" | 
|  | #include "inferior.h" | 
|  | #include "dis-asm.h" | 
|  | #include "symfile.h" | 
|  | #include "remote.h" | 
|  | #include "gdbcore.h" | 
|  | #include "sim/sim-lm32.h" | 
|  | #include "arch-utils.h" | 
|  | #include "regcache.h" | 
|  | #include "trad-frame.h" | 
|  | #include "reggroups.h" | 
|  | #include <algorithm> | 
|  | #include "gdbarch.h" | 
|  |  | 
|  | /* Make cgen names unique to prevent ODR conflicts with other targets.  */ | 
|  | #define GDB_CGEN_REMAP_PREFIX lm32 | 
|  | #include "cgen-remap.h" | 
|  | #include "opcodes/lm32-desc.h" | 
|  |  | 
|  | /* Macros to extract fields from an instruction.  */ | 
|  | #define LM32_OPCODE(insn)       ((insn >> 26) & 0x3f) | 
|  | #define LM32_REG0(insn)         ((insn >> 21) & 0x1f) | 
|  | #define LM32_REG1(insn)         ((insn >> 16) & 0x1f) | 
|  | #define LM32_REG2(insn)         ((insn >> 11) & 0x1f) | 
|  | #define LM32_IMM16(insn)        ((((long)insn & 0xffff) << 16) >> 16) | 
|  |  | 
|  | struct lm32_gdbarch_tdep : gdbarch_tdep_base | 
|  | { | 
|  | /* gdbarch target dependent data here.  Currently unused for LM32.  */ | 
|  | }; | 
|  |  | 
|  | struct lm32_frame_cache | 
|  | { | 
|  | /* The frame's base.  Used when constructing a frame ID.  */ | 
|  | CORE_ADDR base; | 
|  | CORE_ADDR pc; | 
|  | /* Size of frame.  */ | 
|  | int size; | 
|  | /* Table indicating the location of each and every register.  */ | 
|  | trad_frame_saved_reg *saved_regs; | 
|  | }; | 
|  |  | 
|  | /* Return whether a given register is in a given group.  */ | 
|  |  | 
|  | static int | 
|  | lm32_register_reggroup_p (struct gdbarch *gdbarch, int regnum, | 
|  | const struct reggroup *group) | 
|  | { | 
|  | if (group == general_reggroup) | 
|  | return ((regnum >= SIM_LM32_R0_REGNUM) && (regnum <= SIM_LM32_RA_REGNUM)) | 
|  | || (regnum == SIM_LM32_PC_REGNUM); | 
|  | else if (group == system_reggroup) | 
|  | return ((regnum >= SIM_LM32_BA_REGNUM) && (regnum <= SIM_LM32_EA_REGNUM)) | 
|  | || ((regnum >= SIM_LM32_EID_REGNUM) && (regnum <= SIM_LM32_IP_REGNUM)); | 
|  | return default_register_reggroup_p (gdbarch, regnum, group); | 
|  | } | 
|  |  | 
|  | /* Return a name that corresponds to the given register number.  */ | 
|  |  | 
|  | static const char * | 
|  | lm32_register_name (struct gdbarch *gdbarch, int reg_nr) | 
|  | { | 
|  | static const char *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", "ra", "ea", "ba", | 
|  | "PC", "EID", "EBA", "DEBA", "IE", "IM", "IP" | 
|  | }; | 
|  |  | 
|  | static_assert (ARRAY_SIZE (register_names) == SIM_LM32_NUM_REGS); | 
|  | return register_names[reg_nr]; | 
|  | } | 
|  |  | 
|  | /* Return type of register.  */ | 
|  |  | 
|  | static struct type * | 
|  | lm32_register_type (struct gdbarch *gdbarch, int reg_nr) | 
|  | { | 
|  | return builtin_type (gdbarch)->builtin_int32; | 
|  | } | 
|  |  | 
|  | /* Return non-zero if a register can't be written.  */ | 
|  |  | 
|  | static int | 
|  | lm32_cannot_store_register (struct gdbarch *gdbarch, int regno) | 
|  | { | 
|  | return (regno == SIM_LM32_R0_REGNUM) || (regno == SIM_LM32_EID_REGNUM); | 
|  | } | 
|  |  | 
|  | /* Analyze a function's prologue.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | lm32_analyze_prologue (struct gdbarch *gdbarch, | 
|  | CORE_ADDR pc, CORE_ADDR limit, | 
|  | struct lm32_frame_cache *info) | 
|  | { | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | unsigned long instruction; | 
|  |  | 
|  | /* Keep reading though instructions, until we come across an instruction | 
|  | that isn't likely to be part of the prologue.  */ | 
|  | info->size = 0; | 
|  | for (; pc < limit; pc += 4) | 
|  | { | 
|  |  | 
|  | /* Read an instruction.  */ | 
|  | instruction = read_memory_integer (pc, 4, byte_order); | 
|  |  | 
|  | if ((LM32_OPCODE (instruction) == OP_SW) | 
|  | && (LM32_REG0 (instruction) == SIM_LM32_SP_REGNUM)) | 
|  | { | 
|  | /* Any stack displaced store is likely part of the prologue. | 
|  | Record that the register is being saved, and the offset | 
|  | into the stack.  */ | 
|  | info->saved_regs[LM32_REG1 (instruction)].set_addr (LM32_IMM16 (instruction)); | 
|  | } | 
|  | else if ((LM32_OPCODE (instruction) == OP_ADDI) | 
|  | && (LM32_REG1 (instruction) == SIM_LM32_SP_REGNUM)) | 
|  | { | 
|  | /* An add to the SP is likely to be part of the prologue. | 
|  | Adjust stack size by whatever the instruction adds to the sp.  */ | 
|  | info->size -= LM32_IMM16 (instruction); | 
|  | } | 
|  | else if (			/* add fp,fp,sp */ | 
|  | ((LM32_OPCODE (instruction) == OP_ADD) | 
|  | && (LM32_REG2 (instruction) == SIM_LM32_FP_REGNUM) | 
|  | && (LM32_REG0 (instruction) == SIM_LM32_FP_REGNUM) | 
|  | && (LM32_REG1 (instruction) == SIM_LM32_SP_REGNUM)) | 
|  | /* mv fp,imm */ | 
|  | || ((LM32_OPCODE (instruction) == OP_ADDI) | 
|  | && (LM32_REG1 (instruction) == SIM_LM32_FP_REGNUM) | 
|  | && (LM32_REG0 (instruction) == SIM_LM32_R0_REGNUM))) | 
|  | { | 
|  | /* Likely to be in the prologue for functions that require | 
|  | a frame pointer.  */ | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Any other instruction is likely not to be part of the | 
|  | prologue.  */ | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | return pc; | 
|  | } | 
|  |  | 
|  | /* Return PC of first non prologue instruction, for the function at the | 
|  | specified address.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR func_addr, limit_pc; | 
|  | struct lm32_frame_cache frame_info; | 
|  | trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS]; | 
|  |  | 
|  | /* See if we can determine the end of the prologue via the symbol table. | 
|  | If so, then return either PC, or the PC after the prologue, whichever | 
|  | is greater.  */ | 
|  | if (find_pc_partial_function (pc, NULL, &func_addr, NULL)) | 
|  | { | 
|  | CORE_ADDR post_prologue_pc | 
|  | = skip_prologue_using_sal (gdbarch, func_addr); | 
|  | if (post_prologue_pc != 0) | 
|  | return std::max (pc, post_prologue_pc); | 
|  | } | 
|  |  | 
|  | /* Can't determine prologue from the symbol table, need to examine | 
|  | instructions.  */ | 
|  |  | 
|  | /* 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 use an arbitrary large number as the upper bound.  */ | 
|  | limit_pc = skip_prologue_using_sal (gdbarch, pc); | 
|  | if (limit_pc == 0) | 
|  | limit_pc = pc + 100;	/* Magic.  */ | 
|  |  | 
|  | frame_info.saved_regs = saved_regs; | 
|  | return lm32_analyze_prologue (gdbarch, pc, limit_pc, &frame_info); | 
|  | } | 
|  |  | 
|  | /* Create a breakpoint instruction.  */ | 
|  | constexpr gdb_byte lm32_break_insn[4] = { OP_RAISE << 2, 0, 0, 2 }; | 
|  |  | 
|  | typedef BP_MANIPULATION (lm32_break_insn) lm32_breakpoint; | 
|  |  | 
|  |  | 
|  | /* Setup registers and stack for faking a call to a function in the | 
|  | inferior.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | lm32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | 
|  | struct regcache *regcache, CORE_ADDR bp_addr, | 
|  | int nargs, struct value **args, CORE_ADDR sp, | 
|  | function_call_return_method return_method, | 
|  | CORE_ADDR struct_addr) | 
|  | { | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | int first_arg_reg = SIM_LM32_R1_REGNUM; | 
|  | int num_arg_regs = 8; | 
|  | int i; | 
|  |  | 
|  | /* Set the return address.  */ | 
|  | regcache_cooked_write_signed (regcache, SIM_LM32_RA_REGNUM, bp_addr); | 
|  |  | 
|  | /* If we're returning a large struct, a pointer to the address to | 
|  | store it at is passed as a first hidden parameter.  */ | 
|  | if (return_method == return_method_struct) | 
|  | { | 
|  | regcache_cooked_write_unsigned (regcache, first_arg_reg, struct_addr); | 
|  | first_arg_reg++; | 
|  | num_arg_regs--; | 
|  | sp -= 4; | 
|  | } | 
|  |  | 
|  | /* Setup parameters.  */ | 
|  | for (i = 0; i < nargs; i++) | 
|  | { | 
|  | struct value *arg = args[i]; | 
|  | struct type *arg_type = check_typedef (arg->type ()); | 
|  | gdb_byte *contents; | 
|  | ULONGEST val; | 
|  |  | 
|  | /* Promote small integer types to int.  */ | 
|  | switch (arg_type->code ()) | 
|  | { | 
|  | case TYPE_CODE_INT: | 
|  | case TYPE_CODE_BOOL: | 
|  | case TYPE_CODE_CHAR: | 
|  | case TYPE_CODE_RANGE: | 
|  | case TYPE_CODE_ENUM: | 
|  | if (arg_type->length () < 4) | 
|  | { | 
|  | arg_type = builtin_type (gdbarch)->builtin_int32; | 
|  | arg = value_cast (arg_type, arg); | 
|  | } | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* FIXME: Handle structures.  */ | 
|  |  | 
|  | contents = (gdb_byte *) arg->contents ().data (); | 
|  | val = extract_unsigned_integer (contents, arg_type->length (), | 
|  | byte_order); | 
|  |  | 
|  | /* First num_arg_regs parameters are passed by registers, | 
|  | and the rest are passed on the stack.  */ | 
|  | if (i < num_arg_regs) | 
|  | regcache_cooked_write_unsigned (regcache, first_arg_reg + i, val); | 
|  | else | 
|  | { | 
|  | write_memory_unsigned_integer (sp, arg_type->length (), byte_order, | 
|  | val); | 
|  | sp -= 4; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Update stack pointer.  */ | 
|  | regcache_cooked_write_signed (regcache, SIM_LM32_SP_REGNUM, sp); | 
|  |  | 
|  | /* Return adjusted stack pointer.  */ | 
|  | return sp; | 
|  | } | 
|  |  | 
|  | /* Extract return value after calling a function in the inferior.  */ | 
|  |  | 
|  | static void | 
|  | lm32_extract_return_value (struct type *type, struct regcache *regcache, | 
|  | gdb_byte *valbuf) | 
|  | { | 
|  | struct gdbarch *gdbarch = regcache->arch (); | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | ULONGEST l; | 
|  | CORE_ADDR return_buffer; | 
|  |  | 
|  | if (type->code () != TYPE_CODE_STRUCT | 
|  | && type->code () != TYPE_CODE_UNION | 
|  | && type->code () != TYPE_CODE_ARRAY && type->length () <= 4) | 
|  | { | 
|  | /* Return value is returned in a single register.  */ | 
|  | regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l); | 
|  | store_unsigned_integer (valbuf, type->length (), byte_order, l); | 
|  | } | 
|  | else if ((type->code () == TYPE_CODE_INT) && (type->length () == 8)) | 
|  | { | 
|  | /* 64-bit values are returned in a register pair.  */ | 
|  | regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l); | 
|  | memcpy (valbuf, &l, 4); | 
|  | regcache_cooked_read_unsigned (regcache, SIM_LM32_R2_REGNUM, &l); | 
|  | memcpy (valbuf + 4, &l, 4); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Aggregate types greater than a single register are returned | 
|  | in memory.  FIXME: Unless they are only 2 regs?.  */ | 
|  | regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l); | 
|  | return_buffer = l; | 
|  | read_memory (return_buffer, valbuf, type->length ()); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Write into appropriate registers a function return value of type | 
|  | TYPE, given in virtual format.  */ | 
|  | static void | 
|  | lm32_store_return_value (struct type *type, struct regcache *regcache, | 
|  | const gdb_byte *valbuf) | 
|  | { | 
|  | struct gdbarch *gdbarch = regcache->arch (); | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | ULONGEST val; | 
|  | int len = type->length (); | 
|  |  | 
|  | if (len <= 4) | 
|  | { | 
|  | val = extract_unsigned_integer (valbuf, len, byte_order); | 
|  | regcache_cooked_write_unsigned (regcache, SIM_LM32_R1_REGNUM, val); | 
|  | } | 
|  | else if (len <= 8) | 
|  | { | 
|  | val = extract_unsigned_integer (valbuf, 4, byte_order); | 
|  | regcache_cooked_write_unsigned (regcache, SIM_LM32_R1_REGNUM, val); | 
|  | val = extract_unsigned_integer (valbuf + 4, len - 4, byte_order); | 
|  | regcache_cooked_write_unsigned (regcache, SIM_LM32_R2_REGNUM, val); | 
|  | } | 
|  | else | 
|  | error (_("lm32_store_return_value: type length too large.")); | 
|  | } | 
|  |  | 
|  | /* Determine whether a functions return value is in a register or memory.  */ | 
|  | static enum return_value_convention | 
|  | lm32_return_value (struct gdbarch *gdbarch, struct value *function, | 
|  | struct type *valtype, struct regcache *regcache, | 
|  | gdb_byte *readbuf, const gdb_byte *writebuf) | 
|  | { | 
|  | enum type_code code = valtype->code (); | 
|  |  | 
|  | if (code == TYPE_CODE_STRUCT | 
|  | || code == TYPE_CODE_UNION | 
|  | || code == TYPE_CODE_ARRAY || valtype->length () > 8) | 
|  | return RETURN_VALUE_STRUCT_CONVENTION; | 
|  |  | 
|  | if (readbuf) | 
|  | lm32_extract_return_value (valtype, regcache, readbuf); | 
|  | if (writebuf) | 
|  | lm32_store_return_value (valtype, regcache, writebuf); | 
|  |  | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  |  | 
|  | /* Put here the code to store, into fi->saved_regs, the addresses of | 
|  | the saved registers of frame described by FRAME_INFO.  This | 
|  | includes special registers such as pc and fp saved in special ways | 
|  | in the stack frame.  sp is even more special: the address we return | 
|  | for it IS the sp for the next frame.  */ | 
|  |  | 
|  | static struct lm32_frame_cache * | 
|  | lm32_frame_cache (const frame_info_ptr &this_frame, void **this_prologue_cache) | 
|  | { | 
|  | CORE_ADDR current_pc; | 
|  | ULONGEST prev_sp; | 
|  | ULONGEST this_base; | 
|  | struct lm32_frame_cache *info; | 
|  | int i; | 
|  |  | 
|  | if ((*this_prologue_cache)) | 
|  | return (struct lm32_frame_cache *) (*this_prologue_cache); | 
|  |  | 
|  | info = FRAME_OBSTACK_ZALLOC (struct lm32_frame_cache); | 
|  | (*this_prologue_cache) = info; | 
|  | info->saved_regs = trad_frame_alloc_saved_regs (this_frame); | 
|  |  | 
|  | info->pc = get_frame_func (this_frame); | 
|  | current_pc = get_frame_pc (this_frame); | 
|  | lm32_analyze_prologue (get_frame_arch (this_frame), | 
|  | info->pc, current_pc, info); | 
|  |  | 
|  | /* Compute the frame's base, and the previous frame's SP.  */ | 
|  | this_base = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM); | 
|  | prev_sp = this_base + info->size; | 
|  | info->base = this_base; | 
|  |  | 
|  | /* Convert callee save offsets into addresses.  */ | 
|  | for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++) | 
|  | { | 
|  | if (info->saved_regs[i].is_addr ()) | 
|  | info->saved_regs[i].set_addr (this_base + info->saved_regs[i].addr ()); | 
|  | } | 
|  |  | 
|  | /* The call instruction moves the caller's PC in the callee's RA register. | 
|  | Since this is an unwind, do the reverse.  Copy the location of RA register | 
|  | into PC (the address / regnum) so that a request for PC will be | 
|  | converted into a request for the RA register.  */ | 
|  | info->saved_regs[SIM_LM32_PC_REGNUM] = info->saved_regs[SIM_LM32_RA_REGNUM]; | 
|  |  | 
|  | /* The previous frame's SP needed to be computed.  Save the computed | 
|  | value.  */ | 
|  | info->saved_regs[SIM_LM32_SP_REGNUM].set_value (prev_sp); | 
|  |  | 
|  | return info; | 
|  | } | 
|  |  | 
|  | static void | 
|  | lm32_frame_this_id (const frame_info_ptr &this_frame, void **this_cache, | 
|  | struct frame_id *this_id) | 
|  | { | 
|  | struct lm32_frame_cache *cache = lm32_frame_cache (this_frame, this_cache); | 
|  |  | 
|  | /* This marks the outermost frame.  */ | 
|  | if (cache->base == 0) | 
|  | return; | 
|  |  | 
|  | (*this_id) = frame_id_build (cache->base, cache->pc); | 
|  | } | 
|  |  | 
|  | static struct value * | 
|  | lm32_frame_prev_register (const frame_info_ptr &this_frame, | 
|  | void **this_prologue_cache, int regnum) | 
|  | { | 
|  | struct lm32_frame_cache *info; | 
|  |  | 
|  | info = lm32_frame_cache (this_frame, this_prologue_cache); | 
|  | return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); | 
|  | } | 
|  |  | 
|  | static const struct frame_unwind lm32_frame_unwind = { | 
|  | "lm32 prologue", | 
|  | NORMAL_FRAME, | 
|  | default_frame_unwind_stop_reason, | 
|  | lm32_frame_this_id, | 
|  | lm32_frame_prev_register, | 
|  | NULL, | 
|  | default_frame_sniffer | 
|  | }; | 
|  |  | 
|  | static CORE_ADDR | 
|  | lm32_frame_base_address (const frame_info_ptr &this_frame, void **this_cache) | 
|  | { | 
|  | struct lm32_frame_cache *info = lm32_frame_cache (this_frame, this_cache); | 
|  |  | 
|  | return info->base; | 
|  | } | 
|  |  | 
|  | static const struct frame_base lm32_frame_base = { | 
|  | &lm32_frame_unwind, | 
|  | lm32_frame_base_address, | 
|  | lm32_frame_base_address, | 
|  | lm32_frame_base_address | 
|  | }; | 
|  |  | 
|  | static CORE_ADDR | 
|  | lm32_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) | 
|  | { | 
|  | /* Align to the size of an instruction (so that they can safely be | 
|  | pushed onto the stack.  */ | 
|  | return sp & ~3; | 
|  | } | 
|  |  | 
|  | static struct gdbarch * | 
|  | lm32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | 
|  | { | 
|  | /* If there is already a candidate, use it.  */ | 
|  | arches = gdbarch_list_lookup_by_info (arches, &info); | 
|  | if (arches != NULL) | 
|  | return arches->gdbarch; | 
|  |  | 
|  | /* None found, create a new architecture from the information provided.  */ | 
|  | gdbarch *gdbarch | 
|  | = gdbarch_alloc (&info, gdbarch_tdep_up (new lm32_gdbarch_tdep)); | 
|  |  | 
|  | /* Type sizes.  */ | 
|  | 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_float_bit (gdbarch, 32); | 
|  | set_gdbarch_double_bit (gdbarch, 64); | 
|  | set_gdbarch_long_double_bit (gdbarch, 64); | 
|  | set_gdbarch_ptr_bit (gdbarch, 32); | 
|  |  | 
|  | /* Register info.  */ | 
|  | set_gdbarch_num_regs (gdbarch, SIM_LM32_NUM_REGS); | 
|  | set_gdbarch_sp_regnum (gdbarch, SIM_LM32_SP_REGNUM); | 
|  | set_gdbarch_pc_regnum (gdbarch, SIM_LM32_PC_REGNUM); | 
|  | set_gdbarch_register_name (gdbarch, lm32_register_name); | 
|  | set_gdbarch_register_type (gdbarch, lm32_register_type); | 
|  | set_gdbarch_cannot_store_register (gdbarch, lm32_cannot_store_register); | 
|  |  | 
|  | /* Frame info.  */ | 
|  | set_gdbarch_skip_prologue (gdbarch, lm32_skip_prologue); | 
|  | set_gdbarch_inner_than (gdbarch, core_addr_lessthan); | 
|  | set_gdbarch_decr_pc_after_break (gdbarch, 0); | 
|  | set_gdbarch_frame_args_skip (gdbarch, 0); | 
|  |  | 
|  | /* Frame unwinding.  */ | 
|  | set_gdbarch_frame_align (gdbarch, lm32_frame_align); | 
|  | frame_base_set_default (gdbarch, &lm32_frame_base); | 
|  | frame_unwind_append_unwinder (gdbarch, &lm32_frame_unwind); | 
|  |  | 
|  | /* Breakpoints.  */ | 
|  | set_gdbarch_breakpoint_kind_from_pc (gdbarch, lm32_breakpoint::kind_from_pc); | 
|  | set_gdbarch_sw_breakpoint_from_kind (gdbarch, lm32_breakpoint::bp_from_kind); | 
|  | set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); | 
|  |  | 
|  | /* Calling functions in the inferior.  */ | 
|  | set_gdbarch_push_dummy_call (gdbarch, lm32_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, lm32_return_value); | 
|  |  | 
|  | set_gdbarch_register_reggroup_p (gdbarch, lm32_register_reggroup_p); | 
|  |  | 
|  | return gdbarch; | 
|  | } | 
|  |  | 
|  | void _initialize_lm32_tdep (); | 
|  | void | 
|  | _initialize_lm32_tdep () | 
|  | { | 
|  | gdbarch_register (bfd_arch_lm32, lm32_gdbarch_init); | 
|  | } |