This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
gdb 5.0: mips-tdep.c (mips32_next_pc): branches get misdecoded (fwd)
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: gdb 5.0: mips-tdep.c (mips32_next_pc): branches get misdecoded (fwd)
- From: "Maciej W. Rozycki" <macro at ds2 dot pg dot gda dot pl>
- Date: Wed, 21 Jun 2000 16:14:23 +0200 (MET DST)
- Organization: Technical University of Gdansk
---------- Forwarded message ----------
Message-ID: <Pine.GSO.3.96.1000619190736.10348R-100000@delta.ds2.pg.gda.pl>
Date: Mon, 19 Jun 2000 19:17:39 +0200 (MET DST)
From: "Maciej W. Rozycki" <macro@ds2.pg.gda.pl>
To: bug-gdb@gnu.org
Subject: gdb 5.0: mips-tdep.c (mips32_next_pc): branches get misdecoded
Hi,
Due to a number of bugs mips32_next_pc () does not get many of the
branches right. As a result breakpoints get inserted in wrong places thus
single-stepping does not work as expected. The following patch fixes the
problem for me. It also cleans up comments a bit.
I was only able to test it on a MIPS I CPU so likely branches are not
runtime tested. All of them were verified with MIPS documentation.
Maciej
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro@ds2.pg.gda.pl, PGP key available +
diff -u --recursive --new-file gdb-5.0.macro/gdb/mips-tdep.c gdb-5.0/gdb/mips-tdep.c
--- gdb-5.0.macro/gdb/mips-tdep.c Sun Apr 9 14:35:35 2000
+++ gdb-5.0/gdb/mips-tdep.c Sat Jun 17 15:29:42 2000
@@ -596,21 +596,21 @@
unsigned long inst;
int op;
inst = mips_fetch_instruction (pc);
- if ((inst & 0xe0000000) != 0) /* Not a special, junp or branch instruction */
+ if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch instruction */
{
- if ((inst >> 27) == 5) /* BEQL BNEZ BLEZL BGTZE , bits 0101xx */
+ if ((inst >> 28) == 5) /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
{
- op = ((inst >> 25) & 0x03);
+ op = ((inst >> 26) & 0x03);
switch (op)
{
- case 0:
- goto equal_branch; /* BEQL */
- case 1:
- goto neq_branch; /* BNEZ */
- case 2:
- goto less_branch; /* BLEZ */
- case 3:
- goto greater_branch; /* BGTZ */
+ case 0: /* BEQL */
+ goto equal_branch;
+ case 1: /* BNEL */
+ goto neq_branch;
+ case 2: /* BLEZL */
+ goto less_branch;
+ case 3: /* BGTZ */
+ goto greater_branch;
default:
pc += 4;
}
@@ -636,45 +636,45 @@
pc += 4;
}
- break; /* end special */
+ break; /* end SPECIAL */
case 1: /* REGIMM */
{
op = jtype_op (inst); /* branch condition */
switch (jtype_op (inst))
{
case 0: /* BLTZ */
- case 2: /* BLTXL */
- case 16: /* BLTZALL */
+ case 2: /* BLTZL */
+ case 16: /* BLTZAL */
case 18: /* BLTZALL */
less_branch:
- if (read_register (itype_rs (inst)) < 0)
+ if ((LONGEST) read_register (itype_rs (inst)) < 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
break;
- case 1: /* GEZ */
+ case 1: /* BGEZ */
case 3: /* BGEZL */
case 17: /* BGEZAL */
case 19: /* BGEZALL */
greater_equal_branch:
- if (read_register (itype_rs (inst)) >= 0)
+ if ((LONGEST) read_register (itype_rs (inst)) >= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
break;
- /* All of the other intructions in the REGIMM catagory */
+ /* All of the other instructions in the REGIMM category */
default:
pc += 4;
}
}
- break; /* end REGIMM */
+ break; /* end REGIMM */
case 2: /* J */
case 3: /* JAL */
{
unsigned long reg;
reg = jtype_target (inst) << 2;
+ /* Upper four bits never changed... */
pc = reg + ((pc + 4) & 0xf0000000);
- /* Whats this mysterious 0xf000000 adjustment ??? */
}
break;
/* FIXME case JALX : */
@@ -685,38 +685,37 @@
/* Add 1 to indicate 16 bit mode - Invert ISA mode */
}
break; /* The new PC will be alternate mode */
- case 4: /* BEQ , BEQL */
+ case 4: /* BEQ, BEQL */
equal_branch:
- if (read_register (itype_rs (inst)) ==
- read_register (itype_rt (inst)))
+ if ((LONGEST) read_register (itype_rs (inst)) ==
+ (LONGEST) read_register (itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
- case 5: /* BNE , BNEL */
+ case 5: /* BNE, BNEL */
neq_branch:
- if (read_register (itype_rs (inst)) !=
- read_register (itype_rs (inst)))
+ if ((LONGEST) read_register (itype_rs (inst)) !=
+ (LONGEST) read_register (itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
- case 6: /* BLEZ , BLEZL */
+ case 6: /* BLEZ, BLEZL */
less_zero_branch:
- if (read_register (itype_rs (inst) <= 0))
+ if ((LONGEST) read_register (itype_rs (inst)) <= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 7:
- greater_branch: /* BGTZ BGTZL */
- if (read_register (itype_rs (inst) > 0))
+ default:
+ greater_branch: /* BGTZ, BGTZL */
+ if ((LONGEST) read_register (itype_rs (inst)) > 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
- default:
- pc += 8;
} /* switch */
} /* else */
return pc;