This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[committed] Add a new operand type for MIPS JALX
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: binutils at sourceware dot org
- Date: Sun, 07 Jul 2013 10:53:52 +0100
- Subject: [committed] Add a new operand type for MIPS JALX
Until now we've used the same operand type, "a", for both JAL and JALX.
That made sense for the standard encoding and for MIPS16, but is a bit
more of a stretch for microMIPS, where the two instructions have different
shifts and therefore different ranges.
This patch adds new operand types for JALX. It also fixes the inverted
logic in the microMIPS code:
/* For gdb disassembler, force odd address on jalx. */
if (info->flavour == bfd_target_unknown_flavour
&& strcmp (op->name, "jalx") == 0)
since in that case the ISA bit should be preserved when the instruction
_isn't_ JALX. Since this had gone unnoticed for a while, I was wondering
whether GDB still cared, but Maciej confirmed that it does (thanks).
I'll leave fixing the branch ISA bit until the main rewrite patch,
where the test is made in one place.
Again, this looks less ugly after the rewrite...
Applied.
Richard
include/opcode/
* mips.h: Document "+i".
opcodes/
* mips-opc.c (mips_builtin_opcodes): Use "+i" rather than "a" for
"jalx".
* mips16-opc.c (mips16_opcodes): Likewise.
* micromips-opc.c (micromips_opcodes): Likewise.
* mips-dis.c (print_insn_args, print_mips16_insn_arg)
(print_insn_mips16): Handle "+i".
(print_insn_micromips): Likewise. Conditionally preserve the
ISA bit for "a" but not for "+i".
gas/
* config/tc-mips.c (validate_mips_insn, validate_micromips_insn):
(mips_ip, mips16_ip): Handle "+i".
Index: include/opcode/mips.h
===================================================================
--- include/opcode/mips.h 2013-07-01 19:22:52.689357775 +0100
+++ include/opcode/mips.h 2013-07-01 19:29:27.337536933 +0100
@@ -379,6 +379,7 @@ struct mips_opcode
"<" 5 bit shift amount (OP_*_SHAMT)
">" shift amount between 32 and 63, stored after subtracting 32 (OP_*_SHAMT)
"a" 26 bit target address (OP_*_TARGET)
+ "+i" likewise, but flips bit 0
"b" 5 bit base register (OP_*_RS)
"c" 10 bit breakpoint code (OP_*_CODE)
"d" 5 bit destination register specifier (OP_*_RD)
@@ -539,7 +540,7 @@ struct mips_opcode
following), for quick reference when adding more:
"1234"
"ABCEFGHIJPQSXZ"
- "abcjpstxz"
+ "abcijpstxz"
*/
/* These are the bits which may be set in the pinfo field of an
@@ -1383,6 +1384,7 @@ #define MIPS16OP_SH_IMM6 5
"Y" 5 bit MIPS register (MIPS16OP_*_REG32R)
"6" 6 bit unsigned break code (MIPS16OP_*_IMM6)
"a" 26 bit jump address
+ "i" likewise, but flips bit 0
"e" 11 bit extension value
"l" register list for entry instruction
"L" register list for exit instruction
@@ -1741,6 +1743,7 @@ #define MICROMIPSOP_MASK_EVAOFFSET 0x1ff
"|" 4-bit trap code (MICROMIPSOP_*_TRAP)
"~" 12-bit signed offset (MICROMIPSOP_*_OFFSET12)
"a" 26-bit target address (MICROMIPSOP_*_TARGET)
+ "+i" likewise, but flips bit 0
"b" 5-bit base register (MICROMIPSOP_*_RS)
"c" 10-bit higher breakpoint code (MICROMIPSOP_*_CODE)
"d" 5-bit destination register specifier (MICROMIPSOP_*_RD)
@@ -1846,10 +1849,10 @@ #define MICROMIPSOP_MASK_EVAOFFSET 0x1ff
Extension character sequences used so far ("+" followed by the
following), for quick reference when adding more:
- "j"
""
- "ABCEFGHI"
""
+ "ABCEFGHI"
+ "ij"
Extension character sequences used so far ("m" followed by the
following), for quick reference when adding more:
Index: opcodes/mips-opc.c
===================================================================
--- opcodes/mips-opc.c 2013-07-01 19:17:23.797696361 +0100
+++ opcodes/mips-opc.c 2013-07-01 19:29:27.339536949 +0100
@@ -852,7 +852,7 @@ const struct mips_opcode mips_builtin_op
assembler, but will never match user input (because the line above
will match first). */
{"jal", "a", 0x0c000000, 0xfc000000, UBD|WR_31, 0, I1 },
-{"jalx", "a", 0x74000000, 0xfc000000, UBD|WR_31, 0, I1 },
+{"jalx", "+i", 0x74000000, 0xfc000000, UBD|WR_31, 0, I1 },
{"la", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, 0, I1 },
{"laa", "d,(b),t", 0x7000049f, 0xfc0007ff, LDD|SM|WR_d|RD_t|RD_b, 0, IOCT2 },
{"laad", "d,(b),t", 0x700004df, 0xfc0007ff, LDD|SM|WR_d|RD_t|RD_b, 0, IOCT2 },
Index: opcodes/mips16-opc.c
===================================================================
--- opcodes/mips16-opc.c 2013-07-01 19:17:23.797696361 +0100
+++ opcodes/mips16-opc.c 2013-07-01 19:29:27.340536957 +0100
@@ -167,7 +167,7 @@ const struct mips_opcode mips16_opcodes[
{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 },
{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 },
{"jal", "a", 0x1800, 0xfc00, UBD|WR_31, 0, I1 },
-{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31, 0, I1 },
+{"jalx", "i", 0x1c00, 0xfc00, UBD|WR_31, 0, I1 },
{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 },
{"jr", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 },
{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 },
Index: opcodes/micromips-opc.c
===================================================================
--- opcodes/micromips-opc.c 2013-07-01 19:22:52.690357783 +0100
+++ opcodes/micromips-opc.c 2013-07-01 19:29:27.338536941 +0100
@@ -587,7 +587,7 @@ const struct mips_opcode micromips_opcod
{"jals", "s", 0, (int) M_JALS_1, INSN_MACRO, 0, I1 },
{"jals", "a", 0, (int) M_JALS_A, INSN_MACRO, 0, I1 },
{"jals", "a", 0x74000000, 0xfc000000, UBD|WR_31, BD16, I1 },
-{"jalx", "a", 0xf0000000, 0xfc000000, UBD|WR_31, BD32, I1 },
+{"jalx", "+i", 0xf0000000, 0xfc000000, UBD|WR_31, BD32, I1 },
{"la", "t,A(b)", 0, (int) M_LA_AB, INSN_MACRO, 0, I1 },
{"lb", "t,o(b)", 0x1c000000, 0xfc000000, RD_b|WR_t, 0, I1 },
{"lb", "t,A(b)", 0, (int) M_LB_AB, INSN_MACRO, 0, I1 },
Index: opcodes/mips-dis.c
===================================================================
--- opcodes/mips-dis.c 2013-07-01 19:22:52.692357799 +0100
+++ opcodes/mips-dis.c 2013-07-01 19:29:27.347537013 +0100
@@ -1105,6 +1105,15 @@ #define GET_OP_S(insn, field) \
infprintf (is, "%s", mips_fpr_names[GET_OP (l, FZ)]);
break;
+ case 'i': /* JALX destination */
+ info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
+ | (GET_OP (l, TARGET) << 2));
+ /* For gdb disassembler, force odd address on jalx. */
+ if (info->flavour == bfd_target_unknown_flavour)
+ info->target |= 1;
+ (*info->print_address_func) (info->target, info);
+ break;
+
case 'j': /* 9-bit signed offset in bit 7. */
infprintf (is, "%d", GET_OP_S (l, EVAOFFSET));
break;
@@ -1229,10 +1238,6 @@ #define GET_OP_S(insn, field) \
case 'a':
info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
| (GET_OP (l, TARGET) << 2));
- /* For gdb disassembler, force odd address on jalx. */
- if (info->flavour == bfd_target_unknown_flavour
- && strcmp (opp->name, "jalx") == 0)
- info->target |= 1;
(*info->print_address_func) (info->target, info);
break;
@@ -1874,13 +1879,12 @@ #define GET_OP_S(insn, field) \
break;
case 'a':
+ case 'i':
{
- int jalx = l & 0x400;
-
if (! use_extend)
extend = 0;
l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
- if (!jalx && info->flavour == bfd_target_unknown_flavour)
+ if (type == 'a' && info->flavour == bfd_target_unknown_flavour)
/* For gdb disassembler, maintain odd address. */
l |= 1;
}
@@ -2147,7 +2151,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
{
const char *s;
- if (strchr (op->args, 'a') != NULL)
+ if (op->args[0] == 'a' || op->args[0] == 'i')
{
if (use_extend)
{
@@ -2422,15 +2426,10 @@ #define GET_OP_S(insn, field) \
break;
case 'a':
- if (strcmp (op->name, "jalx") == 0)
- info->target = (((memaddr + 4) & ~(bfd_vma) 0x0fffffff)
- | (GET_OP (insn, TARGET) << 2));
- else
- info->target = (((memaddr + 4) & ~(bfd_vma) 0x07ffffff)
- | (GET_OP (insn, TARGET) << 1));
- /* For gdb disassembler, force odd address on jalx. */
- if (info->flavour == bfd_target_unknown_flavour
- && strcmp (op->name, "jalx") == 0)
+ info->target = (((memaddr + 4) & ~(bfd_vma) 0x07ffffff)
+ | (GET_OP (insn, TARGET) << 1));
+ /* For gdb disassembler, maintain odd address. */
+ if (info->flavour == bfd_target_unknown_flavour)
info->target |= 1;
(*info->print_address_func) (info->target, info);
break;
@@ -2658,6 +2657,12 @@ #define GET_OP_S(insn, field) \
infprintf (is, "0x%x", msbd + 1);
break;
+ case 'i':
+ info->target = (((memaddr + 4) & ~(bfd_vma) 0x0fffffff)
+ | (GET_OP (insn, TARGET) << 2));
+ (*info->print_address_func) (info->target, info);
+ break;
+
case 'j': /* 9-bit signed offset in bit 0. */
delta = GET_OP_S (insn, EVAOFFSET);
infprintf (is, "%d", delta);
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c 2013-07-01 19:23:48.448807235 +0100
+++ gas/config/tc-mips.c 2013-07-01 19:29:27.346537005 +0100
@@ -10910,6 +10910,7 @@ #define USE_BITS(mask,shift) (used_bits
case 'a': USE_BITS (OP_MASK_OFFSET_A, OP_SH_OFFSET_A); break;
case 'b': USE_BITS (OP_MASK_OFFSET_B, OP_SH_OFFSET_B); break;
case 'c': USE_BITS (OP_MASK_OFFSET_C, OP_SH_OFFSET_C); break;
+ case 'i': USE_BITS (OP_MASK_TARGET, OP_SH_TARGET); break;
case 'j': USE_BITS (OP_MASK_EVAOFFSET, OP_SH_EVAOFFSET); break;
default:
@@ -11071,6 +11072,7 @@ #define USE_BITS(field) \
case 'F': USE_BITS (INSMSB); break;
case 'G': USE_BITS (EXTMSBD); break;
case 'H': USE_BITS (EXTMSBD); break;
+ case 'i': USE_BITS (TARGET); break;
case 'j': USE_BITS (EVAOFFSET); break;
default:
as_bad (_("Internal error: bad mips opcode "
@@ -12173,6 +12175,9 @@ mips_ip (char *str, struct mips_cl_insn
INSERT_OPERAND (0, FZ, *ip, regno);
continue;
+ case 'i':
+ goto jump;
+
case 'j':
{
int shift = 8;
@@ -13031,6 +13036,7 @@ mips_ip (char *str, struct mips_cl_insn
continue;
case 'a': /* 26-bit address. */
+ jump:
*offset_reloc = BFD_RELOC_MIPS_JMP;
my_getExpression (&offset_expr, s);
s = expr_end;
@@ -14279,6 +14285,7 @@ mips16_ip (char *str, struct mips_cl_ins
continue;
case 'a': /* 26 bit address */
+ case 'i':
my_getExpression (&offset_expr, s);
s = expr_end;
*offset_reloc = BFD_RELOC_MIPS16_JMP;