#ifdef TE_PE
static void pe_directive_secrel PARAMS ((int));
#endif
+static void signed_cons PARAMS ((int));
static char *output_invalid PARAMS ((int c));
static int i386_operand PARAMS ((char *operand_string));
static int i386_intel_operand PARAMS ((char *operand_string, int got_a_float));
#ifndef I386COFF
static void s_bss PARAMS ((int));
#endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+static void handle_large_common (int small ATTRIBUTE_UNUSED);
+#endif
static const char *default_arch = DEFAULT_ARCH;
#if (defined (TE_I386AIX) \
|| ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \
+ && !defined (TE_GNU) \
&& !defined (TE_LINUX) \
&& !defined (TE_NETWARE) \
&& !defined (TE_FreeBSD) \
&& !defined (TE_NetBSD)))
/* This array holds the chars that always start a comment. If the
- pre-processor is disabled, these aren't very useful. */
-const char comment_chars[] = "#/";
+ pre-processor is disabled, these aren't very useful. The option
+ --divide will remove '/' from this list. */
+const char *i386_comment_chars = "#/";
+#define SVR4_COMMENT_CHARS 1
#define PREFIX_SEPARATOR '\\'
+#else
+const char *i386_comment_chars = "#";
+#define PREFIX_SEPARATOR '/'
+#endif
+
/* This array holds the chars that only start a comment at the beginning of
a line. If the line seems to have the form '# 123 filename'
.line and .file directives will appear in the pre-processed output.
#NO_APP at the beginning of its output.
Also note that comments started like this one will always work if
'/' isn't otherwise defined. */
-const char line_comment_chars[] = "#";
-
-#else
-/* Putting '/' here makes it impossible to use the divide operator.
- However, we need it for compatibility with SVR4 systems. */
-const char comment_chars[] = "#";
-#define PREFIX_SEPARATOR '/'
-
-const char line_comment_chars[] = "/#";
-#endif
+const char line_comment_chars[] = "#/";
const char line_separator_chars[] = ";";
#define NUM_FLAG_CODE ((int) CODE_64BIT + 1)
static enum flag_code flag_code;
+static unsigned int object_64bit;
static int use_rela_relocations = 0;
/* The names used to print error messages. */
{"dfloat", float_cons, 'd'},
{"tfloat", float_cons, 'x'},
{"value", cons, 2},
+ {"slong", signed_cons, 4},
{"noopt", s_ignore, 0},
{"optim", s_ignore, 0},
{"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT},
{"code64", set_code_flag, CODE_64BIT},
{"intel_syntax", set_intel_syntax, 1},
{"att_syntax", set_intel_syntax, 0},
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ {"largecomm", handle_large_common, 0},
+#else
{"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
{"loc", dwarf2_directive_loc, 0},
+ {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0},
+#endif
#ifdef TE_PE
{"secrel32", pe_directive_secrel, 0},
#endif
default:
break;
}
+
+ /* Sign-checking 4-byte relocations in 16-/32-bit code is pointless. */
+ if (size == 4 && flag_code != CODE_64BIT)
+ sign = -1;
+
reloc = bfd_reloc_type_lookup (stdoutput, other);
if (!reloc)
as_bad (_("unknown relocation (%u)"), other);
/* Symbols and expressions. */
default:
- /* Convert symbolic operand to proper sizes for matching. */
- switch (guess_suffix)
- {
- case QWORD_MNEM_SUFFIX:
- i.types[op] &= Imm64 | Imm32S;
- break;
- case LONG_MNEM_SUFFIX:
- i.types[op] &= Imm32;
- break;
- case WORD_MNEM_SUFFIX:
- i.types[op] &= Imm16;
- break;
- case BYTE_MNEM_SUFFIX:
- i.types[op] &= Imm8 | Imm8S;
- break;
- }
+ /* Convert symbolic operand to proper sizes for matching, but don't
+ prevent matching a set of insns that only supports sizes other
+ than those matching the insn suffix. */
+ {
+ unsigned int mask, allowed = 0;
+ const template *t;
+
+ for (t = current_templates->start; t < current_templates->end; ++t)
+ allowed |= t->operand_types[op];
+ switch (guess_suffix)
+ {
+ case QWORD_MNEM_SUFFIX:
+ mask = Imm64 | Imm32S;
+ break;
+ case LONG_MNEM_SUFFIX:
+ mask = Imm32;
+ break;
+ case WORD_MNEM_SUFFIX:
+ mask = Imm16;
+ break;
+ case BYTE_MNEM_SUFFIX:
+ mask = Imm8;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
+ if (mask & allowed)
+ i.types[op] &= mask;
+ }
break;
}
}
add += p - frag_now->fr_literal;
}
- if (flag_code != CODE_64BIT)
+ if (!object_64bit)
reloc_type = BFD_RELOC_386_GOTPC;
else
reloc_type = BFD_RELOC_X86_64_GOTPC32;
add += p - frag_now->fr_literal;
}
- if (flag_code != CODE_64BIT)
+ if (!object_64bit)
reloc_type = BFD_RELOC_386_GOTPC;
else
reloc_type = BFD_RELOC_X86_64_GOTPC32;
}
}
\f
+/* x86_cons_fix_new is called via the expression parsing code when a
+ reloc is needed. We use this hook to get the correct .got reloc. */
+static enum bfd_reloc_code_real got_reloc = NO_RELOC;
+static int cons_sign = -1;
+
+void
+x86_cons_fix_new (fragS *frag,
+ unsigned int off,
+ unsigned int len,
+ expressionS *exp)
+{
+ enum bfd_reloc_code_real r = reloc (len, 0, cons_sign, got_reloc);
+
+ got_reloc = NO_RELOC;
+
+#ifdef TE_PE
+ if (exp->X_op == O_secrel)
+ {
+ exp->X_op = O_symbol;
+ r = BFD_RELOC_32_SECREL;
+ }
+#endif
+
+ fix_new_exp (frag, off, len, exp, 0, r);
+}
+
#if (!defined (OBJ_ELF) && !defined (OBJ_MAYBE_ELF)) || defined (LEX_AT)
# define lex_got(reloc, adjust, types) NULL
#else
int *adjust,
unsigned int *types)
{
- static const char * const mode_name[NUM_FLAG_CODE] = { "32", "16", "64" };
static const struct {
const char *str;
- const enum bfd_reloc_code_real rel[NUM_FLAG_CODE];
+ const enum bfd_reloc_code_real rel[2];
const unsigned int types64;
} gotrel[] = {
- { "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 }, Imm32|Imm32S|Disp32 },
- { "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 },
- { "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 },
- { "TLSGD", { BFD_RELOC_386_TLS_GD, 0, BFD_RELOC_X86_64_TLSGD }, Imm32|Imm32S|Disp32 },
- { "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0, 0 }, 0 },
- { "TLSLD", { 0, 0, BFD_RELOC_X86_64_TLSLD }, Imm32|Imm32S|Disp32 },
- { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, 0, BFD_RELOC_X86_64_GOTTPOFF }, Imm32|Imm32S|Disp32 },
- { "TPOFF", { BFD_RELOC_386_TLS_LE_32, 0, BFD_RELOC_X86_64_TPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
- { "NTPOFF", { BFD_RELOC_386_TLS_LE, 0, 0 }, 0 },
- { "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, 0, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
- { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0, 0 }, 0 },
- { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0, 0 }, 0 },
- { "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32 }
+ { "PLT", { BFD_RELOC_386_PLT32, BFD_RELOC_X86_64_PLT32 }, Imm32|Imm32S|Disp32 },
+ { "GOTOFF", { BFD_RELOC_386_GOTOFF, BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 },
+ { "GOTPCREL", { 0, BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 },
+ { "TLSGD", { BFD_RELOC_386_TLS_GD, BFD_RELOC_X86_64_TLSGD }, Imm32|Imm32S|Disp32 },
+ { "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0 }, 0 },
+ { "TLSLD", { 0, BFD_RELOC_X86_64_TLSLD }, Imm32|Imm32S|Disp32 },
+ { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, BFD_RELOC_X86_64_GOTTPOFF }, Imm32|Imm32S|Disp32 },
+ { "TPOFF", { BFD_RELOC_386_TLS_LE_32, BFD_RELOC_X86_64_TPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
+ { "NTPOFF", { BFD_RELOC_386_TLS_LE, 0 }, 0 },
+ { "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
+ { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0 }, 0 },
+ { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0 }, 0 },
+ { "GOT", { BFD_RELOC_386_GOT32, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32 }
};
char *cp;
unsigned int j;
len = strlen (gotrel[j].str);
if (strncasecmp (cp + 1, gotrel[j].str, len) == 0)
{
- if (gotrel[j].rel[(unsigned int) flag_code] != 0)
+ if (gotrel[j].rel[object_64bit] != 0)
{
int first, second;
char *tmpbuf, *past_reloc;
- *reloc = gotrel[j].rel[(unsigned int) flag_code];
+ *reloc = gotrel[j].rel[object_64bit];
if (adjust)
*adjust = len;
return tmpbuf;
}
- as_bad (_("@%s reloc is not supported in %s bit mode"),
- gotrel[j].str, mode_name[(unsigned int) flag_code]);
+ as_bad (_("@%s reloc is not supported with %d-bit output format"),
+ gotrel[j].str, 1 << (5 + object_64bit));
return NULL;
}
}
return NULL;
}
-/* x86_cons_fix_new is called via the expression parsing code when a
- reloc is needed. We use this hook to get the correct .got reloc. */
-static enum bfd_reloc_code_real got_reloc = NO_RELOC;
-
-void
-x86_cons_fix_new (frag, off, len, exp)
- fragS *frag;
- unsigned int off;
- unsigned int len;
- expressionS *exp;
-{
- enum bfd_reloc_code_real r = reloc (len, 0, -1, got_reloc);
- got_reloc = NO_RELOC;
- fix_new_exp (frag, off, len, exp, 0, r);
-}
-
void
x86_cons (exp, size)
expressionS *exp;
int size;
{
- if (size == 4 || (flag_code == CODE_64BIT && size == 8))
+ if (size == 4 || (object_64bit && size == 8))
{
/* Handle @GOTOFF and the like in an expression. */
char *save;
}
#endif
-#ifdef TE_PE
-
-void
-x86_pe_cons_fix_new (frag, off, len, exp)
- fragS *frag;
- unsigned int off;
- unsigned int len;
- expressionS *exp;
+static void signed_cons (int size)
{
- enum bfd_reloc_code_real r = reloc (len, 0, -1, NO_RELOC);
-
- if (exp->X_op == O_secrel)
- {
- exp->X_op = O_symbol;
- r = BFD_RELOC_32_SECREL;
- }
-
- fix_new_exp (frag, off, len, exp, 0, r);
+ if (flag_code == CODE_64BIT)
+ cons_sign = 1;
+ cons (size);
+ cons_sign = -1;
}
+#ifdef TE_PE
static void
pe_directive_secrel (dummy)
int dummy ATTRIBUTE_UNUSED;
input_line_pointer--;
demand_empty_rest_of_line ();
}
-
#endif
static int i386_immediate PARAMS ((char *));
segT exp_seg = 0;
char *save_input_line_pointer;
char *gotfree_input_line;
- int bigdisp = Disp32;
+ int bigdisp, override;
unsigned int types = Disp;
+ if ((i.types[this_operand] & JumpAbsolute)
+ || !(current_templates->start->opcode_modifier & (Jump | JumpDword)))
+ {
+ bigdisp = Disp32;
+ override = (i.prefix[ADDR_PREFIX] != 0);
+ }
+ else
+ {
+ /* For PC-relative branches, the width of the displacement
+ is dependent upon data size, not address size. */
+ bigdisp = 0;
+ override = (i.prefix[DATA_PREFIX] != 0);
+ }
if (flag_code == CODE_64BIT)
{
- if (i.prefix[ADDR_PREFIX] == 0)
+ if (!bigdisp)
+ bigdisp = (override || i.suffix == WORD_MNEM_SUFFIX)
+ ? Disp16
+ : Disp32S | Disp32;
+ else if (!override)
bigdisp = Disp64 | Disp32S | Disp32;
}
- else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
- bigdisp = Disp16;
+ else
+ {
+ if (!bigdisp)
+ {
+ if (!override)
+ override = (i.suffix == (flag_code != CODE_16BIT
+ ? WORD_MNEM_SUFFIX
+ : LONG_MNEM_SUFFIX));
+ bigdisp = Disp32;
+ }
+ if ((flag_code == CODE_16BIT) ^ override)
+ bigdisp = Disp16;
+ }
i.types[this_operand] |= bigdisp;
exp = &disp_expressions[i.disp_operands];
}
/* Check if operand is a register. */
- if ((*op_string == REGISTER_PREFIX || allow_naked_reg)
- && (r = parse_register (op_string, &end_op)) != NULL)
+ if ((r = parse_register (op_string, &end_op)) != NULL)
{
/* Check for a segment override by searching for ':' after a
segment register. */
++base_string;
if (*base_string == ','
- || ((*base_string == REGISTER_PREFIX || allow_naked_reg)
- && (i.base_reg = parse_register (base_string, &end_op)) != NULL))
+ || ((i.base_reg = parse_register (base_string, &end_op)) != NULL))
{
displacement_string_end = temp_string;
if (is_space_char (*base_string))
++base_string;
- if ((*base_string == REGISTER_PREFIX || allow_naked_reg)
- && (i.index_reg = parse_register (base_string, &end_op)) != NULL)
+ if ((i.index_reg = parse_register (base_string, &end_op)) != NULL)
{
base_string = end_op;
if (is_space_char (*base_string))
/* Size of dword displacement jmp. */
int md_long_jump_size = 5;
-/* Size of relocation record. */
-const int md_reloc_size = 8;
-
void
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
/* For some reason, the PE format does not store a
section address offset for a PC relative symbol. */
if (S_GET_SEGMENT (fixP->fx_addsy) != seg
-#if defined(BFD_ASSEMBLER) || defined(S_IS_WEAK)
- || S_IS_WEAK (fixP->fx_addsy)
-#endif
- )
+ || S_IS_WEAK (fixP->fx_addsy))
value += md_pcrel_from (fixP);
#endif
}
/* REG_STRING starts *before* REGISTER_PREFIX. */
static const reg_entry *
-parse_register (reg_string, end_op)
- char *reg_string;
- char **end_op;
+parse_real_register (char *reg_string, char **end_op)
{
char *s = reg_string;
char *p;
return r;
}
+
+/* REG_STRING starts *before* REGISTER_PREFIX. */
+
+static const reg_entry *
+parse_register (char *reg_string, char **end_op)
+{
+ const reg_entry *r;
+
+ if (*reg_string == REGISTER_PREFIX || allow_naked_reg)
+ r = parse_real_register (reg_string, end_op);
+ else
+ r = NULL;
+ if (!r)
+ {
+ char *save = input_line_pointer;
+ char c;
+ symbolS *symbolP;
+
+ input_line_pointer = reg_string;
+ c = get_symbol_end ();
+ symbolP = symbol_find (reg_string);
+ if (symbolP && S_GET_SEGMENT (symbolP) == reg_section)
+ {
+ const expressionS *e = symbol_get_value_expression (symbolP);
+
+ know (e->X_op == O_register);
+ know (e->X_add_number >= 0 && (valueT) e->X_add_number < ARRAY_SIZE (i386_regtab));
+ r = i386_regtab + e->X_add_number;
+ *end_op = input_line_pointer;
+ }
+ *input_line_pointer = c;
+ input_line_pointer = save;
+ }
+ return r;
+}
+
+int
+i386_parse_name (char *name, expressionS *e, char *nextcharP)
+{
+ const reg_entry *r;
+ char *end = input_line_pointer;
+
+ *end = *nextcharP;
+ r = parse_register (name, &input_line_pointer);
+ if (r && end <= input_line_pointer)
+ {
+ *nextcharP = *input_line_pointer;
+ *input_line_pointer = 0;
+ e->X_op = O_register;
+ e->X_add_number = r - i386_regtab;
+ return 1;
+ }
+ input_line_pointer = end;
+ *end = 0;
+ return 0;
+}
+
+void
+md_operand (expressionS *e)
+{
+ if (*input_line_pointer == REGISTER_PREFIX)
+ {
+ char *end;
+ const reg_entry *r = parse_real_register (input_line_pointer, &end);
+
+ if (r)
+ {
+ e->X_op = O_register;
+ e->X_add_number = r - i386_regtab;
+ input_line_pointer = end;
+ }
+ }
+}
+
\f
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
const char *md_shortopts = "kVQ:sqn";
const char *md_shortopts = "qn";
#endif
-struct option md_longopts[] = {
#define OPTION_32 (OPTION_MD_BASE + 0)
+#define OPTION_64 (OPTION_MD_BASE + 1)
+#define OPTION_DIVIDE (OPTION_MD_BASE + 2)
+
+struct option md_longopts[] = {
{"32", no_argument, NULL, OPTION_32},
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
-#define OPTION_64 (OPTION_MD_BASE + 1)
{"64", no_argument, NULL, OPTION_64},
#endif
+ {"divide", no_argument, NULL, OPTION_DIVIDE},
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
default_arch = "i386";
break;
+ case OPTION_DIVIDE:
+#ifdef SVR4_COMMENT_CHARS
+ {
+ char *n, *t;
+ const char *s;
+
+ n = (char *) xmalloc (strlen (i386_comment_chars) + 1);
+ t = n;
+ for (s = i386_comment_chars; *s != '\0'; s++)
+ if (*s != '/')
+ *t++ = *s;
+ *t = '\0';
+ i386_comment_chars = n;
+ }
+#endif
+ break;
+
default:
return 0;
}
fprintf (stream, _("\
-Q ignored\n\
-V print assembler version number\n\
- -k ignored\n\
+ -k ignored\n"));
+#endif
+ fprintf (stream, _("\
-n Do not optimize code alignment\n\
- -q quieten some warnings\n\
+ -q quieten some warnings\n"));
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ fprintf (stream, _("\
-s ignored\n"));
+#endif
+#ifdef SVR4_COMMENT_CHARS
+ fprintf (stream, _("\
+ --divide do not treat `/' as a comment character\n"));
#else
fprintf (stream, _("\
- -n Do not optimize code alignment\n\
- -q quieten some warnings\n"));
+ --divide ignored\n"));
#endif
}
case bfd_target_elf_flavour:
{
if (flag_code == CODE_64BIT)
- use_rela_relocations = 1;
+ {
+ object_64bit = 1;
+ use_rela_relocations = 1;
+ }
return flag_code == CODE_64BIT ? "elf64-x86-64" : ELF_TARGET_FORMAT;
}
#endif
{
if (fixp->fx_r_type == BFD_RELOC_32_PCREL)
{
- if (flag_code != CODE_64BIT)
+ if (!object_64bit)
abort ();
fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
}
else
{
- if (flag_code != CODE_64BIT)
+ if (!object_64bit)
fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
else
fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
break;
}
- if ((code == BFD_RELOC_32 || code == BFD_RELOC_32_PCREL)
+ if ((code == BFD_RELOC_32
+ || code == BFD_RELOC_32_PCREL
+ || code == BFD_RELOC_X86_64_32S)
&& GOT_symbol
&& fixp->fx_addsy == GOT_symbol)
{
- if (flag_code != CODE_64BIT)
+ if (!object_64bit)
code = BFD_RELOC_386_GOTPC;
else
code = BFD_RELOC_X86_64_GOTPC32;
suffix = WORD_MNEM_SUFFIX;
else if (flag_code == CODE_16BIT
&& (current_templates->start->opcode_modifier
- & (Jump|JumpDword|JumpInterSegment)))
+ & (Jump | JumpDword)))
suffix = LONG_DOUBLE_MNEM_SUFFIX;
else if (intel_parser.got_a_float == 1) /* "f..." */
suffix = SHORT_MNEM_SUFFIX;
return 0;
}
+ /* Operands for jump/call using 'ptr' notation denote absolute
+ addresses. */
+ if (current_templates->start->opcode_modifier & (Jump | JumpDword))
+ i.types[this_operand] |= JumpAbsolute;
+
if (current_templates->start->base_opcode == 0x8d /* lea */)
;
else if (!i.suffix)
if (!intel_parser.in_offset)
{
++intel_parser.in_bracket;
+
+ /* Operands for jump/call inside brackets denote absolute addresses. */
+ if (current_templates->start->opcode_modifier & (Jump | JumpDword))
+ i.types[this_operand] |= JumpAbsolute;
+
/* Unfortunately gas always diverged from MASM in a respect that can't
be easily fixed without risking to break code sequences likely to be
encountered (the testsuite even check for this): MASM doesn't consider
/* e11 [ expr ] */
case '[':
- /* Operands for jump/call inside brackets denote absolute addresses.
- XXX This shouldn't be needed anymore (or if it should rather live
- in intel_bracket_expr). */
- if (current_templates->start->opcode_modifier
- & (Jump|JumpDword|JumpByte|JumpInterSegment))
- i.types[this_operand] |= JumpAbsolute;
-
return intel_bracket_expr ();
/* e11 $
/* No scaling. If this is a memory operand, the register is either a
base register (first occurrence) or an index register (second
occurrence). */
- else if (intel_parser.in_bracket && !(reg->reg_type & (SReg2 | SReg3)))
+ else if (intel_parser.in_bracket)
{
if (!i.base_reg)
i.types[this_operand] |= BaseIndex;
}
- /* Offset modifier. Add the register to the displacement string to be
- parsed as an immediate expression after we're done. */
- else if (intel_parser.in_offset)
- {
- as_warn (_("Using register names in OFFSET expressions is deprecated"));
- strcat (intel_parser.disp, reg->reg_name);
- }
-
- /* It's neither base nor index nor offset. */
- else if (!intel_parser.is_mem)
+ /* It's neither base nor index. */
+ else if (!intel_parser.in_offset && !intel_parser.is_mem)
{
i.types[this_operand] |= reg->reg_type & ~BaseIndex;
i.op[this_operand].regs = reg;
new_token.code = T_ID;
}
- else if ((*intel_parser.op_string == REGISTER_PREFIX || allow_naked_reg)
- && ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL))
+ else if ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL)
{
+ size_t len = end_op - intel_parser.op_string;
+
new_token.code = T_REG;
new_token.reg = reg;
- if (*intel_parser.op_string == REGISTER_PREFIX)
- {
- new_token.str[0] = REGISTER_PREFIX;
- new_token.str[1] = '\0';
- }
-
- strcat (new_token.str, reg->reg_name);
+ memcpy (new_token.str, intel_parser.op_string, len);
+ new_token.str[len] = '\0';
}
else if (is_identifier_char (*intel_parser.op_string))
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7"
+ "mm4", "mm5", "mm6", "mm7",
+ "fcw", "fsw", "mxcsr",
+ "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
+ "tr", "ldtr"
};
static const char *const regnames_64[] =
{
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7"
+ "mm4", "mm5", "mm6", "mm7",
+ "rflags",
+ "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
+ "fs.base", "gs.base", NULL, NULL,
+ "tr", "ldtr",
+ "mxcsr", "fcw", "fsw"
};
const char *const *regnames;
emit_expr (&expr, size);
}
#endif
+
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+/* For ELF on x86-64, add support for SHF_X86_64_LARGE. */
+
+int
+x86_64_section_letter (int letter, char **ptr_msg)
+{
+ if (flag_code == CODE_64BIT)
+ {
+ if (letter == 'l')
+ return SHF_X86_64_LARGE;
+
+ *ptr_msg = _("Bad .section directive: want a,l,w,x,M,S,G,T in string");
+ }
+ else
+ *ptr_msg = _("Bad .section directive: want a,w,x,M,S,G,T in string");
+ return -1;
+}
+
+int
+x86_64_section_word (char *str, size_t len)
+{
+ if (len == 5 && flag_code == CODE_64BIT && strncmp (str, "large", 5) == 0)
+ return SHF_X86_64_LARGE;
+
+ return -1;
+}
+
+static void
+handle_large_common (int small ATTRIBUTE_UNUSED)
+{
+ if (flag_code != CODE_64BIT)
+ {
+ s_comm_internal (0, elf_common_parse);
+ as_warn (_(".largecomm supported only in 64bit mode, producing .comm"));
+ }
+ else
+ {
+ static segT lbss_section;
+ asection *saved_com_section_ptr = elf_com_section_ptr;
+ asection *saved_bss_section = bss_section;
+
+ if (lbss_section == NULL)
+ {
+ flagword applicable;
+ segT seg = now_seg;
+ subsegT subseg = now_subseg;
+
+ /* The .lbss section is for local .largecomm symbols. */
+ lbss_section = subseg_new (".lbss", 0);
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, lbss_section,
+ applicable & SEC_ALLOC);
+ seg_info (lbss_section)->bss = 1;
+
+ subseg_set (seg, subseg);
+ }
+
+ elf_com_section_ptr = &_bfd_elf_large_com_section;
+ bss_section = lbss_section;
+
+ s_comm_internal (0, elf_common_parse);
+
+ elf_com_section_ptr = saved_com_section_ptr;
+ bss_section = saved_bss_section;
+ }
+}
+#endif /* OBJ_ELF || OBJ_MAYBE_ELF */