diff options
-rw-r--r-- | gas/ChangeLog | 23 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 778 | ||||
-rw-r--r-- | gas/config/tc-mips.h | 3 |
3 files changed, 432 insertions, 372 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 077395a..5cf2850 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,4 +1,27 @@ 2006-05-19 Thiemo Seufer <ths@mips.com> + David Ung <davidu@mips.com> + + * config/tc-mips.h (tc_mips_regname_to_dw2regnum): Declare. + * config/tc-mipc.c (ABI_NEEDS_64BIT_REGS, ISA_HAS_64BIT_REGS, + ISA_HAS_DROR, ISA_HAS_ROR): Reformat. + (regname, RTYPE_MASK, RTYPE_NUM, RTYPE_FPU, RTYPE_FCC, RTYPE_VEC, + RTYPE_GP, RTYPE_CP0, RTYPE_PC, RTYPE_ACC, RTYPE_CCC, RNUM_MASK, + RWARN, GENERIC_REGISTER_NUMBERS, FPU_REGISTER_NAMES, + FPU_CONDITION_CODE_NAMES, COPROC_CONDITION_CODE_NAMES, + N32N64_SYMBOLIC_REGISTER_NAMES, O32_SYMBOLIC_REGISTER_NAMES, + SYMBOLIC_REGISTER_NAMES, MIPS16_SPECIAL_REGISTER_NAMES, + MDMX_VECTOR_REGISTER_NAMES, MIPS_DSP_ACCUMULATOR_NAMES, reg_names, + reg_names_o32, reg_names_n32n64): Define register classes. + (reg_lookup): New function, use register classes. + (md_begin): Reserve register names in the symbol table. Simplify + OBJ_ELF defines. + (mips_ip): Fix comment formatting. Handle symbolic COP0 registers. + Use reg_lookup. + (mips16_ip): Use reg_lookup. + (tc_get_register): Likewise. + (tc_mips_regname_to_dw2regnum): New function. + +2006-05-19 Thiemo Seufer <ths@mips.com> * config/tc-arm.c, config/tc-arm.h (tc_arm_regname_to_dw2regnum): Un-constify string argument. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 75c3ae9..c33b4ff 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -301,33 +301,31 @@ static int mips_32bitmode = 0; #define ABI_NEEDS_32BIT_REGS(ABI) ((ABI) == O32_ABI) /* Likewise 64-bit registers. */ -#define ABI_NEEDS_64BIT_REGS(ABI) \ - ((ABI) == N32_ABI \ - || (ABI) == N64_ABI \ +#define ABI_NEEDS_64BIT_REGS(ABI) \ + ((ABI) == N32_ABI \ + || (ABI) == N64_ABI \ || (ABI) == O64_ABI) /* Return true if ISA supports 64 bit gp register instructions. */ -#define ISA_HAS_64BIT_REGS(ISA) ( \ - (ISA) == ISA_MIPS3 \ - || (ISA) == ISA_MIPS4 \ - || (ISA) == ISA_MIPS5 \ - || (ISA) == ISA_MIPS64 \ - || (ISA) == ISA_MIPS64R2 \ - ) +#define ISA_HAS_64BIT_REGS(ISA) \ + ((ISA) == ISA_MIPS3 \ + || (ISA) == ISA_MIPS4 \ + || (ISA) == ISA_MIPS5 \ + || (ISA) == ISA_MIPS64 \ + || (ISA) == ISA_MIPS64R2) /* Return true if ISA supports 64-bit right rotate (dror et al.) instructions. */ -#define ISA_HAS_DROR(ISA) ( \ - (ISA) == ISA_MIPS64R2 \ - ) +#define ISA_HAS_DROR(ISA) \ + ((ISA) == ISA_MIPS64R2) /* Return true if ISA supports 32-bit right rotate (ror et al.) instructions. */ -#define ISA_HAS_ROR(ISA) ( \ - (ISA) == ISA_MIPS32R2 \ - || (ISA) == ISA_MIPS64R2 \ - || mips_opts.ase_smartmips \ - ) +#define ISA_HAS_ROR(ISA) \ + ((ISA) == ISA_MIPS32R2 \ + || (ISA) == ISA_MIPS64R2 \ + || mips_opts.ase_smartmips) + #define HAVE_32BIT_GPRS \ (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) @@ -1402,8 +1400,297 @@ init_vr4120_conflicts (void) #undef CONFLICT } -/* This function is called once, at assembler startup time. It should - set up all the tables, etc. that the MD part of the assembler will need. */ +struct regname { + const char *name; + unsigned int num; +}; + +#define RTYPE_MASK 0x1ff00 +#define RTYPE_NUM 0x00100 +#define RTYPE_FPU 0x00200 +#define RTYPE_FCC 0x00400 +#define RTYPE_VEC 0x00800 +#define RTYPE_GP 0x01000 +#define RTYPE_CP0 0x02000 +#define RTYPE_PC 0x04000 +#define RTYPE_ACC 0x08000 +#define RTYPE_CCC 0x10000 +#define RNUM_MASK 0x000ff +#define RWARN 0x80000 + +#define GENERIC_REGISTER_NUMBERS \ + {"$0", RTYPE_NUM | 0}, \ + {"$1", RTYPE_NUM | 1}, \ + {"$2", RTYPE_NUM | 2}, \ + {"$3", RTYPE_NUM | 3}, \ + {"$4", RTYPE_NUM | 4}, \ + {"$5", RTYPE_NUM | 5}, \ + {"$6", RTYPE_NUM | 6}, \ + {"$7", RTYPE_NUM | 7}, \ + {"$8", RTYPE_NUM | 8}, \ + {"$9", RTYPE_NUM | 9}, \ + {"$10", RTYPE_NUM | 10}, \ + {"$11", RTYPE_NUM | 11}, \ + {"$12", RTYPE_NUM | 12}, \ + {"$13", RTYPE_NUM | 13}, \ + {"$14", RTYPE_NUM | 14}, \ + {"$15", RTYPE_NUM | 15}, \ + {"$16", RTYPE_NUM | 16}, \ + {"$17", RTYPE_NUM | 17}, \ + {"$18", RTYPE_NUM | 18}, \ + {"$19", RTYPE_NUM | 19}, \ + {"$20", RTYPE_NUM | 20}, \ + {"$21", RTYPE_NUM | 21}, \ + {"$22", RTYPE_NUM | 22}, \ + {"$23", RTYPE_NUM | 23}, \ + {"$24", RTYPE_NUM | 24}, \ + {"$25", RTYPE_NUM | 25}, \ + {"$26", RTYPE_NUM | 26}, \ + {"$27", RTYPE_NUM | 27}, \ + {"$28", RTYPE_NUM | 28}, \ + {"$29", RTYPE_NUM | 29}, \ + {"$30", RTYPE_NUM | 30}, \ + {"$31", RTYPE_NUM | 31} + +#define FPU_REGISTER_NAMES \ + {"$f0", RTYPE_FPU | 0}, \ + {"$f1", RTYPE_FPU | 1}, \ + {"$f2", RTYPE_FPU | 2}, \ + {"$f3", RTYPE_FPU | 3}, \ + {"$f4", RTYPE_FPU | 4}, \ + {"$f5", RTYPE_FPU | 5}, \ + {"$f6", RTYPE_FPU | 6}, \ + {"$f7", RTYPE_FPU | 7}, \ + {"$f8", RTYPE_FPU | 8}, \ + {"$f9", RTYPE_FPU | 9}, \ + {"$f10", RTYPE_FPU | 10}, \ + {"$f11", RTYPE_FPU | 11}, \ + {"$f12", RTYPE_FPU | 12}, \ + {"$f13", RTYPE_FPU | 13}, \ + {"$f14", RTYPE_FPU | 14}, \ + {"$f15", RTYPE_FPU | 15}, \ + {"$f16", RTYPE_FPU | 16}, \ + {"$f17", RTYPE_FPU | 17}, \ + {"$f18", RTYPE_FPU | 18}, \ + {"$f19", RTYPE_FPU | 19}, \ + {"$f20", RTYPE_FPU | 20}, \ + {"$f21", RTYPE_FPU | 21}, \ + {"$f22", RTYPE_FPU | 22}, \ + {"$f23", RTYPE_FPU | 23}, \ + {"$f24", RTYPE_FPU | 24}, \ + {"$f25", RTYPE_FPU | 25}, \ + {"$f26", RTYPE_FPU | 26}, \ + {"$f27", RTYPE_FPU | 27}, \ + {"$f28", RTYPE_FPU | 28}, \ + {"$f29", RTYPE_FPU | 29}, \ + {"$f30", RTYPE_FPU | 30}, \ + {"$f31", RTYPE_FPU | 31} + +#define FPU_CONDITION_CODE_NAMES \ + {"$fcc0", RTYPE_FCC | 0}, \ + {"$fcc1", RTYPE_FCC | 1}, \ + {"$fcc2", RTYPE_FCC | 2}, \ + {"$fcc3", RTYPE_FCC | 3}, \ + {"$fcc4", RTYPE_FCC | 4}, \ + {"$fcc5", RTYPE_FCC | 5}, \ + {"$fcc6", RTYPE_FCC | 6}, \ + {"$fcc7", RTYPE_FCC | 7} + +#define COPROC_CONDITION_CODE_NAMES \ + {"$cc0", RTYPE_FCC | RTYPE_CCC | 0}, \ + {"$cc1", RTYPE_FCC | RTYPE_CCC | 1}, \ + {"$cc2", RTYPE_FCC | RTYPE_CCC | 2}, \ + {"$cc3", RTYPE_FCC | RTYPE_CCC | 3}, \ + {"$cc4", RTYPE_FCC | RTYPE_CCC | 4}, \ + {"$cc5", RTYPE_FCC | RTYPE_CCC | 5}, \ + {"$cc6", RTYPE_FCC | RTYPE_CCC | 6}, \ + {"$cc7", RTYPE_FCC | RTYPE_CCC | 7} + +#define N32N64_SYMBOLIC_REGISTER_NAMES \ + {"$a4", RTYPE_GP | 8}, \ + {"$a5", RTYPE_GP | 9}, \ + {"$a6", RTYPE_GP | 10}, \ + {"$a7", RTYPE_GP | 11}, \ + {"$ta0", RTYPE_GP | 8}, /* alias for $a4 */ \ + {"$ta1", RTYPE_GP | 9}, /* alias for $a5 */ \ + {"$ta2", RTYPE_GP | 10}, /* alias for $a6 */ \ + {"$ta3", RTYPE_GP | 11}, /* alias for $a7 */ \ + {"$t0", RTYPE_GP | 12}, \ + {"$t1", RTYPE_GP | 13}, \ + {"$t2", RTYPE_GP | 14}, \ + {"$t3", RTYPE_GP | 15} + +#define O32_SYMBOLIC_REGISTER_NAMES \ + {"$t0", RTYPE_GP | 8}, \ + {"$t1", RTYPE_GP | 9}, \ + {"$t2", RTYPE_GP | 10}, \ + {"$t3", RTYPE_GP | 11}, \ + {"$t4", RTYPE_GP | 12}, \ + {"$t5", RTYPE_GP | 13}, \ + {"$t6", RTYPE_GP | 14}, \ + {"$t7", RTYPE_GP | 15}, \ + {"$ta0", RTYPE_GP | 12}, /* alias for $t4 */ \ + {"$ta1", RTYPE_GP | 13}, /* alias for $t5 */ \ + {"$ta2", RTYPE_GP | 14}, /* alias for $t6 */ \ + {"$ta3", RTYPE_GP | 15} /* alias for $t7 */ + +/* Remaining symbolic register names */ +#define SYMBOLIC_REGISTER_NAMES \ + {"$zero", RTYPE_GP | 0}, \ + {"$at", RTYPE_GP | 1}, \ + {"$AT", RTYPE_GP | 1}, \ + {"$v0", RTYPE_GP | 2}, \ + {"$v1", RTYPE_GP | 3}, \ + {"$a0", RTYPE_GP | 4}, \ + {"$a1", RTYPE_GP | 5}, \ + {"$a2", RTYPE_GP | 6}, \ + {"$a3", RTYPE_GP | 7}, \ + {"$s0", RTYPE_GP | 16}, \ + {"$s1", RTYPE_GP | 17}, \ + {"$s2", RTYPE_GP | 18}, \ + {"$s3", RTYPE_GP | 19}, \ + {"$s4", RTYPE_GP | 20}, \ + {"$s5", RTYPE_GP | 21}, \ + {"$s6", RTYPE_GP | 22}, \ + {"$s7", RTYPE_GP | 23}, \ + {"$t8", RTYPE_GP | 24}, \ + {"$t9", RTYPE_GP | 25}, \ + {"$k0", RTYPE_GP | 26}, \ + {"$kt0", RTYPE_GP | 26}, \ + {"$k1", RTYPE_GP | 27}, \ + {"$kt1", RTYPE_GP | 27}, \ + {"$gp", RTYPE_GP | 28}, \ + {"$sp", RTYPE_GP | 29}, \ + {"$s8", RTYPE_GP | 30}, \ + {"$fp", RTYPE_GP | 30}, \ + {"$ra", RTYPE_GP | 31} + +#define MIPS16_SPECIAL_REGISTER_NAMES \ + {"$pc", RTYPE_PC | 0} + +#define MDMX_VECTOR_REGISTER_NAMES \ + /* {"$v0", RTYPE_VEC | 0}, clash with REG 2 above */ \ + /* {"$v1", RTYPE_VEC | 1}, clash with REG 3 above */ \ + {"$v2", RTYPE_VEC | 2}, \ + {"$v3", RTYPE_VEC | 3}, \ + {"$v4", RTYPE_VEC | 4}, \ + {"$v5", RTYPE_VEC | 5}, \ + {"$v6", RTYPE_VEC | 6}, \ + {"$v7", RTYPE_VEC | 7}, \ + {"$v8", RTYPE_VEC | 8}, \ + {"$v9", RTYPE_VEC | 9}, \ + {"$v10", RTYPE_VEC | 10}, \ + {"$v11", RTYPE_VEC | 11}, \ + {"$v12", RTYPE_VEC | 12}, \ + {"$v13", RTYPE_VEC | 13}, \ + {"$v14", RTYPE_VEC | 14}, \ + {"$v15", RTYPE_VEC | 15}, \ + {"$v16", RTYPE_VEC | 16}, \ + {"$v17", RTYPE_VEC | 17}, \ + {"$v18", RTYPE_VEC | 18}, \ + {"$v19", RTYPE_VEC | 19}, \ + {"$v20", RTYPE_VEC | 20}, \ + {"$v21", RTYPE_VEC | 21}, \ + {"$v22", RTYPE_VEC | 22}, \ + {"$v23", RTYPE_VEC | 23}, \ + {"$v24", RTYPE_VEC | 24}, \ + {"$v25", RTYPE_VEC | 25}, \ + {"$v26", RTYPE_VEC | 26}, \ + {"$v27", RTYPE_VEC | 27}, \ + {"$v28", RTYPE_VEC | 28}, \ + {"$v29", RTYPE_VEC | 29}, \ + {"$v30", RTYPE_VEC | 30}, \ + {"$v31", RTYPE_VEC | 31} + +#define MIPS_DSP_ACCUMULATOR_NAMES \ + {"$ac0", RTYPE_ACC | 0}, \ + {"$ac1", RTYPE_ACC | 1}, \ + {"$ac2", RTYPE_ACC | 2}, \ + {"$ac3", RTYPE_ACC | 3} + +static const struct regname reg_names[] = { + GENERIC_REGISTER_NUMBERS, + FPU_REGISTER_NAMES, + FPU_CONDITION_CODE_NAMES, + COPROC_CONDITION_CODE_NAMES, + + /* The $txx registers depends on the abi, + these will be added later into the symbol table from + one of the tables below once mips_abi is set after + parsing of arguments from the command line. */ + SYMBOLIC_REGISTER_NAMES, + + MIPS16_SPECIAL_REGISTER_NAMES, + MDMX_VECTOR_REGISTER_NAMES, + MIPS_DSP_ACCUMULATOR_NAMES, + {0, 0} +}; + +static const struct regname reg_names_o32[] = { + O32_SYMBOLIC_REGISTER_NAMES, + {0, 0} +}; + +static const struct regname reg_names_n32n64[] = { + N32N64_SYMBOLIC_REGISTER_NAMES, + {0, 0} +}; + +static int +reg_lookup (char **s, unsigned int types, unsigned int *regnop) +{ + symbolS *symbolP; + char *e; + char save_c; + int reg = -1; + + /* Find end of name. */ + e = *s; + if (is_name_beginner (*e)) + ++e; + while (is_part_of_name (*e)) + ++e; + + /* Terminate name. */ + save_c = *e; + *e = '\0'; + + /* Look for a register symbol. */ + if ((symbolP = symbol_find (*s)) && S_GET_SEGMENT (symbolP) == reg_section) + { + int r = S_GET_VALUE (symbolP); + if (r & types) + reg = r & RNUM_MASK; + else if ((types & RTYPE_VEC) && (r & ~1) == (RTYPE_GP | 2)) + /* Convert GP reg $v0/1 to MDMX reg $v0/1! */ + reg = (r & RNUM_MASK) - 2; + } + /* Else see if this is a register defined in an itbl entry. */ + else if ((types & RTYPE_GP) && itbl_have_entries) + { + char *n = *s; + unsigned long r; + + if (*n == '$') + ++n; + if (itbl_get_reg_val (n, &r)) + reg = r & RNUM_MASK; + } + + /* Advance to next token if a register was recognised. */ + if (reg >= 0) + *s = e; + else if (types & RWARN) + as_warn ("Unrecognized register name `%s'", *s); + + *e = save_c; + if (regnop) + *regnop = reg; + return reg >= 0; +} + +/* This function is called once, at assembler startup time. It should set up + all the tables, etc. that the MD part of the assembler will need. */ void md_begin (void) @@ -1490,46 +1777,20 @@ md_begin (void) /* We add all the general register names to the symbol table. This helps us detect invalid uses of them. */ - for (i = 0; i < 32; i++) - { - char buf[5]; - - sprintf (buf, "$%d", i); - symbol_table_insert (symbol_new (buf, reg_section, i, + for (i = 0; reg_names[i].name; i++) + symbol_table_insert (symbol_new (reg_names[i].name, reg_section, + reg_names[i].num, // & RNUM_MASK, + &zero_address_frag)); + if (HAVE_NEWABI) + for (i = 0; reg_names_n32n64[i].name; i++) + symbol_table_insert (symbol_new (reg_names_n32n64[i].name, reg_section, + reg_names_n32n64[i].num, // & RNUM_MASK, &zero_address_frag)); - } - symbol_table_insert (symbol_new ("$ra", reg_section, RA, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$fp", reg_section, FP, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$sp", reg_section, SP, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$gp", reg_section, GP, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$at", reg_section, AT, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$kt0", reg_section, KT0, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$kt1", reg_section, KT1, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$zero", reg_section, ZERO, - &zero_address_frag)); - symbol_table_insert (symbol_new ("$pc", reg_section, -1, - &zero_address_frag)); - - /* If we don't add these register names to the symbol table, they - may end up being added as regular symbols by operand(), and then - make it to the object file as undefined in case they're not - regarded as local symbols. They're local in o32, since `$' is a - local symbol prefix, but not in n32 or n64. */ - for (i = 0; i < 8; i++) - { - char buf[6]; - - sprintf (buf, "$fcc%i", i); - symbol_table_insert (symbol_new (buf, reg_section, -1, + else + for (i = 0; reg_names_o32[i].name; i++) + symbol_table_insert (symbol_new (reg_names_o32[i].name, reg_section, + reg_names_o32[i].num, // & RNUM_MASK, &zero_address_frag)); - } mips_no_prev_insn (); @@ -1544,6 +1805,7 @@ md_begin (void) bfd_set_gp_size (stdoutput, g_switch_value); +#ifdef OBJ_ELF if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { /* On a native system other than VxWorks, sections must be aligned @@ -1582,9 +1844,7 @@ md_begin (void) bfd_set_section_flags (stdoutput, sec, flags); bfd_set_section_alignment (stdoutput, sec, HAVE_NEWABI ? 3 : 2); -#ifdef OBJ_ELF mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo)); -#endif } else { @@ -1594,7 +1854,6 @@ md_begin (void) bfd_set_section_flags (stdoutput, sec, flags); bfd_set_section_alignment (stdoutput, sec, 3); -#ifdef OBJ_ELF /* Set up the option header. */ { Elf_Internal_Options opthdr; @@ -1611,7 +1870,6 @@ md_begin (void) mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo)); } -#endif } if (ECOFF_DEBUGGING) @@ -1621,7 +1879,6 @@ md_begin (void) SEC_HAS_CONTENTS | SEC_READONLY); (void) bfd_set_section_alignment (stdoutput, sec, 2); } -#ifdef OBJ_ELF else if (OUTPUT_FLAVOR == bfd_target_elf_flavour && mips_flag_pdr) { pdr_seg = subseg_new (".pdr", (subsegT) 0); @@ -1630,11 +1887,11 @@ md_begin (void) | SEC_DEBUGGING); (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2); } -#endif subseg_set (seg, subseg); } } +#endif /* OBJ_ELF */ if (! ECOFF_DEBUGGING) md_obj_begin (); @@ -7972,6 +8229,8 @@ mips_ip (char *str, struct mips_cl_insn *ip) char *s_reset; char save_c = 0; offsetT min_range, max_range; + int argnum; + unsigned int rtype; insn_error = NULL; @@ -8079,6 +8338,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) create_insn (ip, insn); insn_error = NULL; + argnum = 1; for (args = insn->args;; ++args) { int is_mdmx; @@ -8495,11 +8755,11 @@ do_msbd: s = expr_end; continue; - case 'T': /* Coprocessor register */ + case 'T': /* Coprocessor register. */ /* +T is for disassembly only; never match. */ break; - case 't': /* Coprocessor register number */ + case 't': /* Coprocessor register number. */ if (s[0] == '$' && ISDIGIT (s[1])) { ++s; @@ -8633,7 +8893,7 @@ do_msbd: s = expr_end; continue; - case 'P': /* Performance register */ + case 'P': /* Performance register. */ my_getExpression (&imm_expr, s); check_absolute_expr (ip, &imm_expr); if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1) @@ -8644,6 +8904,20 @@ do_msbd: s = expr_end; continue; + case 'G': /* Coprocessor destination register. */ + if (((ip->insn_opcode >> OP_SH_OP) & OP_MASK_OP) == OP_OP_COP0) + ok = reg_lookup (&s, RTYPE_NUM | RTYPE_CP0, ®no); + else + ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); + ip->insn_opcode |= regno << OP_SH_RD; + if (ok) + { + lastregno = regno; + continue; + } + else + break; + case 'b': /* base register */ case 'd': /* destination register */ case 's': /* source register */ @@ -8652,106 +8926,22 @@ do_msbd: case 'v': /* both dest and source */ case 'w': /* both dest and target */ case 'E': /* coprocessor target register */ - case 'G': /* coprocessor destination register */ case 'K': /* 'rdhwr' destination register */ case 'x': /* ignore register name */ case 'z': /* must be zero register */ case 'U': /* destination register (clo/clz). */ case 'g': /* coprocessor destination register */ - s_reset = s; - if (s[0] == '$') + s_reset = s; + if (*args == 'E' || *args == 'K') + ok = reg_lookup (&s, RTYPE_NUM, ®no); + else + { + ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no); + if (regno == AT && ! mips_opts.noat) + as_warn ("Used $at without \".set noat\""); + } + if (ok) { - if (ISDIGIT (s[1])) - { - ++s; - regno = 0; - do - { - regno *= 10; - regno += *s - '0'; - ++s; - } - while (ISDIGIT (*s)); - if (regno > 31) - as_bad (_("Invalid register number (%d)"), regno); - } - else if (*args == 'E' || *args == 'G' || *args == 'K') - goto notreg; - else - { - if (s[1] == 'r' && s[2] == 'a') - { - s += 3; - regno = RA; - } - else if (s[1] == 'f' && s[2] == 'p') - { - s += 3; - regno = FP; - } - else if (s[1] == 's' && s[2] == 'p') - { - s += 3; - regno = SP; - } - else if (s[1] == 'g' && s[2] == 'p') - { - s += 3; - regno = GP; - } - else if (s[1] == 'a' && s[2] == 't') - { - s += 3; - regno = AT; - } - else if (s[1] == 'k' && s[2] == 't' && s[3] == '0') - { - s += 4; - regno = KT0; - } - else if (s[1] == 'k' && s[2] == 't' && s[3] == '1') - { - s += 4; - regno = KT1; - } - else if (s[1] == 'z' && s[2] == 'e' && s[3] == 'r' && s[4] == 'o') - { - s += 5; - regno = ZERO; - } - else if (itbl_have_entries) - { - char *p, *n; - unsigned long r; - - p = s + 1; /* advance past '$' */ - n = itbl_get_field (&p); /* n is name */ - - /* See if this is a register defined in an - itbl entry. */ - if (itbl_get_reg_val (n, &r)) - { - /* Get_field advances to the start of - the next field, so we need to back - rack to the end of the last field. */ - if (p) - s = p - 1; - else - s = strchr (s, '\0'); - regno = r; - } - else - goto notreg; - } - else - goto notreg; - } - if (regno == AT - && ! mips_opts.noat - && *args != 'E' - && *args != 'G' - && *args != 'K') - as_warn (_("Used $at without \".set noat\"")); c = *args; if (*s == ' ') ++s; @@ -8817,7 +9007,6 @@ do_msbd: lastregno = regno; continue; } - notreg: switch (*args++) { case 'r': @@ -8870,26 +9059,19 @@ do_msbd: case 'R': /* floating point source register */ case 'V': case 'W': + rtype = RTYPE_FPU; + if (is_mdmx + || (mips_opts.ase_mdmx + && (ip->insn_mo->pinfo & FP_D) + && (ip->insn_mo->pinfo & (INSN_COPROC_MOVE_DELAY + | INSN_COPROC_MEMORY_DELAY + | INSN_LOAD_COPROC_DELAY + | INSN_LOAD_MEMORY_DELAY + | INSN_STORE_MEMORY)))) + rtype |= RTYPE_VEC; s_reset = s; - /* Accept $fN for FP and MDMX register numbers, and in - addition accept $vN for MDMX register numbers. */ - if ((s[0] == '$' && s[1] == 'f' && ISDIGIT (s[2])) - || (is_mdmx != 0 && s[0] == '$' && s[1] == 'v' - && ISDIGIT (s[2]))) + if (reg_lookup (&s, rtype, ®no)) { - s += 2; - regno = 0; - do - { - regno *= 10; - regno += *s - '0'; - ++s; - } - while (ISDIGIT (*s)); - - if (regno > 31) - as_bad (_("Invalid float register number (%d)"), regno); - if ((regno & 1) != 0 && HAVE_32BIT_FPRS && ! (strcmp (str, "mtc1") == 0 @@ -9291,19 +9473,11 @@ do_msbd: case 'N': /* 3 bit branch condition code */ case 'M': /* 3 bit compare condition code */ - if (strncmp (s, "$fcc", 4) != 0) + rtype = RTYPE_CCC; + if (ip->insn_mo->pinfo & (FP_D| FP_S)) + rtype |= RTYPE_FCC; + if (!reg_lookup (&s, rtype, ®no)) break; - s += 4; - regno = 0; - do - { - regno *= 10; - regno += *s - '0'; - ++s; - } - while (ISDIGIT (*s)); - if (regno > 7) - as_bad (_("Invalid condition code register $fcc%d"), regno); if ((strcmp(str + strlen(str) - 3, ".ps") == 0 || strcmp(str + strlen(str) - 5, "any2f") == 0 || strcmp(str + strlen(str) - 5, "any2t") == 0) @@ -9614,70 +9788,19 @@ mips16_ip (char *str, struct mips_cl_insn *ip) case 'R': case 'X': case 'Y': - if (s[0] != '$') - break; - s_reset = s; - if (ISDIGIT (s[1])) - { - ++s; - regno = 0; - do - { - regno *= 10; - regno += *s - '0'; - ++s; - } - while (ISDIGIT (*s)); - if (regno > 31) - { - as_bad (_("invalid register number (%d)"), regno); - regno = 2; - } - } - else + s_reset = s; + if (!reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no)) { - if (s[1] == 'r' && s[2] == 'a') - { - s += 3; - regno = RA; - } - else if (s[1] == 'f' && s[2] == 'p') - { - s += 3; - regno = FP; - } - else if (s[1] == 's' && s[2] == 'p') - { - s += 3; - regno = SP; - } - else if (s[1] == 'g' && s[2] == 'p') - { - s += 3; - regno = GP; - } - else if (s[1] == 'a' && s[2] == 't') - { - s += 3; - regno = AT; - } - else if (s[1] == 'k' && s[2] == 't' && s[3] == '0') - { - s += 4; - regno = KT0; - } - else if (s[1] == 'k' && s[2] == 't' && s[3] == '1') - { - s += 4; - regno = KT1; - } - else if (s[1] == 'z' && s[2] == 'e' && s[3] == 'r' && s[4] == 'o') + if (c == 'v' || c == 'w') { - s += 5; - regno = ZERO; + if (c == 'v') + ip->insn_opcode |= lastregno << MIPS16OP_SH_RX; + else + ip->insn_opcode |= lastregno << MIPS16OP_SH_RY; + ++args; + continue; } - else - break; + break; } if (*s == ' ') @@ -9883,29 +10006,18 @@ mips16_ip (char *str, struct mips_cl_insn *ip) mask = 7 << 3; while (*s != '\0') { - int freg, reg1, reg2; + unsigned int freg, reg1, reg2; while (*s == ' ' || *s == ',') ++s; - if (*s != '$') - { - as_bad (_("can't parse register list")); - break; - } - ++s; - if (*s != 'f') + if (reg_lookup (&s, RTYPE_GP | RTYPE_NUM, ®1)) freg = 0; + else if (reg_lookup (&s, RTYPE_FPU, ®1)) + freg = 1; else { - freg = 1; - ++s; - } - reg1 = 0; - while (ISDIGIT (*s)) - { - reg1 *= 10; - reg1 += *s - '0'; - ++s; + as_bad (_("can't parse register list")); + break; } if (*s == ' ') ++s; @@ -9914,25 +10026,11 @@ mips16_ip (char *str, struct mips_cl_insn *ip) else { ++s; - if (*s != '$') - break; - ++s; - if (freg) - { - if (*s == 'f') - ++s; - else - { - as_bad (_("invalid register list")); - break; - } - } - reg2 = 0; - while (ISDIGIT (*s)) + if (!reg_lookup (&s, freg ? RTYPE_FPU + : (RTYPE_GP | RTYPE_NUM), ®2)) { - reg2 *= 10; - reg2 += *s - '0'; - ++s; + as_bad (_("invalid register list")); + break; } } if (freg && reg1 == 0 && reg2 == 0 && c == 'L') @@ -9997,39 +10095,26 @@ mips16_ip (char *str, struct mips_cl_insn *ip) continue; } - if (*s != '$') + if (! reg_lookup (&s, RTYPE_GP | RTYPE_NUM, ®1)) { as_bad (_("can't parse register list")); break; } - ++s; - reg1 = 0; - while (ISDIGIT (*s)) - { - reg1 *= 10; - reg1 += *s - '0'; - ++s; - } - SKIP_SPACE_TABS (s); + while (*s == ' ') + ++s; + if (*s != '-') reg2 = reg1; else { ++s; - if (*s != '$') + if (! reg_lookup (&s, RTYPE_GP | RTYPE_NUM, ®2) + || reg2 < reg1) { as_bad (_("can't parse register list")); break; } - ++s; - reg2 = 0; - while (ISDIGIT (*s)) - { - reg2 *= 10; - reg2 += *s - '0'; - ++s; - } } while (reg1 <= reg2) @@ -12786,73 +12871,11 @@ s_mips_weakext (int ignore ATTRIBUTE_UNUSED) int tc_get_register (int frame) { - int reg; + unsigned int reg; SKIP_WHITESPACE (); - if (*input_line_pointer++ != '$') - { - as_warn (_("expected `$'")); - reg = ZERO; - } - else if (ISDIGIT (*input_line_pointer)) - { - reg = get_absolute_expression (); - if (reg < 0 || reg >= 32) - { - as_warn (_("Bad register number")); - reg = ZERO; - } - } - else - { - if (strncmp (input_line_pointer, "ra", 2) == 0) - { - reg = RA; - input_line_pointer += 2; - } - else if (strncmp (input_line_pointer, "fp", 2) == 0) - { - reg = FP; - input_line_pointer += 2; - } - else if (strncmp (input_line_pointer, "sp", 2) == 0) - { - reg = SP; - input_line_pointer += 2; - } - else if (strncmp (input_line_pointer, "gp", 2) == 0) - { - reg = GP; - input_line_pointer += 2; - } - else if (strncmp (input_line_pointer, "at", 2) == 0) - { - reg = AT; - input_line_pointer += 2; - } - else if (strncmp (input_line_pointer, "kt0", 3) == 0) - { - reg = KT0; - input_line_pointer += 3; - } - else if (strncmp (input_line_pointer, "kt1", 3) == 0) - { - reg = KT1; - input_line_pointer += 3; - } - else if (strncmp (input_line_pointer, "zero", 4) == 0) - { - reg = ZERO; - input_line_pointer += 4; - } - else - { - as_warn (_("Unrecognized register name")); - reg = ZERO; - while (ISALNUM(*input_line_pointer)) - input_line_pointer++; - } - } + if (! reg_lookup (&input_line_pointer, RWARN | RTYPE_NUM | RTYPE_GP, ®)) + reg = 0; if (frame) { mips_frame_reg = reg != 0 ? reg : SP; @@ -14708,3 +14731,14 @@ mips_cfi_frame_initial_instructions (void) cfi_add_CFA_def_cfa_register (SP); } +int +tc_mips_regname_to_dw2regnum (char *regname) +{ + unsigned int regnum = -1; + unsigned int reg; + + if (reg_lookup (®name, RTYPE_GP | RTYPE_NUM, ®)) + regnum = reg; + + return regnum; +} diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h index 5665d3d..fadf320 100644 --- a/gas/config/tc-mips.h +++ b/gas/config/tc-mips.h @@ -160,6 +160,9 @@ extern int mips_dwarf2_addr_size (void); #define tc_cfi_frame_initial_instructions mips_cfi_frame_initial_instructions extern void mips_cfi_frame_initial_instructions (void); +#define tc_regname_to_dw2regnum tc_mips_regname_to_dw2regnum +extern int tc_mips_regname_to_dw2regnum (char *regname); + #define DWARF2_DEFAULT_RETURN_COLUMN 31 #define DWARF2_CIE_DATA_ALIGNMENT -4 |