diff options
author | obrien <obrien@FreeBSD.org> | 2002-01-27 12:00:11 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2002-01-27 12:00:11 +0000 |
commit | fc89183cdc6be5afa8deb7250fd15a20832ab528 (patch) | |
tree | 5c493199a70976c54e1b9c6a7804a3de85b43e84 /contrib/binutils/gas/config/tc-i386.c | |
parent | 94820fd8060f6f43089d1a3ddb8a482402e7e494 (diff) | |
download | FreeBSD-src-fc89183cdc6be5afa8deb7250fd15a20832ab528.zip FreeBSD-src-fc89183cdc6be5afa8deb7250fd15a20832ab528.tar.gz |
Enlist the FreeBSD-CURRENT users as testers of what is to become Binutils
version 2.12.0. These bits are taken from the FSF anoncvs repo on
27-January-2002 03:41 PST.
Diffstat (limited to 'contrib/binutils/gas/config/tc-i386.c')
-rw-r--r-- | contrib/binutils/gas/config/tc-i386.c | 227 |
1 files changed, 156 insertions, 71 deletions
diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c index bbd4fc4..c81f870 100644 --- a/contrib/binutils/gas/config/tc-i386.c +++ b/contrib/binutils/gas/config/tc-i386.c @@ -26,9 +26,8 @@ Bugs & suggestions are completely welcome. This is free software. Please help us make it better. */ -#include <ctype.h> - #include "as.h" +#include "safe-ctype.h" #include "subsegs.h" #include "dwarf2dbg.h" #include "opcode/i386.h" @@ -78,7 +77,7 @@ static bfd_reloc_code_real_type reloc #ifndef DEFAULT_ARCH #define DEFAULT_ARCH "i386" #endif -static char *default_arch = DEFAULT_ARCH; +static const char *default_arch = DEFAULT_ARCH; /* 'md_assemble ()' gathers together information and puts it into a i386_insn. */ @@ -157,7 +156,7 @@ const char extra_symbol_chars[] = "*%-("; /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. */ -#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD)) +#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD)) /* Putting '/' here makes it impossible to use the divide operator. However, we need it for compatibility with SVR4 systems. */ const char comment_chars[] = "#/"; @@ -175,7 +174,7 @@ const char comment_chars[] = "#"; #NO_APP at the beginning of its output. Also note that comments started like this one will always work if '/' isn't otherwise defined. */ -#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD)) +#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD)) const char line_comment_chars[] = ""; #else const char line_comment_chars[] = "/"; @@ -540,8 +539,7 @@ static int smallest_imm_type (num) offsetT num; { - if (cpu_arch_flags != (Cpu086 | Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64) - && !(cpu_arch_flags & (CpuUnknown))) + if (cpu_arch_flags != (Cpu086 | Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64)) { /* This code is disabled on the 486 because all the Imm1 forms in the opcode table are slower on the i486. They're the @@ -891,27 +889,27 @@ md_begin () for (c = 0; c < 256; c++) { - if (isdigit (c)) + if (ISDIGIT (c)) { digit_chars[c] = c; mnemonic_chars[c] = c; register_chars[c] = c; operand_chars[c] = c; } - else if (islower (c)) + else if (ISLOWER (c)) { mnemonic_chars[c] = c; register_chars[c] = c; operand_chars[c] = c; } - else if (isupper (c)) + else if (ISUPPER (c)) { - mnemonic_chars[c] = tolower (c); + mnemonic_chars[c] = TOLOWER (c); register_chars[c] = mnemonic_chars[c]; operand_chars[c] = c; } - if (isalpha (c) || isdigit (c)) + if (ISALPHA (c) || ISDIGIT (c)) identifier_chars[c] = c; else if (c >= 128) { @@ -1269,7 +1267,8 @@ md_assemble (line) } if (!is_space_char (*l) && *l != END_OF_INSN - && *l != PREFIX_SEPARATOR) + && *l != PREFIX_SEPARATOR + && *l != ',') { as_bad (_("invalid character %s in mnemonic"), output_invalid (*l)); @@ -1360,20 +1359,49 @@ md_assemble (line) } } - /* Check if instruction is supported on specified architecture. */ - if (cpu_arch_flags != 0) + if (current_templates->start->opcode_modifier & (Jump | JumpByte)) { - if ((current_templates->start->cpu_flags & ~(Cpu64 | CpuNo64)) - & ~(cpu_arch_flags & ~(Cpu64 | CpuNo64))) - { - as_warn (_("`%s' is not supported on `%s'"), - current_templates->start->name, cpu_arch_name); - } - else if ((Cpu386 & ~cpu_arch_flags) && (flag_code != CODE_16BIT)) + /* Check for a branch hint. We allow ",pt" and ",pn" for + predict taken and predict not taken respectively. + I'm not sure that branch hints actually do anything on loop + and jcxz insns (JumpByte) for current Pentium4 chips. They + may work in the future and it doesn't hurt to accept them + now. */ + if (l[0] == ',' && l[1] == 'p') { - as_warn (_("use .code16 to ensure correct addressing mode")); + if (l[2] == 't') + { + if (! add_prefix (DS_PREFIX_OPCODE)) + return; + l += 3; + } + else if (l[2] == 'n') + { + if (! add_prefix (CS_PREFIX_OPCODE)) + return; + l += 3; + } } } + /* Any other comma loses. */ + if (*l == ',') + { + as_bad (_("invalid character %s in mnemonic"), + output_invalid (*l)); + return; + } + + /* Check if instruction is supported on specified architecture. */ + if ((current_templates->start->cpu_flags & ~(Cpu64 | CpuNo64)) + & ~(cpu_arch_flags & ~(Cpu64 | CpuNo64))) + { + as_warn (_("`%s' is not supported on `%s'"), + current_templates->start->name, cpu_arch_name); + } + else if ((Cpu386 & ~cpu_arch_flags) && (flag_code != CODE_16BIT)) + { + as_warn (_("use .code16 to ensure correct addressing mode")); + } /* Check for rep/repne without a string instruction. */ if (expecting_string_instruction @@ -2695,6 +2723,9 @@ md_assemble (line) { int code16; int prefix; + relax_substateT subtype; + symbolS *sym; + offsetT off; code16 = 0; if (flag_code == CODE_16BIT) @@ -2739,19 +2770,29 @@ md_assemble (line) if (i.prefix[REX_PREFIX]) *p++ = i.prefix[REX_PREFIX]; *p = i.tm.base_opcode; - /* 1 possible extra opcode + displacement go in var part. + + if ((unsigned char) *p == JUMP_PC_RELATIVE) + subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL); + else if ((cpu_arch_flags & Cpu386) != 0) + subtype = ENCODE_RELAX_STATE (COND_JUMP, SMALL); + else + subtype = ENCODE_RELAX_STATE (COND_JUMP86, SMALL); + subtype |= code16; + + sym = i.op[0].disps->X_add_symbol; + off = i.op[0].disps->X_add_number; + + if (i.op[0].disps->X_op != O_constant + && i.op[0].disps->X_op != O_symbol) + { + /* Handle complex expressions. */ + sym = make_expr_symbol (i.op[0].disps); + off = 0; + } + + /* 1 possible extra opcode + 4 byte displacement go in var part. Pass reloc in fr_var. */ - frag_var (rs_machine_dependent, - 1 + 4, - i.reloc[0], - ((unsigned char) *p == JUMP_PC_RELATIVE - ? ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL) | code16 - : ((cpu_arch_flags & Cpu386) != 0 - ? ENCODE_RELAX_STATE (COND_JUMP, SMALL) | code16 - : ENCODE_RELAX_STATE (COND_JUMP86, SMALL) | code16)), - i.op[0].disps->X_add_symbol, - i.op[0].disps->X_add_number, - p); + frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); } else if (i.tm.opcode_modifier & (JumpByte | JumpDword)) { @@ -3135,27 +3176,41 @@ lex_got (reloc, adjust) int len; len = strlen (gotrel[j].str); - if (strncmp (cp + 1, gotrel[j].str, len) == 0) + if (strncasecmp (cp + 1, gotrel[j].str, len) == 0) { if (gotrel[j].rel[(unsigned int) flag_code] != 0) { - int first; - char *tmpbuf; + int first, second; + char *tmpbuf, *past_reloc; *reloc = gotrel[j].rel[(unsigned int) flag_code]; + if (adjust) + *adjust = len; if (GOT_symbol == NULL) GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); /* Replace the relocation token with ' ', so that errors like foo@GOTOFF1 will be detected. */ + + /* The length of the first part of our input line. */ first = cp - input_line_pointer; - tmpbuf = xmalloc (strlen (input_line_pointer)); + + /* The second part goes from after the reloc token until + (and including) an end_of_line char. Don't use strlen + here as the end_of_line char may not be a NUL. */ + past_reloc = cp + 1 + len; + for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; ) + ; + second = cp - past_reloc; + + /* Allocate and copy string. The trailing NUL shouldn't + be necessary, but be safe. */ + tmpbuf = xmalloc (first + second + 2); memcpy (tmpbuf, input_line_pointer, first); tmpbuf[first] = ' '; - strcpy (tmpbuf + first + 1, cp + 1 + len); - if (adjust) - *adjust = len; + memcpy (tmpbuf + first + 1, past_reloc, second); + tmpbuf[first + second + 1] = '\0'; return tmpbuf; } @@ -4042,15 +4097,6 @@ md_convert_frag (abfd, sec, fragP) /* Address we want to reach in file space. */ target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; -#ifdef BFD_ASSEMBLER - /* Not needed otherwise? */ - { - /* Local symbols which have already been resolved have a NULL frag. */ - fragS *sym_frag = symbol_get_frag (fragP->fr_symbol); - if (sym_frag) - target_address += sym_frag->fr_address; - } -#endif /* Address opcode resides at in file space. */ opcode_address = fragP->fr_address + fragP->fr_fix; @@ -4165,19 +4211,17 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) the same (little-endian) format, so we don't need to care about which we are handling. */ -int -md_apply_fix3 (fixP, valp, seg) +void +md_apply_fix3 (fixP, valP, seg) /* The fix we're to put in. */ fixS *fixP; - /* Pointer to the value of the bits. */ - valueT *valp; - + valueT * valP; /* Segment fix is from. */ segT seg ATTRIBUTE_UNUSED; { - register char *p = fixP->fx_where + fixP->fx_frag->fr_literal; - valueT value = *valp; + char *p = fixP->fx_where + fixP->fx_frag->fr_literal; + valueT value = * valP; #if defined (BFD_ASSEMBLER) && !defined (TE_Mach) if (fixP->fx_pcrel) @@ -4311,30 +4355,26 @@ md_apply_fix3 (fixP, valp, seg) case BFD_RELOC_VTABLE_INHERIT: case BFD_RELOC_VTABLE_ENTRY: fixP->fx_done = 0; - return 1; + return; default: break; } #endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) */ - *valp = value; + * valP = value; #endif /* defined (BFD_ASSEMBLER) && !defined (TE_Mach) */ -#ifndef BFD_ASSEMBLER - md_number_to_chars (p, value, fixP->fx_size); -#else /* Are we finished with this relocation now? */ - if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) + if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1; +#ifdef BFD_ASSEMBLER else if (use_rela_relocations) { fixP->fx_no_overflow = 1; value = 0; } - md_number_to_chars (p, value, fixP->fx_size); #endif - - return 1; + md_number_to_chars (p, value, fixP->fx_size); } #define MAX_LITTLENUMS 6 @@ -4397,7 +4437,7 @@ static char * output_invalid (c) int c; { - if (isprint (c)) + if (ISPRINT (c)) sprintf (output_invalid_buf, "'%c'", c); else sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); @@ -4611,6 +4651,48 @@ i386_target_format () } #endif /* OBJ_MAYBE_ more than one */ + +#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) +void i386_elf_emit_arch_note () +{ + if (OUTPUT_FLAVOR == bfd_target_elf_flavour + && cpu_arch_name != NULL) + { + char *p; + asection *seg = now_seg; + subsegT subseg = now_subseg; + Elf_Internal_Note i_note; + Elf_External_Note e_note; + asection *note_secp; + int len; + + /* Create the .note section. */ + note_secp = subseg_new (".note", 0); + bfd_set_section_flags (stdoutput, + note_secp, + SEC_HAS_CONTENTS | SEC_READONLY); + + /* Process the arch string. */ + len = strlen (cpu_arch_name); + + i_note.namesz = len + 1; + i_note.descsz = 0; + i_note.type = NT_ARCH; + p = frag_more (sizeof (e_note.namesz)); + md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz)); + p = frag_more (sizeof (e_note.descsz)); + md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz)); + p = frag_more (sizeof (e_note.type)); + md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type)); + p = frag_more (len + 1); + strcpy (p, cpu_arch_name); + + frag_align (2, 0, 0); + + subseg_set (seg, subseg); + } +} +#endif #endif /* BFD_ASSEMBLER */ symbolS * @@ -4741,8 +4823,9 @@ tc_gen_reloc (section, fixp) switch (fixp->fx_size) { default: - as_bad (_("can not do %d byte pc-relative relocation"), - fixp->fx_size); + as_bad_where (fixp->fx_file, fixp->fx_line, + _("can not do %d byte pc-relative relocation"), + fixp->fx_size); code = BFD_RELOC_32_PCREL; break; case 1: code = BFD_RELOC_8_PCREL; break; @@ -4755,7 +4838,9 @@ tc_gen_reloc (section, fixp) switch (fixp->fx_size) { default: - as_bad (_("can not do %d byte relocation"), fixp->fx_size); + as_bad_where (fixp->fx_file, fixp->fx_line, + _("can not do %d byte relocation"), + fixp->fx_size); code = BFD_RELOC_32; break; case 1: code = BFD_RELOC_8; break; |