diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-01 10:10:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-01 10:10:16 -0800 |
commit | b286cedd473006b33d5ae076afac509e6b2c3bf4 (patch) | |
tree | f45cbb0337238771d6ebe2220f9d5b4f02771903 /arch/powerpc/xmon | |
parent | 522214d9be9c9f00f34ed89cb95e901b7ac31c59 (diff) | |
parent | 9f3768e02335ddd6ebe1d85d5cb3a68ee6264004 (diff) |
Merge tag 'powerpc-4.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull more powerpc updates from Michael Ellerman:
"Highlights include:
- an update of the disassembly code used by xmon to the latest
versions in binutils. We've received permission from all the
authors of the relevant binutils changes to relicense their changes
to the relevant files from GPLv3 to GPLv2, for inclusion in Linux.
Thanks to Peter Bergner for doing the leg work to get permission
from everyone.
- addition of the "architected" Power9 CPU table entry, allowing us
to boot in Power9 architected mode under a hypervisor.
- updates to the Power9 PMU code.
- implementation of clear_bit_unlock_is_negative_byte() to optimise
unlock_page().
- Freescale updates from Scott: "Highlights include 8xx breakpoints
and perf, t1042rdb display support, and board updates."
Thanks to:
Al Viro, Andrew Donnellan, Aneesh Kumar K.V, Balbir Singh, Douglas
Miller, Frédéric Weisbecker, Gavin Shan, Madhavan Srinivasan,
Michael Roth, Nathan Fontenot, Naveen N. Rao, Nicholas Piggin, Peter
Bergner, Paul E. McKenney, Rashmica Gupta, Russell Currey, Sahil
Mehta, Stewart Smith"
* tag 'powerpc-4.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (48 commits)
powerpc: Remove leftover cputime_to_nsecs call causing build error
powerpc/mm/hash: Always clear UPRT and Host Radix bits when setting up CPU
powerpc/optprobes: Fix TOC handling in optprobes trampoline
powerpc/pseries: Advertise Hot Plug Event support to firmware
cxl: fix nested locking hang during EEH hotplug
powerpc/xmon: Dump memory in CPU endian format
powerpc/pseries: Revert 'Auto-online hotplugged memory'
powerpc/powernv: Make PCI non-optional
powerpc/64: Implement clear_bit_unlock_is_negative_byte()
powerpc/powernv: Remove unused variable in pnv_pci_sriov_disable()
powerpc/kernel: Remove error message in pcibios_setup_phb_resources()
powerpc/mm: Fix typo in set_pte_at()
pci/hotplug/pnv-php: Disable MSI and PCI device properly
pci/hotplug/pnv-php: Disable surprise hotplug capability on conflicts
pci/hotplug/pnv-php: Remove WARN_ON() in pnv_php_put_slot()
powerpc: Add POWER9 architected mode to cputable
powerpc/perf: use is_kernel_addr macro in perf_get_misc_flags()
powerpc/perf: Avoid FAB_*_MATCH checks for power9
powerpc/perf: Add restrictions to PMC5 in power9 DD1
powerpc/perf: Use Instruction Counter value
...
Diffstat (limited to 'arch/powerpc/xmon')
-rw-r--r-- | arch/powerpc/xmon/ppc-dis.c | 260 | ||||
-rw-r--r-- | arch/powerpc/xmon/ppc-opc.c | 8999 | ||||
-rw-r--r-- | arch/powerpc/xmon/ppc.h | 268 | ||||
-rw-r--r-- | arch/powerpc/xmon/xmon.c | 58 |
4 files changed, 6085 insertions, 3500 deletions
diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c index ee9891734149..31db8c072acd 100644 --- a/arch/powerpc/xmon/ppc-dis.c +++ b/arch/powerpc/xmon/ppc-dis.c @@ -1,6 +1,5 @@ /* ppc-dis.c -- Disassemble PowerPC instructions - Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1994-2016 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support This file is part of GDB, GAS, and the GNU binutils. @@ -26,57 +25,94 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, US #include "ppc.h" #include "dis-asm.h" -/* Print a PowerPC or POWER instruction. */ +/* This file provides several disassembler functions, all of which use + the disassembler interface defined in dis-asm.h. Several functions + are provided because this file handles disassembly for the PowerPC + in both big and little endian mode and also for the POWER (RS/6000) + chip. */ + +/* Extract the operand value from the PowerPC or POWER instruction. */ -int -print_insn_powerpc (unsigned long insn, unsigned long memaddr) +static long +operand_value_powerpc (const struct powerpc_operand *operand, + unsigned long insn, ppc_cpu_t dialect) { - const struct powerpc_opcode *opcode; - const struct powerpc_opcode *opcode_end; - unsigned long op; - int dialect; + long value; + int invalid; + /* Extract the value from the instruction. */ + if (operand->extract) + value = (*operand->extract) (insn, dialect, &invalid); + else + { + if (operand->shift >= 0) + value = (insn >> operand->shift) & operand->bitm; + else + 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; + } + } - dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON - | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC; + return value; +} - if (cpu_has_feature(CPU_FTRS_POWER5)) - dialect |= PPC_OPCODE_POWER5; +/* Determine whether the optional operand(s) should be printed. */ - if (cpu_has_feature(CPU_FTRS_CELL)) - dialect |= PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC; +static int +skip_optional_operands (const unsigned char *opindex, + unsigned long insn, ppc_cpu_t dialect) +{ + const struct powerpc_operand *operand; - if (cpu_has_feature(CPU_FTRS_POWER6)) - dialect |= PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC; + for (; *opindex != 0; opindex++) + { + operand = &powerpc_operands[*opindex]; + if ((operand->flags & PPC_OPERAND_NEXT) != 0 + || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 + && operand_value_powerpc (operand, insn, dialect) != + ppc_optional_operand_value (operand))) + return 0; + } + + return 1; +} + +/* Find a match for INSN in the opcode table, given machine DIALECT. + A DIALECT of -1 is special, matching all machine opcode variations. */ + +static const struct powerpc_opcode * +lookup_powerpc (unsigned long insn, ppc_cpu_t dialect) +{ + const struct powerpc_opcode *opcode; + const struct powerpc_opcode *opcode_end; + unsigned long op; /* Get the major opcode of the instruction. */ op = PPC_OP (insn); - /* Find the first match in the opcode table. We could speed this up - a bit by doing a binary search on the major opcode. */ opcode_end = powerpc_opcodes + powerpc_num_opcodes; - again: - for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++) + /* Find the first match in the opcode table for this major opcode. */ + for (opcode = powerpc_opcodes; opcode < opcode_end; ++opcode) { - unsigned long table_op; const unsigned char *opindex; const struct powerpc_operand *operand; int invalid; - int need_comma; - int need_paren; - - table_op = PPC_OP (opcode->opcode); - if (op < table_op) - break; - if (op > table_op) - continue; if ((insn & opcode->mask) != opcode->opcode - || (opcode->flags & dialect) == 0) + || (dialect != (ppc_cpu_t) -1 + && ((opcode->flags & dialect) == 0 + || (opcode->deprecated & dialect) != 0))) continue; - /* Make two passes over the operands. First see if any of them - have extraction functions, and, if they do, make sure the - instruction is valid. */ + /* Check validity of operands. */ invalid = 0; for (opindex = opcode->operands; *opindex != 0; opindex++) { @@ -87,14 +123,77 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr) if (invalid) continue; - /* The instruction is valid. */ - printf("%s", opcode->name); + return opcode; + } + + return NULL; +} + +/* Print a PowerPC or POWER instruction. */ + +int print_insn_powerpc (unsigned long insn, unsigned long memaddr) +{ + const struct powerpc_opcode *opcode; + bool insn_is_short; + ppc_cpu_t dialect; + + dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON + | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC; + + if (cpu_has_feature(CPU_FTRS_POWER5)) + dialect |= PPC_OPCODE_POWER5; + + if (cpu_has_feature(CPU_FTRS_CELL)) + dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC); + + if (cpu_has_feature(CPU_FTRS_POWER6)) + dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC); + + if (cpu_has_feature(CPU_FTRS_POWER7)) + dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 + | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX); + + if (cpu_has_feature(CPU_FTRS_POWER8)) + dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 + | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM + | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX); + + if (cpu_has_feature(CPU_FTRS_POWER9)) + dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 + | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM + | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 + | PPC_OPCODE_VSX | PPC_OPCODE_VSX3), + + /* Get the major opcode of the insn. */ + opcode = NULL; + insn_is_short = false; + + if (opcode == NULL) + opcode = lookup_powerpc (insn, dialect); + if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) + opcode = lookup_powerpc (insn, (ppc_cpu_t) -1); + + if (opcode != NULL) + { + const unsigned char *opindex; + const struct powerpc_operand *operand; + int need_comma; + int need_paren; + int skip_optional; + if (opcode->operands[0] != 0) - printf("\t"); + printf("%-7s ", opcode->name); + else + printf("%s", opcode->name); + + if (insn_is_short) + /* The operands will be fetched out of the 16-bit instruction. */ + insn >>= 16; /* Now extract and print the operands. */ need_comma = 0; need_paren = 0; + skip_optional = -1; for (opindex = opcode->operands; *opindex != 0; opindex++) { long value; @@ -107,23 +206,18 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr) if ((operand->flags & PPC_OPERAND_FAKE) != 0) continue; - /* Extract the value from the instruction. */ - if (operand->extract) - value = (*operand->extract) (insn, dialect, &invalid); - else + /* If all of the optional operands have the value zero, + then don't print any of them. */ + if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) { - value = (insn >> operand->shift) & ((1 << operand->bits) - 1); - if ((operand->flags & PPC_OPERAND_SIGNED) != 0 - && (value & (1 << (operand->bits - 1))) != 0) - value -= 1 << operand->bits; + if (skip_optional < 0) + skip_optional = skip_optional_operands (opindex, insn, + dialect); + if (skip_optional) + continue; } - /* If the operand is optional, and the value is zero, don't - print anything. */ - if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 - && (operand->flags & PPC_OPERAND_NEXT) == 0 - && value == 0) - continue; + value = operand_value_powerpc (operand, insn, dialect); if (need_comma) { @@ -139,30 +233,38 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr) printf("f%ld", value); else if ((operand->flags & PPC_OPERAND_VR) != 0) printf("v%ld", value); + else if ((operand->flags & PPC_OPERAND_VSR) != 0) + printf("vs%ld", value); else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) - print_address (memaddr + value); + print_address(memaddr + value); else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) - print_address (value & 0xffffffff); - else if ((operand->flags & PPC_OPERAND_CR) == 0 - || (dialect & PPC_OPCODE_PPC) == 0) + print_address(value & 0xffffffff); + else if ((operand->flags & PPC_OPERAND_FSL) != 0) + printf("fsl%ld", value); + else if ((operand->flags & PPC_OPERAND_FCR) != 0) + printf("fcr%ld", value); + else if ((operand->flags & PPC_OPERAND_UDI) != 0) printf("%ld", value); - else + else if ((operand->flags & PPC_OPERAND_CR_REG) != 0 + && (((dialect & PPC_OPCODE_PPC) != 0) + || ((dialect & PPC_OPCODE_VLE) != 0))) + printf("cr%ld", value); + else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0) + && (((dialect & PPC_OPCODE_PPC) != 0) + || ((dialect & PPC_OPCODE_VLE) != 0))) { - if (operand->bits == 3) - printf("cr%ld", value); - else - { - static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; - int cr; - int cc; - - cr = value >> 2; - if (cr != 0) - printf("4*cr%d+", cr); - cc = value & 3; - printf("%s", cbnames[cc]); - } + static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; + int cr; + int cc; + + cr = value >> 2; + if (cr != 0) + printf("4*cr%d+", cr); + cc = value & 3; + printf("%s", cbnames[cc]); } + else + printf("%d", (int) value); if (need_paren) { @@ -179,14 +281,16 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr) } } - /* We have found and printed an instruction; return. */ - return 4; - } - - if ((dialect & PPC_OPCODE_ANY) != 0) - { - dialect = ~PPC_OPCODE_ANY; - goto again; + /* We have found and printed an instruction. + If it was a short VLE instruction we have more to do. */ + if (insn_is_short) + { + memaddr += 2; + return 2; + } + else + /* Otherwise, return. */ + return 4; } /* We could not find a match. */ diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c index 954dbf8222d7..ac2b55b1332e 100644 --- a/arch/powerpc/xmon/ppc-opc.c +++ b/arch/powerpc/xmon/ppc-opc.c @@ -1,6 +1,5 @@ /* ppc-opc.c -- PowerPC opcode list - Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, - 2005 Free Software Foundation, Inc. + Copyright (C) 1994-2016 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support This file is part of GDB, GAS, and the GNU binutils. @@ -42,66 +41,97 @@ /* Local insertion and extraction functions. */ -static unsigned long insert_bat (unsigned long, long, int, const char **); -static long extract_bat (unsigned long, int, int *); -static unsigned long insert_bba (unsigned long, long, int, const char **); -static long extract_bba (unsigned long, int, int *); -static unsigned long insert_bd (unsigned long, long, int, const char **); -static long extract_bd (unsigned long, int, int *); -static unsigned long insert_bdm (unsigned long, long, int, const char **); -static long extract_bdm (unsigned long, int, int *); -static unsigned long insert_bdp (unsigned long, long, int, const char **); -static long extract_bdp (unsigned long, int, int *); -static unsigned long insert_bo (unsigned long, long, int, const char **); -static long extract_bo (unsigned long, int, int *); -static unsigned long insert_boe (unsigned long, long, int, const char **); -static long extract_boe (unsigned long, int, int *); -static unsigned long insert_dq (unsigned long, long, int, const char **); -static long extract_dq (unsigned long, int, int *); -static unsigned long insert_ds (unsigned long, long, int, const char **); -static long extract_ds (unsigned long, int, int *); -static unsigned long insert_de (unsigned long, long, int, const char **); -static long extract_de (unsigned long, int, int *); -static unsigned long insert_des (unsigned long, long, int, const char **); -static long extract_des (unsigned long, int, int *); -static unsigned long insert_fxm (unsigned long, long, int, const char **); -static long extract_fxm (unsigned long, int, int *); -static unsigned long insert_li (unsigned long, long, int, const char **); -static long extract_li (unsigned long, int, int *); -static unsigned long insert_mbe (unsigned long, long, int, const char **); -static long extract_mbe (unsigned long, int, int *); -static unsigned long insert_mb6 (unsigned long, long, int, const char **); -static long extract_mb6 (unsigned long, int, int *); -static unsigned long insert_nb (unsigned long, long, int, const char **); -static long extract_nb (unsigned long, int, int *); -static unsigned long insert_nsi (unsigned long, long, int, const char **); -static long extract_nsi (unsigned long, int, int *); -static unsigned long insert_ral (unsigned long, long, int, const char **); -static unsigned long insert_ram (unsigned long, long, int, const char **); -static unsigned long insert_raq (unsigned long, long, int, const char **); -static unsigned long insert_ras (unsigned long, long, int, const char **); -static unsigned long insert_rbs (unsigned long, long, int, const char **); -static long extract_rbs (unsigned long, int, int *); -static unsigned long insert_rsq (unsigned long, long, int, const char **); -static unsigned long insert_rtq (unsigned long, long, int, const char **); -static unsigned long insert_sh6 (unsigned long, long, int, const char **); -static long extract_sh6 (unsigned long, int, int *); -static unsigned long insert_spr (unsigned long, long, int, const char **); -static long extract_spr (unsigned long, int, int *); -static unsigned long insert_sprg (unsigned long, long, int, const char **); -static long extract_sprg (unsigned long, int, int *); -static unsigned long insert_tbr (unsigned long, long, int, const char **); -static long extract_tbr (unsigned long, int, int *); -static unsigned long insert_ev2 (unsigned long, long, int, const char **); -static long extract_ev2 (unsigned long, int, int *); -static unsigned long insert_ev4 (unsigned long, long, int, const char **); -static long extract_ev4 (unsigned long, int, int *); -static unsigned long insert_ev8 (unsigned long, long, int, const char **); -static long extract_ev8 (unsigned long, int, int *); +static unsigned long insert_arx (unsigned long, long, ppc_cpu_t, const char **); +static long extract_arx (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_ary (unsigned long, long, ppc_cpu_t, const char **); +static long extract_ary (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_bat (unsigned long, long, ppc_cpu_t, const char **); +static long extract_bat (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_bba (unsigned long, long, ppc_cpu_t, const char **); +static long extract_bba (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_bdm (unsigned long, long, ppc_cpu_t, const char **); +static long extract_bdm (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_bdp (unsigned long, long, ppc_cpu_t, const char **); +static long extract_bdp (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_bo (unsigned long, long, ppc_cpu_t, const char **); +static long extract_bo (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_boe (unsigned long, long, ppc_cpu_t, const char **); +static long extract_boe (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_esync (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_dcmxs (unsigned long, long, ppc_cpu_t, const char **); +static long extract_dcmxs (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_dxd (unsigned long, long, ppc_cpu_t, const char **); +static long extract_dxd (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_dxdn (unsigned long, long, ppc_cpu_t, const char **); +static long extract_dxdn (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_fxm (unsigned long, long, ppc_cpu_t, const char **); +static long extract_fxm (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_li20 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_li20 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_ls (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_mbe (unsigned long, long, ppc_cpu_t, const char **); +static long extract_mbe (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_mb6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_mb6 (unsigned long, ppc_cpu_t, int *); +static long extract_nb (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_nbi (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_nsi (unsigned long, long, ppc_cpu_t, const char **); +static long extract_nsi (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_oimm (unsigned long, long, ppc_cpu_t, const char **); +static long extract_oimm (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_ral (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_ram (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_raq (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_ras (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_rbs (unsigned long, long, ppc_cpu_t, const char **); +static long extract_rbs (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_rbx (unsigned long, long, ppc_cpu_t, const char **); +static unsigned long insert_rx (unsigned long, long, ppc_cpu_t, const char **); +static long extract_rx (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_ry (unsigned long, long, ppc_cpu_t, const char **); +static long extract_ry (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_sh6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_sh6 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_sci8 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_sci8 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_sci8n (unsigned long, long, ppc_cpu_t, const char **); +static long extract_sci8n (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_sd4h (unsigned long, long, ppc_cpu_t, const char **); +static long extract_sd4h (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_sd4w (unsigned long, long, ppc_cpu_t, const char **); +static long extract_sd4w (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_spr (unsigned long, long, ppc_cpu_t, const char **); +static long extract_spr (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_sprg (unsigned long, long, ppc_cpu_t, const char **); +static long extract_sprg (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_tbr (unsigned long, long, ppc_cpu_t, const char **); +static long extract_tbr (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_xt6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_xt6 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_xtq6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_xtq6 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_xa6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_xa6 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_xb6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_xb6 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_xb6s (unsigned long, long, ppc_cpu_t, const char **); +static long extract_xb6s (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_xc6 (unsigned long, long, ppc_cpu_t, const char **); +static long extract_xc6 (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_dm (unsigned long, long, ppc_cpu_t, const char **); +static long extract_dm (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_vlesi (unsigned long, long, ppc_cpu_t, const char **); +static long extract_vlesi (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_vlensi (unsigned long, long, ppc_cpu_t, const char **); +static long extract_vlensi (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_vleui (unsigned long, long, ppc_cpu_t, const char **); +static long extract_vleui (unsigned long, ppc_cpu_t, int *); +static unsigned long insert_vleil (unsigned long, long, ppc_cpu_t, const char **); +static long extract_vleil (unsigned long, ppc_cpu_t, int *); /* The operands table. - The fields are bits, shift, insert, extract, flags. + The fields are bitm, shift, insert, extract, flags. We used to put parens around the various additions, like the one for BA just below. However, that caused trouble with feeble @@ -119,493 +149,934 @@ const struct powerpc_operand powerpc_operands[] = /* The BA field in an XL form instruction. */ #define BA UNUSED + 1 -#define BA_MASK (0x1f << 16) - { 5, 16, NULL, NULL, PPC_OPERAND_CR }, + /* The BI field in a B form or XL form instruction. */ +#define BI BA +#define BI_MASK (0x1f << 16) + { 0x1f, 16, NULL, NULL, PPC_OPERAND_CR_BIT }, /* The BA field in an XL form instruction when it must be the same as the BT field in the same instruction. */ #define BAT BA + 1 - { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE }, + { 0x1f, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE }, /* The BB field in an XL form instruction. */ #define BB BAT + 1 #define BB_MASK (0x1f << 11) - { 5, 11, NULL, NULL, PPC_OPERAND_CR }, + { 0x1f, 11, NULL, NULL, PPC_OPERAND_CR_BIT }, /* The BB field in an XL form instruction when it must be the same as the BA field in the same instruction. */ #define BBA BB + 1 - { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE }, + /* The VB field in a VX form instruction when it must be the same + as the VA field in the same instruction. */ +#define VBA BBA + { 0x1f, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE }, /* The BD field in a B form instruction. The lower two bits are forced to zero. */ #define BD BBA + 1 - { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + { 0xfffc, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, /* The BD field in a B form instruction when absolute addressing is used. */ #define BDA BD + 1 - { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + { 0xfffc, 0, NULL, NULL, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, /* The BD field in a B form instruction when the - modifier is used. This sets the y bit of the BO field appropriately. */ #define BDM BDA + 1 - { 16, 0, insert_bdm, extract_bdm, - PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + { 0xfffc, 0, insert_bdm, extract_bdm, + PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, /* The BD field in a B form instruction when the - modifier is used and absolute address is used. */ #define BDMA BDM + 1 - { 16, 0, insert_bdm, extract_bdm, - PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + { 0xfffc, 0, insert_bdm, extract_bdm, + PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, /* The BD field in a B form instruction when the + modifier is used. This sets the y bit of the BO field appropriately. */ #define BDP BDMA + 1 - { 16, 0, insert_bdp, extract_bdp, - PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + { 0xfffc, 0, insert_bdp, extract_bdp, + PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, /* The BD field in a B form instruction when the + modifier is used and absolute addressing is used. */ #define BDPA BDP + 1 - { 16, 0, insert_bdp, extract_bdp, - PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + { 0xfffc, 0, insert_bdp, extract_bdp, + PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, /* The BF field in an X or XL form instruction. */ #define BF BDPA + 1 - { 3, 23, NULL, NULL, PPC_OPERAND_CR }, + /* The CRFD field in an X form instruction. */ +#define CRFD BF + /* The CRD field in an XL form instruction. */ +#define CRD BF + { 0x7, 23, NULL, NULL, PPC_OPERAND_CR_REG }, + + /* The BF field in an X or XL form instruction. */ +#define BFF BF + 1 + { 0x7, 23, NULL, NULL, 0 }, /* An optional BF field. This is used for comparison instructions, in which an omitted BF field is taken as zero. */ -#define OBF BF + 1 - { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, +#define OBF BFF + 1 + { 0x7, 23, NULL, NULL, PPC_OPERAND_CR_REG | PPC_OPERAND_OPTIONAL }, /* The BFA field in an X or XL form instruction. */ #define BFA OBF + 1 - { 3, 18, NULL, NULL, PPC_OPERAND_CR }, - - /* The BI field in a B form or XL form instruction. */ -#define BI BFA + 1 -#define BI_MASK (0x1f << 16) - { 5, 16, NULL, NULL, PPC_OPERAND_CR }, + { 0x7, 18, NULL, NULL, PPC_OPERAND_CR_REG }, /* The BO field in a B form instruction. Certain values are illegal. */ -#define BO BI + 1 +#define BO BFA + 1 #define BO_MASK (0x1f << 21) - { 5, 21, insert_bo, extract_bo, 0 }, + { 0x1f, 21, insert_bo, extract_bo, 0 }, /* The BO field in a B form instruction when the + or - modifier is used. This is like the BO field, but it must be even. */ #define BOE BO + 1 - { 5, 21, insert_boe, extract_boe, 0 }, + { 0x1e, 21, insert_boe, extract_boe, 0 }, + + /* The RM field in an X form instruction. */ +#define RM BOE + 1 + { 0x3, 11, NULL, NULL, 0 }, -#define BH BOE + 1 - { 2, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, +#define BH RM + 1 + { 0x3, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, /* The BT field in an X or XL form instruction. */ #define BT BH + 1 - { 5, 21, NULL, NULL, PPC_OPERAND_CR }, + { 0x1f, 21, NULL, NULL, PPC_OPERAND_CR_BIT }, + + /* The BI16 field in a BD8 form instruction. */ +#define BI16 BT + 1 + { 0x3, 8, NULL, NULL, PPC_OPERAND_CR_BIT }, + + /* The BI32 field in a BD15 form instruction. */ +#define BI32 BI16 + 1 + { 0xf, 16, NULL, NULL, PPC_OPERAND_CR_BIT }, + + /* The BO32 field in a BD15 form instruction. */ +#define BO32 BI32 + 1 + { 0x3, 20, NULL, NULL, 0 }, + + /* The B8 field in a BD8 form instruction. */ +#define B8 BO32 + 1 + { 0x1fe, -1, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The B15 field in a BD15 form instruction. The lowest bit is + forced to zero. */ +#define B15 B8 + 1 + { 0xfffe, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The B24 field in a BD24 form instruction. The lowest bit is + forced to zero. */ +#define B24 B15 + 1 + { 0x1fffffe, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, /* The condition register number portion of the BI field in a B form or XL form instruction. This is used for the extended conditional branch mnemonics, which set the lower two bits of the BI field. This field is optional. */ -#define CR BT + 1 - { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, +#define CR B24 + 1 + { 0x7, 18, NULL, NULL, PPC_OPERAND_CR_REG | PPC_OPERAND_OPTIONAL }, /* The CRB field in an X form instruction. */ #define CRB CR + 1 - { 5, 6, NULL, NULL, 0 }, + /* The MB field in an M form instruction. */ +#define MB CRB +#define MB_MASK (0x1f << 6) + { 0x1f, 6, NULL, NULL, 0 }, - /* The CRFD field in an X form instruction. */ -#define CRFD CRB + 1 - { 3, 23, NULL, NULL, PPC_OPERAND_CR }, + /* The CRD32 field in an XL form instruction. */ +#define CRD32 CRB + 1 + { 0x3, 21, NULL, NULL, PPC_OPERAND_CR_REG }, /* The CRFS field in an X form instruction. */ -#define CRFS CRFD + 1 - { 3, 0, NULL, NULL, PPC_OPERAND_CR }, +#define CRFS CRD32 + 1 + { 0x7, 0, NULL, NULL, PPC_OPERAND_CR_REG }, + +#define CRS CRFS + 1 + { 0x3, 18, NULL, NULL, PPC_OPERAND_CR_REG | PPC_OPERAND_OPTIONAL }, /* The CT field in an X form instruction. */ -#define CT CRFS + 1 - { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, +#define CT CRS + 1 + /* The MO field in an mbar instruction. */ +#define MO CT + { 0x1f, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, /* The D field in a D form instruction. This is a displacement off a register, and implies that the next operand is a register in parentheses. */ #define D CT + 1 - { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + { 0xffff, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, - /* The DE field in a DE form instruction. This is like D, but is 12 - bits only. */ -#define DE D + 1 - { 14, 0, insert_de, extract_de, PPC_OPERAND_PARENS }, + /* The D8 field in a D form instruction. This is a displacement off + a register, and implies that the next operand is a register in + parentheses. */ +#define D8 D + 1 + { 0xff, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + + /* The DCMX field in an X form instruction. */ +#define DCMX D8 + 1 + { 0x7f, 16, NULL, NULL, 0 }, - /* The DES field in a DES form instruction. This is like DS, but is 14 - bits only (12 stored.) */ -#define DES DE + 1 - { 14, 0, insert_des, extract_des, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + /* The split DCMX field in an X form instruction. */ +#define DCMXS DCMX + 1 + { 0x7f, PPC_OPSHIFT_INV, insert_dcmxs, extract_dcmxs, 0 }, /* The DQ field in a DQ form instruction. This is like D, but the lower four bits are forced to zero. */ -#define DQ DES + 1 - { 16, 0, insert_dq, extract_dq, - PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ }, +#define DQ DCMXS + 1 + { 0xfff0, 0, NULL, NULL, + PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ }, /* The DS field in a DS form instruction. This is like D, but the lower two bits are forced to zero. */ #define DS DQ + 1 - { 16, 0, insert_ds, extract_ds, - PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS }, + { 0xfffc, 0, NULL, NULL, + PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS }, + + /* The DUIS or BHRBE fields in a XFX form instruction, 10 bits + unsigned imediate */ +#define DUIS DS + 1 +#define BHRBE DUIS + { 0x3ff, 11, NULL, NULL, 0 }, + + /* The split D field in a DX form instruction. */ +#define DXD DUIS + 1 + { 0xffff, PPC_OPSHIFT_INV, insert_dxd, extract_dxd, + PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT}, + + /* The split ND field in a DX form instruction. + This is the same as the DX field, only negated. */ +#define NDXD DXD + 1 + { 0xffff, PPC_OPSHIFT_INV, insert_dxdn, extract_dxdn, + PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT}, /* The E field in a wrteei instruction. */ -#define E DS + 1 - { 1, 15, NULL, NULL, 0 }, + /* And the W bit in the pair singles instructions. */ + /* And the ST field in a VX form instruction. */ +#define E NDXD + 1 +#define PSW E +#define ST E + { 0x1, 15, NULL, NULL, 0 }, /* The FL1 field in a POWER SC form instruction. */ #define FL1 E + 1 - { 4, 12, NULL, NULL, 0 }, + /* The U field in an X form instruction. */ +#define U FL1 + { 0xf, 12, NULL, NULL, 0 }, /* The FL2 field in a POWER SC form instruction. */ #define FL2 FL1 + 1 - { 3, 2, NULL, NULL, 0 }, + { 0x7, 2, NULL, NULL, 0 }, /* The FLM field in an XFL form instruction. */ #define FLM FL2 + 1 - { 8, 17, NULL, NULL, 0 }, + { 0xff, 17, NULL, NULL, 0 }, /* The FRA field in an X or A form instruction. */ #define FRA FLM + 1 #define FRA_MASK (0x1f << 16) - { 5, 16, NULL, NULL, PPC_OPERAND_FPR }, + { 0x1f, 16, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FRAp field of DFP instructions. */ +#define FRAp FRA + 1 + { 0x1e, 16, NULL, NULL, PPC_OPERAND_FPR }, /* The FRB field in an X or A form instruction. */ -#define FRB FRA + 1 +#define FRB FRAp + 1 #define FRB_MASK (0x1f << 11) - { 5, 11, NULL, NULL, PPC_OPERAND_FPR }, + { 0x1f, 11, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FRBp field of DFP instructions. */ +#define FRBp FRB + 1 + { 0x1e, 11, NULL, NULL, PPC_OPERAND_FPR }, /* The FRC field in an A form instruction. */ -#define FRC FRB + 1 +#define FRC FRBp + 1 #define FRC_MASK (0x1f << 6) - { 5, 6, NULL, NULL, PPC_OPERAND_FPR }, + { 0x1f, 6, NULL, NULL, PPC_OPERAND_FPR }, /* The FRS field in an X form instruction or the FRT field in a D, X or A form instruction. */ #define FRS FRC + 1 #define FRT FRS - { 5, 21, NULL, NULL, PPC_OPERAND_FPR }, + { 0x1f, 21, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FRSp field of stfdp or the FRTp field of lfdp and DFP + instructions. */ +#define FRSp FRS + 1 +#define FRTp FRSp + { 0x1e, 21, NULL, NULL, PPC_OPERAND_FPR }, /* The FXM field in an XFX instruction. */ -#define FXM FRS + 1 -#define FXM_MASK (0xff << 12) - { 8, 12, insert_fxm, extract_fxm, 0 }, +#define FXM FRSp + 1 + { 0xff, 12, insert_fxm, extract_fxm, 0 }, /* Power4 version for mfcr. */ #define FXM4 FXM + 1 - { 8, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL }, + { 0xff, 12, insert_fxm, extract_fxm, + PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE}, + /* If the FXM4 operand is ommitted, use the sentinel value -1. */ + { -1, -1, NULL, NULL, 0}, + + /* The IMM20 field in an LI instruction. */ +#define IMM20 FXM4 + 2 + { 0xfffff, PPC_OPSHIFT_INV, insert_li20, extract_li20, PPC_OPERAND_SIGNED}, /* The L field in a D or X form instruction. */ -#define L FXM4 + 1 - { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, +#define L IMM20 + 1 + { 0x1, 21, NULL, NULL, 0 }, + + /* The optional L field in tlbie and tlbiel instructions. */ +#define LOPT L + 1 + /* The R field in a HTM X form instruction. */ +#define HTM_R LOPT + { 0x1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The optional (for 32-bit) L field in cmp[l][i] instructions. */ +#define L32OPT LOPT + 1 + { 0x1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL32 }, + + /* The L field in dcbf instruction. */ +#define L2OPT L32OPT + 1 + { 0x3, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, /* The LEV field in a POWER S |