OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 206 to Rev 207
    Reverse comparison

Rev 206 → Rev 207

/trunk/insight/gdb/config/or1k/tm-or1k.h
28,6 → 28,17
#include "defs.h"
#include <inttypes.h> /* CZ */
 
/* CZ 11/09/01 -- Cause GDB to expect actual PC value to appear
in breakpoint exception vector instead of being in PC itself */
 
#define NEW_PC_HANDLING
 
#ifdef NEW_PC_HANDLING
#define TARGET_READ_PC(pid) or1k_target_read_pc(pid)
#define TARGET_WRITE_PC(pc,pid) or1k_target_write_pc(pc,pid)
#endif
 
 
struct value;
 
struct struct_or1k_implementation
144,6 → 155,21
#define PS_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 1)
#define CCR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 2)
 
/*******************************************/
/* Added by CZ on 12/09/01 Used for new style breakpoints */
/* These really aren't designed to be seen by the user */
#define EPC_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 3)
#define EAR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 4)
#define ESR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 5)
 
#define EPC_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP,32+cid)
#define EAR_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP,48+cid)
#define ESR_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP,64+cid)
 
#define MAX_EXTRA_NUM_REGS 6
 
/******** END OF ADDITIONS BY CZ ************/
 
extern int or1k_regnum_to_sprnum PARAMS ((int regno));
#define REGNUM_TO_SPRNUM(regno) (or1k_regnum_to_sprnum(regno))
 
151,6 → 177,8
#define DMR1_ST (0x00400000)
 
/* Changed by CZ 21/06/01 */
#define DRR_SS (0x00004000)
#define DRR_TE (0x00002000)
#define DRR_BE (0x00001000)
#define DRR_SCE (0x00000800)
#define DRR_RE (0x00000400)
177,9 → 205,12
#define NUM_VF_REGS (or1k_implementation.num_vfpr_regs)
#define MAX_VF_REGS (32)
 
/*******************************/
/* Paramterized by CZ 11/09/01 */
/*******************************/
/* gdb mapping of registers */
#ifndef NUM_REGS
#define NUM_REGS (MAX_GPR_REGS+MAX_VF_REGS+3)
#define NUM_REGS (MAX_GPR_REGS+MAX_VF_REGS+MAX_EXTRA_NUM_REGS)
#endif
 
/* Can act like a little or big endian. */
270,11 → 301,23
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
 
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
/* Note: several attempts have been made to account for
differences between hardware and software breakpoints
and still allow hardware breakpoints to advance the
PC beyond the offending instruction. However, short
of rewriting gdb, none of them seem to work. Thus,
for now, we assume that a hardware breakpoint will
always give control to the breakpoint vector BEFORE
it executes the instruction, thus, when the breakpoint
vector returns, it will return to the same instruction
that caused the exception (and thus hit the exception
again if it hasn't been cleared) Note that if it actually
executes this instruction, things fail bandly inside of
gdb. This should not be an issue for now, as the or1200
implementation will not implement hardware breakpoints
at all.. */
 
#define DECR_PC_AFTER_BREAK 0
 
extern int or1k_insert_breakpoint (CORE_ADDR addr, char *contents_cache);
319,7 → 362,7
/* Given a name (SIGHUP, etc.), return its signal. */
extern enum target_signal or1k_signal_from_name PARAMS ((char *));
 
#define NUM_OR1K_SIGNALS (10)
#define NUM_OR1K_SIGNALS (14)
 
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
357,6 → 400,7
#define SKIP_PROLOGUE(pc) (or1k_skip_prologue (pc))
 
/* FRAMES */
 
#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
 
#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
411,7 → 455,7
/* Is floating/vector unit present. */
#define OR1K_VF_PRESENT (or1k_implementation.vf_present)
 
#define INIT_FRAME_PC /* Not necessary */
/* #define INIT_FRAME_PC */ /* Not necessary */
 
/* Stack grows downward. */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
/trunk/insight/gdb/remote-or1k.c
164,6 → 164,15
unsigned int dsr = 0;
unsigned int drr = 0;
 
static void (*old_sigint) (); /* Old signal-handler for sigint */
static int interrupt_requested = 0; /* Interrupted flag */
static void or1k_request_int ()
{
/* restore original signalhandler */
signal (SIGINT, old_sigint);
interrupt_requested = 1;
}
 
