Line 110... |
Line 110... |
"ZERO", "SP", "FP", "A0", "A1", "A2", "A3", "A4",
|
"ZERO", "SP", "FP", "A0", "A1", "A2", "A3", "A4",
|
"A5", "LR", "R10", "RV", "R12", "R13", "R14", "R15",
|
"A5", "LR", "R10", "RV", "R12", "R13", "R14", "R15",
|
"R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
|
"R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
|
"R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
|
"R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
|
|
|
|
/* Modified by CZ 12/09/01 */
|
/* vector/floating point registers */
|
/* vector/floating point registers */
|
"VFA0", "VFA1", "VFA2", "VFA3", "VFA4", "VFA5", "VFRV ", "VFR7",
|
"VFA0", "VFA1", "VFA2", "VFA3", "VFA4", "VFA5", "VFRV ", "VFR7",
|
"VFR8", "VFR9", "VFR10", "VFR11", "VFR12", "VFR13", "VFR14", "VFR15",
|
"VFR8", "VFR9", "VFR10", "VFR11", "VFR12", "VFR13", "VFR14", "VFR15",
|
"VFR16", "VFR17", "VFR18", "VFR19", "VFR20", "VFR21", "VFR22", "VFR23",
|
"VFR16", "VFR17", "VFR18", "VFR19", "VFR20", "VFR21", "VFR22", "VFR23",
|
"VFR24", "VFR25", "VFR26", "VFR27", "VFR28", "VFR29", "VFR30", "VFR31",
|
"VFR24", "VFR25", "VFR26", "VFR27", "VFR28", "VFR29", "VFR30", "VFR31",
|
"PC", "SR", "EPCR"
|
"PC", "SR", "EPCR", "ExPC", "ExEAR", "ExSR"
|
};
|
};
|
|
|
static char *or1k_group_names[] = {
|
static char *or1k_group_names[] = {
|
"SYS", "DMMU", "IMMU", "DCACHE", "ICACHE", "MAC", "DEBUG", "PERF", "POWER",
|
"SYS", "DMMU", "IMMU", "DCACHE", "ICACHE", "MAC", "DEBUG", "PERF", "POWER",
|
"PIC", "TIMER"
|
"PIC", "TIMER"
|
Line 131... |
Line 132... |
char *name;
|
char *name;
|
char *string;
|
char *string;
|
} or1k_signals [NUM_OR1K_SIGNALS + 1] =
|
} or1k_signals [NUM_OR1K_SIGNALS + 1] =
|
{
|
{
|
{"RSTE", "Reset Exception"},
|
{"RSTE", "Reset Exception"},
|
|
{"BUSE", "Bus Error" },
|
{"DFPE", "Data Page Fault Exception"},
|
{"DFPE", "Data Page Fault Exception"},
|
{"IFPE", "Instruction Page Fault Exception"},
|
{"IFPE", "Instruction Page Fault Exception"},
|
{"LPINTE", "Low Priority Interrupt Exception"},
|
{"LPINTE", "Low Priority Interrupt Exception"},
|
{"AE", "Alignment Exception"},
|
{"AE", "Alignment Exception"},
|
|
{"ILINSE" "Illegal Instruction" },
|
{"HPINTE", "High Priority Interrupt Exception"},
|
{"HPINTE", "High Priority Interrupt Exception"},
|
{"DME", "DTLB Miss Exception"},
|
{"DME", "DTLB Miss Exception"},
|
{"IME", "ITLB Miss Exception"},
|
{"IME", "ITLB Miss Exception"},
|
{"RE", "Range Exception"},
|
{"RE", "Range Exception"},
|
{"SCE", "SCE Exception"},
|
{"SCE", "SCE Exception"},
|
|
{"BRKPTE", "Breakpoint Exception"},
|
|
{"TRAPE", "Trap Exception"},
|
{NULL, NULL}
|
{NULL, NULL}
|
};
|
};
|
|
|
const char *compare_to_names[NUM_CT_NAMES] =
|
const char *compare_to_names[NUM_CT_NAMES] =
|
{
|
{
|
Line 188... |
Line 193... |
|
|
/* Previous values for buffer display. */
|
/* Previous values for buffer display. */
|
static int prev_length = 10;
|
static int prev_length = 10;
|
static int prev_from = 0;
|
static int prev_from = 0;
|
|
|
|
/* Define NEW_PC_HANDLING if you want to use the new style routines
|
|
where control is given to the debug interface AFTER the exception
|
|
has already been taken. */
|
|
|
|
#ifdef NEW_PC_HANDLING
|
|
|
|
/* Specialized read_pc routine. Looks at returned value. If value
|
|
is detected inside the breakpoint exception vector, the actual
|
|
value stored in EPC is returned instead. The breakpoint exception
|
|
vector should consist of nothing more than an RTE and a NOP. Note
|
|
that this mechanism prohibits the use of GDB in an environment
|
|
where this restriction is not met, however this is not expected
|
|
to cause a significant problem. Anyone wishing to use GDB can
|
|
easily store the appropriate instructions at the vector, and if
|
|
they're not using GDB, why the hell are they inserting breakpoint
|
|
exceptions?...
|
|
*/
|
|
|
|
CORE_ADDR or1k_target_read_pc(int pid)
|
|
{
|
|
#if defined(PC_REGNUM) && defined(EPC_REGNUM)
|
|
if(PC_REGNUM >= 0)
|
|
{
|
|
unsigned long pc_val = or1k_read_spr_reg(PC_SPRNUM);
|
|
|
|
/* If we're currently at the breakpoint exception, get the logical PC
|
|
from the exception register instead. */
|
|
if(pc_val == 0xD00)
|
|
{
|
|
unsigned long sr_val = or1k_read_spr_reg(ESR_SPRNUM(CURRENT_CID));
|
|
|
|
pc_val = or1k_read_spr_reg(EPC_SPRNUM(CURRENT_CID));
|
|
#if 0
|
|
if(!(sr_val & 0x2000)) /* If ESR[DSX] is not set */
|
|
pc_val += 4;
|
|
#endif
|
|
}
|
|
return pc_val;
|
|
}
|
|
#endif
|
|
internal_error ("or1k_target_read_pc");
|
|
return 0;
|
|
}
|
|
|
|
void or1k_target_write_pc(CORE_ADDR pc,int pid)
|
|
{
|
|
#if defined(PC_REGNUM) && defined(EPC_REGNUM)
|
|
if(PC_REGNUM >= 0)
|
|
{
|
|
unsigned long pc_val = or1k_read_spr_reg(PC_SPRNUM);
|
|
if(pc_val == 0xD00)
|
|
{
|
|
unsigned long sr_val = or1k_read_spr_reg(ESR_SPRNUM(CURRENT_CID));
|
|
|
|
if(or1k_read_spr_reg(EPC_SPRNUM(CURRENT_CID)) != pc)
|
|
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID), pc);
|
|
}
|
|
else
|
|
{
|
|
unsigned char break_bytes[4] = BRK_INSTR_STRUCT;
|
|
unsigned long b_insn = ntohl(*((unsigned long*)break_bytes));
|
|
unsigned long saved_insn = or1k_read_spr_reg((pc_val >> 2) + MEM_SPACE);
|
|
unsigned long saved_sr = or1k_read_spr_reg(SR_SPRNUM);
|
|
unsigned long saved_dmr1 = or1k_read_spr_reg(DMR1_SPRNUM);
|
|
unsigned long working_sr = saved_sr;
|
|
unsigned long working_dmr1 = saved_dmr1;
|
|
unsigned long new_pc_val = pc_val;
|
|
|
|
or1k_save_stall_state();
|
|
/* Install a breakpoint */
|
|
or1k_write_spr_reg((pc_val >> 2) + MEM_SPACE,b_insn);
|
|
|
|
/* Make sure exceptions are enabled and interrupts
|
|
are disabled */
|
|
working_sr |= 0x02; /* Exceptions enabled */
|
|
working_sr &= ~0x04; /* Interrupts disabled */
|
|
or1k_write_spr_reg(SR_SPRNUM,working_sr);
|
|
|
|
/* Make sure we are in hardware single step... */
|
|
dmr1 |= DMR1_ST;
|
|
or1k_write_spr_reg(DMR1_SPRNUM, dmr1);
|
|
|
|
or1k_do_1_processor_step();
|
|
while((new_pc_val = or1k_read_spr_reg(PC_SPRNUM)) != 0xD00)
|
|
{
|
|
/* We still haven't managed to get into the exception.
|
|
Perhaps there was an exception pending already and
|
|
it jumped somewhere else? Let's try it again. */
|
|
|
|
/* Restore the old instruction */
|
|
or1k_write_spr_reg((pc_val >> 2) + MEM_SPACE, saved_insn);
|
|
pc_val = new_pc_val;
|
|
|
|
/* Install a new breakpoint */
|
|
saved_insn = or1k_read_spr_reg(( pc_val >> 2) + MEM_SPACE);
|
|
or1k_write_spr_reg((pc_val >> 2) + MEM_SPACE,b_insn);
|
|
|
|
/* Again, make sure exceptions are enabled */
|
|
working_sr = or1k_read_spr_reg(SR_SPRNUM);
|
|
working_sr |= 0x02; /* Exceptions enabled */
|
|
working_sr &= ~0x04; /* Interrupts disabled */
|
|
or1k_write_spr_reg(SR_SPRNUM,working_sr);
|
|
|
|
or1k_do_1_processor_step();
|
|
}
|
|
|
|
/* Restore the state of everything */
|
|
#if 0
|
|
if(saved_sr & 0x2000)
|
|
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID), pc);
|
|
else
|
|
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID), pc-4);
|
|
#endif
|
|
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID), pc);
|
|
or1k_write_spr_reg(ESR_SPRNUM(CURRENT_CID), saved_sr);
|
|
or1k_write_spr_reg((pc_val >> 2) + MEM_SPACE, saved_insn);
|
|
|
|
/* Step the processor twice to finish through the
|
|
breakpoint instruction */
|
|
or1k_do_1_processor_step();
|
|
or1k_do_1_processor_step();
|
|
|
|
or1k_restore_stall_state();
|
|
|
|
/* Reset the single step mode */
|
|
or1k_write_spr_reg(DMR1_SPRNUM,saved_dmr1);
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
internal_error ("or1k_target_write_pc");
|
|
return;
|
|
}
|
|
|
|
#endif /* NEW_PC_HANDLING */
|
|
|
/* Converts regno to sprno. or1k debug unit has GPRs mapped to SPRs,
|
/* Converts regno to sprno. or1k debug unit has GPRs mapped to SPRs,
|
which are not compact, so we are mapping them for GDB. */
|
which are not compact, so we are mapping them for GDB. */
|
|
/* Rewritten by CZ 12/09/01 */
|
int
|
int
|
or1k_regnum_to_sprnum (int regno)
|
or1k_regnum_to_sprnum (int regno)
|
{
|
{
|
if (regno < MAX_GPR_REGS)
|
if (regno < MAX_GPR_REGS)
|
return SPR_REG(SPR_SYSTEM_GROUP, regno + CURRENT_CID * MAX_GPR_REGS + SPR_GPR_START);
|
return SPR_REG(SPR_SYSTEM_GROUP, regno + CURRENT_CID * MAX_GPR_REGS + SPR_GPR_START);
|
|
|
if (regno < MAX_GPR_REGS + MAX_VF_REGS)
|
if (regno < MAX_GPR_REGS + MAX_VF_REGS)
|
return SPR_REG(SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
|
return SPR_REG(SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
|
+ CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);
|
+ CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);
|
if (regno == PS_REGNUM)
|
|
return SR_SPRNUM;
|
switch(regno)
|
if (regno == PC_REGNUM)
|
{
|
return PC_SPRNUM;
|
case PS_REGNUM: return SR_SPRNUM;
|
if (regno == CCR_REGNUM)
|
case PC_REGNUM: return PC_SPRNUM;
|
return CCR_SPRNUM(CURRENT_CID);
|
case CCR_REGNUM: return CCR_SPRNUM(CURRENT_CID);
|
|
case EPC_REGNUM: return EPC_SPRNUM(CURRENT_CID);
|
|
case EAR_REGNUM: return EAR_SPRNUM(CURRENT_CID);
|
|
case ESR_REGNUM: return ESR_SPRNUM(CURRENT_CID);
|
|
default:
|
error ("Invalid register number!");
|
error ("Invalid register number!");
|
|
break;
|
|
}
|
|
|
|
return 0;
|
}
|
}
|
|
|
/* Builds and returns register name. */
|
/* Builds and returns register name. */
|
|
|
static char tmp_name[16];
|
static char tmp_name[16];
|
Line 632... |
Line 782... |
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
|
/* CZ -- 25/09/01 -- The prologue handling code has been rewritten
|
prologue:
|
to bring it inline with the new C compiler and various changes
|
00000000 <_proc1>:
|
that have been made. The code below expects to see various
|
0: d7 e1 17 e4 l.sw 0xffffffe4(r1),r2
|
instructions that are identified by states. States are ordered
|
4: 9c 41 00 00 l.addi r2,r1,0x0
|
and should flow from one to the next. If a state is encountered
|
8: 9c 21 ff e8 l.addi r1,r1,0xffffffe8
|
out of order, it is assumed to be function code and not
|
c: d7 e2 1f f8 l.sw 0xfffffff8(r2),r3
|
prologue, so the prologue parsing is terminated. I've tried
|
10: d7 e2 27 f4 l.sw 0xfffffff4(r2),r4
|
several real world tests from the C compiler, and this seems
|
14: 84 82 ff f8 l.lwz r4,0xfffffff8(r2)
|
to recognize the transition from prologue to code even under
|
18: 9d 24 00 00 l.addi r9,r4,0x0
|
a worst case (21 instructions) scenario. */
|
1c: 00 00 00 02 l.j 0x2
|
|
20: 15 00 00 00 l.nop
|
typedef enum {
|
|
PrologueStateMachineStart,
|
00000024 <_L2>:
|
PrologueStateMachineFrameInitialized,
|
24: 84 41 ff fc l.lwz r2,0xfffffffc(r1)
|
PrologueStateMachineFrameSaved,
|
28: 48 00 58 00 l.jalr r11
|
PrologueStateMachineFrameAdjusted,
|
2c: 9c 21 00 18 l.addi r1,r1,0x18 */
|
PrologueStateMachineRegisterSaved,
|
|
PrologueStateMachineParameterSaved,
|
|
PrologueStateMachineInvalid,
|
|
} FunctionPrologueStates;
|
|
|
|
/* Parse the insn and save the arguments */
|
|
static FunctionPrologueStates getPrologueInsnType(unsigned long insn,
|
|
int* arg1,int* arg2)
|
|
{
|
|
int code = insn >> 26;
|
|
int state = PrologueStateMachineInvalid;
|
|
int op1,op2;
|
|
short offset;
|
|
|
|
switch(code)
|
|
{
|
|
case 0x27: /* l.addi */
|
|
op1 = (insn & 0x03E00000) >> 21;
|
|
op2 = (insn & 0x001F0000) >> 16;
|
|
if(op1 == 1 && op2 == 1)
|
|
{
|
|
offset = insn & 0xFFFF;
|
|
state = PrologueStateMachineFrameInitialized;
|
|
}
|
|
else if(op1 == 2 && op2 == 1)
|
|
{
|
|
offset = insn & 0xFFFF;
|
|
state = PrologueStateMachineFrameAdjusted;
|
|
}
|
|
*arg1 = op1;
|
|
*arg2 = offset;
|
|
break;
|
|
case 0x35: /* l.sw */
|
|
op1 = (insn & 0x001F0000) >> 16;
|
|
op2 = (insn & 0x0000F800) >> 11;
|
|
offset = (insn & 0x000007FF) |
|
|
((insn & 0x03E00000) >> 10);
|
|
|
|
if(op1 == 1)
|
|
state = (op2 == 2) ? PrologueStateMachineFrameSaved :
|
|
PrologueStateMachineRegisterSaved;
|
|
else if(op1 == 2)
|
|
state = PrologueStateMachineParameterSaved;
|
|
*arg1 = op2;
|
|
*arg2 = offset;
|
|
break;
|
|
default: /* unknown */
|
|
break;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
CORE_ADDR
|
CORE_ADDR or1k_skip_prologue (CORE_ADDR pc)
|
or1k_skip_prologue (CORE_ADDR pc)
|
|
{
|
{
|
unsigned long inst;
|
int frame_size = 0,i;
|
CORE_ADDR skip_pc;
|
FunctionPrologueStates state = PrologueStateMachineStart;
|
CORE_ADDR func_addr, func_end;
|
CORE_ADDR t_pc;
|
struct symtab_and_line sal;
|
|
int i;
|
/*
|
int offset = 0;
|
Maximum prologue: save even reg's 10-30 (11 insns)
|
|
save params passed in regs (6 insns)
|
|
adjust stack (1 insn), adjust frame (1 insn),
|
|
save old frame pointer (1 insn),
|
|
save old link register (1 insn)
|
|
*/
|
|
static const int MAX_PROLOGUE_LENGTH = 21;
|
|
|
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_addr[i] = -1;
|
|
|
/* Is there a prologue? */
|
for(t_pc=pc; t_pc < (pc + MAX_PROLOGUE_LENGTH) &&
|
inst = or1k_fetch_instruction (pc);
|
state != PrologueStateMachineInvalid; t_pc += OR1K_INSTLEN)
|
if (inst & 0xfc1ff800 != 0xd4011000) return pc; /* l.sw I(r1),r2 */
|
{
|
or1k_saved_reg_addr[2] = offset++;
|
unsigned long insn = or1k_fetch_instruction(t_pc);
|
inst = or1k_fetch_instruction (pc + OR1K_INSTLEN);
|
int reg;
|
if (inst & 0xFFFF0000 != 0x9c410000) return pc; /* l.addi r2,r1,I */
|
int offset;
|
pc += 2 * OR1K_INSTLEN;
|
FunctionPrologueStates new_state = getPrologueInsnType(insn,®,&offset);
|
inst = or1k_fetch_instruction (pc);
|
|
if (inst & 0xFFFF0000 != 0x9c210000) return pc; /* l.addi r1,r1,I */
|
switch(state)
|
pc += OR1K_INSTLEN;
|
{
|
|
case PrologueStateMachineStart:
|
/* Skip stored registers. */
|
if(new_state == PrologueStateMachineFrameInitialized)
|
inst = or1k_fetch_instruction (pc);
|
{
|
while (inst & 0xfc1ff800 != 0xd4020000) /* l.sw 0x0(r2),rx */
|
frame_size = -offset;
|
{
|
or1k_saved_reg_addr[1] = frame_size;
|
/* get saved reg. */
|
}
|
or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
|
else
|
pc += OR1K_INSTLEN;
|
new_state = PrologueStateMachineInvalid;
|
inst = or1k_fetch_instruction (pc);
|
break;
|
|
case PrologueStateMachineFrameInitialized:
|
|
if(new_state == PrologueStateMachineFrameSaved)
|
|
or1k_saved_reg_addr[reg] = frame_size - offset;
|
|
else if(new_state == PrologueStateMachineRegisterSaved)
|
|
{
|
|
/* Ooops...we have a frameless function.
|
|
Not sure what this might mean, but
|
|
let's try and continue. */
|
|
or1k_saved_reg_addr[reg] = frame_size - offset;
|
|
}
|
|
else
|
|
new_state = PrologueStateMachineInvalid;
|
|
break;
|
|
case PrologueStateMachineFrameSaved:
|
|
if(new_state != PrologueStateMachineFrameAdjusted &&
|
|
offset != frame_size)
|
|
new_state = PrologueStateMachineInvalid;
|
|
break;
|
|
case PrologueStateMachineFrameAdjusted:
|
|
case PrologueStateMachineRegisterSaved:
|
|
if(new_state == PrologueStateMachineRegisterSaved)
|
|
or1k_saved_reg_addr[reg] = frame_size - offset;
|
|
else if(new_state == PrologueStateMachineParameterSaved)
|
|
or1k_saved_reg_addr[reg] = -offset;
|
|
else
|
|
new_state = PrologueStateMachineInvalid;
|
|
break;
|
|
case PrologueStateMachineParameterSaved:
|
|
if(new_state == PrologueStateMachineParameterSaved)
|
|
or1k_saved_reg_addr[reg] = -offset;
|
|
else
|
|
new_state = PrologueStateMachineInvalid;
|
|
break;
|
|
default:
|
|
new_state = PrologueStateMachineInvalid;
|
|
}
|
|
|
|
state = new_state;
|
}
|
}
|
return pc;
|
|
|
return t_pc;
|
}
|
}
|
|
|
/* Determines whether this function has frame. */
|
/* Determines whether this function has frame. */
|
|
|
int
|
int
|
Line 730... |
Line 975... |
&& FRAMELESS_FUNCTION_INVOCATION (frame))
|
&& FRAMELESS_FUNCTION_INVOCATION (frame))
|
/* A frameless function interrupted by a signal did not change the
|
/* A frameless function interrupted by a signal did not change the
|
frame pointer. */
|
frame pointer. */
|
fp = FRAME_FP (frame);
|
fp = FRAME_FP (frame);
|
else
|
else
|
fp = read_memory_integer (frame->frame, 4);
|
{
|
|
unsigned long func_pc = get_pc_function_start(frame->pc);
|
|
unsigned long insn = read_memory_integer(func_pc,4);
|
|
int i;
|
|
int offset = 0;
|
|
|
|
/* The first instruction should be the number of bytes
|
|
in our frame. If it isn't we're in trouble because
|
|
the function is without a prologue... */
|
|
if(((insn & 0xFC000000) == 0x9C000000) &&
|
|
((insn & 0x03E00000) == 0x00200000) &&
|
|
((insn & 0x001F0000) == 0x00010000))
|
|
{
|
|
short off = insn & 0xFFFF;
|
|
|
|
/* Look for the storage of the frame pointer in the
|
|
function prologue.. */
|
|
for(i=1;i<20;i++)
|
|
{
|
|
unsigned long insn = read_memory_integer(func_pc+4*i,4);
|
|
|
|
/* If bits are 31 - 26 are %110101,
|
|
and bits 20 - 16 are %00001,
|
|
and bits 15 - 11 are %00010,
|
|
then our frame pointer lies at the offset specified
|
|
by bits [25-21][10-0]. */
|
|
|
|
int code = insn >> 26;
|
|
int r1 = (insn & 0x001F0000) >> 16;
|
|
int r2 = (insn & 0x0000F800) >> 11;
|
|
int idx_h = (insn & 0x03E00000) >> 10;
|
|
int idx = (insn & 0x000007FF) | idx_h;
|
|
|
|
if(code == 0x35 && r1 == 1 && r2 == 2)
|
|
{
|
|
offset = off + idx;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 756... |
Line 1043... |
void
|
void
|
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;
|
|
int frame_size;
|
|
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 or1k_saved_reg_addr[], we will use it later. */
|
or1k_skip_prologue (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
|
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
|
|
routine which we can't traverse beyond. Let's give up here,
|
|
because attempting to continue will only lead to trouble. */
|
|
if(frame_size < 0)
|
|
{
|
|
printf("Found a function without a prologue at 0x%08x\n",func_pc);
|
|
printf("Frame pc was at 0x%08x\n",fi->pc);
|
|
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_addr[i] >= 0)
|
fi->saved_regs[i] = fi->frame + or1k_saved_reg_addr[i];
|
fi->saved_regs[i] = fi->frame - or1k_saved_reg_addr[i];
|
}
|
|
|
|
|
/* 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
|
|
the correct value of r1 for the next frame, which can be
|
|
calculated by adding the frame_size to the frame pointer. */
|
|
fi->saved_regs[1] = fi->frame - frame_size;
|
|
|
|
if(fi->saved_regs[LR_REGNUM])
|
|
fi->saved_regs[PC_REGNUM] = read_memory_integer(fi->saved_regs[LR_REGNUM],4);
|
|
else
|
|
fi->saved_regs[PC_REGNUM] = read_register(LR_REGNUM);
|
|
}
|
|
|
static CORE_ADDR
|
static CORE_ADDR
|
read_next_frame_reg (fi, regno)
|
read_next_frame_reg (fi, regno)
|
struct frame_info *fi;
|
struct frame_info *fi;
|
int regno;
|
int regno;
|
Line 783... |
Line 1097... |
else
|
else
|
{
|
{
|
if (fi->saved_regs == NULL)
|
if (fi->saved_regs == NULL)
|
or1k_init_saved_regs (fi);
|
or1k_init_saved_regs (fi);
|
if (fi->saved_regs[regno])
|
if (fi->saved_regs[regno])
|
|
{
|
|
if(regno == SP_REGNUM || regno == PC_REGNUM)
|
|
return fi->saved_regs[regno];
|
|
else
|
return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
|
return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
|
}
|
}
|
}
|
}
|
|
}
|
return read_register (regno);
|
return read_register (regno);
|
}
|
}
|
|
|
/* Find the caller of this frame. We do this by seeing if LR_REGNUM
|
/* Find the caller of this frame. We do this by seeing if LR_REGNUM
|
is saved in the stack anywhere, otherwise we get it from the
|
is saved in the stack anywhere, otherwise we get it from the
|
Line 2174... |
Line 2493... |
/* Commands to show and set sprs. */
|
/* Commands to show and set sprs. */
|
add_info ("spr", info_spr_command, "Show information about the spr registers.");
|
add_info ("spr", info_spr_command, "Show information about the spr registers.");
|
add_com ("spr", class_support, spr_command, "Set specified SPR register.");
|
add_com ("spr", class_support, spr_command, "Set specified SPR register.");
|
|
|
/* hwatch command. */
|
/* hwatch command. */
|
add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watchpoint.\n\
|
add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watch"
|
Example: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_var)&&($SDATA >= 50).\n\
|
"point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
|
See OR1k Architecture document for more info.");
|
"var)&&($SDATA >= 50).\nSee OR1k Architecture document for more"
|
|
" info.");
|
|
|
/* htrace commands. */
|
/* htrace commands. */
|
add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
|
add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
|
"Group of commands for handling hardware assisted trace\n\n"
|
"Group of commands for handling hardware assisted trace\n\n"
|
"See OR1k Architecture and gdb for or1k documents for more info.",
|
"See OR1k Architecture and gdb for or1k documents for more info.",
|