X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-sh.c;h=a7e60ea9d0b59cce4776908b9d212696ddfe08b5;hb=f6f9408fbfe7631114ec914fbe30f2c60d3150e1;hp=0bacdce122efe6de719977e9918b5539922ea8d5;hpb=67c1ffbec916d2c18096f2a285d4f5812f20bd24;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 0bacdce122..a7e60ea9d0 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -1,6 +1,6 @@ /* tc-sh.c -- Assemble code for the Renesas / SuperH SH - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 - Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -35,6 +35,7 @@ #endif #include "dwarf2dbg.h" +#include "dw2gencfi.h" typedef struct { @@ -131,13 +132,17 @@ int sh_relax; /* set if -relax seen */ int sh_small; +/* Flag to generate relocations against symbol values for local symbols. */ + +static int dont_adjust_reloc_32; + /* preset architecture set, if given; zero otherwise. */ -static int preset_target_arch; +static unsigned int preset_target_arch; /* The bit mask of architectures that could accommodate the insns seen so far. */ -static int valid_arch; +static unsigned int valid_arch; const char EXP_CHARS[] = "eE"; @@ -801,6 +806,10 @@ sh_elf_cons (register int nbytes) return; } +#ifdef md_cons_align + md_cons_align (nbytes); +#endif + do { expression (&exp); @@ -827,10 +836,10 @@ md_begin (void) { const sh_opcode_info *opcode; char *prev_name = ""; - int target_arch; + unsigned int target_arch; target_arch - = preset_target_arch ? preset_target_arch : arch_sh1_up & ~arch_sh_dsp_up; + = preset_target_arch ? preset_target_arch : arch_sh1_up & ~arch_sh_has_dsp; valid_arch = target_arch; #ifdef HAVE_SH64 @@ -844,7 +853,7 @@ md_begin (void) { if (strcmp (prev_name, opcode->name) != 0) { - if (! (opcode->arch & target_arch)) + if (!SH_MERGE_ARCH_SET_VALID (opcode->arch, target_arch)) continue; prev_name = opcode->name; hash_insert (opcode_hash_control, opcode->name, (char *) opcode); @@ -1396,13 +1405,13 @@ parse_at (char *src, sh_operand_info *op) || (l0 == 'i' && (l1 == 'x' || l1 == 's'))) { src += 2; - op->type = A_PMOD_N; + op->type = AX_PMOD_N; } else if ( (l0 == 'r' && l1 == '9') || (l0 == 'i' && l1 == 'y')) { src += 2; - op->type = A_PMODY_N; + op->type = AY_PMOD_N; } else op->type = A_INC_N; @@ -1575,8 +1584,6 @@ get_specific (sh_opcode_info *opcode, sh_operand_info *operands) case V_REG_N: case FPUL_N: case FPSCR_N: - case A_PMOD_N: - case A_PMODY_N: case DSP_REG_N: /* Opcode needs rn */ if (user->type != arg) @@ -1622,6 +1629,237 @@ get_specific (sh_opcode_info *opcode, sh_operand_info *operands) reg_m = user->reg; break; + case AS_DEC_N: + if (user->type != A_DEC_N) + goto fail; + if (user->reg < 2 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AS_INC_N: + if (user->type != A_INC_N) + goto fail; + if (user->reg < 2 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AS_IND_N: + if (user->type != A_IND_N) + goto fail; + if (user->reg < 2 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AS_PMOD_N: + if (user->type != AX_PMOD_N) + goto fail; + if (user->reg < 2 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AX_INC_N: + if (user->type != A_INC_N) + goto fail; + if (user->reg < 4 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AX_IND_N: + if (user->type != A_IND_N) + goto fail; + if (user->reg < 4 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AX_PMOD_N: + if (user->type != AX_PMOD_N) + goto fail; + if (user->reg < 4 || user->reg > 5) + goto fail; + reg_n = user->reg; + break; + + case AXY_INC_N: + if (user->type != A_INC_N) + goto fail; + if ((user->reg < 4 || user->reg > 5) + && (user->reg < 0 || user->reg > 1)) + goto fail; + reg_n = user->reg; + break; + + case AXY_IND_N: + if (user->type != A_IND_N) + goto fail; + if ((user->reg < 4 || user->reg > 5) + && (user->reg < 0 || user->reg > 1)) + goto fail; + reg_n = user->reg; + break; + + case AXY_PMOD_N: + if (user->type != AX_PMOD_N) + goto fail; + if ((user->reg < 4 || user->reg > 5) + && (user->reg < 0 || user->reg > 1)) + goto fail; + reg_n = user->reg; + break; + + case AY_INC_N: + if (user->type != A_INC_N) + goto fail; + if (user->reg < 6 || user->reg > 7) + goto fail; + reg_n = user->reg; + break; + + case AY_IND_N: + if (user->type != A_IND_N) + goto fail; + if (user->reg < 6 || user->reg > 7) + goto fail; + reg_n = user->reg; + break; + + case AY_PMOD_N: + if (user->type != AY_PMOD_N) + goto fail; + if (user->reg < 6 || user->reg > 7) + goto fail; + reg_n = user->reg; + break; + + case AYX_INC_N: + if (user->type != A_INC_N) + goto fail; + if ((user->reg < 6 || user->reg > 7) + && (user->reg < 2 || user->reg > 3)) + goto fail; + reg_n = user->reg; + break; + + case AYX_IND_N: + if (user->type != A_IND_N) + goto fail; + if ((user->reg < 6 || user->reg > 7) + && (user->reg < 2 || user->reg > 3)) + goto fail; + reg_n = user->reg; + break; + + case AYX_PMOD_N: + if (user->type != AY_PMOD_N) + goto fail; + if ((user->reg < 6 || user->reg > 7) + && (user->reg < 2 || user->reg > 3)) + goto fail; + reg_n = user->reg; + break; + + case DSP_REG_A_M: + if (user->type != DSP_REG_N) + goto fail; + if (user->reg != A_A0_NUM + && user->reg != A_A1_NUM) + goto fail; + reg_m = user->reg; + break; + + case DSP_REG_AX: + if (user->type != DSP_REG_N) + goto fail; + switch (user->reg) + { + case A_A0_NUM: + reg_x = 0; + break; + case A_A1_NUM: + reg_x = 2; + break; + case A_X0_NUM: + reg_x = 1; + break; + case A_X1_NUM: + reg_x = 3; + break; + default: + goto fail; + } + break; + + case DSP_REG_XY: + if (user->type != DSP_REG_N) + goto fail; + switch (user->reg) + { + case A_X0_NUM: + reg_x = 0; + break; + case A_X1_NUM: + reg_x = 2; + break; + case A_Y0_NUM: + reg_x = 1; + break; + case A_Y1_NUM: + reg_x = 3; + break; + default: + goto fail; + } + break; + + case DSP_REG_AY: + if (user->type != DSP_REG_N) + goto fail; + switch (user->reg) + { + case A_A0_NUM: + reg_y = 0; + break; + case A_A1_NUM: + reg_y = 1; + break; + case A_Y0_NUM: + reg_y = 2; + break; + case A_Y1_NUM: + reg_y = 3; + break; + default: + goto fail; + } + break; + + case DSP_REG_YX: + if (user->type != DSP_REG_N) + goto fail; + switch (user->reg) + { + case A_Y0_NUM: + reg_y = 0; + break; + case A_Y1_NUM: + reg_y = 1; + break; + case A_X0_NUM: + reg_y = 2; + break; + case A_X1_NUM: + reg_y = 3; + break; + default: + goto fail; + } + break; + case DSP_REG_X: if (user->type != DSP_REG_N) goto fail; @@ -1780,9 +2018,9 @@ get_specific (sh_opcode_info *opcode, sh_operand_info *operands) goto fail; } } - if ( !(valid_arch & this_try->arch)) + if ( !SH_MERGE_ARCH_SET_VALID (valid_arch, this_try->arch)) goto fail; - valid_arch &= this_try->arch; + valid_arch = SH_MERGE_ARCH_SET (valid_arch, this_try->arch); return this_try; fail: ; @@ -1909,6 +2147,7 @@ build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand) switch (i) { case REG_N: + case REG_N_D: nbuf[index] = reg_n; break; case REG_M: @@ -1925,6 +2164,9 @@ build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand) case REG_B: nbuf[index] = reg_b | 0x08; break; + case REG_N_B01: + nbuf[index] = reg_n | 0x01; + break; case IMM0_4BY4: insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0, operand); break; @@ -2065,6 +2307,7 @@ assemble_ppi (char *op_end, sh_opcode_info *opcode) if (opcode->arg[0] != A_END) op_end = get_operands (opcode, op_end, operand); + try_another_opcode: opcode = get_specific (opcode, operand); if (opcode == 0) { @@ -2095,9 +2338,43 @@ assemble_ppi (char *op_end, sh_opcode_info *opcode) movy = DDT_BASE; break; + case MOVX_NOPY: + if (movx) + as_bad (_("multiple movx specifications")); + if ((reg_n < 4 || reg_n > 5) + && (reg_n < 0 || reg_n > 1)) + as_bad (_("invalid movx address register")); + if (movy && movy != DDT_BASE) + as_bad (_("insn cannot be combined with non-nopy")); + movx = ((((reg_n & 1) != 0) << 9) + + (((reg_n & 4) == 0) << 8) + + (reg_x << 6) + + (opcode->nibbles[2] << 4) + + opcode->nibbles[3] + + DDT_BASE); + break; + + case MOVY_NOPX: + if (movy) + as_bad (_("multiple movy specifications")); + if ((reg_n < 6 || reg_n > 7) + && (reg_n < 2 || reg_n > 3)) + as_bad (_("invalid movy address register")); + if (movx && movx != DDT_BASE) + as_bad (_("insn cannot be combined with non-nopx")); + movy = ((((reg_n & 1) != 0) << 8) + + (((reg_n & 4) == 0) << 9) + + (reg_y << 6) + + (opcode->nibbles[2] << 4) + + opcode->nibbles[3] + + DDT_BASE); + break; + case MOVX: if (movx) as_bad (_("multiple movx specifications")); + if (movy & 0x2ac) + as_bad (_("previous movy requires nopx")); if (reg_n < 4 || reg_n > 5) as_bad (_("invalid movx address register")); if (opcode->nibbles[2] & 8) @@ -2119,6 +2396,8 @@ assemble_ppi (char *op_end, sh_opcode_info *opcode) case MOVY: if (movy) as_bad (_("multiple movy specifications")); + if (movx & 0x153) + as_bad (_("previous movx requires nopy")); if (opcode->nibbles[2] & 8) { /* Bit 3 in nibbles[2] is intended for bit 4 of the opcode, @@ -2147,11 +2426,31 @@ assemble_ppi (char *op_end, sh_opcode_info *opcode) | (operand[0].immediate.X_add_number & 127) << 4 | reg_n); break; + case PPI3NC: + if (cond) + { + opcode++; + goto try_another_opcode; + } + /* Fall through. */ case PPI3: if (field_b) as_bad (_("multiple parallel processing specifications")); field_b = ((opcode->nibbles[2] << 12) + (opcode->nibbles[3] << 8) + (reg_x << 6) + (reg_y << 4) + reg_n); + switch (opcode->nibbles[4]) + { + case HEX_0: + case HEX_XX00: + case HEX_00YY: + break; + case HEX_1: + case HEX_4: + field_b += opcode->nibbles[4] << 4; + break; + default: + abort (); + } break; case PDC: if (cond) @@ -2166,13 +2465,34 @@ assemble_ppi (char *op_end, sh_opcode_info *opcode) field_b = ((opcode->nibbles[2] << 12) + (opcode->nibbles[3] << 8) + cond + (reg_x << 6) + (reg_y << 4) + reg_n); cond = 0; + switch (opcode->nibbles[4]) + { + case HEX_0: + case HEX_XX00: + case HEX_00YY: + break; + case HEX_1: + case HEX_4: + field_b += opcode->nibbles[4] << 4; + break; + default: + abort (); + } break; case PMUL: if (field_b) { - if ((field_b & 0xef00) != 0xa100) + if ((field_b & 0xef00) == 0xa100) + field_b -= 0x8100; + /* pclr Dz pmuls Se,Sf,Dg */ + else if ((field_b & 0xff00) == 0x8d00 + && (SH_MERGE_ARCH_SET_VALID (valid_arch, arch_sh4al_dsp_up))) + { + valid_arch = SH_MERGE_ARCH_SET (valid_arch, arch_sh4al_dsp_up); + field_b -= 0x8cf0; + } + else as_bad (_("insn cannot be combined with pmuls")); - field_b -= 0x8100; switch (field_b & 0xf) { case A_X0_NUM: @@ -2188,7 +2508,7 @@ assemble_ppi (char *op_end, sh_opcode_info *opcode) field_b += 3 - A_A1_NUM; break; default: - as_bad (_("bad padd / psub pmuls output operand")); + as_bad (_("bad combined pmuls output operand")); } /* Generate warning if the destination register for padd / psub and pmuls is the same ( only for A0 or A1 ). @@ -2272,6 +2592,7 @@ md_assemble (char *str) sh_operand_info operand[3]; sh_opcode_info *opcode; unsigned int size = 0; + char *initial_str = str; #ifdef HAVE_SH64 if (sh64_isa_mode == sh64_isa_shmedia) @@ -2298,7 +2619,46 @@ md_assemble (char *str) if (opcode == NULL) { - as_bad (_("unknown opcode")); + /* The opcode is not in the hash table. + This means we definately have an assembly failure, + but the instruction may be valid in another CPU variant. + In this case emit something better than 'unknown opcode'. + Search the full table in sh-opc.h to check. */ + + char *name = initial_str; + int name_length = 0; + const sh_opcode_info *op; + int found = 0; + + /* identify opcode in string */ + while (isspace (*name)) + { + name++; + } + while (!isspace (name[name_length])) + { + name_length++; + } + + /* search for opcode in full list */ + for (op = sh_table; op->name; op++) + { + if (strncasecmp (op->name, name, name_length) == 0 + && op->name[name_length] == '\0') + { + found = 1; + break; + } + } + + if ( found ) + { + as_bad (_("opcode not valid for this cpu variant")); + } + else + { + as_bad (_("unknown opcode")); + } return; } @@ -2323,8 +2683,8 @@ md_assemble (char *str) { /* Since we skip get_specific here, we have to check & update valid_arch now. */ - if (valid_arch & opcode->arch) - valid_arch &= opcode->arch; + if (SH_MERGE_ARCH_SET_VALID (valid_arch, opcode->arch)) + valid_arch = SH_MERGE_ARCH_SET (valid_arch, opcode->arch); else as_bad (_("Delayed branches not available on SH1")); parse_exp (op_end + 1, &operand[0]); @@ -2528,6 +2888,7 @@ struct option md_longopts[] = #define OPTION_SMALL (OPTION_LITTLE + 1) #define OPTION_DSP (OPTION_SMALL + 1) #define OPTION_ISA (OPTION_DSP + 1) +#define OPTION_RENESAS (OPTION_ISA + 1) {"relax", no_argument, NULL, OPTION_RELAX}, {"big", no_argument, NULL, OPTION_BIG}, @@ -2535,8 +2896,10 @@ struct option md_longopts[] = {"small", no_argument, NULL, OPTION_SMALL}, {"dsp", no_argument, NULL, OPTION_DSP}, {"isa", required_argument, NULL, OPTION_ISA}, + {"renesas", no_argument, NULL, OPTION_RENESAS}, + #ifdef HAVE_SH64 -#define OPTION_ABI (OPTION_ISA + 1) +#define OPTION_ABI (OPTION_RENESAS + 1) #define OPTION_NO_MIX (OPTION_ABI + 1) #define OPTION_SHCOMPACT_CONST_CRANGE (OPTION_NO_MIX + 1) #define OPTION_NO_EXPAND (OPTION_SHCOMPACT_CONST_CRANGE + 1) @@ -2574,12 +2937,26 @@ md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) break; case OPTION_DSP: - preset_target_arch = arch_sh1_up & ~arch_sh3e_up; + preset_target_arch = arch_sh1_up & ~(arch_sh_sp_fpu|arch_sh_dp_fpu); + break; + + case OPTION_RENESAS: + dont_adjust_reloc_32 = 1; break; case OPTION_ISA: if (strcasecmp (arg, "sh4") == 0) preset_target_arch = arch_sh4; + else if (strcasecmp (arg, "sh4-nofpu") == 0) + preset_target_arch = arch_sh4_nofpu; + else if (strcasecmp (arg, "sh4-nommu-nofpu") == 0) + preset_target_arch = arch_sh4_nommu_nofpu; + else if (strcasecmp (arg, "sh4a") == 0) + preset_target_arch = arch_sh4a; + else if (strcasecmp (arg, "dsp") == 0) + preset_target_arch = arch_sh1_up & ~(arch_sh_sp_fpu|arch_sh_dp_fpu); + else if (strcasecmp (arg, "fp") == 0) + preset_target_arch = arch_sh1_up & ~arch_sh_has_dsp; else if (strcasecmp (arg, "any") == 0) preset_target_arch = arch_sh1_up; #ifdef HAVE_SH64 @@ -2599,7 +2976,35 @@ md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) } #endif /* HAVE_SH64 */ else - as_bad ("Invalid argument to --isa option: %s", arg); + { + extern const bfd_arch_info_type bfd_sh_arch; + extern unsigned int sh_ef_archset_table[]; + bfd_arch_info_type *bfd_arch = &bfd_sh_arch; + preset_target_arch = 0; + for (; bfd_arch; bfd_arch=bfd_arch->next) + { + int len = strlen(bfd_arch->printable_name); + + if (bfd_arch->mach == bfd_mach_sh5) + continue; + + if (strncasecmp (bfd_arch->printable_name, arg, len) != 0) + continue; + + if (arg[len] == '\0') + preset_target_arch = + sh_get_arch_from_bfd_mach (bfd_arch->mach); + else if (strcasecmp(&arg[len], "-up") == 0) + preset_target_arch = + sh_get_arch_up_from_bfd_mach (bfd_arch->mach); + else + continue; + break; + } + + if (!preset_target_arch) + as_bad ("Invalid argument to --isa option: %s", arg); + } break; #ifdef HAVE_SH64 @@ -2654,14 +3059,31 @@ SH options:\n\ -little generate little endian code\n\ -big generate big endian code\n\ -relax alter jump instructions for long displacements\n\ +-renesas disable optimization with section symbol for\n\ + compatibility with Renesas assembler.\n\ -small align sections to 4 byte boundaries, not 16\n\ --dsp enable sh-dsp insns, and disable sh2e/sh3e/sh4 insns.\n")); +-dsp enable sh-dsp insns, and disable floating-point ISAs.\n\ +-isa=[any use most appropriate isa\n\ + | dsp same as '-dsp'\n\ + | fp")); + { + extern const bfd_arch_info_type bfd_sh_arch; + bfd_arch_info_type *bfd_arch = &bfd_sh_arch; + for (; bfd_arch; bfd_arch=bfd_arch->next) + if (bfd_arch->mach != bfd_mach_sh5) + { + fprintf (stream, "\n | %s", bfd_arch->printable_name); + fprintf (stream, "\n | %s-up", bfd_arch->printable_name); + } + } + fprintf (stream, "]\n"); #ifdef HAVE_SH64 fprintf (stream, _("\ --isa=[shmedia set default instruction set for SH64\n\ - | SHmedia\n\ - | shcompact\n\ - | SHcompact]\n\ +-isa=[shmedia set as the default instruction set for SH64\n\ + | SHmedia\n\ + | shcompact\n\ + | SHcompact]\n")); + fprintf (stream, _("\ -abi=[32|64] set size of expanded SHmedia operands and object\n\ file type\n\ -shcompact-const-crange emit code-range descriptors for constants in\n\ @@ -2670,7 +3092,7 @@ SH options:\n\ constants and SHcompact code\n\ -no-expand do not expand MOVI, PT, PTA or PTB instructions\n\ -expand-pt32 with -abi=64, expand PT, PTA and PTB instructions\n\ - to 32 bits only")); + to 32 bits only\n")); #endif /* HAVE_SH64 */ } @@ -3191,6 +3613,7 @@ sh_fix_adjustable (fixS *fixP) if (fixP->fx_r_type == BFD_RELOC_32_PLT_PCREL || fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL || fixP->fx_r_type == BFD_RELOC_SH_GOTPC + || ((fixP->fx_r_type == BFD_RELOC_32) && dont_adjust_reloc_32) || fixP->fx_r_type == BFD_RELOC_RVA) return 0; @@ -3208,7 +3631,7 @@ sh_elf_final_processing (void) int val; /* Set file-specific flags to indicate if this code needs - a processor with the sh-dsp / sh3e ISA to execute. */ + a processor with the sh-dsp / sh2e ISA to execute. */ #ifdef HAVE_SH64 /* SH5 and above don't know about the valid_arch arch_sh* bits defined in sh-opc.h, so check SH64 mode before checking valid_arch. */ @@ -3216,24 +3639,7 @@ sh_elf_final_processing (void) val = EF_SH5; else #endif /* HAVE_SH64 */ - if (valid_arch & arch_sh1) - val = EF_SH1; - else if (valid_arch & arch_sh2) - val = EF_SH2; - else if (valid_arch & arch_sh2e) - val = EF_SH2E; - else if (valid_arch & arch_sh_dsp) - val = EF_SH_DSP; - else if (valid_arch & arch_sh3) - val = EF_SH3; - else if (valid_arch & arch_sh3_dsp) - val = EF_SH_DSP; - else if (valid_arch & arch_sh3e) - val = EF_SH3E; - else if (valid_arch & arch_sh4) - val = EF_SH4; - else - abort (); + val = sh_find_elf_flags (valid_arch); elf_elfheader (stdoutput)->e_flags &= ~EF_SH_MACH_MASK; elf_elfheader (stdoutput)->e_flags |= val; @@ -3850,10 +4256,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) rel->addend = 0; rel->howto = bfd_reloc_type_lookup (stdoutput, r_type); -#ifdef OBJ_ELF - if (rel->howto->type == R_SH_IND12W) - rel->addend += fixp->fx_offset - 4; -#endif + if (rel->howto == NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, @@ -3863,6 +4266,10 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); assert (rel->howto != NULL); } +#ifdef OBJ_ELF + else if (rel->howto->type == R_SH_IND12W) + rel->addend += fixp->fx_offset - 4; +#endif return rel; } @@ -3958,4 +4365,53 @@ sh_parse_name (char const *name, expressionS *exprP, char *nextcharP) return 1; } #endif + +void +sh_cfi_frame_initial_instructions (void) +{ + cfi_add_CFA_def_cfa (15, 0); +} + +int +sh_regname_to_dw2regnum (const char *regname) +{ + unsigned int regnum = -1; + unsigned int i; + const char *p; + char *q; + static struct { char *name; int dw2regnum; } regnames[] = + { + { "pr", 17 }, { "t", 18 }, { "gbr", 19 }, { "mach", 20 }, + { "macl", 21 }, { "fpul", 23 } + }; + + for (i = 0; i < ARRAY_SIZE (regnames); ++i) + if (strcmp (regnames[i].name, regname) == 0) + return regnames[i].dw2regnum; + + if (regname[0] == 'r') + { + p = regname + 1; + regnum = strtoul (p, &q, 10); + if (p == q || *q || regnum >= 16) + return -1; + } + else if (regname[0] == 'f' && regname[1] == 'r') + { + p = regname + 2; + regnum = strtoul (p, &q, 10); + if (p == q || *q || regnum >= 16) + return -1; + regnum += 25; + } + else if (regname[0] == 'x' && regname[1] == 'd') + { + p = regname + 2; + regnum = strtoul (p, &q, 10); + if (p == q || *q || regnum >= 8) + return -1; + regnum += 87; + } + return regnum; +} #endif /* BFD_ASSEMBLER */