/* Current matchpoints. */
unsigned int dvr[MAX_MATCHPOINTS];
struct dcr_struct dcr[MAX_MATCHPOINTS];
299,6 → 308,60
return or1k_read_reg (regno + REG_SPACE);
}
 
/* CZ 15/09/01 -- This is hacked in right now. This should
probably NOT be called directly, but at the moment I don't
have the time to figure out how to do it right. The problem
is the following, in order to write the PC, I may need to
step the processor...(long story, but trust me, I need to
do this)...I need to do this sometimes even when I have
not started or even loaded a program, thus I can not
use the default routines gdb provides for this purpose.
 
I do not wish to embed targets directly into or1k-tdep,
but I need a simple function there that will cause the
processor to continue 1 instruction and not pay attention
to gdb's state machine. I know this could conceivably break
things if we stop connecting via jtag and start doing
something else, so anyone who wants to figure out how to do
this right is welcome. Drop me an email if you want to
correct it. I'll try to help you understand the issue. */
 
/* The processor should already be in single step mode or
this will continue indefinitely! */
void or1k_do_1_processor_step()
{
unsigned long drr = 0;
unsigned long val;
 
/* Run the processor */
or1k_set_chain (SC_REGISTER);
val = or1k_read_reg (JTAG_RISCOP);
or1k_write_reg (JTAG_RISCOP, val & ~1);
 
/* Wait for the DEBUG_REASON_REGISTER to be non zero */
while(!(drr = or1k_read_spr_reg (DRR_SPRNUM)))
usleep (10);
 
/* OK..we're done */
}
 
static int saved_stall_state = 0;
void or1k_save_stall_state()
{
or1k_set_chain (SC_REGISTER);
saved_stall_state = or1k_read_reg (JTAG_RISCOP) & 0x01;
}
void or1k_restore_stall_state()
{
int val;
 
or1k_set_chain (SC_REGISTER);
val = or1k_read_reg (JTAG_RISCOP);
val |= saved_stall_state;
or1k_write_reg (JTAG_RISCOP, val);
saved_stall_state = 0;
}
 
/* Stalls the CPU. */
 
static void
322,6 → 385,7
{
unsigned int val;
 
 
or1k_set_chain (SC_REGISTER);
val = or1k_read_reg (JTAG_RISCOP);
or1k_write_reg (JTAG_RISCOP, val & ~1);
645,6 → 709,26
 
or1k_commit_debug_registers ();
/* Run the target. */
#ifdef NEW_PC_HANDLING
/* In the new style PC handling mode, we should always
keep stepping the target until we get out of the
breakpoint exception vector assuming that "step"
has been specified. Otherwise, this isn't
particularly useful, as we'll keep hitting the
same breakpoint that put us here in the first
place. By stepping out of this vector we guarantee
to step over the instruction that caused the
breakpoint, so when they are reinserted we are
already past that location. */
if(step)
{
while((or1k_read_spr_reg(PC_SPRNUM) & 0xFFFFFF00) == 0xD00)
or1k_do_1_processor_step();
}
#endif
 
/* We can now continue normally, independent of step */
or1k_unstall ();
or1k_status = TARGET_RUNNING;
}
674,13 → 758,25
or1k_error ("Remote failure: %s", or1k_err_name (err));
 
/* Wait for or1k DRR register to be nonzero. */
interrupt_requested = 0;
old_sigint = signal (SIGINT, or1k_request_int);
do
{
if(interrupt_requested)
{
or1k_stall();
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_INT;
or1k_status = TARGET_STOPPED;
or1k_read_trace();
return 0;
}
drr = or1k_read_spr_reg (DRR_SPRNUM);
usleep (10);
}
while (drr == 0);
 
signal (SIGINT, old_sigint);
status->kind = TARGET_WAITKIND_STOPPED;
or1k_flush_pipeline ();
 
