* [PATCH] MIPS: Handle MIPS-3D and DSP ASE branch instructions
@ 2011-11-23 21:00 Maciej W. Rozycki
2011-12-05 11:14 ` Joel Brobecker
0 siblings, 1 reply; 4+ messages in thread
From: Maciej W. Rozycki @ 2011-11-23 21:00 UTC (permalink / raw)
To: gdb-patches
Hi,
Not much to say here -- this change adds support for the MIPS-3D ASE
BC1ANY2F, BC1ANY2T, BC1ANY4F and BC1ANY4T as well as DSP ASE BPOSGE32 and
BPOSGE64 instructions where appropriate, specifically to single-stepping
support code, atomic sequence emulation code and branch delay slot
avoidance code. This change relies on recently submitted DSP ASE Linux
support code.
Regression-tested with mips-sde-elf and mips-linux-gnu successfully. OK
to apply?
2011-11-23 Maciej W. Rozycki <macro@codesourcery.com>
gdb/
* mips-tdep.c (mips32_bc1_pc): New function, factored out from...
(mips32_next_pc): ... here. Handle BC1ANY2F, BC1ANY2T, BC1ANY4F,
BC1ANY4T, BPOSGE32 and BPOSGE64 instructions.
(deal_with_atomic_sequence): Likewise.
(mips32_instruction_has_delay_slot): Likewise.
Maciej
gdb-mips-branch-mips3d-dsp.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c 2011-11-23 02:43:20.955595369 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c 2011-11-23 02:43:24.915560841 +0000
@@ -1134,6 +1134,36 @@ mips32_relative_offset (ULONGEST inst)
return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
}
+/* Determine the address of the next instruction executed after the INST
+ floating condition branch instruction at PC. COUNT specifies the
+ number of the floating condition bits tested by the branch. */
+
+static CORE_ADDR
+mips32_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST inst, CORE_ADDR pc, int count)
+{
+ int fcsr = mips_regnum (gdbarch)->fp_control_status;
+ int cnum = (itype_rt (inst) >> 2) & (count - 1);
+ int tf = itype_rt (inst) & 1;
+ int mask = (1 << count) - 1;
+ ULONGEST fcs;
+ int cond;
+
+ if (fcsr == -1)
+ /* No way to handle; it'll most likely trap anyway. */
+ return pc;
+
+ fcs = get_frame_register_unsigned (frame, fcsr);
+ cond = ((fcs >> 24) & 0xfe) | ((fcs >> 23) & 0x01);
+
+ if (((cond >> cnum) & mask) != mask * !tf)
+ pc += mips32_relative_offset (inst);
+ else
+ pc += 4;
+
+ return pc;
+}
+
/* Determine where to set a single step breakpoint while considering
branch prediction. */
static CORE_ADDR
@@ -1166,20 +1196,15 @@ mips32_next_pc (struct frame_info *frame
}
else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
- {
- int tf = itype_rt (inst) & 0x01;
- int cnum = itype_rt (inst) >> 2;
- int fcrcs =
- get_frame_register_signed (frame,
- mips_regnum (get_frame_arch (frame))->
- fp_control_status);
- int cond = ((fcrcs >> 24) & 0xfe) | ((fcrcs >> 23) & 0x01);
-
- if (((cond >> cnum) & 0x01) == tf)
- pc += mips32_relative_offset (inst) + 4;
- else
- pc += 8;
- }
+ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1);
+ else if (itype_op (inst) == 17 && itype_rs (inst) == 9
+ && (itype_rt (inst) & 2) == 0)
+ /* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
+ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 2);
+ else if (itype_op (inst) == 17 && itype_rs (inst) == 10
+ && (itype_rt (inst) & 2) == 0)
+ /* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
+ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
else
pc += 4; /* Not a branch, next instruction is easy. */
}
@@ -1238,6 +1263,25 @@ mips32_next_pc (struct frame_info *frame
else
pc += 8; /* after the delay slot */
break;
+ case 0x1c: /* BPOSGE32 */
+ case 0x1e: /* BPOSGE64 */
+ pc += 4;
+ if (itype_rs (inst) == 0)
+ {
+ unsigned int pos = (op & 2) ? 64 : 32;
+ int dspctl = mips_regnum (gdbarch)->dspctl;
+
+ if (dspctl == -1)
+ /* No way to handle; it'll most likely trap anyway. */
+ break;
+
+ if ((get_frame_register_unsigned (frame,
+ dspctl) & 0x7f) >= pos)
+ pc += mips32_relative_offset (inst);
+ else
+ pc += 4;
+ }
+ break;
/* All of the other instructions in the REGIMM category */
default:
pc += 4;
@@ -2648,7 +2692,9 @@ deal_with_atomic_sequence (struct gdbarc
return 0; /* fallback to the standard single-step code. */
break;
case 1: /* REGIMM */
- is_branch = ((itype_rt (insn) & 0xc) == 0); /* B{LT,GE}Z* */
+ is_branch = (((itype_rt (insn) & 0xc) == 0) /* B{LT,GE}Z* */
+ || (((itype_rt (insn) & 0x1e) == 0)
+ && (itype_rs (insn) == 0))); /* BPOSGE* */
break;
case 2: /* J */
case 3: /* JAL */
@@ -2664,6 +2710,11 @@ deal_with_atomic_sequence (struct gdbarc
is_branch = 1;
break;
case 17: /* COP1 */
+ is_branch = (((itype_rs (insn) == 9) || (itype_rs (insn) == 10))
+ && ((itype_rt (insn) & 0x2) == 0));
+ if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+ break;
+ /* Fall through. */
case 18: /* COP2 */
case 19: /* COP3 */
is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
@@ -5363,6 +5414,8 @@ mips32_instruction_has_delay_slot (struc
unsigned long inst;
int status;
int op;
+ int rs;
+ int rt;
status = target_read_memory (addr, buf, MIPS_INSN32_SIZE);
if (status)
@@ -5371,10 +5424,19 @@ mips32_instruction_has_delay_slot (struc
inst = mips_fetch_instruction (gdbarch, addr);
op = itype_op (inst);
if ((inst & 0xe0000000) != 0)
- return (op >> 2 == 5) /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
- || (op == 29) /* JALX: bits 011101 */
- || (op == 17 && itype_rs (inst) == 8);
+ {
+ rs = itype_rs (inst);
+ rt = itype_rt (inst);
+ return (op >> 2 == 5) /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
+ || (op == 29) /* JALX: bits 011101 */
+ || ((op == 17)
+ && ((rs == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
+ || ((rs == 9) && ((rt & 0x2) == 0))
+ /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
+ || ((rs == 10) && ((rt & 0x2) == 0))));
+ /* BC1ANY4F, BC1ANY4T: bits 010001 01010 */
+ }
else
{
switch (op & 0x07) /* extract bits 28,27,26 */
@@ -5385,10 +5447,13 @@ mips32_instruction_has_delay_slot (struc
|| (op == 9); /* JALR */
break; /* end SPECIAL */
case 1: /* REGIMM */
- op = itype_rt (inst); /* branch condition */
- return (op & 0xc) == 0;
+ rs = itype_rs (inst);
+ rt = itype_rt (inst); /* branch condition */
+ return ((rt & 0xc) == 0)
/* BLTZ, BLTZL, BGEZ, BGEZL: bits 000xx */
/* BLTZAL, BLTZALL, BGEZAL, BGEZALL: 100xx */
+ || (((rt & 0x1e) == 0x1c) && (rs == 0));
+ /* BPOSGE32, BPOSGE64: bits 1110x */
break; /* end REGIMM */
default: /* J, JAL, BEQ, BNE, BLEZ, BGTZ */
return 1;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] MIPS: Handle MIPS-3D and DSP ASE branch instructions
2011-11-23 21:00 [PATCH] MIPS: Handle MIPS-3D and DSP ASE branch instructions Maciej W. Rozycki
@ 2011-12-05 11:14 ` Joel Brobecker
2011-12-07 21:33 ` Maciej W. Rozycki
0 siblings, 1 reply; 4+ messages in thread
From: Joel Brobecker @ 2011-12-05 11:14 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: gdb-patches
> 2011-11-23 Maciej W. Rozycki <macro@codesourcery.com>
>
> gdb/
> * mips-tdep.c (mips32_bc1_pc): New function, factored out from...
> (mips32_next_pc): ... here. Handle BC1ANY2F, BC1ANY2T, BC1ANY4F,
> BC1ANY4T, BPOSGE32 and BPOSGE64 instructions.
> (deal_with_atomic_sequence): Likewise.
> (mips32_instruction_has_delay_slot): Likewise.
Pre-approved with one minor coding-style change...
> + return (op >> 2 == 5) /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
> + || (op == 29) /* JALX: bits 011101 */
> + || ((op == 17)
> + && ((rs == 8)
> /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
> + || ((rs == 9) && ((rt & 0x2) == 0))
> + /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
> + || ((rs == 10) && ((rt & 0x2) == 0))));
> + /* BC1ANY4F, BC1ANY4T: bits 010001 01010 */
Use an extra pair of parentheses around the entire condition...
--
Joel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] MIPS: Handle MIPS-3D and DSP ASE branch instructions
2011-12-05 11:14 ` Joel Brobecker
@ 2011-12-07 21:33 ` Maciej W. Rozycki
2012-03-01 22:39 ` Maciej W. Rozycki
0 siblings, 1 reply; 4+ messages in thread
From: Maciej W. Rozycki @ 2011-12-07 21:33 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Mon, 5 Dec 2011, Joel Brobecker wrote:
> > 2011-11-23 Maciej W. Rozycki <macro@codesourcery.com>
> >
> > gdb/
> > * mips-tdep.c (mips32_bc1_pc): New function, factored out from...
> > (mips32_next_pc): ... here. Handle BC1ANY2F, BC1ANY2T, BC1ANY4F,
> > BC1ANY4T, BPOSGE32 and BPOSGE64 instructions.
> > (deal_with_atomic_sequence): Likewise.
> > (mips32_instruction_has_delay_slot): Likewise.
>
> Pre-approved with one minor coding-style change...
Thanks, this depends on gdb-mips-dsp-linux.diff, so I'll wait till that
is approved first.
> > + return (op >> 2 == 5) /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
> > + || (op == 29) /* JALX: bits 011101 */
> > + || ((op == 17)
> > + && ((rs == 8)
> > /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
> > + || ((rs == 9) && ((rt & 0x2) == 0))
> > + /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
> > + || ((rs == 10) && ((rt & 0x2) == 0))));
> > + /* BC1ANY4F, BC1ANY4T: bits 010001 01010 */
>
> Use an extra pair of parentheses around the entire condition...
Umm, well... It's just inherited the weird bracketing style from
gdb-mips-breakpoint-adjust.diff; I've fixed both now, removing some
redundant brackets too. That should improve readability somewhat (except
for Lisp lovers perhaps). Here's the result; will apply in due course
unless you have further comments.
Maciej
2011-12-07 Maciej W. Rozycki <macro@codesourcery.com>
gdb/
* mips-tdep.c (mips32_bc1_pc): New function.
(mips32_next_pc): Handle BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T,
BPOSGE32 and BPOSGE64 instructions.
(deal_with_atomic_sequence): Likewise.
(mips32_instruction_has_delay_slot): Likewise.
gdb-mips-branch-mips3d-dsp.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c 2011-12-07 20:32:38.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c 2011-12-07 20:43:52.165559962 +0000
@@ -1134,6 +1134,36 @@ mips32_relative_offset (ULONGEST inst)
return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
}
+/* Determine the address of the next instruction executed after the INST
+ floating condition branch instruction at PC. COUNT specifies the
+ number of the floating condition bits tested by the branch. */
+
+static CORE_ADDR
+mips32_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST inst, CORE_ADDR pc, int count)
+{
+ int fcsr = mips_regnum (gdbarch)->fp_control_status;
+ int cnum = (itype_rt (inst) >> 2) & (count - 1);
+ int tf = itype_rt (inst) & 1;
+ int mask = (1 << count) - 1;
+ ULONGEST fcs;
+ int cond;
+
+ if (fcsr == -1)
+ /* No way to handle; it'll most likely trap anyway. */
+ return pc;
+
+ fcs = get_frame_register_unsigned (frame, fcsr);
+ cond = ((fcs >> 24) & 0xfe) | ((fcs >> 23) & 0x01);
+
+ if (((cond >> cnum) & mask) != mask * !tf)
+ pc += mips32_relative_offset (inst);
+ else
+ pc += 4;
+
+ return pc;
+}
+
/* Determine where to set a single step breakpoint while considering
branch prediction. */
static CORE_ADDR
@@ -1166,20 +1196,15 @@ mips32_next_pc (struct frame_info *frame
}
else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
- {
- int tf = itype_rt (inst) & 0x01;
- int cnum = itype_rt (inst) >> 2;
- int fcrcs =
- get_frame_register_signed (frame,
- mips_regnum (get_frame_arch (frame))->
- fp_control_status);
- int cond = ((fcrcs >> 24) & 0xfe) | ((fcrcs >> 23) & 0x01);
-
- if (((cond >> cnum) & 0x01) == tf)
- pc += mips32_relative_offset (inst) + 4;
- else
- pc += 8;
- }
+ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1);
+ else if (itype_op (inst) == 17 && itype_rs (inst) == 9
+ && (itype_rt (inst) & 2) == 0)
+ /* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
+ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 2);
+ else if (itype_op (inst) == 17 && itype_rs (inst) == 10
+ && (itype_rt (inst) & 2) == 0)
+ /* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
+ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
else
pc += 4; /* Not a branch, next instruction is easy. */
}
@@ -1238,6 +1263,25 @@ mips32_next_pc (struct frame_info *frame
else
pc += 8; /* after the delay slot */
break;
+ case 0x1c: /* BPOSGE32 */
+ case 0x1e: /* BPOSGE64 */
+ pc += 4;
+ if (itype_rs (inst) == 0)
+ {
+ unsigned int pos = (op & 2) ? 64 : 32;
+ int dspctl = mips_regnum (gdbarch)->dspctl;
+
+ if (dspctl == -1)
+ /* No way to handle; it'll most likely trap anyway. */
+ break;
+
+ if ((get_frame_register_unsigned (frame,
+ dspctl) & 0x7f) >= pos)
+ pc += mips32_relative_offset (inst);
+ else
+ pc += 4;
+ }
+ break;
/* All of the other instructions in the REGIMM category */
default:
pc += 4;
@@ -2650,7 +2694,9 @@ deal_with_atomic_sequence (struct gdbarc
return 0; /* fallback to the standard single-step code. */
break;
case 1: /* REGIMM */
- is_branch = ((itype_rt (insn) & 0xc) == 0); /* B{LT,GE}Z* */
+ is_branch = ((itype_rt (insn) & 0xc) == 0 /* B{LT,GE}Z* */
+ || ((itype_rt (insn) & 0x1e) == 0
+ && itype_rs (insn) == 0)); /* BPOSGE* */
break;
case 2: /* J */
case 3: /* JAL */
@@ -2666,6 +2712,11 @@ deal_with_atomic_sequence (struct gdbarc
is_branch = 1;
break;
case 17: /* COP1 */
+ is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10)
+ && (itype_rt (insn) & 0x2) == 0);
+ if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+ break;
+ /* Fall through. */
case 18: /* COP2 */
case 19: /* COP3 */
is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
@@ -5365,6 +5416,8 @@ mips32_instruction_has_delay_slot (struc
unsigned long inst;
int status;
int op;
+ int rs;
+ int rt;
status = target_read_memory (addr, buf, MIPS_INSN32_SIZE);
if (status)
@@ -5373,10 +5426,19 @@ mips32_instruction_has_delay_slot (struc
inst = mips_fetch_instruction (gdbarch, addr);
op = itype_op (inst);
if ((inst & 0xe0000000) != 0)
- return (op >> 2 == 5 /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
- || op == 29 /* JALX: bits 011101 */
- || (op == 17 && itype_rs (inst) == 8));
+ {
+ rs = itype_rs (inst);
+ rt = itype_rt (inst);
+ return (op >> 2 == 5 /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
+ || op == 29 /* JALX: bits 011101 */
+ || (op == 17
+ && (rs == 8
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
+ || (rs == 9 && (rt & 0x2) == 0)
+ /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
+ || (rs == 10 && (rt & 0x2) == 0))));
+ /* BC1ANY4F, BC1ANY4T: bits 010001 01010 */
+ }
else
switch (op & 0x07) /* extract bits 28,27,26 */
{
@@ -5386,10 +5448,13 @@ mips32_instruction_has_delay_slot (struc
|| op == 9); /* JALR */
break; /* end SPECIAL */
case 1: /* REGIMM */
- op = itype_rt (inst); /* branch condition */
- return (op & 0xc) == 0;
+ rs = itype_rs (inst);
+ rt = itype_rt (inst); /* branch condition */
+ return ((rt & 0xc) == 0
/* BLTZ, BLTZL, BGEZ, BGEZL: bits 000xx */
/* BLTZAL, BLTZALL, BGEZAL, BGEZALL: 100xx */
+ || ((rt & 0x1e) == 0x1c && rs == 0));
+ /* BPOSGE32, BPOSGE64: bits 1110x */
break; /* end REGIMM */
default: /* J, JAL, BEQ, BNE, BLEZ, BGTZ */
return 1;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] MIPS: Handle MIPS-3D and DSP ASE branch instructions
2011-12-07 21:33 ` Maciej W. Rozycki
@ 2012-03-01 22:39 ` Maciej W. Rozycki
0 siblings, 0 replies; 4+ messages in thread
From: Maciej W. Rozycki @ 2012-03-01 22:39 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Wed, 7 Dec 2011, Maciej W. Rozycki wrote:
> > > 2011-11-23 Maciej W. Rozycki <macro@codesourcery.com>
> > >
> > > gdb/
> > > * mips-tdep.c (mips32_bc1_pc): New function, factored out from...
> > > (mips32_next_pc): ... here. Handle BC1ANY2F, BC1ANY2T, BC1ANY4F,
> > > BC1ANY4T, BPOSGE32 and BPOSGE64 instructions.
> > > (deal_with_atomic_sequence): Likewise.
> > > (mips32_instruction_has_delay_slot): Likewise.
> >
> > Pre-approved with one minor coding-style change...
>
> Thanks, this depends on gdb-mips-dsp-linux.diff, so I'll wait till that
> is approved first.
So now that gdb-mips-dsp-linux.diff went in I have applied this change as
well.
Maciej
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-03-01 22:39 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-23 21:00 [PATCH] MIPS: Handle MIPS-3D and DSP ASE branch instructions Maciej W. Rozycki
2011-12-05 11:14 ` Joel Brobecker
2011-12-07 21:33 ` Maciej W. Rozycki
2012-03-01 22:39 ` Maciej W. Rozycki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).