aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog8
-rw-r--r--gas/config/tc-mips.c99
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/mips/loongson-3a-2.d65
-rw-r--r--gas/testsuite/gas/mips/loongson-3a-2.s65
-rw-r--r--gas/testsuite/gas/mips/loongson-3a-3.d13
-rw-r--r--gas/testsuite/gas/mips/loongson-3a-3.s4
-rw-r--r--gas/testsuite/gas/mips/mips.exp2
-rw-r--r--include/opcode/ChangeLog6
-rw-r--r--include/opcode/mips.h23
-rw-r--r--opcodes/ChangeLog6
-rw-r--r--opcodes/mips-dis.c31
-rw-r--r--opcodes/mips-opc.c65
13 files changed, 392 insertions, 1 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index ca9b61d..50216fd 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,11 @@
+2010-12-18 Mingjie Xing <mingjie.xing@gmail.com>
+
+ * config/tc-mips.c (insn_uses_reg): Handle the new flags
+ INSN2_READ_FPR_Z, INSN2_READ_GPR_D and INSN2_READ_GPR_Z.
+ (append_insn): Handle delay-slot filling for the new flags.
+ (validate_mips_insn): Handle the new arguments +a|b|c|z|Z.
+ (mips_ip): Handle the new arguments +a|b|c|z|Z.
+
2010-12-18 DJ Delorie <dj@redhat.com>
* config/rx-parse.y (SUB): Correct subtraction of immediate
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 65d1989..20bf431 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -2275,6 +2275,10 @@ insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg,
&& ((EXTRACT_OPERAND (FT, *ip) & ~(unsigned) 1)
== (reg &~ (unsigned) 1)))
return 1;
+ if ((ip->insn_mo->pinfo2 & INSN2_READ_FPR_Z)
+ && ((EXTRACT_OPERAND (FZ, *ip) & ~(unsigned) 1)
+ == (reg &~ (unsigned) 1)))
+ return 1;
}
else if (! mips_opts.mips16)
{
@@ -2284,6 +2288,12 @@ insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg,
if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)
&& EXTRACT_OPERAND (RT, *ip) == reg)
return 1;
+ if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_D)
+ && EXTRACT_OPERAND (RD, *ip) == reg)
+ return 1;
+ if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_Z)
+ && EXTRACT_OPERAND (RZ, *ip) == reg)
+ return 1;
}
else
{
@@ -2809,6 +2819,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
bfd_reloc_code_real_type *reloc_type)
{
unsigned long prev_pinfo, pinfo;
+ unsigned long prev_pinfo2, pinfo2;
relax_stateT prev_insn_frag_type = 0;
bfd_boolean relaxed_branch = FALSE;
segment_info_type *si = seg_info (now_seg);
@@ -2822,7 +2833,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
file_ase_mips16 |= mips_opts.mips16;
prev_pinfo = history[0].insn_mo->pinfo;
+ prev_pinfo2 = history[0].insn_mo->pinfo2;
pinfo = ip->insn_mo->pinfo;
+ pinfo2 = ip->insn_mo->pinfo2;
if (mips_relax.sequence != 2 && !mips_opts.noreorder)
{
@@ -3162,7 +3175,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
/* Update the register mask information. */
if (! mips_opts.mips16)
{
- if (pinfo & INSN_WRITE_GPR_D)
+ if ((pinfo & INSN_WRITE_GPR_D) || (pinfo2 & INSN2_READ_GPR_D))
mips_gprmask |= 1 << EXTRACT_OPERAND (RD, *ip);
if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0)
mips_gprmask |= 1 << EXTRACT_OPERAND (RT, *ip);
@@ -3170,6 +3183,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
mips_gprmask |= 1 << EXTRACT_OPERAND (RS, *ip);
if (pinfo & INSN_WRITE_GPR_31)
mips_gprmask |= 1 << RA;
+ if (pinfo2 & (INSN2_WRITE_GPR_Z | INSN2_READ_GPR_Z))
+ mips_gprmask |= 1 << EXTRACT_OPERAND (RZ, *ip);
if (pinfo & INSN_WRITE_FPR_D)
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FD, *ip);
if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0)
@@ -3178,6 +3193,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FT, *ip);
if ((pinfo & INSN_READ_FPR_R) != 0)
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FR, *ip);
+ if (pinfo2 & (INSN2_WRITE_FPR_Z | INSN2_READ_FPR_Z))
+ mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FZ, *ip);
if (pinfo & INSN_COP)
{
/* We don't keep enough information to sort these cases out.
@@ -3272,6 +3289,10 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
&& (prev_pinfo & INSN_WRITE_GPR_D)
&& insn_uses_reg (ip, EXTRACT_OPERAND (RD, history[0]),
MIPS_GR_REG))
+ || (! mips_opts.mips16
+ && (prev_pinfo2 & INSN2_WRITE_GPR_Z)
+ && insn_uses_reg (ip, EXTRACT_OPERAND (RZ, history[0]),
+ MIPS_GR_REG))
|| (mips_opts.mips16
&& (((prev_pinfo & MIPS16_INSN_WRITE_X)
&& (insn_uses_reg
@@ -8479,6 +8500,11 @@ validate_mips_insn (const struct mips_opcode *opc)
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;
+ case 'z': USE_BITS (OP_MASK_RZ, OP_SH_RZ); break;
+ case 'Z': USE_BITS (OP_MASK_FZ, OP_SH_FZ); break;
+ 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;
default:
as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
@@ -9290,6 +9316,77 @@ mips_ip (char *str, struct mips_cl_insn *ip)
s = expr_end;
continue;
+ case 'a': /* 8-bit signed offset in bit 6 */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ min_range = -((OP_MASK_OFFSET_A + 1) >> 1);
+ max_range = ((OP_MASK_OFFSET_A + 1) >> 1) - 1;
+ if (imm_expr.X_add_number < min_range
+ || imm_expr.X_add_number > max_range)
+ {
+ as_bad (_("immediate not in range %ld..%ld (%ld)"),
+ (long) min_range, (long) max_range,
+ (long) imm_expr.X_add_number);
+ }
+ INSERT_OPERAND (OFFSET_A, *ip, imm_expr.X_add_number);
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'b': /* 8-bit signed offset in bit 3 */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ min_range = -((OP_MASK_OFFSET_B + 1) >> 1);
+ max_range = ((OP_MASK_OFFSET_B + 1) >> 1) - 1;
+ if (imm_expr.X_add_number < min_range
+ || imm_expr.X_add_number > max_range)
+ {
+ as_bad (_("immediate not in range %ld..%ld (%ld)"),
+ (long) min_range, (long) max_range,
+ (long) imm_expr.X_add_number);
+ }
+ INSERT_OPERAND (OFFSET_B, *ip, imm_expr.X_add_number);
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'c': /* 9-bit signed offset in bit 6 */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ min_range = -((OP_MASK_OFFSET_C + 1) >> 1);
+ max_range = ((OP_MASK_OFFSET_C + 1) >> 1) - 1;
+ if (imm_expr.X_add_number < min_range
+ || imm_expr.X_add_number > max_range)
+ {
+ as_bad (_("immediate not in range %ld..%ld (%ld)"),
+ (long) min_range, (long) max_range,
+ (long) imm_expr.X_add_number);
+ }
+ INSERT_OPERAND (OFFSET_C, *ip, imm_expr.X_add_number);
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'z':
+ if (!reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno))
+ break;
+ if (regno == AT && mips_opts.at)
+ {
+ if (mips_opts.at == ATREG)
+ as_warn (_("used $at without \".set noat\""));
+ else
+ as_warn (_("used $%u with \".set at=$%u\""),
+ regno, mips_opts.at);
+ }
+ INSERT_OPERAND (RZ, *ip, regno);
+ continue;
+
+ case 'Z':
+ if (!reg_lookup (&s, RTYPE_FPU, &regno))
+ break;
+ INSERT_OPERAND (FZ, *ip, regno);
+ continue;
+
default:
as_bad (_("Internal error: bad mips opcode "
"(unknown extension operand type `+%c'): %s %s"),
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 8592bf0..0cf93d6 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-12-18 Mingjie Xing <mingjie.xing@gmail.com>
+
+ * gas/mips/loongson-3a-2.s, gas/mips/loongson-3a-2.d,
+ gas/mips/loongson-3a-3.s, gas/mips/loongson-3a-3.d: New tests.
+ * gas/mips/mips.exp: Run them.
+
2010-12-12 H.J. Lu <hongjiu.lu@intel.com>
* gas/elf/elf.exp: Run section9.
diff --git a/gas/testsuite/gas/mips/loongson-3a-2.d b/gas/testsuite/gas/mips/loongson-3a-2.d
new file mode 100644
index 0000000..4029a60
--- /dev/null
+++ b/gas/testsuite/gas/mips/loongson-3a-2.d
@@ -0,0 +1,65 @@
+#as: -march=loongson3a -mabi=o64
+#objdump: -M reg-names=numeric -dr
+#name: Loongson-3A tests
+
+.*: file format .*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+.*: 70601075 campi \$2,\$3
+.*: 70a02035 campv \$4,\$5
+.*: 70e830b5 camwi \$6,\$7,\$8
+.*: 714048f5 ramri \$9,\$10
+.*: 716c0026 gsle \$11,\$12
+.*: 71ae0027 gsgt \$13,\$14
+.*: c8622010 gslble \$2,\$3,\$4
+.*: c8c53811 gslbgt \$5,\$6,\$7
+.*: c9285012 gslhle \$8,\$9,\$10
+.*: c98b6813 gslhgt \$11,\$12,\$13
+.*: c9ee8014 gslwle \$14,\$15,\$16
+.*: ca519815 gslwgt \$17,\$18,\$19
+.*: cab4b016 gsldle \$20,\$21,\$22
+.*: cb17c817 gsldgt \$23,\$24,\$25
+.*: e8622010 gssble \$2,\$3,\$4
+.*: e8c53811 gssbgt \$5,\$6,\$7
+.*: e9285012 gsshle \$8,\$9,\$10
+.*: e98b6813 gsshgt \$11,\$12,\$13
+.*: e9ee8014 gsswle \$14,\$15,\$16
+.*: ea519815 gsswgt \$17,\$18,\$19
+.*: eab4b016 gssdle \$20,\$21,\$22
+.*: eb17c817 gssdgt \$23,\$24,\$25
+.*: c8401818 gslwlec1 \$f0,\$2,\$3
+.*: c8812819 gslwgtc1 \$f1,\$4,\$5
+.*: c8c2381a gsldlec1 \$f2,\$6,\$7
+.*: c903481b gsldgtc1 \$f3,\$8,\$9
+.*: e944581c gsswlec1 \$f4,\$10,\$11
+.*: e985681d gsswgtc1 \$f5,\$12,\$13
+.*: e9c6781e gssdlec1 \$f6,\$14,\$15
+.*: ea07881f gssdgtc1 \$f7,\$16,\$17
+.*: ca480004 gslwlc1 \$f8,0\(\$18\)
+.*: ca690045 gslwrc1 \$f9,1\(\$19\)
+.*: ca8a0086 gsldlc1 \$f10,2\(\$20\)
+.*: caab00c7 gsldrc1 \$f11,3\(\$21\)
+.*: eacc0104 gsswlc1 \$f12,4\(\$22\)
+.*: eaed0145 gsswrc1 \$f13,5\(\$23\)
+.*: eb0e0186 gssdlc1 \$f14,6\(\$24\)
+.*: eb2f01c7 gssdrc1 \$f15,7\(\$25\)
+.*: d8622000 gslbx \$2,0\(\$3,\$4\)
+.*: d8c53ff9 gslhx \$5,-1\(\$6,\$7\)
+.*: d92857f2 gslwx \$8,-2\(\$9,\$10\)
+.*: d98b6feb gsldx \$11,-3\(\$12,\$13\)
+.*: f9ee87e0 gssbx \$14,-4\(\$15,\$16\)
+.*: fa519fd9 gsshx \$17,-5\(\$18,\$19\)
+.*: fab4b7d2 gsswx \$20,-6\(\$21,\$22\)
+.*: fb17cfcb gssdx \$23,-7\(\$24,\$25\)
+.*: d8501bfe gslwxc1 \$f16,127\(\$2,\$3\)
+.*: d8912c07 gsldxc1 \$f17,-128\(\$4,\$5\)
+.*: f8d23bfe gsswxc1 \$f18,127\(\$6,\$7\)
+.*: f9134c07 gssdxc1 \$f19,-128\(\$8,\$9\)
+.*: c98b3fea gslq \$10,\$11,255\(\$12\)
+.*: e9ee402d gssq \$13,\$14,-256\(\$15\)
+.*: ca15bff4 gslqc1 \$f20,\$f21,255\(\$16\)
+.*: ea37c036 gssqc1 \$f22,\$f23,-256\(\$17\)
+#pass
+
diff --git a/gas/testsuite/gas/mips/loongson-3a-2.s b/gas/testsuite/gas/mips/loongson-3a-2.s
new file mode 100644
index 0000000..16a38c9
--- /dev/null
+++ b/gas/testsuite/gas/mips/loongson-3a-2.s
@@ -0,0 +1,65 @@
+ .text
+ .set noreorder
+
+ campi $2,$3
+ campv $4,$5
+ camwi $6,$7,$8
+ ramri $9,$10
+
+ gsle $11,$12
+ gsgt $13,$14
+
+ gslble $2,$3,$4
+ gslbgt $5,$6,$7
+ gslhle $8,$9,$10
+ gslhgt $11,$12,$13
+ gslwle $14,$15,$16
+ gslwgt $17,$18,$19
+ gsldle $20,$21,$22
+ gsldgt $23,$24,$25
+ gssble $2,$3,$4
+ gssbgt $5,$6,$7
+ gsshle $8,$9,$10
+ gsshgt $11,$12,$13
+ gsswle $14,$15,$16
+ gsswgt $17,$18,$19
+ gssdle $20,$21,$22
+ gssdgt $23,$24,$25
+
+ gslwlec1 $f0,$2,$3
+ gslwgtc1 $f1,$4,$5
+ gsldlec1 $f2,$6,$7
+ gsldgtc1 $f3,$8,$9
+ gsswlec1 $f4,$10,$11
+ gsswgtc1 $f5,$12,$13
+ gssdlec1 $f6,$14,$15
+ gssdgtc1 $f7,$16,$17
+
+ gslwlc1 $f8,0($18)
+ gslwrc1 $f9,1($19)
+ gsldlc1 $f10,2($20)
+ gsldrc1 $f11,3($21)
+ gsswlc1 $f12,4($22)
+ gsswrc1 $f13,5($23)
+ gssdlc1 $f14,6($24)
+ gssdrc1 $f15,7($25)
+
+ gslbx $2,0($3,$4)
+ gslhx $5,-1($6,$7)
+ gslwx $8,-2($9,$10)
+ gsldx $11,-3($12,$13)
+ gssbx $14,-4($15,$16)
+ gsshx $17,-5($18,$19)
+ gsswx $20,-6($21,$22)
+ gssdx $23,-7($24,$25)
+
+ gslwxc1 $f16,127($2,$3)
+ gsldxc1 $f17,-128($4,$5)
+ gsswxc1 $f18,127($6,$7)
+ gssdxc1 $f19,-128($8,$9)
+
+ gslq $10,$11,255($12)
+ gssq $13,$14,-256($15)
+ gslqc1 $f20,$f21,255($16)
+ gssqc1 $f22,$f23,-256($17)
+
diff --git a/gas/testsuite/gas/mips/loongson-3a-3.d b/gas/testsuite/gas/mips/loongson-3a-3.d
new file mode 100644
index 0000000..e242c5d
--- /dev/null
+++ b/gas/testsuite/gas/mips/loongson-3a-3.d
@@ -0,0 +1,13 @@
+#as: -march=loongson3a -mabi=o64
+#objdump: -M reg-names=numeric -dr
+#name: Loongson delay slot tests
+
+.*: file format .*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.text>:
+.*: c8c50024 gslq \$4,\$5,0\(\$6\)
+.*: 10800002 beqz \$4,0x10
+.*: 00000000 nop
+#pass
diff --git a/gas/testsuite/gas/mips/loongson-3a-3.s b/gas/testsuite/gas/mips/loongson-3a-3.s
new file mode 100644
index 0000000..24f427b
--- /dev/null
+++ b/gas/testsuite/gas/mips/loongson-3a-3.s
@@ -0,0 +1,4 @@
+ gslq $4,$5,0($6)
+ beq $4,$0,1f
+ nop
+1:
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index baea397..056dd75 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -916,6 +916,8 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "loongson-2f-3"
run_dump_test "loongson-3a"
+ run_dump_test "loongson-3a-2"
+ run_dump_test "loongson-3a-3"
run_dump_test_arches "octeon" [mips_arch_list_matching octeon]
run_list_test_arches "octeon-ill" "" \
diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog
index 85ae8ab..f68805f 100644
--- a/include/opcode/ChangeLog
+++ b/include/opcode/ChangeLog
@@ -1,3 +1,9 @@
+2010-12-18 Mingjie Xing <mingjie.xing@gmail.com>
+
+ * mips.h (OP_*_OFFSET_A, OP_*_OFFSET_B, OP_*_OFFSET_C)
+ (OP_*_RZ, OP_*_FZ, INSN2_M_FP_D, INSN2_WRITE_GPR_Z, INSN2_WRITE_FPR_Z)
+ (INSN2_READ_GPR_Z, INSN2_READ_FPR_Z, INSN2_READ_GPR_D): Define.
+
2010-11-23 Richard Sandiford <rdsandiford@googlemail.com>
* mips.h: Fix previous commit.
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index f707d46..f6656a6 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -226,6 +226,18 @@
#define OP_SH_SEQI 6
#define OP_MASK_SEQI 0x3ff
+/* Loongson */
+#define OP_SH_OFFSET_A 6
+#define OP_MASK_OFFSET_A 0xff
+#define OP_SH_OFFSET_B 3
+#define OP_MASK_OFFSET_B 0xff
+#define OP_SH_OFFSET_C 6
+#define OP_MASK_OFFSET_C 0x1ff
+#define OP_SH_RZ 0
+#define OP_MASK_RZ 0x1f
+#define OP_SH_FZ 0
+#define OP_MASK_FZ 0x1f
+
/* This structure holds information for a particular instruction. */
struct mips_opcode
@@ -503,6 +515,17 @@ struct mips_opcode
only be set for macros. For instructions, FP_D in pinfo carries the
same information. */
#define INSN2_M_FP_D 0x00000010
+/* Modifies the general purpose register in OP_*_RZ. */
+#define INSN2_WRITE_GPR_Z 0x00000020
+/* Modifies the floating point register in OP_*_FZ. */
+#define INSN2_WRITE_FPR_Z 0x00000040
+/* Reads the general purpose register in OP_*_RZ. */
+#define INSN2_READ_GPR_Z 0x00000080
+/* Reads the floating point register in OP_*_FZ. */
+#define INSN2_READ_FPR_Z 0x00000100
+/* Reads the general purpose register in OP_*_RD. */
+#define INSN2_READ_GPR_D 0x00000200
+
/* Masks used to mark instructions to indicate which MIPS ISA level
they were introduced in. INSN_ISA_MASK masks an enumeration that
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index bef474e..b18b6b9 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,9 @@
+2010-12-18 Mingjie Xing <mingjie.xing@gmail.com>
+
+ * mips-opc.c (WR_z, WR_Z, RD_z, RD_Z, RD_d): Define.
+ (mips_builtin_opcodes): Add loongson3a specific instructions.
+ * mips-dis.c (print_insn_args): Handle the new arguments +a|b|c|z|Z.
+
2010-12-11 Mingming Sun <mingm.sun@gmail.com>
* mips-opc.c: (mips_builtin_opcodes): Add loongson3a mul/div and
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index a528e96..ca65d71 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -973,6 +973,37 @@ print_insn_args (const char *d,
(*info->fprintf_func) (info->stream, "%d", op);
break;
+ case 'a': /* 8-bit signed offset in bit 6 */
+ delta = (l >> OP_SH_OFFSET_A) & OP_MASK_OFFSET_A;
+ if (delta & 0x80)
+ delta |= ~OP_MASK_OFFSET_A;
+ (*info->fprintf_func) (info->stream, "%d", delta);
+ break;
+
+ case 'b': /* 8-bit signed offset in bit 3 */
+ delta = (l >> OP_SH_OFFSET_B) & OP_MASK_OFFSET_B;
+ if (delta & 0x80)
+ delta |= ~OP_MASK_OFFSET_B;
+ (*info->fprintf_func) (info->stream, "%d", delta);
+ break;
+
+ case 'c': /* 9-bit signed offset in bit 6 */
+ delta = (l >> OP_SH_OFFSET_C) & OP_MASK_OFFSET_C;
+ if (delta & 0x100)
+ delta |= ~OP_MASK_OFFSET_C;
+ (*info->fprintf_func) (info->stream, "%d", delta);
+ break;
+
+ case 'z':
+ (*info->fprintf_func) (info->stream, "%s",
+ mips_gpr_names[(l >> OP_SH_RZ) & OP_MASK_RZ]);
+ break;
+
+ case 'Z':
+ (*info->fprintf_func) (info->stream, "%s",
+ mips_fpr_names[(l >> OP_SH_FZ) & OP_MASK_FZ]);
+ break;
+
default:
/* xgettext:c-format */
(*info->fprintf_func) (info->stream,
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index e22c20c..fc25e07 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -164,6 +164,13 @@
/* MIPS MT ASE support. */
#define MT32 INSN_MT
+/* Loongson support. */
+#define WR_z INSN2_WRITE_GPR_Z
+#define WR_Z INSN2_WRITE_FPR_Z
+#define RD_z INSN2_READ_GPR_Z
+#define RD_Z INSN2_READ_FPR_Z
+#define RD_d INSN2_READ_GPR_D
+
/* The order of overloaded instructions matters. Label arguments and
register arguments look the same. Instructions that can have either
for arguments must apear in the correct order in this table for the
@@ -199,6 +206,64 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"b", "p", 0x04010000, 0xffff0000, UBD, INSN2_ALIAS, I1 },/* bgez 0 */
{"bal", "p", 0x04110000, 0xffff0000, UBD|WR_31, INSN2_ALIAS, I1 },/* bgezal 0*/
+/* Loongson specific instructions. Loongson 3A redefines the Coprocessor 2
+ instructions. Put them here so that disassembler will find them first.
+ The assemblers uses a hash table based on the instruction name anyhow. */
+{"campi", "d,s", 0x70000075, 0xfc1f07ff, WR_d|RD_s, 0, IL3A },
+{"campv", "d,s", 0x70000035, 0xfc1f07ff, WR_d|RD_s, 0, IL3A },
+{"camwi", "d,s,t", 0x700000b5, 0xfc0007ff, RD_s|RD_t, RD_d, IL3A },
+{"ramri", "d,s", 0x700000f5, 0xfc1f07ff, WR_d|RD_s, 0, IL3A },
+{"gsle", "s,t", 0x70000026, 0xfc00ffff, RD_s|RD_t, 0, IL3A },
+{"gsgt", "s,t", 0x70000027, 0xfc00ffff, RD_s|RD_t, 0, IL3A },
+{"gslble", "t,b,d", 0xc8000010, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslbgt", "t,b,d", 0xc8000011, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslhle", "t,b,d", 0xc8000012, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslhgt", "t,b,d", 0xc8000013, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslwle", "t,b,d", 0xc8000014, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslwgt", "t,b,d", 0xc8000015, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gsldle", "t,b,d", 0xc8000016, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gsldgt", "t,b,d", 0xc8000017, 0xfc0007ff, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gssble", "t,b,d", 0xe8000010, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gssbgt", "t,b,d", 0xe8000011, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gsshle", "t,b,d", 0xe8000012, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gsshgt", "t,b,d", 0xe8000013, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gsswle", "t,b,d", 0xe8000014, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gsswgt", "t,b,d", 0xe8000015, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gssdle", "t,b,d", 0xe8000016, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gssdgt", "t,b,d", 0xe8000017, 0xfc0007ff, RD_t|RD_b|SM, RD_d, IL3A },
+{"gslwlec1", "T,b,d", 0xc8000018, 0xfc0007ff, WR_T|RD_b|LDD, RD_d, IL3A },
+{"gslwgtc1", "T,b,d", 0xc8000019, 0xfc0007ff, WR_T|RD_b|LDD, RD_d, IL3A },
+{"gsldlec1", "T,b,d", 0xc800001a, 0xfc0007ff, WR_T|RD_b|LDD, RD_d, IL3A },
+{"gsldgtc1", "T,b,d", 0xc800001b, 0xfc0007ff, WR_T|RD_b|LDD, RD_d, IL3A },
+{"gsswlec1", "T,b,d", 0xe800001c, 0xfc0007ff, RD_T|RD_b|SM, RD_d, IL3A },
+{"gsswgtc1", "T,b,d", 0xe800001d, 0xfc0007ff, RD_T|RD_b|SM, RD_d, IL3A },
+{"gssdlec1", "T,b,d", 0xe800001e, 0xfc0007ff, RD_T|RD_b|SM, RD_d, IL3A },
+{"gssdgtc1", "T,b,d", 0xe800001f, 0xfc0007ff, RD_T|RD_b|SM, RD_d, IL3A },
+{"gslwlc1", "T,+a(b)", 0xc8000004, 0xfc00c03f, WR_T|RD_b|LDD, 0, IL3A },
+{"gslwrc1", "T,+a(b)", 0xc8000005, 0xfc00c03f, WR_T|RD_b|LDD, 0, IL3A },
+{"gsldlc1", "T,+a(b)", 0xc8000006, 0xfc00c03f, WR_T|RD_b|LDD, 0, IL3A },
+{"gsldrc1", "T,+a(b)", 0xc8000007, 0xfc00c03f, WR_T|RD_b|LDD, 0, IL3A },
+{"gsswlc1", "T,+a(b)", 0xe8000004, 0xfc00c03f, RD_T|RD_b|SM, 0, IL3A },
+{"gsswrc1", "T,+a(b)", 0xe8000005, 0xfc00c03f, RD_T|RD_b|SM, 0, IL3A },
+{"gssdlc1", "T,+a(b)", 0xe8000006, 0xfc00c03f, RD_T|RD_b|SM, 0, IL3A },
+{"gssdrc1", "T,+a(b)", 0xe8000007, 0xfc00c03f, RD_T|RD_b|SM, 0, IL3A },
+{"gslbx", "t,+b(b,d)", 0xd8000000, 0xfc000007, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslhx", "t,+b(b,d)", 0xd8000001, 0xfc000007, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gslwx", "t,+b(b,d)", 0xd8000002, 0xfc000007, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gsldx", "t,+b(b,d)", 0xd8000003, 0xfc000007, WR_t|RD_b|LDD, RD_d, IL3A },
+{"gssbx", "t,+b(b,d)", 0xf8000000, 0xfc000007, RD_t|RD_b|SM, RD_d, IL3A },
+{"gsshx", "t,+b(b,d)", 0xf8000001, 0xfc000007, RD_t|RD_b|SM, RD_d, IL3A },
+{"gsswx", "t,+b(b,d)", 0xf8000002, 0xfc000007, RD_t|RD_b|SM, RD_d, IL3A },
+{"gssdx", "t,+b(b,d)", 0xf8000003, 0xfc000007, RD_t|RD_b|SM, RD_d, IL3A },
+{"gslwxc1", "T,+b(b,d)", 0xd8000006, 0xfc000007, WR_T|RD_b|LDD, RD_d, IL3A },
+{"gsldxc1", "T,+b(b,d)", 0xd8000007, 0xfc000007, WR_T|RD_b|LDD, RD_d, IL3A },
+{"gsswxc1", "T,+b(b,d)", 0xf8000006, 0xfc000007, RD_T|RD_b|SM, RD_d, IL3A },
+{"gssdxc1", "T,+b(b,d)", 0xf8000007, 0xfc000007, RD_T|RD_b|SM, RD_d, IL3A },
+{"gslq", "+z,t,+c(b)", 0xc8000020, 0xfc008020, WR_t|RD_b|LDD, WR_z, IL3A },
+{"gssq", "+z,t,+c(b)", 0xe8000020, 0xfc008020, RD_t|RD_b|SM, RD_z, IL3A },
+{"gslqc1", "+Z,T,+c(b)", 0xc8008020, 0xfc008020, WR_T|RD_b|LDD, WR_Z, IL3A },
+{"gssqc1", "+Z,T,+c(b)", 0xe8008020, 0xfc008020, RD_T|RD_b|SM, RD_Z, IL3A },
+
{"abs", "d,v", 0, (int) M_ABS, INSN_MACRO, 0, I1 },
{"abs.s", "D,V", 0x46000005, 0xffff003f, WR_D|RD_S|FP_S, 0, I1 },
{"abs.d", "D,V", 0x46200005, 0xffff003f, WR_D|RD_S|FP_D, 0, I1 },