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>
|
||||
|
||||
PR binutils/24700
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,9 @@ extern const char *ppc_target_format (void);
|
|||
if ((FRAGP)->fr_type == rs_align_code) \
|
||||
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_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 "altivec_xcoff"
|
||||
run_dump_test "altivec_xcoff64"
|
||||
run_dump_test "groupnop"
|
||||
}
|
||||
|
||||
# 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 "broadway"
|
||||
run_dump_test "booke"
|
||||
run_dump_test "groupnop"
|
||||
run_dump_test "e500"
|
||||
run_list_test "e500-ill" "-me500"
|
||||
run_dump_test "ppc750ps"
|
||||
|
|
Loading…
Reference in New Issue