710,6 → 806,10
status->value.sig = TARGET_SIGNAL_REALTIME_40;
else if (drr & DRR_BE)
status->value.sig = TARGET_SIGNAL_TRAP;
else if (drr & DRR_TE)
status->value.sig = TARGET_SIGNAL_REALTIME_41;
else if (drr & DRR_SS) /* CZ 16/09/01 */
status->value.sig = TARGET_SIGNAL_TRAP;
else
{
status->value.sig = TARGET_SIGNAL_UNKNOWN;
739,6 → 839,8
}
hit_watchpoint = !breakpoint;
 
 
#ifndef NEW_PC_HANDLING
/* Cause the trap/breakpoint exception to be ignored. This is
the behavior of the simulator when the PC value is changed
by a write command. All pending exceptions are cleared and
750,6 → 852,24
{
or1k_write_spr_reg(PC_SPRNUM,value);
}
#endif
 
#ifdef NEW_PC_HANDLING
 
/* If we're a software breakpoint and we're currently located
in the breakpoint vector, then we need to reset the pc
back 4 bytes. This will ensure that the instruction gets
executed. If we don't do this, gdb will skip this instruction,
even if we set DECR_PC_AFTER_BREAK, which seems to have no
effect other than to calculate the correct breakpoint
address. */
 
if((b_insn == or1k_read_spr_reg(((pc-4) >> 2) + MEM_SPACE)) &&
or1k_read_spr_reg(PC_SPRNUM) == 0xD00)
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID),pc-4);
 
#endif
 
}
else
hit_watchpoint = 0;
1061,9 → 1181,13
void
or1k_flush_pipeline ()
{
/* CZ 15/09/01 -- Damjan has made it perfectly clear
that the DIR will not be implemented on any chip
as the entire concept is poorly conceived. This
section has therefore been removed. */
/* or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR); */
}
 
/* Print info on this target. */
/trunk/insight/gdb/or1k-tdep.c
112,12 → 112,13
"R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
"R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
 
/* Modified by CZ 12/09/01 */
/* vector/floating point registers */
"VFA0", "VFA1", "VFA2", "VFA3", "VFA4", "VFA5", "VFRV ", "VFR7",
"VFR8", "VFR9", "VFR10", "VFR11", "VFR12", "VFR13", "VFR14", "VFR15",
"VFR16", "VFR17", "VFR18", "VFR19", "VFR20", "VFR21", "VFR22", "VFR23",
"VFR24", "VFR25", "VFR26", "VFR27", "VFR28", "VFR29", "VFR30", "VFR31",
"PC", "SR", "EPCR"
"PC", "SR", "EPCR", "ExPC", "ExEAR", "ExSR"
};
 
static char *or1k_group_names[] = {
133,15 → 134,19
} or1k_signals [NUM_OR1K_SIGNALS + 1] =
{
{"RSTE", "Reset Exception"},
{"BUSE", "Bus Error" },
{"DFPE", "Data Page Fault Exception"},
{"IFPE", "Instruction Page Fault Exception"},
{"LPINTE", "Low Priority Interrupt Exception"},
{"AE", "Alignment Exception"},
{"ILINSE" "Illegal Instruction" },
{"HPINTE", "High Priority Interrupt Exception"},
{"DME", "DTLB Miss Exception"},
{"IME", "ITLB Miss Exception"},
{"RE", "Range Exception"},
{"SCE", "SCE Exception"},
{"BRKPTE", "Breakpoint Exception"},
{"TRAPE", "Trap Exception"},
{NULL, NULL}
};
 
190,24 → 195,169
static int prev_length = 10;
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,
which are not compact, so we are mapping them for GDB. */
 
/* Rewritten by CZ 12/09/01 */
int
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);
 
if (regno < MAX_GPR_REGS + MAX_VF_REGS)
return SPR_REG(SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
+ CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);
if (regno == PS_REGNUM)
return SR_SPRNUM;
if (regno == PC_REGNUM)
return PC_SPRNUM;
if (regno == CCR_REGNUM)
return CCR_SPRNUM(CURRENT_CID);
error ("Invalid register number!");
 
switch(regno)
{
case PS_REGNUM: return SR_SPRNUM;
case PC_REGNUM: return PC_SPRNUM;
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!");
break;
}
 
return 0;
}
 
/* Builds and returns register name. */
634,58 → 784,153
memcpy (valbuf, &regbuf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
}
 
