diff options
author | Alan Modra <amodra@gmail.com> | 2010-11-04 03:30:05 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2010-11-04 03:30:05 +0000 |
commit | cef4f75472a54f9dc833d3491a1ee6cf3a5a0968 (patch) | |
tree | 98564a94b22fe5e8e5947da162821c4f90733b9f /gas | |
parent | 1dd6f20d5ec108230aef1fd3160cc77b268acfa6 (diff) | |
download | gdb-cef4f75472a54f9dc833d3491a1ee6cf3a5a0968.zip gdb-cef4f75472a54f9dc833d3491a1ee6cf3a5a0968.tar.gz gdb-cef4f75472a54f9dc833d3491a1ee6cf3a5a0968.tar.bz2 |
* config/tc-ppc.c (nop_limit): New var.
(OPTION_NOPS): Define.
(md_longopts): Add --nops.
(md_parse_option): Handle it.
(md_show_usage): Publish.
(ppc_handle_align): Pad with a branch followed by nops if more
than nop_limit nops.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 42 |
2 files changed, 52 insertions, 0 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 5cb95f8..65ca4cb 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2010-11-04 Alan Modra <amodra@gmail.com> + + * config/tc-ppc.c (nop_limit): New var. + (OPTION_NOPS): Define. + (md_longopts): Add --nops. + (md_parse_option): Handle it. + (md_show_usage): Publish. + (ppc_handle_align): Pad with a branch followed by nops if more + than nop_limit nops. + 2010-11-03 H.J. Lu <hongjiu.lu@intel.com> PR gas/12186 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index f8c5d35..469abc1 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -180,6 +180,10 @@ const char ppc_symbol_chars[] = "%["; /* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ int ppc_cie_data_alignment; +/* More than this number of nops in an alignment op gets a branch + instead. */ +unsigned long nop_limit = 4; + /* The type of processor we are assembling for. This is one or more of the PPC_OPCODE flags defined in opcode/ppc.h. */ ppc_cpu_t ppc_cpu = 0; @@ -1018,7 +1022,9 @@ const char *const md_shortopts = "b:l:usm:K:VQ:"; #else const char *const md_shortopts = "um:"; #endif +#define OPTION_NOPS (OPTION_MD_BASE + 0) const struct option md_longopts[] = { + {"nops", required_argument, NULL, OPTION_NOPS}, {NULL, no_argument, NULL, 0} }; const size_t md_longopts_size = sizeof (md_longopts); @@ -1172,6 +1178,15 @@ md_parse_option (int c, char *arg) break; #endif + case OPTION_NOPS: + { + char *end; + nop_limit = strtoul (optarg, &end, 0); + if (*end) + as_bad (_("--nops needs a numeric argument")); + } + break; + default: return 0; } @@ -1238,6 +1253,8 @@ PowerPC options:\n\ -V print assembler version number\n\ -Qy, -Qn ignored\n")); #endif + fprintf (stream, _("\ +-nops=count when aligning, more than COUNT nops uses a branch\n")); } /* Set ppc_cpu if it is not already set. */ @@ -5748,6 +5765,31 @@ ppc_handle_align (struct frag *fragP) char *dest = fragP->fr_literal + fragP->fr_fix; fragP->fr_var = 4; + + if (count > 4 * nop_limit && count < 0x2000000) + { + struct frag *rest; + + /* Make a branch, then follow with nops. Insert another + frag to handle the nops. */ + md_number_to_chars (dest, 0x48000000 + count, 4); + count -= 4; + if (count == 0) + return; + + rest = xmalloc (SIZEOF_STRUCT_FRAG + 4); + memcpy (rest, fragP, SIZEOF_STRUCT_FRAG); + fragP->fr_next = rest; + fragP = rest; + rest->fr_address += rest->fr_fix + 4; + rest->fr_fix = 0; + /* If we leave the next frag as rs_align_code we'll come here + again, resulting in a bunch of branches rather than a + branch followed by nops. */ + rest->fr_type = rs_align; + dest = rest->fr_literal; + } + md_number_to_chars (dest, 0x60000000, 4); if ((ppc_cpu & PPC_OPCODE_POWER6) != 0 |