This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
RE: [PATCH] Add MIPS ufr macro instruction
- From: Andrew Bennett <Andrew dot Bennett at imgtec dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Date: Wed, 20 Nov 2013 14:58:44 +0000
- Subject: RE: [PATCH] Add MIPS ufr macro instruction
- Authentication-results: sourceware.org; auth=none
- References: <0DA23CC379F5F945ACB41CF394B982774C835E at LEMAIL01 dot le dot imgtec dot org> <87vc01erxi dot fsf at talisman dot default> <87siuzcpp4 dot fsf at talisman dot default> <0DA23CC379F5F945ACB41CF394B982774CB15B at LEMAIL01 dot le dot imgtec dot org>
>> Seems like this might have hit a log-jam, so just in case, what I really
>> meant was: please answer David's question first.
> Hi Richard,
> Sorry for the delay in the replying I have been thinking about David's comments.
> David, I agree with you, having ufr as an actual instruction, rather than a macro
> would make it much clearer to see it's use when disassembling a program.
> I am currently changing the patch to reflect these changes, and will post it back
> in the next few days.
The updated patch and ChangeLog entry is below.
Regards,
Andrew
2013-11-20 Andrew Bennett <andrew.bennett@imgtec.com>
gas/config/
* tc-mips.c (operand_reg_mask): Add OP_UFR_INT case.
(match_operand): Likewise.
(match_ufr_operand): New function.
gas/testsuite/gas/mips/
* mips.exp: Added ufr test.
* ufr.d: New test.
* ufr.s: New test.
include/opcode/
* mips.h: Updated the arg field character information for MIPS and
microMIPS.
(mips_operand_type): Add OP_UFR_INT.
opcodes/
* micromips-opc.c (decode_micromips_operand): Added support for the ?
character.
(micromips_opcodes): Added the ufr instruction.
* opcodes/mips-opc.c (decode_mips_operand): Added support for the ?
character.
(mips_builtin_opcodes): Added the ufr instruction.
* opcodes/mips-dis.c (print_insn_arg): Add OP_UFR_INT case.
(print_insn_mips): Don't try to disassemble ufr instruction
if the coprocessor register number is not 1 or 4.
(print_insn_micromips): Likewise.
---
gas/config/tc-mips.c | 39 ++++++++++++++++++++++++++++++++++++
gas/testsuite/gas/mips/mips.exp | 1 +
gas/testsuite/gas/mips/ufr.d | 42 +++++++++++++++++++++++++++++++++++++++
gas/testsuite/gas/mips/ufr.s | 38 +++++++++++++++++++++++++++++++++++
include/opcode/mips.h | 16 ++++++++++++---
opcodes/micromips-opc.c | 2 ++
opcodes/mips-dis.c | 30 ++++++++++++++++++++++++++++
opcodes/mips-opc.c | 2 ++
8 files changed, 167 insertions(+), 3 deletions(-)
create mode 100644 gas/testsuite/gas/mips/ufr.d
create mode 100644 gas/testsuite/gas/mips/ufr.s
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 34f1bf0..dab2889 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -4031,6 +4031,18 @@ operand_reg_mask (const struct mips_cl_insn *insn,
case OP_IMM_INDEX:
abort ();
+ case OP_UFR_INT:
+ {
+ if ((type_mask & (1 << OP_REG_GP)))
+ /* ufr implicitly uses the zero reg */
+ return 1;
+ else if ((type_mask & (1 << OP_REG_COPRO)))
+ /* ufr only works with control regs 1 and 4 */
+ return (1 << 1) | (1 << 4);
+ else
+ return 0;
+ }
+
case OP_REG:
case OP_OPTIONAL_REG:
{
@@ -4796,6 +4808,30 @@ match_perf_reg_operand (struct mips_arg_info *arg,
return TRUE;
}
+/* OP_UFR matcher. */
+
+static bfd_boolean
+match_ufr_operand (struct mips_arg_info *arg,
+ const struct mips_operand *operand)
+{
+ offsetT sval;
+
+ if (!match_const_int (arg, &sval))
+ return FALSE;
+
+ switch (sval)
+ {
+ case 0:
+ insn_insert_operand (arg->insn, operand, 1);
+ return TRUE;
+ case 1:
+ insn_insert_operand (arg->insn, operand, 4);
+ return TRUE;
+ default:
+ match_out_of_range (arg);
+ return FALSE;
+ }
+}
/* OP_ADDIUSP matcher. */
static bfd_boolean
@@ -5470,6 +5506,9 @@ match_operand (struct mips_arg_info *arg,
case OP_PERF_REG:
return match_perf_reg_operand (arg, operand);
+ case OP_UFR_INT:
+ return match_ufr_operand (arg, operand);
+
case OP_ADDIUSP_INT:
return match_addiusp_operand (arg, operand);
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 121566a..68514c5 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -1156,4 +1156,5 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test_arches "msa64" [mips_arch_list_matching mips64r2]
run_dump_test_arches "msa-relax" [mips_arch_list_matching mips32r2]
run_dump_test_arches "msa-branch" [mips_arch_list_matching mips32r2]
+ run_dump_test_arches "ufr" [mips_arch_list_matching mips32r2]
}
diff --git a/gas/testsuite/gas/mips/ufr.d b/gas/testsuite/gas/mips/ufr.d
new file mode 100644
index 0000000..4fc1421
--- /dev/null
+++ b/gas/testsuite/gas/mips/ufr.d
@@ -0,0 +1,42 @@
+#objdump: -d --prefix-addresses
+#name: MIPS ufr
+
+# Test the ufr instruction.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> ufr 0
+0+0004 <[^>]*> ufr 1
+0+0008 <[^>]*> ctc1 zero,\$0
+0+000c <[^>]*> ufr 0
+0+0010 <[^>]*> ctc1 zero,\$2
+0+0014 <[^>]*> ctc1 zero,\$3
+0+0018 <[^>]*> ufr 1
+0+001c <[^>]*> ctc1 zero,\$5
+0+0020 <[^>]*> ctc1 zero,\$6
+0+0024 <[^>]*> ctc1 zero,\$7
+0+0028 <[^>]*> ctc1 zero,\$8
+0+002c <[^>]*> ctc1 zero,\$9
+0+0030 <[^>]*> ctc1 zero,\$10
+0+0034 <[^>]*> ctc1 zero,\$11
+0+0038 <[^>]*> ctc1 zero,\$12
+0+003c <[^>]*> ctc1 zero,\$13
+0+0040 <[^>]*> ctc1 zero,\$14
+0+0044 <[^>]*> ctc1 zero,\$15
+0+0048 <[^>]*> ctc1 zero,\$16
+0+004c <[^>]*> ctc1 zero,\$17
+0+0050 <[^>]*> ctc1 zero,\$18
+0+0054 <[^>]*> ctc1 zero,\$19
+0+0058 <[^>]*> ctc1 zero,\$20
+0+005c <[^>]*> ctc1 zero,\$21
+0+0060 <[^>]*> ctc1 zero,\$22
+0+0064 <[^>]*> ctc1 zero,\$23
+0+0068 <[^>]*> ctc1 zero,\$24
+0+006c <[^>]*> ctc1 zero,\$25
+0+0070 <[^>]*> ctc1 zero,\$26
+0+0074 <[^>]*> ctc1 zero,\$27
+0+0078 <[^>]*> ctc1 zero,\$28
+0+007c <[^>]*> ctc1 zero,\$29
+0+0080 <[^>]*> ctc1 zero,\$30
+0+0084 <[^>]*> ctc1 zero,\$31
diff --git a/gas/testsuite/gas/mips/ufr.s b/gas/testsuite/gas/mips/ufr.s
new file mode 100644
index 0000000..433e3f6
--- /dev/null
+++ b/gas/testsuite/gas/mips/ufr.s
@@ -0,0 +1,38 @@
+# Source file used to test the ufr instruction.
+
+ .text
+foo:
+ ufr 0
+ ufr 1
+ ctc1 $0,$f0
+ ctc1 $0,$f1
+ ctc1 $0,$f2
+ ctc1 $0,$f3
+ ctc1 $0,$f4
+ ctc1 $0,$f5
+ ctc1 $0,$f6
+ ctc1 $0,$f7
+ ctc1 $0,$f8
+ ctc1 $0,$f9
+ ctc1 $0,$f10
+ ctc1 $0,$f11
+ ctc1 $0,$f12
+ ctc1 $0,$f13
+ ctc1 $0,$f14
+ ctc1 $0,$f15
+ ctc1 $0,$f16
+ ctc1 $0,$f17
+ ctc1 $0,$f18
+ ctc1 $0,$f19
+ ctc1 $0,$f20
+ ctc1 $0,$f21
+ ctc1 $0,$f22
+ ctc1 $0,$f23
+ ctc1 $0,$f24
+ ctc1 $0,$f25
+ ctc1 $0,$f26
+ ctc1 $0,$f27
+ ctc1 $0,$f28
+ ctc1 $0,$f29
+ ctc1 $0,$f30
+ ctc1 $0,$f31
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index c9dc52b..80e85c7 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -419,7 +419,13 @@ enum mips_operand_type {
OP_IMM_INDEX,
/* An index selected by a register, e.g. [$2]. */
- OP_REG_INDEX
+ OP_REG_INDEX,
+
+ /* An operand to the ufr instruction. The only values that are allowed are 0 and 1.
+ They are mapped in the following manner:
+ 0 => 1
+ 1 => 4 */
+ OP_UFR_INT
};
/* Enumerates the types of MIPS register. */
@@ -807,6 +813,8 @@ struct mips_opcode
"P" 5 bit performance-monitor register (OP_*_PERFREG)
"e" 5 bit vector register byte specifier (OP_*_VECBYTE)
"%" 3 bit immediate vr5400 vector alignment operand (OP_*_VECALIGN)
+ "?" 5 bit destination register. It is used to set the FR mode, only
+ allowed values are 1 (FR = 0) and 4 (FR = 1).
Macro instructions:
"A" General 32 bit expression
@@ -936,7 +944,7 @@ struct mips_opcode
Characters used so far, for quick reference when adding more:
"1234567890"
- "%[]<>(),+:'@!#$*&\~"
+ "%[]<>(),+:'@!#$*&\~?"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklopqrstuvwxz"
@@ -2062,6 +2070,8 @@ extern const int bfd_mips16_num_opcodes;
"E" 5-bit target register (MICROMIPSOP_*_RT)
"G" 5-bit source register (MICROMIPSOP_*_RS)
"H" 3-bit sel field for (D)MTC* and (D)MFC* (MICROMIPSOP_*_SEL)
+ "?" 5 bit target register. It is used to set the FR mode, only
+ allowed values are 1 (FR = 0) and 4 (FR = 1).
Macro instructions:
"A" general 32 bit expression
@@ -2121,7 +2131,7 @@ extern const int bfd_mips16_num_opcodes;
Characters used so far, for quick reference when adding more:
"12345678 0"
- "<>(),+.@\^|~"
+ "<>(),+.@\^|~?"
"ABCDEFGHI KLMN RST V "
"abcd f hijklmnopqrstuvw yz"
diff --git a/opcodes/micromips-opc.c b/opcodes/micromips-opc.c
index a68916a..702e6c7 100644
--- a/opcodes/micromips-opc.c
+++ b/opcodes/micromips-opc.c
@@ -147,6 +147,7 @@ decode_micromips_operand (const char *p)
case '~': SINT (12, 0);
case '@': SINT (10, 16);
case '^': HINT (5, 11);
+ case '?': SPECIAL (5, 16, UFR_INT);
case '0': SINT (6, 16);
case '1': HINT (5, 16);
@@ -546,6 +547,7 @@ const struct mips_opcode micromips_opcodes[] =
{"clo", "t,s", 0x00004b3c, 0xfc00ffff, WR_1|RD_2, 0, I1, 0, 0 },
{"clz", "t,s", 0x00005b3c, 0xfc00ffff, WR_1|RD_2, 0, I1, 0, 0 },
{"cop2", "C", 0x00000002, 0xfc000007, CP, 0, I1, 0, 0 },
+{"ufr", "?", 0x5400183b, 0xffe0ffff, RD_1|WR_CC|FP_S, 0, I1, 0, 0 },
{"ctc1", "t,G", 0x5400183b, 0xfc00ffff, RD_1|WR_CC|FP_S, 0, I1, 0, 0 },
{"ctc1", "t,S", 0x5400183b, 0xfc00ffff, RD_1|WR_CC|FP_S, 0, I1, 0, 0 },
{"ctc2", "t,G", 0x0000dd3c, 0xfc00ffff, RD_1|WR_C2|WR_CC, 0, I1, 0, 0 },
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index 1929ffc..a903b4e 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -1114,6 +1114,22 @@ print_insn_arg (struct disassemble_info *info,
infprintf (is, "%d", uval);
break;
+ case OP_UFR_INT:
+ {
+ switch (uval)
+ {
+ case 1:
+ infprintf (is, "0");
+ break;
+ case 4:
+ infprintf (is, "1");
+ break;
+ default:
+ abort ();
+ }
+ break;
+ }
+
case OP_ADDIUSP_INT:
{
int sval;
@@ -1427,6 +1443,13 @@ print_insn_mips (bfd_vma memaddr,
&& !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
&& (word & op->mask) == op->match)
{
+ if (strcmp (op->name, "ufr") == 0)
+ {
+ unsigned int val = (word >> 11) & 0x1F;
+ if (val != 1 && val != 4)
+ continue;
+ }
+
/* We always allow to disassemble the jalx instruction. */
if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
&& strcmp (op->name, "jalx"))
@@ -1974,6 +1997,13 @@ print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
&& ((length == 2 && (op->mask & 0xffff0000) == 0)
|| (length == 4 && (op->mask & 0xffff0000) != 0)))
{
+ if (strcmp (op->name, "ufr") == 0)
+ {
+ unsigned int val = (insn >> 16) & 0x1F;
+ if (val != 1 && val != 4)
+ continue;
+ }
+
infprintf (is, "%s", op->name);
if (op->args[0])
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index cd43185..9f13702 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -130,6 +130,7 @@ decode_mips_operand (const char *p)
case '&': REG (2, 13, ACC);
case '~': SINT (12, 0);
case '\\': BIT (3, 12, 0); /* (0 .. 7) */
+ case '?': SPECIAL (5, 11, UFR_INT);
case '0': SINT (6, 20);
case '1': HINT (5, 6);
@@ -911,6 +912,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"clo", "U,s", 0x70000021, 0xfc0007ff, WR_1|RD_2, 0, I32|N55, 0, 0 },
{"clz", "U,s", 0x70000020, 0xfc0007ff, WR_1|RD_2, 0, I32|N55, 0, 0 },
{"ctc0", "t,G", 0x40c00000, 0xffe007ff, RD_1|WR_CC|COD, 0, I1, 0, IOCT|IOCTP|IOCT2 },
+{"ufr", "?", 0x44c00000, 0xffff07ff, RD_1|WR_CC|COD|FP_S, 0, I1, 0, 0 },
{"ctc1", "t,G", 0x44c00000, 0xffe007ff, RD_1|WR_CC|COD|FP_S, 0, I1, 0, 0 },
{"ctc1", "t,S", 0x44c00000, 0xffe007ff, RD_1|WR_CC|COD|FP_S, 0, I1, 0, 0 },
/* ctc2 is at the bottom of the table. */
--
1.7.10.1