dir_encoding_swap
} dir_encoding;
- /* Prefer 8bit or 32bit displacement in encoding. */
+ /* Prefer 8bit, 16bit, 32bit displacement in encoding. */
enum
{
disp_encoding_default = 0,
disp_encoding_8bit,
+ disp_encoding_16bit,
disp_encoding_32bit
} disp_encoding;
#endif
;
-#if (defined (TE_I386AIX) \
- || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \
- && !defined (TE_GNU) \
- && !defined (TE_LINUX) \
- && !defined (TE_FreeBSD) \
- && !defined (TE_DragonFly) \
- && !defined (TE_NetBSD)))
+#if ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \
+ && !defined (TE_GNU) \
+ && !defined (TE_LINUX) \
+ && !defined (TE_FreeBSD) \
+ && !defined (TE_DragonFly) \
+ && !defined (TE_NetBSD))
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful. The option
--divide will remove '/' from this list. */
extern char *input_line_pointer;
/* Hash table for instruction mnemonic lookup. */
-static struct hash_control *op_hash;
+static htab_t op_hash;
/* Hash table for register lookup. */
-static struct hash_control *reg_hash;
+static htab_t reg_hash;
\f
/* Various efficient no-op patterns for aligning code labels.
Note: Don't try to assemble the instructions in the comments.
void
md_begin (void)
{
- const char *hash_err;
-
/* Support pseudo prefixes like {disp32}. */
lex_type ['{'] = LEX_BEGIN_NAME;
/* Initialize op_hash hash table. */
- op_hash = hash_new ();
+ op_hash = str_htab_create ();
{
const insn_template *optab;
/* different name --> ship out current template list;
add to hash table; & begin anew. */
core_optab->end = optab;
- hash_err = hash_insert (op_hash,
- (optab - 1)->name,
- (void *) core_optab);
- if (hash_err)
- {
- as_fatal (_("can't hash %s: %s"),
- (optab - 1)->name,
- hash_err);
- }
+ str_hash_insert (op_hash, (optab - 1)->name, (void *) core_optab);
if (optab->name == NULL)
break;
core_optab = XNEW (templates);
}
/* Initialize reg_hash hash table. */
- reg_hash = hash_new ();
+ reg_hash = str_htab_create ();
{
const reg_entry *regtab;
unsigned int regtab_size = i386_regtab_size;
for (regtab = i386_regtab; regtab_size--; regtab++)
- {
- hash_err = hash_insert (reg_hash, regtab->reg_name, (void *) regtab);
- if (hash_err)
- as_fatal (_("can't hash %s: %s"),
- regtab->reg_name,
- hash_err);
- }
+ str_hash_insert (reg_hash, regtab->reg_name, (void *) regtab);
}
/* Fill in lexical tables: mnemonic_chars, operand_chars. */
mnemonic_chars[c] = c;
operand_chars[c] = c;
}
+#ifdef SVR4_COMMENT_CHARS
+ else if (c == '\\' && strchr (i386_comment_chars, '/'))
+ operand_chars[c] = c;
+#endif
if (ISALPHA (c) || ISDIGIT (c))
identifier_chars[c] = c;
void
i386_print_statistics (FILE *file)
{
- hash_print_statistics (file, "i386 opcode", op_hash);
- hash_print_statistics (file, "i386 register", reg_hash);
+ htab_print_statistics (file, "i386 opcode", op_hash);
+ htab_print_statistics (file, "i386 register", reg_hash);
}
\f
#ifdef DEBUG386
}
/* Look up instruction (or prefix) via hash table. */
- current_templates = (const templates *) hash_find (op_hash, mnemonic);
+ current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
if (*l != END_OF_INSN
&& (!is_space_char (*l) || l[1] != END_OF_INSN)
/* Handle pseudo prefixes. */
switch (current_templates->start->base_opcode)
{
- case 0x0:
+ case Prefix_Disp8:
/* {disp8} */
i.disp_encoding = disp_encoding_8bit;
break;
- case 0x1:
+ case Prefix_Disp16:
+ /* {disp16} */
+ i.disp_encoding = disp_encoding_16bit;
+ break;
+ case Prefix_Disp32:
/* {disp32} */
i.disp_encoding = disp_encoding_32bit;
break;
- case 0x2:
+ case Prefix_Load:
/* {load} */
i.dir_encoding = dir_encoding_load;
break;
- case 0x3:
+ case Prefix_Store:
/* {store} */
i.dir_encoding = dir_encoding_store;
break;
- case 0x4:
+ case Prefix_VEX:
/* {vex} */
i.vec_encoding = vex_encoding_vex;
break;
- case 0x5:
+ case Prefix_VEX3:
/* {vex3} */
i.vec_encoding = vex_encoding_vex3;
break;
- case 0x6:
+ case Prefix_EVEX:
/* {evex} */
i.vec_encoding = vex_encoding_evex;
break;
- case 0x7:
+ case Prefix_REX:
/* {rex} */
i.rex_encoding = TRUE;
break;
- case 0x8:
+ case Prefix_NoOptimize:
/* {nooptimize} */
i.no_optimize = TRUE;
break;
goto check_suffix;
mnem_p = dot_p;
*dot_p = '\0';
- current_templates = (const templates *) hash_find (op_hash, mnemonic);
+ current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
}
if (!current_templates)
case QWORD_MNEM_SUFFIX:
i.suffix = mnem_p[-1];
mnem_p[-1] = '\0';
- current_templates = (const templates *) hash_find (op_hash,
+ current_templates = (const templates *) str_hash_find (op_hash,
mnemonic);
break;
case SHORT_MNEM_SUFFIX:
{
i.suffix = mnem_p[-1];
mnem_p[-1] = '\0';
- current_templates = (const templates *) hash_find (op_hash,
+ current_templates = (const templates *) str_hash_find (op_hash,
mnemonic);
}
break;
else
i.suffix = LONG_MNEM_SUFFIX;
mnem_p[-1] = '\0';
- current_templates = (const templates *) hash_find (op_hash,
+ current_templates = (const templates *) str_hash_find (op_hash,
mnemonic);
}
break;
i.flags[j] = i.flags[j - 1];
}
i.op[0].regs
- = (const reg_entry *) hash_find (reg_hash, "xmm0");
+ = (const reg_entry *) str_hash_find (reg_hash, "xmm0");
i.types[0] = regxmm;
i.tm.operand_types[0] = regxmm;
if (operand_type_check (i.types[op], disp) == 0)
{
/* fake (%bp) into 0(%bp) */
- i.types[op].bitfield.disp8 = 1;
+ if (i.disp_encoding == disp_encoding_16bit)
+ i.types[op].bitfield.disp16 = 1;
+ else
+ i.types[op].bitfield.disp8 = 1;
fake_zero_displacement = 1;
}
}
default: /* (%si) -> 4 or (%di) -> 5 */
i.rm.regmem = i.base_reg->reg_num - 6 + 4;
}
+ if (!fake_zero_displacement
+ && !i.disp_operands
+ && i.disp_encoding)
+ {
+ fake_zero_displacement = 1;
+ if (i.disp_encoding == disp_encoding_8bit)
+ i.types[op].bitfield.disp8 = 1;
+ else
+ i.types[op].bitfield.disp16 = 1;
+ }
i.rm.mode = mode_from_disp_size (i.types[op]);
}
else /* i.base_reg and 32/64 bit mode */
if (i.base_reg->reg_num == 5 && i.disp_operands == 0)
{
fake_zero_displacement = 1;
- i.types[op].bitfield.disp8 = 1;
+ if (i.disp_encoding == disp_encoding_32bit)
+ i.types[op].bitfield.disp32 = 1;
+ else
+ i.types[op].bitfield.disp8 = 1;
}
i.sib.scale = i.log2_scale_factor;
if (i.index_reg == 0)
&& current_templates->end[-1].operand_types[1]
.bitfield.baseindex))
op = 1;
- expected_reg = hash_find (reg_hash, di_si[addr_mode][op == es_op]);
+ expected_reg = (const reg_entry *)str_hash_find (reg_hash, di_si[addr_mode][op == es_op]);
}
else
- expected_reg = hash_find (reg_hash, bx[addr_mode]);
+ expected_reg = (const reg_entry *)str_hash_find (reg_hash, bx[addr_mode]);
if (i.base_reg != expected_reg
|| i.index_reg
if (addr_mode != CODE_16BIT)
{
/* 32-bit/64-bit checks. */
+ if (i.disp_encoding == disp_encoding_16bit)
+ {
+ bad_disp:
+ as_bad (_("invalid `%s' prefix"),
+ addr_mode == CODE_16BIT ? "{disp32}" : "{disp16}");
+ return 0;
+ }
+
if ((i.base_reg
&& ((addr_mode == CODE_64BIT
? !i.base_reg->reg_type.bitfield.qword
else
{
/* 16-bit checks. */
+ if (i.disp_encoding == disp_encoding_32bit)
+ goto bad_disp;
+
if ((i.base_reg
&& (!i.base_reg->reg_type.bitfield.word
|| !i.base_reg->reg_type.bitfield.baseindex))
*end_op = s;
- r = (const reg_entry *) hash_find (reg_hash, reg_name_given);
+ r = (const reg_entry *) str_hash_find (reg_hash, reg_name_given);
/* Handle floating point regs, allowing spaces in the (i) part. */
if (r == i386_regtab /* %st is first entry of table */)
if (*s == ')')
{
*end_op = s + 1;
- r = (const reg_entry *) hash_find (reg_hash, "st(0)");
+ r = (const reg_entry *) str_hash_find (reg_hash, "st(0)");
know (r);
return r + fpr;
}
if (symbol_find (name))
as_bad (_("GOT already in symbol table"));
GOT_symbol = symbol_new (name, undefined_section,
- (valueT) 0, &zero_address_frag);
+ &zero_address_frag, 0);
};
return GOT_symbol;
}