This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 7/9] MIPS/opcodes: Fix and clean up MIPS16 branch annotation
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: binutils at sourceware dot org
- Cc: Richard Sandiford <rdsandiford at googlemail dot com>, Catherine Moore <clm at codesourcery dot com>, gnu-mips-sgxx at codesourcery dot com
- Date: Fri, 2 Jul 2010 17:15:00 +0100 (BST)
- Subject: [PATCH 7/9] MIPS/opcodes: Fix and clean up MIPS16 branch annotation
Hi,
This is a change that cleans up MIPS16 branch annotation held by opcodes.
With this change it is possible to classify a relevant instruction as one
of: an unconditional branch, a conditional branch or a jump to a
subroutine, based solely on opcode flags and without a need to decode
operands, similarly to what the case is with standard MIPS code.
It fixes MIPS16e compact jump additions; previously these instructions
were not annotated as branches.
The most likely beneficiary of this change is GDB, although I do not
remember off the head if this change showed up as a progression anywhere.
As it is GDB does mistreat MIPS16 branches in some places though.
2010-07-02 Maciej W. Rozycki <macro@codesourcery.com>
gas/
* config/tc-mips.c (nops_for_insn_or_target): Replace
MIPS16_INSN_BRANCH with MIPS16_INSN_UNCOND_BRANCH and
MIPS16_INSN_COND_BRANCH.
include/opcode/
* mips.h (MIPS16_INSN_UNCOND_BRANCH): New macro.
(MIPS16_INSN_BRANCH): Rename to...
(MIPS16_INSN_COND_BRANCH): ... this.
opcodes/
* mips-dis.c (print_mips16_insn_arg): Remove branch instruction
type and delay slot determination.
(print_insn_mips16): Extend branch instruction type and delay
slot determination to cover all instructions.
* mips16-opc.c (BR): Remove macro.
(UBR, CBR): New macros.
(mips16_opcodes): Update branch annotation for "b", "beqz",
"bnez", "bteqz" and "btnez". Add branch annotation for "jalrc"
and "jrc".
OK to commit?
Maciej
binutils-254623.diff
Index: binutils-fsf-trunk-quilt/gas/config/tc-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/config/tc-mips.c 2010-06-30 00:31:59.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/config/tc-mips.c 2010-06-30 14:49:48.000000000 +0100
@@ -2730,7 +2730,9 @@
if (tmp_nops > nops)
nops = tmp_nops;
}
- else if (mips_opts.mips16 && (insn->insn_mo->pinfo & MIPS16_INSN_BRANCH))
+ else if (mips_opts.mips16
+ && (insn->insn_mo->pinfo & (MIPS16_INSN_UNCOND_BRANCH
+ | MIPS16_INSN_COND_BRANCH)))
{
tmp_nops = nops_for_sequence (1, hist, insn);
if (tmp_nops > nops)
Index: binutils-fsf-trunk-quilt/include/opcode/mips.h
===================================================================
--- binutils-fsf-trunk-quilt.orig/include/opcode/mips.h 2010-06-24 22:49:55.000000000 +0100
+++ binutils-fsf-trunk-quilt/include/opcode/mips.h 2010-06-30 14:49:48.000000000 +0100
@@ -1089,8 +1089,10 @@
#define MIPS16_INSN_READ_PC 0x00002000
/* Reads the general purpose register in MIPS16OP_*_REGR32. */
#define MIPS16_INSN_READ_GPR_X 0x00004000
-/* Is a branch insn. */
-#define MIPS16_INSN_BRANCH 0x00010000
+/* Is an unconditional branch insn. */
+#define MIPS16_INSN_UNCOND_BRANCH 0x00008000
+/* Is a conditional branch insn. */
+#define MIPS16_INSN_COND_BRANCH 0x00010000
/* The following flags have the same value for the mips16 opcode
table:
Index: binutils-fsf-trunk-quilt/opcodes/mips-dis.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/opcodes/mips-dis.c 2010-06-24 22:50:15.000000000 +0100
+++ binutils-fsf-trunk-quilt/opcodes/mips-dis.c 2010-06-30 14:49:48.000000000 +0100
@@ -1660,7 +1660,6 @@
signedp = 1;
pcrel = 1;
branch = 1;
- info->insn_type = dis_condbranch;
break;
case 'q':
nbits = 11;
@@ -1668,7 +1667,6 @@
signedp = 1;
pcrel = 1;
branch = 1;
- info->insn_type = dis_branch;
break;
case 'A':
nbits = 8;
@@ -1789,8 +1787,6 @@
}
info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
(*info->print_address_func) (info->target, info);
- info->insn_type = dis_jsr;
- info->branch_delay_insns = 1;
break;
case 'l':
@@ -2082,12 +2078,19 @@
info);
}
+ /* Figure out branch instruction type and delay slot information. */
if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
+ info->branch_delay_insns = 1;
+ if ((op->pinfo & (INSN_UNCOND_BRANCH_DELAY
+ | MIPS16_INSN_UNCOND_BRANCH)) != 0)
{
- info->branch_delay_insns = 1;
- if (info->insn_type != dis_jsr)
+ if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
+ info->insn_type = dis_jsr;
+ else
info->insn_type = dis_branch;
}
+ else if ((op->pinfo & MIPS16_INSN_COND_BRANCH) != 0)
+ info->insn_type = dis_condbranch;
return length;
}
Index: binutils-fsf-trunk-quilt/opcodes/mips16-opc.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/opcodes/mips16-opc.c 2010-05-12 22:08:00.000000000 +0100
+++ binutils-fsf-trunk-quilt/opcodes/mips16-opc.c 2010-06-30 14:49:48.000000000 +0100
@@ -33,7 +33,8 @@
the opcodes table. */
#define UBD INSN_UNCOND_BRANCH_DELAY
-#define BR MIPS16_INSN_BRANCH
+#define UBR MIPS16_INSN_UNCOND_BRANCH
+#define CBR MIPS16_INSN_COND_BRANCH
#define WR_x MIPS16_INSN_WRITE_X
#define WR_y MIPS16_INSN_WRITE_Y
@@ -85,10 +86,10 @@
{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 },
{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, I1 },
{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y, 0, I1 },
-{"b", "q", 0x1000, 0xf800, BR, 0, I1 },
+{"b", "q", 0x1000, 0xf800, UBR, 0, I1 },
{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO, 0, I1 },
{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, I1 },
-{"beqz", "x,p", 0x2000, 0xf800, BR|RD_x, 0, I1 },
+{"beqz", "x,p", 0x2000, 0xf800, CBR|RD_x, 0, I1 },
{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO, 0, I1 },
{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO, 0, I1 },
{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO, 0, I1 },
@@ -107,10 +108,10 @@
{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, I1 },
{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO, 0, I1 },
{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I1 },
-{"bnez", "x,p", 0x2800, 0xf800, BR|RD_x, 0, I1 },
+{"bnez", "x,p", 0x2800, 0xf800, CBR|RD_x, 0, I1 },
{"break", "6", 0xe805, 0xf81f, TRAP, 0, I1 },
-{"bteqz", "p", 0x6000, 0xff00, BR|RD_T, 0, I1 },
-{"btnez", "p", 0x6100, 0xff00, BR|RD_T, 0, I1 },
+{"bteqz", "p", 0x6000, 0xff00, CBR|RD_T, 0, I1 },
+{"btnez", "p", 0x6100, 0xff00, CBR|RD_T, 0, I1 },
{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 },
{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y, 0, I1 },
{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 },
@@ -226,10 +227,10 @@
{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, 0, I1 },
{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, 0, I1 },
/* MIPS16e additions */
-{"jalrc", "x", 0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0, I32 },
-{"jalrc", "R,x", 0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0, I32 },
-{"jrc", "x", 0xe880, 0xf8ff, RD_x|TRAP, 0, I32 },
-{"jrc", "R", 0xe8a0, 0xffff, RD_31|TRAP, 0, I32 },
+{"jalrc", "x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
+{"jalrc", "R,x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
+{"jrc", "x", 0xe880, 0xf8ff, UBR|RD_x|TRAP, 0, I32 },
+{"jrc", "R", 0xe8a0, 0xffff, UBR|RD_31|TRAP, 0, I32 },
{"restore", "M", 0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, 0, I32 },
{"save", "m", 0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, 0, I32 },
{"sdbbp", "6", 0xe801, 0xf81f, TRAP, 0, I32 },