/* The or1k cc defines the following
prologue:
00000000 <_proc1>:
0: d7 e1 17 e4 l.sw 0xffffffe4(r1),r2
4: 9c 41 00 00 l.addi r2,r1,0x0
8: 9c 21 ff e8 l.addi r1,r1,0xffffffe8
c: d7 e2 1f f8 l.sw 0xfffffff8(r2),r3
10: d7 e2 27 f4 l.sw 0xfffffff4(r2),r4
14: 84 82 ff f8 l.lwz r4,0xfffffff8(r2)
18: 9d 24 00 00 l.addi r9,r4,0x0
1c: 00 00 00 02 l.j 0x2
20: 15 00 00 00 l.nop
/* CZ -- 25/09/01 -- The prologue handling code has been rewritten
to bring it inline with the new C compiler and various changes
that have been made. The code below expects to see various
instructions that are identified by states. States are ordered
and should flow from one to the next. If a state is encountered
out of order, it is assumed to be function code and not
prologue, so the prologue parsing is terminated. I've tried
several real world tests from the C compiler, and this seems
to recognize the transition from prologue to code even under
a worst case (21 instructions) scenario. */
 
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 */
typedef enum {
PrologueStateMachineStart,
PrologueStateMachineFrameInitialized,
PrologueStateMachineFrameSaved,
PrologueStateMachineFrameAdjusted,
PrologueStateMachineRegisterSaved,
PrologueStateMachineParameterSaved,
PrologueStateMachineInvalid,
} FunctionPrologueStates;
 
