diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 49 | ||||
-rw-r--r-- | gas/config/tc-ppc.h | 33 |
3 files changed, 60 insertions, 29 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 5c0b736..2d1137d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2006-09-22 Alan Modra <amodra@bigpond.net.au> + + * config/tc-ppc.c (md_section_align): Don't round up address for ELF. + (ppc_handle_align): New function. + * config/tc-ppc.h (HANDLE_ALIGN): Use ppc_handle_align. + (SUB_SEGMENT_ALIGN): Define as zero. + 2006-09-20 Bob Wilson <bob.wilson@acm.org> * doc/as.texinfo: Fix cross reference usage, typos and grammar. diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 7af4fa6..35e30b0 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -5265,13 +5265,15 @@ md_number_to_chars (buf, val, n) /* Align a section (I don't know why this is machine dependent). */ valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr) { +#ifdef OBJ_ELF + return addr; +#else int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); +#endif } /* We don't have any form of relaxing. */ @@ -5519,6 +5521,47 @@ ppc_fix_adjustable (fix) } #endif +/* Implement HANDLE_ALIGN. This writes the NOP pattern into an + rs_align_code frag. */ + +void +ppc_handle_align (struct frag *fragP) +{ + valueT count = (fragP->fr_next->fr_address + - (fragP->fr_address + fragP->fr_fix)); + + if (count != 0 && (count & 3) == 0) + { + char *dest = fragP->fr_literal + fragP->fr_fix; + + fragP->fr_var = 4; + md_number_to_chars (dest, 0x60000000, 4); + + if ((ppc_cpu & PPC_OPCODE_POWER6) != 0) + { + /* For power6, we want the last nop to be a group terminating + one, "ori 1,1,0". Do this by inserting an rs_fill frag + immediately after this one, with its address set to the last + nop location. This will automatically reduce the number of + nops in the current frag by one. */ + if (count > 4) + { + struct frag *group_nop = xmalloc (SIZEOF_STRUCT_FRAG + 4); + + memcpy (group_nop, fragP, SIZEOF_STRUCT_FRAG); + group_nop->fr_address = group_nop->fr_next->fr_address - 4; + group_nop->fr_fix = 0; + group_nop->fr_offset = 1; + group_nop->fr_type = rs_fill; + fragP->fr_next = group_nop; + dest = group_nop->fr_literal; + } + + md_number_to_chars (dest, 0x60210000, 4); + } + } +} + /* Apply a fixup to the object code. This is called for all the fixups we generated by the call to fix_new_exp, above. In the call above we used a reloc code which was the largest legal reloc code diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index 5a43420..e9cce7f 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -1,6 +1,6 @@ /* tc-ppc.h -- Header file for tc-ppc.c. Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005 Free Software Foundation, Inc. + 2004, 2005, 2006 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of GAS, the GNU Assembler. @@ -78,31 +78,12 @@ extern char *ppc_target_format PARAMS ((void)); #define MAX_MEM_FOR_RS_ALIGN_CODE 4 #define HANDLE_ALIGN(FRAGP) \ - if ((FRAGP)->fr_type == rs_align_code) \ - { \ - valueT count = ((FRAGP)->fr_next->fr_address \ - - ((FRAGP)->fr_address + (FRAGP)->fr_fix)); \ - if (count != 0 && (count & 3) == 0) \ - { \ - char *dest = (FRAGP)->fr_literal + (FRAGP)->fr_fix; \ - \ - (FRAGP)->fr_var = 4; \ - if (target_big_endian) \ - { \ - *dest++ = 0x60; \ - *dest++ = 0; \ - *dest++ = 0; \ - *dest++ = 0; \ - } \ - else \ - { \ - *dest++ = 0; \ - *dest++ = 0; \ - *dest++ = 0; \ - *dest++ = 0x60; \ - } \ - } \ - } + if ((FRAGP)->fr_type == rs_align_code) \ + ppc_handle_align (FRAGP); + +extern void ppc_handle_align (struct frag *); + +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0 #define md_frag_check(FRAGP) \ if ((FRAGP)->has_code \ |