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.
This commit is contained in:
parent
2e7c439dec
commit
22f72c4868
|
@ -1,3 +1,15 @@
|
||||||
|
2019-06-25 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2019-06-19 H.J. Lu <hongjiu.lu@intel.com>
|
2019-06-19 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR binutils/24700
|
PR binutils/24700
|
||||||
|
|
|
@ -2608,6 +2608,12 @@ ppc_elf_end (void)
|
||||||
elf_elfheader (stdoutput)->e_flags &= ~EF_PPC64_ABI;
|
elf_elfheader (stdoutput)->e_flags &= ~EF_PPC64_ABI;
|
||||||
elf_elfheader (stdoutput)->e_flags |= ppc_abiversion & 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
|
/* 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);
|
symbol_set_value_now (dwss->end_exp.X_add_symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ppc_cpu = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* OBJ_XCOFF */
|
#endif /* OBJ_XCOFF */
|
||||||
|
@ -7077,26 +7084,58 @@ ppc_frag_check (struct frag *fragP)
|
||||||
fragP->insn_addr + 1);
|
fragP->insn_addr + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implement HANDLE_ALIGN. This writes the NOP pattern into an
|
/* rs_align_code frag handling. */
|
||||||
rs_align_code frag. */
|
|
||||||
|
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
|
void
|
||||||
ppc_handle_align (struct frag *fragP)
|
ppc_handle_align (struct frag *fragP)
|
||||||
{
|
{
|
||||||
valueT count = (fragP->fr_next->fr_address
|
valueT count = (fragP->fr_next->fr_address
|
||||||
- (fragP->fr_address + fragP->fr_fix));
|
- (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;
|
||||||
|
|
||||||
if ((ppc_cpu & PPC_OPCODE_VLE) != 0 && count != 0 && (count & 1) == 0)
|
/* 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 (nop_select == PPC_NOP_VLE)
|
||||||
{
|
{
|
||||||
char *dest = fragP->fr_literal + fragP->fr_fix;
|
|
||||||
|
|
||||||
fragP->fr_var = 2;
|
fragP->fr_var = 2;
|
||||||
md_number_to_chars (dest, 0x4400, 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;
|
fragP->fr_var = 4;
|
||||||
|
|
||||||
if (count > 4 * nop_limit && count < 0x2000000)
|
if (count > 4 * nop_limit && count < 0x2000000)
|
||||||
|
@ -7125,8 +7164,7 @@ ppc_handle_align (struct frag *fragP)
|
||||||
|
|
||||||
md_number_to_chars (dest, 0x60000000, 4);
|
md_number_to_chars (dest, 0x60000000, 4);
|
||||||
|
|
||||||
if ((ppc_cpu & PPC_OPCODE_POWER6) != 0
|
if (nop_select >= PPC_NOP_GROUP_P6)
|
||||||
&& (ppc_cpu & PPC_OPCODE_POWER9) == 0)
|
|
||||||
{
|
{
|
||||||
/* For power6, power7, and power8, we want the last nop to
|
/* For power6, power7, and power8, we want the last nop to
|
||||||
be a group terminating one. Do this by inserting an
|
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;
|
dest = group_nop->fr_literal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ppc_cpu & PPC_OPCODE_POWER7) != 0)
|
if (nop_select == PPC_NOP_GROUP_P6)
|
||||||
{
|
|
||||||
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
|
|
||||||
/* power6 group terminating nop: "ori 1,1,0". */
|
/* power6 group terminating nop: "ori 1,1,0". */
|
||||||
md_number_to_chars (dest, 0x60210000, 4);
|
md_number_to_chars (dest, 0x60210000, 4);
|
||||||
|
else
|
||||||
|
/* power7/power8 group terminating nop: "ori 2,2,0". */
|
||||||
|
md_number_to_chars (dest, 0x60420000, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,9 @@ extern const char *ppc_target_format (void);
|
||||||
if ((FRAGP)->fr_type == rs_align_code) \
|
if ((FRAGP)->fr_type == rs_align_code) \
|
||||||
ppc_handle_align (FRAGP);
|
ppc_handle_align (FRAGP);
|
||||||
|
|
||||||
|
extern unsigned int ppc_nop_select (void);
|
||||||
|
#define NOP_OPCODE ppc_nop_select ()
|
||||||
|
|
||||||
extern void ppc_handle_align (struct frag *);
|
extern void ppc_handle_align (struct frag *);
|
||||||
extern void ppc_frag_check (struct frag *);
|
extern void ppc_frag_check (struct frag *);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#as:
|
||||||
|
#objdump: -dr
|
||||||
|
|
||||||
|
.*
|
||||||
|
|
||||||
|
Disassembly of section \.text:
|
||||||
|
|
||||||
|
0+ <\.text>:
|
||||||
|
0: (60 00 00 00|00 00 00 60) .*
|
||||||
|
4: (60 00 00 00|00 00 00 60) .*
|
||||||
|
8: (60 00 00 00|00 00 00 60) .*
|
||||||
|
c: (60 42 00 00|00 00 42 60) .*
|
||||||
|
10: (60 00 00 00|00 00 00 60) .*
|
||||||
|
14: (60 42 00 00|00 00 42 60) .*
|
||||||
|
18: (60 00 00 00|00 00 00 60) .*
|
||||||
|
1c: (60 21 00 00|00 00 21 60) .*
|
||||||
|
20: (60 00 00 00|00 00 00 60) .*
|
||||||
|
24: (60 00 00 00|00 00 00 60) .*
|
||||||
|
#pass
|
|
@ -0,0 +1,19 @@
|
||||||
|
.machine power9
|
||||||
|
nop
|
||||||
|
.p2align 3
|
||||||
|
|
||||||
|
.machine power8
|
||||||
|
nop
|
||||||
|
.p2align 3
|
||||||
|
|
||||||
|
.machine power7
|
||||||
|
nop
|
||||||
|
.p2align 3
|
||||||
|
|
||||||
|
.machine power6
|
||||||
|
nop
|
||||||
|
.p2align 3
|
||||||
|
|
||||||
|
.machine power5
|
||||||
|
nop
|
||||||
|
.p2align 3
|
|
@ -51,6 +51,7 @@ if { [istarget "*-*-aix*"]
|
||||||
run_dump_test "test2xcoff32"
|
run_dump_test "test2xcoff32"
|
||||||
run_dump_test "altivec_xcoff"
|
run_dump_test "altivec_xcoff"
|
||||||
run_dump_test "altivec_xcoff64"
|
run_dump_test "altivec_xcoff64"
|
||||||
|
run_dump_test "groupnop"
|
||||||
}
|
}
|
||||||
|
|
||||||
# These tests are currently ELF specific, only because nobody has
|
# These tests are currently ELF specific, only because nobody has
|
||||||
|
@ -105,6 +106,7 @@ run_dump_test "altivec2"
|
||||||
run_dump_test "altivec3"
|
run_dump_test "altivec3"
|
||||||
run_dump_test "broadway"
|
run_dump_test "broadway"
|
||||||
run_dump_test "booke"
|
run_dump_test "booke"
|
||||||
|
run_dump_test "groupnop"
|
||||||
run_dump_test "e500"
|
run_dump_test "e500"
|
||||||
run_list_test "e500-ill" "-me500"
|
run_list_test "e500-ill" "-me500"
|
||||||
run_dump_test "ppc750ps"
|
run_dump_test "ppc750ps"
|
||||||
|
|
Loading…
Reference in New Issue