CORE_ADDR
or1k_skip_prologue (CORE_ADDR pc)
/* Parse the insn and save the arguments */
static FunctionPrologueStates getPrologueInsnType(unsigned long insn,
int* arg1,int* arg2)
{
unsigned long inst;
CORE_ADDR skip_pc;
CORE_ADDR func_addr, func_end;
struct symtab_and_line sal;
int i;
int offset = 0;
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)
{
int frame_size = 0,i;
FunctionPrologueStates state = PrologueStateMachineStart;
CORE_ADDR t_pc;
/*
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++)
or1k_saved_reg_addr[i] = -1;
 
/* Is there a prologue? */
inst = or1k_fetch_instruction (pc);
if (inst & 0xfc1ff800 != 0xd4011000) return pc; /* l.sw I(r1),r2 */
or1k_saved_reg_addr[2] = offset++;
inst = or1k_fetch_instruction (pc + OR1K_INSTLEN);
if (inst & 0xFFFF0000 != 0x9c410000) return pc; /* l.addi r2,r1,I */
pc += 2 * OR1K_INSTLEN;
inst = or1k_fetch_instruction (pc);
if (inst & 0xFFFF0000 != 0x9c210000) return pc; /* l.addi r1,r1,I */
pc += OR1K_INSTLEN;
for(t_pc=pc; t_pc < (pc + MAX_PROLOGUE_LENGTH) &&
state != PrologueStateMachineInvalid; t_pc += OR1K_INSTLEN)
{
unsigned long insn = or1k_fetch_instruction(t_pc);
int reg;
int offset;
FunctionPrologueStates new_state = getPrologueInsnType(insn,&reg,&offset);
 
/* Skip stored registers. */
inst = or1k_fetch_instruction (pc);
while (inst & 0xfc1ff800 != 0xd4020000) /* l.sw 0x0(r2),rx */
{
/* get saved reg. */
or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
pc += OR1K_INSTLEN;
inst = or1k_fetch_instruction (pc);
switch(state)
{
case PrologueStateMachineStart:
if(new_state == PrologueStateMachineFrameInitialized)
{
frame_size = -offset;
or1k_saved_reg_addr[1] = frame_size;
}
else
new_state = PrologueStateMachineInvalid;
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. */
732,8 → 977,50
frame pointer. */
fp = FRAME_FP (frame);
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)
{
CORE_ADDR fpp, lr;
758,17 → 1045,44
{
int i;
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);
/* 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++)
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
read_next_frame_reg (fi, regno)
struct frame_info *fi;
785,7 → 1099,12
if (fi->saved_regs == NULL)
or1k_init_saved_regs (fi);
if (fi->saved_regs[regno])
return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
{
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_register (regno);
2176,9 → 2495,10
add_com ("spr", class_support, spr_command, "Set specified SPR register.");
 
/* hwatch command. */
add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watchpoint.\n\
Example: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_var)&&($SDATA >= 50).\n\
See OR1k Architecture document for more info.");
add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watch"
"point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
"var)&&($SDATA >= 50).\nSee OR1k Architecture document for more"
" info.");
 
/* htrace commands. */
add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
/trunk/gdb-5.0/gdb/remote-or1k.c
164,6 → 164,15
unsigned int dsr = 0;
unsigned int drr = 0;
 
static void (*old_sigint) (); /* Old signal-handler for sigint */
static int interrupt_requested = 0; /* Interrupted flag */
static void or1k_request_int ()
{
/* restore original signalhandler */
signal (SIGINT, old_sigint);
interrupt_requested = 1;
}
 
/* Current matchpoints. */
unsigned int dvr[MAX_MATCHPOINTS];
struct dcr_struct dcr[MAX_MATCHPOINTS];
299,6 → 308,60
return or1k_read_reg (regno + REG_SPACE);
}
 
/* CZ 15/09/01 -- This is hacked in right now. This should
probably NOT be called directly, but at the moment I don't
have the time to figure out how to do it right. The problem
is the following, in order to write the PC, I may need to
step the processor...(long story, but trust me, I need to
do this)...I need to do this sometimes even when I have
not started or even loaded a program, thus I can not
use the default routines gdb provides for this purpose.
 
I do not wish to embed targets directly into or1k-tdep,
but I need a simple function there that will cause the
processor to continue 1 instruction and not pay attention
to gdb's state machine. I know this could conceivably break
things if we stop connecting via jtag and start doing
something else, so anyone who wants to figure out how to do
this right is welcome. Drop me an email if you want to
correct it. I'll try to help you understand the issue. */
 
/* The processor should already be in single step mode or
this will continue indefinitely! */
void or1k_do_1_processor_step()
{
unsigned long drr = 0;
unsigned long val;
 
/* Run the processor */
or1k_set_chain (SC_REGISTER);
val = or1k_read_reg (JTAG_RISCOP);
or1k_write_reg (JTAG_RISCOP, val & ~1);
 
/* Wait for the DEBUG_REASON_REGISTER to be non zero */
while(!(drr = or1k_read_spr_reg (DRR_SPRNUM)))
usleep (10);
 
/* OK..we're done */
}
 
static int saved_stall_state = 0;
void or1k_save_stall_state()
{
or1k_set_chain (SC_REGISTER);
saved_stall_state = or1k_read_reg (JTAG_RISCOP) & 0x01;
}
void or1k_restore_stall_state()
{
int val;
 
or1k_set_chain (SC_REGISTER);
val = or1k_read_reg (JTAG_RISCOP);
val |= saved_stall_state;
or1k_write_reg (JTAG_RISCOP, val);
saved_stall_state = 0;
}
 
/* Stalls the CPU. */
 
static void
322,6 → 385,7
{
unsigned int val;
 
 
or1k_set_chain (SC_REGISTER);
val = or1k_read_reg (JTAG_RISCOP);
or1k_write_reg (JTAG_RISCOP, val & ~1);
645,6 → 709,26
 
or1k_commit_debug_registers ();
/* Run the target. */
#ifdef NEW_PC_HANDLING
/* In the new style PC handling mode, we should always
keep stepping the target until we get out of the
breakpoint exception vector assuming that "step"
has been specified. Otherwise, this isn't
particularly useful, as we'll keep hitting the
same breakpoint that put us here in the first
place. By stepping out of this vector we guarantee
to step over the instruction that caused the
breakpoint, so when they are reinserted we are
already past that location. */
if(step)
{
while((or1k_read_spr_reg(PC_SPRNUM) & 0xFFFFFF00) == 0xD00)
or1k_do_1_processor_step();
}
#endif
 
/* We can now continue normally, independent of step */
or1k_unstall ();
or1k_status = TARGET_RUNNING;
}
674,13 → 758,25
or1k_error ("Remote failure: %s", or1k_err_name (err));
 
/* Wait for or1k DRR register to be nonzero. */
interrupt_requested = 0;
old_sigint = signal (SIGINT, or1k_request_int);
do
{
if(interrupt_requested)
{
or1k_stall();
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_INT;
or1k_status = TARGET_STOPPED;
or1k_read_trace();
return 0;
}
drr = or1k_read_spr_reg (DRR_SPRNUM);
usleep (10);
}
while (drr == 0);
 
signal (SIGINT, old_sigint);
status->kind = TARGET_WAITKIND_STOPPED;
or1k_flush_pipeline ();
 
710,6 → 806,10
status->value.sig = TARGET_SIGNAL_REALTIME_40;
else if (drr & DRR_BE)
status->value.sig = TARGET_SIGNAL_TRAP;
else if (drr & DRR_TE)
status->value.sig = TARGET_SIGNAL_REALTIME_41;
else if (drr & DRR_SS) /* CZ 16/09/01 */
status->value.sig = TARGET_SIGNAL_TRAP;
else
{
status->value.sig = TARGET_SIGNAL_UNKNOWN;
739,6 → 839,8
}
hit_watchpoint = !breakpoint;
 
 
#ifndef NEW_PC_HANDLING
/* Cause the trap/breakpoint exception to be ignored. This is
the behavior of the simulator when the PC value is changed
by a write command. All pending exceptions are cleared and
750,6 → 852,24
{
or1k_write_spr_reg(PC_SPRNUM,value);
}
#endif
 
#ifdef NEW_PC_HANDLING
 
/* If we're a software breakpoint and we're currently located
in the breakpoint vector, then we need to reset the pc
back 4 bytes. This will ensure that the instruction gets
executed. If we don't do this, gdb will skip this instruction,
even if we set DECR_PC_AFTER_BREAK, which seems to have no
effect other than to calculate the correct breakpoint
address. */
 
if((b_insn == or1k_read_spr_reg(((pc-4) >> 2) + MEM_SPACE)) &&
or1k_read_spr_reg(PC_SPRNUM) == 0xD00)
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID),pc-4);
 
