* 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.
-------------------------------------------------------------------
This commit is contained in:
Thiemo Seufer
2006-05-19 12:34:09 +00:00
parent 9e328bda63
commit 707bfff6e6
3 changed files with 432 additions and 372 deletions

View File

@ -1,3 +1,26 @@
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> 2006-05-19 Thiemo Seufer <ths@mips.com>
* config/tc-arm.c, config/tc-arm.h (tc_arm_regname_to_dw2regnum): * config/tc-arm.c, config/tc-arm.h (tc_arm_regname_to_dw2regnum):

View File

@ -301,33 +301,31 @@ static int mips_32bitmode = 0;
#define ABI_NEEDS_32BIT_REGS(ABI) ((ABI) == O32_ABI) #define ABI_NEEDS_32BIT_REGS(ABI) ((ABI) == O32_ABI)
/* Likewise 64-bit registers. */ /* Likewise 64-bit registers. */
#define ABI_NEEDS_64BIT_REGS(ABI) \ #define ABI_NEEDS_64BIT_REGS(ABI) \
((ABI) == N32_ABI \ ((ABI) == N32_ABI \
|| (ABI) == N64_ABI \ || (ABI) == N64_ABI \
|| (ABI) == O64_ABI) || (ABI) == O64_ABI)
/* Return true if ISA supports 64 bit gp register instructions. */ /* Return true if ISA supports 64 bit gp register instructions. */
#define ISA_HAS_64BIT_REGS(ISA) ( \ #define ISA_HAS_64BIT_REGS(ISA) \
(ISA) == ISA_MIPS3 \ ((ISA) == ISA_MIPS3 \
|| (ISA) == ISA_MIPS4 \ || (ISA) == ISA_MIPS4 \
|| (ISA) == ISA_MIPS5 \ || (ISA) == ISA_MIPS5 \
|| (ISA) == ISA_MIPS64 \ || (ISA) == ISA_MIPS64 \
|| (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R2)
)
/* Return true if ISA supports 64-bit right rotate (dror et al.) /* Return true if ISA supports 64-bit right rotate (dror et al.)
instructions. */ instructions. */
#define ISA_HAS_DROR(ISA) ( \ #define ISA_HAS_DROR(ISA) \
(ISA) == ISA_MIPS64R2 \ ((ISA) == ISA_MIPS64R2)
)
/* Return true if ISA supports 32-bit right rotate (ror et al.) /* Return true if ISA supports 32-bit right rotate (ror et al.)
instructions. */ instructions. */
#define ISA_HAS_ROR(ISA) ( \ #define ISA_HAS_ROR(ISA) \
(ISA) == ISA_MIPS32R2 \ ((ISA) == ISA_MIPS32R2 \
|| (ISA) == ISA_MIPS64R2 \ || (ISA) == ISA_MIPS64R2 \
|| mips_opts.ase_smartmips \ || mips_opts.ase_smartmips)
)
#define HAVE_32BIT_GPRS \ #define HAVE_32BIT_GPRS \
(mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
@ -1402,8 +1400,297 @@ init_vr4120_conflicts (void)
#undef CONFLICT #undef CONFLICT
} }
/* This function is called once, at assembler startup time. It should struct regname {
set up all the tables, etc. that the MD part of the assembler will need. */ 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 void
md_begin (void) md_begin (void)
@ -1490,46 +1777,20 @@ md_begin (void)
/* We add all the general register names to the symbol table. This /* We add all the general register names to the symbol table. This
helps us detect invalid uses of them. */ helps us detect invalid uses of them. */
for (i = 0; i < 32; i++) for (i = 0; reg_names[i].name; i++)
{ symbol_table_insert (symbol_new (reg_names[i].name, reg_section,
char buf[5]; reg_names[i].num, // & RNUM_MASK,
&zero_address_frag));
sprintf (buf, "$%d", i); if (HAVE_NEWABI)
symbol_table_insert (symbol_new (buf, reg_section, i, 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)); &zero_address_frag));
} else
symbol_table_insert (symbol_new ("$ra", reg_section, RA, for (i = 0; reg_names_o32[i].name; i++)
&zero_address_frag)); symbol_table_insert (symbol_new (reg_names_o32[i].name, reg_section,
symbol_table_insert (symbol_new ("$fp", reg_section, FP, reg_names_o32[i].num, // & RNUM_MASK,
&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,
&zero_address_frag)); &zero_address_frag));
}
mips_no_prev_insn (); mips_no_prev_insn ();
@ -1544,6 +1805,7 @@ md_begin (void)
bfd_set_gp_size (stdoutput, g_switch_value); bfd_set_gp_size (stdoutput, g_switch_value);
#ifdef OBJ_ELF
if (OUTPUT_FLAVOR == bfd_target_elf_flavour) if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
{ {
/* On a native system other than VxWorks, sections must be aligned /* 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_flags (stdoutput, sec, flags);
bfd_set_section_alignment (stdoutput, sec, HAVE_NEWABI ? 3 : 2); bfd_set_section_alignment (stdoutput, sec, HAVE_NEWABI ? 3 : 2);
#ifdef OBJ_ELF
mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo)); mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
#endif
} }
else else
{ {
@ -1594,7 +1854,6 @@ md_begin (void)
bfd_set_section_flags (stdoutput, sec, flags); bfd_set_section_flags (stdoutput, sec, flags);
bfd_set_section_alignment (stdoutput, sec, 3); bfd_set_section_alignment (stdoutput, sec, 3);
#ifdef OBJ_ELF
/* Set up the option header. */ /* Set up the option header. */
{ {
Elf_Internal_Options opthdr; Elf_Internal_Options opthdr;
@ -1611,7 +1870,6 @@ md_begin (void)
mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo)); mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo));
} }
#endif
} }
if (ECOFF_DEBUGGING) if (ECOFF_DEBUGGING)
@ -1621,7 +1879,6 @@ md_begin (void)
SEC_HAS_CONTENTS | SEC_READONLY); SEC_HAS_CONTENTS | SEC_READONLY);
(void) bfd_set_section_alignment (stdoutput, sec, 2); (void) bfd_set_section_alignment (stdoutput, sec, 2);
} }
#ifdef OBJ_ELF
else if (OUTPUT_FLAVOR == bfd_target_elf_flavour && mips_flag_pdr) else if (OUTPUT_FLAVOR == bfd_target_elf_flavour && mips_flag_pdr)
{ {
pdr_seg = subseg_new (".pdr", (subsegT) 0); pdr_seg = subseg_new (".pdr", (subsegT) 0);
@ -1630,11 +1887,11 @@ md_begin (void)
| SEC_DEBUGGING); | SEC_DEBUGGING);
(void) bfd_set_section_alignment (stdoutput, pdr_seg, 2); (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
} }
#endif
subseg_set (seg, subseg); subseg_set (seg, subseg);
} }
} }
#endif /* OBJ_ELF */
if (! ECOFF_DEBUGGING) if (! ECOFF_DEBUGGING)
md_obj_begin (); md_obj_begin ();
@ -7972,6 +8229,8 @@ mips_ip (char *str, struct mips_cl_insn *ip)
char *s_reset; char *s_reset;
char save_c = 0; char save_c = 0;
offsetT min_range, max_range; offsetT min_range, max_range;
int argnum;
unsigned int rtype;
insn_error = NULL; insn_error = NULL;
@ -8079,6 +8338,7 @@ mips_ip (char *str, struct mips_cl_insn *ip)
create_insn (ip, insn); create_insn (ip, insn);
insn_error = NULL; insn_error = NULL;
argnum = 1;
for (args = insn->args;; ++args) for (args = insn->args;; ++args)
{ {
int is_mdmx; int is_mdmx;
@ -8495,11 +8755,11 @@ do_msbd:
s = expr_end; s = expr_end;
continue; continue;
case 'T': /* Coprocessor register */ case 'T': /* Coprocessor register. */
/* +T is for disassembly only; never match. */ /* +T is for disassembly only; never match. */
break; break;
case 't': /* Coprocessor register number */ case 't': /* Coprocessor register number. */
if (s[0] == '$' && ISDIGIT (s[1])) if (s[0] == '$' && ISDIGIT (s[1]))
{ {
++s; ++s;
@ -8633,7 +8893,7 @@ do_msbd:
s = expr_end; s = expr_end;
continue; continue;
case 'P': /* Performance register */ case 'P': /* Performance register. */
my_getExpression (&imm_expr, s); my_getExpression (&imm_expr, s);
check_absolute_expr (ip, &imm_expr); check_absolute_expr (ip, &imm_expr);
if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1) if (imm_expr.X_add_number != 0 && imm_expr.X_add_number != 1)
@ -8644,6 +8904,20 @@ do_msbd:
s = expr_end; s = expr_end;
continue; 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, &regno);
else
ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno);
ip->insn_opcode |= regno << OP_SH_RD;
if (ok)
{
lastregno = regno;
continue;
}
else
break;
case 'b': /* base register */ case 'b': /* base register */
case 'd': /* destination register */ case 'd': /* destination register */
case 's': /* source register */ case 's': /* source register */
@ -8652,106 +8926,22 @@ do_msbd:
case 'v': /* both dest and source */ case 'v': /* both dest and source */
case 'w': /* both dest and target */ case 'w': /* both dest and target */
case 'E': /* coprocessor target register */ case 'E': /* coprocessor target register */
case 'G': /* coprocessor destination register */
case 'K': /* 'rdhwr' destination register */ case 'K': /* 'rdhwr' destination register */
case 'x': /* ignore register name */ case 'x': /* ignore register name */
case 'z': /* must be zero register */ case 'z': /* must be zero register */
case 'U': /* destination register (clo/clz). */ case 'U': /* destination register (clo/clz). */
case 'g': /* coprocessor destination register */ case 'g': /* coprocessor destination register */
s_reset = s; s_reset = s;
if (s[0] == '$') if (*args == 'E' || *args == 'K')
ok = reg_lookup (&s, RTYPE_NUM, &regno);
else
{
ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno);
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; c = *args;
if (*s == ' ') if (*s == ' ')
++s; ++s;
@ -8817,7 +9007,6 @@ do_msbd:
lastregno = regno; lastregno = regno;
continue; continue;
} }
notreg:
switch (*args++) switch (*args++)
{ {
case 'r': case 'r':
@ -8870,26 +9059,19 @@ do_msbd:
case 'R': /* floating point source register */ case 'R': /* floating point source register */
case 'V': case 'V':
case 'W': 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; s_reset = s;
/* Accept $fN for FP and MDMX register numbers, and in if (reg_lookup (&s, rtype, &regno))
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])))
{ {
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 if ((regno & 1) != 0
&& HAVE_32BIT_FPRS && HAVE_32BIT_FPRS
&& ! (strcmp (str, "mtc1") == 0 && ! (strcmp (str, "mtc1") == 0
@ -9291,19 +9473,11 @@ do_msbd:
case 'N': /* 3 bit branch condition code */ case 'N': /* 3 bit branch condition code */
case 'M': /* 3 bit compare 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, &regno))
break; 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 if ((strcmp(str + strlen(str) - 3, ".ps") == 0
|| strcmp(str + strlen(str) - 5, "any2f") == 0 || strcmp(str + strlen(str) - 5, "any2f") == 0
|| strcmp(str + strlen(str) - 5, "any2t") == 0) || strcmp(str + strlen(str) - 5, "any2t") == 0)
@ -9614,70 +9788,19 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
case 'R': case 'R':
case 'X': case 'X':
case 'Y': case 'Y':
if (s[0] != '$') s_reset = s;
break; if (!reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno))
s_reset = s;
if (ISDIGIT (s[1]))
{ {
++s; if (c == 'v' || c == 'w')
regno = 0;
do
{ {
regno *= 10; if (c == 'v')
regno += *s - '0'; ip->insn_opcode |= lastregno << MIPS16OP_SH_RX;
++s; else
ip->insn_opcode |= lastregno << MIPS16OP_SH_RY;
++args;
continue;
} }
while (ISDIGIT (*s)); break;
if (regno > 31)
{
as_bad (_("invalid register number (%d)"), regno);
regno = 2;
}
}
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
break;
} }
if (*s == ' ') if (*s == ' ')
@ -9883,30 +10006,19 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
mask = 7 << 3; mask = 7 << 3;
while (*s != '\0') while (*s != '\0')
{ {
int freg, reg1, reg2; unsigned int freg, reg1, reg2;
while (*s == ' ' || *s == ',') while (*s == ' ' || *s == ',')
++s; ++s;
if (*s != '$') if (reg_lookup (&s, RTYPE_GP | RTYPE_NUM, &reg1))
freg = 0;
else if (reg_lookup (&s, RTYPE_FPU, &reg1))
freg = 1;
else
{ {
as_bad (_("can't parse register list")); as_bad (_("can't parse register list"));
break; break;
} }
++s;
if (*s != 'f')
freg = 0;
else
{
freg = 1;
++s;
}
reg1 = 0;
while (ISDIGIT (*s))
{
reg1 *= 10;
reg1 += *s - '0';
++s;
}
if (*s == ' ') if (*s == ' ')
++s; ++s;
if (*s != '-') if (*s != '-')
@ -9914,25 +10026,11 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
else else
{ {
++s; ++s;
if (*s != '$') if (!reg_lookup (&s, freg ? RTYPE_FPU
break; : (RTYPE_GP | RTYPE_NUM), &reg2))
++s;
if (freg)
{ {
if (*s == 'f') as_bad (_("invalid register list"));
++s; break;
else
{
as_bad (_("invalid register list"));
break;
}
}
reg2 = 0;
while (ISDIGIT (*s))
{
reg2 *= 10;
reg2 += *s - '0';
++s;
} }
} }
if (freg && reg1 == 0 && reg2 == 0 && c == 'L') if (freg && reg1 == 0 && reg2 == 0 && c == 'L')
@ -9997,39 +10095,26 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
continue; continue;
} }
if (*s != '$') if (! reg_lookup (&s, RTYPE_GP | RTYPE_NUM, &reg1))
{ {
as_bad (_("can't parse register list")); as_bad (_("can't parse register list"));
break; break;
} }
++s;
reg1 = 0; while (*s == ' ')
while (ISDIGIT (*s)) ++s;
{
reg1 *= 10;
reg1 += *s - '0';
++s;
}
SKIP_SPACE_TABS (s);
if (*s != '-') if (*s != '-')
reg2 = reg1; reg2 = reg1;
else else
{ {
++s; ++s;
if (*s != '$') if (! reg_lookup (&s, RTYPE_GP | RTYPE_NUM, &reg2)
|| reg2 < reg1)
{ {
as_bad (_("can't parse register list")); as_bad (_("can't parse register list"));
break; break;
} }
++s;
reg2 = 0;
while (ISDIGIT (*s))
{
reg2 *= 10;
reg2 += *s - '0';
++s;
}
} }
while (reg1 <= reg2) while (reg1 <= reg2)
@ -12786,73 +12871,11 @@ s_mips_weakext (int ignore ATTRIBUTE_UNUSED)
int int
tc_get_register (int frame) tc_get_register (int frame)
{ {
int reg; unsigned int reg;
SKIP_WHITESPACE (); SKIP_WHITESPACE ();
if (*input_line_pointer++ != '$') if (! reg_lookup (&input_line_pointer, RWARN | RTYPE_NUM | RTYPE_GP, &reg))
{ reg = 0;
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 (frame) if (frame)
{ {
mips_frame_reg = reg != 0 ? reg : SP; mips_frame_reg = reg != 0 ? reg : SP;
@ -14708,3 +14731,14 @@ mips_cfi_frame_initial_instructions (void)
cfi_add_CFA_def_cfa_register (SP); 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 (&regname, RTYPE_GP | RTYPE_NUM, &reg))
regnum = reg;
return regnum;
}

View File

@ -160,6 +160,9 @@ extern int mips_dwarf2_addr_size (void);
#define tc_cfi_frame_initial_instructions mips_cfi_frame_initial_instructions #define tc_cfi_frame_initial_instructions mips_cfi_frame_initial_instructions
extern void mips_cfi_frame_initial_instructions (void); 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_DEFAULT_RETURN_COLUMN 31
#define DWARF2_CIE_DATA_ALIGNMENT -4 #define DWARF2_CIE_DATA_ALIGNMENT -4