Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc64 Add debugger single-stepping and fix interr...
details: https://anonhg.NetBSD.org/src/rev/1c9d6687054e
branches: trunk
changeset: 480372:1c9d6687054e
user: eeh <eeh%NetBSD.org@localhost>
date: Mon Jan 10 03:53:20 2000 +0000
description:
Add debugger single-stepping and fix interrupt dispatch bugs.
diffstat:
sys/arch/sparc64/include/db_machdep.h | 41 +++-
sys/arch/sparc64/include/instr.h | 31 +++-
sys/arch/sparc64/include/reg.h | 12 +-
sys/arch/sparc64/sparc64/db_interface.c | 248 +++++++++++++++++++++++++++-
sys/arch/sparc64/sparc64/intr.c | 20 +-
sys/arch/sparc64/sparc64/locore.s | 46 +++-
sys/arch/sparc64/sparc64/process_machdep.c | 9 +-
sys/arch/sparc64/sparc64/trap.c | 9 +-
8 files changed, 355 insertions(+), 61 deletions(-)
diffs (truncated from 695 to 300 lines):
diff -r 81a08dd595f9 -r 1c9d6687054e sys/arch/sparc64/include/db_machdep.h
--- a/sys/arch/sparc64/include/db_machdep.h Mon Jan 10 03:24:31 2000 +0000
+++ b/sys/arch/sparc64/include/db_machdep.h Mon Jan 10 03:53:20 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.h,v 1.8 1999/11/06 20:13:50 eeh Exp $ */
+/* $NetBSD: db_machdep.h,v 1.9 2000/01/10 03:53:20 eeh Exp $ */
/*
* Mach Operating System
@@ -96,18 +96,39 @@
#define BKPT_SIZE (4) /* size of breakpoint inst */
#define BKPT_SET(inst) (BKPT_INST)
-#define db_clear_single_step(regs) (void) (0)
-#define db_set_single_step(regs) (void) (0)
-
#define IS_BREAKPOINT_TRAP(type, code) \
((type) == T_BREAKPOINT || (type) == T_KGDB_EXEC)
-#define IS_WATCHPOINT_TRAP(type, code) (0)
+#define IS_WATCHPOINT_TRAP(type, code) \
+ ((type) ==T_PA_WATCHPT || (type) == T_VA_WATCHPT)
+
+/*
+ * Sparc cpus have no hardware single-step.
+ */
+#define SOFTWARE_SSTEP
-#define inst_trap_return(ins) ((ins)&0)
-#define inst_return(ins) ((ins)&0)
-#define inst_call(ins) ((ins)&0)
-#define inst_load(ins) 0
-#define inst_store(ins) 0
+boolean_t db_inst_trap_return __P((int inst));
+boolean_t db_inst_return __P((int inst));
+boolean_t db_inst_call __P((int inst));
+boolean_t db_inst_branch __P((int inst));
+int db_inst_load __P((int inst));
+int db_inst_store __P((int inst));
+boolean_t db_inst_unconditional_flow_transfer __P((int inst));
+db_addr_t db_branch_taken __P((int inst, db_addr_t pc, db_regs_t *regs));
+
+#define inst_trap_return(ins) db_inst_trap_return(ins)
+#define inst_return(ins) db_inst_return(ins)
+#define inst_call(ins) db_inst_call(ins)
+#define inst_branch(ins) db_inst_branch(ins)
+#define inst_load(ins) db_inst_load(ins)
+#define inst_store(ins) db_inst_store(ins)
+#define inst_unconditional_flow_transfer(ins) \
+ db_inst_unconditional_flow_transfer(ins)
+#define branch_taken(ins, pc, regs) \
+ db_branch_taken((ins), (pc), (regs))
+
+/* see note in db_interface.c about reversed breakpoint addrs */
+#define next_instr_address(pc, bd) \
+ ((bd) ? (pc) : ddb_regs.ddb_tf.tf_npc)
#define DB_MACHINE_COMMANDS
diff -r 81a08dd595f9 -r 1c9d6687054e sys/arch/sparc64/include/instr.h
--- a/sys/arch/sparc64/include/instr.h Mon Jan 10 03:24:31 2000 +0000
+++ b/sys/arch/sparc64/include/instr.h Mon Jan 10 03:53:20 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: instr.h,v 1.2 1998/09/22 02:48:43 eeh Exp $ */
+/* $NetBSD: instr.h,v 1.3 2000/01/10 03:53:20 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -46,8 +46,8 @@
/* see also Appendix F of the SPARC version 8 document */
enum IOP { IOP_OP2, IOP_CALL, IOP_reg, IOP_mem };
-enum IOP2 { IOP2_UNIMP, IOP2_err1, IOP2_Bicc, IOP2_err3,
- IOP2_SETHI, IOP2_err5, IOP2_FBfcc, IOP2_CBccc };
+enum IOP2 { IOP2_UNIMP, IOP2_BPcc, IOP2_Bicc, IOP2_BPr,
+ IOP2_SETHI, IOP2_FBPfcc, IOP2_FBfcc, IOP2_CBccc };
enum IOP3_reg {
IOP3_ADD, IOP3_AND, IOP3_OR, IOP3_XOR,
IOP3_SUB, IOP3_ANDN, IOP3_ORN, IOP3_XNOR,
@@ -193,6 +193,31 @@
int i_disp:22; /* branch displacement */
} i_branch;
+ /* more branches: BPcc, FBPfcc */
+ struct {
+ u_int :2; /* 00 */
+ u_int i_annul:1; /* annul bit */
+ u_int i_cond:4; /* condition codes */
+ u_int i_op2:3; /* opcode: {BP,FBPf}cc */
+ u_int i_cc:2; /* condition code selector */
+ u_int i_pred:1; /* branch prediction bit */
+ int i_disp:19; /* branch displacement */
+ } i_branch_p;
+
+ /* one last branch: BPr */
+ struct {
+ u_int :2; /* 00 */
+ u_int i_annul:1; /* annul bit */
+ u_int :1; /* 0 */
+ u_int i_rcond:4; /* register condition */
+ u_int :3; /* 011 */
+ int i_disphi:2; /* branch displacement, hi bits */
+ u_int i_pred:1; /* branch prediction bit */
+ u_int i_rs1:1; /* source register 1 */
+ u_int i_displo:16; /* branch displacement, lo bits */
+ } i_branch_pr;
+
+
/*
* Format 3 instructions (memory reference; arithmetic, logical,
* shift, and other miscellaneous operations). The second-level
diff -r 81a08dd595f9 -r 1c9d6687054e sys/arch/sparc64/include/reg.h
--- a/sys/arch/sparc64/include/reg.h Mon Jan 10 03:24:31 2000 +0000
+++ b/sys/arch/sparc64/include/reg.h Mon Jan 10 03:53:20 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: reg.h,v 1.5 1999/12/30 16:20:43 eeh Exp $ */
+/* $NetBSD: reg.h,v 1.6 2000/01/10 03:53:20 eeh Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -142,6 +142,8 @@
* ``I'd suggest allowing 16 ... allowing an indeterminate variable
* size would be even better''. Of course, we cannot do that; we
* need to malloc these.
+ *
+ * XXXX UltraSPARC processors don't implement a floating point queue.
*/
#define FP_QSIZE 16
#define ALIGNFPSTATE(f) ((struct fpstate64 *)(((long)(f))&(~BLOCK_ALIGN)))
@@ -170,14 +172,14 @@
};
/*
- * Clone fpstate into an fpreg structure to satisfy <kern/sys_process.c>
+ * The actual FP registers are made accessable (c.f. ptrace(2)) through
+ * a `struct fpreg'; <arch/sparc64/sparc64/process_machdep.c> relies on the
+ * fact that `fpreg' is a prefix of `fpstate'.
*/
struct fpreg64 {
u_int fr_regs[64]; /* our view is 64 32-bit registers */
int64_t fr_fsr; /* %fsr */
int fr_gsr; /* graphics state reg */
- int fr_qsize; /* actual queue depth */
- struct fp_qentry fr_queue[FP_QSIZE]; /* queue contents */
};
/*
@@ -186,8 +188,6 @@
struct fpreg32 {
u_int fr_regs[32]; /* our view is 32 32-bit registers */
int fr_fsr; /* %fsr */
- int fr_qsize; /* actual queue depth */
- struct fp_qentry fr_queue[FP_QSIZE]; /* queue contents */
};
#if defined(__arch64__)
diff -r 81a08dd595f9 -r 1c9d6687054e sys/arch/sparc64/sparc64/db_interface.c
--- a/sys/arch/sparc64/sparc64/db_interface.c Mon Jan 10 03:24:31 2000 +0000
+++ b/sys/arch/sparc64/sparc64/db_interface.c Mon Jan 10 03:53:20 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.25 1999/12/30 16:34:02 eeh Exp $ */
+/* $NetBSD: db_interface.c,v 1.26 2000/01/10 03:53:22 eeh Exp $ */
/*
* Mach Operating System
@@ -52,6 +52,7 @@
#include <ddb/db_output.h>
#include <ddb/db_interface.h>
+#include <machine/instr.h>
#include <machine/cpu.h>
#include <machine/openfirm.h>
#include <machine/ctlreg.h>
@@ -179,13 +180,6 @@
default:
printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
if (db_recover != 0) {
-#if 0
-#ifdef __arch64__
- /* For now, don't get into infinite DDB trap loop */
- printf("Faulted in DDB; going to OBP...\n");
- OF_enter();
-#endif
-#endif
db_error("Faulted in DDB; continuing...\n");
OF_enter();
/*NOTREACHED*/
@@ -224,10 +218,10 @@
}
#endif
+ s = splhigh();
db_active++;
cnpollc(TRUE);
/* Need to do spl stuff till cnpollc works */
- s = splhigh();
tl = savetstate(ts);
for (i=0; i<tl; i++) {
printf("%d tt=%lx tstate=%lx tpc=%p tnpc=%p\n",
@@ -236,15 +230,15 @@
}
db_trap(type, 0/*code*/);
restoretstate(tl,ts);
- splx(s);
cnpollc(FALSE);
db_active--;
+ splx(s);
#if 0
/* We will not alter the machine's running state until we get everything else working */
*(struct frame *)tf->tf_out[6] = ddb_regs.ddb_fr;
+#endif
*tf = ddb_regs.ddb_tf;
-#endif
trap_trace_dis = traptrace_enabled;
return (1);
@@ -865,3 +859,235 @@
{
db_machine_commands_install(sparc_db_command_table);
}
+
+/*
+ * support for SOFTWARE_SSTEP:
+ * return the next pc if the given branch is taken.
+ *
+ * note: in the case of conditional branches with annul,
+ * this actually returns the next pc in the "not taken" path,
+ * but in that case next_instr_address() will return the
+ * next pc in the "taken" path. so even tho the breakpoints
+ * are backwards, everything will still work, and the logic is
+ * much simpler this way.
+ */
+db_addr_t
+db_branch_taken(inst, pc, regs)
+ int inst;
+ db_addr_t pc;
+ db_regs_t *regs;
+{
+ union instr insn;
+ db_addr_t npc = ddb_regs.ddb_tf.tf_npc;
+
+ insn.i_int = inst;
+
+ /*
+ * if this is not an annulled conditional branch, the next pc is "npc".
+ */
+
+ if (insn.i_any.i_op != IOP_OP2 || insn.i_branch.i_annul != 1)
+ return npc;
+
+ switch (insn.i_op2.i_op2) {
+ case IOP2_Bicc:
+ case IOP2_FBfcc:
+ case IOP2_BPcc:
+ case IOP2_FBPfcc:
+ case IOP2_CBccc:
+ /* branch on some condition-code */
+ switch (insn.i_branch.i_cond)
+ {
+ case Icc_A: /* always */
+ return pc + ((inst << 10) >> 8);
+
+ default: /* all other conditions */
+ return npc + 4;
+ }
+
+ case IOP2_BPr:
+ /* branch on register, always conditional */
+ return npc + 4;
+
+ default:
+ /* not a branch */
+ panic("branch_taken() on non-branch");
+ }
+}
+
+boolean_t
+db_inst_branch(inst)
+ int inst;
+{
+ union instr insn;
+
+ insn.i_int = inst;
+
+ if (insn.i_any.i_op != IOP_OP2)
+ return FALSE;
+
+ switch (insn.i_op2.i_op2) {
+ case IOP2_BPcc:
+ case IOP2_Bicc:
+ case IOP2_BPr:
+ case IOP2_FBPfcc:
+ case IOP2_FBfcc:
+ case IOP2_CBccc:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
Home |
Main Index |
Thread Index |
Old Index