Line 144... |
Line 144... |
{"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"},
|
{"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 193... |
Line 192... |
|
|
/* 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 */
|
/* Rewritten by CZ 12/09/01 */
|
int
|
int
|
or1k_regnum_to_sprnum (int regno)
|
or1k_regnum_to_sprnum (int regno)
|
Line 783... |
Line 646... |
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));
|
}
|
}
|
|
|
/* CZ -- 25/09/01 -- The prologue handling code has been rewritten
|
/* The or1k cc defines the following
|
to bring it inline with the new C compiler and various changes
|
prologue:
|
that have been made. The code below expects to see various
|
00000000 <_proc1>:
|
instructions that are identified by states. States are ordered
|
0: d7 e1 17 e4 l.sw 0xffffffe4(r1),r2
|
and should flow from one to the next. If a state is encountered
|
4: 9c 41 00 00 l.addi r2,r1,0x0
|
out of order, it is assumed to be function code and not
|
8: 9c 21 ff e8 l.addi r1,r1,0xffffffe8
|
prologue, so the prologue parsing is terminated. I've tried
|
c: d7 e2 1f f8 l.sw 0xfffffff8(r2),r3
|
several real world tests from the C compiler, and this seems
|
10: d7 e2 27 f4 l.sw 0xfffffff4(r2),r4
|
to recognize the transition from prologue to code even under
|
14: 84 82 ff f8 l.lwz r4,0xfffffff8(r2)
|
a worst case (21 instructions) scenario. */
|
18: 9d 24 00 00 l.addi r9,r4,0x0
|
|
1c: 00 00 00 02 l.j 0x2
|
typedef enum {
|
20: 15 00 00 00 l.nop
|
PrologueStateMachineStart,
|
|
PrologueStateMachineFrameInitialized,
|
00000024 <_L2>:
|
PrologueStateMachineFrameSaved,
|
24: 84 41 ff fc l.lwz r2,0xfffffffc(r1)
|
PrologueStateMachineFrameAdjusted,
|
28: 48 00 58 00 l.jalr r11
|
PrologueStateMachineRegisterSaved,
|
2c: 9c 21 00 18 l.addi r1,r1,0x18 */
|
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 or1k_skip_prologue (CORE_ADDR pc)
|
CORE_ADDR
|
|
or1k_skip_prologue (CORE_ADDR pc)
|
{
|
{
|
int frame_size = 0,i;
|
unsigned long inst;
|
FunctionPrologueStates state = PrologueStateMachineStart;
|
CORE_ADDR skip_pc;
|
CORE_ADDR t_pc;
|
CORE_ADDR func_addr, func_end;
|
|
struct symtab_and_line sal;
|
/*
|
int i;
|
Maximum prologue: save even reg's 10-30 (11 insns)
|
int offset = 0;
|
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? */
|
/* Is there a prologue? */
|
Line 890... |
Line 697... |
/* get saved reg. */
|
/* get saved reg. */
|
or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
|
or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
|
pc += OR1K_INSTLEN;
|
pc += OR1K_INSTLEN;
|
inst = or1k_fetch_instruction (pc);
|
inst = or1k_fetch_instruction (pc);
|
}
|
}
|
|
return pc;
|
return t_pc;
|
|
}
|
}
|
|
|
/* Determines whether this function has frame. */
|
/* Determines whether this function has frame. */
|
|
|
int
|
int
|