This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH, MIPS] Add Octeon instructions seq* and sne*
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: binutils at sourceware dot org
- Date: Wed, 21 May 2008 23:49:32 -0700
- Subject: [PATCH, MIPS] Add Octeon instructions seq* and sne*
I wanted to keep this separate from the other instructions because this
changes the related macros, seq and sne.
For small immediates we can expand the immediate variants of these
instructions. If the immediate is big enough so that we need to load it into
a register we can expand the register variants instead of using xor and sltu.
For the other cases I kept the original expansions as they are equally good on
Octeon.
Tested on mips64octeon-linux-gnu.
OK to install?
Adam
include/opcode/
* mips.h: Document new field descriptors +Q.
(OP_SH_SEQI, OP_MASK_SEQI): New bit mask and shift count for SEQI.
opcodes/
* mips-dis.c (print_insn_args): Handle field descriptor +Q.
* mips-opc.c (mips_builtin_opcodes): Add Octeon instructions seq,
seqi, sne and snei.
gas/
* config/tc-mips.c (validate_mips_insn): Handle field descriptor +Q.
(mips_ip): Likewise.
(macro_build): Likewise.
(CPU_HAS_SEQ): New macro.
(macro2) <M_SEQ_I, M_SNE_I>: Use it. Emit seq/sne and seqi/snei.
gas/testsuite/
* gas/mips/octeon.s, gas/mips/octeon.d: Add tests for seq* and sne*.
* gas/mips/octeon-ill.s, gas/mips/octeon-ill.s: Add tests for seqi
and snei.
Index: src/include/opcode/mips.h
===================================================================
--- src.orig/include/opcode/mips.h 2008-05-16 17:13:26.000000000 -0700
+++ src/include/opcode/mips.h 2008-05-17 20:28:15.000000000 -0700
@@ -222,6 +222,8 @@ Software Foundation, 51 Franklin Street
#define OP_MASK_CINSPOS 0x1f
#define OP_SH_CINSLM1 11
#define OP_MASK_CINSLM1 0x1f
+#define OP_SH_SEQI 6
+#define OP_MASK_SEQI 0x3ff
/* This structure holds information for a particular instruction. */
@@ -385,6 +387,7 @@ struct mips_opcode
"+p" Position field of cins/cins32/exts/exts32. Enforces 0 <= pos < 32.
"+P" Position field of cins/exts aliasing cins32/exts32. Matches if
32 <= pos < 64, otherwise skips to next candidate.
+ "+Q" Immediate field of seqi/snei. Enforces -512 <= imm < 512.
"+s" Length-minus-one field of cins/exts. Enforces: 0 <= lenm1 < 32.
"+S" Length-minus-one field of cins32/exts32 or cins/exts aliasing
cint32/exts32. Enforces non-negative value and that
@@ -406,7 +409,7 @@ struct mips_opcode
Extension character sequences used so far ("+" followed by the
following), for quick reference when adding more:
"1234"
- "ABCDEFGHIPSTX"
+ "ABCDEFGHIPQSTX"
"pstx"
*/
Index: src/opcodes/mips-opc.c
===================================================================
--- src.orig/opcodes/mips-opc.c 2008-05-16 16:59:17.000000000 -0700
+++ src/opcodes/mips-opc.c 2008-05-19 09:10:52.000000000 -0700
@@ -1191,10 +1191,12 @@ const struct mips_opcode mips_builtin_op
{"seh", "d,w", 0x7c000620, 0xffe007ff, WR_d|RD_t, 0, I33 },
{"selsl", "d,v,t", 0x00000005, 0xfc0007ff, WR_d|RD_s|RD_t, 0, L1 },
{"selsr", "d,v,t", 0x00000001, 0xfc0007ff, WR_d|RD_s|RD_t, 0, L1 },
+{"seq", "d,v,t", 0x7000002a, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCT },
{"seq", "d,v,t", 0, (int) M_SEQ, INSN_MACRO, 0, I1 },
{"seq", "d,v,I", 0, (int) M_SEQ_I, INSN_MACRO, 0, I1 },
{"seq", "S,T", 0x46a00032, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E },
{"seq", "S,T", 0x4ba0000c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F },
+{"seqi", "t,r,+Q", 0x7000002e, 0xfc00003f, WR_t|RD_s, 0, IOCT },
{"sge", "d,v,t", 0, (int) M_SGE, INSN_MACRO, 0, I1 },
{"sge", "d,v,I", 0, (int) M_SGE_I, INSN_MACRO, 0, I1 },
{"sgeu", "d,v,t", 0, (int) M_SGEU, INSN_MACRO, 0, I1 },
@@ -1246,8 +1248,10 @@ const struct mips_opcode mips_builtin_op
{"sltu", "d,v,I", 0, (int) M_SLTU_I, INSN_MACRO, 0, I1 },
{"sltu", "S,T", 0x4680003c, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2E },
{"sltu", "S,T", 0x4b80000d, 0xffe007ff, RD_S|RD_T|WR_CC|FP_D, 0, IL2F },
+{"sne", "d,v,t", 0x7000002b, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IOCT },
{"sne", "d,v,t", 0, (int) M_SNE, INSN_MACRO, 0, I1 },
{"sne", "d,v,I", 0, (int) M_SNE_I, INSN_MACRO, 0, I1 },
+{"snei", "t,r,+Q", 0x7000002f, 0xfc00003f, WR_t|RD_s, 0, IOCT },
{"sqrt.d", "D,S", 0x46200004, 0xffff003f, WR_D|RD_S|FP_D, 0, I2 },
{"sqrt.s", "D,S", 0x46000004, 0xffff003f, WR_D|RD_S|FP_S, 0, I2 },
{"sqrt.ps", "D,S", 0x46c00004, 0xffff003f, WR_D|RD_S|FP_D, 0, SB1 },
Index: src/opcodes/mips-dis.c
===================================================================
--- src.orig/opcodes/mips-dis.c 2008-05-17 20:49:11.000000000 -0700
+++ src/opcodes/mips-dis.c 2008-05-17 23:34:43.000000000 -0700
@@ -902,6 +902,13 @@ print_insn_args (const char *d,
(l >> OP_SH_CINSLM1) & OP_MASK_CINSLM1);
break;
+ case 'Q': /* seqi/snei immediate field */
+ op = (l >> OP_SH_SEQI) & OP_MASK_SEQI;
+ /* Sign-extend it. */
+ op = (op ^ 512) - 512;
+ (*info->fprintf_func) (info->stream, "%d", op);
+ break;
+
default:
/* xgettext:c-format */
(*info->fprintf_func) (info->stream,
Index: src/gas/config/tc-mips.c
===================================================================
--- src.orig/gas/config/tc-mips.c 2008-05-16 16:54:46.000000000 -0700
+++ src/gas/config/tc-mips.c 2008-05-21 23:05:41.000000000 -0700
@@ -444,6 +444,9 @@ static int mips_32bitmode = 0;
/* True if CPU has a ror instruction. */
#define CPU_HAS_ROR(CPU) CPU_HAS_DROR (CPU)
+/* True if CPU has seq/sne and seqi/snei instructions. */
+#define CPU_HAS_SEQ(CPU) ((CPU) == CPU_OCTEON)
+
/* True if mflo and mfhi can be immediately followed by instructions
which write to the HI and LO registers.
@@ -3500,6 +3503,10 @@ macro_build (expressionS *ep, const char
INSERT_OPERAND (EXTMSBD, insn, va_arg (args, int));
continue;
+ case 'Q':
+ INSERT_OPERAND (SEQI, insn, va_arg (args, int));
+ continue;
+
default:
internalError ();
}
@@ -7541,6 +7548,14 @@ macro2 (struct mips_cl_insn *ip)
move_register (dreg, 0);
break;
}
+ if (CPU_HAS_SEQ (mips_opts.arch)
+ && -512 <= imm_expr.X_add_number
+ && imm_expr.X_add_number < 512)
+ {
+ macro_build (NULL, "seqi", "t,r,+Q", dreg, sreg,
+ imm_expr.X_add_number);
+ break;
+ }
if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number >= 0
&& imm_expr.X_add_number < 0x10000)
@@ -7555,6 +7570,13 @@ macro2 (struct mips_cl_insn *ip)
macro_build (&imm_expr, HAVE_32BIT_GPRS ? "addiu" : "daddiu",
"t,r,j", dreg, sreg, BFD_RELOC_LO16);
}
+ else if (CPU_HAS_SEQ (mips_opts.arch))
+ {
+ used_at = 1;
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, "seq", "d,v,t", dreg, sreg, AT);
+ break;
+ }
else
{
load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
@@ -7688,6 +7710,14 @@ macro2 (struct mips_cl_insn *ip)
dreg, 0, BFD_RELOC_LO16);
break;
}
+ if (CPU_HAS_SEQ (mips_opts.arch)
+ && -512 <= imm_expr.X_add_number
+ && imm_expr.X_add_number < 512)
+ {
+ macro_build (NULL, "snei", "t,r,+Q", dreg, sreg,
+ imm_expr.X_add_number);
+ break;
+ }
if (imm_expr.X_op == O_constant
&& imm_expr.X_add_number >= 0
&& imm_expr.X_add_number < 0x10000)
@@ -7702,6 +7732,13 @@ macro2 (struct mips_cl_insn *ip)
macro_build (&imm_expr, HAVE_32BIT_GPRS ? "addiu" : "daddiu",
"t,r,j", dreg, sreg, BFD_RELOC_LO16);
}
+ else if (CPU_HAS_SEQ (mips_opts.arch))
+ {
+ used_at = 1;
+ load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
+ macro_build (NULL, "sne", "d,v,t", dreg, sreg, AT);
+ break;
+ }
else
{
load_register (AT, &imm_expr, HAVE_64BIT_GPRS);
@@ -8272,6 +8309,7 @@ validate_mips_insn (const struct mips_op
case 'X': USE_BITS (OP_MASK_BBITIND, OP_SH_BBITIND); break;
case 'p': USE_BITS (OP_MASK_CINSPOS, OP_SH_CINSPOS); break;
case 'P': USE_BITS (OP_MASK_CINSPOS, OP_SH_CINSPOS); break;
+ case 'Q': USE_BITS (OP_MASK_SEQI, OP_SH_SEQI); break;
case 's': USE_BITS (OP_MASK_CINSLM1, OP_SH_CINSLM1); break;
case 'S': USE_BITS (OP_MASK_CINSLM1, OP_SH_CINSLM1); break;
@@ -9068,6 +9106,22 @@ do_msbd:
s = expr_end;
continue;
+ case 'Q':
+ /* seqi/snei immediate field. */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((long) imm_expr.X_add_number < -512
+ || (long) imm_expr.X_add_number >= 512)
+ {
+ as_bad (_("Improper immediate (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number = 0;
+ }
+ INSERT_OPERAND (SEQI, *ip, imm_expr.X_add_number);
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
default:
as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
*args, insn->name, insn->args);
Index: src/gas/testsuite/gas/mips/octeon.s
===================================================================
--- src.orig/gas/testsuite/gas/mips/octeon.s 2008-05-17 23:41:14.000000000 -0700
+++ src/gas/testsuite/gas/mips/octeon.s 2008-05-21 23:03:36.000000000 -0700
@@ -49,6 +49,33 @@ foo:
mtp1 $25
mtp2 $9
+ seq $29,$23,$24
+ seq $6,$28
+
+ seqi $17,$15,-512
+ seqi $16,38
+
+ seq $5,$4,-274 # seqi
+ seq $12,511 # seqi
+ seq $30,$25,512 # xori $30,$25,512;sltiu $30,$30,1
+ seq $2,$12,-777 # daddiu $2,$12,777;sltiu $2,$2,1
+ seq $10,$30,0x10000 # lui $1,0x1; seq $10,$30,$1
+ seq $30,$25,-47366 # lui $1,0xffff; ori $1,$1,0x46fa; seq $30,$25,$1
+
+ sne $6,$2,$2
+ sne $23,$20
+
+ snei $4,$16,-313
+ snei $26,511
+
+ sne $21,$23,-512 # snei
+ sne $12,81 # snei
+
+ sne $4,$14,889 # xori $4,$14,889;sltu $4,$0,$4
+ sne $24,$13,-513 # daddiu $24,$13,513;sltu $24,$0,$24
+ sne $10,$30,119250 # lui $1,0x1; ori $1,$1,0xd1d2; sne $10,$30,$1
+ sne $30,$25,-0x8000 # li $1,-32768; sne $30,$25,$1
+
synciobdma
syncs
syncw
Index: src/gas/testsuite/gas/mips/octeon.d
===================================================================
--- src.orig/gas/testsuite/gas/mips/octeon.d 2008-05-18 16:07:52.000000000 -0700
+++ src/gas/testsuite/gas/mips/octeon.d 2008-05-21 22:47:44.000000000 -0700
@@ -45,6 +45,36 @@ Disassembly of section .text:
.*: 72000009 mtp0 \$16
.*: 7320000a mtp1 \$25
.*: 7120000b mtp2 \$9
+.*: 72f8e82a seq \$29,\$23,\$24
+.*: 70dc302a seq \$6,\$6,\$28
+.*: 71f1802e seqi \$17,\$15,-512
+.*: 721009ae seqi \$16,\$16,38
+.*: 7085bbae seqi \$5,\$4,-274
+.*: 718c7fee seqi \$12,\$12,511
+.*: 3b3e0200 xori \$30,\$25,0x200
+.*: 2fde0001 sltiu \$30,\$30,1
+.*: 65820309 daddiu \$2,\$12,777
+.*: 2c420001 sltiu \$2,\$2,1
+.*: 3c010001 lui \$1,0x1
+.*: 73c1502a seq \$10,\$30,\$1
+.*: 3c01ffff lui \$1,0xffff
+.*: 342146fa ori \$1,\$1,0x46fa
+.*: 7321f02a seq \$30,\$25,\$1
+.*: 7042302b sne \$6,\$2,\$2
+.*: 72f4b82b sne \$23,\$23,\$20
+.*: 7204b1ef snei \$4,\$16,-313
+.*: 735a7fef snei \$26,\$26,511
+.*: 72f5802f snei \$21,\$23,-512
+.*: 718c146f snei \$12,\$12,81
+.*: 39c40379 xori \$4,\$14,0x379
+.*: 0004202b sltu \$4,\$0,\$4
+.*: 65b80201 daddiu \$24,\$13,513
+.*: 0018c02b sltu \$24,\$0,\$24
+.*: 3c010001 lui \$1,0x1
+.*: 3421d1d2 ori \$1,\$1,0xd1d2
+.*: 73c1502b sne \$10,\$30,\$1
+.*: 24018000 li \$1,-32768
+.*: 7321f02b sne \$30,\$25,\$1
.*: 0000008f synciobdma
.*: 0000018f syncs
.*: 0000010f syncw
Index: src/gas/testsuite/gas/mips/octeon-ill.l
===================================================================
--- src.orig/gas/testsuite/gas/mips/octeon-ill.l 2008-05-18 16:00:07.000000000 -0700
+++ src/gas/testsuite/gas/mips/octeon-ill.l 2008-05-21 23:03:25.000000000 -0700
@@ -13,3 +13,7 @@
.*:26: Error: Improper size \(29\)
.*:28: Error: Improper position \(70\)
.*:29: Error: Improper size \(25\)
+.*:31: Error: Improper immediate \(512\)
+.*:32: Error: Improper immediate \(-771\)
+.*:33: Error: Improper immediate \(615\)
+.*:34: Error: Improper immediate \(-513\)
Index: src/gas/testsuite/gas/mips/octeon-ill.s
===================================================================
--- src.orig/gas/testsuite/gas/mips/octeon-ill.s 2008-05-18 15:58:47.000000000 -0700
+++ src/gas/testsuite/gas/mips/octeon-ill.s 2008-05-18 16:03:03.000000000 -0700
@@ -27,3 +27,8 @@ foo:
exts $14,$29,70,14
exts $20,$16,39,25
+
+ seqi $14,$13,512
+ seqi $19,-771
+ snei $18,$30,615
+ snei $17,-513