diff options
Diffstat (limited to 'contrib/binutils/gas/config')
-rw-r--r-- | contrib/binutils/gas/config/tc-arm.c | 316 | ||||
-rw-r--r-- | contrib/binutils/gas/config/tc-i386.c | 87 | ||||
-rw-r--r-- | contrib/binutils/gas/config/te-freebsd.h | 36 |
3 files changed, 248 insertions, 191 deletions
diff --git a/contrib/binutils/gas/config/tc-arm.c b/contrib/binutils/gas/config/tc-arm.c index 4779b3d..c6a1979 100644 --- a/contrib/binutils/gas/config/tc-arm.c +++ b/contrib/binutils/gas/config/tc-arm.c @@ -382,39 +382,50 @@ static CONST struct asm_flg cplong_flag[] = struct asm_psr { CONST char * template; - unsigned long number; + boolean cpsr; + unsigned long field; }; -#define PSR_FIELD_MASK 0x000f0000 +#define SPSR_BIT (1 << 22) /* The bit that distnguishes CPSR and SPSR. */ +#define PSR_SHIFT 16 /* How many bits to shift the PSR_xxx bits up by. */ -#define PSR_FLAGS 0x00080000 -#define PSR_CONTROL 0x00010000 /* Undocumented instruction, its use is discouraged by ARM */ -#define PSR_ALL 0x00090000 - -#define CPSR_ALL 0 -#define SPSR_ALL 1 -#define CPSR_FLG 2 -#define SPSR_FLG 3 -#define CPSR_CTL 4 -#define SPSR_CTL 5 +#define PSR_c (1 << 0) +#define PSR_x (1 << 1) +#define PSR_s (1 << 2) +#define PSR_f (1 << 3) static CONST struct asm_psr psrs[] = { - /* Valid <psr>'s */ - {"cpsr", CPSR_ALL}, - {"cpsr_all", CPSR_ALL}, - {"spsr", SPSR_ALL}, - {"spsr_all", SPSR_ALL}, - - /* Valid <psrf>'s */ - {"cpsr_flg", CPSR_FLG}, - {"spsr_flg", SPSR_FLG}, - - /* Valid <psrc>'s */ - {"cpsr_c", CPSR_CTL}, - {"cpsr_ctl", CPSR_CTL}, - {"spsr_c", SPSR_CTL}, - {"spsr_ctl", SPSR_CTL} + {"CPSR", true, PSR_c | PSR_f}, + {"CPSR_all", true, PSR_c | PSR_f}, + {"SPSR", false, PSR_c | PSR_f}, + {"SPSR_all", false, PSR_c | PSR_f}, + {"CPSR_flg", true, PSR_f}, + {"CPSR_f", true, PSR_f}, + {"SPSR_flg", false, PSR_f}, + {"SPSR_f", false, PSR_f}, + {"CPSR_c", true, PSR_c}, + {"CPSR_ctl", true, PSR_c}, + {"SPSR_c", false, PSR_c}, + {"SPSR_ctl", false, PSR_c}, + {"CPSR_x", true, PSR_x}, + {"CPSR_s", true, PSR_s}, + {"SPSR_x", false, PSR_x}, + {"SPSR_s", false, PSR_s}, + /* For backwards compatability with older toolchain we also + support lower case versions of some of these flags. */ + {"cpsr", true, PSR_c | PSR_f}, + {"cpsr_all", true, PSR_c | PSR_f}, + {"spsr", false, PSR_c | PSR_f}, + {"spsr_all", false, PSR_c | PSR_f}, + {"cpsr_flg", true, PSR_f}, + {"cpsr_f", true, PSR_f}, + {"spsr_flg", false, PSR_f}, + {"spsr_f", false, PSR_f}, + {"cpsr_c", true, PSR_c}, + {"cpsr_ctl", true, PSR_c}, + {"spsr_c", false, PSR_c}, + {"spsr_ctl", false, PSR_c} }; /* Functions called by parser. */ @@ -459,7 +470,7 @@ static void do_fp_to_reg PARAMS ((char *, unsigned long)); static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *, int, int)); static int arm_reg_parse PARAMS ((char **)); -static int arm_psr_parse PARAMS ((char **)); +static CONST struct asm_psr * arm_psr_parse PARAMS ((char **)); static void symbol_locate PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *)); static int add_to_lit_pool PARAMS ((void)); static unsigned validate_immediate PARAMS ((unsigned)); @@ -468,7 +479,7 @@ static int validate_offset_imm PARAMS ((unsigned int, int)); static void opcode_select PARAMS ((int)); static void end_of_line PARAMS ((char *)); static int reg_required_here PARAMS ((char **, int)); -static int psr_required_here PARAMS ((char **, int, int)); +static int psr_required_here PARAMS ((char **)); static int co_proc_number PARAMS ((char **)); static int cp_opc_expr PARAMS ((char **, int, int)); static int cp_reg_required_here PARAMS ((char **, int)); @@ -570,8 +581,8 @@ static CONST struct asm_opcode insns[] = {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs}, {"msr", 0x0120f000, NULL, NULL, ARM_6UP, do_msr}, /* ScottB: our code uses 0x0128f000 for msr. - NickC: but this is wrong because the bits 16 and 19 are handled - by the PSR_xxx defines above. */ + NickC: but this is wrong because the bits 16 through 19 are + handled by the PSR_xxx defines above. */ /* ARM 7M long multiplies - need signed/unsigned flags! */ {"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull}, @@ -1563,27 +1574,65 @@ reg_required_here (str, shift) return FAIL; } +static CONST struct asm_psr * +arm_psr_parse (ccp) + register char ** ccp; +{ + char * start = * ccp; + char c; + char * p; + CONST struct asm_psr * psr; + + p = start; + + /* Skip to the end of the next word in the input stream. */ + do + { + c = *p++; + } + while (isalpha (c) || c == '_'); + + /* Terminate the word. */ + *--p = 0; + + /* Now locate the word in the psr hash table. */ + psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start); + + /* Restore the input stream. */ + *p = c; + + /* If we found a valid match, advance the + stream pointer past the end of the word. */ + *ccp = p; + + return psr; +} + +/* Parse the input looking for a PSR flag. */ static int -psr_required_here (str, cpsr, spsr) +psr_required_here (str) char ** str; - int cpsr; - int spsr; { - int psr; char * start = *str; - psr = arm_psr_parse (str); + CONST struct asm_psr * psr; - if (psr == cpsr || psr == spsr) + psr = arm_psr_parse (str); + + if (psr) { - if (psr == spsr) - inst.instruction |= 1 << 22; + /* If this is the SPSR that is being modified, set the R bit. */ + if (! psr->cpsr) + inst.instruction |= SPSR_BIT; + + /* Set the psr flags in the MSR instruction. */ + inst.instruction |= psr->field << PSR_SHIFT; return SUCCESS; } - /* In the few cases where we might be able to accept something else - this error can be overridden. */ - inst.error = _("<psr(f)> expected"); + /* In the few cases where we might be able to accept + something else this error can be overridden. */ + inst.error = _("flag for {c}psr instruction expected"); /* Restore the start point. */ *str = start; @@ -1866,6 +1915,8 @@ do_mrs (str, flags) char *str; unsigned long flags; { + int skip = 0; + /* Only one syntax. */ skip_whitespace (str); @@ -1875,104 +1926,111 @@ do_mrs (str, flags) return; } - if (skip_past_comma (&str) == FAIL - || psr_required_here (& str, CPSR_ALL, SPSR_ALL) == FAIL) + if (skip_past_comma (&str) == FAIL) { - inst.error = _("<psr> expected"); + inst.error = _("comma expected after register name"); return; } + skip_whitespace (str); + + if ( strcmp (str, "CPSR") == 0 + || strcmp (str, "SPSR") == 0 + /* Lower case versions for backwards compatability. */ + || strcmp (str, "cpsr") == 0 + || strcmp (str, "spsr") == 0) + skip = 4; + /* This is for backwards compatability with older toolchains. */ + else if (strcmp (str, "cpsr_all") == 0 + || strcmp (str, "spsr_all") == 0) + skip = 7; + else + { + inst.error = _("{C|S}PSR expected"); + return; + } + + if (* str == 's' || * str == 'S') + inst.instruction |= SPSR_BIT; + str += skip; + inst.instruction |= flags; end_of_line (str); - return; } -/* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression". */ +/* Two possible forms: + "{C|S}PSR_<field>, Rm", + "{C|S}PSR_f, #expression". */ static void do_msr (str, flags) char * str; unsigned long flags; { - int reg; + skip_whitespace (str); + + if (psr_required_here (& str) == FAIL) + return; + + if (skip_past_comma (& str) == FAIL) + { + inst.error = _("comma missing after psr flags"); + return; + } skip_whitespace (str); - if (psr_required_here (&str, CPSR_ALL, SPSR_ALL) == SUCCESS) + if (reg_required_here (& str, 0) != FAIL) { - inst.instruction |= PSR_ALL; + inst.error = NULL; + inst.instruction |= flags; + end_of_line (str); + return; + } - /* Sytax should be "<psr>, Rm" */ - if (skip_past_comma (&str) == FAIL - || (reg = reg_required_here (&str, 0)) == FAIL) - { - inst.error = BAD_ARGS; - return; - } + if (! is_immediate_prefix (* str)) + { + inst.error = _("only a register or immediate value can follow a psr flag"); + return; + } + + str ++; + inst.error = NULL; + + if (my_get_expression (& inst.reloc.exp, & str)) + { + inst.error = _("only a register or immediate value can follow a psr flag"); + return; + } + + if (inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT)) + { + inst.error = _("can only set flag field with immediate value"); + return; + } + + flags |= INST_IMMEDIATE; + + if (inst.reloc.exp.X_add_symbol) + { + inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; + inst.reloc.pc_rel = 0; } else { - if (psr_required_here (& str, CPSR_FLG, SPSR_FLG) == SUCCESS) - inst.instruction |= PSR_FLAGS; - else if (psr_required_here (& str, CPSR_CTL, SPSR_CTL) == SUCCESS) - inst.instruction |= PSR_CONTROL; - else - { - inst.error = BAD_ARGS; - return; - } + unsigned value = validate_immediate (inst.reloc.exp.X_add_number); - if (skip_past_comma (&str) == FAIL) + if (value == (unsigned) FAIL) { - inst.error = BAD_ARGS; + inst.error = _("Invalid constant"); return; } - /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */ - - if ((reg = reg_required_here (& str, 0)) != FAIL) - ; - /* Immediate expression. */ - else if (is_immediate_prefix (* str)) - { - str ++; - inst.error = NULL; - - if (my_get_expression (& inst.reloc.exp, & str)) - { - inst.error = _("Register or shift expression expected"); - return; - } - - if (inst.reloc.exp.X_add_symbol) - { - inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; - inst.reloc.pc_rel = 0; - } - else - { - unsigned value = validate_immediate (inst.reloc.exp.X_add_number); - if (value == (unsigned) FAIL) - { - inst.error = _("Invalid constant"); - return; - } - - inst.instruction |= value; - } - - flags |= INST_IMMEDIATE; - } - else - { - inst.error = _("Error: unrecognised syntax for second argument to msr instruction"); - return; - } + inst.instruction |= value; } inst.error = NULL; inst.instruction |= flags; end_of_line (str); - return; } /* Long Multiply Parser @@ -5242,7 +5300,7 @@ md_section_align (segment, size) /* ARGSUSED */ symbolS * md_undefined_symbol (name) - char * name; + char * name ATTRIBUTE_UNUSED; { #ifdef OBJ_ELF if (name[0] == '_' && name[1] == 'G' @@ -5307,33 +5365,6 @@ arm_reg_parse (ccp) return FAIL; } -static int -arm_psr_parse (ccp) - register char ** ccp; -{ - char * start = * ccp; - char c; - char * p; - CONST struct asm_psr * psr; - - p = start; - c = *p++; - while (isalpha (c) || c == '_') - c = *p++; - - *--p = 0; - psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start); - *p = c; - - if (psr) - { - *ccp = p; - return psr->number; - } - - return FAIL; -} - int md_apply_fix3 (fixP, val, seg) fixS * fixP; @@ -6390,7 +6421,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n")); * -m[arm]8[10] Arm 8 processors * -m[arm]9[20][tdmi] Arm 9 processors * -mstrongarm[110[0]] StrongARM processors - * -m[arm]v[2345] Arm architectures + * -m[arm]v[2345[t]] Arm architectures * -mall All (except the ARM1) * FP variants: * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions @@ -6847,12 +6878,13 @@ cons_fix_new_arm (frag, where, size, exp) bfd_reloc_code_real_type type; int pcrel = 0; - /* Pick a reloc ... - * - * @@ Should look at CPU word size. - */ + /* Pick a reloc. + FIXME: @@ Should look at CPU word size. */ switch (size) { + case 1: + type = BFD_RELOC_8; + break; case 2: type = BFD_RELOC_16; break; diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c index 7efd6dd..17b1f79 100644 --- a/contrib/binutils/gas/config/tc-i386.c +++ b/contrib/binutils/gas/config/tc-i386.c @@ -143,7 +143,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)) +#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && !defined (TE_LINUX) && !defined(TE_FreeBSD)) /* Putting '/' here makes it impossible to use the divide operator. However, we need it for compatibility with SVR4 systems. */ const char comment_chars[] = "#/"; @@ -161,7 +161,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)) +#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && !defined (TE_LINUX) && !defined(TE_FreeBSD)) const char line_comment_chars[] = ""; #else const char line_comment_chars[] = "/"; @@ -937,12 +937,11 @@ int tc_i386_fix_adjustable (fixP) fixS *fixP; { -#if defined (OBJ_ELF) || defined (TE_PE) +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (TE_PE) /* Prevent all adjustments to global symbols, or else dynamic linking will not work correctly. */ - if (S_IS_EXTERN (fixP->fx_addsy)) - return 0; - if (S_IS_WEAK (fixP->fx_addsy)) + if (S_IS_EXTERNAL (fixP->fx_addsy) + || S_IS_WEAK (fixP->fx_addsy)) return 0; #endif /* adjust_reloc_syms doesn't know about the GOT */ @@ -2157,10 +2156,11 @@ md_assemble (line) if (prefix) *p++ = DATA_PREFIX_OPCODE; *p = i.tm.base_opcode; - /* 1 possible extra opcode + displacement go in fr_var. */ + /* 1 possible extra opcode + displacement go in var part. + Pass reloc in fr_var. */ frag_var (rs_machine_dependent, 1 + size, - 1, + i.disp_reloc[0], ((unsigned char) *p == JUMP_PC_RELATIVE ? ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL) | code16 : ENCODE_RELAX_STATE (COND_JUMP, SMALL) | code16), @@ -3647,54 +3647,56 @@ i386_operand (operand_string) return 1; /* normal return */ } -/* - * md_estimate_size_before_relax() - * - * Called just before relax(). - * Any symbol that is now undefined will not become defined. - * Return the correct fr_subtype in the frag. - * Return the initial "guess for fr_var" to caller. - * The guess for fr_var is ACTUALLY the growth beyond fr_fix. - * Whatever we do to grow fr_fix or fr_var contributes to our returned value. - * Although it may not be explicit in the frag, pretend fr_var starts with a - * 0 value. - */ +/* md_estimate_size_before_relax() + + Called just before relax() for rs_machine_dependent frags. The x86 + assembler uses these frags to handle variable size jump + instructions. + + Any symbol that is now undefined will not become defined. + Return the correct fr_subtype in the frag. + Return the initial "guess for variable size of frag" to caller. + The guess is actually the growth beyond the fixed part. Whatever + we do to grow the fixed or variable part contributes to our + returned value. */ + int md_estimate_size_before_relax (fragP, segment) register fragS *fragP; register segT segment; { - register unsigned char *opcode; - register int old_fr_fix; - - old_fr_fix = fragP->fr_fix; - opcode = (unsigned char *) fragP->fr_opcode; /* We've already got fragP->fr_subtype right; all we have to do is - check for un-relaxable symbols. */ - if (S_GET_SEGMENT (fragP->fr_symbol) != segment) + check for un-relaxable symbols. On an ELF system, we can't relax + an externally visible symbol, because it may be overridden by a + shared library. */ + if (S_GET_SEGMENT (fragP->fr_symbol) != segment +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (TE_PE) + || S_IS_EXTERNAL (fragP->fr_symbol) + || S_IS_WEAK (fragP->fr_symbol) +#endif + ) { - /* symbol is undefined in this segment */ - int code16 = fragP->fr_subtype & CODE16; - int size = code16 ? 2 : 4; + /* Symbol is undefined in this segment, or we need to keep a + reloc so that weak symbols can be overridden. */ + int size = (fragP->fr_subtype & CODE16) ? 2 : 4; #ifdef BFD_ASSEMBLER enum bfd_reloc_code_real reloc_type; #else int reloc_type; #endif + unsigned char *opcode; + int old_fr_fix; - if (GOT_symbol /* Not quite right - we should switch on presence of - @PLT, but I cannot see how to get to that from - here. We should have done this in md_assemble to - really get it right all of the time, but I think it - does not matter that much, as this will be right - most of the time. ERY */ - && S_GET_SEGMENT(fragP->fr_symbol) == undefined_section) - reloc_type = BFD_RELOC_386_PLT32; - else if (code16) + if (fragP->fr_var != NO_RELOC) + reloc_type = fragP->fr_var; + else if (size == 2) reloc_type = BFD_RELOC_16_PCREL; else reloc_type = BFD_RELOC_32_PCREL; + old_fr_fix = fragP->fr_fix; + opcode = (unsigned char *) fragP->fr_opcode; + switch (opcode[0]) { case JUMP_PC_RELATIVE: /* make jmp (0xeb) a dword displacement jump */ @@ -3719,10 +3721,11 @@ md_estimate_size_before_relax (fragP, segment) break; } frag_wane (fragP); + return fragP->fr_fix - old_fr_fix; } - return (fragP->fr_var + fragP->fr_fix - old_fr_fix); -} /* md_estimate_size_before_relax() */ - + return 1; /* Guess a short jump. */ +} + /* * md_convert_frag(); * diff --git a/contrib/binutils/gas/config/te-freebsd.h b/contrib/binutils/gas/config/te-freebsd.h index 1314235..44f4610 100644 --- a/contrib/binutils/gas/config/te-freebsd.h +++ b/contrib/binutils/gas/config/te-freebsd.h @@ -1,8 +1,30 @@ -/* - * Target environment for FreeBSD. It is the same as the generic - * target, except it arranges to suppress the use of "/" as a comment - * character. Some code in the FreeBSD kernel uses "/" to mean - * division. (What a concept.) - */ +/* te-freebsd.h -- FreeBSD target environment declarations. + Copyright (C) 2000 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* Target environment for FreeBSD. It is the same as the generic + target, except that it arranges via the TE_FreeBSD define to + suppress the use of "/" as a comment character. Some code in the + FreeBSD kernel uses "/" to mean division. (What a concept!) */ #define TE_FreeBSD 1 -#include "te-generic.h" + +#define LOCAL_LABELS_DOLLAR 1 +#define LOCAL_LABELS_FB 1 + +#include "obj-format.h" |