gdb/nios2-tdep.c - gdb
Global variables defined
Data types defined
Functions defined
Source code
- #include "defs.h"
- #include "frame.h"
- #include "frame-unwind.h"
- #include "frame-base.h"
- #include "trad-frame.h"
- #include "dwarf2-frame.h"
- #include "symtab.h"
- #include "inferior.h"
- #include "gdbtypes.h"
- #include "gdbcore.h"
- #include "gdbcmd.h"
- #include "osabi.h"
- #include "target.h"
- #include "dis-asm.h"
- #include "regcache.h"
- #include "value.h"
- #include "symfile.h"
- #include "arch-utils.h"
- #include "floatformat.h"
- #include "infcall.h"
- #include "regset.h"
- #include "target-descriptions.h"
- #include "objfiles.h"
- #include "opcode/nios2.h"
- #include "nios2-tdep.h"
- #include "features/nios2.c"
- static int nios2_debug = 0;
- struct reg_value
- {
- int reg;
- unsigned int offset;
- };
- struct reg_saved
- {
- int basereg;
- CORE_ADDR addr;
- };
- struct nios2_unwind_cache
- {
-
- CORE_ADDR base;
-
- CORE_ADDR cfa;
-
- CORE_ADDR pc;
-
- int return_regnum;
-
- struct reg_value reg_value[NIOS2_NUM_REGS];
-
- struct reg_saved reg_saved[NIOS2_NUM_REGS];
- };
- static int nios2_dwarf2gdb_regno_map[] =
- {
- 0, 1, 2, 3,
- 4, 5, 6, 7,
- 8, 9, 10, 11,
- 12, 13, 14, 15,
- 16, 17, 18, 19,
- 20, 21, 22, 23,
- 24, 25,
- NIOS2_GP_REGNUM,
- NIOS2_SP_REGNUM,
- NIOS2_FP_REGNUM,
- NIOS2_EA_REGNUM,
- NIOS2_BA_REGNUM,
- NIOS2_RA_REGNUM,
- NIOS2_PC_REGNUM,
- NIOS2_STATUS_REGNUM,
- NIOS2_ESTATUS_REGNUM,
- NIOS2_BSTATUS_REGNUM,
- NIOS2_IENABLE_REGNUM,
- NIOS2_IPENDING_REGNUM,
- NIOS2_CPUID_REGNUM,
- 39,
- NIOS2_EXCEPTION_REGNUM,
- NIOS2_PTEADDR_REGNUM,
- NIOS2_TLBACC_REGNUM,
- NIOS2_TLBMISC_REGNUM,
- NIOS2_ECCINJ_REGNUM,
- NIOS2_BADADDR_REGNUM,
- NIOS2_CONFIG_REGNUM,
- NIOS2_MPUBASE_REGNUM,
- NIOS2_MPUACC_REGNUM
- };
- static int
- nios2_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int dw_reg)
- {
- if (dw_reg < 0 || dw_reg > NIOS2_NUM_REGS)
- {
- warning (_("Dwarf-2 uses unmapped register #%d"), dw_reg);
- return dw_reg;
- }
- return nios2_dwarf2gdb_regno_map[dw_reg];
- }
- static const char *const nios2_reg_names[NIOS2_NUM_REGS] =
- {
- "zero", "at", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "et", "bt", "gp", "sp", "fp", "ea", "sstatus", "ra",
- "pc",
- "status", "estatus", "bstatus", "ienable",
- "ipending", "cpuid", "ctl6", "exception",
- "pteaddr", "tlbacc", "tlbmisc", "eccinj",
- "badaddr", "config", "mpubase", "mpuacc"
- };
- static const char *
- nios2_register_name (struct gdbarch *gdbarch, int regno)
- {
-
- if (regno >= 0 && regno < NIOS2_NUM_REGS)
- return nios2_reg_names[regno];
- else
- return tdesc_register_name (gdbarch, regno);
- }
- static struct type *
- nios2_register_type (struct gdbarch *gdbarch, int regno)
- {
-
- if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
- return tdesc_register_type (gdbarch, regno);
- if (regno == NIOS2_PC_REGNUM)
- return builtin_type (gdbarch)->builtin_func_ptr;
- else if (regno == NIOS2_SP_REGNUM)
- return builtin_type (gdbarch)->builtin_data_ptr;
- else
- return builtin_type (gdbarch)->builtin_uint32;
- }
- static void
- nios2_extract_return_value (struct gdbarch *gdbarch, struct type *valtype,
- struct regcache *regcache, gdb_byte *valbuf)
- {
- int len = TYPE_LENGTH (valtype);
-
- if (len <= register_size (gdbarch, NIOS2_R2_REGNUM))
- regcache_cooked_read (regcache, NIOS2_R2_REGNUM, valbuf);
- else
- {
- gdb_assert (len <= (register_size (gdbarch, NIOS2_R2_REGNUM)
- + register_size (gdbarch, NIOS2_R3_REGNUM)));
- regcache_cooked_read (regcache, NIOS2_R2_REGNUM, valbuf);
- regcache_cooked_read (regcache, NIOS2_R3_REGNUM, valbuf + 4);
- }
- }
- static void
- nios2_store_return_value (struct gdbarch *gdbarch, struct type *valtype,
- struct regcache *regcache, const gdb_byte *valbuf)
- {
- int len = TYPE_LENGTH (valtype);
-
- if (len <= register_size (gdbarch, NIOS2_R2_REGNUM))
- regcache_cooked_write (regcache, NIOS2_R2_REGNUM, valbuf);
- else
- {
- gdb_assert (len <= (register_size (gdbarch, NIOS2_R2_REGNUM)
- + register_size (gdbarch, NIOS2_R3_REGNUM)));
- regcache_cooked_write (regcache, NIOS2_R2_REGNUM, valbuf);
- regcache_cooked_write (regcache, NIOS2_R3_REGNUM, valbuf + 4);
- }
- }
- static void
- nios2_setup_default (struct nios2_unwind_cache *cache)
- {
- int i;
- for (i = 0; i < NIOS2_NUM_REGS; i++)
- {
-
- cache->reg_value[i].reg = i;
- cache->reg_value[i].offset = 0;
-
- cache->reg_saved[i].basereg = -1;
- cache->reg_saved[i].addr = 0;
- }
- }
- static void
- nios2_init_cache (struct nios2_unwind_cache *cache, CORE_ADDR pc)
- {
- cache->base = 0;
- cache->cfa = 0;
- cache->pc = pc;
- cache->return_regnum = NIOS2_RA_REGNUM;
- nios2_setup_default (cache);
- }
- static const struct nios2_opcode *
- nios2_fetch_insn (struct gdbarch *gdbarch, CORE_ADDR pc,
- unsigned int *insnp)
- {
- LONGEST memword;
- unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
- unsigned int insn;
- if (!safe_read_memory_integer (pc, NIOS2_OPCODE_SIZE,
- gdbarch_byte_order (gdbarch), &memword))
- return NULL;
- insn = (unsigned int) memword;
- if (insnp)
- *insnp = insn;
- return nios2_find_opcode_hash (insn, mach);
- }
- static int
- nios2_match_add (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, int *rc)
- {
- if (op->match == MATCH_R1_ADD || op->match == MATCH_R1_MOV)
- {
- *ra = GET_IW_R_A (insn);
- *rb = GET_IW_R_B (insn);
- *rc = GET_IW_R_C (insn);
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_sub (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, int *rc)
- {
- if (op->match == MATCH_R1_SUB)
- {
- *ra = GET_IW_R_A (insn);
- *rb = GET_IW_R_B (insn);
- *rc = GET_IW_R_C (insn);
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_addi (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, int *imm)
- {
- if (op->match == MATCH_R1_ADDI)
- {
- *ra = GET_IW_I_A (insn);
- *rb = GET_IW_I_B (insn);
- *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_orhi (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, unsigned int *uimm)
- {
- if (op->match == MATCH_R1_ORHI)
- {
- *ra = GET_IW_I_A (insn);
- *rb = GET_IW_I_B (insn);
- *uimm = GET_IW_I_IMM16 (insn);
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_stw (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, int *imm)
- {
- if (op->match == MATCH_R1_STW || op->match == MATCH_R1_STWIO)
- {
- *ra = GET_IW_I_A (insn);
- *rb = GET_IW_I_B (insn);
- *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_ldw (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, int *imm)
- {
- if (op->match == MATCH_R1_LDW || op->match == MATCH_R1_LDWIO)
- {
- *ra = GET_IW_I_A (insn);
- *rb = GET_IW_I_B (insn);
- *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_rdctl (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rc)
- {
- if (op->match == MATCH_R1_RDCTL)
- {
- *ra = GET_IW_R_IMM5 (insn);
- *rc = GET_IW_R_C (insn);
- return 1;
- }
- return 0;
- }
- enum branch_condition {
- branch_none,
- branch_eq,
- branch_ne,
- branch_ge,
- branch_geu,
- branch_lt,
- branch_ltu
- };
- static int
- nios2_match_branch (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra, int *rb, int *imm,
- enum branch_condition *cond)
- {
- switch (op->match)
- {
- case MATCH_R1_BR:
- *cond = branch_none;
- break;
- case MATCH_R1_BEQ:
- *cond = branch_eq;
- break;
- case MATCH_R1_BNE:
- *cond = branch_ne;
- break;
- case MATCH_R1_BGE:
- *cond = branch_ge;
- break;
- case MATCH_R1_BGEU:
- *cond = branch_geu;
- break;
- case MATCH_R1_BLT:
- *cond = branch_lt;
- break;
- case MATCH_R1_BLTU:
- *cond = branch_ltu;
- break;
- default:
- return 0;
- }
- *imm = (signed) (GET_IW_I_IMM16 (insn) << 16) >> 16;
- *ra = GET_IW_I_A (insn);
- *rb = GET_IW_I_B (insn);
- return 1;
- }
- static int
- nios2_match_jmpi (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, unsigned int *uimm)
- {
- if (op->match == MATCH_R1_JMPI)
- {
- *uimm = GET_IW_J_IMM26 (insn) << 2;
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_calli (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, unsigned int *uimm)
- {
- if (op->match == MATCH_R1_CALL)
- {
- *uimm = GET_IW_J_IMM26 (insn) << 2;
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_jmpr (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra)
- {
- switch (op->match)
- {
- case MATCH_R1_JMP:
- *ra = GET_IW_I_A (insn);
- return 1;
- case MATCH_R1_RET:
- *ra = NIOS2_RA_REGNUM;
- return 1;
- case MATCH_R1_ERET:
- *ra = NIOS2_EA_REGNUM;
- return 1;
- case MATCH_R1_BRET:
- *ra = NIOS2_BA_REGNUM;
- return 1;
- default:
- return 0;
- }
- }
- static int
- nios2_match_callr (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, int *ra)
- {
- if (op->match == MATCH_R1_CALLR)
- {
- *ra = GET_IW_I_A (insn);
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_break (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, unsigned int *uimm)
- {
- if (op->match == MATCH_R1_BREAK)
- {
- *uimm = GET_IW_R_IMM5 (insn);
- return 1;
- }
- return 0;
- }
- static int
- nios2_match_trap (uint32_t insn, const struct nios2_opcode *op,
- unsigned long mach, unsigned int *uimm)
- {
- if (op->match == MATCH_R1_TRAP)
- {
- *uimm = GET_IW_R_IMM5 (insn);
- return 1;
- }
- return 0;
- }
- static int
- nios2_in_epilogue_p (struct gdbarch *gdbarch,
- CORE_ADDR current_pc,
- CORE_ADDR start_pc)
- {
- unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
-
- int ninsns, max_insns = 5;
- unsigned int insn;
- const struct nios2_opcode *op = NULL;
- unsigned int uimm;
- int imm;
- int ra, rb, rc;
- enum branch_condition cond;
- CORE_ADDR pc;
-
- if (current_pc <= start_pc)
- return 0;
-
- pc = current_pc - NIOS2_OPCODE_SIZE;
-
- for (ninsns = 0; ninsns < max_insns; ninsns++)
- {
- int ok = 0;
-
- op = nios2_fetch_insn (gdbarch, pc, &insn);
- if (op == NULL)
- return 0;
- pc += op->size;
-
- if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
- ok = (rb == NIOS2_SP_REGNUM);
- else if (nios2_match_add (insn, op, mach, &ra, &rb, &rc))
- ok = (rc == NIOS2_SP_REGNUM);
- else if (nios2_match_ldw (insn, op, mach, &ra, &rb, &imm))
- ok = (rb == NIOS2_SP_REGNUM);
- if (!ok)
- break;
- }
-
- if (ninsns == 0)
- return 0;
-
- if (ninsns == max_insns)
- return 1;
-
- if (nios2_match_jmpr (insn, op, mach, &ra)
- || nios2_match_jmpi (insn, op, mach, &uimm)
- || (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond)
- && cond == branch_none))
- return 1;
- return 0;
- }
- static int
- nios2_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- CORE_ADDR func_addr;
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
- return nios2_in_epilogue_p (gdbarch, pc, func_addr);
- return 0;
- }
- static CORE_ADDR
- nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
- const CORE_ADDR current_pc,
- struct nios2_unwind_cache *cache,
- struct frame_info *this_frame)
- {
-
- int ninsns, max_insns = 50;
- int regno;
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
-
- int base_reg = 0;
- struct reg_value *value = cache->reg_value;
- struct reg_value temp_value[NIOS2_NUM_REGS];
- int i;
-
- CORE_ADDR pc = start_pc;
-
- int exception_handler = 0;
-
- CORE_ADDR frame_high;
-
- CORE_ADDR prologue_end;
-
- int innermost = (this_frame ? (frame_relative_level (this_frame) == 0) : 1);
- if (nios2_debug)
- fprintf_unfiltered (gdb_stdlog,
- "{ nios2_analyze_prologue start=%s, current=%s ",
- paddress (gdbarch, start_pc),
- paddress (gdbarch, current_pc));
-
- nios2_setup_default (cache);
-
- prologue_end = start_pc;
- for (ninsns = 0; ninsns < max_insns; ninsns++)
- {
-
- uint32_t insn;
- const struct nios2_opcode *op;
- int ra, rb, rc, imm;
- unsigned int uimm;
- unsigned int reglist;
- int wb, ret;
- enum branch_condition cond;
- if (pc == current_pc)
- {
-
- memcpy (temp_value, value, sizeof (temp_value));
- value = temp_value;
- if (nios2_debug)
- fprintf_unfiltered (gdb_stdlog, "*");
- }
- op = nios2_fetch_insn (gdbarch, pc, &insn);
-
- if (op == NULL)
- break;
- pc += op->size;
- if (nios2_debug)
- fprintf_unfiltered (gdb_stdlog, "[%08X]", insn);
-
- if (nios2_match_add (insn, op, mach, &ra, &rb, &rc))
- {
-
- if (rc == NIOS2_SP_REGNUM
- && rb == 0
- && value[ra].reg == cache->reg_saved[NIOS2_SP_REGNUM].basereg)
- {
-
-
- for (i = 0 ; i < NIOS2_NUM_REGS ; i++)
- {
- if (cache->reg_saved[i].basereg == NIOS2_SP_REGNUM)
- cache->reg_saved[i].basereg = -1;
- if (value[i].reg == NIOS2_SP_REGNUM)
- value[i].reg = -1;
- }
-
- value[NIOS2_SP_REGNUM].reg = NIOS2_SP_REGNUM;
- value[NIOS2_SP_REGNUM].offset
- = (value[ra].offset
- - cache->reg_saved[NIOS2_SP_REGNUM].addr
- - 4);
- cache->reg_saved[NIOS2_SP_REGNUM].basereg = NIOS2_SP_REGNUM;
- cache->reg_saved[NIOS2_SP_REGNUM].addr = -4;
- }
- else if (rc == NIOS2_SP_REGNUM && ra == NIOS2_FP_REGNUM)
-
- break;
- else if (rc != 0)
- {
- if (value[rb].reg == 0)
- value[rc].reg = value[ra].reg;
- else if (value[ra].reg == 0)
- value[rc].reg = value[rb].reg;
- else
- value[rc].reg = -1;
- value[rc].offset = value[ra].offset + value[rb].offset;
- }
-
- if (rc == NIOS2_SP_REGNUM || rc == NIOS2_FP_REGNUM)
- prologue_end = pc;
- }
- else if (nios2_match_sub (insn, op, mach, &ra, &rb, &rc))
- {
-
- if (rc == NIOS2_SP_REGNUM && rb == NIOS2_SP_REGNUM
- && value[rc].reg != 0)
-
- break;
- else if (rc != 0)
- {
- if (value[rb].reg == 0)
- value[rc].reg = value[ra].reg;
- else
- value[rc].reg = -1;
- value[rc].offset = value[ra].offset - value[rb].offset;
- }
- }
- else if (nios2_match_addi (insn, op, mach, &ra, &rb, &imm))
- {
-
-
- if (rb == NIOS2_SP_REGNUM
- && (imm > 0 || value[ra].reg != NIOS2_SP_REGNUM))
- break;
-
- else if (rb == NIOS2_SP_REGNUM && ra == NIOS2_FP_REGNUM)
- break;
- if (rb != 0)
- {
- value[rb].reg = value[ra].reg;
- value[rb].offset = value[ra].offset + imm;
- }
-
- if (rb == NIOS2_SP_REGNUM || rb == NIOS2_FP_REGNUM)
- prologue_end = pc;
- }
- else if (nios2_match_orhi (insn, op, mach, &ra, &rb, &uimm))
- {
-
- if (rb != 0)
- {
- value[rb].reg = (value[ra].reg == 0) ? 0 : -1;
- value[rb].offset = value[ra].offset | (uimm << 16);
- }
- }
- else if (nios2_match_stw (insn, op, mach, &ra, &rb, &imm))
- {
-
-
- int orig = value[rb].reg;
- if (orig > 0
- && (value[rb].offset == 0
- || (orig == NIOS2_EA_REGNUM && value[rb].offset == -4))
- && ((value[ra].reg == NIOS2_SP_REGNUM
- && cache->reg_saved[orig].basereg != NIOS2_SP_REGNUM)
- || cache->reg_saved[orig].basereg == -1))
- {
- if (pc < current_pc)
- {
-
- cache->reg_saved[orig].basereg = value[ra].reg;
- cache->reg_saved[orig].addr = value[ra].offset + imm;
- }
- prologue_end = pc;
- if (orig == NIOS2_EA_REGNUM || orig == NIOS2_ESTATUS_REGNUM)
- exception_handler = 1;
- }
- else
-
- break;
- }
- else if (nios2_match_rdctl (insn, op, mach, &ra, &rc))
- {
-
- if (rc != 0)
- {
- value[rc].reg = NIOS2_STATUS_REGNUM + ra;
- value[rc].offset = 0;
- }
- }
- else if (nios2_match_calli (insn, op, mach, &uimm))
- {
- if (value[8].reg == NIOS2_RA_REGNUM
- && value[8].offset == 0
- && value[NIOS2_SP_REGNUM].reg == NIOS2_SP_REGNUM
- && value[NIOS2_SP_REGNUM].offset == 0)
- {
-
- for (i = 2 ; i <= 3 ; i++)
- value[i].reg = -1;
- for (i = 9 ; i <= 15 ; i++)
- value[i].reg = -1;
- value[NIOS2_RA_REGNUM].reg = -1;
- prologue_end = pc;
- }
-
- else
- break;
- }
- else if (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond))
- {
-
- if (ra != NIOS2_SP_REGNUM)
- break;
- else if (cond == branch_geu)
- {
-
- unsigned int next_insn;
- const struct nios2_opcode *next_op
- = nios2_fetch_insn (gdbarch, pc, &next_insn);
- if (next_op != NULL
- && nios2_match_break (next_insn, op, mach, &uimm))
- pc += next_op->size;
- else
- break;
- }
- else if (cond == branch_ltu)
- {
-
- unsigned int next_insn;
- const struct nios2_opcode *next_op
- = nios2_fetch_insn (gdbarch, pc + imm, &next_insn);
- if (next_op != NULL
- && nios2_match_break (next_insn, op, mach, &uimm))
- ;
- else
- break;
- }
- else
- break;
- }
-
- else if (nios2_match_callr (insn, op, mach, &ra)
- || nios2_match_jmpr (insn, op, mach, &ra)
- || nios2_match_jmpi (insn, op, mach, &uimm))
- break;
- }
-
- if (this_frame == NULL)
- return prologue_end;
-
- if (innermost && nios2_in_epilogue_p (gdbarch, current_pc, start_pc))
- nios2_setup_default (cache);
-
- if (exception_handler)
- cache->return_regnum = NIOS2_EA_REGNUM;
- if (nios2_debug)
- fprintf_unfiltered (gdb_stdlog, "\n-> retreg=%d, ", cache->return_regnum);
- if (cache->reg_value[NIOS2_FP_REGNUM].reg == NIOS2_SP_REGNUM)
-
- base_reg = NIOS2_FP_REGNUM;
- else if (cache->reg_value[NIOS2_SP_REGNUM].reg == NIOS2_SP_REGNUM)
-
- base_reg = NIOS2_SP_REGNUM;
- else
- {
-
- if (nios2_debug)
- fprintf_unfiltered (gdb_stdlog, "<can't reach cfa> }\n");
- return 0;
- }
- if (cache->reg_value[base_reg].offset == 0
- || cache->reg_saved[NIOS2_RA_REGNUM].basereg != NIOS2_SP_REGNUM
- || cache->reg_saved[cache->return_regnum].basereg != NIOS2_SP_REGNUM)
- {
-
- if (!innermost)
- {
-
- CORE_ADDR ra
- = get_frame_register_unsigned (this_frame, NIOS2_RA_REGNUM);
- if (ra == current_pc)
- {
- if (nios2_debug)
- fprintf_unfiltered
- (gdb_stdlog,
- "<noreturn ADJUST %s, r31@r%d+?>, r%d@r%d+?> }\n",
- paddress (gdbarch, cache->reg_value[base_reg].offset),
- cache->reg_saved[NIOS2_RA_REGNUM].basereg,
- cache->return_regnum,
- cache->reg_saved[cache->return_regnum].basereg);
- return 0;
- }
- }
- }
-
- cache->base = get_frame_register_unsigned (this_frame, base_reg);
-
- frame_high = cache->base - cache->reg_value[base_reg].offset;
-
- for (i = 0; i < NIOS2_NUM_REGS; i++)
- if (cache->reg_saved[i].basereg == NIOS2_SP_REGNUM)
- {
- cache->reg_saved[i].basereg = NIOS2_Z_REGNUM;
- cache->reg_saved[i].addr += frame_high;
- }
- for (i = 0; i < NIOS2_NUM_REGS; i++)
- if (cache->reg_saved[i].basereg == NIOS2_GP_REGNUM)
- {
- CORE_ADDR gp = get_frame_register_unsigned (this_frame,
- NIOS2_GP_REGNUM);
- for ( ; i < NIOS2_NUM_REGS; i++)
- if (cache->reg_saved[i].basereg == NIOS2_GP_REGNUM)
- {
- cache->reg_saved[i].basereg = NIOS2_Z_REGNUM;
- cache->reg_saved[i].addr += gp;
- }
- }
-
- if (cache->reg_saved[NIOS2_SP_REGNUM].basereg == NIOS2_Z_REGNUM)
- cache->cfa
- = read_memory_unsigned_integer (cache->reg_saved[NIOS2_SP_REGNUM].addr,
- 4, byte_order);
- else
- cache->cfa = frame_high;
-
- if (exception_handler)
- {
- cache->reg_saved[NIOS2_STATUS_REGNUM]
- = cache->reg_saved[NIOS2_ESTATUS_REGNUM];
- cache->reg_saved[NIOS2_ESTATUS_REGNUM].basereg = -1;
- }
- if (nios2_debug)
- fprintf_unfiltered (gdb_stdlog, "cfa=%s }\n",
- paddress (gdbarch, cache->cfa));
- return prologue_end;
- }
- static CORE_ADDR
- nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
- {
- CORE_ADDR func_addr;
- struct nios2_unwind_cache cache;
-
- if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (start_pc, post_prologue_pc);
- }
-
- nios2_init_cache (&cache, start_pc);
- return nios2_analyze_prologue (gdbarch, start_pc, start_pc, &cache, NULL);
- }
- static const gdb_byte*
- nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
- int *bp_size)
- {
- enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
- unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
-
- static const gdb_byte r1_breakpoint_le[] = {0xfa, 0xa7, 0x3d, 0x0};
- static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3d, 0xa7, 0xfa};
- *bp_size = NIOS2_OPCODE_SIZE;
- if (byte_order_for_code == BFD_ENDIAN_BIG)
- return r1_breakpoint_be;
- else
- return r1_breakpoint_le;
- }
- static int
- nios2_print_insn (bfd_vma memaddr, disassemble_info *info)
- {
- if (info->endian == BFD_ENDIAN_BIG)
- return print_insn_big_nios2 (memaddr, info);
- else
- return print_insn_little_nios2 (memaddr, info);
- }
- static CORE_ADDR
- nios2_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
- {
- return align_down (addr, 4);
- }
- static enum return_value_convention
- nios2_return_value (struct gdbarch *gdbarch, struct value *function,
- struct type *type, struct regcache *regcache,
- gdb_byte *readbuf, const gdb_byte *writebuf)
- {
- if (TYPE_LENGTH (type) > 8)
- return RETURN_VALUE_STRUCT_CONVENTION;
- if (readbuf)
- nios2_extract_return_value (gdbarch, type, regcache, readbuf);
- if (writebuf)
- nios2_store_return_value (gdbarch, type, regcache, writebuf);
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- static struct frame_id
- nios2_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
- {
- return frame_id_build
- (get_frame_register_unsigned (this_frame, NIOS2_SP_REGNUM),
- get_frame_pc (this_frame));
- }
- static CORE_ADDR
- nios2_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)
- {
- int argreg;
- int float_argreg;
- int argnum;
- int len = 0;
- int stack_offset = 0;
- CORE_ADDR func_addr = find_function_addr (function, NULL);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
- regcache_cooked_write_signed (regcache, NIOS2_RA_REGNUM, bp_addr);
-
- for (argnum = 0; argnum < nargs; argnum++)
- len += align_up (TYPE_LENGTH (value_type (args[argnum])), 4);
- sp -= len;
-
- argreg = NIOS2_FIRST_ARGREG;
-
- if (struct_return)
- regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- const gdb_byte *val;
- gdb_byte valbuf[MAX_REGISTER_SIZE];
- struct value *arg = args[argnum];
- struct type *arg_type = check_typedef (value_type (arg));
- int len = TYPE_LENGTH (arg_type);
- enum type_code typecode = TYPE_CODE (arg_type);
- val = value_contents (arg);
-
- while (len > 0)
- {
- int partial_len = (len < 4 ? len : 4);
- if (argreg <= NIOS2_LAST_ARGREG)
- {
-
- CORE_ADDR regval = extract_unsigned_integer (val, partial_len,
- byte_order);
- regcache_cooked_write_unsigned (regcache, argreg, regval);
- argreg++;
- }
- else
- {
-
- CORE_ADDR addr = sp + stack_offset;
- write_memory (addr, val, partial_len);
- stack_offset += align_up (partial_len, 4);
- }
- len -= partial_len;
- val += partial_len;
- }
- }
- regcache_cooked_write_signed (regcache, NIOS2_SP_REGNUM, sp);
-
- return sp;
- }
- static CORE_ADDR
- nios2_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
- {
- gdb_byte buf[4];
- frame_unwind_register (next_frame, NIOS2_PC_REGNUM, buf);
- return extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr);
- }
- static CORE_ADDR
- nios2_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
- {
- return frame_unwind_register_unsigned (this_frame, NIOS2_SP_REGNUM);
- }
- static struct nios2_unwind_cache *
- nios2_frame_unwind_cache (struct frame_info *this_frame,
- void **this_prologue_cache)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- CORE_ADDR current_pc;
- struct nios2_unwind_cache *cache;
- int i;
- if (*this_prologue_cache)
- return *this_prologue_cache;
- cache = FRAME_OBSTACK_ZALLOC (struct nios2_unwind_cache);
- *this_prologue_cache = cache;
-
- nios2_init_cache (cache, get_frame_func (this_frame));
-
- current_pc = get_frame_pc (this_frame);
- if (cache->pc != 0)
- nios2_analyze_prologue (gdbarch, cache->pc, current_pc, cache, this_frame);
- return cache;
- }
- static void
- nios2_frame_this_id (struct frame_info *this_frame, void **this_cache,
- struct frame_id *this_id)
- {
- struct nios2_unwind_cache *cache =
- nios2_frame_unwind_cache (this_frame, this_cache);
-
- if (cache->base == 0)
- return;
- *this_id = frame_id_build (cache->cfa, cache->pc);
- }
- static struct value *
- nios2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
- int regnum)
- {
- struct nios2_unwind_cache *cache =
- nios2_frame_unwind_cache (this_frame, this_cache);
- gdb_assert (regnum >= 0 && regnum < NIOS2_NUM_REGS);
-
- if (regnum == NIOS2_PC_REGNUM)
- regnum = cache->return_regnum;
- if (regnum == NIOS2_SP_REGNUM && cache->cfa)
- return frame_unwind_got_constant (this_frame, regnum, cache->cfa);
-
- if (cache->reg_saved[regnum].basereg == NIOS2_Z_REGNUM)
- return frame_unwind_got_memory (this_frame, regnum,
- cache->reg_saved[regnum].addr);
- return frame_unwind_got_register (this_frame, regnum, regnum);
- }
- static CORE_ADDR
- nios2_frame_base_address (struct frame_info *this_frame, void **this_cache)
- {
- struct nios2_unwind_cache *info
- = nios2_frame_unwind_cache (this_frame, this_cache);
- return info->base;
- }
- static const struct frame_unwind nios2_frame_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- nios2_frame_this_id,
- nios2_frame_prev_register,
- NULL,
- default_frame_sniffer
- };
- static const struct frame_base nios2_frame_base =
- {
- &nios2_frame_unwind,
- nios2_frame_base_address,
- nios2_frame_base_address,
- nios2_frame_base_address
- };
- static struct trad_frame_cache *
- nios2_stub_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 = get_frame_arch (this_frame);
- int num_regs = gdbarch_num_regs (gdbarch);
- if (*this_cache != NULL)
- return *this_cache;
- this_trad_cache = trad_frame_cache_zalloc (this_frame);
- *this_cache = this_trad_cache;
-
- trad_frame_set_reg_realreg (this_trad_cache,
- gdbarch_pc_regnum (gdbarch),
- NIOS2_RA_REGNUM);
-
- pc = get_frame_pc (this_frame);
- find_pc_partial_function (pc, NULL, &start_addr, NULL);
- stack_addr = get_frame_register_unsigned (this_frame, NIOS2_SP_REGNUM);
- trad_frame_set_id (this_trad_cache, frame_id_build (start_addr, stack_addr));
-
- trad_frame_set_this_base (this_trad_cache, stack_addr);
- return this_trad_cache;
- }
- static void
- nios2_stub_frame_this_id (struct frame_info *this_frame, void **this_cache,
- struct frame_id *this_id)
- {
- struct trad_frame_cache *this_trad_cache
- = nios2_stub_frame_cache (this_frame, this_cache);
- trad_frame_get_id (this_trad_cache, this_id);
- }
- static struct value *
- nios2_stub_frame_prev_register (struct frame_info *this_frame,
- void **this_cache, int regnum)
- {
- struct trad_frame_cache *this_trad_cache
- = nios2_stub_frame_cache (this_frame, this_cache);
- return trad_frame_get_register (this_trad_cache, this_frame, regnum);
- }
- static int
- nios2_stub_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame, void **cache)
- {
- gdb_byte dummy[4];
- struct obj_section *s;
- CORE_ADDR pc = get_frame_address_in_block (this_frame);
-
- if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
- return 1;
- if (in_plt_section (pc))
- return 1;
- return 0;
- }
- static const struct frame_unwind nios2_stub_frame_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- nios2_stub_frame_this_id,
- nios2_stub_frame_prev_register,
- NULL,
- nios2_stub_frame_sniffer
- };
- static CORE_ADDR
- nios2_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
- unsigned int insn;
- const struct nios2_opcode *op = nios2_fetch_insn (gdbarch, pc, &insn);
- int ra;
- int rb;
- int imm;
- unsigned int uimm;
- int wb, ret;
- enum branch_condition cond;
-
- if (op == NULL)
- return pc + NIOS2_OPCODE_SIZE;
- if (nios2_match_branch (insn, op, mach, &ra, &rb, &imm, &cond))
- {
- int ras = get_frame_register_signed (frame, ra);
- int rbs = get_frame_register_signed (frame, rb);
- unsigned int rau = get_frame_register_unsigned (frame, ra);
- unsigned int rbu = get_frame_register_unsigned (frame, rb);
- pc += op->size;
- switch (cond)
- {
- case branch_none:
- pc += imm;
- break;
- case branch_eq:
- if (ras == rbs)
- pc += imm;
- break;
- case branch_ne:
- if (ras != rbs)
- pc += imm;
- break;
- case branch_ge:
- if (ras >= rbs)
- pc += imm;
- break;
- case branch_geu:
- if (rau >= rbu)
- pc += imm;
- break;
- case branch_lt:
- if (ras < rbs)
- pc += imm;
- break;
- case branch_ltu:
- if (rau < rbu)
- pc += imm;
- break;
- default:
- break;
- }
- }
- else if (nios2_match_jmpi (insn, op, mach, &uimm)
- || nios2_match_calli (insn, op, mach, &uimm))
- pc = (pc & 0xf0000000) | uimm;
- else if (nios2_match_jmpr (insn, op, mach, &ra)
- || nios2_match_callr (insn, op, mach, &ra))
- pc = get_frame_register_unsigned (frame, ra);
- else if (nios2_match_trap (insn, op, mach, &uimm))
- {
- if (tdep->syscall_next_pc != NULL)
- return tdep->syscall_next_pc (frame);
- }
- else
- pc += op->size;
- return pc;
- }
- static int
- nios2_software_single_step (struct frame_info *frame)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- struct address_space *aspace = get_frame_address_space (frame);
- CORE_ADDR next_pc = nios2_get_next_pc (frame, get_frame_pc (frame));
- insert_single_step_breakpoint (gdbarch, aspace, next_pc);
- return 1;
- }
- static int
- nios2_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR jb_addr = get_frame_register_unsigned (frame, NIOS2_R4_REGNUM);
- gdb_byte buf[4];
- if (target_read_memory (jb_addr + (tdep->jb_pc * 4), buf, 4))
- return 0;
- *pc = extract_unsigned_integer (buf, 4, byte_order);
- return 1;
- }
- static struct gdbarch *
- nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
- {
- struct gdbarch *gdbarch;
- struct gdbarch_tdep *tdep;
- int register_bytes, i;
- struct tdesc_arch_data *tdesc_data = NULL;
- const struct target_desc *tdesc = info.target_desc;
- if (!tdesc_has_registers (tdesc))
-
- tdesc = tdesc_nios2;
-
- if (tdesc_has_registers (tdesc))
- {
- const struct tdesc_feature *feature;
- int valid_p;
- feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nios2.cpu");
- if (feature == NULL)
- return NULL;
- tdesc_data = tdesc_data_alloc ();
- valid_p = 1;
- for (i = 0; i < NIOS2_NUM_REGS; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
- nios2_reg_names[i]);
- if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
- }
-
- arches = gdbarch_list_lookup_by_info (arches, &info);
- if (arches != NULL)
- return arches->gdbarch;
-
- tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
- gdbarch = gdbarch_alloc (&info, tdep);
-
- tdep->jb_pc = -1;
-
- set_gdbarch_ptr_bit (gdbarch, 32);
- set_gdbarch_addr_bit (gdbarch, 32);
- 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_float_format (gdbarch, floatformats_ieee_single);
- set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
-
- set_gdbarch_num_regs (gdbarch, NIOS2_NUM_REGS);
- set_gdbarch_sp_regnum (gdbarch, NIOS2_SP_REGNUM);
- set_gdbarch_pc_regnum (gdbarch, NIOS2_PC_REGNUM);
- set_gdbarch_register_name (gdbarch, nios2_register_name);
- set_gdbarch_register_type (gdbarch, nios2_register_type);
-
- set_gdbarch_stab_reg_to_regnum (gdbarch, nios2_dwarf_reg_to_regnum);
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, nios2_dwarf_reg_to_regnum);
- set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-
- set_gdbarch_frame_align (gdbarch, nios2_frame_align);
- set_gdbarch_return_value (gdbarch, nios2_return_value);
- set_gdbarch_skip_prologue (gdbarch, nios2_skip_prologue);
- set_gdbarch_in_function_epilogue_p (gdbarch, nios2_in_function_epilogue_p);
- set_gdbarch_breakpoint_from_pc (gdbarch, nios2_breakpoint_from_pc);
- set_gdbarch_dummy_id (gdbarch, nios2_dummy_id);
- set_gdbarch_unwind_pc (gdbarch, nios2_unwind_pc);
- set_gdbarch_unwind_sp (gdbarch, nios2_unwind_sp);
-
- dwarf2_append_unwinders (gdbarch);
- frame_unwind_append_unwinder (gdbarch, &nios2_stub_frame_unwind);
- frame_unwind_append_unwinder (gdbarch, &nios2_frame_unwind);
-
- set_gdbarch_software_single_step (gdbarch, nios2_software_single_step);
-
- gdbarch_init_osabi (info, gdbarch);
- if (tdep->jb_pc >= 0)
- set_gdbarch_get_longjmp_target (gdbarch, nios2_get_longjmp_target);
- frame_base_set_default (gdbarch, &nios2_frame_base);
- set_gdbarch_print_insn (gdbarch, nios2_print_insn);
-
- set_gdbarch_push_dummy_call (gdbarch, nios2_push_dummy_call);
- if (tdesc_data)
- tdesc_use_registers (gdbarch, tdesc, tdesc_data);
- return gdbarch;
- }
- extern initialize_file_ftype _initialize_nios2_tdep;
- void
- _initialize_nios2_tdep (void)
- {
- gdbarch_register (bfd_arch_nios2, nios2_gdbarch_init, NULL);
- initialize_tdesc_nios2 ();
-
- add_setshow_boolean_cmd ("nios2", class_maintenance, &nios2_debug,
- _("Set Nios II debugging."),
- _("Show Nios II debugging."),
- _("When on, Nios II specific debugging is enabled."),
- NULL,
- NULL,
- &setdebuglist, &showdebuglist);
- }