PERFORCE change 100869 for review

Wojciech A. Koszek wkoszek at FreeBSD.org
Fri Jul 7 12:20:10 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=100869

Change 100869 by wkoszek at wkoszek_laptop on 2006/07/07 12:19:12

	This is very hackish way of getting db_interface.c work. Some
	routines need to be investigated and uncommented to make kernel with
	DDB more happy. Leave those #ifdef'ed.

Affected files ...

.. //depot/projects/mips2/src/sys/mips/mips/db_interface.c#3 edit

Differences ...

==== //depot/projects/mips2/src/sys/mips/mips/db_interface.c#3 (text+ko) ====

@@ -1,30 +1,31 @@
-/*-
- * Copyright (c) [year] [your name]
- * All rights reserved.
+/*	$NetBSD: db_interface.c,v 1.46 2003/01/17 23:36:11 thorpej Exp $	*/
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * Carnegie Mellon requests users of this software to return to
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ *  Software Distribution Coordinator  or  Software.Distribution at CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
  *
- * $Id$
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
  */
+
 #include "opt_ddb.h"
 
 #include <sys/types.h>
@@ -53,21 +54,727 @@
 #include <ddb/db_output.h>
 #include <ddb/db_sym.h>
 
+int		db_active = 0;
+db_regs_t	ddb_regs;
+register_t	kdbaux[11]; /* XXX struct switchframe: better inside curpcb? XXX */
+
+static void	kdbpoke_4(db_addr_t addr, int newval);
+static void	kdbpoke_2(db_addr_t addr, short newval);
+static void	kdbpoke_1(db_addr_t addr, char newval);
+/*
+ * XXXMIPS:
+ */
+#if 0
+static short	kdbpeek_2(db_addr_t addr);
+static char	kdbpeek_1(db_addr_t addr);
+static db_addr_t	MachEmulateBranch(struct frame *, db_addr_t, unsigned long, int);
+#endif
+
+/*
+ * XXXMIPS:
+ */
+#if 0
+int
+kdbpeek(db_addr_t addr)
+{
+
+	if (addr == 0 || (addr & 3))
+		return 0;
+	return *(int *)addr;
+}
+
+static short
+kdbpeek_2(db_addr_t addr)
+{
+
+	return *(short *)addr;
+}
+
+static char
+kdbpeek_1(db_addr_t addr)
+{
+
+	return *(char *)addr;
+}
+#endif
+
+/*
+ * kdbpoke -- write a value to a kernel virtual address.
+ *    XXX should handle KSEG2 addresses and check for unmapped pages.
+ *    XXX user-space addresess?
+ */
+static void
+kdbpoke_4(db_addr_t addr, int newval)
+{
+
+	*(int*) addr = newval;
+	mips_wbflush();
+}
+
+static void
+kdbpoke_2(db_addr_t addr, short newval)
+{
+
+	*(short*) addr = newval;
+	mips_wbflush();
+}
+
+static void
+kdbpoke_1(db_addr_t addr, char newval)
+{
+	*(char*) addr = newval;
+	mips_wbflush();
+}
+
+#if 0 /* UNUSED */
+/*
+ * Received keyboard interrupt sequence.
+ */
+void
+kdb_kbd_trap(int *tf)
+{
+
+	if (db_active == 0 && (boothowto & RB_KDB)) {
+		printf("\n\nkernel: keyboard interrupt\n");
+		ddb_trap(-1, tf);
+	}
+}
+#endif
+
+/*
+ * XXXMIPS: kdb_trap is disabled for now. I probably saw it somewhere in
+ * subr_kdb.c, but not for sure.
+ */
+#if 0
+int
+kdb_trap(int type, struct trapframe *tfp)
+{
+
+	struct frame *f = (struct frame *)&ddb_regs;
+/*
+ * XXXMIPS:
+ */
+#if 0
+#ifdef notyet
+	switch (type) {
+	case T_BREAK:		/* breakpoint */
+	case -1:		/* keyboard interrupt */
+		break;
+	default:
+		printf("kernel: %s trap", trap_type[type & 0xff]);
+		if (db_recover != 0) {
+			db_error("Faulted in DDB; continuing...\n");
+			/*NOTREACHED*/
+		}
+		break;
+	}
+#endif
+#endif
+	/* Should switch to kdb`s own stack here. */
+	db_set_ddb_regs(type, tfp);
+
+	db_active++;
+	cndbctl(TRUE);
+/*
+ * XXXMIPS:
+ */
+#if 0
+#if	notyet
+	db_trap(type & ~T_USER, 0 /*code*/);
+#else
+	db_trap(type, 0 /*code*/);
+#endif
+#endif
+	cndbctl(FALSE);
+	db_active--;
+/*
+ * XXXMIPS:
+ */
+#if 0
+#if	notyet
+	if (type & T_USER)
+		*(struct frame *)curthread->td_md.md_regs = *f;
+#else
+	if (0)
+		return (1);
+#endif
+#endif
+	else {
+		/* Synthetic full scale register context when trap happens */
+		kdbaux[0] = f->f_regs[S0];
+		kdbaux[1] = f->f_regs[S1];
+		kdbaux[2] = f->f_regs[S2];
+		kdbaux[3] = f->f_regs[S3];
+		kdbaux[4] = f->f_regs[S4];
+		kdbaux[5] = f->f_regs[S5];
+		kdbaux[6] = f->f_regs[S6];
+		kdbaux[7] = f->f_regs[S7];
+		kdbaux[8] = f->f_regs[SP];
+		kdbaux[9] = f->f_regs[S8];
+		kdbaux[10] = f->f_regs[GP];
+	}
+
+	return (1);
+}
+#endif
 
 void
