This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 19/24] Add MIPS MSA vector branch instruction support
- From: Bhushan Attarde <bhushan dot attarde at imgtec dot com>
- To: <gdb-patches at sourceware dot org>
- Cc: <Maciej dot Rozycki at imgtec dot com>, <Matthew dot Fortune at imgtec dot com>, <James dot Hogan at imgtec dot com>, <Andrew dot Bennett at imgtec dot com>, <Jaydeep dot Patil at imgtec dot com>, Bhushan Attarde <bhushan dot attarde at imgtec dot com>
- Date: Mon, 27 Jun 2016 20:19:46 +0530
- Subject: [PATCH 19/24] Add MIPS MSA vector branch instruction support
- Authentication-results: sourceware.org; auth=none
- References: <1467038991-6600-1-git-send-email-bhushan dot attarde at imgtec dot com>
Add support for the MIPS & microMIPS MSA vector branch instructions,
primarily to allow them to be single stepped.
There are 4 such branch encodings:
- BZ.df (BZ.B, BZ.H, BZ.W, BZ.D)
Branch if any element in vector in the given format is zero.
- BZ.V
Branch if every element in vector in any format (i.e. the whole vector)
is zero.
- BNZ.df (BZ.B, BZ.H, BZ.W, BZ.D)
Branch if no element in vector in the given format is zero. This is the
inverse of BZ.df.
- BNZ.V
Branch if any element in vector in any format (i.e. any bit in whole
vector) is non-zero. This is the inverse of BZ.V.
The MIPS encodings use the COP1 opcode, and the microMIPS encodings use
the POOL32D opcode.
gdb/ChangeLog:
* mips-tdep.c (mips_bc1_w_taken): New function.
(mips32_bc1_w_pc): Likewise.
(micromips_bc1_w_pc): Likewise.
(mips32_next_pc): Add cases for BZ.df/BNZ.df and BZ.V/BNZ.V.
(micromips_next_pc): Likewise.
(mips_deal_with_atomic_sequence): Recognise BZ.df/BNZ.df and
BZ.V/BNZ.V as branches.
(micromips_deal_with_atomic_sequence): Likewise.
(mips32_instruction_has_delay_slot): Likewise.
(micromips_instruction_has_delay_slot): Likewise.
---
gdb/mips-tdep.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 171 insertions(+), 4 deletions(-)
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 63291db..7a6d23d 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -2496,6 +2496,100 @@ mips32_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
return pc;
}
+/* Determine whether a vector branch will be taken.
+ Returns 1 if branch taken, 0 if branch not taken, -1 on error. */
+
+static int
+mips_bc1_w_taken (struct gdbarch *gdbarch, struct frame_info *frame,
+ unsigned int op, unsigned int wt)
+{
+ int wr = gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->w0;
+ int taken = -1;
+ int size, elem_size, tog;
+ gdb_byte *buf, *end, *elem_end;
+
+ if (wr == -1)
+ /* No way to handle; it'll most likely trap anyway. */
+ return -1;
+ wr += wt;
+
+ /* Read vector register. */
+ size = register_size (gdbarch, wr);
+ buf = alloca (size);
+ if (!deprecated_frame_register_read (frame, wr, buf))
+ return -1;
+
+ if ((op & 0x18) == 0x18)
+ {
+ elem_size = 1 << (op & 0x3);
+ /* Check whether this branch would be taken first:
+ BZ.df: 110xx (branch if at least one element is zero) */
+ taken = 0;
+ for (end = buf + size; buf < end;)
+ {
+ taken = 1;
+ for (elem_end = buf + elem_size; buf < elem_end; ++buf)
+ if (*buf)
+ {
+ /* this element is non-zero */
+ taken = 0;
+ break;
+ }
+ if (taken)
+ /* this element zero, branch taken */
+ break;
+ buf = elem_end;
+ }
+
+ if (op & 0x4)
+ /* BNZ.df: 111xx (branch if all elements are non-zero)
+ Branch taken is inverted compared to BZ.df */
+ taken = !taken;
+ }
+ else if ((op & 0x1b) == 0x0b)
+ {
+ /* Check whether this branch would be taken first:
+ BZ.V: 01011 (branch if all elements are zero) */
+ taken = 1;
+ for (end = buf + size; buf < end; ++buf)
+ if (*buf)
+ {
+ /* this element is non-zero, branch not taken */
+ taken = 0;
+ break;
+ }
+ if (op & 0x4)
+ /* BNZ.V: 01111 (branch if any elements are non-zero)
+ Branch taken is inverted compared to BZ.V */
+ taken = !taken;
+ }
+
+ return taken;
+}
+
+/* Determine the address of the next instruction executed after the INST
+ vector branch instruction at PC. */
+
+static CORE_ADDR
+mips32_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST inst, CORE_ADDR pc)
+{
+ int op = itype_rs (inst);
+ int wt = itype_rt (inst);
+ int taken;
+
+ /* Will the branch be taken? */
+ taken = mips_bc1_w_taken (gdbarch, frame, op, wt);
+
+ /* Calculate branch target */
+ if (taken > 0)
+ pc += mips32_relative_offset (inst);
+ else if (taken == 0)
+ pc += 4;
+
+ return pc;
+}
+
/* Return nonzero if the gdbarch is an Octeon series. */
static int
@@ -2567,6 +2661,14 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
+ else if (op == 17 && (itype_rs (inst) & 0x18) == 0x18)
+ /* BZ.df: 010001 110xx */
+ /* BNZ.df: 010001 111xx */
+ pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
+ else if (op == 17 && (itype_rs (inst) & 0x1b) == 0x0b)
+ /* BZ.V: 010001 01011 */
+ /* BNZ.V: 010001 01111 */
+ pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4);
else if (op == 29)
/* JALX: 011101 */
/* The new PC will be alternate mode. */
@@ -2793,6 +2895,30 @@ micromips_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
}
/* Calculate the address of the next microMIPS instruction to execute
+ after the INSN coprocessor 1 vector conditional branch instruction
+ at the address PC. */
+
+static CORE_ADDR
+micromips_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+ ULONGEST insn, CORE_ADDR pc)
+{
+ int op = b5s5_op (insn >> 16);
+ int wt = b0s5_reg (insn >> 16);
+ int taken;
+
+ /* Will the branch be taken? */
+ taken = mips_bc1_w_taken (gdbarch, frame, op, wt);
+
+ /* Calculate branch target */
+ if (taken > 0)
+ pc += micromips_relative_offset16 (insn);
+ else if (taken == 0)
+ pc += micromips_pc_insn_size (gdbarch, pc);
+
+ return pc;
+}
+
+/* Calculate the address of the next microMIPS instruction to execute
after the instruction at the address PC. */
static CORE_ADDR
@@ -2914,6 +3040,16 @@ micromips_next_pc (struct frame_info *frame, CORE_ADDR pc)
}
break;
+ case 0x20: /* POOL32D: bits 100000 */
+ if ((b5s5_op (insn) & 0x18) == 0x18
+ /* BZ.df: bits 100000 110xx */
+ /* BNZ.df: bits 100000 111xx */
+ || (b5s5_op (insn) & 0x1b) == 0x0b)
+ /* BZ.V: bits 100000 01011 */
+ /* BNZ.V: bits 100000 01111 */
+ pc = micromips_bc1_w_pc (gdbarch, frame, insn, pc);
+ break;
+
case 0x1d: /* JALS: bits 011101 */
case 0x35: /* J: bits 110101 */
case 0x3d: /* JAL: bits 111101 */
@@ -4863,9 +4999,16 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
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 */
+ is_branch = (((itype_rs (insn) == 9 || itype_rs (insn) == 10)
+ && (itype_rt (insn) & 0x2) == 0)
+ /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+ || (itype_rs (insn) & 0x18) == 0x18
+ /* BZ.df: 010001 110xx */
+ /* BNZ.df: 010001 111xx */
+ || (itype_rs (insn) & 0x1b) == 0x0b);
+ /* BZ.V: 010001 01011 */
+ /* BNZ.V: 010001 01111 */
+ if (is_branch)
break;
/* Fall through. */
case 18: /* COP2 */
@@ -4956,6 +5099,16 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
case 2 * MIPS_INSN16_SIZE:
switch (micromips_op (insn))
{
+ case 0x20: /* POOL32D: bits 100000 */
+ if ((b5s5_op (insn) & 0x18) != 0x18
+ /* BZ.df: bits 100000 110xx */
+ /* BNZ.df: bits 100000 111xx */
+ && (b5s5_op (insn) & 0x1b) != 0x0b)
+ /* BZ.V: bits 100000 01011 */
+ /* BNZ.V: bits 100000 01111 */
+ break;
+ goto handle_branch;
+
case 0x10: /* POOL32I: bits 010000 */
if ((b5s5_op (insn) & 0x18) != 0x0
/* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */
@@ -4978,6 +5131,7 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
case 0x25: /* BEQ: bits 100101 */
case 0x2d: /* BNE: bits 101101 */
+handle_branch:
insn <<= 16;
insn |= mips_fetch_instruction (gdbarch,
ISA_MICROMIPS, loc, NULL);
@@ -8259,8 +8413,14 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
|| (rs == 9 && (rt & 0x2) == 0)
/* BC1ANY2F, BC1ANY2T: bits 010001 01001 */
- || (rs == 10 && (rt & 0x2) == 0))));
+ || (rs == 10 && (rt & 0x2) == 0)
/* BC1ANY4F, BC1ANY4T: bits 010001 01010 */
+ || ((rs & 0x18) == 0x18)
+ /* BZ.df: bits 010001 110xx */
+ /* BNZ.df: bits 010001 111xx */
+ || ((rs & 0x1b) == 0x0b))));
+ /* BZ.V: bits 010001 01011 */
+ /* BNZ.V: bits 010001 01111 */
}
else
switch (op & 0x07) /* extract bits 28,27,26 */
@@ -8331,6 +8491,13 @@ micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32)
case 0x35: /* J: bits 110101 */
case 0x2d: /* BNE: bits 101101 */
case 0x25: /* BEQ: bits 100101 */
+ case 0x20: /* POOL32D: bits 100000 */
+ return ((b5s5_op (major) & 0x18) == 0x18
+ /* BZ.df: bits 100000 110xx */
+ /* BNZ.df: bits 100000 111xx */
+ || ((b5s5_op (major) & 0x1b) == 0x0b));
+ /* BZ.V: bits 100000 01011 */
+ /* BNZ.V: bits 100000 01111 */
case 0x1d: /* JALS: bits 011101 */
return 1;
case 0x10: /* POOL32I: bits 010000 */
--
1.9-rc2