#endif
 
}
else
hit_watchpoint = 0;
1061,9 → 1181,13
void
or1k_flush_pipeline ()
{
/* CZ 15/09/01 -- Damjan has made it perfectly clear
that the DIR will not be implemented on any chip
as the entire concept is poorly conceived. This
section has therefore been removed. */
/* or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR); */
}
 
/* Print info on this target. */
/trunk/gdb-5.0/gdb/or1k-tdep.c
112,12 → 112,13
"R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
"R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
 
/* Modified by CZ 12/09/01 */
/* vector/floating point registers */
"VFA0", "VFA1", "VFA2", "VFA3", "VFA4", "VFA5", "VFRV ", "VFR7",
"VFR8", "VFR9", "VFR10", "VFR11", "VFR12", "VFR13", "VFR14", "VFR15",
"VFR16", "VFR17", "VFR18", "VFR19", "VFR20", "VFR21", "VFR22", "VFR23",
"VFR24", "VFR25", "VFR26", "VFR27", "VFR28", "VFR29", "VFR30", "VFR31",
"PC", "SR", "EPCR"
"PC", "SR", "EPCR", "ExPC", "ExEAR", "ExSR"
};
 
static char *or1k_group_names[] = {
133,15 → 134,19
} or1k_signals [NUM_OR1K_SIGNALS + 1] =
{
{"RSTE", "Reset Exception"},
{"BUSE", "Bus Error" },
{"DFPE", "Data Page Fault Exception"},
{"IFPE", "Instruction Page Fault Exception"},
{"LPINTE", "Low Priority Interrupt Exception"},
{"AE", "Alignment Exception"},
{"ILINSE" "Illegal Instruction" },
{"HPINTE", "High Priority Interrupt Exception"},
{"DME", "DTLB Miss Exception"},
{"IME", "ITLB Miss Exception"},
{"RE", "Range Exception"},
{"SCE", "SCE Exception"},
{"BRKPTE", "Breakpoint Exception"},
{"TRAPE", "Trap Exception"},
{NULL, NULL}
};
 
190,24 → 195,169
static int prev_length = 10;
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,
which are not compact, so we are mapping them for GDB. */
 
/* Rewritten by CZ 12/09/01 */
int
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);
 
if (regno < MAX_GPR_REGS + MAX_VF_REGS)
return SPR_REG(SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
+ CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);
if (regno == PS_REGNUM)
return SR_SPRNUM;
if (regno == PC_REGNUM)
return PC_SPRNUM;
if (regno == CCR_REGNUM)
return CCR_SPRNUM(CURRENT_CID);
error ("Invalid register number!");
 
switch(regno)
{
case PS_REGNUM: return SR_SPRNUM;
case PC_REGNUM: return PC_SPRNUM;
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!");
break;
}
 
return 0;
}
 
/* Builds and returns register name. */
634,58 → 784,153
memcpy (valbuf, &regbuf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
}
 
