/* tc-m68k.c -- Assemble for the m68k family
- Copyright (C) 1987-2015 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "opcode/m68k.h"
#include "m68k-parse.h"
-
-#if defined (OBJ_ELF)
#include "elf/m68k.h"
-#endif
-
-#ifdef M68KCOFF
-#include "obj-coff.h"
-#endif
-#ifdef OBJ_ELF
static void m68k_elf_cons (int);
-#endif
+static void m68k_elf_gnu_attribute (int);
/* This string holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful. The macro
{
struct label_line *next;
symbolS *label;
- char *file;
+ const char *file;
unsigned int line;
int text;
};
/* Pointer to list holding the opcodes sorted by name. */
static struct m68k_opcode const ** m68k_sorted_opcodes;
-/* Its an arbitrary name: This means I don't approve of it.
+/* It's an arbitrary name: This means I don't approve of it.
See flames below. */
static struct obstack robyn;
}
fragb[4];
- int nrel; /* Num of reloc strucs in use. */
+ int nrel; /* Num of reloc structs in use. */
struct
{
int n;
significance of some values (in the branch instruction, for
example). */
int pcrel_fix;
-#ifdef OBJ_ELF
/* Whether this expression needs special pic relocation, and if
so, which. */
enum pic_relocation pic_reloc;
-#endif
}
reloc[5]; /* Five is enough??? */
};
the_ins.reloc[the_ins.nrel].exp = exp->exp;
the_ins.reloc[the_ins.nrel].wid = width;
the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
-#ifdef OBJ_ELF
the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
-#endif
the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
}
unsigned long arch; /* Architecture features. */
const enum m68k_register *control_regs; /* Control regs on chip */
const char *name; /* Name */
- int alias; /* Alias for a cannonical name. If 1, then
+ int alias; /* Alias for a canonical name. If 1, then
succeeds canonical name, if -1 then
succeeds canonical name, if <-1 ||>1 this is a
deprecated name, and the next/previous name
{"even", s_even, 0},
{"skip", s_space, 0},
{"proc", s_proc, 0},
-#if defined (TE_SUN3) || defined (OBJ_ELF)
{"align", s_align_bytes, 0},
-#endif
-#ifdef OBJ_ELF
{"swbeg", s_ignore, 0},
{"long", m68k_elf_cons, 4},
-#endif
{"extend", float_cons, 'x'},
{"ldouble", float_cons, 'x'},
{"arch", s_m68k_arch, 0},
{"cpu", s_m68k_cpu, 0},
+ {"gnu_attribute", m68k_elf_gnu_attribute, 0},
/* The following pseudo-ops are supported for MRI compatibility. */
{"chip", s_chip, 0},
{"dsb", s_space, 1},
{"xdef", s_globl, 0},
-#ifdef OBJ_ELF
{"align", s_align_bytes, 0},
-#else
- {"align", s_align_ptwo, 0},
-#endif
-#ifdef M68KCOFF
- {"sect", obj_coff_section, 0},
- {"section", obj_coff_section, 0},
-#endif
{0, 0, 0}
};
|| (*s == ':' \
&& alt_notend_table[(unsigned char) s[1]])))
-#ifdef OBJ_ELF
/* Return zero if the reference to SYMBOL from within the same segment may
be relaxed. */
}
}
-#else /* !OBJ_ELF */
-
-#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
-
-/* PR gas/3041 Weak symbols are not relaxable
- because they must be treated as extern. */
-#define relaxable_symbol(symbol) (!(S_IS_WEAK (symbol)))
-
-#endif /* OBJ_ELF */
-
arelent *
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
{
#undef F
#undef MAP
- reloc = (arelent *) xmalloc (sizeof (arelent));
- reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ reloc = XNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
-#ifndef OBJ_ELF
- if (OUTPUT_FLAVOR == bfd_target_aout_flavour
- && fixp->fx_addsy
- && S_IS_WEAK (fixp->fx_addsy)
- && ! bfd_is_und_section (S_GET_SEGMENT (fixp->fx_addsy)))
- {
- /* PR gas/3041 References to weak symbols must be treated as extern
- in order to be overridable by the linker, even if they are defined
- in the same object file. So the original addend must be written
- "as is" into the output section without further processing.
- The addend value must be hacked here in order to force
- bfd_install_relocation() to write the original value into the
- output section.
- 1) MD_APPLY_SYM_VALUE() is set to 1 for m68k/a.out, so the symbol
- value has already been added to the addend in fixup_segment(). We
- have to remove it.
- 2) bfd_install_relocation() will incorrectly treat this symbol as
- resolved, so it will write the symbol value plus its addend and
- section VMA. As a workaround we can tweak the addend value here in
- order to get the original value in the section after the call to
- bfd_install_relocation(). */
- reloc->addend = fixp->fx_addnumber
- /* Fix because of MD_APPLY_SYM_VALUE() */
- - S_GET_VALUE (fixp->fx_addsy)
- /* Fix for bfd_install_relocation() */
- - (S_GET_VALUE (fixp->fx_addsy)
- + S_GET_SEGMENT (fixp->fx_addsy)->vma);
- }
- else if (fixp->fx_pcrel)
- reloc->addend = fixp->fx_addnumber;
- else
- reloc->addend = 0;
-#else
if (!fixp->fx_pcrel)
reloc->addend = fixp->fx_addnumber;
else
+ fixp->fx_pcrel_adjust
+ fixp->fx_addnumber
+ md_pcrel_from (fixp));
-#endif
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
gas_assert (reloc->howto != 0);
/* Handle of the OPCODE hash table. NULL means any use before
m68k_ip_begin() will crash. */
-static struct hash_control *op_hash;
+static htab_t op_hash;
\f
/* Assemble an m68k instruction. */
c = *p;
*p = '\0';
- opcode = (const struct m68k_incant *) hash_find (op_hash, instring);
+ opcode = (const struct m68k_incant *) str_hash_find (op_hash, instring);
*p = c;
if (pdot != NULL)
char *old = input_line_pointer;
*old = '\n';
input_line_pointer = p;
- /* Ahh - it's a motorola style psuedo op. */
+ /* Ahh - it's a motorola style pseudo op. */
mote_pseudo_table[opcode->m_opnum].poc_handler
(mote_pseudo_table[opcode->m_opnum].poc_val);
input_line_pointer = old;
opsfound = opP - &the_ins.operands[0];
/* This ugly hack is to support the floating pt opcodes in their
- standard form. Essentially, we fake a first enty of type COP#1 */
+ standard form. Essentially, we fake a first entry of type COP#1 */
if (opcode->m_operands[0] == 'I')
{
int n;
const struct m68k_cpu *cpu;
int any = 0;
size_t space = 400;
- char *buf = xmalloc (space + 1);
+ char *buf = XNEWVEC (char, space + 1);
size_t len;
int paren = 1;
int use_pl = 0;
/* This switch is a doozy.
- Watch the first step; its a big one! */
+ Watch the first step; it's a big one! */
switch (s[0])
{
if (opP->reg == PC)
{
if (opP->disp.size == SIZE_LONG
-#ifdef OBJ_ELF
/* If the displacement needs pic
relocation it cannot be relaxed. */
- || opP->disp.pic_reloc != pic_none
-#endif
- )
+ || opP->disp.pic_reloc != pic_none)
{
addword (0x0170);
add_fix ('l', &opP->disp, 1, 2);
default:
abort ();
}
- /* IF its simple,
+ /* IF it's simple,
GET US OUT OF HERE! */
/* Must be INDEX, with an index register. Address
&& opP->reg == PC
&& isvar (&opP->disp)
&& subs (&opP->disp) == NULL
-#ifdef OBJ_ELF
/* If the displacement needs pic
relocation it cannot be relaxed. */
- && opP->disp.pic_reloc == pic_none
-#endif
- )
+ && opP->disp.pic_reloc == pic_none)
{
/* The code in md_convert_frag_1 needs to be
able to adjust nextword. Call frag_grow
&& opP->index.reg <= ZDATA7)
nextword |= (opP->index.reg - ZDATA0) << 12;
else if (opP->index.reg >= ZADDR0
- || opP->index.reg <= ZADDR7)
+ && opP->index.reg <= ZADDR7)
nextword |= (opP->index.reg - ZADDR0 + 8) << 12;
}
if (isvar (&opP->disp)
&& !subs (&opP->disp)
&& adds (&opP->disp)
-#ifdef OBJ_ELF
/* If the displacement needs pic relocation it
cannot be relaxed. */
&& opP->disp.pic_reloc == pic_none
-#endif
&& !flag_long_jumps
&& !strchr ("~%&$?", s[0]))
{
TAB (ABSTOPCREL, SZ_UNDEF));
break;
}
- /* Fall through into long. */
+ /* Fall through. */
case SIZE_LONG:
if (isvar (&opP->disp))
add_fix ('l', &opP->disp, 0, 0);
break;
case '3':
tmpreg &= 0xFF;
+ /* Fall through. */
case '8':
case 'C':
case 'j':
var_branch:
if (subs (&opP->disp) /* We can't relax it. */
-#ifdef OBJ_ELF
/* If the displacement needs pic relocation it cannot be
relaxed. */
- || opP->disp.pic_reloc != pic_none
-#endif
- || 0)
+ || opP->disp.pic_reloc != pic_none)
{
if (!have_disp)
as_warn (_("Can't use long branches on this architecture"));
}
}
- /* By the time whe get here (FINALLY) the_ins contains the complete
+ /* By the time when get here (FINALLY) the_ins contains the complete
instruction, ready to be emitted. . . */
}
switch (mode)
{
case '/': /* Special for mask loads for mac/msac insns with
- possible mask; trailing_ampersend set in bit 8. */
+ possible mask; trailing_ampersand set in bit 8. */
the_ins.opcode[0] |= (val & 0x3f);
the_ins.opcode[1] |= (((val & 0x100) >> 8) << 5);
break;
}
#endif
- symbol_table_insert (symbol_new (regname, reg_section, regnum,
- &zero_address_frag));
+ symbol_table_insert (symbol_new (regname, reg_section,
+ &zero_address_frag, regnum));
for (i = 0; regname[i]; i++)
buf[i] = TOUPPER (regname[i]);
buf[i] = '\0';
- symbol_table_insert (symbol_new (buf, reg_section, regnum,
- &zero_address_frag));
+ symbol_table_insert (symbol_new (buf, reg_section,
+ &zero_address_frag, regnum));
}
struct init_entry
current_label = NULL;
}
-#ifdef OBJ_ELF
/* Tie dwarf2 debug info to the address at the start of the insn. */
dwarf2_emit_insn (0);
-#endif
if (the_ins.nfrag == 0)
{
n = 4;
break;
default:
- as_fatal (_("Don't know how to figure width of %c in md_assemble()"),
+ as_fatal (_("Don't know how to figure out width of %c in md_assemble()"),
the_ins.reloc[m].wid);
}
{
const struct m68k_opcode *ins;
struct m68k_incant *hack, *slak;
- const char *retval = 0; /* Empty string, or error msg text. */
int i;
/* Set up hash tables with 68000 instructions.
m68k_rel32 = 0;
}
- /* First sort the opcode table into alphabetical order to seperate
+ /* First sort the opcode table into alphabetical order to separate
the order that the assembler wants to see the opcodes from the
order that the disassembler wants to see them. */
- m68k_sorted_opcodes = xmalloc (m68k_numopcodes * sizeof (* m68k_sorted_opcodes));
- if (!m68k_sorted_opcodes)
- as_fatal (_("Internal Error: Can't allocate m68k_sorted_opcodes of size %d"),
- m68k_numopcodes * ((int) sizeof (* m68k_sorted_opcodes)));
+ m68k_sorted_opcodes = XNEWVEC (const struct m68k_opcode *, m68k_numopcodes);
for (i = m68k_numopcodes; i--;)
m68k_sorted_opcodes[i] = m68k_opcodes + i;
qsort (m68k_sorted_opcodes, m68k_numopcodes,
sizeof (m68k_sorted_opcodes[0]), m68k_compare_opcode);
- op_hash = hash_new ();
+ op_hash = str_htab_create ();
obstack_begin (&robyn, 4000);
for (i = 0; i < m68k_numopcodes; i++)
{
- hack = slak = obstack_alloc (&robyn, sizeof (struct m68k_incant));
+ hack = slak = XOBNEW (&robyn, struct m68k_incant);
do
{
ins = m68k_sorted_opcodes[i];
if (i + 1 != m68k_numopcodes
&& !strcmp (ins->name, m68k_sorted_opcodes[i + 1]->name))
{
- slak->m_next = obstack_alloc (&robyn, sizeof (struct m68k_incant));
+ slak->m_next = XOBNEW (&robyn, struct m68k_incant);
i++;
}
else
}
while (slak);
- retval = hash_insert (op_hash, ins->name, (char *) hack);
- if (retval)
- as_fatal (_("Internal Error: Can't hash %s: %s"), ins->name, retval);
+ str_hash_insert (op_hash, ins->name, (char *) hack);
}
for (i = 0; i < m68k_numaliases; i++)
{
const char *name = m68k_opcode_aliases[i].primary;
const char *alias = m68k_opcode_aliases[i].alias;
- void *val = hash_find (op_hash, name);
+ void *val = (void *)str_hash_find (op_hash, name);
if (!val)
as_fatal (_("Internal Error: Can't find %s in hash table"), name);
- retval = hash_insert (op_hash, alias, val);
- if (retval)
- as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
+ str_hash_insert (op_hash, alias, val);
}
/* In MRI mode, all unsized branches are variable sized. Normally,
{
const char *name = mri_aliases[i].primary;
const char *alias = mri_aliases[i].alias;
- void *val = hash_find (op_hash, name);
+ void *val = (void *)str_hash_find (op_hash, name);
if (!val)
as_fatal (_("Internal Error: Can't find %s in hash table"), name);
- retval = hash_jam (op_hash, alias, val);
- if (retval)
- as_fatal (_("Internal Error: Can't hash %s: %s"), alias, retval);
+ str_hash_insert (op_hash, alias, val);
}
}
while (mote_pseudo_table[n].poc_name)
{
- hack = obstack_alloc (&robyn, sizeof (struct m68k_incant));
- hash_insert (op_hash,
+ hack = XOBNEW (&robyn, struct m68k_incant);
+ str_hash_insert (op_hash,
mote_pseudo_table[n].poc_name, (char *) hack);
hack->m_operands = 0;
hack->m_opnum = n;
init_regtable ();
-#ifdef OBJ_ELF
record_alignment (text_section, 2);
record_alignment (data_section, 2);
record_alignment (bss_section, 2);
-#endif
}
\f
{
struct label_line *n;
- n = (struct label_line *) xmalloc (sizeof *n);
+ n = XNEW (struct label_line);
n->next = labels;
n->label = sym;
- as_where (&n->file, &n->line);
+ n->file = as_where (&n->line);
n->text = 0;
labels = n;
current_label = n;
-#ifdef OBJ_ELF
dwarf2_emit_label (sym);
-#endif
}
/* This is called when a value that is not an instruction is emitted. */
}
}
-char *
+const char *
md_atof (int type, char *litP, int *sizeP)
{
return ieee_md_atof (type, litP, sizeP, TRUE);
if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
fixP->fx_done = 1;
-#ifdef OBJ_ELF
if (fixP->fx_addsy)
{
memset (buf, 0, fixP->fx_size);
return;
}
-#elif defined(OBJ_AOUT)
- /* PR gas/3041 Do not fix frags referencing a weak symbol. */
- if (fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy))
- {
- memset (buf, 0, fixP->fx_size);
- fixP->fx_addnumber = val; /* Remember value for emit_reloc. */
- return;
- }
-#endif
if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return md_relax_table[fragP->fr_subtype].rlx_length;
}
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
-/* the bit-field entries in the relocation_info struct plays hell
- with the byte-order problems of cross-assembly. So as a hack,
- I added this mach. dependent ri twiddler. Ugly, but it gets
- you there. -KWK */
-/* on m68k: first 4 bytes are normal unsigned long, next three bytes
- are symbolnum, most sig. byte first. Last byte is broken up with
- bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower
- nibble as nuthin. (on Sun 3 at least) */
-/* Translate the internal relocation information into target-specific
- format. */
-#ifdef comment
-void
-md_ri_to_chars (char *the_bytes, struct reloc_info_generic *ri)
-{
- /* This is easy. */
- md_number_to_chars (the_bytes, ri->r_address, 4);
- /* Now the fun stuff. */
- the_bytes[4] = (ri->r_symbolnum >> 16) & 0x0ff;
- the_bytes[5] = (ri->r_symbolnum >> 8) & 0x0ff;
- the_bytes[6] = ri->r_symbolnum & 0x0ff;
- the_bytes[7] = (((ri->r_pcrel << 7) & 0x80)
- | ((ri->r_length << 5) & 0x60)
- | ((ri->r_extern << 4) & 0x10));
-}
-
-#endif
-
-#endif /* OBJ_AOUT or OBJ_BOUT */
-
#ifndef WORKING_DOT_WORD
int md_short_jump_size = 4;
int md_long_jump_size = 6;
#endif
-/* Different values of OK tell what its OK to return. Things that
+/* Different values of OK tell what it's OK to return. Things that
aren't OK are an error (what a shock, no?)
0: Everything is OK
alignment is needed. */
int
-m68k_conditional_pseudoop (pseudo_typeS *pop)
+m68k_conditional_pseudoop (const pseudo_typeS *pop)
{
return (pop->poc_handler == s_mri_if
|| pop->poc_handler == s_mri_else);
{
struct save_opts *s;
- s = (struct save_opts *) xmalloc (sizeof (struct save_opts));
+ s = XNEW (struct save_opts);
s->abspcadd = m68k_abspcadd;
s->symbols_case_sensitive = symbols_case_sensitive;
s->keep_locals = flag_keep_locals;
{
char *n;
- n = (char *) xmalloc (20);
+ n = XNEWVEC (char, 20);
sprintf (n, "%smc%d", FAKE_LABEL_NAME, mri_control_index);
++mri_control_index;
return n;
{
struct mri_control_info *n;
- n = (struct mri_control_info *) xmalloc (sizeof (struct mri_control_info));
+ n = XNEW (struct mri_control_info);
n->type = type;
n->else_seen = 0;
n = mri_control_stack;
mri_control_stack = n->outer;
- if (n->top != NULL)
- free (n->top);
+ free (n->top);
free (n->next);
free (n->bottom);
free (n);
if (leftstart != NULL)
{
- buf = (char *) xmalloc (20
- + (leftstop - leftstart)
- + (rightstop - rightstart));
+ buf = XNEWVEC (char, (20
+ + (leftstop - leftstart)
+ + (rightstop - rightstart)));
s = buf;
*s++ = 'c';
*s++ = 'm';
free (buf);
}
- buf = (char *) xmalloc (20 + strlen (truelab));
+ buf = XNEWVEC (char, 20 + strlen (truelab));
s = buf;
*s++ = 'b';
*s++ = cc >> 8;
mri_control_stack->else_seen = 1;
- buf = (char *) xmalloc (20 + strlen (mri_control_stack->bottom));
+ buf = XNEWVEC (char, 20 + strlen (mri_control_stack->bottom));
q[0] = TOLOWER (qual);
q[1] = '\0';
sprintf (buf, "bra%s %s", q, mri_control_stack->bottom);
return;
}
- buf = (char *) xmalloc (20 + strlen (n->bottom));
+ buf = XNEWVEC (char, 20 + strlen (n->bottom));
ex[0] = TOLOWER (extent);
ex[1] = '\0';
sprintf (buf, "bra%s %s", ex, n->bottom);
return;
}
- buf = (char *) xmalloc (20 + strlen (n->next));
+ buf = XNEWVEC (char, 20 + strlen (n->next));
ex[0] = TOLOWER (extent);
ex[1] = '\0';
sprintf (buf, "bra%s %s", ex, n->next);
/* We have fully parsed the FOR operands. Now build the loop. */
n = push_mri_control (mri_for);
- buf = (char *) xmalloc (50 + (input_line_pointer - varstart));
+ buf = XNEWVEC (char, 50 + (input_line_pointer - varstart));
/* Move init,var. */
s = buf;
return;
}
- buf = (char *) xmalloc (20 + strlen (mri_control_stack->next));
+ buf = XNEWVEC (char, 20 + strlen (mri_control_stack->next));
sprintf (buf, "bra %s", mri_control_stack->next);
mri_assemble (buf);
free (buf);
Invocation line includes a switch not recognized by the base assembler.
*/
-#ifdef OBJ_ELF
const char *md_shortopts = "lSA:m:kQ:V";
-#else
-const char *md_shortopts = "lSA:m:k";
-#endif
struct option md_longopts[] = {
#define OPTION_PIC (OPTION_MD_BASE)
size_t md_longopts_size = sizeof (md_longopts);
int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
{
switch (c)
{
char *n, *t;
const char *s;
- n = (char *) xmalloc (strlen (m68k_comment_chars) + 1);
+ n = XNEWVEC (char, strlen (m68k_comment_chars) + 1);
t = n;
for (s = m68k_comment_chars; *s != '\0'; s++)
if (*s != '|')
"), default_cpu);
for (i = 0; m68k_extensions[i].name; i++)
fprintf (stream, _("\
--m[no-]%-16s enable/disable%s architecture extension\n\
+-m[no-]%-16s enable/disable %s architecture extension\n\
"), m68k_extensions[i].name,
m68k_extensions[i].alias > 0 ? " ColdFire"
: m68k_extensions[i].alias < 0 ? " m68k" : "");
valueT
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
{
-#ifdef OBJ_AOUT
- /* For a.out, force the section size to be aligned. If we don't do
- this, BFD will align it for us, but it will not write out the
- final bytes of the section. This may be a bug in BFD, but it is
- easier to fix it here since that is how the other a.out targets
- work. */
- int align;
-
- align = bfd_get_section_alignment (stdoutput, segment);
- size = ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
-#endif
-
return size;
}
return fixP->fx_where + fixP->fx_frag->fr_address - adjust;
}
-#ifdef OBJ_ELF
void
m68k_elf_final_processing (void)
{
if (size > nbytes)
{
- as_bad (_("%s relocations do not fit in %d bytes\n"),
+ as_bad (ngettext ("%s relocations do not fit in %u byte",
+ "%s relocations do not fit in %u bytes",
+ nbytes),
reloc_howto->name, nbytes);
}
else
input_line_pointer--;
demand_empty_rest_of_line ();
}
-#endif
+
+/* Parse a .gnu_attribute directive. */
+static void
+m68k_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
+{
+ int tag = obj_elf_vendor_attribute (OBJ_ATTR_GNU);
+
+ /* Check validity of defined m68k tags. */
+ if (tag == Tag_GNU_M68K_ABI_FP)
+ {
+ unsigned int val;
+
+ val = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_GNU, tag);
+
+ if (tag == Tag_GNU_M68K_ABI_FP && val > 2)
+ as_warn (_("unknown .gnu_attribute value"));
+ }
+}
int
-tc_m68k_regname_to_dw2regnum (char *regname)
+tc_m68k_regname_to_dw2regnum (const char *regname)
{
unsigned int regnum;
static const char *const regnames[] =