-db_show_mdpcpu(struct pcpu *pc)
+db_set_ddb_regs(int type, struct trapframe *tfp)
 {
+	struct frame *f = (struct frame *)&ddb_regs;
+	
+	/* Should switch to kdb`s own stack here. */
+
+/*
+ * XXXMIPS:
+ */
+#if 0
+#if notyet
+	if (type & T_USER)
+		*f = *(struct frame *)curthread->td_md.md_regs;
+#else
+	if (0)
+		return;
+#endif
+#endif
+	/*
+	 * XXXMIPS: I also added this one.
+	 */
+	if (0)
+		return;
+	else {
+		/* Synthetic full scale register context when trap happens */
+		f->f_regs[AST] = tfp->tf_regs[TF_AST];
+		f->f_regs[V0] = tfp->tf_regs[TF_V0];
+		f->f_regs[V1] = tfp->tf_regs[TF_V1];
+		f->f_regs[A0] = tfp->tf_regs[TF_A0];
+		f->f_regs[A1] = tfp->tf_regs[TF_A1];
+		f->f_regs[A2] = tfp->tf_regs[TF_A2];
+		f->f_regs[A3] = tfp->tf_regs[TF_A3];
+		f->f_regs[T0] = tfp->tf_regs[TF_T0];
+		f->f_regs[T1] = tfp->tf_regs[TF_T1];
+		f->f_regs[T2] = tfp->tf_regs[TF_T2];
+		f->f_regs[T3] = tfp->tf_regs[TF_T3];
+		f->f_regs[TA0] = tfp->tf_regs[TF_TA0];
+		f->f_regs[TA1] = tfp->tf_regs[TF_TA1];
+		f->f_regs[TA2] = tfp->tf_regs[TF_TA2];
+		f->f_regs[TA3] = tfp->tf_regs[TF_TA3];
+		f->f_regs[T8] = tfp->tf_regs[TF_T8];
+		f->f_regs[T9] = tfp->tf_regs[TF_T9];
+		f->f_regs[RA] = tfp->tf_regs[TF_RA];
+		f->f_regs[SR] = tfp->tf_regs[TF_SR];
+		f->f_regs[MULLO] = tfp->tf_regs[TF_MULLO];
+		f->f_regs[MULHI] = tfp->tf_regs[TF_MULHI];
+		f->f_regs[PC] = tfp->tf_regs[TF_EPC];
+		f->f_regs[S0] = kdbaux[0];
+		f->f_regs[S1] = kdbaux[1];
+		f->f_regs[S2] = kdbaux[2];
+		f->f_regs[S3] = kdbaux[3];
+		f->f_regs[S4] = kdbaux[4];
+		f->f_regs[S5] = kdbaux[5];
+		f->f_regs[S6] = kdbaux[6];
+		f->f_regs[S7] = kdbaux[7];
+		f->f_regs[SP] = kdbaux[8];
+		f->f_regs[S8] = kdbaux[9];
+		f->f_regs[GP] = kdbaux[10];
+	}
 }
 
