diff options
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/tc-m68hc11.c | 70 |
2 files changed, 69 insertions, 11 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 075d857..da08b6f 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2002-12-08 Stephane Carrez <stcarrez@nerim.fr> + + Fix Bug savannah/1825: + * config/tc-m68hc11.c (STATE_INDEXED_PCREL): New relax code. + (md_relax_table): Define specific relax for PC-rel offsets. + (build_indexed_byte): Use a STATE_INDEXED_PCREL relax code. + (m68hc11_relax_frag): Handle the new relax code. + (md_convert_frag): Likewise. + (md_estimate_size_before_relax): Likewise. + 2002-12-08 Alan Modra <amodra@bigpond.net.au> * subsegs.c (section_symbol): Use the symbol, not the section, name. diff --git a/gas/config/tc-m68hc11.c b/gas/config/tc-m68hc11.c index f12655e..751bb49 100644 --- a/gas/config/tc-m68hc11.c +++ b/gas/config/tc-m68hc11.c @@ -37,8 +37,9 @@ const char FLT_CHARS[] = "dD"; #define STATE_CONDITIONAL_BRANCH (1) #define STATE_PC_RELATIVE (2) #define STATE_INDEXED_OFFSET (3) -#define STATE_XBCC_BRANCH (4) -#define STATE_CONDITIONAL_BRANCH_6812 (5) +#define STATE_INDEXED_PCREL (4) +#define STATE_XBCC_BRANCH (5) +#define STATE_CONDITIONAL_BRANCH_6812 (6) #define STATE_BYTE (0) #define STATE_BITS5 (0) @@ -90,6 +91,14 @@ relax_typeS md_relax_table[] = { {0, 0, 2, 0}, {1, 1, 0, 0}, + /* Relax for PC relative offset: 5-bits, 9-bits, 16-bits. + For the 9-bit case, there will be a -1 correction to take into + account the new byte that's why the range is -255..256. */ + {(15), (-16), 0, ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9)}, + {(256), (-255), 1, ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16)}, + {0, 0, 2, 0}, + {1, 1, 0, 0}, + /* Relax for dbeq/ibeq/tbeq r,<L>: These insns are translated into db!cc +3 jmp L. */ {(255), (-256), 0, ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_WORD)}, @@ -1955,7 +1964,7 @@ build_indexed_byte (op, format, move_insn) f = frag_more (1); number_to_chars_bigendian (f, byte, 1); frag_var (rs_machine_dependent, 2, 2, - ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF), + ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_UNDF), op->exp.X_add_symbol, op->exp.X_add_number, f); } @@ -2762,11 +2771,14 @@ m68hc11_relax_frag (seg, fragP, stretch) because of the different reasons that it's not relaxable. */ switch (fragP->fr_subtype) { + case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16): case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16): /* When we get to this state, the frag won't grow any more. */ return 0; + case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS5): case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5): + case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9): case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9): if (fragP->fr_symbol == NULL || S_GET_SEGMENT (fragP->fr_symbol) != absolute_section) @@ -2892,20 +2904,26 @@ md_convert_frag (abfd, sec, fragP) fragP->fr_fix += 2; break; - case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5): - if (fragP->fr_opcode[0] == 3 - && fragP->fr_symbol != 0 + case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS5): + if (fragP->fr_symbol != 0 && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section) value = disp; + /* fall through */ + + case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5): fragP->fr_opcode[0] = fragP->fr_opcode[0] << 6; fragP->fr_opcode[0] |= value & 0x1f; break; - case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9): - if (fragP->fr_opcode[0] == 3 - && fragP->fr_symbol != 0 + case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9): + /* For a PC-relative offset, use the displacement with a -1 correction + to take into account the additional byte of the insn. */ + if (fragP->fr_symbol != 0 && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section) - value = disp; + value = disp - 1; + /* fall through */ + + case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9): fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3); fragP->fr_opcode[0] |= 0xE0; fragP->fr_opcode[0] |= (value >> 8) & 1; @@ -2913,6 +2931,7 @@ md_convert_frag (abfd, sec, fragP) fragP->fr_fix += 1; break; + case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16): case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16): fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3); fragP->fr_opcode[0] |= 0xe2; @@ -2923,7 +2942,6 @@ md_convert_frag (abfd, sec, fragP) fixp = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_16_PCREL); - fixp->fx_pcrel_adjust = 2; } else { @@ -3047,6 +3065,29 @@ md_estimate_size_before_relax (fragP, segment) } break; + case STATE_INDEXED_PCREL: + assert (current_architecture & cpu6812); + + if (fragP->fr_symbol + && S_GET_SEGMENT (fragP->fr_symbol) == absolute_section) + { + fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_PCREL, + STATE_BITS5); + /* Return the size of the variable part of the frag. */ + return md_relax_table[fragP->fr_subtype].rlx_length; + } + else + { + fixS* fixp; + + fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3; + fragP->fr_opcode[0] |= 0xe2; + fixp = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, + fragP->fr_offset, 1, BFD_RELOC_16_PCREL); + fragP->fr_fix += 2; + } + break; + case STATE_XBCC_BRANCH: assert (current_architecture & cpu6812); @@ -3110,6 +3151,13 @@ md_estimate_size_before_relax (fragP, segment) STATE_BITS5); break; + case STATE_INDEXED_PCREL: + assert (current_architecture & cpu6812); + + fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_PCREL, + STATE_BITS5); + break; + case STATE_XBCC_BRANCH: assert (current_architecture & cpu6812); |