Line 172... |
Line 172... |
|
|
/* The list of available "set or1k " and "show or1k " commands */
|
/* The list of available "set or1k " and "show or1k " commands */
|
static struct cmd_list_element *htrace_cmdlist = NULL;
|
static struct cmd_list_element *htrace_cmdlist = NULL;
|
static struct cmd_list_element *htrace_mode_cmdlist = NULL;
|
static struct cmd_list_element *htrace_mode_cmdlist = NULL;
|
|
|
/* List of frame offsets of all registers saved in a function's
|
|
prologue. This is deduced by skip_prologue(). Offset is in bytes,
|
|
relative to sp. If value is -1, corresponding reg is not saved by
|
|
the prologue code. */
|
|
static int or1k_saved_reg_frame_offset[NUM_REGS];
|
|
|
|
/* Size of stack frame, in bytes. Produced by skip_prologue() */
|
|
static int frame_size;
|
|
|
|
struct htrace_struct or1k_htrace;
|
struct htrace_struct or1k_htrace;
|
struct hwatch_struct or1k_hwatch[MAX_HW_WATCHES];
|
struct hwatch_struct or1k_hwatch[MAX_HW_WATCHES];
|
int num_hw_watches = 0;
|
int num_hw_watches = 0;
|
|
|
/* Trace data. */
|
/* Trace data. */
|
Line 648... |
Line 639... |
memcpy (valbuf, ®buf[REGISTER_BYTE (VFRV_REGNUM)], TYPE_LENGTH (valtype));
|
memcpy (valbuf, ®buf[REGISTER_BYTE (VFRV_REGNUM)], TYPE_LENGTH (valtype));
|
else
|
else
|
memcpy (valbuf, ®buf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
|
memcpy (valbuf, ®buf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
|
}
|
}
|
|
|
|
/* Given a register index, return the first byte of the register within a remote
|
|
protocol packet. This applies only to serial targets, not jtag or sim. */
|
|
int
|
|
or1k_register_byte(regnum)
|
|
int regnum;
|
|
{
|
|
int byte_offset;
|
|
|
|
byte_offset = 0;
|
|
if (regnum < MAX_GPR_REGS) {
|
|
if (regnum < NUM_GPR_REGS)
|
|
return byte_offset + regnum * OR1K_GPR_REGSIZE;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
byte_offset += NUM_GPR_REGS * OR1K_GPR_REGSIZE;
|
|
regnum -= MAX_GPR_REGS;
|
|
if (regnum < MAX_VF_REGS) {
|
|
if (regnum < NUM_VF_REGS)
|
|
return byte_offset + regnum * OR1K_VF_REGSIZE;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
/* Must be PC, SR, or EPC */
|
|
byte_offset += NUM_VF_REGS * OR1K_VF_REGSIZE;
|
|
regnum -= MAX_VF_REGS;
|
|
if (regnum < 3)
|
|
return byte_offset + regnum * OR1K_SPR_REGSIZE;
|
|
|
|
/* Illegal register */
|
|
return -1;
|
|
}
|
|
|
|
/* Number of bytes of storage in the actual machine representation for
|
|
register N. NOTE: This indirectly defines the register size
|
|
transfered by the GDB protocol. If we have 64bit processor
|
|
implementation, GPR register raw size is 8B, otherwise 4B. */
|
|
int
|
|
or1k_register_raw_size(int regnum)
|
|
{
|
|
int byte_offset;
|
|
|
|
if (regnum < MAX_GPR_REGS) {
|
|
if (regnum < NUM_GPR_REGS)
|
|
return OR1K_GPR_REGSIZE;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
regnum -= MAX_GPR_REGS;
|
|
if (regnum < MAX_VF_REGS) {
|
|
if (regnum < NUM_VF_REGS)
|
|
return OR1K_VF_REGSIZE;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* Must be PC, SR, or EPC */
|
|
regnum -= MAX_VF_REGS;
|
|
if (regnum < 3)
|
|
return OR1K_SPR_REGSIZE;
|
|
|
|
/* Illegal register */
|
|
return 0;
|
|
}
|
|
|
|
/* Extra arch-specific data tied to frame */
|
|
struct frame_extra_info
|
|
{
|
|
/* Size of stack frame, in bytes. Produced by skip_prologue() */
|
|
int frame_size;
|
|
|
|
/* List of frame offsets of all registers saved in a function's
|
|
prologue. This is deduced by skip_prologue(). Offset is in bytes,
|
|
relative to sp. If value is -1, corresponding reg is not saved by
|
|
the prologue code. */
|
|
int saved_reg_frame_offset[NUM_REGS];
|
|
|
|
/* Address of first instruction after the last prologue instruction;
|
|
Note that there may be instructions from the function's body
|
|
intermingled with the prologue.
|
|
If value is -1, not initialized. */
|
|
CORE_ADDR after_prologue;
|
|
};
|
|
|
|
/* Initialize arch-specific frame data */
|
|
void
|
|
or1k_init_extra_frame_info (int fromleaf, struct frame_info *frame)
|
|
{
|
|
int i;
|
|
|
|
frame->extra_info = (struct frame_extra_info *)
|
|
frame_obstack_alloc (sizeof (struct frame_extra_info));
|
|
|
|
frame->extra_info->after_prologue = -1;
|
|
frame->extra_info->frame_size = -1;
|
|
for (i = 0; i < NUM_REGS; i++)
|
|
frame->extra_info->saved_reg_frame_offset[i] = -1;
|
|
}
|
|
|
/* For stack frame sizes less than 0x8000, the or1k version of gcc
|
/* For stack frame sizes less than 0x8000, the or1k version of gcc
|
emits the following prologue:
|
emits the following prologue:
|
|
|
l.addi r1, r1, -<STACK_FRAME_SIZE>
|
l.addi r1, r1, -<STACK_FRAME_SIZE>
|
l.sw <FP_OFFSET>(r1),r2
|
l.sw <FP_OFFSET>(r1),r2
|
Line 663... |
Line 756... |
; ...
|
; ...
|
|
|
*/
|
*/
|
|
|
/* FIXME: Does not work with frames greater than 0x7fff in size */
|
/* FIXME: Does not work with frames greater than 0x7fff in size */
|
|
|
|
/* If pframeless is non-NULL, only parse enough of the prologue to
|
|
determine if a function has a frame or not and return the result in
|
|
*pframeless. This may save some remote transactions with the
|
|
target. */
|
CORE_ADDR
|
CORE_ADDR
|
or1k_skip_prologue (CORE_ADDR pc)
|
or1k_skip_prologue (CORE_ADDR pc, struct frame_info *fi)
|
{
|
{
|
unsigned long insn;
|
unsigned long insn;
|
CORE_ADDR skip_pc;
|
CORE_ADDR skip_pc;
|
CORE_ADDR func_addr, func_end;
|
CORE_ADDR func_addr, func_end;
|
struct symtab_and_line sal;
|
struct symtab_and_line sal;
|
int i;
|
int i, frameless;
|
int offset = 0;
|
int offset = 0;
|
int rB, immediate, immediate_hi;
|
int rB, immediate, immediate_hi;
|
|
int* saved_reg_frame_offset;
|
|
|
for (i = 0; i < MAX_GPR_REGS; i++)
|
/* Check to see if prologue analysis is cached from prior call */
|
or1k_saved_reg_frame_offset[i] = -1;
|
if (fi && fi->extra_info->after_prologue != -1)
|
frame_size = -1;
|
return fi->extra_info->after_prologue;
|
|
|
|
if (fi)
|
|
saved_reg_frame_offset = &fi->extra_info->saved_reg_frame_offset[0];
|
|
|
/* Is there a prologue? */
|
/* Is there a prologue? */
|
insn = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
if ((insn & 0xFFFF0000) != 0x9c210000) /* l.addi r1,r1,I */
|
if ((insn & 0xFFFF0000) != 0x9c210000) /* l.addi r1,r1,I */
|
return pc;
|
goto done;
|
|
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
|
|
insn = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
if ((insn & 0xfc1ff800) != 0xd4011000) /* l.sw I(r1),r2 */
|
if ((insn & 0xfc1ff800) != 0xd4011000) /* l.sw I(r1),r2 */
|
return pc;
|
goto done;
|
immediate_hi = (insn & 0x03E00000) >> 10;
|
immediate_hi = (insn & 0x03E00000) >> 10;
|
immediate = (insn & 0x000007FF) | immediate_hi;
|
immediate = (insn & 0x000007FF) | immediate_hi;
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
or1k_saved_reg_frame_offset[2] = immediate;
|
if (fi)
|
|
saved_reg_frame_offset[2] = immediate;
|
|
|
insn = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
if ((insn & 0xFFFF0000) != 0x9c410000) /* l.addi r2,r1,I */
|
if ((insn & 0xFFFF0000) != 0x9c410000) /* l.addi r2,r1,I */
|
return pc;
|
goto done;
|
frame_size = insn & 0xFFFF;
|
if (fi)
|
|
fi->extra_info->frame_size = insn & 0xFFFF;
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
|
|
/* Skip stored registers. */
|
/* Skip stored registers. */
|
insn = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
while ((insn & 0xfc1f0000) == 0xd4010000) /* l.sw I(r1),rx */
|
while ((insn & 0xfc1f0000) == 0xd4010000) /* l.sw I(r1),rx */
|
Line 707... |
Line 812... |
rB = (insn & 0x0000F800) >> 11;
|
rB = (insn & 0x0000F800) >> 11;
|
immediate_hi = (insn & 0x03E00000) >> 10;
|
immediate_hi = (insn & 0x03E00000) >> 10;
|
immediate = (insn & 0x000007FF) | immediate_hi;
|
immediate = (insn & 0x000007FF) | immediate_hi;
|
|
|
/* get saved reg. */
|
/* get saved reg. */
|
or1k_saved_reg_frame_offset[rB] = immediate;
|
if (fi)
|
|
saved_reg_frame_offset[rB] = immediate;
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
insn = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
}
|
}
|
|
done:
|
|
if (fi)
|
|
fi->extra_info->after_prologue = pc;
|
return pc;
|
return pc;
|
}
|
}
|
|
|
/* Determines whether this function has frame. */
|
/* Determines whether this function has frame. */
|
|
|
int
|
int
|
or1k_frameless_function_invocation (struct frame_info *fi)
|
or1k_frameless_function_invocation (struct frame_info *fi)
|
{
|
{
|
CORE_ADDR func_start, after_prologue;
|
|
int frameless;
|
int frameless;
|
|
CORE_ADDR func_start, after_prologue;
|
func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
|
func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
|
after_prologue = SKIP_PROLOGUE (func_start);
|
|
|
|
/* If we don't skip pc, we don't have even shortest possible prologue. */
|
/* If we don't skip pc, we don't have even shortest possible prologue. */
|
|
after_prologue = or1k_skip_prologue (func_start, fi);
|
frameless = (after_prologue <= func_start);
|
frameless = (after_prologue <= func_start);
|
return frameless;
|
return frameless;
|
}
|
}
|
|
|
/* Given a GDB frame, determine the address of the calling function's frame.
|
/* Given a GDB frame, determine the address of the calling function's frame.
|
Line 826... |
Line 935... |
CORE_ADDR func_pc = get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET;
|
CORE_ADDR func_pc = get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET;
|
int pc_found = 0;
|
int pc_found = 0;
|
|
|
frame_saved_regs_zalloc (fi);
|
frame_saved_regs_zalloc (fi);
|
|
|
/* Skip prologue sets frame_size and or1k_saved_reg_frame_offset[],
|
/* Skip prologue sets frame_size and register frame save offsets
|
which will both be used shortly. */
|
which will both be used shortly. */
|
or1k_skip_prologue (func_pc);
|
or1k_skip_prologue (func_pc, fi);
|
|
|
/* If the frame_size is less than 0, we have hit an assembly
|
/* If the frame_size is less than 0, we have hit an assembly
|
routine which we can't traverse beyond. Let's give up here,
|
routine which we can't traverse beyond. Let's give up here,
|
because attempting to continue will only lead to trouble. */
|
because attempting to continue will only lead to trouble. */
|
if(frame_size < 0)
|
if(fi->extra_info->frame_size < 0)
|
{
|
{
|
printf("Found a function without a prologue at 0x%08x\n",func_pc);
|
printf("Found a function without a prologue at 0x%08x\n",func_pc);
|
printf("Frame pc was at 0x%08x\n",fi->pc);
|
printf("Frame pc was at 0x%08x\n",fi->pc);
|
return;
|
return;
|
}
|
}
|
|
|
for (i = 0; i < NUM_GPR_REGS + NUM_VF_REGS; i++)
|
for (i = 0; i < NUM_GPR_REGS + NUM_VF_REGS; i++)
|
if (or1k_saved_reg_frame_offset[i] >= 0)
|
if (fi->extra_info->saved_reg_frame_offset[i] >= 0)
|
fi->saved_regs[i] =
|
fi->saved_regs[i] =
|
fi->frame + (or1k_saved_reg_frame_offset[i] - frame_size);
|
fi->frame + (fi->extra_info->saved_reg_frame_offset[i] - fi->extra_info->frame_size);
|
|
|
/* We want to make sure we fill in the PC with the value of the
|
/* We want to make sure we fill in the PC with the value of the
|
r9 register from the NEXT frame, and that the value of r1 is
|
r9 register from the NEXT frame, and that the value of r1 is
|
the correct value of r1 for the next frame, which can be
|
the correct value of r1 for the next frame, which can be
|
calculated by adding the frame_size to the frame pointer. */
|
calculated by adding the frame_size to the frame pointer. */
|
fi->saved_regs[1] = fi->frame - frame_size;
|
fi->saved_regs[1] = fi->frame - fi->extra_info->frame_size;
|
|
|
if(fi->saved_regs[LR_REGNUM])
|
if(fi->saved_regs[LR_REGNUM])
|
fi->saved_regs[PC_REGNUM] = read_memory_integer(fi->saved_regs[LR_REGNUM],4);
|
fi->saved_regs[PC_REGNUM] = read_memory_integer(fi->saved_regs[LR_REGNUM],4);
|
else
|
else
|
fi->saved_regs[PC_REGNUM] = read_register(LR_REGNUM);
|
fi->saved_regs[PC_REGNUM] = read_register(LR_REGNUM);
|