+/*
+ * Read bytes from kernel address space for debugger.
+ */
 int
-db_write_bytes(vm_offset_t addr, size_t size, char *data)
+db_read_bytes(vm_offset_t addr, size_t size, char *data)
 {
+
+/*
+ * XXXMIPS: warning: use of cast expressions as lvalues is deprecated
+ */
+#if 0
+	while (size >= 4)
+		*((int*)data)++ = kdbpeek(addr), addr += 4, size -= 4;
+	while (size >= 2)
+		*((short*)data)++ = kdbpeek_2(addr), addr += 2, size -= 2;
+	if (size == 1)
+		*((char*)data)++ = kdbpeek_1(addr);
+#endif
 	return (0);
 }
 
+/*
+ * Write bytes to kernel address space for debugger.
+ */
 int
-db_read_bytes(vm_offset_t addr, size_t  size, char *data)
+db_write_bytes(vm_offset_t addr, size_t size, char *data)
 {
+	db_addr_t p = addr;
+	size_t n = size;
+
+#ifdef DEBUG_DDB
+	printf("db_write_bytes(%lx, %d, %p, val %x)\n", addr, size, data,
+	       	(addr &3 ) == 0? *(u_int*)addr: -1);
+#endif
+
+	while (n >= 4) {
+		kdbpoke_4(p, *(int*)data);
+		p += 4;
+		data += 4;
+		n -= 4;
+	}
+	if (n >= 2) {
+		kdbpoke_2(p, *(short*)data);
+		p += 2;
+		data += 2;
+		n -= 2;
+	}
+	if (n == 1) {
+		kdbpoke_1(p, *(char*)data);
+	}
+
+	mips_icache_sync_range((db_addr_t) addr, size);
 	return (0);
 }
 