/* The or1k cc defines the following
prologue:
00000000 <_proc1>:
0: d7 e1 17 e4 l.sw 0xffffffe4(r1),r2
4: 9c 41 00 00 l.addi r2,r1,0x0
8: 9c 21 ff e8 l.addi r1,r1,0xffffffe8
c: d7 e2 1f f8 l.sw 0xfffffff8(r2),r3
10: d7 e2 27 f4 l.sw 0xfffffff4(r2),r4
14: 84 82 ff f8 l.lwz r4,0xfffffff8(r2)
18: 9d 24 00 00 l.addi r9,r4,0x0
1c: 00 00 00 02 l.j 0x2
20: 15 00 00 00 l.nop
/* CZ -- 25/09/01 -- The prologue handling code has been rewritten
to bring it inline with the new C compiler and various changes
that have been made. The code below expects to see various
instructions that are identified by states. States are ordered
and should flow from one to the next. If a state is encountered
out of order, it is assumed to be function code and not
prologue, so the prologue parsing is terminated. I've tried
several real world tests from the C compiler, and this seems
to recognize the transition from prologue to code even under
a worst case (21 instructions) scenario. */
 
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 */
typedef enum {
PrologueStateMachineStart,
PrologueStateMachineFrameInitialized,
PrologueStateMachineFrameSaved,
PrologueStateMachineFrameAdjusted,
PrologueStateMachineRegisterSaved,
PrologueStateMachineParameterSaved,
PrologueStateMachineInvalid,
} FunctionPrologueStates;
 
