diff options
author | Alan Modra <amodra@gmail.com> | 2019-06-25 10:12:58 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-06-25 13:04:40 +0930 |
commit | 22f72c4868a1fd55d8d9b1cbabe6e01ed5a6f072 (patch) | |
tree | 223bd6f1f60e5fc1ecada40c17aa4c1084d39d54 /gas/config/tc-ppc.c | |
parent | 2e7c439dec066ac8a597d0b85193b8d3ec8e09eb (diff) | |
download | gdb-22f72c4868a1fd55d8d9b1cbabe6e01ed5a6f072.zip gdb-22f72c4868a1fd55d8d9b1cbabe6e01ed5a6f072.tar.gz gdb-22f72c4868a1fd55d8d9b1cbabe6e01ed5a6f072.tar.bz2 |
PowerPC nops
This patch corrects ppc rs_align_code handling to choose the alignment
nops based on the machine in force at the alignment directive rather
than the machine at the end of file.
* config/tc-ppc.h (ppc_nop_select): Declare.
(NOP_OPCODE): Define.
* config/tc-ppc.c (ppc_elf_end, ppc_xcoff_end): Zero ppc_cpu.
(ppc_nop_encoding_for_rs_align_code): New enum.
(ppc_nop_select): New function.
(ppc_handle_align): Don't use ppc_cpu here. Get nop type from frag.
* testsuite/gas/ppc/groupnop.d,
* testsuite/gas/ppc/groupnop.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
Diffstat (limited to 'gas/config/tc-ppc.c')
-rw-r--r-- | gas/config/tc-ppc.c | 70 |
1 files changed, 51 insertions, 19 deletions
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index d709010..de0f8da 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -2608,6 +2608,12 @@ ppc_elf_end (void) elf_elfheader (stdoutput)->e_flags &= ~EF_PPC64_ABI; elf_elfheader (stdoutput)->e_flags |= ppc_abiversion & EF_PPC64_ABI; } + /* Any selection of opcodes based on ppc_cpu after gas has finished + parsing the file is invalid. md_apply_fix and ppc_handle_align + must select opcodes based on the machine in force at the point + where the fixup or alignment frag was created, not the machine in + force at the end of file. */ + ppc_cpu = 0; } /* Validate any relocations emitted for -mrelocatable, possibly adding @@ -5562,6 +5568,7 @@ ppc_xcoff_end (void) symbol_set_value_now (dwss->end_exp.X_add_symbol); } } + ppc_cpu = 0; } #endif /* OBJ_XCOFF */ @@ -7077,26 +7084,58 @@ ppc_frag_check (struct frag *fragP) fragP->insn_addr + 1); } -/* Implement HANDLE_ALIGN. This writes the NOP pattern into an - rs_align_code frag. */ +/* rs_align_code frag handling. */ + +enum ppc_nop_encoding_for_rs_align_code +{ + PPC_NOP_VANILLA, + PPC_NOP_VLE, + PPC_NOP_GROUP_P6, + PPC_NOP_GROUP_P7 +}; + +unsigned int +ppc_nop_select (void) +{ + if ((ppc_cpu & PPC_OPCODE_VLE) != 0) + return PPC_NOP_VLE; + if ((ppc_cpu & (PPC_OPCODE_POWER9 | PPC_OPCODE_E500MC)) == 0) + { + if ((ppc_cpu & PPC_OPCODE_POWER7) != 0) + return PPC_NOP_GROUP_P7; + if ((ppc_cpu & PPC_OPCODE_POWER6) != 0) + return PPC_NOP_GROUP_P6; + } + return PPC_NOP_VANILLA; +} void ppc_handle_align (struct frag *fragP) { valueT count = (fragP->fr_next->fr_address - (fragP->fr_address + fragP->fr_fix)); + char *dest = fragP->fr_literal + fragP->fr_fix; + enum ppc_nop_encoding_for_rs_align_code nop_select = *dest & 0xff; + + /* Pad with zeros if not inserting a whole number of instructions. + We could pad with zeros up to an instruction boundary then follow + with nops but odd counts indicate data in an executable section + so padding with zeros is most appropriate. */ + if (count == 0 + || nop_select == PPC_NOP_VLE ? (count & 1) != 0 : (count & 3) != 0) + { + *dest = 0; + return; + } - if ((ppc_cpu & PPC_OPCODE_VLE) != 0 && count != 0 && (count & 1) == 0) + if (nop_select == PPC_NOP_VLE) { - char *dest = fragP->fr_literal + fragP->fr_fix; fragP->fr_var = 2; md_number_to_chars (dest, 0x4400, 2); } - else if (count != 0 && (count & 3) == 0) + else { - char *dest = fragP->fr_literal + fragP->fr_fix; - fragP->fr_var = 4; if (count > 4 * nop_limit && count < 0x2000000) @@ -7125,8 +7164,7 @@ ppc_handle_align (struct frag *fragP) md_number_to_chars (dest, 0x60000000, 4); - if ((ppc_cpu & PPC_OPCODE_POWER6) != 0 - && (ppc_cpu & PPC_OPCODE_POWER9) == 0) + if (nop_select >= PPC_NOP_GROUP_P6) { /* For power6, power7, and power8, we want the last nop to be a group terminating one. Do this by inserting an @@ -7146,18 +7184,12 @@ ppc_handle_align (struct frag *fragP) dest = group_nop->fr_literal; } - if ((ppc_cpu & PPC_OPCODE_POWER7) != 0) - { - if (ppc_cpu & PPC_OPCODE_E500MC) - /* e500mc group terminating nop: "ori 0,0,0". */ - md_number_to_chars (dest, 0x60000000, 4); - else - /* power7/power8 group terminating nop: "ori 2,2,0". */ - md_number_to_chars (dest, 0x60420000, 4); - } - else + if (nop_select == PPC_NOP_GROUP_P6) /* power6 group terminating nop: "ori 1,1,0". */ md_number_to_chars (dest, 0x60210000, 4); + else + /* power7/power8 group terminating nop: "ori 2,2,0". */ + md_number_to_chars (dest, 0x60420000, 4); } } } |