+DB_COMMAND(tlb, db_tlbdump_cmd)
+{
+	u_long hi;
+	u_long lo[2];
+	u_long pm;
+	int i;
+
+	for (i = 0; i < mips_num_tlb_entries; i++) {
+		mips_wr_index(i);
+		mips_tlbr();
+		hi = mips_rd_entryhi();
+		lo[0] = mips_rd_entrylo0();
+		lo[1] = mips_rd_entrylo1();
+		pm = mips_rd_pagemask();
+
+		printf("=== TLB Entry %02d === ", i);
+		printf("(%svalid) ", (lo[0] | lo[1]) & PG_V ? "  " : "in");
+		printf("EntryHi=0x%016lx ", hi);
+		printf("PageMask=%#lx\n", pm);
+		if (*modif != 'a' && (((lo[0] | lo[1]) & PG_V) == 0))
+			continue;
+		printf("\tEntryLo0 = 0x%016lx (%c%c%c)\n", lo[0],
+			(lo[0] & PG_D) ? 'D' : ' ',
+			(lo[0] & PG_G) ? 'G' : ' ',
+			(lo[0] & PG_V) ? 'V' : '!');
+		printf("\tEntryLo1 = 0x%016lx (%c%c%c)\n", lo[1],
+			(lo[1] & PG_D) ? 'D' : ' ',
+			(lo[1] & PG_G) ? 'G' : ' ',
+			(lo[1] & PG_V) ? 'V' : '!');
+	}
+}
+
+DB_COMMAND(kvtop, db_kvtophys_cmd)
+{
+
+	if (!have_addr)
+		return;
+	db_printf("%#lx -> %#lx\n", (u_long)addr,
+		  (u_long)pmap_kextract(addr));
+}
+
+#define	FLDWIDTH	10
+#define	SHOW32(reg, name)						\
+do {									\
+	uint32_t __val;							\
+									\
+	__asm __volatile("mfc0 %0,$" __STRING(reg) : "=r"(__val));		\
+	printf("  %s:%*s %#x\n", name, FLDWIDTH - (int) strlen(name),	\
+	    "", (u_int)__val);						\
+} while (0)
+
+/*
+ * XXXMIPS:
+ */
+#if 0
+/* XXX not 64-bit ABI safe! */
+#define	SHOW64(reg, name)						\
+do {									\
+	uint64_t __val;							\
+									\
+	__asm __volatile("dmfc0 %0,$" __STRING(reg):"=r"(__val));	\
+	printf("  %s:%*s %#lx\n", name, FLDWIDTH - (int) strlen(name),	\
+	    "", (u_long)__val);						\
+} while (0)
+#endif
+
+#define	SHOW64(reg, name)						\
+do {									\
+	uint64_t __val;							\
+									\
+	__asm __volatile("mfc0 %0,$" __STRING(reg):"=r"(__val));	\
+	printf("  %s:%*s %#lx\n", name, FLDWIDTH - (int) strlen(name),	\
+	    "", (u_long)__val);						\
+} while (0)
+
+DB_COMMAND(cp0, db_cp0dump_cmd)
+{
+	SHOW32(MIPS_COP_0_TLB_INDEX, "index");
+	SHOW32(MIPS_COP_0_TLB_RANDOM, "random");
+
+	SHOW64(MIPS_COP_0_TLB_LO0, "entrylo0");
+	SHOW64(MIPS_COP_0_TLB_LO1, "entrylo1");
+
+	SHOW64(MIPS_COP_0_TLB_CONTEXT, "context");
+
+	SHOW32(MIPS_COP_0_TLB_PG_MASK, "pagemask");
+	SHOW32(MIPS_COP_0_TLB_WIRED, "wired");
+
+	SHOW64(MIPS_COP_0_BAD_VADDR, "badvaddr");
+
+	SHOW32(MIPS_COP_0_COUNT, "count");
+
+	SHOW64(MIPS_COP_0_TLB_HI, "entryhi");
+
+	SHOW32(MIPS_COP_0_COMPARE, "compare");
+
+	SHOW32(MIPS_COP_0_STATUS, "status");
+	SHOW32(MIPS_COP_0_CAUSE, "cause");
+
+	SHOW64(MIPS_COP_0_EXC_PC, "epc");
+
+	SHOW32(MIPS_COP_0_PRID, "prid");
+	SHOW32(MIPS_COP_0_CONFIG, "config");
+
+	SHOW64(MIPS_COP_0_LLADDR, "lladdr");
+	SHOW64(MIPS_COP_0_WATCH_LO, "watchlo");
+
+	SHOW32(MIPS_COP_0_WATCH_HI, "watchhi");
+
+	SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext");
+	SHOW64(MIPS_COP_0_PERFCNT, "perfcnt");
+
+	SHOW32(MIPS_COP_0_ECC, "ecc");
+	SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr");
+	SHOW32(MIPS_COP_0_TAG_LO, "cachelo");
+	SHOW32(MIPS_COP_0_TAG_HI, "cachehi");
+
+	SHOW64(MIPS_COP_0_ERROR_PC, "errorpc");
+}
+
+/*
+ * Determine whether the instruction involves a delay slot.
+ */
+boolean_t
+inst_branch(int inst)
+{
+	InstFmt i;
+	int delay;
+
+	i.word = inst;
+	delay = 0;
+	switch (i.JType.op) {
+	case OP_BCOND:
+	case OP_J:
+	case OP_JAL:
+	case OP_BEQ:
+	case OP_BNE:
+	case OP_BLEZ:
+	case OP_BGTZ:
+	case OP_BEQL:
+	case OP_BNEL:
+	case OP_BLEZL:
+	case OP_BGTZL:
+		delay = 1;
+		break;
+
+	case OP_COP0:
+	case OP_COP1:
+		switch (i.RType.rs) {
+		case OP_BCx:
+		case OP_BCy:
+			delay = 1;
+		}
+		break;
+
+	case OP_SPECIAL:
+		if (i.RType.op == OP_JR || i.RType.op == OP_JALR)
+			delay = 1;
+		break;
+	}
+	return delay;
+}
+
+/*
+ * Determine whether the instruction calls a function.
+ */
+boolean_t
+inst_call(int inst)
+{
+	boolean_t call;
+	InstFmt i;
+
+	i.word = inst;
+	if (i.JType.op == OP_SPECIAL
+	    && ((i.RType.func == OP_JR && i.RType.rs != 31) ||
+		i.RType.func == OP_JALR))
+		call = 1;
+	else if (i.JType.op == OP_JAL)
+		call = 1;
+	else
+		call = 0;
+	return call;
+}
+
+/*
+ * Determine whether the instruction returns from a function (j ra).  The
+ * compiler can use this construct for other jumps, but usually will not.
+ * This lets the ddb "next" command to work (also need inst_trap_return()).
+ */
+boolean_t
+inst_return(int inst)
+{
+	InstFmt i;
+
+	i.word = inst;
+
+	return (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR &&
+		i.RType.rs == 31);
+}
+
+/*
+ * Determine whether the instruction makes a jump.
+ */
+boolean_t
+inst_unconditional_flow_transfer(int inst)
+{
+	InstFmt i;
+	boolean_t jump;
+
+	i.word = inst;
+	jump = (i.JType.op == OP_J) ||
+	       (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR);
+	return jump;
+}
+
+/*
+ * Determine whether the instruction is a load/store as appropriate.
+ */
+boolean_t
+inst_load(int inst)
+{
+	InstFmt i;
+
+	i.word = inst;
+
+	switch (i.JType.op) {
+	case OP_LWC1:
+	case OP_LB:
+	case OP_LH:
+	case OP_LW:
+	case OP_LD:
+	case OP_LBU:
+	case OP_LHU:
+	case OP_LWU:
+	case OP_LDL:
+	case OP_LDR:
+	case OP_LWL:
+	case OP_LWR:
+	case OP_LL:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+boolean_t
+inst_store(int inst)
+{
+	InstFmt i;
+
+	i.word = inst;
+
+	switch (i.JType.op) {
+	case OP_SWC1:
+	case OP_SB:
+	case OP_SH:
+	case OP_SW:
+	case OP_SD:
+	case OP_SDL:
+	case OP_SDR:
+	case OP_SWL:
+	case OP_SWR:
+	case OP_SCD:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * Return the next pc if the given branch is taken.
+ * MachEmulateBranch() runs analysis for branch delay slot.
+ */
+#if 0
+db_addr_t
+branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
+{
+	db_addr_t ra;
+	unsigned long fpucsr;
+
+	fpucsr = curthread ? PCB_FSR(curthread->td_pcb) : 0;
+	ra = MachEmulateBranch((struct frame *)regs, pc, fpucsr, 0);
+	return ra;
+}
+#endif
+
+/*
+ * Return the next pc of an arbitrary instruction.
+ */
+db_addr_t
+next_instr_address(db_addr_t pc, boolean_t bd)
+{
+	unsigned ins;
+
+	if (bd == FALSE)
+		return (pc + 4);
+	
+	if (pc < MIPS_KSEG0_START)
+		ins = fuword((void *)pc);
+	else
+		ins = *(unsigned *)pc;
+
+	if (inst_branch(ins) || inst_call(ins) || inst_return(ins))
+		return (pc + 4);
+
+	return (pc);
+}
+
+void
+db_show_mdpcpu(struct pcpu *pc)
+{
+}
+
+DB_COMMAND(reboot, db_reboot)
+{
+	cpu_reset();
+}
+
+DB_COMMAND(halt, db_halt)
+{
+	cpu_halt();
+}
+
+#if 0
+/*
+ * Analyse 'next' PC address taking account of branch/jump instructions
+ */
+static db_addr_t
+MachEmulateBranch(f, instpc, fpuCSR, allowNonBranch)
+	struct frame *f;
+	db_addr_t instpc;
+	unsigned long fpuCSR;
+	int allowNonBranch;
+{
+#define	BRANCHTARGET(p) (4 + (p) + ((short)((InstFmt *)(p))->IType.imm << 2))
+	InstFmt inst;
+	db_addr_t nextpc;
+
+	if (instpc < MIPS_KSEG0_START)
+		inst.word = fuword((void *)instpc);
+	else
+		inst.word = *(unsigned *)instpc;
+
+	switch ((int)inst.JType.op) {
+	case OP_SPECIAL:
+		if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR)
+			nextpc = f->f_regs[inst.RType.rs];
+		else if (allowNonBranch)
+			nextpc = instpc + 4;
+		else
+			panic("MachEmulateBranch: Non-branch");
+		break;
+
+	case OP_BCOND:
+		switch ((int)inst.IType.rt) {
+		case OP_BLTZ:
+		case OP_BLTZAL:
+		case OP_BLTZL:		/* squashed */
+		case OP_BLTZALL:	/* squashed */
+			if ((int)(f->f_regs[inst.RType.rs]) < 0)
+				nextpc = BRANCHTARGET(instpc);
+			else
+				nextpc = instpc + 8;
+			break;
+
+		case OP_BGEZ:
+		case OP_BGEZAL:
+		case OP_BGEZL:		/* squashed */
+		case OP_BGEZALL:	/* squashed */
+			if ((int)(f->f_regs[inst.RType.rs]) >= 0)
+				nextpc = BRANCHTARGET(instpc);
+			else
+				nextpc = instpc + 8;
+			break;
+
+		default:
+			panic("MachEmulateBranch: Bad branch cond");
+		}
+		break;
+
+	case OP_J:
+	case OP_JAL:
+		nextpc = (inst.JType.target << 2) |
+			((register_t)instpc & 0xF0000000);
+		break;
+
+	case OP_BEQ:
+	case OP_BEQL:	/* squashed */
+		if (f->f_regs[inst.RType.rs] == f->f_regs[inst.RType.rt])
+			nextpc = BRANCHTARGET(instpc);
+		else
+			nextpc = instpc + 8;
+		break;
+
+	case OP_BNE:
+	case OP_BNEL:	/* squashed */
+		if (f->f_regs[inst.RType.rs] != f->f_regs[inst.RType.rt])
+			nextpc = BRANCHTARGET(instpc);
+		else
+			nextpc = instpc + 8;
+		break;
+
+	case OP_BLEZ:
+	case OP_BLEZL:	/* squashed */
+		if ((int)(f->f_regs[inst.RType.rs]) <= 0)
+			nextpc = BRANCHTARGET(instpc);
+		else
+			nextpc = instpc + 8;
+		break;
+
+	case OP_BGTZ:
+	case OP_BGTZL:	/* squashed */
+		if ((int)(f->f_regs[inst.RType.rs]) > 0)
+			nextpc = BRANCHTARGET(instpc);
+		else
+			nextpc = instpc + 8;
+		break;
+
+	case OP_COP1:
+		if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) {
+			int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0;
+			if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE)
+				condition = !condition;
+			if (condition)
+				nextpc = BRANCHTARGET(instpc);
+			else
+				nextpc = instpc + 8;
+		}
+		else if (allowNonBranch)
+			nextpc = instpc + 4;
+		else
+			panic("MachEmulateBranch: Bad COP1 branch instruction");
+		break;
+
+	default:
+		if (!allowNonBranch)
+			panic("MachEmulateBranch: Non-branch instruction");
+		nextpc = instpc + 4;
+	}
+	return nextpc;
+#undef	BRANCHTARGET
+}
+#endif


More information about the p4-projects mailing list