diff options
author | Nick Clifton <nickc@redhat.com> | 1997-10-11 00:55:57 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 1997-10-11 00:55:57 +0000 |
commit | c28060930020783b020efcd6de7f9648c408d755 (patch) | |
tree | dbcec6c2aafd0ab942e794e08318658d461207c8 /gas | |
parent | 5ff4668dea05ff6ba6eefc022419bcbd46ccc75e (diff) | |
download | gdb-c28060930020783b020efcd6de7f9648c408d755.zip gdb-c28060930020783b020efcd6de7f9648c408d755.tar.gz gdb-c28060930020783b020efcd6de7f9648c408d755.tar.bz2 |
Jim fixed the fixups for conditional and unconditional branches.
Added code to support the bss and common sections in thr ZDA and SDA areas.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 23 | ||||
-rw-r--r-- | gas/config/tc-v850.c | 372 | ||||
-rw-r--r-- | gas/config/tc-v850.h | 29 |
3 files changed, 355 insertions, 69 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 50625af..cd3f555 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +Fri Oct 10 17:48:29 1997 Nick Clifton <nickc@cygnus.com> + + * config/tc-v850.c (md_relax_table): Add support for relaxing + unconditional branches. This patch is courtesy of Jim Wilson. + (md_convert_frag): Fix relaxing of branches. This patch is + courtesy of Jim Wilson. + (md_assemble): Create different fixups for conditional and + unconditional branches. This patch is courtesy of Jim Wilson. + (md_estimate_size_before_relax): Estimate size of variable part of + fixup based on whether it is for a conditional or an unconditional + branch. This patch is courtesy of Jim Wilson. + (v850_sdata, v850_tdata, v850_zdata, v850_sbss, v850_tbss, + v850_zbss, v850_rosdata, v850_rozdata, v850_bss): Add call to + obj_elf_section_change_hook(). + (v850_comm): New function. + (md_pseudo_table): Add new pseudo ops .zcomm, .scomm and .tcomm. + (md_begin): Add bss flag to seg_info of bss sections. + + Add support for .scommon, .tcommon and .zcommon sections. + + * config/tc-v850.h (ELF_TC_SPECIAL_SECTIONS): Add .scommon, + .zcommon, .tbss, .call_table_data and .call_table_text. + Fri Oct 10 15:01:14 1997 Doug Evans <dje@canuck.cygnus.com> * configure.in (sparc): Set DEFAULT_ARCH from correct target. diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index 249c853..f4a9ea9 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -24,6 +24,10 @@ #include "subsegs.h" #include "opcode/v850.h" +#define AREA_ZDA 0 +#define AREA_SDA 1 +#define AREA_TDA 2 + /* sign-extend a 16-bit number */ #define SEXT16(x) ((((x) & 0xffff) ^ (~ 0x7fff)) + 0x8000) @@ -69,9 +73,14 @@ const char EXP_CHARS[] = "eE"; const char FLT_CHARS[] = "dD"; -const relax_typeS md_relax_table[] = { - {0xff, -0x100, 2, 1}, +const relax_typeS md_relax_table[] = +{ + /* Conditional branches. */ + {0xff, -0x100, 2, 1}, {0x1fffff, -0x200000, 6, 0}, + /* Unconditional branches. */ + {0xff, -0x100, 2, 3}, + {0x1fffff, -0x200000, 4, 0}, }; @@ -83,6 +92,9 @@ static segT tbss_section = NULL; static segT zbss_section = NULL; static segT rosdata_section = NULL; static segT rozdata_section = NULL; +static segT scommon_section = NULL; +static segT tcommon_section = NULL; +static segT zcommon_section = NULL; /* start-sanitize-v850e */ static segT call_table_data_section = NULL; static segT call_table_text_section = NULL; @@ -109,14 +121,18 @@ static int fc; void v850_sdata (int ignore) { - subseg_set (sdata_section, (subsegT) get_absolute_expression ()); + obj_elf_section_change_hook(); + subseg_set (sdata_section, (subsegT) get_absolute_expression ()); + demand_empty_rest_of_line (); } void v850_tdata (int ignore) { + obj_elf_section_change_hook(); + subseg_set (tdata_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -125,6 +141,8 @@ v850_tdata (int ignore) void v850_zdata (int ignore) { + obj_elf_section_change_hook(); + subseg_set (zdata_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -133,6 +151,8 @@ v850_zdata (int ignore) void v850_sbss (int ignore) { + obj_elf_section_change_hook(); + subseg_set (sbss_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -141,6 +161,8 @@ v850_sbss (int ignore) void v850_tbss (int ignore) { + obj_elf_section_change_hook(); + subseg_set (tbss_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -149,6 +171,8 @@ v850_tbss (int ignore) void v850_zbss (int ignore) { + obj_elf_section_change_hook(); + subseg_set (zbss_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -157,6 +181,8 @@ v850_zbss (int ignore) void v850_rosdata (int ignore) { + obj_elf_section_change_hook(); + subseg_set (rosdata_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -165,6 +191,8 @@ v850_rosdata (int ignore) void v850_rozdata (int ignore) { + obj_elf_section_change_hook(); + subseg_set (rozdata_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -174,6 +202,8 @@ v850_rozdata (int ignore) void v850_call_table_data (int ignore) { + obj_elf_section_change_hook(); + subseg_set (call_table_data_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); @@ -182,30 +212,14 @@ v850_call_table_data (int ignore) void v850_call_table_text (int ignore) { + obj_elf_section_change_hook(); + subseg_set (call_table_text_section, (subsegT) get_absolute_expression ()); demand_empty_rest_of_line (); } /* end-sanitize-v850e */ -static void -v850_section (int arg) -{ - char saved_c; - char * ptr; - - for (ptr = input_line_pointer; * ptr != '\n' && * ptr != 0; ptr ++) - if (* ptr == ',' && ptr[1] == '.') - break; - - saved_c = * ptr; - * ptr = ';'; - - obj_elf_section (arg); - - * ptr = saved_c; -} - void v850_bss (int ignore) { @@ -214,7 +228,7 @@ v850_bss (int ignore) obj_elf_section_change_hook(); subseg_set (bss_section, (subsegT) temp); - + demand_empty_rest_of_line (); } @@ -231,6 +245,225 @@ v850_offset (int ignore) demand_empty_rest_of_line (); } +/* Copied from obj_elf_common() in gas/config/obj-elf.c */ +static void +v850_comm (area) + int area; +{ + char * name; + char c; + char * p; + int temp; + int size; + symbolS * symbolP; + int have_align; + + name = input_line_pointer; + c = get_symbol_end (); + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + as_bad ("Expected comma after symbol-name"); + ignore_rest_of_line (); + return; + } + input_line_pointer++; /* skip ',' */ + if ((temp = get_absolute_expression ()) < 0) + { + as_bad (".COMMon length (%d.) <0! Ignored.", temp); + ignore_rest_of_line (); + return; + } + size = temp; + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) + { + as_bad ("Ignoring attempt to re-define symbol"); + ignore_rest_of_line (); + return; + } + if (S_GET_VALUE (symbolP) != 0) + { + if (S_GET_VALUE (symbolP) != size) + { + as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", + S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); + } + } + know (symbolP->sy_frag == &zero_address_frag); + if (*input_line_pointer != ',') + have_align = 0; + else + { + have_align = 1; + input_line_pointer++; + SKIP_WHITESPACE (); + } + if (! have_align || *input_line_pointer != '"') + { + if (! have_align) + temp = 0; + else + { + temp = get_absolute_expression (); + if (temp < 0) + { + temp = 0; + as_warn ("Common alignment negative; 0 assumed"); + } + } + if (symbolP->local) + { + segT old_sec; + int old_subsec; + char * pfrag; + int align; + + /* allocate_bss: */ + old_sec = now_seg; + old_subsec = now_subseg; + if (temp) + { + /* convert to a power of 2 alignment */ + for (align = 0; (temp & 1) == 0; temp >>= 1, ++align); + if (temp != 1) + { + as_bad ("Common alignment not a power of 2"); + ignore_rest_of_line (); + return; + } + } + else + align = 0; + switch (area) + { + case AREA_SDA: + record_alignment (sbss_section, align); + obj_elf_section_change_hook(); + subseg_set (sbss_section, 0); + break; + + case AREA_ZDA: + record_alignment (zbss_section, align); + obj_elf_section_change_hook(); + subseg_set (zbss_section, 0); + break; + + case AREA_TDA: + record_alignment (tbss_section, align); + obj_elf_section_change_hook(); + subseg_set (tbss_section, 0); + break; + + default: + abort(); + } + + if (align) + frag_align (align, 0, 0); + + switch (area) + { + case AREA_SDA: + if (S_GET_SEGMENT (symbolP) == sbss_section) + symbolP->sy_frag->fr_symbol = 0; + break; + + case AREA_ZDA: + if (S_GET_SEGMENT (symbolP) == zbss_section) + symbolP->sy_frag->fr_symbol = 0; + break; + + case AREA_TDA: + if (S_GET_SEGMENT (symbolP) == tbss_section) + symbolP->sy_frag->fr_symbol = 0; + break; + + default: + abort(); + } + + symbolP->sy_frag = frag_now; + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, + (offsetT) size, (char *) 0); + *pfrag = 0; + S_SET_SIZE (symbolP, size); + + switch (area) + { + case AREA_SDA: S_SET_SEGMENT (symbolP, sbss_section); break; + case AREA_ZDA: S_SET_SEGMENT (symbolP, zbss_section); break; + case AREA_TDA: S_SET_SEGMENT (symbolP, tbss_section); break; + default: + abort(); + } + + S_CLEAR_EXTERNAL (symbolP); + obj_elf_section_change_hook(); + subseg_set (old_sec, old_subsec); + } + else + { + allocate_common: + S_SET_VALUE (symbolP, (valueT) size); + S_SET_ALIGN (symbolP, temp); + S_SET_EXTERNAL (symbolP); + + switch (area) + { + case AREA_SDA: S_SET_SEGMENT (symbolP, scommon_section); break; + case AREA_ZDA: S_SET_SEGMENT (symbolP, zcommon_section); break; + case AREA_TDA: S_SET_SEGMENT (symbolP, tcommon_section); break; + default: + abort(); + } + } + } + else + { + input_line_pointer++; + /* @@ Some use the dot, some don't. Can we get some consistency?? */ + if (*input_line_pointer == '.') + input_line_pointer++; + /* @@ Some say data, some say bss. */ + if (strncmp (input_line_pointer, "bss\"", 4) + && strncmp (input_line_pointer, "data\"", 5)) + { + while (*--input_line_pointer != '"') + ; + input_line_pointer--; + goto bad_common_segment; + } + while (*input_line_pointer++ != '"') + ; + goto allocate_common; + } + + symbolP->bsym->flags |= BSF_OBJECT; + + demand_empty_rest_of_line (); + return; + + { + bad_common_segment: + p = input_line_pointer; + while (*p && *p != '\n') + p++; + c = *p; + *p = '\0'; + as_bad ("bad .common segment %s", input_line_pointer + 1); + *p = c; + input_line_pointer = p; + ignore_rest_of_line (); + return; + } +} + void set_machine (int number) { @@ -260,8 +493,10 @@ const pseudo_typeS md_pseudo_table[] = {"rozdata", v850_rozdata, 0}, {"bss", v850_bss, 0}, {"offset", v850_offset, 0}, - {"section", v850_section, 0}, {"word", cons, 4}, + {"zcomm", v850_comm, AREA_ZDA}, + {"scomm", v850_comm, AREA_SDA}, + {"tcomm", v850_comm, AREA_TDA}, {"v850", set_machine, 0}, /* start-sanitize-v850e */ {"call_table_data", v850_call_table_data, 0}, @@ -324,6 +559,7 @@ static const struct reg_name pre_defined_registers[] = static const struct reg_name system_registers[] = { /* start-sanitize-v850e */ + { "ctbp", 20 }, { "ctpc", 16 }, { "ctpsw", 17 }, @@ -580,9 +816,10 @@ skip_white_space (void) * insn is the partially constructed instruction. * operand is the operand being inserted. * - * out: True if the parse completed successfully, False otherwise. - * If the parse completes the correct bit fields in the - * instruction will be filled in. + * out: NULL if the parse completed successfully, otherwise a + * pointer to an error message is returned. If the parse + * completes the correct bit fields in the instruction + * will be filled in. * * Parses register lists with the syntax: * @@ -627,7 +864,7 @@ parse_register_list skip_white_space(); /* If the expression starts with a curly brace it is a register list. - Otherwise it is a constant expression ,whoes bits indicate which + Otherwise it is a constant expression, whoes bits indicate which registers are to be included in the list. */ if (* input_line_pointer != '{') @@ -919,32 +1156,47 @@ md_convert_frag (abfd, sec, fragP) fragS * fragP; { subseg_change (sec, 0); - if (fragP->fr_subtype == 0) + + /* In range conditional or unconditional branch. */ + if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2) { fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode); fragP->fr_var = 0; fragP->fr_fix += 2; } + /* Out of range conditional branch. Emit a branch around a jump. */ else if (fragP->fr_subtype == 1) { + unsigned char *buffer = + (unsigned char *) (fragP->fr_fix + fragP->fr_literal); + /* Reverse the condition of the first branch. */ - fragP->fr_literal[0] &= 0xf7; + buffer[0] ^= 0x08; /* Mask off all the displacement bits. */ - fragP->fr_literal[0] &= 0x8f; - fragP->fr_literal[1] &= 0x07; + buffer[0] &= 0x8f; + buffer[1] &= 0x07; /* Now set the displacement bits so that we branch around the unconditional branch. */ - fragP->fr_literal[0] |= 0x30; + buffer[0] |= 0x30; /* Now create the unconditional branch + fixup to the final target. */ - md_number_to_chars (&fragP->fr_literal[2], 0x00000780, 4); + md_number_to_chars (buffer + 2, 0x00000780, 4); fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode + 1); fragP->fr_var = 0; fragP->fr_fix += 6; } + /* Out of range unconditional branch. Emit a jump. */ + else if (fragP->fr_subtype == 3) + { + md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4); + fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode + 1); + fragP->fr_var = 0; + fragP->fr_fix += 4; + } else abort (); } @@ -1029,12 +1281,15 @@ md_begin () sbss_section = subseg_new (".sbss", 0); bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC); + seg_info (sbss_section)->bss = 1; tbss_section = subseg_new (".tbss", 0); bfd_set_section_flags (stdoutput, tbss_section, applicable & SEC_ALLOC); + seg_info (tbss_section)->bss = 1; zbss_section = subseg_new (".zbss", 0); bfd_set_section_flags (stdoutput, zbss_section, applicable & SEC_ALLOC); + seg_info (zbss_section)->bss = 1; rosdata_section = subseg_new (".rosdata", 0); bfd_set_section_flags (stdoutput, rosdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY)); @@ -1042,6 +1297,12 @@ md_begin () rozdata_section = subseg_new (".rozdata", 0); bfd_set_section_flags (stdoutput, rozdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY)); + scommon_section = subseg_new (".scommon", 0); + bfd_set_section_flags (stdoutput, scommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON)); + + zcommon_section = subseg_new (".zcommon", 0); + bfd_set_section_flags (stdoutput, zcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON)); + /* start-sanitize-v850e */ call_table_data_section = subseg_new (".call_table_data", 0); bfd_set_section_flags (stdoutput, call_table_data_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS)); @@ -1162,7 +1423,7 @@ v850_reloc_prefix (const struct v850_operand * operand) CHECK_ ("tdaoff", handle_tdaoff (operand)); /* start-sanitize-v850e */ - CHECK_ ("hilo", BFD_RELOC_32); + CHECK_ ("hilo", BFD_RELOC_32); CHECK_ ("ctoff", handle_ctoff (operand)); /* end-sanitize-v850e */ @@ -1193,7 +1454,7 @@ md_assemble (str) unsigned extra_data_len; unsigned long extra_data; char * saved_input_line_pointer; - + /* Get the opcode. */ for (s = str; *s != '\0' && ! isspace (*s); s++) continue; @@ -1491,7 +1752,7 @@ md_assemble (str) if (errmsg) goto error; -/* fprintf (stderr, "insn: %x, operand %d, op: %d, add_number: %d\n", insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number ); */ +/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n", insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */ switch (ex.X_op) { @@ -1564,22 +1825,35 @@ md_assemble (str) input_line_pointer = str; - /* Write out the instruction. - - Four byte insns have an opcode with the two high bits on. */ + /* Write out the instruction. */ + if (relaxable && fc > 0) { - f = frag_var (rs_machine_dependent, 6, 4, 0, - fixups[0].exp.X_add_symbol, - fixups[0].exp.X_add_number, - (char *)fixups[0].opindex); insn_size = 2; - md_number_to_chars (f, insn, insn_size); - md_number_to_chars (f + 2, 0, 4); fc = 0; + + if (!strcmp (opcode->name, "br")) + { + f = frag_var (rs_machine_dependent, 4, 2, 2, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 2); + } + else + { + f = frag_var (rs_machine_dependent, 6, 4, 0, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 4); + } } else { + /* Four byte insns have an opcode with the two high bits on. */ if ((insn & 0x0600) == 0x0600) insn_size = 4; else @@ -1708,7 +1982,12 @@ md_estimate_size_before_relax (fragp, seg) fragS * fragp; asection * seg; { - fragp->fr_var = 4; + if (fragp->fr_subtype == 0) + fragp->fr_var = 4; + else if (fragp->fr_subtype == 2) + fragp->fr_var = 2; + else + abort (); return 2; } @@ -1806,6 +2085,7 @@ md_apply_fix3 (fixp, valuep, seg) { /* We still have to insert the value into memory! */ where = fixp->fx_frag->fr_literal + fixp->fx_where; + if (fixp->fx_size == 1) *where = value & 0xff; else if (fixp->fx_size == 2) diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h index 449777a..ddbb2e6 100644 --- a/gas/config/tc-v850.h +++ b/gas/config/tc-v850.h @@ -32,28 +32,6 @@ /* The target BFD format. */ #define TARGET_FORMAT "elf32-v850" -/* The target BFD machine number. */ -#define TARGET_MACHINE 0 -/* start-sanitize-v850e */ -#undef TARGET_MACHINE -#define TARGET_MACHINE bfd_mach_v850e -/* end-sanitize-v850e */ -/* start-sanitize-v850eq */ -#undef TARGET_MACHINE -#define TARGET_MACHINE bfd_mach_v850eq -/* end-sanitize-v850eq */ - -/* The target processor mask. */ -#define TARGET_PROCESSOR PROCESSOR_V850 -/* start-sanitize-v850e */ -#undef TARGET_PROCESSOR -#define TARGET_PROCESSOR PROCESSOR_V850E -/* end-sanitize-v850e */ -/* start-sanitize-v850eq */ -#undef TARGET_PROCESSOR -#define TARGET_PROCESSOR PROCESSOR_V850EQ -/* end-sanitize-v850eq */ - #define MD_APPLY_FIX3 #define md_operand(x) @@ -87,8 +65,13 @@ extern const struct relax_type md_relax_table[]; { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \ { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \ { ".rosdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_GPREL }, \ + { ".scommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \ { ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \ + { ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \ { ".zdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ { ".rozdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_R0REL }, \ - { ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, + { ".zcommon", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ + { ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ + { ".call_table_data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \ + { ".call_table_text", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR }, |