X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-cris.c;h=25c9ea58bada9459bfd88ed56b64742d5e6e4c3e;hb=3067d3b96cfb88e86acf94d2aa1575cff0e0110f;hp=5e8d4bd6e89d95539fb27896799f11826081030c;hpb=ae57792d90d18306c9e470b9ecc245cdeef389f4;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-cris.c b/gas/config/tc-cris.c index 5e8d4bd6e8..25c9ea58ba 100644 --- a/gas/config/tc-cris.c +++ b/gas/config/tc-cris.c @@ -1,5 +1,5 @@ /* tc-cris.c -- Assembler code for the CRIS CPU core. - Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2000-2015 Free Software Foundation, Inc. Contributed by Axis Communications AB, Lund, Sweden. Originally written for GAS 1.38.1 by Mikael Asker. @@ -9,7 +9,7 @@ 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) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -19,10 +19,9 @@ 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. */ + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include #include "as.h" #include "safe-ctype.h" #include "subsegs.h" @@ -52,7 +51,7 @@ /* Like in ":GOT", ":GOTOFF" etc. Other ports use '@', but that's in line_separator_chars for CRIS, so we avoid it. */ -#define PIC_SUFFIX_CHAR ':' +#define RELOC_SUFFIX_CHAR ':' /* This might be CRIS_INSN_NONE if we're assembling a prefix-insn only. Note that some prefix-insns might be assembled as CRIS_INSN_NORMAL. */ @@ -120,52 +119,45 @@ enum cris_archs arch_cris_any_v0_v10, arch_crisv32, arch_cris_common_v10_v32 }; -static enum cris_archs cris_arch_from_string PARAMS ((char **)); -static int cris_insn_ver_valid_for_arch PARAMS ((enum cris_insn_version_usage, - enum cris_archs)); - -static void cris_process_instruction PARAMS ((char *, - struct cris_instruction *, - struct cris_prefix *)); -static int get_bwd_size_modifier PARAMS ((char **, int *)); -static int get_bw_size_modifier PARAMS ((char **, int *)); -static int get_gen_reg PARAMS ((char **, int *)); -static int get_spec_reg PARAMS ((char **, - const struct cris_spec_reg **)); -static int get_sup_reg PARAMS ((char **, int *)); -static int get_autoinc_prefix_or_indir_op PARAMS ((char **, - struct cris_prefix *, - int *, int *, int *, - expressionS *)); -static int get_3op_or_dip_prefix_op PARAMS ((char **, - struct cris_prefix *)); -static int cris_get_expression PARAMS ((char **, expressionS *)); -static int get_flags PARAMS ((char **, int *)); -static void gen_bdap PARAMS ((int, expressionS *)); -static int branch_disp PARAMS ((int)); -static void gen_cond_branch_32 PARAMS ((char *, char *, fragS *, - symbolS *, symbolS *, long int)); -static void cris_number_to_imm PARAMS ((char *, long, int, fixS *, segT)); -static void cris_create_short_jump PARAMS ((char *, addressT, addressT, - fragS *, symbolS *)); -static void s_syntax PARAMS ((int)); -static void s_cris_file PARAMS ((int)); -static void s_cris_loc PARAMS ((int)); -static void s_cris_arch PARAMS ((int)); +static enum cris_archs cris_arch_from_string (char **); +static int cris_insn_ver_valid_for_arch (enum cris_insn_version_usage, + enum cris_archs); + +static void cris_process_instruction (char *, struct cris_instruction *, + struct cris_prefix *); +static int get_bwd_size_modifier (char **, int *); +static int get_bw_size_modifier (char **, int *); +static int get_gen_reg (char **, int *); +static int get_spec_reg (char **, const struct cris_spec_reg **); +static int get_sup_reg (char **, int *); +static int get_autoinc_prefix_or_indir_op (char **, struct cris_prefix *, + int *, int *, int *, + expressionS *); +static int get_3op_or_dip_prefix_op (char **, struct cris_prefix *); +static int cris_get_expression (char **, expressionS *); +static int get_flags (char **, int *); +static void gen_bdap (int, expressionS *); +static int branch_disp (int); +static void gen_cond_branch_32 (char *, char *, fragS *, symbolS *, symbolS *, + long int); +static void cris_number_to_imm (char *, long, int, fixS *, segT); +static void s_syntax (int); +static void s_cris_file (int); +static void s_cris_loc (int); +static void s_cris_arch (int); +static void s_cris_dtpoff (int); /* Get ":GOT", ":GOTOFF", ":PLT" etc. suffixes. */ -static void cris_get_pic_suffix PARAMS ((char **, - bfd_reloc_code_real_type *, - expressionS *)); -static unsigned int cris_get_pic_reloc_size - PARAMS ((bfd_reloc_code_real_type)); +static void cris_get_reloc_suffix (char **, bfd_reloc_code_real_type *, + expressionS *); +static unsigned int cris_get_specified_reloc_size (bfd_reloc_code_real_type); /* All the .syntax functions. */ -static void cris_force_reg_prefix PARAMS ((void)); -static void cris_relax_reg_prefix PARAMS ((void)); -static void cris_sym_leading_underscore PARAMS ((void)); -static void cris_sym_no_leading_underscore PARAMS ((void)); -static char *cris_insn_first_word_frag PARAMS ((void)); +static void cris_force_reg_prefix (void); +static void cris_relax_reg_prefix (void); +static void cris_sym_leading_underscore (void); +static void cris_sym_no_leading_underscore (void); +static char *cris_insn_first_word_frag (void); /* Handle to the opcode hash table. */ static struct hash_control *op_hash = NULL; @@ -189,6 +181,9 @@ static bfd_boolean symbols_have_leading_underscore /* Whether or not we allow PIC, and expand to PIC-friendly constructs. */ static bfd_boolean pic = FALSE; +/* Whether or not we allow TLS suffixes. For the moment, we always do. */ +static const bfd_boolean tls = TRUE; + /* If we're configured for "cris", default to allow all v0..v10 instructions and register names. */ #ifndef DEFAULT_CRIS_ARCH @@ -201,6 +196,7 @@ static enum cris_archs cris_arch = XCONCAT2 (arch_,DEFAULT_CRIS_ARCH); const pseudo_typeS md_pseudo_table[] = { {"dword", cons, 4}, + {"dtpoffd", s_cris_dtpoff, 4}, {"syntax", s_syntax, 0}, {"file", s_cris_file, 0}, {"loc", s_cris_loc, 0}, @@ -273,6 +269,7 @@ const char FLT_CHARS[] = ""; #define STATE_COND_BRANCH_COMMON (5) #define STATE_ABS_BRANCH_V32 (6) #define STATE_LAPC (7) +#define STATE_COND_BRANCH_PIC (8) #define STATE_LENGTH_MASK (3) #define STATE_BYTE (0) @@ -396,6 +393,18 @@ const relax_typeS md_cris_relax_table[] = {0, 0, 4, 0}, /* Unused (7, 3). */ + {1, 1, 0, 0}, + + /* PIC for pre-v32: Bcc o (8, 0). */ + {BRANCH_BF, BRANCH_BB, 0, ENCODE_RELAX (STATE_COND_BRANCH_PIC, 1)}, + + /* Bcc [PC+] (8, 1). */ + {BRANCH_WF, BRANCH_WB, 2, ENCODE_RELAX (STATE_COND_BRANCH_PIC, 2)}, + + /* 32-bit expansion, PIC (8, 2). */ + {0, 0, 12, 0}, + + /* Unused (8, 3). */ {1, 1, 0, 0} }; @@ -438,8 +447,10 @@ const char *md_shortopts = "hHN"; int md_short_jump_size = 6; -/* The v32 version has a delay-slot, hence two bytes longer. */ +/* The v32 version has a delay-slot, hence two bytes longer. + The pre-v32 PIC version uses a prefixed insn. */ #define cris_any_v0_v10_long_jump_size 6 +#define cris_any_v0_v10_long_jump_size_pic 8 #define crisv32_long_jump_size 8 int md_long_jump_size = XCONCAT2 (DEFAULT_CRIS_ARCH,_long_jump_size); @@ -449,7 +460,7 @@ int md_long_jump_size = XCONCAT2 (DEFAULT_CRIS_ARCH,_long_jump_size); that, the output format must remain fixed. */ const char * -cris_target_format () +cris_target_format (void) { switch (OUTPUT_FLAVOR) { @@ -471,7 +482,7 @@ cris_target_format () cris_arch. */ unsigned int -cris_mach () +cris_mach (void) { unsigned int retval = 0; @@ -505,10 +516,8 @@ cris_mach () The offset can be 8, 16 or 32 bits long. */ long -cris_relax_frag (seg, fragP, stretch) - segT seg ATTRIBUTE_UNUSED; - fragS *fragP; - long stretch ATTRIBUTE_UNUSED; +cris_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP, + long stretch ATTRIBUTE_UNUSED) { long growth; offsetT aim = 0; @@ -524,6 +533,7 @@ cris_relax_frag (seg, fragP, stretch) because of the different reasons that they aren't relaxable. */ switch (fragP->fr_subtype) { + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD): case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD): case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD): case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_DWORD): @@ -612,10 +622,7 @@ cris_relax_frag (seg, fragP, stretch) fr_var starts with a value. */ int -md_estimate_size_before_relax (fragP, segment_type) - fragS *fragP; - /* The segment is either N_DATA or N_TEXT. */ - segT segment_type; +md_estimate_size_before_relax (fragS *fragP, segT segment_type) { int old_fr_fix; symbolS *symbolP = fragP->fr_symbol; @@ -644,6 +651,7 @@ md_estimate_size_before_relax (fragP, segment_type) HANDLE_RELAXABLE (STATE_COND_BRANCH); HANDLE_RELAXABLE (STATE_COND_BRANCH_V32); HANDLE_RELAXABLE (STATE_COND_BRANCH_COMMON); + HANDLE_RELAXABLE (STATE_COND_BRANCH_PIC); HANDLE_RELAXABLE (STATE_ABS_BRANCH_V32); case ENCODE_RELAX (STATE_LAPC, STATE_UNDF): @@ -751,6 +759,9 @@ md_estimate_size_before_relax (fragP, segment_type) case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE): case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD): case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD): + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_BYTE): + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_WORD): + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD): case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE): case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD): case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD): @@ -792,10 +803,8 @@ md_estimate_size_before_relax (fragP, segment_type) The caller will turn the frag into a ".space 0". */ void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS *fragP; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, + fragS *fragP) { /* Pointer to first byte in variable-sized part of the frag. */ char *var_partp; @@ -805,7 +814,7 @@ md_convert_frag (abfd, sec, fragP) /* Used to check integrity of the relaxation. One of 2 = long, 1 = word, or 0 = byte. */ - int length_code; + int length_code ATTRIBUTE_UNUSED; /* Size in bytes of variable-sized part of frag. */ int var_part_size = 0; @@ -837,6 +846,7 @@ md_convert_frag (abfd, sec, fragP) switch (fragP->fr_subtype) { case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE): + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_BYTE): case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE): case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_BYTE): case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_BYTE): @@ -845,6 +855,7 @@ md_convert_frag (abfd, sec, fragP) break; case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD): + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_WORD): case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD): case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_WORD): case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_WORD): @@ -872,6 +883,14 @@ md_convert_frag (abfd, sec, fragP) var_part_size = 2 + 2 + 4 + 2; break; + case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD): + gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP, + fragP->fr_symbol, (symbolS *) NULL, + fragP->fr_offset); + /* Twelve bytes added: a branch, nop and a pic-branch-32. */ + var_part_size = 2 + 2 + 4 + 2 + 2; + break; + case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD): gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP, fragP->fr_symbol, (symbolS *) NULL, @@ -975,7 +994,7 @@ md_convert_frag (abfd, sec, fragP) break; case ENCODE_RELAX (STATE_MUL, STATE_BYTE): - /* This is the only time we check position and aligmnent of the + /* This is the only time we check position and alignment of the placement-tracking frag. */ if (sec->alignment_power < 2) as_bad_where (fragP->fr_file, fragP->fr_line, @@ -1001,37 +1020,42 @@ md_convert_frag (abfd, sec, fragP) } /* Generate a short jump around a secondary jump table. - Used by md_create_long_jump. - - This used to be md_create_short_jump, but is now called from - md_create_long_jump instead, when sufficient, since the sizes of the - jumps are the same for pre-v32. */ + Also called from md_create_long_jump, when sufficient. */ -static void -cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol) - char *storep; - addressT from_addr; - addressT to_addr; - fragS *fragP ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; +void +md_create_short_jump (char *storep, addressT from_addr, addressT to_addr, + fragS *fragP ATTRIBUTE_UNUSED, + symbolS *to_symbol ATTRIBUTE_UNUSED) { long int distance; /* See md_create_long_jump about the comment on the "+ 2". */ long int max_minimal_minus_distance; long int max_minimal_plus_distance; + long int max_minus_distance; + long int max_plus_distance; int nop_opcode; if (cris_arch == arch_crisv32) { max_minimal_minus_distance = BRANCH_BB_V32 + 2; max_minimal_plus_distance = BRANCH_BF_V32 + 2; + max_minus_distance = BRANCH_WB_V32 + 2; + max_plus_distance = BRANCH_WF_V32 + 2; nop_opcode = NOP_OPCODE_V32; } + else if (cris_arch == arch_cris_common_v10_v32) + /* Bail out for compatibility mode. (It seems it can be implemented, + perhaps with a 10-byte sequence: "move.d NNNN,$pc/$acr", "jump + $acr", "nop"; but doesn't seem worth it at the moment.) */ + as_fatal (_("Out-of-range .word offset handling\ + is not implemented for .arch common_v10_v32")); else { max_minimal_minus_distance = BRANCH_BB + 2; max_minimal_plus_distance = BRANCH_BF + 2; + max_minus_distance = BRANCH_WB + 2; + max_plus_distance = BRANCH_WF + 2; nop_opcode = NOP_OPCODE; } @@ -1051,7 +1075,8 @@ cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol) a nop to keep disassembly sane. */ md_number_to_chars (storep + 4, nop_opcode, 2); } - else + else if (max_minus_distance <= distance + && distance <= max_plus_distance) { /* Make it a "long" short jump: "BA (PC+)". */ md_number_to_chars (storep, BA_PC_INCR_OPCODE, 2); @@ -1066,6 +1091,9 @@ cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol) /* A nop for the delay slot. */ md_number_to_chars (storep + 4, nop_opcode, 2); } + else + as_bad_where (fragP->fr_file, fragP->fr_line, + _(".word case-table handling failed: table too large")); } /* Generate a long jump in a secondary jump table. @@ -1078,12 +1106,8 @@ cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol) to_symbol Destination symbol. */ void -md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol) - char *storep; - addressT from_addr; - addressT to_addr; - fragS *fragP; - symbolS *to_symbol; +md_create_long_jump (char *storep, addressT from_addr, addressT to_addr, + fragS *fragP, symbolS *to_symbol) { long int distance; @@ -1096,29 +1120,29 @@ md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol) long int max_short_plus_distance = cris_arch != arch_crisv32 ? BRANCH_WF + 3 : BRANCH_WF_V32 + 3; - /* Bail out for compatibility mode. (It seems it can be implemented, - perhaps with a 10-byte sequence: "move.d NNNN,$pc/$acr", "jump - $acr", "nop"; but doesn't seem worth it at the moment.) */ - if (cris_arch == arch_cris_common_v10_v32) - as_fatal (_("Out-of-range .word offset handling\ - is not implemented for .arch common_v10_v32")); - distance = to_addr - from_addr; if (max_short_minus_distance <= distance && distance <= max_short_plus_distance) - /* Then make it a "short" long jump. */ - cris_create_short_jump (storep, from_addr, to_addr, fragP, + { + /* Then make it a "short" long jump. */ + md_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol); + if (cris_arch == arch_crisv32) + md_number_to_chars (storep + 6, NOP_OPCODE_V32, 2); + else + md_number_to_chars (storep + 6, NOP_OPCODE, 2); + } else { /* We have a "long" long jump: "JUMP [PC+]". If CRISv32, always - make it a BA. Else make it an "ADD [PC+],PC" if we're supposed + make it a BA. Else make it an "MOVE [PC=PC+N],P0" if we're supposed to emit PIC code. */ md_number_to_chars (storep, cris_arch == arch_crisv32 ? BA_DWORD_OPCODE - : (pic ? ADD_PC_INCR_OPCODE : JUMP_PC_INCR_OPCODE), + : (pic ? MOVE_PC_INCR_OPCODE_PREFIX + : JUMP_PC_INCR_OPCODE), 2); /* Follow with a ".DWORD to_addr", PC-relative for PIC. */ @@ -1131,6 +1155,9 @@ md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol) /* Follow it with a "NOP" for CRISv32. */ if (cris_arch == arch_crisv32) md_number_to_chars (storep + 6, NOP_OPCODE_V32, 2); + else if (pic) + /* ...and the rest of the move-opcode for pre-v32 PIC. */ + md_number_to_chars (storep + 6, MOVE_PC_INCR_OPCODE_SUFFIX, 2); } } @@ -1138,7 +1165,7 @@ md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol) start of the insn for debug-format use. */ static char * -cris_insn_first_word_frag () +cris_insn_first_word_frag (void) { char *insnp = frag_more (2); @@ -1157,7 +1184,7 @@ cris_insn_first_word_frag () /* Port-specific assembler initialization. */ void -md_begin () +md_begin (void) { const char *hashret = NULL; int i = 0; @@ -1195,7 +1222,8 @@ md_begin () continue; } - hashret = hash_insert (op_hash, name, (PTR) &cris_opcodes[i]); + /* Need to cast to get rid of "const". FIXME: Fix hash_insert instead. */ + hashret = hash_insert (op_hash, name, (void *) &cris_opcodes[i]); if (hashret != NULL && *hashret != '\0') as_fatal (_("Can't hash `%s': %s\n"), cris_opcodes[i].name, @@ -1216,8 +1244,7 @@ md_begin () /* Assemble a source line. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { struct cris_instruction output_instruction; struct cris_prefix prefix; @@ -1239,7 +1266,7 @@ md_assemble (str) /* When the expression is unknown for a BDAP, it can need 0, 2 or 4 extra bytes, so we handle it separately. */ case PREFIX_BDAP_IMM: - /* We only do it if the relocation is unspecified, i.e. not a PIC + /* We only do it if the relocation is unspecified, i.e. not a PIC or TLS relocation. */ if (prefix.reloc == BFD_RELOC_NONE) { @@ -1256,13 +1283,13 @@ md_assemble (str) md_number_to_chars (opcodep, (long) prefix.opcode, 2); /* Having a specified reloc only happens for DIP and for BDAP with - PIC operands, but it is ok to drop through here for the other + PIC or TLS operands, but it is ok to drop through here for the other prefixes as they can have no relocs specified. */ if (prefix.reloc != BFD_RELOC_NONE) { unsigned int relocsize = (prefix.kind == PREFIX_DIP - ? 4 : cris_get_pic_reloc_size (prefix.reloc)); + ? 4 : cris_get_specified_reloc_size (prefix.reloc)); p = frag_more (relocsize); fix_new_exp (frag_now, (p - frag_now->fr_literal), relocsize, @@ -1341,11 +1368,12 @@ md_assemble (str) That case is handled by md_estimate_size_before_relax. */ length_code = to_seg == now_seg ? STATE_BYTE : STATE_UNDF; - /* Make room for max twelve bytes of variable length for v32 mode, - ten for v10 and older. */ + /* Make room for max twelve bytes of variable length for v32 mode + or PIC, ten for v10 and older. */ frag_var (rs_machine_dependent, (cris_arch == arch_crisv32 - || cris_arch == arch_cris_common_v10_v32) ? 12 : 10, 0, + || cris_arch == arch_cris_common_v10_v32 + || pic) ? 12 : 10, 0, ENCODE_RELAX (cris_arch == arch_crisv32 ? (output_instruction.opcode == BA_QUICK_OPCODE @@ -1353,7 +1381,8 @@ md_assemble (str) : STATE_COND_BRANCH_V32) : (cris_arch == arch_cris_common_v10_v32 ? STATE_COND_BRANCH_COMMON - : STATE_COND_BRANCH), + : (pic ? STATE_COND_BRANCH_PIC + : STATE_COND_BRANCH)), length_code), sym, addvalue, opcodep); } @@ -1364,7 +1393,8 @@ md_assemble (str) section, perhaps an absolute address. Emit a 32-bit branch. */ char *cond_jump = frag_more ((cris_arch == arch_crisv32 - || cris_arch == arch_cris_common_v10_v32) + || cris_arch == arch_cris_common_v10_v32 + || pic) ? 12 : 10); gen_cond_branch_32 (opcodep, cond_jump, frag_now, @@ -1462,13 +1492,24 @@ md_assemble (str) } } +/* Helper error-reporting function: calls as_bad for a format string + for a single value and zeroes the offending value (zero assumed + being a valid value) to avoid repeated error reports in later value + checking. */ + +static void +cris_bad (const char *format, offsetT *valp) +{ + /* We cast to long so the format string can assume that format. */ + as_bad (format, (long) *valp); + *valp = 0; +} + /* Low level text-to-bits assembly. */ static void -cris_process_instruction (insn_text, out_insnp, prefixp) - char *insn_text; - struct cris_instruction *out_insnp; - struct cris_prefix *prefixp; +cris_process_instruction (char *insn_text, struct cris_instruction *out_insnp, + struct cris_prefix *prefixp) { char *s; char modified_char = 0; @@ -1618,8 +1659,8 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (out_insnp->expr.X_op == O_constant && (out_insnp->expr.X_add_number < 0 || out_insnp->expr.X_add_number > 31)) - as_bad (_("Immediate value not in 5 bit unsigned range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 5 bit unsigned range: %ld"), + &out_insnp->expr.X_add_number); out_insnp->reloc = BFD_RELOC_CRIS_UNSIGNED_5; continue; @@ -1634,8 +1675,8 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (out_insnp->expr.X_op == O_constant && (out_insnp->expr.X_add_number < 0 || out_insnp->expr.X_add_number > 15)) - as_bad (_("Immediate value not in 4 bit unsigned range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 4 bit unsigned range: %ld"), + &out_insnp->expr.X_add_number); out_insnp->reloc = BFD_RELOC_CRIS_UNSIGNED_4; continue; @@ -1686,8 +1727,9 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (out_insnp->expr.X_op == O_constant && (out_insnp->expr.X_add_number < -32 || out_insnp->expr.X_add_number > 31)) - as_bad (_("Immediate value not in 6 bit range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 6 bit range: %ld"), + &out_insnp->expr.X_add_number); + out_insnp->reloc = BFD_RELOC_CRIS_SIGNED_6; continue; } @@ -1701,8 +1743,9 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (out_insnp->expr.X_op == O_constant && (out_insnp->expr.X_add_number < 0 || out_insnp->expr.X_add_number > 63)) - as_bad (_("Immediate value not in 6 bit unsigned range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 6 bit unsigned range: %ld"), + &out_insnp->expr.X_add_number); + out_insnp->reloc = BFD_RELOC_CRIS_UNSIGNED_6; continue; } @@ -1769,7 +1812,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp) out_insnp->opcode |= regno << 12; out_insnp->reloc = BFD_RELOC_CRIS_SIGNED_8; continue; - + case 'O': /* A BDAP expression for any size, "expr,R". */ if (! cris_get_expression (&s, &prefixp->expr)) @@ -1805,7 +1848,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp) pseudo yet, so some of this is just unused framework. */ if (out_insnp->spec_reg->warning) - as_warn (out_insnp->spec_reg->warning); + as_warn ("%s", out_insnp->spec_reg->warning); else if (out_insnp->spec_reg->applicable_version == cris_ver_warning) /* Others have a generic warning. */ @@ -1875,7 +1918,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp) whether or not this is autoincrement mode. */ out_insnp->opcode |= (mode << 10); - /* If there was a PIC reloc specifier, then it was + /* If there was a reloc specifier, then it was attached to the prefix. Note that we can't check that the reloc size matches, since we don't have all the operands yet in all cases. */ @@ -1889,8 +1932,8 @@ cris_process_instruction (insn_text, out_insnp, prefixp) case 'N': case 'Y': - /* Like 's', but immediate operand only. Also does not - modify insn. There are no insns where a PIC reloc + /* Like 's', but immediate operand only. Also do not + modify insn. There are no insns where an explicit reloc specifier makes sense. */ if (cris_get_expression (&s, &out_insnp->expr)) { @@ -1913,9 +1956,10 @@ cris_process_instruction (insn_text, out_insnp, prefixp) relocation. */ out_insnp->expr.X_add_number += 6; - if (pic && *s == PIC_SUFFIX_CHAR) - cris_get_pic_suffix (&s, &out_insnp->reloc, - &out_insnp->expr); + /* TLS specifiers do not make sense here. */ + if (pic && *s == RELOC_SUFFIX_CHAR) + cris_get_reloc_suffix (&s, &out_insnp->reloc, + &out_insnp->expr); continue; } @@ -2093,8 +2137,8 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (out_insnp->expr.X_op == O_constant && (out_insnp->expr.X_add_number < -128 || out_insnp->expr.X_add_number > 255)) - as_bad (_("Immediate value not in 8 bit range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 8 bit range: %ld"), + &out_insnp->expr.X_add_number); /* Fall through. */ case 2: /* FIXME: We need an indicator in the instruction @@ -2103,8 +2147,8 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (out_insnp->expr.X_op == O_constant && (out_insnp->expr.X_add_number < -32768 || out_insnp->expr.X_add_number > 65535)) - as_bad (_("Immediate value not in 16 bit range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 16 bit range: %ld"), + &out_insnp->expr.X_add_number); out_insnp->imm_oprnd_size = 2; break; @@ -2133,18 +2177,18 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (instruction->imm_oprnd_size == SIZE_FIELD && (out_insnp->expr.X_add_number < -128 || out_insnp->expr.X_add_number > 255)) - as_bad (_("Immediate value not in 8 bit range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 8 bit range: %ld"), + &out_insnp->expr.X_add_number); else if (instruction->imm_oprnd_size == SIZE_FIELD_SIGNED && (out_insnp->expr.X_add_number < -128 || out_insnp->expr.X_add_number > 127)) - as_bad (_("Immediate value not in 8 bit signed range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 8 bit signed range: %ld"), + &out_insnp->expr.X_add_number); else if (instruction->imm_oprnd_size == SIZE_FIELD_UNSIGNED && (out_insnp->expr.X_add_number < 0 || out_insnp->expr.X_add_number > 255)) - as_bad (_("Immediate value not in 8 bit unsigned range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 8 bit unsigned range: %ld"), + &out_insnp->expr.X_add_number); } /* Fall through. */ @@ -2154,18 +2198,18 @@ cris_process_instruction (insn_text, out_insnp, prefixp) if (instruction->imm_oprnd_size == SIZE_FIELD && (out_insnp->expr.X_add_number < -32768 || out_insnp->expr.X_add_number > 65535)) - as_bad (_("Immediate value not in 16 bit range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 16 bit range: %ld"), + &out_insnp->expr.X_add_number); else if (instruction->imm_oprnd_size == SIZE_FIELD_SIGNED && (out_insnp->expr.X_add_number < -32768 || out_insnp->expr.X_add_number > 32767)) - as_bad (_("Immediate value not in 16 bit signed range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 16 bit signed range: %ld"), + &out_insnp->expr.X_add_number); else if (instruction->imm_oprnd_size == SIZE_FIELD_UNSIGNED && (out_insnp->expr.X_add_number < 0 || out_insnp->expr.X_add_number > 65535)) - as_bad (_("Immediate value not in 16 bit unsigned range: %ld"), - out_insnp->expr.X_add_number); + cris_bad (_("Immediate value not in 16 bit unsigned range: %ld"), + &out_insnp->expr.X_add_number); } out_insnp->imm_oprnd_size = 2; break; @@ -2180,13 +2224,18 @@ cris_process_instruction (insn_text, out_insnp, prefixp) } /* If there was a relocation specified for the immediate - expression (i.e. it had a PIC modifier) check that the - size of the PIC relocation matches the size specified by + expression (i.e. it had a PIC or TLS modifier) check that the + size of the relocation matches the size specified by the opcode. */ if (out_insnp->reloc != BFD_RELOC_NONE - && (cris_get_pic_reloc_size (out_insnp->reloc) + && (cris_get_specified_reloc_size (out_insnp->reloc) != (unsigned int) out_insnp->imm_oprnd_size)) - as_bad (_("PIC relocation size does not match operand size")); + as_bad (out_insnp->reloc == BFD_RELOC_CRIS_32_GD + || out_insnp->reloc == BFD_RELOC_CRIS_32_TPREL + || out_insnp->reloc == BFD_RELOC_CRIS_16_TPREL + || out_insnp->reloc == BFD_RELOC_CRIS_32_IE + ? _("TLS relocation size does not match operand size") + : _("PIC relocation size does not match operand size")); } else if (instruction->op == cris_muls_op || instruction->op == cris_mulu_op) @@ -2210,9 +2259,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp) Return 1 iff a correct size modifier is found, else 0. */ static int -get_bwd_size_modifier (cPP, size_bitsp) - char **cPP; - int *size_bitsp; +get_bwd_size_modifier (char **cPP, int *size_bitsp) { if (**cPP != '.') return 0; @@ -2262,9 +2309,7 @@ get_bwd_size_modifier (cPP, size_bitsp) Return 1 iff a correct size modifier is found, else 0. */ static int -get_bw_size_modifier (cPP, size_bitsp) - char **cPP; - int *size_bitsp; +get_bw_size_modifier (char **cPP, int *size_bitsp) { if (**cPP != '.') return 0; @@ -2309,9 +2354,7 @@ get_bw_size_modifier (cPP, size_bitsp) else 0. */ static int -get_gen_reg (cPP, regnop) - char **cPP; - int *regnop; +get_gen_reg (char **cPP, int *regnop) { char *oldp; oldp = *cPP; @@ -2434,9 +2477,7 @@ get_gen_reg (cPP, regnop) Return 1 iff a correct special register name is found. */ static int -get_spec_reg (cPP, sregpp) - char **cPP; - const struct cris_spec_reg **sregpp; +get_spec_reg (char **cPP, const struct cris_spec_reg **sregpp) { char *s1; const char *s2; @@ -2494,9 +2535,7 @@ get_spec_reg (cPP, sregpp) Return 1 iff a correct support-register name is found. */ static int -get_sup_reg (cPP, regnop) - char **cPP; - int *regnop; +get_sup_reg (char **cPP, int *regnop) { char *s1; const char *s2; @@ -2565,14 +2604,9 @@ get_sup_reg (cPP, regnop) Return 1 iff a correct indirect operand is found. */ static int -get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, - imm_foundp, imm_exprP) - char **cPP; - struct cris_prefix *prefixp; - int *is_autoincp; - int *src_regnop; - int *imm_foundp; - expressionS *imm_exprP; +get_autoinc_prefix_or_indir_op (char **cPP, struct cris_prefix *prefixp, + int *is_autoincp, int *src_regnop, + int *imm_foundp, expressionS *imm_exprP) { /* Assume there was no immediate mode expression. */ *imm_foundp = 0; @@ -2716,8 +2750,8 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, /* We tentatively put an opcode corresponding to a 32-bit operand here, although it may be - relaxed when there's no PIC specifier for the - operand. */ + relaxed when there's no relocation + specifier for the operand. */ prefixp->opcode = (BDAP_INDIR_OPCODE | (prefixp->base_reg_number << 12) @@ -2727,18 +2761,18 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, /* This can have a PIC suffix, specifying reloc type to use. */ - if (pic && **cPP == PIC_SUFFIX_CHAR) + if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR) { unsigned int relocsize; - cris_get_pic_suffix (cPP, &prefixp->reloc, - &prefixp->expr); + cris_get_reloc_suffix (cPP, &prefixp->reloc, + &prefixp->expr); /* Tweak the size of the immediate operand in the prefix opcode if it isn't what we set. */ relocsize - = cris_get_pic_reloc_size (prefixp->reloc); + = cris_get_specified_reloc_size (prefixp->reloc); if (relocsize != 4) prefixp->opcode = ((prefixp->opcode & ~(3 << 4)) @@ -2764,8 +2798,9 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, in the blanks and break out to match the final ']'. - Note that we don't allow a PIC suffix for an - operand with a minus sign. */ + Note that we don't allow a relocation + suffix for an operand with a minus + sign. */ prefixp->kind = PREFIX_BDAP_IMM; break; } @@ -2803,8 +2838,8 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, /* This can have a PIC suffix, specifying reloc type to use. The caller must check that the reloc size matches the operand size. */ - if (pic && **cPP == PIC_SUFFIX_CHAR) - cris_get_pic_suffix (cPP, &prefixp->reloc, imm_exprP); + if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR) + cris_get_reloc_suffix (cPP, &prefixp->reloc, imm_exprP); return 1; } @@ -2827,9 +2862,7 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, Returns 1 iff a correct indirect operand is found. */ static int -get_3op_or_dip_prefix_op (cPP, prefixp) - char **cPP; - struct cris_prefix *prefixp; +get_3op_or_dip_prefix_op (char **cPP, struct cris_prefix *prefixp) { int reg_number; @@ -2974,15 +3007,15 @@ get_3op_or_dip_prefix_op (cPP, prefixp) | REG_PC /* << 0 */); /* This can have a PIC suffix, specifying reloc type to use. */ - if (pic && **cPP == PIC_SUFFIX_CHAR) + if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR) { unsigned int relocsize; - cris_get_pic_suffix (cPP, &prefixp->reloc, &prefixp->expr); + cris_get_reloc_suffix (cPP, &prefixp->reloc, &prefixp->expr); /* Tweak the size of the immediate operand in the prefix opcode if it isn't what we set. */ - relocsize = cris_get_pic_reloc_size (prefixp->reloc); + relocsize = cris_get_specified_reloc_size (prefixp->reloc); if (relocsize != 4) prefixp->opcode = ((prefixp->opcode & ~(3 << 4)) @@ -3038,6 +3071,10 @@ get_3op_or_dip_prefix_op (cPP, prefixp) prefixp->kind = PREFIX_DIP; prefixp->opcode = DIP_OPCODE | (AUTOINCR_BIT << 8) | REG_PC; prefixp->reloc = BFD_RELOC_32; + + /* For :GD and :IE, it makes sense to have TLS specifiers here. */ + if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR) + cris_get_reloc_suffix (cPP, &prefixp->reloc, &prefixp->expr); } else /* Neither '[' nor register nor expression. We lose. */ @@ -3065,12 +3102,9 @@ get_3op_or_dip_prefix_op (cPP, prefixp) Return 1 iff a correct expression is found. */ static int -cris_get_expression (cPP, exprP) - char **cPP; - expressionS *exprP; +cris_get_expression (char **cPP, expressionS *exprP) { char *saved_input_line_pointer; - segT exp; /* The "expression" function expects to find an expression at the global variable input_line_pointer, so we have to save it to give @@ -3089,7 +3123,7 @@ cris_get_expression (cPP, exprP) return 0; } - exp = expression (exprP); + expression (exprP); if (exprP->X_op == O_illegal || exprP->X_op == O_absent) { input_line_pointer = saved_input_line_pointer; @@ -3114,9 +3148,7 @@ cris_get_expression (cPP, exprP) Return 1 iff a correct flags expression is found. */ static int -get_flags (cPP, flagsp) - char **cPP; - int *flagsp; +get_flags (char **cPP, int *flagsp) { for (;;) { @@ -3225,9 +3257,7 @@ get_flags (cPP, flagsp) exprP Pointer to structure containing the offset expression. */ static void -gen_bdap (base_regno, exprP) - int base_regno; - expressionS *exprP; +gen_bdap (int base_regno, expressionS *exprP) { unsigned int opcode; char *opcodep; @@ -3292,8 +3322,7 @@ gen_bdap (base_regno, exprP) offset The displacement value in bytes. */ static int -branch_disp (offset) - int offset; +branch_disp (int offset) { int disp; @@ -3325,13 +3354,8 @@ branch_disp (offset) add_num. */ static void -gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num) - char *opcodep; - char *writep; - fragS *fragP; - symbolS *add_symP; - symbolS *sub_symP; - long int add_num; +gen_cond_branch_32 (char *opcodep, char *writep, fragS *fragP, + symbolS *add_symP, symbolS *sub_symP, long int add_num) { int nop_opcode; int opc_offset; @@ -3343,6 +3367,12 @@ gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num) opc_offset = 10; branch_offset = -2 - 8; } + else if (pic) + { + nop_opcode = NOP_OPCODE; + opc_offset = 10; + branch_offset = -2 - 8; + } else { nop_opcode = NOP_OPCODE; @@ -3381,18 +3411,20 @@ gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num) merged later. */ md_number_to_chars (opcodep, BA_QUICK_OPCODE - + (cris_arch == arch_crisv32 ? 12 : 8), 2); + + (cris_arch == arch_crisv32 ? 12 : (pic ? 10 : 8)), + 2); md_number_to_chars (writep, nop_opcode, 2); /* Then the extended thing, the 32-bit jump insn. opcodep+4: JUMP [PC+] or, in the PIC case, - opcodep+4: ADD [PC+],PC. */ + opcodep+4: MOVE [PC=PC+N],P0. */ md_number_to_chars (writep + 2, cris_arch == arch_crisv32 ? BA_DWORD_OPCODE - : (pic ? ADD_PC_INCR_OPCODE : JUMP_PC_INCR_OPCODE), 2); + : (pic ? MOVE_PC_INCR_OPCODE_PREFIX + : JUMP_PC_INCR_OPCODE), 2); /* We have to fill in the actual value too. opcodep+6: .DWORD @@ -3428,16 +3460,24 @@ gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num) if (cris_arch == arch_crisv32) /* Follow it with a "NOP" for CRISv32. */ md_number_to_chars (writep + 8, NOP_OPCODE_V32, 2); + else if (pic) + /* ...and the rest of the move-opcode for pre-v32 PIC. */ + md_number_to_chars (writep + 8, MOVE_PC_INCR_OPCODE_SUFFIX, 2); } -/* Get the size of an immediate-reloc in bytes. Only valid for PIC - relocs. */ +/* Get the size of an immediate-reloc in bytes. Only valid for + specified relocs (TLS, PIC). */ static unsigned int -cris_get_pic_reloc_size (reloc) - bfd_reloc_code_real_type reloc; +cris_get_specified_reloc_size (bfd_reloc_code_real_type reloc) { - return reloc == BFD_RELOC_CRIS_16_GOTPLT || reloc == BFD_RELOC_CRIS_16_GOT + return + reloc == BFD_RELOC_CRIS_16_GOTPLT + || reloc == BFD_RELOC_CRIS_16_GOT + || reloc == BFD_RELOC_CRIS_16_GOT_GD + || reloc == BFD_RELOC_CRIS_16_DTPREL + || reloc == BFD_RELOC_CRIS_16_GOT_TPREL + || reloc == BFD_RELOC_CRIS_16_TPREL ? 2 : 4; } @@ -3445,10 +3485,8 @@ cris_get_pic_reloc_size (reloc) Adjust *EXPRP with any addend found after the PIC suffix. */ static void -cris_get_pic_suffix (cPP, relocp, exprP) - char **cPP; - bfd_reloc_code_real_type *relocp; - expressionS *exprP; +cris_get_reloc_suffix (char **cPP, bfd_reloc_code_real_type *relocp, + expressionS *exprP) { char *s = *cPP; unsigned int i; @@ -3459,10 +3497,14 @@ cris_get_pic_suffix (cPP, relocp, exprP) const char *const suffix; unsigned int len; bfd_reloc_code_real_type reloc; + bfd_boolean pic_p; + bfd_boolean tls_p; } pic_suffixes[] = { #undef PICMAP -#define PICMAP(s, r) {s, sizeof (s) - 1, r} +#define PICMAP(s, r) {s, sizeof (s) - 1, r, TRUE, FALSE} +#define PICTLSMAP(s, r) {s, sizeof (s) - 1, r, TRUE, TRUE} +#define TLSMAP(s, r) {s, sizeof (s) - 1, r, FALSE, TRUE} /* Keep this in order with longest unambiguous prefix first. */ PICMAP ("GOTPLT16", BFD_RELOC_CRIS_16_GOTPLT), PICMAP ("GOTPLT", BFD_RELOC_CRIS_32_GOTPLT), @@ -3470,7 +3512,17 @@ cris_get_pic_suffix (cPP, relocp, exprP) PICMAP ("PLT", BFD_RELOC_CRIS_32_PLT_PCREL), PICMAP ("GOTOFF", BFD_RELOC_CRIS_32_GOTREL), PICMAP ("GOT16", BFD_RELOC_CRIS_16_GOT), - PICMAP ("GOT", BFD_RELOC_CRIS_32_GOT) + PICMAP ("GOT", BFD_RELOC_CRIS_32_GOT), + PICTLSMAP ("GDGOTREL16", BFD_RELOC_CRIS_16_GOT_GD), + PICTLSMAP ("GDGOTREL", BFD_RELOC_CRIS_32_GOT_GD), + TLSMAP ("GD", BFD_RELOC_CRIS_32_GD), + PICTLSMAP ("DTPREL16", BFD_RELOC_CRIS_16_DTPREL), + PICTLSMAP ("DTPREL", BFD_RELOC_CRIS_32_DTPREL), + TLSMAP ("IE", BFD_RELOC_CRIS_32_IE), + PICTLSMAP ("TPOFFGOT16", BFD_RELOC_CRIS_16_GOT_TPREL), + PICTLSMAP ("TPOFFGOT", BFD_RELOC_CRIS_32_GOT_TPREL), + TLSMAP ("TPOFF16", BFD_RELOC_CRIS_16_TPREL), + TLSMAP ("TPOFF", BFD_RELOC_CRIS_32_TPREL) }; /* We've already seen the ':', so consume it. */ @@ -3479,7 +3531,11 @@ cris_get_pic_suffix (cPP, relocp, exprP) for (i = 0; i < sizeof (pic_suffixes)/sizeof (pic_suffixes[0]); i++) { if (strncmp (s, pic_suffixes[i].suffix, pic_suffixes[i].len) == 0 - && ! is_part_of_name (s[pic_suffixes[i].len])) + && ! is_part_of_name (s[pic_suffixes[i].len]) + /* PIC and non-PIC relocations are exclusive. */ + && (pic != 0) == (pic_suffixes[i].pic_p != 0) + /* But TLS can be active for non-TLS relocations too. */ + && (pic_suffixes[i].tls_p == 0 || tls)) { /* We have a match. Consume the suffix and set the relocation type. */ @@ -3536,10 +3592,8 @@ cris_get_pic_suffix (cPP, relocp, exprP) find out the correct bit patterns and use them. */ char * -md_atof (type, litp, sizep) - char type ATTRIBUTE_UNUSED; - char *litp ATTRIBUTE_UNUSED; - int *sizep ATTRIBUTE_UNUSED; +md_atof (int type ATTRIBUTE_UNUSED, char *litp ATTRIBUTE_UNUSED, + int *sizep ATTRIBUTE_UNUSED) { /* FIXME: Is this function mentioned in the internals.texi manual? If not, add it. */ @@ -3562,12 +3616,7 @@ md_atof (type, litp, sizep) seg The segment containing this number. */ static void -cris_number_to_imm (bufp, val, n, fixP, seg) - char *bufp; - long val; - int n; - fixS *fixP; - segT seg; +cris_number_to_imm (char *bufp, long val, int n, fixS *fixP, segT seg) { segT sym_seg; @@ -3594,10 +3643,12 @@ cris_number_to_imm (bufp, val, n, fixP, seg) ; } - /* Only do this for old-arch binaries. */ + /* Only use the computed value for old-arch binaries. For all + others, where we're going to output a relocation, put 0 in the + code. */ if (cris_arch != arch_cris_any_v0_v10 && (fixP->fx_addsy != NULL || fixP->fx_pcrel)) - return; + val = 0; switch (fixP->fx_r_type) { @@ -3606,6 +3657,22 @@ cris_number_to_imm (bufp, val, n, fixP, seg) regression tests on the object file contents. FIXME: Seems uninteresting now that we have a test suite. */ + case BFD_RELOC_CRIS_32_GOT_GD: + case BFD_RELOC_CRIS_16_GOT_GD: + case BFD_RELOC_CRIS_32_GD: + case BFD_RELOC_CRIS_32_IE: + case BFD_RELOC_CRIS_32_DTPREL: + case BFD_RELOC_CRIS_16_DTPREL: + case BFD_RELOC_CRIS_32_GOT_TPREL: + case BFD_RELOC_CRIS_16_GOT_TPREL: + case BFD_RELOC_CRIS_32_TPREL: + case BFD_RELOC_CRIS_16_TPREL: +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) + if (IS_ELF && fixP->fx_addsy != NULL) + S_SET_THREAD_LOCAL (fixP->fx_addsy); +#endif + /* Fall through. */ + case BFD_RELOC_CRIS_16_GOT: case BFD_RELOC_CRIS_32_GOT: case BFD_RELOC_CRIS_32_GOTREL: @@ -3615,13 +3682,14 @@ cris_number_to_imm (bufp, val, n, fixP, seg) case BFD_RELOC_CRIS_32_PLT_PCREL: /* We don't want to put in any kind of non-zero bits in the data being relocated for these. */ + md_number_to_chars (bufp, 0, n); break; case BFD_RELOC_32_PCREL: - /* If this one isn't fully resolved, we don't want to put anything + /* If this one isn't fully resolved, we don't want to put non-zero in the object. */ if (fixP->fx_addsy != NULL || fixP->fx_pcrel) - break; + val = 0; /* Fall through. */ case BFD_RELOC_32: @@ -3643,38 +3711,30 @@ cris_number_to_imm (bufp, val, n, fixP, seg) if (val > 0xffff || val < -32768) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 16 bit range: %ld"), val); - if (! fixP->fx_addsy) - { - bufp[1] = (val >> 8) & 0xFF; - bufp[0] = val & 0xFF; - } + bufp[1] = (val >> 8) & 0xFF; + bufp[0] = val & 0xFF; break; case BFD_RELOC_CRIS_SIGNED_16: if (val > 32767 || val < -32768) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 16 bit signed range: %ld"), val); - if (! fixP->fx_addsy) - { - bufp[1] = (val >> 8) & 0xFF; - bufp[0] = val & 0xFF; - } + bufp[1] = (val >> 8) & 0xFF; + bufp[0] = val & 0xFF; break; case BFD_RELOC_8: case BFD_RELOC_8_PCREL: if (val > 255 || val < -128) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 8 bit range: %ld"), val); - if (! fixP->fx_addsy) - bufp[0] = val & 0xFF; + bufp[0] = val & 0xFF; break; case BFD_RELOC_CRIS_SIGNED_8: if (val > 127 || val < -128) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 8 bit signed range: %ld"), val); - if (! fixP->fx_addsy) - bufp[0] = val & 0xFF; + bufp[0] = val & 0xFF; break; case BFD_RELOC_CRIS_LAPCQ_OFFSET: @@ -3684,37 +3744,32 @@ cris_number_to_imm (bufp, val, n, fixP, seg) if (val > 15 || val < 0) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 4 bit unsigned range: %ld"), val); - if (! fixP->fx_addsy) - bufp[0] |= val & 0x0F; + bufp[0] |= val & 0x0F; break; case BFD_RELOC_CRIS_UNSIGNED_5: if (val > 31 || val < 0) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 5 bit unsigned range: %ld"), val); - if (! fixP->fx_addsy) - bufp[0] |= val & 0x1F; + bufp[0] |= val & 0x1F; break; case BFD_RELOC_CRIS_SIGNED_6: if (val > 31 || val < -32) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 6 bit range: %ld"), val); - if (! fixP->fx_addsy) - bufp[0] |= val & 0x3F; + bufp[0] |= val & 0x3F; break; case BFD_RELOC_CRIS_UNSIGNED_6: if (val > 63 || val < 0) as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 6 bit unsigned range: %ld"), val); - if (! fixP->fx_addsy) - bufp[0] |= val & 0x3F; + bufp[0] |= val & 0x3F; break; case BFD_RELOC_CRIS_BDISP8: - if (! fixP->fx_addsy) - bufp[0] = branch_disp (val); + bufp[0] = branch_disp (val); break; case BFD_RELOC_NONE: @@ -3747,9 +3802,7 @@ cris_number_to_imm (bufp, val, n, fixP, seg) GAS does not understand. */ int -md_parse_option (arg, argp) - int arg; - char *argp ATTRIBUTE_UNUSED; +md_parse_option (int arg, char *argp ATTRIBUTE_UNUSED) { switch (arg) { @@ -3778,7 +3831,13 @@ md_parse_option (arg, argp) break; case OPTION_PIC: + if (OUTPUT_FLAVOR != bfd_target_elf_flavour) + as_bad (_("--pic is invalid for this object format")); pic = TRUE; + if (cris_arch != arch_crisv32) + md_long_jump_size = cris_any_v0_v10_long_jump_size_pic; + else + md_long_jump_size = crisv32_long_jump_size; break; case OPTION_ARCH: @@ -3797,7 +3856,12 @@ md_parse_option (arg, argp) md_long_jump_size = crisv32_long_jump_size; } else - md_long_jump_size = cris_any_v0_v10_long_jump_size; + { + if (pic) + md_long_jump_size = cris_any_v0_v10_long_jump_size_pic; + else + md_long_jump_size = cris_any_v0_v10_long_jump_size; + } } break; @@ -3818,9 +3882,7 @@ md_parse_option (arg, argp) /* Round up a section size to the appropriate boundary. */ valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { /* Round all sects to multiple of 4, except the bss section, which we'll round to word-size. @@ -3848,9 +3910,7 @@ md_section_align (segment, size) /* Generate a machine-dependent relocation. */ arelent * -tc_gen_reloc (section, fixP) - asection *section ATTRIBUTE_UNUSED; - fixS *fixP; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) { arelent *relP; bfd_reloc_code_real_type code; @@ -3881,6 +3941,16 @@ tc_gen_reloc (section, fixP) case BFD_RELOC_CRIS_UNSIGNED_8: case BFD_RELOC_CRIS_UNSIGNED_16: case BFD_RELOC_CRIS_LAPCQ_OFFSET: + case BFD_RELOC_CRIS_32_GOT_GD: + case BFD_RELOC_CRIS_16_GOT_GD: + case BFD_RELOC_CRIS_32_GD: + case BFD_RELOC_CRIS_32_IE: + case BFD_RELOC_CRIS_32_DTPREL: + case BFD_RELOC_CRIS_16_DTPREL: + case BFD_RELOC_CRIS_32_GOT_TPREL: + case BFD_RELOC_CRIS_16_GOT_TPREL: + case BFD_RELOC_CRIS_32_TPREL: + case BFD_RELOC_CRIS_16_TPREL: code = fixP->fx_r_type; break; default: @@ -3890,7 +3960,7 @@ tc_gen_reloc (section, fixP) } relP = (arelent *) xmalloc (sizeof (arelent)); - assert (relP != 0); + gas_assert (relP != 0); relP->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); relP->address = fixP->fx_frag->fr_address + fixP->fx_where; @@ -3944,8 +4014,7 @@ tc_gen_reloc (section, fixP) /* Machine-dependent usage-output. */ void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { /* The messages are formatted to line up with the generic options. */ fprintf (stream, _("CRIS-specific options:\n")); @@ -3961,8 +4030,10 @@ md_show_usage (stream) _(" --no-underscore User symbols do not have any prefix.\n")); fprintf (stream, "%s", _(" Registers will require a `$'-prefix.\n")); +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) fprintf (stream, "%s", _(" --pic Enable generation of position-independent code.\n")); +#endif fprintf (stream, "%s", _(" --march= Generate code for . Valid choices for \n\ are v0_v10, v10, v32 and common_v10_v32.\n")); @@ -3972,10 +4043,7 @@ md_show_usage (stream) enough info to complete immediately) to the data in a frag. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg; +md_apply_fix (fixS *fixP, valueT *valP, segT seg) { /* This assignment truncates upper bits if valueT is 64 bits (as with --enable-64-bit-bfd), which is fine here, though we cast to avoid @@ -4009,8 +4077,7 @@ md_apply_fix3 (fixP, valP, seg) the address of the fixup plus its size. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; @@ -4032,8 +4099,7 @@ md_pcrel_from (fixP) /* We have no need to give defaults for symbol-values. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -4043,8 +4109,7 @@ md_undefined_symbol (name) against section symbols, and guarantees that a relocation will be emitted even when the value can be resolved locally. */ int -md_cris_force_relocation (fixp) - struct fix *fixp; +md_cris_force_relocation (struct fix *fixp) { switch (fixp->fx_r_type) { @@ -4068,9 +4133,7 @@ md_cris_force_relocation (fixp) knows about how to handle broken words. */ void -tc_cris_check_adjusted_broken_word (new_offset, brokwP) - offsetT new_offset; - struct broken_word *brokwP; +tc_cris_check_adjusted_broken_word (offsetT new_offset, struct broken_word *brokwP) { if (new_offset > 32767 || new_offset < -32768) /* We really want a genuine error, not a warning, so make it one. */ @@ -4081,21 +4144,24 @@ tc_cris_check_adjusted_broken_word (new_offset, brokwP) /* Make a leading REGISTER_PREFIX_CHAR mandatory for all registers. */ -static void cris_force_reg_prefix () +static void +cris_force_reg_prefix (void) { demand_register_prefix = TRUE; } /* Do not demand a leading REGISTER_PREFIX_CHAR for all registers. */ -static void cris_relax_reg_prefix () +static void +cris_relax_reg_prefix (void) { demand_register_prefix = FALSE; } /* Adjust for having a leading '_' on all user symbols. */ -static void cris_sym_leading_underscore () +static void +cris_sym_leading_underscore (void) { /* We can't really do anything more than assert that what the program thinks symbol starts with agrees with the command-line options, since @@ -4108,7 +4174,7 @@ static void cris_sym_leading_underscore () /* Adjust for not having any particular prefix on user symbols. */ -static void cris_sym_no_leading_underscore () +static void cris_sym_no_leading_underscore (void) { if (symbols_have_leading_underscore) as_bad (_(".syntax %s requires command-line option `--no-underscore'"), @@ -4119,13 +4185,12 @@ static void cris_sym_no_leading_underscore () syntax the assembly code has. */ static void -s_syntax (ignore) - int ignore ATTRIBUTE_UNUSED; +s_syntax (int ignore ATTRIBUTE_UNUSED) { static const struct syntaxes { const char *const operand; - void (*fn) PARAMS ((void)); + void (*fn) (void); } syntax_table[] = {{SYNTAX_ENFORCE_REG_PREFIX, cris_force_reg_prefix}, {SYNTAX_RELAX_REG_PREFIX, cris_relax_reg_prefix}, @@ -4156,8 +4221,7 @@ s_syntax (ignore) not emitting ELF. */ static void -s_cris_file (dummy) - int dummy; +s_cris_file (int dummy) { if (OUTPUT_FLAVOR != bfd_target_elf_flavour) as_bad (_("Pseudodirective .file is only valid when generating ELF")); @@ -4169,8 +4233,7 @@ s_cris_file (dummy) emitting ELF. */ static void -s_cris_loc (dummy) - int dummy; +s_cris_loc (int dummy) { if (OUTPUT_FLAVOR != bfd_target_elf_flavour) as_bad (_("Pseudodirective .loc is only valid when generating ELF")); @@ -4178,14 +4241,37 @@ s_cris_loc (dummy) dwarf2_directive_loc (dummy); } +/* Worker for .dtpoffd: generate a R_CRIS_32_DTPREL reloc, as for + expr:DTPREL but for use in debug info. */ + +static void +s_cris_dtpoff (int bytes) +{ + expressionS ex; + char *p; + + if (bytes != 4) + as_fatal (_("internal inconsistency problem: %s called for %d bytes"), + __FUNCTION__, bytes); + + expression (&ex); + + p = frag_more (bytes); + md_number_to_chars (p, 0, bytes); + fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE, + BFD_RELOC_CRIS_32_DTPREL); + + demand_empty_rest_of_line (); +} + + /* Translate a string (as common to --march= and .arch ) into an enum. If the string *STR is recognized, *STR is updated to point to the end of the string. If the string is not recognized, arch_cris_unknown is returned. */ static enum cris_archs -cris_arch_from_string (str) - char **str; +cris_arch_from_string (char **str) { static const struct cris_arch_struct { @@ -4222,9 +4308,8 @@ cris_arch_from_string (str) IVER. */ static int -cris_insn_ver_valid_for_arch (iver, arch) - enum cris_insn_version_usage iver; - enum cris_archs arch; +cris_insn_ver_valid_for_arch (enum cris_insn_version_usage iver, + enum cris_archs arch) { switch (arch) { @@ -4242,7 +4327,7 @@ cris_insn_ver_valid_for_arch (iver, arch) || iver == cris_ver_v8_10 || iver == cris_ver_v10 || iver == cris_ver_v10p); - + case arch_crisv32: return (iver == cris_ver_version_all @@ -4306,8 +4391,7 @@ cris_insn_ver_valid_for_arch (iver, arch) default --march= option. */ static void -s_cris_arch (dummy) - int dummy ATTRIBUTE_UNUSED; +s_cris_arch (int dummy ATTRIBUTE_UNUSED) { /* Right now we take the easy route and check for sameness. It's not obvious that allowing e.g. --march=v32 and .arch common_v0_v32