Commit 5b161fc3 authored by Doug Gilbert's avatar Doug Gilbert Committed by Patrick Williams

PowerPC PPE42 modifications

parent 237df3fa
......@@ -3183,6 +3183,7 @@ instruction. */
BFD_RELOC_PPC_EMB_RELST_HA,
BFD_RELOC_PPC_EMB_BIT_FLD,
BFD_RELOC_PPC_EMB_RELSDA,
BFD_RELOC_PPC_PPE_REL10,
BFD_RELOC_PPC_VLE_REL8,
BFD_RELOC_PPC_VLE_REL15,
BFD_RELOC_PPC_VLE_REL24,
......
......@@ -1402,6 +1402,22 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A relative 12 bit branch. */
HOWTO (R_PPC_PPE_REL10, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
10, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PPE_REL10", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x7fe, /* dst_mask */
TRUE), /* pcrel_offset */
/* A relative 8 bit branch. */
HOWTO (R_PPC_VLE_REL8, /* type */
1, /* rightshift */
......@@ -1958,6 +1974,7 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break;
case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break;
case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break;
case BFD_RELOC_PPC_PPE_REL10: r = R_PPC_PPE_REL10; break;
case BFD_RELOC_PPC_VLE_REL8: r = R_PPC_VLE_REL8; break;
case BFD_RELOC_PPC_VLE_REL15: r = R_PPC_VLE_REL15; break;
case BFD_RELOC_PPC_VLE_REL24: r = R_PPC_VLE_REL24; break;
......@@ -4121,6 +4138,7 @@ ppc_elf_check_relocs (bfd *abfd,
}
break;
case R_PPC_PPE_REL10:
case R_PPC_VLE_REL8:
case R_PPC_VLE_REL15:
case R_PPC_VLE_REL24:
......@@ -8236,6 +8254,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_UADDR16:
goto dodyn;
case R_PPC_PPE_REL10:
case R_PPC_VLE_REL8:
case R_PPC_VLE_REL15:
case R_PPC_VLE_REL24:
......
......@@ -1359,6 +1359,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_PPC_EMB_RELST_HA",
"BFD_RELOC_PPC_EMB_BIT_FLD",
"BFD_RELOC_PPC_EMB_RELSDA",
"BFD_RELOC_PPC_PPE_REL10",
"BFD_RELOC_PPC_VLE_REL8",
"BFD_RELOC_PPC_VLE_REL15",
"BFD_RELOC_PPC_VLE_REL24",
......
......@@ -2815,6 +2815,8 @@ ENUMX
BFD_RELOC_PPC_EMB_BIT_FLD
ENUMX
BFD_RELOC_PPC_EMB_RELSDA
ENUMX
BFD_RELOC_PPC_PPE_REL10
ENUMX
BFD_RELOC_PPC_VLE_REL8
ENUMX
......
......@@ -141,7 +141,7 @@ host_libs="intl libiberty opcodes bfd readline tcl tk itcl libgui zlib libbacktr
# binutils, gas and ld appear in that order because it makes sense to run
# "make check" in that particular order.
# If --enable-gold is used, "gold" may replace "ld".
host_tools="texinfo flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools"
host_tools="flex bison binutils gas ld fixincludes gcc cgen sid sim gdb gprof etc expect dejagnu m4 utils guile fastjar gnattools"
# libgcj represents the runtime libraries only used by gcj.
libgcj="target-libffi \
......
......@@ -177,6 +177,8 @@ enum
R_PPC64_DTPREL16_HIGHA = 115,
R_PPC_EMB_RELSDA = 116,
R_PPC_PPE_REL10 = 200,
R_PPC_VLE_REL8 = 216,
R_PPC_VLE_REL15 = 217,
R_PPC_VLE_REL24 = 218,
......@@ -204,6 +206,7 @@ enum
R_POWERPC_GNU_VTINHERIT = 253,
R_POWERPC_GNU_VTENTRY = 254,
R_PPC_TOC16 = 255,
};
// e_flags values defined for powerpc
......
......@@ -364,6 +364,36 @@ static const struct pd_reg pre_defined_registers[] =
{ "ctr", 9 },
{ "d.0", 0 }, /* Double Word Regs for PPE */
{ "d.1", 1 },
{ "d.2", 2 },
{ "d.28", 28 },
{ "d.29", 29 },
{ "d.3", 3 },
{ "d.30", 30 },
{ "d.31", 31 },
{ "d.4", 4 },
{ "d.5", 5 },
{ "d.6", 6 },
{ "d.7", 7 },
{ "d.8", 8 },
{ "d.9", 9 },
{ "d0", 0 }, /* More Double Word Regs for PPE */
{ "d1", 1 },
{ "d2", 2 },
{ "d28", 28 },
{ "d29", 29 },
{ "d3", 3 },
{ "d30", 30 },
{ "d31", 31 },
{ "d4", 4 },
{ "d5", 5 },
{ "d6", 6 },
{ "d7", 7 },
{ "d8", 8 },
{ "d9", 9 },
{ "dar", 19 }, /* Data Access Register */
{ "dec", 22 }, /* Decrementer */
{ "dsisr", 18 }, /* Data Storage Interrupt Status Register */
......@@ -1272,6 +1302,7 @@ PowerPC options:\n\
generate code for PowerPC 603/604\n\
-m403 generate code for PowerPC 403\n\
-m405 generate code for PowerPC 405\n\
-mppe42 generate code for PowerPC ppe\n\
-m440 generate code for PowerPC 440\n\
-m464 generate code for PowerPC 464\n\
-m476 generate code for PowerPC 476\n\
......@@ -1362,7 +1393,7 @@ ppc_arch (void)
const char *default_cpu = TARGET_CPU;
ppc_set_cpu ();
if ((ppc_cpu & PPC_OPCODE_PPC) != 0)
if ((ppc_cpu & (PPC_OPCODE_PPC | PPC_OPCODE_PPE)) != 0)
return bfd_arch_powerpc;
if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
return bfd_arch_powerpc;
......@@ -1820,6 +1851,47 @@ ppc_insert_operand (unsigned long insn,
as_bad_value_out_of_range (_("operand"), val, min, max, file, line);
}
if (cpu & PPC_OPCODE_PPE)
{
if (operand->flags & (PPC_OPERAND_GPR | PPC_OPERAND_GPR_0))
switch(val)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6:
case 7: case 8: case 9: case 10: case 13:
case 28: case 29: case 30: case 31:
break;
/* do nothing */
default:
if (val > 1 && val < 31)
as_bad_where (file, line, "%s %d", "Invalid PPE register: ", (int)val);
break;
}
else if (operand->flags & PPC_OPERAND_GPVDR)
switch(val)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6:
case 7: case 8: case 9:
case 28: case 29: case 30: case 31:
break;
/* do nothing */
default:
if (val > 0 && val < 31)
as_bad_where (file, line, "%s %d %x", "Invalid PPE virtual double register:", (int)val, (unsigned)operand->flags);
break;
}
else if (operand->flags & PPC_OPERAND_CR_REG)
switch(val)
{
case 0:
break;
/* do nothing */
default:
if (val != 0)
as_bad_where (file, line, "%s %d %x", "Invalid PPE Condition register:", (int)val, (unsigned)operand->flags);
break;
}
}
if (operand->insert)
{
const char *errmsg;
......@@ -3255,6 +3327,10 @@ md_assemble (char *str)
&& operand->bitm == 0xfffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_B16;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0xffc
&& operand->shift == -1)
reloc = BFD_RELOC_PPC_PPE_REL10;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0x1fe
&& operand->shift == -1)
......@@ -7030,6 +7106,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_24_PLT_PCREL:
case BFD_RELOC_32_PLT_PCREL:
case BFD_RELOC_64_PLT_PCREL:
case BFD_RELOC_PPC_PPE_REL10:
case BFD_RELOC_PPC_VLE_REL8:
case BFD_RELOC_PPC_VLE_REL15:
case BFD_RELOC_PPC_VLE_REL24:
......
......@@ -131,6 +131,9 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type)
RELOC_NUMBER (R_PPC_EMB_BIT_FLD, 115)
RELOC_NUMBER (R_PPC_EMB_RELSDA, 116)
/* PowerPC PPE relocations. */
RELOC_NUMBER (R_PPC_PPE_REL10, 200)
/* PowerPC VLE relocations. */
RELOC_NUMBER (R_PPC_VLE_REL8, 216)
RELOC_NUMBER (R_PPC_VLE_REL15, 217)
......
......@@ -191,6 +191,9 @@ extern const int vle_num_opcodes;
/* Opcode is only supported by Power8 architecture. */
#define PPC_OPCODE_POWER8 0x2000000000ull
/* Opcode is only supported by PPE architecture. */
#define PPC_OPCODE_PPE 0x8000000000ull
/* Opcode which is supported by the Hardware Transactional Memory extension. */
/* Currently, this is the same as the POWER8 mask. If another cpu comes out
that isn't a superset of POWER8, we can define this to its own mask. */
......@@ -386,6 +389,12 @@ extern const unsigned int num_powerpc_operands;
with the operands table for simplicity. The macro table is an
array of struct powerpc_macro. */
/* This operand names a general purpose double register. PPE42 specific.
* The disassembler uses this to print
register names with a leading 'd'. */
#define PPC_OPERAND_GPVDR (0x400000)
struct powerpc_macro
{
/* The macro name. */
......@@ -409,5 +418,8 @@ extern const struct powerpc_macro powerpc_macros[];
extern const int powerpc_num_macros;
extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
extern int string_print_insn_powerpc (unsigned long insn,
uint64_t dialect, char * assemblyString);
extern void disassemble_init_powerpc_standalone (void);
#endif /* PPC_H */
......@@ -34,7 +34,7 @@
in both big and little endian mode and also for the POWER (RS/6000)
chip. */
static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
ppc_cpu_t);
ppc_cpu_t);
struct dis_private
{
......@@ -56,14 +56,16 @@ struct ppc_mopt ppc_opts[] = {
0 },
{ "405", (PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405),
0 },
{ "ppe42", (PPC_OPCODE_PPE),
0 },
{ "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
| PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
| PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
0 },
{ "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
| PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
| PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
0 },
{ "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_440
| PPC_OPCODE_476 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
| PPC_OPCODE_476 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
0 },
{ "601", (PPC_OPCODE_PPC | PPC_OPCODE_601),
0 },
......@@ -84,8 +86,8 @@ struct ppc_mopt ppc_opts[] = {
{ "750cl", (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS)
, 0 },
{ "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
| PPC_OPCODE_A2),
| PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
| PPC_OPCODE_A2),
0 },
{ "altivec", (PPC_OPCODE_PPC),
PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 },
......@@ -96,61 +98,61 @@ struct ppc_mopt ppc_opts[] = {
{ "booke32", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE),
0 },
{ "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
| PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
0 },
{ "com", (PPC_OPCODE_COMMON),
0 },
{ "e300", (PPC_OPCODE_PPC | PPC_OPCODE_E300),
0 },
{ "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500),
| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500),
0 },
{ "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC),
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC),
0 },
{ "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
0 },
{ "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7),
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7),
0 },
{ "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
| PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_E6500 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
| PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_E6500 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
0 },
{ "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500),
| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
| PPC_OPCODE_E500),
0 },
{ "efs", (PPC_OPCODE_PPC | PPC_OPCODE_EFS),
0 },
{ "power4", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4),
0 },
{ "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5),
| PPC_OPCODE_POWER5),
0 },
{ "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
0 },
{ "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
0 },
{ "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
0 },
{ "ppc", (PPC_OPCODE_PPC),
0 },
......@@ -169,29 +171,29 @@ struct ppc_mopt ppc_opts[] = {
{ "pwr4", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4),
0 },
{ "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5),
| PPC_OPCODE_POWER5),
0 },
{ "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5),
| PPC_OPCODE_POWER5),
0 },
{ "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
0 },
{ "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
0 },
{ "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
0 },
{ "pwrx", (PPC_OPCODE_POWER | PPC_OPCODE_POWER2),
0 },
{ "spe", (PPC_OPCODE_PPC | PPC_OPCODE_EFS),
PPC_OPCODE_SPE },
{ "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
| PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
| PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
0 },
{ "vle", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_VLE),
PPC_OPCODE_VLE },
......@@ -230,14 +232,14 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
for (i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++)
if (strcmp (ppc_opts[i].opt, arg) == 0)
{
if (ppc_opts[i].sticky)
{
*sticky |= ppc_opts[i].sticky;
if ((ppc_cpu & ~*sticky) != 0)
break;
}
ppc_cpu = ppc_opts[i].cpu;
break;
if (ppc_opts[i].sticky)
{
*sticky |= ppc_opts[i].sticky;
if ((ppc_cpu & ~*sticky) != 0)
break;
}
ppc_cpu = ppc_opts[i].cpu;
break;
}
if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0]))
return 0;
......@@ -308,19 +310,19 @@ powerpc_init_dialect (struct disassemble_info *info)
char *end = strchr (arg, ',');
if (end != NULL)
*end = 0;
*end = 0;
if ((new_cpu = ppc_parse_cpu (dialect, &sticky, arg)) != 0)
dialect = new_cpu;
dialect = new_cpu;
else if (strcmp (arg, "32") == 0)
dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
else if (strcmp (arg, "64") == 0)
dialect |= PPC_OPCODE_64;
dialect |= PPC_OPCODE_64;
else
fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg);
fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg);
if (end != NULL)
*end++ = ',';
*end++ = ',';
arg = end;
}
......@@ -354,7 +356,7 @@ disassemble_init_powerpc (struct disassemble_info *info)
for (i = PPC_OPCD_SEGS; i > 0; --i)
{
if (powerpc_opcd_indices[i] == 0)
powerpc_opcd_indices[i] = last;
powerpc_opcd_indices[i] = last;
last = powerpc_opcd_indices[i];
}
......@@ -371,7 +373,7 @@ disassemble_init_powerpc (struct disassemble_info *info)
for (i = VLE_OPCD_SEGS; i > 0; --i)
{
if (vle_opcd_indices[i] == 0)
vle_opcd_indices[i] = last;
vle_opcd_indices[i] = last;
last = vle_opcd_indices[i];
}
......@@ -379,6 +381,33 @@ disassemble_init_powerpc (struct disassemble_info *info)
powerpc_init_dialect (info);
}
/* Calculate opcode table indices to speed up disassembly,
and init dialect. */
void
disassemble_init_powerpc_standalone ()
{
int i;
unsigned short last;
i = powerpc_num_opcodes;
while (--i >= 0)
{
unsigned op = PPC_OP (powerpc_opcodes[i].opcode);
powerpc_opcd_indices[op] = i;
}
last = powerpc_num_opcodes;
for (i = PPC_OPCD_SEGS; i > 0; --i)
{
if (powerpc_opcd_indices[i] == 0)
powerpc_opcd_indices[i] = last;
last = powerpc_opcd_indices[i];
}
}
/* Print a big endian PowerPC instruction. */
int
......@@ -407,7 +436,7 @@ print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
static long
operand_value_powerpc (const struct powerpc_operand *operand,
unsigned long insn, ppc_cpu_t dialect)
unsigned long insn, ppc_cpu_t dialect)
{
long value;
int invalid;
......@@ -417,20 +446,20 @@ operand_value_powerpc (const struct powerpc_operand *operand,
else
{
if (operand->shift >= 0)
value = (insn >> operand->shift) & operand->bitm;
value = (insn >> operand->shift) & operand->bitm;
else
value = (insn << -operand->shift) & operand->bitm;
value = (insn << -operand->shift) & operand->bitm;
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
{
/* BITM is always some number of zeros followed by some
number of ones, followed by some number of zeros. */
unsigned long top = operand->bitm;
/* top & -top gives the rightmost 1 bit, so this
fills in any trailing zeros. */
top |= (top & -top) - 1;
top &= ~(top >> 1);
value = (value ^ top) - top;
}
{
/* BITM is always some number of zeros followed by some
number of ones, followed by some number of zeros. */
unsigned long top = operand->bitm;
/* top & -top gives the rightmost 1 bit, so this
fills in any trailing zeros. */
top |= (top & -top) - 1;
top &= ~(top >> 1);
value = (value ^ top) - top;
}
}
return value;
......@@ -440,7 +469,7 @@ operand_value_powerpc (const struct powerpc_operand *operand,
static int
skip_optional_operands (const unsigned char *opindex,
unsigned long insn, ppc_cpu_t dialect)
unsigned long insn, ppc_cpu_t dialect)
{
const struct powerpc_operand *operand;
......@@ -448,9 +477,9 @@ skip_optional_operands (const unsigned char *opindex,
{
operand = &powerpc_operands[*opindex];
if ((operand->flags & PPC_OPERAND_NEXT) != 0
|| ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
&& operand_value_powerpc (operand, insn, dialect) != 0))
return 0;
|| ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
&& operand_value_powerpc (operand, insn, dialect) != 0))
return 0;
}
return 1;
......@@ -480,21 +509,21 @@ lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
int invalid;
if ((insn & opcode->mask) != opcode->opcode
|| (dialect != (ppc_cpu_t) -1
&& ((opcode->flags & dialect) == 0
|| (opcode->deprecated & dialect) != 0)))
continue;
|| (dialect != (ppc_cpu_t) -1
&& ((opcode->flags & dialect) == 0
|| (opcode->deprecated & dialect) != 0)))
continue;
/* Check validity of operands. */
invalid = 0;
for (opindex = opcode->operands; *opindex != 0; opindex++)
{
operand = powerpc_operands + *opindex;
if (operand->extract)
(*operand->extract) (insn, dialect, &invalid);
}
{
operand = powerpc_operands + *opindex;
if (operand->extract)
(*operand->extract) (insn, dialect, &invalid);
}
if (invalid)
continue;
continue;
return opcode;
}
......@@ -535,20 +564,20 @@ lookup_vle (unsigned long insn)
insn2 = insn;
if (table_op_is_short)
insn2 >>= 16;
insn2 >>= 16;
if ((insn2 & table_mask) != table_opcd)
continue;
continue;
/* Check validity of operands. */
invalid = 0;
for (opindex = opcode->operands; *opindex != 0; ++opindex)
{
operand = powerpc_operands + *opindex;
if (operand->extract)
(*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
}
{
operand = powerpc_operands + *opindex;
if (operand->extract)
(*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
}
if (invalid)
continue;
continue;
return opcode;
}
......@@ -560,9 +589,9 @@ lookup_vle (unsigned long insn)
static int
print_insn_powerpc (bfd_vma memaddr,
struct disassemble_info *info,
int bigendian,
ppc_cpu_t dialect)
struct disassemble_info *info,
int bigendian,
ppc_cpu_t dialect)
{
bfd_byte buffer[4];
int status;
......@@ -604,7 +633,7 @@ print_insn_powerpc (bfd_vma memaddr,
{
opcode = lookup_vle (insn);
if (opcode != NULL)
insn_is_short = PPC_OP_SE_VLE(opcode->mask);
insn_is_short = PPC_OP_SE_VLE(opcode->mask);
}
if (opcode == NULL)
opcode = lookup_powerpc (insn, dialect);
......@@ -620,9 +649,9 @@ print_insn_powerpc (bfd_vma memaddr,
int skip_optional;
if (opcode->operands[0] != 0)
(*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
(*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
else
(*info->fprintf_func) (info->stream, "%s", opcode->name);
(*info->fprintf_func) (info->stream, "%s", opcode->name);
if (insn_is_short)
/* The operands will be fetched out of the 16-bit instruction. */
......@@ -633,91 +662,93 @@ print_insn_powerpc (bfd_vma memaddr,
need_paren = 0;
skip_optional = -1;
for (opindex = opcode->operands; *opindex != 0; opindex++)
{
long value;
operand = powerpc_operands + *opindex;
/* Operands that are marked FAKE are simply ignored. We
already made sure that the extract function considered
the instruction to be valid. */
if ((operand->flags & PPC_OPERAND_FAKE) != 0)
continue;
/* If all of the optional operands have the value zero,
then don't print any of them. */
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
{
if (skip_optional < 0)
skip_optional = skip_optional_operands (opindex, insn,
dialect);
if (skip_optional)
continue;
}
value = operand_value_powerpc (operand, insn, dialect);
if (need_comma)
{
(*info->fprintf_func) (info->stream, ",");
need_comma = 0;
}
/* Print the operand as directed by the flags. */
if ((operand->flags & PPC_OPERAND_GPR) != 0
|| ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
(*info->fprintf_func) (info->stream, "r%ld", value);
else if ((operand->flags & PPC_OPERAND_FPR) != 0)
(*info->fprintf_func) (info->stream, "f%ld", value);
else if ((operand->flags & PPC_OPERAND_VR) != 0)
(*info->fprintf_func) (info->stream, "v%ld", value);
else if ((operand->flags & PPC_OPERAND_VSR) != 0)