Index: gas/config/tc-mips.c =================================================================== RCS file: /cvs/src/src/gas/config/tc-mips.c,v retrieving revision 1.434 diff -u -p -r1.434 tc-mips.c --- gas/config/tc-mips.c 23 Nov 2010 17:04:10 -0000 1.434 +++ gas/config/tc-mips.c 26 Nov 2010 06:56:52 -0000 @@ -3698,6 +3698,11 @@ macro_build (expressionS *ep, const char INSERT_OPERAND (BP, insn, va_arg (args, int)); continue; + /* Loongson-3A */ + case 'y': + INSERT_OPERAND (RY, insn, va_arg (args, int)); + continue; + case 't': case 'w': case 'E': @@ -3713,6 +3718,11 @@ macro_build (expressionS *ep, const char INSERT_OPERAND (FT, insn, va_arg (args, int)); continue; + /* Loongson-3A */ + case '^': + INSERT_OPERAND (FZ, insn, va_arg (args, int)); + continue; + case 'd': case 'G': case 'K': @@ -8476,6 +8486,20 @@ validate_mips_insn (const struct mips_op return 0; } break; + case '-': /* Loongson-3A */ + switch (c = *p++) + { + case 'A': USE_BITS (OP_MASK_MINUS_A, OP_SH_MINUS_A); break; + case 'B': USE_BITS (OP_MASK_MINUS_B, OP_SH_MINUS_B); break; + case 'F': USE_BITS (OP_MASK_MINUS_F, OP_SH_MINUS_F); break; + + default: + as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"), + c, opc->name, opc->args); + return 0; + } + break; + case '<': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break; case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break; case 'A': break; @@ -8495,6 +8519,7 @@ validate_mips_insn (const struct mips_op case 'O': USE_BITS (OP_MASK_ALN, OP_SH_ALN); break; case 'Q': USE_BITS (OP_MASK_VSEL, OP_SH_VSEL); USE_BITS (OP_MASK_FT, OP_SH_FT); break; + case '^': USE_BITS (OP_MASK_FZ, OP_SH_FZ); break; case 'R': USE_BITS (OP_MASK_FR, OP_SH_FR); break; case 'S': USE_BITS (OP_MASK_FS, OP_SH_FS); break; case 'T': USE_BITS (OP_MASK_FT, OP_SH_FT); break; @@ -8522,6 +8547,7 @@ validate_mips_insn (const struct mips_op case 'u': USE_BITS (OP_MASK_IMMEDIATE, OP_SH_IMMEDIATE); break; case 'v': USE_BITS (OP_MASK_RS, OP_SH_RS); break; case 'w': USE_BITS (OP_MASK_RT, OP_SH_RT); break; + case 'y': USE_BITS (OP_MASK_RY, OP_SH_RY); break; case 'x': break; case 'z': break; case 'P': USE_BITS (OP_MASK_PERFREG, OP_SH_PERFREG); break; @@ -8742,6 +8768,62 @@ mips_ip (char *str, struct mips_cl_insn if (*s == '\0') return; break; + /* Loongson-3A */ + case '-': + switch (*++args) + { + case 'A': /* 8-bit signed offset in bit 6 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_MINUS_A + 1) >> 1); + max_range = ((OP_MASK_MINUS_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 (MINUS_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_MINUS_B + 1) >> 1); + max_range = ((OP_MASK_MINUS_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 (MINUS_B, *ip, imm_expr.X_add_number); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case 'F': /* 9-bit signed offset in bit 6 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_MINUS_F + 1) >> 1); + max_range = ((OP_MASK_MINUS_F + 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 (MINUS_F, *ip, imm_expr.X_add_number); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + } + break; case '2': /* dsp 2-bit unsigned immediate in bit 11 */ my_getExpression (&imm_expr, s); @@ -9444,6 +9526,7 @@ do_msbd: else break; + case 'y': /* Loongson-3A: for offset 0 register */ case 'b': /* base register */ case 'd': /* destination register */ case 's': /* source register */ @@ -9528,6 +9611,9 @@ do_msbd: case 'E': INSERT_OPERAND (RT, *ip, regno); break; + case 'y': /* Loongson-3A */ + INSERT_OPERAND (RY, *ip, regno); + break; case 'x': /* This case exists because on the r3000 trunc expands into a macro which requires a gp @@ -9602,6 +9688,7 @@ do_msbd: case 'S': /* floating point source register */ case 'T': /* floating point target register */ case 'R': /* floating point source register */ + case '^': /* Loongson-3A: floating point register */ case 'V': case 'W': rtype = RTYPE_FPU; @@ -9641,6 +9728,10 @@ do_msbd: case 'X': INSERT_OPERAND (FD, *ip, regno); break; + /* Loongson-3A */ + case '^': + INSERT_OPERAND (FZ, *ip, regno); + break; case 'V': case 'S': case 'Y': Index: include/opcode/mips.h =================================================================== RCS file: /cvs/src/src/include/opcode/mips.h,v retrieving revision 1.70 diff -u -p -r1.70 mips.h --- include/opcode/mips.h 23 Nov 2010 20:24:32 -0000 1.70 +++ include/opcode/mips.h 26 Nov 2010 06:56:55 -0000 @@ -226,6 +226,18 @@ #define OP_SH_SEQI 6 #define OP_MASK_SEQI 0x3ff +/* Loongson 3A */ +#define OP_SH_MINUS_A 6 +#define OP_MASK_MINUS_A 0xff +#define OP_SH_MINUS_B 3 +#define OP_MASK_MINUS_B 0xff +#define OP_SH_MINUS_F 6 +#define OP_MASK_MINUS_F 0x1ff +#define OP_SH_RY 0 +#define OP_MASK_RY 0x1f +#define OP_SH_FZ 0 +#define OP_MASK_FZ 0x1f + /* This structure holds information for a particular instruction. */ struct mips_opcode @@ -430,6 +442,12 @@ struct mips_opcode #define INSN_WRITE_FPR_S 0x00000010 /* Modifies the floating point register in OP_*_FT. */ #define INSN_WRITE_FPR_T 0x00000020 +/* Loongson-3A: Modifies the general purpose register in OP_*_RY. */ +#define INSN_WRITE_GPR_Y 0x00000009 +/* Loongson-3A: Modifies the floating point register in OP_*_FZ. */ +#define INSN_WRITE_FPR_Z 0x00000090 +/* Loongson-3A: Reads the general purpose register in OP_*_RD. */ +#define INSN_READ_GPR_D 0x0000000c /* Reads the general purpose register in OP_*_RS. */ #define INSN_READ_GPR_S 0x00000040 /* Reads the general purpose register in OP_*_RT. */ @@ -440,6 +458,11 @@ struct mips_opcode #define INSN_READ_FPR_T 0x00000200 /* Reads the floating point register in OP_*_FR. */ #define INSN_READ_FPR_R 0x00000400 +/* Loongson-3A: Reads the general purpose register in OP_*_RY. */ +#define INSN_READ_GPR_Y 0x00000030 +/* Loongson-3A: Reads the floating point register in OP_*_FZ. */ +#define INSN_READ_FPR_Z 0x00000900 + /* Modifies coprocessor condition code. */ #define INSN_WRITE_COND_CODE 0x00000800 /* Reads coprocessor condition code. */ Index: opcodes/mips-dis.c =================================================================== RCS file: /cvs/src/src/opcodes/mips-dis.c,v retrieving revision 1.82 diff -u -p -r1.82 mips-dis.c --- opcodes/mips-dis.c 11 Nov 2010 10:23:39 -0000 1.82 +++ opcodes/mips-dis.c 26 Nov 2010 06:56:56 -0000 @@ -834,6 +834,40 @@ print_insn_args (const char *d, (*info->fprintf_func) (info->stream, "%c", *d); break; + case '-': /* Loongson-3A */ + /* Extension character; switch for second char. */ + d++; + switch (*d) + { + case '\0': + (*info->fprintf_func) (info->stream, + _("# internal error, incomplete extension sequence (-)")); + return; + + case 'A': /* 8-bit signed offset in bit 6 */ + /* Sign extend the offset. */ + delta = (l >> OP_SH_MINUS_A) & OP_MASK_MINUS_A; + if (delta & 0x80) + delta |= ~OP_MASK_MINUS_A; + (*info->fprintf_func) (info->stream, "%d", delta); + break; + case 'B': /* 8-bit signed offset in bit 3 */ + /* Sign extend the offset. */ + delta = (l >> OP_SH_MINUS_B) & OP_MASK_MINUS_B; + if (delta & 0x80) + delta |= ~OP_MASK_MINUS_B; + (*info->fprintf_func) (info->stream, "%d", delta); + break; + case 'F': /* 9-bit signed offset in bit 6 */ + /* Sign extend the offset. */ + delta = (l >> OP_SH_MINUS_F) & OP_MASK_MINUS_F; + if (delta & 0x100) + delta |= ~OP_MASK_MINUS_F; + (*info->fprintf_func) (info->stream, "%d", delta); + break; + } + break; + case '+': /* Extension character; switch for second char. */ d++; @@ -1087,6 +1121,11 @@ print_insn_args (const char *d, (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]); break; + /* Loongson-3A */ + case 'y': + (*info->fprintf_func) (info->stream, "%s", + mips_gpr_names[(l >> OP_SH_RY) & OP_MASK_RY]); + break; case 'i': case 'u': @@ -1199,6 +1238,12 @@ print_insn_args (const char *d, (l >> OP_SH_CODE19) & OP_MASK_CODE19); break; + /* Loongson-3A */ + case '^': + (*info->fprintf_func) (info->stream, "%s", + mips_fpr_names[(l >> OP_SH_FZ) & OP_MASK_FZ]); + break; + case 'S': case 'V': (*info->fprintf_func) (info->stream, "%s", Index: opcodes/mips-opc.c =================================================================== RCS file: /cvs/src/src/opcodes/mips-opc.c,v retrieving revision 1.82 diff -u -p -r1.82 mips-opc.c --- opcodes/mips-opc.c 11 Nov 2010 10:23:39 -0000 1.82 +++ opcodes/mips-opc.c 26 Nov 2010 06:56:57 -0000 @@ -164,6 +164,13 @@ /* MIPS MT ASE support. */ #define MT32 INSN_MT +/* Loongson-3A support */ +#define WR_y INSN_WRITE_GPR_Y +#define WR_z INSN_WRITE_FPR_Z +#define RD_y INSN_READ_GPR_Y +#define RD_z INSN_READ_FPR_Z +#define RD_d INSN_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,76 @@ const struct mips_opcode mips_builtin_op {"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, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsddiv", "d,s,t", 0x70000015, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsddivu", "d,s,t", 0x70000017, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsdiv", "d,s,t", 0x70000014, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsdivu", "d,s,t", 0x70000016, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsdmod", "d,s,t", 0x7000001d, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsdmodu", "d,s,t", 0x7000001f, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsdmult", "d,s,t", 0x70000011, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsdmultu", "d,s,t", 0x70000013, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsmod", "d,s,t", 0x7000001c, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsmodu", "d,s,t", 0x7000001e, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsmult", "d,s,t", 0x70000010, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"gsmultu", "d,s,t", 0x70000012, 0xfc0007ff, WR_d|RD_s|RD_t, 0, IL3A }, +{"ramri", "d,s", 0x700000f5, 0xfc1f07ff, WR_d|RD_s, 0, IL3A }, +{"gslbgt", "d,b,t", 0xc8000011, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslble", "d,b,t", 0xc8000010, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gsldle", "d,b,t", 0xc8000016, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gsldgt", "d,b,t", 0xc8000017, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslhgt", "d,b,t", 0xc8000013, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslhle", "d,b,t", 0xc8000012, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslwgt", "d,b,t", 0xc8000015, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslwle", "d,b,t", 0xc8000014, 0xfc0007ff, WR_d|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gsgt", "s,t", 0x70000027, 0xfc00ffff, 0, 0, IL3A }, +{"gsle", "s,t", 0x70000026, 0xfc00ffff, 0, 0, IL3A }, +{"gssbgt", "t,b,d", 0xe8000011, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gssble", "t,b,d", 0xe8000010, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gssdgt", "t,b,d", 0xe8000017, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gssdle", "t,b,d", 0xe8000016, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsshgt", "t,b,d", 0xe8000013, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsshle", "t,b,d", 0xe8000012, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsswgt", "t,b,d", 0xe8000015, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsswle", "t,b,d", 0xe8000014, 0xfc0007ff, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsldlc1", "T,-A(b)", 0xc8000006, 0xfc00c03f, LDD|WR_T|RD_b, 0, IL3A }, +{"gsldrc1", "T,-A(b)", 0xc8000007, 0xfc00c03f, LDD|WR_T|RD_b, 0, IL3A }, +{"gslwlc1", "T,-A(b)", 0xc8000004, 0xfc00c03f, LDD|WR_T|RD_b, 0, IL3A }, +{"gslwrc1", "T,-A(b)", 0xc8000005, 0xfc00c03f, LDD|WR_T|RD_b, 0, IL3A }, +{"gssdlc1", "T,-A(b)", 0xe8000006, 0xfc00c03f, SM|RD_T|RD_b, 0, IL3A }, +{"gssdrc1", "T,-A(b)", 0xe8000007, 0xfc00c03f, SM|RD_T|RD_b, 0, IL3A }, +{"gsswlc1", "T,-A(b)", 0xe8000004, 0xfc00c03f, SM|RD_T|RD_b|RD_CC, 0, IL3A }, +{"gsswrc1", "T,-A(b)", 0xe8000005, 0xfc00c03f, SM|RD_T|RD_b|RD_CC, 0, IL3A }, +{"gslbx", "t,-B(b,d)", 0xd8000000, 0xfc000007, WR_t|RD_b|RD_d|WR_CC|LDD|RD_CC, 0, IL3A }, +{"gsldx", "t,-B(b,d)", 0xd8000003, 0xfc000007, WR_t|RD_b|RD_d|WR_CC|LDD|RD_CC, 0, IL3A }, +{"gslhx", "t,-B(b,d)", 0xd8000001, 0xfc000007, WR_t|RD_b|RD_d|WR_CC|LDD|RD_CC, 0, IL3A }, +{"gslwx", "t,-B(b,d)", 0xd8000002, 0xfc000007, WR_t|RD_b|RD_d|WR_CC|LDD|RD_CC, 0, IL3A }, +{"gssbx", "t,-B(b,d)", 0xf8000000, 0xfc000007, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gssdx", "t,-B(b,d)", 0xf8000003, 0xfc000007, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsshx", "t,-B(b,d)", 0xf8000001, 0xfc000007, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsswx", "t,-B(b,d)", 0xf8000002, 0xfc000007, SM|RD_d|RD_b|RD_t|WR_CC, 0, IL3A }, +{"gsldxc1", "T,-B(b,d)", 0xd8000003, 0xfc000007, WR_T|RD_b|RD_d|WR_CC|LDD|RD_CC, 0, IL3A }, +{"gslwxc1", "T,-B(b,d)", 0xd8000003, 0xfc000007, WR_T|RD_b|RD_d|WR_CC|LDD|RD_CC, 0, IL3A }, +{"gssdxc1", "T,-B(b,d)", 0xf8000007, 0xfc000007, SM|RD_T|RD_b|RD_d|WR_CC, 0, IL3A }, +{"gsswxc1", "T,-B(b,d)", 0xf8000006, 0xfc000007, SM|RD_T|RD_b|RD_d|WR_CC, 0, IL3A }, +{"gsldgtc1", "T,b,d", 0xc800001b, 0xfc0007ff, WR_D|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gsldlec1", "T,b,d", 0xc800001a, 0xfc0007ff, WR_D|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslwgtc1", "T,b,d", 0xc8000019, 0xfc0007ff, WR_D|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gslwlec1", "T,b,d", 0xc8000018, 0xfc0007ff, WR_D|RD_b|RD_s|WR_CC|LDD, 0, IL3A }, +{"gssdgtc1", "T,b,d", 0xe800001f, 0xfc0007ff, SM|RD_T|RD_b|RD_d|WR_CC, 0, IL3A }, +{"gssdlec1", "T,b,d", 0xe800001e, 0xfc0007ff, SM|RD_T|RD_b|RD_d|WR_CC, 0, IL3A }, +{"gsswgtc1", "T,b,d", 0xe800001d, 0xfc0007ff, SM|RD_T|RD_b|RD_d|WR_CC, 0, IL3A }, +{"gsswlec1", "T,b,d", 0xe800001c, 0xfc0007ff, SM|RD_T|RD_b|RD_d|WR_CC, 0, IL3A }, +{"gslq", "y,t,-F(b)", 0xc8000020, 0xfc008020, LDD|WR_t|WR_y|RD_b|WR_CC, 0, IL3A }, +{"gssq", "y,t,-F(b)", 0xe8000020, 0xfc008020, SM|WR_t|RD_y|RD_b|RD_CC, 0, IL3A }, +{"gslqc1", "^,T,-F(b)", 0xc8008020, 0xfc008020, LDD|WR_T|WR_z|RD_b|WR_CC, 0, IL3A }, +{"gssqc1", "^,T,-F(b)", 0xe8008020, 0xfc008020, SM|RD_T|RD_z|RD_b|RD_CC, 0, 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 },