CORE_ADDR
or1k_skip_prologue (CORE_ADDR pc)
/* Parse the insn and save the arguments */
static FunctionPrologueStates getPrologueInsnType(unsigned long insn,
int* arg1,int* arg2)
{
unsigned long inst;
CORE_ADDR skip_pc;
CORE_ADDR func_addr, func_end;
struct symtab_and_line sal;
int i;
int offset = 0;
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)
{
int frame_size = 0,i;
FunctionPrologueStates state = PrologueStateMachineStart;
CORE_ADDR t_pc;
/*
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++)
or1k_saved_reg_addr[i] = -1;
 
/* Is there a prologue? */
inst = or1k_fetch_instruction (pc);
if (inst & 0xfc1ff800 != 0xd4011000) return pc; /* l.sw I(r1),r2 */
or1k_saved_reg_addr[2] = offset++;
inst = or1k_fetch_instruction (pc + OR1K_INSTLEN);
if (inst & 0xFFFF0000 != 0x9c410000) return pc; /* l.addi r2,r1,I */
pc += 2 * OR1K_INSTLEN;
inst = or1k_fetch_instruction (pc);
if (inst & 0xFFFF0000 != 0x9c210000) return pc; /* l.addi r1,r1,I */
pc += OR1K_INSTLEN;
for(t_pc=pc; t_pc < (pc + MAX_PROLOGUE_LENGTH) &&
state != PrologueStateMachineInvalid; t_pc += OR1K_INSTLEN)
{
unsigned long insn = or1k_fetch_instruction(t_pc);
int reg;
int offset;
FunctionPrologueStates new_state = getPrologueInsnType(insn,&reg,&offset);
 
/* Skip stored registers. */
inst = or1k_fetch_instruction (pc);
while (inst & 0xfc1ff800 != 0xd4020000) /* l.sw 0x0(r2),rx */
{
/* get saved reg. */
or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
pc += OR1K_INSTLEN;
inst = or1k_fetch_instruction (pc);
switch(state)
{
case PrologueStateMachineStart:
if(new_state == PrologueStateMachineFrameInitialized)
{
frame_size = -offset;
or1k_saved_reg_addr[1] = frame_size;
}
else
new_state = PrologueStateMachineInvalid;
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. */
732,8 → 977,50
frame pointer. */
fp = FRAME_FP (frame);
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)
{
CORE_ADDR fpp, lr;
758,17 → 1045,44
{
int i;
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);
/* 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++)
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
read_next_frame_reg (fi, regno)
struct frame_info *fi;
785,7 → 1099,12
if (fi->saved_regs == NULL)
or1k_init_saved_regs (fi);
if (fi->saved_regs[regno])
return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
{
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_register (regno);
2176,9 → 2495,10
add_com ("spr", class_support, spr_command, "Set specified SPR register.");
 
/* hwatch command. */
add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watchpoint.\n\
Example: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_var)&&($SDATA >= 50).\n\
See OR1k Architecture document for more info.");
add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watch"
"point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
"var)&&($SDATA >= 50).\nSee OR1k Architecture document for more"
" info.");
 
/* htrace commands. */
add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
/trunk/gdb-5.0/gdb/config/or1k/tm-or1k.h
28,6 → 28,17
#include "defs.h"
#include <inttypes.h> /* CZ */
 
/* CZ 11/09/01 -- Cause GDB to expect actual PC value to appear
in breakpoint exception vector instead of being in PC itself */
 
#define NEW_PC_HANDLING
 
#ifdef NEW_PC_HANDLING
#define TARGET_READ_PC(pid) or1k_target_read_pc(pid)
#define TARGET_WRITE_PC(pc,pid) or1k_target_write_pc(pc,pid)
#endif
 
 
struct value;
 
struct struct_or1k_implementation
144,6 → 155,21
#define PS_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 1)
#define CCR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 2)
 
/*******************************************/
/* Added by CZ on 12/09/01 Used for new style breakpoints */
/* These really aren't designed to be seen by the user */
#define EPC_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 3)
#define EAR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 4)
#define ESR_REGNUM (MAX_GPR_REGS + MAX_VF_REGS + 5)
 
#define EPC_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP,32+cid)
#define EAR_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP,48+cid)
#define ESR_SPRNUM(cid) SPR_REG(SPR_SYSTEM_GROUP,64+cid)
 
#define MAX_EXTRA_NUM_REGS 6
 
/******** END OF ADDITIONS BY CZ ************/
 
extern int or1k_regnum_to_sprnum PARAMS ((int regno));
#define REGNUM_TO_SPRNUM(regno) (or1k_regnum_to_sprnum(regno))
 
151,6 → 177,8
#define DMR1_ST (0x00400000)
 
/* Changed by CZ 21/06/01 */
#define DRR_SS (0x00004000)
#define DRR_TE (0x00002000)
#define DRR_BE (0x00001000)
#define DRR_SCE (0x00000800)
#define DRR_RE (0x00000400)
177,9 → 205,12
#define NUM_VF_REGS (or1k_implementation.num_vfpr_regs)
#define MAX_VF_REGS (32)
 
/*******************************/
/* Paramterized by CZ 11/09/01 */
/*******************************/
/* gdb mapping of registers */
#ifndef NUM_REGS
#define NUM_REGS (MAX_GPR_REGS+MAX_VF_REGS+3)
#define NUM_REGS (MAX_GPR_REGS+MAX_VF_REGS+MAX_EXTRA_NUM_REGS)
#endif
 
/* Can act like a little or big endian. */
270,11 → 301,23
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
 
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
/* Note: several attempts have been made to account for
differences between hardware and software breakpoints
and still allow hardware breakpoints to advance the
PC beyond the offending instruction. However, short
of rewriting gdb, none of them seem to work. Thus,
for now, we assume that a hardware breakpoint will
always give control to the breakpoint vector BEFORE
it executes the instruction, thus, when the breakpoint
vector returns, it will return to the same instruction
that caused the exception (and thus hit the exception
again if it hasn't been cleared) Note that if it actually
executes this instruction, things fail bandly inside of
gdb. This should not be an issue for now, as the or1200
implementation will not implement hardware breakpoints
at all.. */
 
#define DECR_PC_AFTER_BREAK 0
 
extern int or1k_insert_breakpoint (CORE_ADDR addr, char *contents_cache);
319,7 → 362,7
/* Given a name (SIGHUP, etc.), return its signal. */
extern enum target_signal or1k_signal_from_name PARAMS ((char *));
 
#define NUM_OR1K_SIGNALS (10)
#define NUM_OR1K_SIGNALS (14)
 
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
357,6 → 400,7
#define SKIP_PROLOGUE(pc) (or1k_skip_prologue (pc))
 
/* FRAMES */
 
#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
 
#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
411,7 → 455,7
/* Is floating/vector unit present. */
#define OR1K_VF_PRESENT (or1k_implementation.vf_present)
 
#define INIT_FRAME_PC /* Not necessary */
/* #define INIT_FRAME_PC */ /* Not necessary */
 
/* Stack grows downward. */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.