Line 178... |
Line 178... |
|
|
/* 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 all saved register addresses, produced by skip_prologue.
|
/* List of frame offsets of all registers saved in a function's
|
Relative address to sp, not used if 0. */
|
prologue. This is deduced by skip_prologue(). Offset is in bytes,
|
static int or1k_saved_reg_addr[NUM_REGS];
|
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;
|
|
|
Line 650... |
Line 655... |
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));
|
}
|
}
|
|
|
/* The or1k cc defines the following
|
/* For stack frame sizes less than 0x8000, the or1k version of gcc
|
prologue:
|
emits the following prologue:
|
00000000 <_proc1>:
|
|
0: d7 e1 17 e4 l.sw 0xffffffe4(r1),r2
|
l.addi r1, r1, -<STACK_FRAME_SIZE>
|
4: 9c 41 00 00 l.addi r2,r1,0x0
|
l.sw <FP_OFFSET>(r1),r2
|
8: 9c 21 ff e8 l.addi r1,r1,0xffffffe8
|
l.addi r2, r1, <STACK_FRAME_SIZE>
|
c: d7 e2 1f f8 l.sw 0xfffffff8(r2),r3
|
|
10: d7 e2 27 f4 l.sw 0xfffffff4(r2),r4
|
; Save regs that will be clobbered
|
14: 84 82 ff f8 l.lwz r4,0xfffffff8(r2)
|
l.sw <OFFSET_Rx>(r1),rx
|
18: 9d 24 00 00 l.addi r9,r4,0x0
|
l.sw <OFFSET_Ry>(r1),ry
|
1c: 00 00 00 02 l.j 0x2
|
; ...
|
20: 15 00 00 00 l.nop
|
|
|
|
00000024 <_L2>:
|
|
24: 84 41 ff fc l.lwz r2,0xfffffffc(r1)
|
|
28: 48 00 58 00 l.jalr r11
|
|
2c: 9c 21 00 18 l.addi r1,r1,0x18 */
|
|
|
|
|
*/
|
|
|
|
/* FIXME: Does not work with frames greater than 0x7fff in size */
|
CORE_ADDR
|
CORE_ADDR
|
or1k_skip_prologue (CORE_ADDR pc)
|
or1k_skip_prologue (CORE_ADDR pc)
|
{
|
{
|
unsigned long inst;
|
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;
|
int offset = 0;
|
int offset = 0;
|
|
int rB, immediate, immediate_hi;
|
|
|
for (i = 0; i < MAX_GPR_REGS; i++)
|
for (i = 0; i < MAX_GPR_REGS; i++)
|
or1k_saved_reg_addr[i] = -1;
|
or1k_saved_reg_frame_offset[i] = -1;
|
|
frame_size = -1;
|
|
|
/* Is there a prologue? */
|
/* Is there a prologue? */
|
inst = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
if ((inst & 0xfc1ff800) != 0xd4011000) return pc; /* l.sw I(r1),r2 */
|
if ((insn & 0xFFFF0000) != 0x9c210000) /* l.addi r1,r1,I */
|
or1k_saved_reg_addr[2] = offset++;
|
return pc;
|
inst = or1k_fetch_instruction (pc + OR1K_INSTLEN);
|
pc += OR1K_INSTLEN;
|
if ((inst & 0xFFFF0000) != 0x9c410000) return pc; /* l.addi r2,r1,I */
|
|
pc += 2 * OR1K_INSTLEN;
|
insn = or1k_fetch_instruction (pc);
|
inst = or1k_fetch_instruction (pc);
|
if ((insn & 0xfc1ff800) != 0xd4011000) /* l.sw I(r1),r2 */
|
if ((inst & 0xFFFF0000) != 0x9c210000) return pc; /* l.addi r1,r1,I */
|
return pc;
|
|
immediate_hi = (insn & 0x03E00000) >> 10;
|
|
immediate = (insn & 0x000007FF) | immediate_hi;
|
|
pc += OR1K_INSTLEN;
|
|
or1k_saved_reg_frame_offset[2] = immediate;
|
|
|
|
insn = or1k_fetch_instruction (pc);
|
|
if ((insn & 0xFFFF0000) != 0x9c410000) /* l.addi r2,r1,I */
|
|
return pc;
|
|
frame_size = insn & 0xFFFF;
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
|
|
/* Skip stored registers. */
|
/* Skip stored registers. */
|
inst = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
while ((inst & 0xfc1ff800) != 0xd4020000) /* l.sw 0x0(r2),rx */
|
while ((insn & 0xfc1f0000) == 0xd4010000) /* l.sw I(r1),rx */
|
{
|
{
|
|
rB = (insn & 0x0000F800) >> 11;
|
|
immediate_hi = (insn & 0x03E00000) >> 10;
|
|
immediate = (insn & 0x000007FF) | immediate_hi;
|
|
|
/* get saved reg. */
|
/* get saved reg. */
|
or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
|
or1k_saved_reg_frame_offset[rB] = immediate;
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
inst = or1k_fetch_instruction (pc);
|
insn = or1k_fetch_instruction (pc);
|
}
|
}
|
return pc;
|
return pc;
|
}
|
}
|
|
|
/* Determines whether this function has frame. */
|
/* Determines whether this function has frame. */
|
Line 727... |
Line 744... |
|
|
CORE_ADDR
|
CORE_ADDR
|
or1k_frame_chain (frame)
|
or1k_frame_chain (frame)
|
struct frame_info *frame;
|
struct frame_info *frame;
|
{
|
{
|
CORE_ADDR fp;
|
CORE_ADDR fp = 0;
|
if (USE_GENERIC_DUMMY_FRAMES)
|
if (USE_GENERIC_DUMMY_FRAMES)
|
{
|
{
|
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
|
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
|
/* dummy frame same as caller's frame */
|
/* dummy frame same as caller's frame */
|
return frame->frame;
|
return frame->frame;
|
Line 754... |
Line 771... |
unsigned long func_pc = get_pc_function_start(frame->pc);
|
unsigned long func_pc = get_pc_function_start(frame->pc);
|
unsigned long insn = read_memory_integer(func_pc,4);
|
unsigned long insn = read_memory_integer(func_pc,4);
|
int i;
|
int i;
|
int offset = 0;
|
int offset = 0;
|
|
|
/* The first instruction should be the number of bytes
|
/* The first instruction should tell us the number of bytes
|
in our frame. If it isn't we're in trouble because
|
in our frame. If it isn't we're in trouble because
|
the function is without a prologue... */
|
the function is without a prologue... */
|
if(((insn & 0xFC000000) == 0x9C000000) &&
|
if ((insn & 0xFFFF0000) == 0x9c210000) /* l.addi r1,r1,I */
|
((insn & 0x03E00000) == 0x00200000) &&
|
|
((insn & 0x001F0000) == 0x00010000))
|
|
{
|
{
|
short off = insn & 0xFFFF;
|
/* Sign extend immediate */
|
|
int immediate = (long)(insn << 16) >> 16;
|
|
int frame_size = -immediate;
|
|
|
/* Look for the storage of the frame pointer in the
|
/* Look for the storage of the frame pointer in the
|
function prologue.. */
|
function prologue.. */
|
for(i=1;i<20;i++)
|
unsigned long insn = read_memory_integer(func_pc+4,4);
|
{
|
|
unsigned long insn = read_memory_integer(func_pc+4*i,4);
|
|
|
|
/* If bits are 31 - 26 are %110101,
|
/* If bits are 31 - 26 are %110101,
|
and bits 20 - 16 are %00001,
|
and bits 20 - 16 are %00001,
|
and bits 15 - 11 are %00010,
|
and bits 15 - 11 are %00010,
|
then our frame pointer lies at the offset specified
|
then our frame pointer lies at the offset specified
|
Line 783... |
Line 798... |
int idx_h = (insn & 0x03E00000) >> 10;
|
int idx_h = (insn & 0x03E00000) >> 10;
|
int idx = (insn & 0x000007FF) | idx_h;
|
int idx = (insn & 0x000007FF) | idx_h;
|
|
|
if(code == 0x35 && r1 == 1 && r2 == 2)
|
if(code == 0x35 && r1 == 1 && r2 == 2)
|
{
|
{
|
offset = off + idx;
|
offset = idx - frame_size;
|
break;
|
fp = read_memory_integer (frame->frame + offset, 4);
|
}
|
|
}
|
}
|
}
|
}
|
|
|
fp = read_memory_integer (frame->frame + offset, 4);
|
|
}
|
}
|
|
|
if (USE_GENERIC_DUMMY_FRAMES)
|
if (USE_GENERIC_DUMMY_FRAMES)
|
{
|
{
|
CORE_ADDR fpp, lr;
|
CORE_ADDR fpp, lr;
|
Line 817... |
Line 829... |
or1k_init_saved_regs (struct frame_info *fi)
|
or1k_init_saved_regs (struct frame_info *fi)
|
{
|
{
|
int i;
|
int i;
|
CORE_ADDR frame_addr;
|
CORE_ADDR frame_addr;
|
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 frame_size;
|
|
int pc_found = 0;
|
int pc_found = 0;
|
|
|
frame_saved_regs_zalloc (fi);
|
frame_saved_regs_zalloc (fi);
|
|
|
/* Skip prologue sets or1k_saved_reg_addr[], we will use it later. */
|
/* Skip prologue sets frame_size and or1k_saved_reg_frame_offset[],
|
|
which will both be used shortly. */
|
or1k_skip_prologue (func_pc);
|
or1k_skip_prologue (func_pc);
|
|
|
frame_size = or1k_saved_reg_addr[1];
|
|
or1k_saved_reg_addr[1] = -1;
|
|
|
|
/* 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(frame_size < 0)
|
{
|
{
|
Line 839... |
Line 848... |
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_addr[i] >= 0)
|
if (or1k_saved_reg_frame_offset[i] >= 0)
|
fi->saved_regs[i] = fi->frame - or1k_saved_reg_addr[i];
|
fi->saved_regs[i] =
|
|
fi->frame + (or1k_saved_reg_frame_offset[i] - 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. */
|