X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-m32c.c;h=b28797b38e3f7cd33b3a254498f614f1dfac7f00;hb=eb408eaac923140f561d8307cb63da9c9550096a;hp=cb589ac17a80bac195f5a3efc76a6a051f84e792;hpb=6b73c529e04e27601eb1183d2a5be8e955053100;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-m32c.c b/gas/config/tc-m32c.c index cb589ac17a..b28797b38e 100644 --- a/gas/config/tc-m32c.c +++ b/gas/config/tc-m32c.c @@ -1,12 +1,12 @@ /* tc-m32c.c -- Assembler for the Renesas M32C. - Copyright (C) 2005 Free Software Foundation. + Copyright (C) 2005-2016 Free Software Foundation, Inc. Contributed by RedHat. 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) + 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,9 +19,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include #include "as.h" -#include "subsegs.h" +#include "subsegs.h" #include "symcat.h" #include "opcodes/m32c-desc.h" #include "opcodes/m32c-opc.h" @@ -29,7 +28,6 @@ #include "elf/common.h" #include "elf/m32c.h" #include "libbfd.h" -#include "libiberty.h" #include "safe-ctype.h" /* Structure to hold all of the different components @@ -54,6 +52,9 @@ typedef struct } m32c_insn; +#define rl_for(_insn) (CGEN_ATTR_CGEN_INSN_RL_TYPE_VALUE (&((_insn).insn->base->attrs))) +#define relaxable(_insn) (CGEN_ATTR_CGEN_INSN_RELAXABLE_VALUE (&((_insn).insn->base->attrs))) + const char comment_chars[] = ";"; const char line_comment_chars[] = "#"; const char line_separator_chars[] = "|"; @@ -66,11 +67,15 @@ const char * md_shortopts = M32C_SHORTOPTS; /* assembler options */ #define OPTION_CPU_M16C (OPTION_MD_BASE) #define OPTION_CPU_M32C (OPTION_MD_BASE + 1) +#define OPTION_LINKRELAX (OPTION_MD_BASE + 2) +#define OPTION_H_TICK_HEX (OPTION_MD_BASE + 3) struct option md_longopts[] = { { "m16c", no_argument, NULL, OPTION_CPU_M16C }, { "m32c", no_argument, NULL, OPTION_CPU_M32C }, + { "relax", no_argument, NULL, OPTION_LINKRELAX }, + { "h-tick-hex", no_argument, NULL, OPTION_H_TICK_HEX }, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -83,22 +88,24 @@ size_t md_longopts_size = sizeof (md_longopts); static unsigned long m32c_mach = bfd_mach_m16c; static int cpu_mach = (1 << MACH_M16C); static int insn_size; +static int m32c_relax = 0; /* Flags to set in the elf header */ static flagword m32c_flags = DEFAULT_FLAGS; -static unsigned int m32c_isa = (1 << ISA_M16C); +static char default_isa = 1 << (7 - ISA_M16C); +static CGEN_BITSET m32c_isa = {1, & default_isa}; static void set_isa (enum isa_attr isa_num) { - m32c_isa = (1 << isa_num); + cgen_bitset_set (& m32c_isa, isa_num); } static void s_bss (int); int -md_parse_option (int c, char * arg ATTRIBUTE_UNUSED) +md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED) { switch (c) { @@ -116,6 +123,14 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED) set_isa (ISA_M32C); break; + case OPTION_LINKRELAX: + m32c_relax = 1; + break; + + case OPTION_H_TICK_HEX: + enable_h_tick_hex = 1; + break; + default: return 0; } @@ -126,7 +141,7 @@ void md_show_usage (FILE * stream) { fprintf (stream, _(" M32C specific command line options:\n")); -} +} static void s_bss (int ignore ATTRIBUTE_UNUSED) @@ -142,6 +157,7 @@ s_bss (int ignore ATTRIBUTE_UNUSED) const pseudo_typeS md_pseudo_table[] = { { "bss", s_bss, 0}, + { "3byte", cons, 3 }, { "word", cons, 4 }, { NULL, NULL, 0 } }; @@ -151,12 +167,12 @@ void md_begin (void) { /* Initialize the `cgen' interface. */ - + /* Set the machine number and endian. */ gas_cgen_cpu_desc = m32c_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach, CGEN_CPU_OPEN_ENDIAN, CGEN_ENDIAN_BIG, - CGEN_CPU_OPEN_ISAS, m32c_isa, + CGEN_CPU_OPEN_ISAS, & m32c_isa, CGEN_CPU_OPEN_END); m32c_cgen_init_asm (gas_cgen_cpu_desc); @@ -179,10 +195,13 @@ m32c_md_end (void) { int i, n_nops; - /* Pad with nops for objdump. */ - n_nops = (32 - ((insn_size) % 32)) / 8; - for (i = 1; i <= n_nops; i++) - md_assemble ("nop"); + if (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) + { + /* Pad with nops for objdump. */ + n_nops = (32 - ((insn_size) % 32)) / 8; + for (i = 1; i <= n_nops; i++) + md_assemble ((char *) "nop"); + } } void @@ -242,21 +261,21 @@ m32c_indirect_operand (char *str) if (s[0] == '[' && s[1] == '[') indirection[operand] = relative; } - + if (indirection[1] == none && indirection[2] == none) return FALSE; - + operand = 1; ns_len = strlen (str); - new_str = (char*) xmalloc (ns_len); + new_str = XNEWVEC (char, ns_len); ns = new_str; ns_end = ns + ns_len; - + for (s = str; *s; s++) { if (s[0] == ',') operand = 2; - + if (s[0] == '[' && ! brace_n[operand]) { brace_n[operand] += 1; @@ -264,7 +283,7 @@ m32c_indirect_operand (char *str) if (indirection[operand] != none) continue; } - + else if (s[0] == '[' && brace_n[operand]) { brace_n[operand] += 1; @@ -296,13 +315,13 @@ m32c_indirect_operand (char *str) { fprintf (stderr, "Unmatched [[operand-%d]] %d\n", operand, brace_n[operand]); } - + if (indirection[1] != none && indirection[2] != none) - md_assemble ("src-dest-indirect"); + md_assemble ((char *) "src-dest-indirect"); else if (indirection[1] != none) - md_assemble ("src-indirect"); + md_assemble ((char *) "src-indirect"); else if (indirection[2] != none) - md_assemble ("dest-indirect"); + md_assemble ((char *) "dest-indirect"); md_assemble (new_str); free (new_str); @@ -315,6 +334,8 @@ md_assemble (char * str) static int last_insn_had_delay_slot = 0; m32c_insn insn; char * errmsg; + finished_insnS results; + int rl_type; if (m32c_mach == bfd_mach_m32c && m32c_indirect_operand (str)) return; @@ -324,26 +345,60 @@ md_assemble (char * str) insn.insn = m32c_cgen_assemble_insn (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg); - + if (!insn.insn) { as_bad ("%s", errmsg); return; } + results.num_fixups = 0; /* Doesn't really matter what we pass for RELAX_P here. */ gas_cgen_finish_insn (insn.insn, insn.buffer, - CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL); + CGEN_FIELDS_BITSIZE (& insn.fields), 1, &results); last_insn_had_delay_slot = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT); + (void) last_insn_had_delay_slot; insn_size = CGEN_INSN_BITSIZE(insn.insn); + + rl_type = rl_for (insn); + + /* We have to mark all the jumps, because we need to adjust them + when we delete bytes, but we only need to mark the displacements + if they're symbolic - if they're not, we've already picked the + shortest opcode by now. The linker, however, will still have to + check any operands to see if they're the displacement type, since + we don't know (nor record) *which* operands are relaxable. */ + if (m32c_relax + && rl_type != RL_TYPE_NONE + && (rl_type == RL_TYPE_JUMP || results.num_fixups) + && !relaxable (insn)) + { + int reloc = 0; + int addend = results.num_fixups + 16 * insn_size/8; + + switch (rl_for (insn)) + { + case RL_TYPE_JUMP: reloc = BFD_RELOC_M32C_RL_JUMP; break; + case RL_TYPE_1ADDR: reloc = BFD_RELOC_M32C_RL_1ADDR; break; + case RL_TYPE_2ADDR: reloc = BFD_RELOC_M32C_RL_2ADDR; break; + } + if (insn.insn->base->num == M32C_INSN_JMP16_S + || insn.insn->base->num == M32C_INSN_JMP32_S) + addend = 0x10; + + fix_new (results.frag, + results.addr - results.frag->fr_literal, + 0, abs_section_sym, addend, 0, + reloc); + } } /* The syntax in the manual says constants begin with '#'. We just ignore it. */ -void +void md_operand (expressionS * exp) { /* In case of a syntax error, escape back to try next syntax combo. */ @@ -355,7 +410,7 @@ valueT md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); - return ((size + (1 << align) - 1) & (-1 << align)); + return ((size + (1 << align) - 1) & -(1 << align)); } symbolS * @@ -395,7 +450,17 @@ const relax_typeS md_relax_table[] = /* 15 */ { 8, 1, 1, 16 }, /* jmp32.s */ /* 16 */ { 127, -128, 2, 17 }, /* jmp32.b */ /* 17 */ { 32767, -32768, 3, 18 }, /* jmp32.w */ - /* 18 */ { 0, 0, 4, 0 } /* jmp32.a */ + /* 18 */ { 0, 0, 4, 0 }, /* jmp32.a */ + + /* 19 */ { 32767, -32768, 3, 20 }, /* jsr16.w */ + /* 20 */ { 0, 0, 4, 0 }, /* jsr16.a */ + /* 21 */ { 32767, -32768, 3, 11 }, /* jsr32.w */ + /* 22 */ { 0, 0, 4, 0 }, /* jsr32.a */ + + /* 23 */ { 0, 0, 3, 0 }, /* adjnz pc8 */ + /* 24 */ { 0, 0, 4, 0 }, /* adjnz disp8 pc8 */ + /* 25 */ { 0, 0, 5, 0 }, /* adjnz disp16 pc8 */ + /* 26 */ { 0, 0, 6, 0 } /* adjnz disp24 pc8 */ }; enum { @@ -405,7 +470,12 @@ enum { M32C_MACRO_JCND16_A, M32C_MACRO_JCND32_W, M32C_MACRO_JCND32_A, -} M32C_Macros; + /* the digit is the array index of the pcrel byte */ + M32C_MACRO_ADJNZ_2, + M32C_MACRO_ADJNZ_3, + M32C_MACRO_ADJNZ_4, + M32C_MACRO_ADJNZ_5, +}; static struct { int insn; @@ -436,7 +506,17 @@ static struct { /* 15 */ { M32C_INSN_JMP32_S, 1, M32C_INSN_JMP32_A, 0 }, /* 16 */ { M32C_INSN_JMP32_B, 2, M32C_INSN_JMP32_A, 1 }, /* 17 */ { M32C_INSN_JMP32_W, 3, M32C_INSN_JMP32_A, 2 }, - /* 18 */ { M32C_INSN_JMP32_A, 4, M32C_INSN_JMP32_A, 0 } + /* 18 */ { M32C_INSN_JMP32_A, 4, M32C_INSN_JMP32_A, 0 }, + + /* 19 */ { M32C_INSN_JSR16_W, 3, M32C_INSN_JSR16_A, 2 }, + /* 20 */ { M32C_INSN_JSR16_A, 4, M32C_INSN_JSR16_A, 0 }, + /* 21 */ { M32C_INSN_JSR32_W, 3, M32C_INSN_JSR32_A, 2 }, + /* 22 */ { M32C_INSN_JSR32_A, 4, M32C_INSN_JSR32_A, 0 }, + + /* 23 */ { -M32C_MACRO_ADJNZ_2, 3, -M32C_MACRO_ADJNZ_2, 0 }, + /* 24 */ { -M32C_MACRO_ADJNZ_3, 4, -M32C_MACRO_ADJNZ_3, 0 }, + /* 25 */ { -M32C_MACRO_ADJNZ_4, 5, -M32C_MACRO_ADJNZ_4, 0 }, + /* 26 */ { -M32C_MACRO_ADJNZ_5, 6, -M32C_MACRO_ADJNZ_5, 0 } }; #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0])) @@ -451,11 +531,21 @@ m32c_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state) } static int -insn_to_subtype (int insn) +insn_to_subtype (int inum, const CGEN_INSN *insn) { unsigned int i; + + if (insn + && (strncmp (insn->base->mnemonic, "adjnz", 5) == 0 + || strncmp (insn->base->mnemonic, "sbjnz", 5) == 0)) + { + i = 23 + insn->base->bitsize/8 - 3; + /*printf("mapping %d used for %s\n", i, insn->base->mnemonic);*/ + return i; + } + for (i=0; ifr_opcode - fragP->fr_literal; if (fragP->fr_subtype == 1) - fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num); + fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num, fragP->fr_cgen.insn); if (S_GET_SEGMENT (fragP->fr_symbol) != segment) { int new_insn; new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern; - fragP->fr_subtype = insn_to_subtype (new_insn); + fragP->fr_subtype = insn_to_subtype (new_insn, 0); } if (fragP->fr_cgen.insn->base @@ -505,7 +595,7 @@ md_estimate_size_before_relax (fragS * fragP, segT segment ATTRIBUTE_UNUSED) } return subtype_mappings[fragP->fr_subtype].bytes - (fragP->fr_fix - where); -} +} /* *fragP has been relaxed to its final size, and now needs to have the bytes inside it modified to conform to the new size. @@ -534,12 +624,12 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, { int addend; int operand; - int new_insn; int where = fragP->fr_opcode - fragP->fr_literal; + int rl_where = fragP->fr_opcode - fragP->fr_literal; unsigned char *op = (unsigned char *)fragP->fr_opcode; + int rl_addend = 0; addend = target_address_for (fragP) - (fragP->fr_address + where); - new_insn = subtype_mappings[fragP->fr_subtype].insn; fragP->fr_fix = where + subtype_mappings[fragP->fr_subtype].bytes; @@ -548,6 +638,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, case M32C_INSN_JCND16_5: op[1] = addend - 1; operand = M32C_OPERAND_LAB_8_8; + rl_addend = 0x21; break; case -M32C_MACRO_JCND16_5_W: @@ -558,7 +649,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[4] = (addend - 3) >> 8; operand = M32C_OPERAND_LAB_8_16; where += 2; - new_insn = M32C_INSN_JMP16_W; + rl_addend = 0x51; break; case -M32C_MACRO_JCND16_5_A: @@ -567,13 +658,14 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[2] = 0xfc; operand = M32C_OPERAND_LAB_8_24; where += 2; - new_insn = M32C_INSN_JMP16_A; + rl_addend = 0x61; break; case M32C_INSN_JCND16: op[2] = addend - 2; operand = M32C_OPERAND_LAB_16_8; + rl_addend = 0x31; break; case -M32C_MACRO_JCND16_W: @@ -584,7 +676,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[5] = (addend - 4) >> 8; operand = M32C_OPERAND_LAB_8_16; where += 3; - new_insn = M32C_INSN_JMP16_W; + rl_addend = 0x61; break; case -M32C_MACRO_JCND16_A: @@ -593,18 +685,20 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[3] = 0xfc; operand = M32C_OPERAND_LAB_8_24; where += 3; - new_insn = M32C_INSN_JMP16_A; + rl_addend = 0x71; break; case M32C_INSN_JMP16_S: op[0] = 0x60 | ((addend-2) & 0x07); operand = M32C_OPERAND_LAB_5_3; + rl_addend = 0x10; break; case M32C_INSN_JMP16_B: op[0] = 0xfe; op[1] = addend - 1; operand = M32C_OPERAND_LAB_8_8; + rl_addend = 0x21; break; case M32C_INSN_JMP16_W: @@ -612,6 +706,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[1] = addend - 1; op[2] = (addend - 1) >> 8; operand = M32C_OPERAND_LAB_8_16; + rl_addend = 0x31; break; case M32C_INSN_JMP16_A: @@ -620,11 +715,13 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[2] = 0; op[3] = 0; operand = M32C_OPERAND_LAB_8_24; + rl_addend = 0x41; break; case M32C_INSN_JCND32: op[1] = addend - 1; operand = M32C_OPERAND_LAB_8_8; + rl_addend = 0x21; break; case -M32C_MACRO_JCND32_W: @@ -635,7 +732,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[4] = (addend - 3) >> 8; operand = M32C_OPERAND_LAB_8_16; where += 2; - new_insn = M32C_INSN_JMP32_W; + rl_addend = 0x51; break; case -M32C_MACRO_JCND32_A: @@ -644,21 +741,21 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[2] = 0xcc; operand = M32C_OPERAND_LAB_8_24; where += 2; - new_insn = M32C_INSN_JMP32_A; + rl_addend = 0x61; break; - - case M32C_INSN_JMP32_S: addend = ((addend-2) & 0x07); op[0] = 0x4a | (addend & 0x01) | ((addend << 3) & 0x30); operand = M32C_OPERAND_LAB32_JMP_S; + rl_addend = 0x10; break; case M32C_INSN_JMP32_B: op[0] = 0xbb; op[1] = addend - 1; operand = M32C_OPERAND_LAB_8_8; + rl_addend = 0x21; break; case M32C_INSN_JMP32_W: @@ -666,6 +763,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[1] = addend - 1; op[2] = (addend - 1) >> 8; operand = M32C_OPERAND_LAB_8_16; + rl_addend = 0x31; break; case M32C_INSN_JMP32_A: @@ -674,8 +772,64 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, op[2] = 0; op[3] = 0; operand = M32C_OPERAND_LAB_8_24; + rl_addend = 0x41; + break; + + + case M32C_INSN_JSR16_W: + op[0] = 0xf5; + op[1] = addend - 1; + op[2] = (addend - 1) >> 8; + operand = M32C_OPERAND_LAB_8_16; + rl_addend = 0x31; break; + case M32C_INSN_JSR16_A: + op[0] = 0xfd; + op[1] = 0; + op[2] = 0; + op[3] = 0; + operand = M32C_OPERAND_LAB_8_24; + rl_addend = 0x41; + break; + + case M32C_INSN_JSR32_W: + op[0] = 0xcf; + op[1] = addend - 1; + op[2] = (addend - 1) >> 8; + operand = M32C_OPERAND_LAB_8_16; + rl_addend = 0x31; + break; + + case M32C_INSN_JSR32_A: + op[0] = 0xcd; + op[1] = 0; + op[2] = 0; + op[3] = 0; + operand = M32C_OPERAND_LAB_8_24; + rl_addend = 0x41; + break; + + case -M32C_MACRO_ADJNZ_2: + rl_addend = 0x31; + op[2] = addend - 2; + operand = M32C_OPERAND_LAB_16_8; + break; + case -M32C_MACRO_ADJNZ_3: + rl_addend = 0x41; + op[3] = addend - 2; + operand = M32C_OPERAND_LAB_24_8; + break; + case -M32C_MACRO_ADJNZ_4: + rl_addend = 0x51; + op[4] = addend - 2; + operand = M32C_OPERAND_LAB_32_8; + break; + case -M32C_MACRO_ADJNZ_5: + rl_addend = 0x61; + op[5] = addend - 2; + operand = M32C_OPERAND_LAB_40_8; + break; default: printf("\nHey! Need more opcode converters! missing: %d %s\n\n", @@ -684,10 +838,23 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, abort(); } + if (m32c_relax) + { + if (operand != M32C_OPERAND_LAB_8_24) + fragP->fr_offset = (fragP->fr_address + where); + + fix_new (fragP, + rl_where, + 0, abs_section_sym, rl_addend, 0, + BFD_RELOC_M32C_RL_JUMP); + } + if (S_GET_SEGMENT (fragP->fr_symbol) != sec - || operand == M32C_OPERAND_LAB_8_24) + || operand == M32C_OPERAND_LAB_8_24 + || (m32c_relax && (operand != M32C_OPERAND_LAB_5_3 + && operand != M32C_OPERAND_LAB32_JMP_S))) { - assert (fragP->fr_cgen.insn != 0); + gas_assert (fragP->fr_cgen.insn != 0); gas_cgen_record_fixup (fragP, where, fragP->fr_cgen.insn, @@ -695,7 +862,8 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, cgen_operand_lookup_by_num (gas_cgen_cpu_desc, operand), fragP->fr_cgen.opinfo, - fragP->fr_symbol, fragP->fr_offset); + fragP->fr_symbol, + fragP->fr_offset); } } @@ -739,11 +907,15 @@ md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED, } op_reloc_table[] = { /* PC-REL relocs for 8-bit fields. */ + { M32C_OPERAND_LAB_8_8, BFD_RELOC_8_PCREL, 1 }, { M32C_OPERAND_LAB_16_8, BFD_RELOC_8_PCREL, 2 }, { M32C_OPERAND_LAB_24_8, BFD_RELOC_8_PCREL, 3 }, { M32C_OPERAND_LAB_32_8, BFD_RELOC_8_PCREL, 4 }, { M32C_OPERAND_LAB_40_8, BFD_RELOC_8_PCREL, 5 }, + /* PC-REL relocs for 16-bit fields. */ + { M32C_OPERAND_LAB_8_16, BFD_RELOC_16_PCREL, 1 }, + /* Absolute relocs for 8-bit fields. */ { M32C_OPERAND_IMM_8_QI, BFD_RELOC_8, 1 }, { M32C_OPERAND_IMM_16_QI, BFD_RELOC_8, 2 }, @@ -843,6 +1015,68 @@ md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED, return BFD_RELOC_NONE; } +void +m32c_cons_fix_new (fragS * frag, + int where, + int size, + expressionS *exp, + bfd_reloc_code_real_type type) +{ + switch (size) + { + case 1: + type = BFD_RELOC_8; + break; + case 2: + type = BFD_RELOC_16; + break; + case 3: + type = BFD_RELOC_24; + break; + case 4: + default: + type = BFD_RELOC_32; + break; + case 8: + type = BFD_RELOC_64; + break; + } + + fix_new_exp (frag, where, (int) size, exp, 0, type); +} + +void +m32c_apply_fix (struct fix *f, valueT *t, segT s) +{ + if (f->fx_r_type == BFD_RELOC_M32C_RL_JUMP + || f->fx_r_type == BFD_RELOC_M32C_RL_1ADDR + || f->fx_r_type == BFD_RELOC_M32C_RL_2ADDR) + return; + gas_cgen_md_apply_fix (f, t, s); +} + +arelent * +tc_gen_reloc (asection *sec, fixS *fx) +{ + if (fx->fx_r_type == BFD_RELOC_M32C_RL_JUMP + || fx->fx_r_type == BFD_RELOC_M32C_RL_1ADDR + || fx->fx_r_type == BFD_RELOC_M32C_RL_2ADDR) + { + arelent * reloc; + + reloc = XNEW (arelent); + + reloc->sym_ptr_ptr = XNEW (asymbol *); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fx->fx_addsy); + reloc->address = fx->fx_frag->fr_address + fx->fx_where; + reloc->howto = bfd_reloc_type_lookup (stdoutput, fx->fx_r_type); + reloc->addend = fx->fx_offset; + return reloc; + + } + return gas_cgen_tc_gen_reloc (sec, fx); +} + /* See whether we need to force a relocation into the output file. This is used to force out switch and PC relative relocations when relaxing. */ @@ -867,12 +1101,40 @@ m32c_force_relocation (fixS * fixp) case M32C_OPERAND_DSP_24_U16: case M32C_OPERAND_IMM_24_HI: return 1; + + /* If we're doing linker relaxing, we need to keep all the + pc-relative jumps in case we need to fix them due to + deleted bytes between the jump and its destination. */ + case M32C_OPERAND_LAB_8_8: + case M32C_OPERAND_LAB_8_16: + case M32C_OPERAND_LAB_8_24: + case M32C_OPERAND_LAB_16_8: + case M32C_OPERAND_LAB_24_8: + case M32C_OPERAND_LAB_32_8: + case M32C_OPERAND_LAB_40_8: + if (m32c_relax) + return 1; + default: + break; } } else { - if (fixp->fx_r_type == BFD_RELOC_16) - return 1; + switch (fixp->fx_r_type) + { + case BFD_RELOC_16: + return 1; + + case BFD_RELOC_M32C_RL_JUMP: + case BFD_RELOC_M32C_RL_1ADDR: + case BFD_RELOC_M32C_RL_2ADDR: + case BFD_RELOC_8_PCREL: + case BFD_RELOC_16_PCREL: + if (m32c_relax) + return 1; + default: + break; + } } return generic_force_reloc (fixp); @@ -893,50 +1155,10 @@ md_number_to_chars (char * buf, valueT val, int n) /* Equal to MAX_PRECISION in atof-ieee.c. */ #define MAX_LITTLENUMS 6 -char * +const char * md_atof (int type, char * litP, int * sizeP) { - int i; - int prec; - LITTLENUM_TYPE words [MAX_LITTLENUMS]; - char * t; - - switch (type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - prec = 4; - break; - - /* FIXME: Some targets allow other format chars for bigger sizes here. */ - - default: - * sizeP = 0; - return _("Bad call to md_atof()"); - } - - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - * sizeP = prec * sizeof (LITTLENUM_TYPE); - - for (i = 0; i < prec; i++) - { - md_number_to_chars (litP, (valueT) words[i], - sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - - return 0; + return ieee_md_atof (type, litP, sizeP, TRUE); } bfd_boolean @@ -1018,25 +1240,23 @@ m32c_fix_adjustable (fixS * fixP) if (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) return 0; + if (m32c_relax) + return 0; + return 1; } /* Worker function for m32c_is_colon_insn(). */ -static char restore_colon PARAMS ((int)); - -static char -restore_colon (int advance_i_l_p_by) +static int +restore_colon (char *next_i_l_p, char *nul_char) { - char c; - /* Restore the colon, and advance input_line_pointer to the end of the new symbol. */ - * input_line_pointer = ':'; - input_line_pointer += advance_i_l_p_by; - c = * input_line_pointer; - * input_line_pointer = 0; - - return c; + *input_line_pointer = *nul_char; + input_line_pointer = next_i_l_p; + *nul_char = *next_i_l_p; + *next_i_l_p = 0; + return 1; } /* Determines if the symbol starting at START and ending in @@ -1044,28 +1264,31 @@ restore_colon (int advance_i_l_p_by) (but which has now been replaced bu a NUL) is in fact an :Z, :S, :Q, or :G suffix. If it is, then it restores the colon, advances INPUT_LINE_POINTER - to the real end of the instruction/symbol, and returns the character - that really terminated the symbol. Otherwise it returns 0. */ -char -m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED) + to the real end of the instruction/symbol, saves the char there to + NUL_CHAR and pokes a NUL, and returns 1. Otherwise it returns 0. */ +int +m32c_is_colon_insn (char *start ATTRIBUTE_UNUSED, char *nul_char) { char * i_l_p = input_line_pointer; + if (*nul_char == '"') + ++i_l_p; + /* Check to see if the text following the colon is 'G' */ if (TOLOWER (i_l_p[1]) == 'g' && (i_l_p[2] == ' ' || i_l_p[2] == '\t')) - return restore_colon (2); + return restore_colon (i_l_p + 2, nul_char); /* Check to see if the text following the colon is 'Q' */ if (TOLOWER (i_l_p[1]) == 'q' && (i_l_p[2] == ' ' || i_l_p[2] == '\t')) - return restore_colon (2); + return restore_colon (i_l_p + 2, nul_char); /* Check to see if the text following the colon is 'S' */ if (TOLOWER (i_l_p[1]) == 's' && (i_l_p[2] == ' ' || i_l_p[2] == '\t')) - return restore_colon (2); + return restore_colon (i_l_p + 2, nul_char); /* Check to see if the text following the colon is 'Z' */ if (TOLOWER (i_l_p[1]) == 'z' && (i_l_p[2] == ' ' || i_l_p[2] == '\t')) - return restore_colon (2); + return restore_colon (i_l_p + 2, nul_char); return 0; }