From cef4f75472a54f9dc833d3491a1ee6cf3a5a0968 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 4 Nov 2010 03:30:05 +0000 Subject: [PATCH] * 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. --- gas/ChangeLog | 10 ++++++++++ gas/config/tc-ppc.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/gas/ChangeLog b/gas/ChangeLog index 5cb95f85ec7..65ca4cbc6dc 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2010-11-04 Alan Modra + + * 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 PR gas/12186 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index f8c5d350810..469abc17754 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 -- 2.30.2