aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/xmon
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/xmon')
-rw-r--r--arch/powerpc/xmon/Makefile15
-rw-r--r--arch/powerpc/xmon/dis-asm.h31
-rw-r--r--arch/powerpc/xmon/nonstdio.c58
-rw-r--r--arch/powerpc/xmon/nonstdio.h7
-rw-r--r--arch/powerpc/xmon/ppc-dis.c29
-rw-r--r--arch/powerpc/xmon/ppc-opc.c786
-rw-r--r--arch/powerpc/xmon/ppc.h39
-rw-r--r--arch/powerpc/xmon/setjmp.S135
-rw-r--r--arch/powerpc/xmon/spu-dis.c248
-rw-r--r--arch/powerpc/xmon/spu-insns.h410
-rw-r--r--arch/powerpc/xmon/spu-opc.c45
-rw-r--r--arch/powerpc/xmon/spu.h126
-rw-r--r--arch/powerpc/xmon/start.c34
-rw-r--r--arch/powerpc/xmon/xmon.c1087
14 files changed, 2407 insertions, 643 deletions
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index 109d874ecfb..1278788d96e 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -1,7 +1,14 @@
# Makefile for xmon
-ifdef CONFIG_PPC64
-EXTRA_CFLAGS += -mno-minimal-toc
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
+GCOV_PROFILE := n
+
+ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
+
+obj-y += xmon.o nonstdio.o
+
+ifdef CONFIG_XMON_DISASSEMBLY
+obj-y += ppc-dis.o ppc-opc.o
+obj-$(CONFIG_SPU_BASE) += spu-dis.o spu-opc.o
endif
-obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o start.o \
- nonstdio.o
diff --git a/arch/powerpc/xmon/dis-asm.h b/arch/powerpc/xmon/dis-asm.h
new file mode 100644
index 00000000000..be3533b93f3
--- /dev/null
+++ b/arch/powerpc/xmon/dis-asm.h
@@ -0,0 +1,31 @@
+#ifndef _POWERPC_XMON_DIS_ASM_H
+#define _POWERPC_XMON_DIS_ASM_H
+/*
+ * Copyright (C) 2006 Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+extern void print_address (unsigned long memaddr);
+
+#ifdef CONFIG_XMON_DISASSEMBLY
+extern int print_insn_powerpc(unsigned long insn, unsigned long memaddr);
+extern int print_insn_spu(unsigned long insn, unsigned long memaddr);
+#else
+static inline int print_insn_powerpc(unsigned long insn, unsigned long memaddr)
+{
+ printf("%.8x", insn);
+ return 0;
+}
+
+static inline int print_insn_spu(unsigned long insn, unsigned long memaddr)
+{
+ printf("%.8x", insn);
+ return 0;
+}
+#endif
+
+#endif /* _POWERPC_XMON_DIS_ASM_H */
diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c
index 78765833f4c..c9874861789 100644
--- a/arch/powerpc/xmon/nonstdio.c
+++ b/arch/powerpc/xmon/nonstdio.c
@@ -7,9 +7,23 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/string.h>
+#include <asm/udbg.h>
#include <asm/time.h>
#include "nonstdio.h"
+
+static int xmon_write(const void *ptr, int nb)
+{
+ return udbg_write(ptr, nb);
+}
+
+static int xmon_readchar(void)
+{
+ if (udbg_getc)
+ return udbg_getc();
+ return -1;
+}
+
int xmon_putchar(int c)
{
char ch = c;
@@ -23,34 +37,7 @@ static char line[256];
static char *lineptr;
static int lineleft;
-int xmon_expect(const char *str, unsigned long timeout)
-{
- int c;
- unsigned long t0;
-
- /* assume 25MHz default timebase if tb_ticks_per_sec not set yet */
- timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000;
- t0 = get_tbl();
- do {
- lineptr = line;
- for (;;) {
- c = xmon_read_poll();
- if (c == -1) {
- if (get_tbl() - t0 > timeout)
- return 0;
- continue;
- }
- if (c == '\n')
- break;
- if (c != '\r' && lineptr < &line[sizeof(line) - 1])
- *lineptr++ = c;
- }
- *lineptr = 0;
- } while (strstr(line, str) == NULL);
- return 1;
-}
-
-int xmon_getchar(void)
+static int xmon_getchar(void)
{
int c;
@@ -124,11 +111,22 @@ char *xmon_gets(char *str, int nb)
void xmon_printf(const char *format, ...)
{
va_list args;
- int n;
static char xmon_outbuf[1024];
+ int rc, n;
va_start(args, format);
n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
va_end(args);
- xmon_write(xmon_outbuf, n);
+
+ rc = xmon_write(xmon_outbuf, n);
+
+ if (n && rc == 0) {
+ /* No udbg hooks, fallback to printk() - dangerous */
+ printk("%s", xmon_outbuf);
+ }
+}
+
+void xmon_puts(const char *str)
+{
+ xmon_write(str, strlen(str));
}
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h
index 47cebbd2b1b..18a51ded4ff 100644
--- a/arch/powerpc/xmon/nonstdio.h
+++ b/arch/powerpc/xmon/nonstdio.h
@@ -4,11 +4,6 @@
#define putchar xmon_putchar
extern int xmon_putchar(int c);
-extern int xmon_getchar(void);
+extern void xmon_puts(const char *);
extern char *xmon_gets(char *, int);
extern void xmon_printf(const char *, ...);
-extern void xmon_map_scc(void);
-extern int xmon_expect(const char *str, unsigned long timeout);
-extern int xmon_write(void *ptr, int nb);
-extern int xmon_readchar(void);
-extern int xmon_read_poll(void);
diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c
index ac0a9d2427e..89098f320ad 100644
--- a/arch/powerpc/xmon/ppc-dis.c
+++ b/arch/powerpc/xmon/ppc-dis.c
@@ -1,5 +1,6 @@
/* ppc-dis.c -- Disassemble PowerPC instructions
- Copyright 1994 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
This file is part of GDB, GAS, and the GNU binutils.
@@ -16,27 +17,36 @@ the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+#include <asm/cputable.h>
#include "nonstdio.h"
#include "ansidecl.h"
#include "ppc.h"
-
-extern void print_address (unsigned long memaddr);
+#include "dis-asm.h"
/* Print a PowerPC or POWER instruction. */
int
-print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
+print_insn_powerpc (unsigned long insn, unsigned long memaddr)
{
const struct powerpc_opcode *opcode;
const struct powerpc_opcode *opcode_end;
unsigned long op;
+ int dialect;
- if (dialect == 0)
- dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
+ dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | 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;
+
/* Get the major opcode of the instruction. */
op = PPC_OP (insn);
@@ -121,7 +131,8 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
}
/* Print the operand as directed by the flags. */
- if ((operand->flags & PPC_OPERAND_GPR) != 0)
+ if ((operand->flags & PPC_OPERAND_GPR) != 0
+ || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
printf("r%ld", value);
else if ((operand->flags & PPC_OPERAND_FPR) != 0)
printf("f%ld", value);
@@ -137,7 +148,7 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
else
{
if (operand->bits == 3)
- printf("cr%d", value);
+ printf("cr%ld", value);
else
{
static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c
index 5ee8fc32f82..6845e91ba04 100644
--- a/arch/powerpc/xmon/ppc-opc.c
+++ b/arch/powerpc/xmon/ppc-opc.c
@@ -1,6 +1,6 @@
/* ppc-opc.c -- PowerPC opcode list
- Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
This file is part of GDB, GAS, and the GNU binutils.
@@ -17,10 +17,12 @@
You should have received a copy of the GNU General Public License
along with this file; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
#include "nonstdio.h"
#include "ppc.h"
@@ -86,6 +88,8 @@ 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 **);
@@ -196,8 +200,11 @@ const struct powerpc_operand powerpc_operands[] =
#define BOE BO + 1
{ 5, 21, insert_boe, extract_boe, 0 },
+#define BH BOE + 1
+ { 2, 11, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
/* The BT field in an X or XL form instruction. */
-#define BT BOE + 1
+#define BT BH + 1
{ 5, 21, NULL, NULL, PPC_OPERAND_CR },
/* The condition register number portion of the BI field in a B form
@@ -301,10 +308,14 @@ const struct powerpc_operand powerpc_operands[] =
#define L FXM4 + 1
{ 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
- /* The LEV field in a POWER SC form instruction. */
-#define LEV L + 1
+ /* The LEV field in a POWER SVC form instruction. */
+#define SVC_LEV L + 1
{ 7, 5, NULL, NULL, 0 },
+ /* The LEV field in an SC form instruction. */
+#define LEV SVC_LEV + 1
+ { 7, 5, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
/* The LI field in an I form instruction. The lower two bits are
forced to zero. */
#define LI LEV + 1
@@ -346,7 +357,7 @@ const struct powerpc_operand powerpc_operands[] =
/* The MO field in an mbar instruction. */
#define MO MB6 + 1
- { 5, 21, NULL, NULL, 0 },
+ { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
/* The NB field in an X form instruction. The value 32 is stored as
0. */
@@ -364,30 +375,38 @@ const struct powerpc_operand powerpc_operands[] =
#define RA_MASK (0x1f << 16)
{ 5, 16, NULL, NULL, PPC_OPERAND_GPR },
+ /* As above, but 0 in the RA field means zero, not r0. */
+#define RA0 RA + 1
+ { 5, 16, NULL, NULL, PPC_OPERAND_GPR_0 },
+
/* The RA field in the DQ form lq instruction, which has special
value restrictions. */
-#define RAQ RA + 1
- { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR },
+#define RAQ RA0 + 1
+ { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR_0 },
/* The RA field in a D or X form instruction which is an updating
load, which means that the RA field may not be zero and may not
equal the RT field. */
#define RAL RAQ + 1
- { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR },
+ { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR_0 },
/* The RA field in an lmw instruction, which has special value
restrictions. */
#define RAM RAL + 1
- { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
+ { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR_0 },
/* The RA field in a D or X form instruction which is an updating
store or an updating floating point load, which means that the RA
field may not be zero. */
#define RAS RAM + 1
- { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR },
+ { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR_0 },
+
+ /* The RA field of the tlbwe instruction, which is optional. */
+#define RAOPT RAS + 1
+ { 5, 16, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL },
/* The RB field in an X, XO, M, or MDS form instruction. */
-#define RB RAS + 1
+#define RB RAOPT + 1
#define RB_MASK (0x1f << 11)
{ 5, 11, NULL, NULL, PPC_OPERAND_GPR },
@@ -408,15 +427,20 @@ const struct powerpc_operand powerpc_operands[] =
/* The RS field of the DS form stq instruction, which has special
value restrictions. */
#define RSQ RS + 1
- { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR },
+ { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR_0 },
/* The RT field of the DQ form lq instruction, which has special
value restrictions. */
#define RTQ RSQ + 1
- { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR },
+ { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR_0 },
+
+ /* The RS field of the tlbwe instruction, which is optional. */
+#define RSO RTQ + 1
+#define RTO RSO
+ { 5, 21, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL },
/* The SH field in an X or M form instruction. */
-#define SH RTQ + 1
+#define SH RSO + 1
#define SH_MASK (0x1f << 11)
{ 5, 11, NULL, NULL, 0 },
@@ -425,8 +449,12 @@ const struct powerpc_operand powerpc_operands[] =
#define SH6_MASK ((0x1f << 11) | (1 << 1))
{ 6, 1, insert_sh6, extract_sh6, 0 },
+ /* The SH field of the tlbwe instruction, which is optional. */
+#define SHO SH6 + 1
+ { 5, 11,NULL, NULL, PPC_OPERAND_OPTIONAL },
+
/* The SI field in a D form instruction. */
-#define SI SH6 + 1
+#define SI SHO + 1
{ 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
/* The SI field in a D form instruction when we accept a wide range
@@ -448,8 +476,7 @@ const struct powerpc_operand powerpc_operands[] =
/* The SPRG register number in an XFX form m[ft]sprg instruction. */
#define SPRG SPRBAT + 1
-#define SPRG_MASK (0x3 << 16)
- { 2, 16, NULL, NULL, 0 },
+ { 5, 16, insert_sprg, extract_sprg, 0 },
/* The SR field in an X form instruction. */
#define SR SPRG + 1
@@ -536,10 +563,45 @@ const struct powerpc_operand powerpc_operands[] =
#define WS_MASK (0x7 << 11)
{ 3, 11, NULL, NULL, 0 },
- /* The L field in an mtmsrd instruction */
+ /* The L field in an mtmsrd or A form instruction. */
#define MTMSRD_L WS + 1
+#define A_L MTMSRD_L
{ 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
+ /* The DCM field in a Z form instruction. */
+#define DCM MTMSRD_L + 1
+ { 6, 16, NULL, NULL, 0 },
+
+ /* Likewise, the DGM field in a Z form instruction. */
+#define DGM DCM + 1
+ { 6, 16, NULL, NULL, 0 },
+
+#define TE DGM + 1
+ { 5, 11, NULL, NULL, 0 },
+
+#define RMC TE + 1
+ { 2, 21, NULL, NULL, 0 },
+
+#define R RMC + 1
+ { 1, 15, NULL, NULL, 0 },
+
+#define SP R + 1
+ { 2, 11, NULL, NULL, 0 },
+
+#define S SP + 1
+ { 1, 11, NULL, NULL, 0 },
+
+ /* SH field starting at bit position 16. */
+#define SH16 S + 1
+ { 6, 10, NULL, NULL, 0 },
+
+ /* The L field in an X form with the RT field fixed instruction. */
+#define XRT_L SH16 + 1
+ { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
+ /* The EH field in larx instruction. */
+#define EH XRT_L + 1
+ { 1, 0, NULL, NULL, PPC_OPERAND_OPTIONAL },
};
/* The functions used to insert and extract complicated operands. */
@@ -550,7 +612,6 @@ const struct powerpc_operand powerpc_operands[] =
and the extraction function just checks that the fields are the
same. */
-/*ARGSUSED*/
static unsigned long
insert_bat (unsigned long insn,
long value ATTRIBUTE_UNUSED,
@@ -576,7 +637,6 @@ extract_bat (unsigned long insn,
and the extraction function just checks that the fields are the
same. */
-/*ARGSUSED*/
static unsigned long
insert_bba (unsigned long insn,
long value ATTRIBUTE_UNUSED,
@@ -599,7 +659,6 @@ extract_bba (unsigned long insn,
/* The BD field in a B form instruction. The lower two bits are
forced to zero. */
-/*ARGSUSED*/
static unsigned long
insert_bd (unsigned long insn,
long value,
@@ -609,7 +668,6 @@ insert_bd (unsigned long insn,
return insn | (value & 0xfffc);
}
-/*ARGSUSED*/
static long
extract_bd (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -631,7 +689,6 @@ extract_bd (unsigned long insn,
in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000
for branch on CTR. We only handle the taken/not-taken hint here. */
-/*ARGSUSED*/
static unsigned long
insert_bdm (unsigned long insn,
long value,
@@ -677,7 +734,6 @@ extract_bdm (unsigned long insn,
This is like BDM, above, except that the branch is expected to be
taken. */
-/*ARGSUSED*/
static unsigned long
insert_bdp (unsigned long insn,
long value,
@@ -831,7 +887,6 @@ extract_boe (unsigned long insn,
/* The DQ field in a DQ form instruction. This is like D, but the
lower four bits are forced to zero. */
-/*ARGSUSED*/
static unsigned long
insert_dq (unsigned long insn,
long value,
@@ -843,7 +898,6 @@ insert_dq (unsigned long insn,
return insn | (value & 0xfff0);
}
-/*ARGSUSED*/
static long
extract_dq (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -918,7 +972,6 @@ extract_ev8 (unsigned long insn,
/* The DS field in a DS form instruction. This is like D, but the
lower two bits are forced to zero. */
-/*ARGSUSED*/
static unsigned long
insert_ds (unsigned long insn,
long value,
@@ -930,7 +983,6 @@ insert_ds (unsigned long insn,
return insn | (value & 0xfffc);
}
-/*ARGSUSED*/
static long
extract_ds (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -941,7 +993,6 @@ extract_ds (unsigned long insn,
/* The DE field in a DE form instruction. */
-/*ARGSUSED*/
static unsigned long
insert_de (unsigned long insn,
long value,
@@ -953,7 +1004,6 @@ insert_de (unsigned long insn,
return insn | ((value << 4) & 0xfff0);
}
-/*ARGSUSED*/
static long
extract_de (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -964,7 +1014,6 @@ extract_de (unsigned long insn,
/* The DES field in a DES form instruction. */
-/*ARGSUSED*/
static unsigned long
insert_des (unsigned long insn,
long value,
@@ -978,7 +1027,6 @@ insert_des (unsigned long insn,
return insn | ((value << 2) & 0xfff0);
}
-/*ARGSUSED*/
static long
extract_des (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -995,17 +1043,33 @@ insert_fxm (unsigned long insn,
int dialect,
const char **errmsg)
{
+ /* If we're handling the mfocrf and mtocrf insns ensure that exactly
+ one bit of the mask field is set. */
+ if ((insn & (1 << 20)) != 0)
+ {
+ if (value == 0 || (value & -value) != value)
+ {
+ *errmsg = _("invalid mask field");
+ value = 0;
+ }
+ }
+
/* If the optional field on mfcr is missing that means we want to use
the old form of the instruction that moves the whole cr. In that
case we'll have VALUE zero. There doesn't seem to be a way to
distinguish this from the case where someone writes mfcr %r3,0. */
- if (value == 0)
+ else if (value == 0)
;
/* If only one bit of the FXM field is set, we can use the new form
of the instruction, which is faster. Unlike the Power4 branch hint
- encoding, this is not backward compatible. */
- else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) == value)
+ encoding, this is not backward compatible. Do not generate the
+ new form unless -mpower4 has been given, or -many and the two
+ operand form of mfcr was used. */
+ else if ((value & -value) == value
+ && ((dialect & PPC_OPCODE_POWER4) != 0
+ || ((dialect & PPC_OPCODE_ANY) != 0
+ && (insn & (0x3ff << 1)) == 19 << 1)))
insn |= 1 << 20;
/* Any other value on mfcr is an error. */
@@ -1020,7 +1084,7 @@ insert_fxm (unsigned long insn,
static long
extract_fxm (unsigned long insn,
- int dialect,
+ int dialect ATTRIBUTE_UNUSED,
int *invalid)
{
long mask = (insn >> 12) & 0xff;
@@ -1028,14 +1092,9 @@ extract_fxm (unsigned long insn,
/* Is this a Power4 insn? */
if ((insn & (1 << 20)) != 0)
{
- if ((dialect & PPC_OPCODE_POWER4) == 0)
+ /* Exactly one bit of MASK should be set. */
+ if (mask == 0 || (mask & -mask) != mask)
*invalid = 1;
- else
- {
- /* Exactly one bit of MASK should be set. */
- if (mask == 0 || (mask & -mask) != mask)
- *invalid = 1;
- }
}
/* Check that non-power4 form of mfcr has a zero MASK. */
@@ -1051,7 +1110,6 @@ extract_fxm (unsigned long insn,
/* The LI field in an I form instruction. The lower two bits are
forced to zero. */
-/*ARGSUSED*/
static unsigned long
insert_li (unsigned long insn,
long value,
@@ -1063,7 +1121,6 @@ insert_li (unsigned long insn,
return insn | (value & 0x3fffffc);
}
-/*ARGSUSED*/
static long
extract_li (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -1163,7 +1220,6 @@ extract_mbe (unsigned long insn,
/* The MB or ME field in an MD or MDS form instruction. The high bit
is wrapped to the low end. */
-/*ARGSUSED*/
static unsigned long
insert_mb6 (unsigned long insn,
long value,
@@ -1173,7 +1229,6 @@ insert_mb6 (unsigned long insn,
return insn | ((value & 0x1f) << 6) | (value & 0x20);
}
-/*ARGSUSED*/
static long
extract_mb6 (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -1198,7 +1253,6 @@ insert_nb (unsigned long insn,
return insn | ((value & 0x1f) << 11);
}
-/*ARGSUSED*/
static long
extract_nb (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -1217,7 +1271,6 @@ extract_nb (unsigned long insn,
invalid, since we never want to recognize an instruction which uses
a field of this type. */
-/*ARGSUSED*/
static unsigned long
insert_nsi (unsigned long insn,
long value,
@@ -1269,7 +1322,6 @@ insert_ram (unsigned long insn,
/* The RA field in the DQ form lq instruction, which has special
value restrictions. */
-/*ARGSUSED*/
static unsigned long
insert_raq (unsigned long insn,
long value,
@@ -1304,7 +1356,6 @@ insert_ras (unsigned long insn,
function just copies the BT field into the BA field, and the
extraction function just checks that the fields are the same. */
-/*ARGSUSED*/
static unsigned long
insert_rbs (unsigned long insn,
long value ATTRIBUTE_UNUSED,
@@ -1327,7 +1378,6 @@ extract_rbs (unsigned long insn,
/* The RT field of the DQ form lq instruction, which has special
value restrictions. */
-/*ARGSUSED*/
static unsigned long
insert_rtq (unsigned long insn,
long value,
@@ -1342,7 +1392,6 @@ insert_rtq (unsigned long insn,
/* The RS field of the DS form stq instruction, which has special
value restrictions. */
-/*ARGSUSED*/
static unsigned long
insert_rsq (unsigned long insn,
long value ATTRIBUTE_UNUSED,
@@ -1356,7 +1405,6 @@ insert_rsq (unsigned long insn,
/* The SH field in an MD form instruction. This is split. */
-/*ARGSUSED*/
static unsigned long
insert_sh6 (unsigned long insn,
long value,
@@ -1366,7 +1414,6 @@ insert_sh6 (unsigned long insn,
return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
}
-/*ARGSUSED*/
static long
extract_sh6 (unsigned long insn,
int dialect ATTRIBUTE_UNUSED,
@@ -1395,6 +1442,47 @@ extract_spr (unsigned long insn,
return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
}
+/* Some dialects have 8 SPRG registers instead of the standard 4. */
+
+static unsigned long
+insert_sprg (unsigned long insn,
+ long value,
+ int dialect,
+ const char **errmsg)
+{
+ /* This check uses PPC_OPCODE_403 because PPC405 is later defined
+ as a synonym. If ever a 405 specific dialect is added this
+ check should use that instead. */
+ if (value > 7
+ || (value > 3
+ && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0))
+ *errmsg = _("invalid sprg number");
+
+ /* If this is mfsprg4..7 then use spr 260..263 which can be read in
+ user mode. Anything else must use spr 272..279. */
+ if (value <= 3 || (insn & 0x100) != 0)
+ value |= 0x10;
+
+ return insn | ((value & 0x17) << 16);
+}
+
+static long
+extract_sprg (unsigned long insn,
+ int dialect,
+ int *invalid)
+{
+ unsigned long val = (insn >> 16) & 0x1f;
+
+ /* mfsprg can use 260..263 and 272..279. mtsprg only uses spr 272..279
+ If not BOOKE or 405, then both use only 272..275. */
+ if (val <= 3
+ || (val < 0x10 && (insn & 0x100) != 0)
+ || (val - 0x10 > 3
+ && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0))
+ *invalid = 1;
+ return val & 7;
+}
+
/* The TBR field in an XFX instruction. This is just like SPR, but it
is optional. When TBR is omitted, it must be inserted as 268 (the
magic number of the TB register). These functions treat 0
@@ -1460,6 +1548,9 @@ extract_tbr (unsigned long insn,
/* An A_MASK with the FRA and FRC fields fixed. */
#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK)
+/* An AFRAFRC_MASK, but with L bit clear. */
+#define AFRALFRC_MASK (AFRAFRC_MASK & ~((unsigned long) 1 << 16))
+
/* A B form instruction. */
#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1))
#define B_MASK B (0x3f, 1, 1)
@@ -1494,11 +1585,11 @@ extract_tbr (unsigned long insn,
/* An Context form instruction. */
#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7))
-#define CTX_MASK CTX(0x3f, 0x7)
+#define CTX_MASK CTX(0x3f, 0x7)
/* An User Context form instruction. */
#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f))
-#define UCTX_MASK UCTX(0x3f, 0x1f)
+#define UCTX_MASK UCTX(0x3f, 0x1f)
/* The main opcode mask with the RA field clear. */
#define DRA_MASK (OP_MASK | RA_MASK)
@@ -1570,12 +1661,21 @@ extract_tbr (unsigned long insn,
/* An X form instruction. */
#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1))
+/* A Z form instruction. */
+#define Z(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1))
+
/* An X form instruction with the RC bit specified. */
#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
+/* A Z form instruction with the RC bit specified. */
+#define ZRC(op, xop, rc) (Z ((op), (xop)) | ((rc) & 1))
+
/* The mask for an X form instruction. */
#define X_MASK XRC (0x3f, 0x3ff, 1)
+/* The mask for a Z form instruction. */
+#define Z_MASK ZRC (0x3f, 0x1ff, 1)
+
/* An X_MASK with the RA field fixed. */
#define XRA_MASK (X_MASK | RA_MASK)
@@ -1585,6 +1685,9 @@ extract_tbr (unsigned long insn,
/* An X_MASK with the RT field fixed. */
#define XRT_MASK (X_MASK | RT_MASK)
+/* An XRT_MASK mask with the L bits clear. */
+#define XLRT_MASK (XRT_MASK & ~((unsigned long) 0x3 << 21))
+
/* An X_MASK with the RA and RB fields fixed. */
#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
@@ -1597,8 +1700,8 @@ extract_tbr (unsigned long insn,
/* An XRTRA_MASK, but with L bit clear. */
#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21))
-/* An X form comparison instruction. */
-#define XCMPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21))
+/* An X form instruction with the L bit specified. */
+#define XOPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21))
/* The mask for an X form comparison instruction. */
#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22))
@@ -1621,6 +1724,9 @@ extract_tbr (unsigned long insn,
/* An X form sync instruction with everything filled in except the LS field. */
#define XSYNC_MASK (0xff9fffff)
+/* An X_MASK, but with the EH bit clear. */
+#define XEH_MASK (X_MASK & ~((unsigned long )1))
+
/* An X form AltiVec dss instruction. */
#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25))
#define XDSS_MASK XDSS(0x3f, 0x3ff, 1)
@@ -1663,6 +1769,9 @@ extract_tbr (unsigned long insn,
#define XLYBB_MASK (XLYLK_MASK | BB_MASK)
#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK)
+/* A mask for branch instructions using the BH field. */
+#define XLBH_MASK (XL_MASK | (0x1c << 11))
+
/* An XL_MASK with the BO and BB fields fixed. */
#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK)
@@ -1682,11 +1791,12 @@ extract_tbr (unsigned long insn,
#define XS_MASK XS (0x3f, 0x1ff, 1)
/* A mask for the FXM version of an XFX form instruction. */
-#define XFXFXM_MASK (X_MASK | (1 << 11))
+#define XFXFXM_MASK (X_MASK | (1 << 11) | (1 << 20))
/* An XFX form instruction with the FXM field filled in. */
-#define XFXM(op, xop, fxm) \
- (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12))
+#define XFXM(op, xop, fxm, p4) \
+ (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12) \
+ | ((unsigned long)(p4) << 20))
/* An XFX form instruction with the SPR field filled in. */
#define XSPR(op, xop, spr) \
@@ -1699,7 +1809,7 @@ extract_tbr (unsigned long insn,
/* An XFX form instruction with the SPR field filled in except for the
SPRG field. */
-#define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK)
+#define XSPRG_MASK (XSPR_MASK & ~(0x17 << 16))
/* An X form instruction with everything filled in except the E field. */
#define XE_MASK (0xffff7fff)
@@ -1769,6 +1879,9 @@ extract_tbr (unsigned long insn,
#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON
#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM
#define POWER4 PPC_OPCODE_POWER4
+#define POWER5 PPC_OPCODE_POWER5
+#define POWER6 PPC_OPCODE_POWER6
+#define CELL PPC_OPCODE_CELL
#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC
#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC
#define PPC403 PPC_OPCODE_403
@@ -1776,7 +1889,7 @@ extract_tbr (unsigned long insn,
#define PPC440 PPC_OPCODE_440
#define PPC750 PPC
#define PPC860 PPC
-#define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC
+#define PPCVEC PPC_OPCODE_ALTIVEC
#define POWER PPC_OPCODE_POWER
#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2
@@ -1790,6 +1903,7 @@ extract_tbr (unsigned long insn,
#define BOOKE PPC_OPCODE_BOOKE
#define BOOKE64 PPC_OPCODE_BOOKE64
#define CLASSIC PPC_OPCODE_CLASSIC
+#define PPCE300 PPC_OPCODE_E300
#define PPCSPE PPC_OPCODE_SPE
#define PPCISEL PPC_OPCODE_ISEL
#define PPCEFS PPC_OPCODE_EFS
@@ -1952,6 +2066,41 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } },
{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } },
{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } },
+
+ /* Double-precision opcodes. */
+ /* Some of these conflict with AltiVec, so move them before, since
+ PPCVEC includes the PPC_OPCODE_PPC set. */
+{ "efscfd", VX(4, 719), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdabs", VX(4, 740), VX_MASK, PPCEFS, { RS, RA } },
+{ "efdnabs", VX(4, 741), VX_MASK, PPCEFS, { RS, RA } },
+{ "efdneg", VX(4, 742), VX_MASK, PPCEFS, { RS, RA } },
+{ "efdadd", VX(4, 736), VX_MASK, PPCEFS, { RS, RA, RB } },
+{ "efdsub", VX(4, 737), VX_MASK, PPCEFS, { RS, RA, RB } },
+{ "efdmul", VX(4, 744), VX_MASK, PPCEFS, { RS, RA, RB } },
+{ "efddiv", VX(4, 745), VX_MASK, PPCEFS, { RS, RA, RB } },
+{ "efdcmpgt", VX(4, 748), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+{ "efdcmplt", VX(4, 749), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+{ "efdcmpeq", VX(4, 750), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+{ "efdtstgt", VX(4, 764), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+{ "efdtstlt", VX(4, 765), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+{ "efdtsteq", VX(4, 766), VX_MASK, PPCEFS, { CRFD, RA, RB } },
+{ "efdcfsi", VX(4, 753), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdcfsid", VX(4, 739), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdcfui", VX(4, 752), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdcfuid", VX(4, 738), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdcfsf", VX(4, 755), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdcfuf", VX(4, 754), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctsi", VX(4, 757), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctsidz",VX(4, 747), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctsiz", VX(4, 762), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctui", VX(4, 756), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctuidz",VX(4, 746), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctuiz", VX(4, 760), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctsf", VX(4, 759), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdctuf", VX(4, 758), VX_MASK, PPCEFS, { RS, RB } },
+{ "efdcfs", VX(4, 751), VX_MASK, PPCEFS, { RS, RB } },
+ /* End of double-precision opcodes. */
+
{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } },
{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } },
{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } },
@@ -2389,16 +2538,16 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } },
{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } },
-{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA, SI } },
-{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA } },
-{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA, NSI } },
-{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA } },
+{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA0, SI } },
+{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA0 } },
+{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA0, NSI } },
+{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA0 } },
{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } },
{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } },
-{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA,SISIGNOPT } },
-{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA,SISIGNOPT } },
-{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA, NSI } },
+{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA0,SISIGNOPT } },
+{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA0,SISIGNOPT } },
+{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA0, NSI } },
{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } },
{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } },
@@ -2665,9 +2814,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } },
{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } },
-{ "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } },
-{ "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } },
-{ "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } },
+{ "sc", SC(17,1,0), SC_MASK, PPC, { LEV } },
+{ "svc", SC(17,0,0), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } },
+{ "svcl", SC(17,0,1), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } },
{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } },
{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } },
@@ -2890,12 +3039,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } },
{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } },
-{ "bclr", XLLK(19,16,0), XLYBB_MASK, PPCCOM, { BO, BI } },
-{ "bclrl", XLLK(19,16,1), XLYBB_MASK, PPCCOM, { BO, BI } },
{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
+{ "bclr", XLLK(19,16,0), XLBH_MASK, PPCCOM, { BO, BI, BH } },
+{ "bclrl", XLLK(19,16,1), XLBH_MASK, PPCCOM, { BO, BI, BH } },
{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } },
{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } },
{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } },
@@ -2924,14 +3073,23 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } },
+{ "hrfid", XL(19,274), 0xffffffff, POWER5 | CELL, { 0 } },
+
{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } },
{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } },
+{ "doze", XL(19,402), 0xffffffff, POWER6, { 0 } },
+
{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } },
+{ "nap", XL(19,434), 0xffffffff, POWER6, { 0 } },
+
{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } },
{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } },
+{ "sleep", XL(19,466), 0xffffffff, POWER6, { 0 } },
+{ "rvwinkle", XL(19,498), 0xffffffff, POWER6, { 0 } },
+
{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } },
{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } },
{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } },
@@ -3074,12 +3232,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } },
{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } },
{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } },
-{ "bcctr", XLLK(19,528,0), XLYBB_MASK, PPCCOM, { BO, BI } },
{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } },
-{ "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPCCOM, { BO, BI } },
{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } },
+{ "bcctr", XLLK(19,528,0), XLBH_MASK, PPCCOM, { BO, BI, BH } },
+{ "bcctrl", XLLK(19,528,1), XLBH_MASK, PPCCOM, { BO, BI, BH } },
{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } },
{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } },
{ "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } },
@@ -3158,8 +3316,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } },
-{ "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
-{ "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
+{ "cmpw", XOPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
+{ "cmpd", XOPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } },
{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
@@ -3228,17 +3386,18 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } },
{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } },
-{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4, { RT } },
+{ "mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, { RT, FXM } },
+{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4 | COM, { RT } },
{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } },
-{ "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } },
+{ "lwarx", X(31,20), XEH_MASK, PPC, { RT, RA0, RB, EH } },
-{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA, RB } },
+{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA0, RB } },
-{ "icbt", X(31,22), X_MASK, BOOKE, { CT, RA, RB } },
+{ "icbt", X(31,22), X_MASK, BOOKE|PPCE300, { CT, RA, RB } },
{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } },
-{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA, RB } },
+{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA0, RB } },
{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } },
{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } },
@@ -3262,10 +3421,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } },
-{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA0, RB } },
-{ "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
-{ "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
+{ "cmplw", XOPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } },
+{ "cmpld", XOPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } },
{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } },
{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } },
@@ -3324,15 +3483,16 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } },
-{ "ldarx", X(31,84), X_MASK, PPC64, { RT, RA, RB } },
+{ "ldarx", X(31,84), XEH_MASK, PPC64, { RT, RA0, RB, EH } },
-{ "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } },
+{ "dcbfl", XOPL(31,86,1), XRT_MASK, POWER5, { RA, RB } },
+{ "dcbf", X(31,86), XLRT_MASK, PPC, { RA, RB, XRT_L } },
-{ "lbzx", X(31,87), X_MASK, COM, { RT, RA, RB } },
+{ "lbzx", X(31,87), X_MASK, COM, { RT, RA0, RB } },
{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } },
-{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA0, RB } },
{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } },
{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } },
@@ -3350,12 +3510,14 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } },
+{ "popcntb", X(31,122), XRB_MASK, POWER5, { RA, RS } },
+
{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } },
{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } },
{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } },
{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } },
-{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA0, RB } },
{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } },
@@ -3383,21 +3545,22 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }},
-{ "mtcr", XFXM(31,144,0xff), XRARB_MASK, COM, { RS }},
+{ "mtocrf", XFXM(31,144,0,1), XFXFXM_MASK, COM, { FXM, RS } },
+{ "mtcr", XFXM(31,144,0xff,0), XRARB_MASK, COM, { RS }},
{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } },
{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } },
-{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA, RB } },
+{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA0, RB } },
-{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } },
+{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA0, RB } },
-{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA, RB } },
+{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA0, RB } },
{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } },
-{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA0, RB } },
-{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA0, RB } },
{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } },
{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } },
@@ -3405,6 +3568,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } },
{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } },
+{ "prtyw", X(31,154), XRB_MASK, POWER6, { RA, RS } },
+
{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } },
{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }},
@@ -3415,11 +3580,13 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } },
{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } },
-{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA, RB } },
+{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA0, RB } },
{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } },
{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } },
+{ "prtyd", X(31,186), XRB_MASK, POWER6, { RA, RS } },
+
{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } },
{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } },
@@ -3442,9 +3609,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } },
-{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA, RB } },
+{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA0, RB } },
-{ "stbx", X(31,215), X_MASK, COM, { RS, RA, RB } },
+{ "stbx", X(31,215), X_MASK, COM, { RS, RA0, RB } },
{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } },
{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } },
@@ -3452,7 +3619,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } },
{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } },
-{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA0, RB } },
{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }},
@@ -3492,7 +3659,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } },
{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } },
-{ "dcbtst", X(31,246), XRT_MASK, PPC, { CT, RA, RB } },
+{ "dcbtst", X(31,246), X_MASK, PPC, { CT, RA, RB } },
{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } },
@@ -3519,26 +3686,26 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } },
{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } },
-{ "tlbiel", X(31,274), XRTRA_MASK, POWER4, { RB } },
+{ "tlbiel", X(31,274), XRTLRA_MASK, POWER4, { RB, L } },
{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } },
{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } },
{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } },
-{ "dcbt", X(31,278), XRT_MASK, PPC, { CT, RA, RB } },
+{ "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } },
-{ "lhzx", X(31,279), X_MASK, COM, { RT, RA, RB } },
+{ "lhzx", X(31,279), X_MASK, COM, { RT, RA0, RB } },
{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } },
{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } },
{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } },
-{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA0, RB } },
{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } },
-{ "tlbi", X(31,306), XRT_MASK, POWER, { RA, RB } },
+{ "tlbi", X(31,306), XRT_MASK, POWER, { RA0, RB } },
{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } },
@@ -3607,6 +3774,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } },
{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } },
{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } },
+{ "mfcfar", XSPR(31,339,28), XSPR_MASK, POWER6, { RT } },
{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } },
{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } },
{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } },
@@ -3634,21 +3802,21 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } },
{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } },
{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } },
-{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405, { RT } },
-{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405, { RT } },
-{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405, { RT } },
-{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405, { RT } },
{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } },
{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } },
{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } },
{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } },
{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } },
-{ "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } },
+{ "mfsprg", XSPR(31,339,256), XSPRG_MASK, PPC, { RT, SPRG } },
{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } },
{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } },
{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } },
{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } },
+{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405 | BOOKE, { RT } },
+{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405 | BOOKE, { RT } },
+{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405 | BOOKE, { RT } },
+{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405 | BOOKE, { RT } },
{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } },
{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } },
{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } },
@@ -3699,6 +3867,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } },
{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } },
{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } },
+{ "mfivor32", XSPR(31,339,528), XSPR_MASK, PPCSPE, { RT } },
+{ "mfivor33", XSPR(31,339,529), XSPR_MASK, PPCSPE, { RT } },
+{ "mfivor34", XSPR(31,339,530), XSPR_MASK, PPCSPE, { RT } },
+{ "mfivor35", XSPR(31,339,531), XSPR_MASK, PPCPMR, { RT } },
{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } },
@@ -3708,10 +3880,11 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } },
{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } },
{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } },
-{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } },
{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } },
+{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } },
{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } },
{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } },
+{ "mfmcar", XSPR(31,339,573), XSPR_MASK, PPCRFMCI, { RT } },
{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } },
{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } },
{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } },
@@ -3775,14 +3948,14 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } },
{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } },
-{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA, RB } },
+{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA0, RB } },
{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
-{ "lhax", X(31,343), X_MASK, COM, { RT, RA, RB } },
+{ "lhax", X(31,343), X_MASK, COM, { RT, RA0, RB } },
-{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA0, RB } },
{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } },
@@ -3821,14 +3994,20 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } },
-{ "sthx", X(31,407), X_MASK, COM, { RS, RA, RB } },
+{ "sthx", X(31,407), X_MASK, COM, { RS, RA0, RB } },
+
+{ "cmpb", X(31,508), X_MASK, POWER6, { RA, RS, RB } },
{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } },
+{ "lfdpx", X(31,791), X_MASK, POWER6, { FRT, RA, RB } },
+
{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } },
{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } },
+{ "stfdpx", X(31,919), X_MASK, POWER6, { FRS, RA, RB } },
+
{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } },
{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } },
@@ -3837,7 +4016,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } },
{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } },
-{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA0, RB } },
{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } },
@@ -3918,6 +4097,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } },
{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } },
{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } },
+{ "mtcfar", XSPR(31,467,28), XSPR_MASK, POWER6, { RS } },
{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } },
{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } },
{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } },
@@ -3946,7 +4126,7 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } },
{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } },
{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } },
-{ "mtsprg", XSPR(31,467,272), XSPRG_MASK,PPC, { SPRG, RS } },
+{ "mtsprg", XSPR(31,467,256), XSPRG_MASK,PPC, { SPRG, RS } },
{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } },
{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } },
{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } },
@@ -4005,6 +4185,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } },
{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } },
{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } },
+{ "mtivor32", XSPR(31,467,528), XSPR_MASK, PPCSPE, { RS } },
+{ "mtivor33", XSPR(31,467,529), XSPR_MASK, PPCSPE, { RS } },
+{ "mtivor34", XSPR(31,467,530), XSPR_MASK, PPCSPE, { RS } },
+{ "mtivor35", XSPR(31,467,531), XSPR_MASK, PPCPMR, { RS } },
{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } },
@@ -4101,13 +4285,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } },
-{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA, RB } },
+{ "ldbrx", X(31,532), X_MASK, CELL, { RT, RA0, RB } },
+
+{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA0, RB } },
{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } },
-{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA, RB } },
+{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA0, RB } },
{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } },
-{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA, RB } },
+{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA0, RB } },
{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } },
{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } },
@@ -4123,11 +4309,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } },
{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } },
-{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA0, RB } },
-{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA, RB } },
+{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA0, RB } },
{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }},
+
{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } },
{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } },
@@ -4136,8 +4323,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } },
-{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA, NB } },
-{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA, NB } },
+{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA0, NB } },
+{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA0, NB } },
{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } },
{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } },
@@ -4145,9 +4332,11 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } },
{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } },
-{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA, RB } },
+{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA0, RB } },
+
+{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA0, RB } },
-{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA, RB } },
+{ "mffgpr", XRC(31,607,0), XRA_MASK, POWER6, { FRT, RB } },
{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } },
@@ -4159,13 +4348,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } },
-{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA, RB } },
-{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA, RB } },
+{ "stdbrx", X(31,660), X_MASK, CELL, { RS, RA0, RB } },
+
+{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA0, RB } },
+{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA0, RB } },
-{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA, RB } },
-{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA, RB } },
+{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA0, RB } },
+{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA0, RB } },
-{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA, RB } },
+{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA0, RB } },
{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } },
{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } },
@@ -4173,9 +4364,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } },
{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } },
-{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA0, RB } },
-{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA, RB } },
+{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA0, RB } },
{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } },
@@ -4184,10 +4375,10 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } },
-{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA, NB } },
-{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA, NB } },
+{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA0, NB } },
+{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA0, NB } },
-{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA, RB } },
+{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA0, RB } },
{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } },
{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } },
@@ -4195,7 +4386,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } },
{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } },
-{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA, RB } },
+{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA0, RB } },
+
+{ "mftgpr", XRC(31,735,0), XRA_MASK, POWER6, { RT, FRB } },
{ "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } },
@@ -4211,7 +4404,9 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } },
{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } },
-{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA, RB } },
+{ "lwzcix", X(31,789), X_MASK, POWER6, { RT, RA0, RB } },
+
+{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA0, RB } },
{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } },
{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } },
@@ -4221,13 +4416,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } },
{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } },
-{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA0, RB } },
-{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA, RB } },
-{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA, RB } },
+{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA0, RB } },
+{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA0, RB } },
{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } },
+{ "lhzcix", X(31,821), X_MASK, POWER6, { RT, RA0, RB } },
+
{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } },
{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } },
@@ -4238,19 +4435,25 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } },
+{ "lbzcix", X(31,853), X_MASK, POWER6, { RT, RA0, RB } },
+
{ "mbar", X(31,854), X_MASK, BOOKE, { MO } },
{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } },
-{ "tlbsx", XRC(31,914,0), X_MASK, BOOKE, { RA, RB } },
-{ "tlbsx", XRC(31,914,0), X_MASK, PPC403, { RT, RA, RB } },
-{ "tlbsx.", XRC(31,914,1), X_MASK, BOOKE, { RA, RB } },
-{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403, { RT, RA, RB } },
+{ "lfiwax", X(31,855), X_MASK, POWER6, { FRT, RA0, RB } },
+
+{ "ldcix", X(31,885), X_MASK, POWER6, { RT, RA0, RB } },
+
+{ "tlbsx", XRC(31,914,0), X_MASK, PPC403|BOOKE, { RTO, RA, RB } },
+{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403|BOOKE, { RTO, RA, RB } },
{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } },
{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } },
{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } },
-{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA, RB } },
+{ "stwcix", X(31,917), X_MASK, POWER6, { RS, RA0, RB } },
+
+{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA0, RB } },
{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } },
{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } },
@@ -4263,14 +4466,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } },
{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } },
-{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA0, RB } },
-{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA, RB } },
+{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA0, RB } },
{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } },
{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } },
-{ "tlbre", X(31,946), X_MASK, BOOKE, { 0 } },
-{ "tlbre", X(31,946), X_MASK, PPC403, { RS, RA, SH } },
+{ "tlbre", X(31,946), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } },
+
+{ "sthcix", X(31,949), X_MASK, POWER6, { RS, RA0, RB } },
{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } },
{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } },
@@ -4284,13 +4488,14 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } },
{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } },
-{ "tlbwe", X(31,978), X_MASK, BOOKE, { 0 } },
-{ "tlbwe", X(31,978), X_MASK, PPC403, { RS, RA, SH } },
+{ "tlbwe", X(31,978), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } },
{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } },
+{ "stbcix", X(31,981), X_MASK, POWER6, { RS, RA0, RB } },
+
{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } },
-{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } },
+{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA0, RB } },
{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } },
{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } },
@@ -4298,10 +4503,13 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } },
{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } },
-{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA, RB } },
+{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA0, RB } },
{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } },
+{ "stdcix", X(31,1013), X_MASK, POWER6, { RS, RA0, RB } },
+
+{ "dcbzl", XOPL(31,1014,1), XRT_MASK,POWER4, { RA, RB } },
{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } },
@@ -4320,86 +4528,104 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } },
{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } },
-{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA } },
-{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA } },
+/* New load/store left/right index vector instructions that are in the Cell only. */
+{ "lvlx", X(31, 519), X_MASK, CELL, { VD, RA0, RB } },
+{ "lvlxl", X(31, 775), X_MASK, CELL, { VD, RA0, RB } },
+{ "lvrx", X(31, 551), X_MASK, CELL, { VD, RA0, RB } },
+{ "lvrxl", X(31, 807), X_MASK, CELL, { VD, RA0, RB } },
+{ "stvlx", X(31, 647), X_MASK, CELL, { VS, RA0, RB } },
+{ "stvlxl", X(31, 903), X_MASK, CELL, { VS, RA0, RB } },
+{ "stvrx", X(31, 679), X_MASK, CELL, { VS, RA0, RB } },
+{ "stvrxl", X(31, 935), X_MASK, CELL, { VS, RA0, RB } },
+
+{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA0 } },
+{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA0 } },
{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } },
-{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA } },
+{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA0 } },
-{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA } },
+{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA0 } },
{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } },
-{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA } },
-{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA } },
+{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA0 } },
+{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA0 } },
{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } },
-{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA } },
+{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA0 } },
-{ "stb", OP(38), OP_MASK, COM, { RS, D, RA } },
+{ "stb", OP(38), OP_MASK, COM, { RS, D, RA0 } },
{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } },
-{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA } },
+{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA0 } },
{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } },
-{ "lha", OP(42), OP_MASK, COM, { RT, D, RA } },
+{ "lha", OP(42), OP_MASK, COM, { RT, D, RA0 } },
{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } },
-{ "sth", OP(44), OP_MASK, COM, { RS, D, RA } },
+{ "sth", OP(44), OP_MASK, COM, { RS, D, RA0 } },
{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } },
{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } },
-{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA } },
+{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA0 } },
-{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA } },
-{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA } },
+{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA0 } },
+{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA0 } },
-{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA } },
+{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA0 } },
{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } },
-{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA } },
+{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA0 } },
{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } },
-{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA } },
+{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA0 } },
{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } },
-{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA } },
+{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA0 } },
{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } },
{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } },
-{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } },
+{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA0 } },
+
+{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA0 } },
-{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } },
+{ "lfdp", OP(57), OP_MASK, POWER6, { FRT, D, RA0 } },
-{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA } },
+{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA0 } },
{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } },
-{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA } },
+{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA0 } },
{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } },
-{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA } },
+{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA0 } },
{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } },
-{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA } },
+{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA0 } },
{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } },
-{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA } },
+{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA0 } },
{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } },
-{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA } },
+{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA0 } },
{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } },
-{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA } },
+{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA0 } },
{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } },
-{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA } },
+{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA0 } },
{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } },
-{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA } },
+{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA0 } },
+
+{ "dadd", XRC(59,2,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "dadd.", XRC(59,2,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "dqua", ZRC(59,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+{ "dqua.", ZRC(59,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } },
{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } },
@@ -4413,12 +4639,15 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
-{ "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
-{ "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+{ "fres", A(59,24,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
+{ "fres.", A(59,24,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } },
{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } },
+{ "frsqrtes", A(59,26,0), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } },
+{ "frsqrtes.",A(59,26,1), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } },
+
{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
@@ -4431,31 +4660,103 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "drrnd", ZRC(59,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+{ "drrnd.", ZRC(59,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+
+{ "dscli", ZRC(59,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+{ "dscli.", ZRC(59,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+
+{ "dquai", ZRC(59,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } },
+{ "dquai.", ZRC(59,67,1), Z_MASK, POWER6, { TE, FRT, FRB, RMC } },
+
+{ "dscri", ZRC(59,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+{ "dscri.", ZRC(59,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+
+{ "drintx", ZRC(59,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+{ "drintx.", ZRC(59,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+
+{ "dcmpo", X(59,130), X_MASK, POWER6, { BF, FRA, FRB } },
+
+{ "dtstex", X(59,162), X_MASK, POWER6, { BF, FRA, FRB } },
+{ "dtstdc", Z(59,194), Z_MASK, POWER6, { BF, FRA, DCM } },
+{ "dtstdg", Z(59,226), Z_MASK, POWER6, { BF, FRA, DGM } },
+
+{ "drintn", ZRC(59,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+{ "drintn.", ZRC(59,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+
+{ "dctdp", XRC(59,258,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dctdp.", XRC(59,258,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "dctfix", XRC(59,290,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dctfix.", XRC(59,290,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "ddedpd", XRC(59,322,0), X_MASK, POWER6, { SP, FRT, FRB } },
+{ "ddedpd.", XRC(59,322,1), X_MASK, POWER6, { SP, FRT, FRB } },
+
+{ "dxex", XRC(59,354,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dxex.", XRC(59,354,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "dsub", XRC(59,514,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "dsub.", XRC(59,514,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "ddiv", XRC(59,546,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "ddiv.", XRC(59,546,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "dcmpu", X(59,642), X_MASK, POWER6, { BF, FRA, FRB } },
+
+{ "dtstsf", X(59,674), X_MASK, POWER6, { BF, FRA, FRB } },
+
+{ "drsp", XRC(59,770,0), X_MASK, POWER6, { FRT, FRB } },
+{ "drsp.", XRC(59,770,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "dcffix", XRC(59,802,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dcffix.", XRC(59,802,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "denbcd", XRC(59,834,0), X_MASK, POWER6, { S, FRT, FRB } },
+{ "denbcd.", XRC(59,834,1), X_MASK, POWER6, { S, FRT, FRB } },
+
+{ "diex", XRC(59,866,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "diex.", XRC(59,866,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } },
{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } },
-{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA } },
-{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA } },
-{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA } },
+{ "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } },
+
+{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA0 } },
+{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA0 } },
+{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA0 } },
{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } },
-{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA } },
+{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA0 } },
{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } },
-{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA } },
+{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA0 } },
{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } },
-{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA } },
+{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA0 } },
{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } },
-{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA } },
+{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA0 } },
{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } },
-{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA } },
+{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA0 } },
{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } },
-{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA } },
+{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA0 } },
{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
+{ "daddq", XRC(63,2,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "daddq.", XRC(63,2,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "dquaq", ZRC(63,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+{ "dquaq.", ZRC(63,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+
+{ "fcpsgn", XRC(63,8,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "fcpsgn.", XRC(63,8,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } },
{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } },
@@ -4490,13 +4791,16 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
+{ "fre", A(63,24,0), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } },
+{ "fre.", A(63,24,1), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } },
+
{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } },
{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } },
-{ "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } },
-{ "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } },
+{ "frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
+{ "frsqrte.",A(63,26,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } },
{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } },
{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } },
@@ -4520,6 +4824,12 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } },
+{ "dmulq", XRC(63,34,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "dmulq.", XRC(63,34,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "drrndq", ZRC(63,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+{ "drrndq.", ZRC(63,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+
{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } },
{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } },
@@ -4528,40 +4838,103 @@ const struct powerpc_opcode powerpc_opcodes[] = {
{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } },
+{ "dscliq", ZRC(63,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+{ "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+
+{ "dquaiq", ZRC(63,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } },
+{ "dquaiq.", ZRC(63,67,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+
{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } },
{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } },
{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } },
{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } },
+{ "dscriq", ZRC(63,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+{ "dscriq.", ZRC(63,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
+
+{ "drintxq", ZRC(63,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+{ "drintxq.",ZRC(63,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+
+{ "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } },
+
{ "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
{ "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } },
{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } },
{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } },
+{ "dtstexq", X(63,162), X_MASK, POWER6, { BF, FRA, FRB } },
+{ "dtstdcq", Z(63,194), Z_MASK, POWER6, { BF, FRA, DCM } },
+{ "dtstdgq", Z(63,226), Z_MASK, POWER6, { BF, FRA, DGM } },
+
+{ "drintnq", ZRC(63,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+{ "drintnq.",ZRC(63,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } },
+
+{ "dctqpq", XRC(63,258,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dctqpq.", XRC(63,258,1), X_MASK, POWER6, { FRT, FRB } },
+
{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } },
{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } },
+{ "dctfixq", XRC(63,290,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dctfixq.",XRC(63,290,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "ddedpdq", XRC(63,322,0), X_MASK, POWER6, { SP, FRT, FRB } },
+{ "ddedpdq.",XRC(63,322,1), X_MASK, POWER6, { SP, FRT, FRB } },
+
+{ "dxexq", XRC(63,354,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dxexq.", XRC(63,354,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "frin", XRC(63,392,0), XRA_MASK, POWER5, { FRT, FRB } },
+{ "frin.", XRC(63,392,1), XRA_MASK, POWER5, { FRT, FRB } },
+{ "friz", XRC(63,424,0), XRA_MASK, POWER5, { FRT, FRB } },
+{ "friz.", XRC(63,424,1), XRA_MASK, POWER5, { FRT, FRB } },
+{ "frip", XRC(63,456,0), XRA_MASK, POWER5, { FRT, FRB } },
+{ "frip.", XRC(63,456,1), XRA_MASK, POWER5, { FRT, FRB } },
+{ "frim", XRC(63,488,0), XRA_MASK, POWER5, { FRT, FRB } },
+{ "frim.", XRC(63,488,1), XRA_MASK, POWER5, { FRT, FRB } },
+
+{ "dsubq", XRC(63,514,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "dsubq.", XRC(63,514,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
+{ "ddivq", XRC(63,546,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "ddivq.", XRC(63,546,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } },
{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } },
+{ "dcmpuq", X(63,642), X_MASK, POWER6, { BF, FRA, FRB } },
+
+{ "dtstsfq", X(63,674), X_MASK, POWER6, { BF, FRA, FRB } },
+
{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } },
{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } },
+{ "drdpq", XRC(63,770,0), X_MASK, POWER6, { FRT, FRB } },
+{ "drdpq.", XRC(63,770,1), X_MASK, POWER6, { FRT, FRB } },
+
+{ "dcffixq", XRC(63,802,0), X_MASK, POWER6, { FRT, FRB } },
+{ "dcffixq.",XRC(63,802,1), X_MASK, POWER6, { FRT, FRB } },
+
{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } },
{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } },
{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } },
{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } },
+{ "denbcdq", XRC(63,834,0), X_MASK, POWER6, { S, FRT, FRB } },
+{ "denbcdq.",XRC(63,834,1), X_MASK, POWER6, { S, FRT, FRB } },
+
{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } },
{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } },
+{ "diexq", XRC(63,866,0), X_MASK, POWER6, { FRT, FRA, FRB } },
+{ "diexq.", XRC(63,866,1), X_MASK, POWER6, { FRT, FRA, FRB } },
+
};
-const int powerpc_num_opcodes =
- sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]);
+const int powerpc_num_opcodes = ARRAY_SIZE(powerpc_opcodes);
/* The macro table. This is only used by the assembler. */
@@ -4617,5 +4990,4 @@ const struct powerpc_macro powerpc_macros[] = {
{ "clrlslwi.",4, PPCCOM, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" },
};
-const int powerpc_num_macros =
- sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
+const int powerpc_num_macros = ARRAY_SIZE(powerpc_macros);
diff --git a/arch/powerpc/xmon/ppc.h b/arch/powerpc/xmon/ppc.h
index 342237e8dd6..110df96354b 100644
--- a/arch/powerpc/xmon/ppc.h
+++ b/arch/powerpc/xmon/ppc.h
@@ -1,5 +1,5 @@
/* ppc.h -- Header file for PowerPC opcode table
- Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003
+ Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
@@ -17,7 +17,7 @@ the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef PPC_H
#define PPC_H
@@ -134,6 +134,18 @@ extern const int powerpc_num_opcodes;
/* Opcode is supported by machine check APU. */
#define PPC_OPCODE_RFMCI 0x800000
+/* Opcode is only supported by Power5 architecture. */
+#define PPC_OPCODE_POWER5 0x1000000
+
+/* Opcode is supported by PowerPC e300 family. */
+#define PPC_OPCODE_E300 0x2000000
+
+/* Opcode is only supported by Power6 architecture. */
+#define PPC_OPCODE_POWER6 0x4000000
+
+/* Opcode is only supported by PowerPC Cell family. */
+#define PPC_OPCODE_CELL 0x8000000
+
/* A macro to extract the major opcode from an instruction. */
#define PPC_OP(i) (((i) >> 26) & 0x3f)
@@ -233,25 +245,28 @@ extern const struct powerpc_operand powerpc_operands[];
register names with a leading 'r'. */
#define PPC_OPERAND_GPR (040)
+/* Like PPC_OPERAND_GPR, but don't print a leading 'r' for r0. */
+#define PPC_OPERAND_GPR_0 (0100)
+
/* This operand names a floating point register. The disassembler
prints these with a leading 'f'. */
-#define PPC_OPERAND_FPR (0100)
+#define PPC_OPERAND_FPR (0200)
/* This operand is a relative branch displacement. The disassembler
prints these symbolically if possible. */
-#define PPC_OPERAND_RELATIVE (0200)
+#define PPC_OPERAND_RELATIVE (0400)
/* This operand is an absolute branch address. The disassembler
prints these symbolically if possible. */
-#define PPC_OPERAND_ABSOLUTE (0400)
+#define PPC_OPERAND_ABSOLUTE (01000)
/* This operand is optional, and is zero if omitted. This is used for
- the optional BF and L fields in the comparison instructions. The
+ example, in the optional BF field in the comparison instructions. The
assembler must count the number of operands remaining on the line,
and the number of operands remaining for the opcode, and decide
whether this operand is present or not. The disassembler should
print this operand out only if it is not zero. */
-#define PPC_OPERAND_OPTIONAL (01000)
+#define PPC_OPERAND_OPTIONAL (02000)
/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
is omitted, then for the next operand use this operand value plus
@@ -259,24 +274,24 @@ extern const struct powerpc_operand powerpc_operands[];
hack is needed because the Power rotate instructions can take
either 4 or 5 operands. The disassembler should print this operand
out regardless of the PPC_OPERAND_OPTIONAL field. */
-#define PPC_OPERAND_NEXT (02000)
+#define PPC_OPERAND_NEXT (04000)
/* This operand should be regarded as a negative number for the
purposes of overflow checking (i.e., the normal most negative
number is disallowed and one more than the normal most positive
number is allowed). This flag will only be set for a signed
operand. */
-#define PPC_OPERAND_NEGATIVE (04000)
+#define PPC_OPERAND_NEGATIVE (010000)
/* This operand names a vector unit register. The disassembler
prints these with a leading 'v'. */
-#define PPC_OPERAND_VR (010000)
+#define PPC_OPERAND_VR (020000)
/* This operand is for the DS field in a DS form instruction. */
-#define PPC_OPERAND_DS (020000)
+#define PPC_OPERAND_DS (040000)
/* This operand is for the DQ field in a DQ form instruction. */
-#define PPC_OPERAND_DQ (040000)
+#define PPC_OPERAND_DQ (0100000)
/* The POWER and PowerPC assemblers use a few macros. We keep them
with the operands table for simplicity. The macro table is an
diff --git a/arch/powerpc/xmon/setjmp.S b/arch/powerpc/xmon/setjmp.S
deleted file mode 100644
index 96a91f10e2e..00000000000
--- a/arch/powerpc/xmon/setjmp.S
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
-/*
- * Grab the register values as they are now.
- * This won't do a particularily good job because we really
- * want our caller's caller's registers, and our caller has
- * already executed its prologue.
- * ToDo: We could reach back into the caller's save area to do
- * a better job of representing the caller's state (note that
- * that will be different for 32-bit and 64-bit, because of the
- * different ABIs, though).
- */
-_GLOBAL(xmon_save_regs)
- PPC_STL r0,0*SZL(r3)
- PPC_STL r2,2*SZL(r3)
- PPC_STL r3,3*SZL(r3)
- PPC_STL r4,4*SZL(r3)
- PPC_STL r5,5*SZL(r3)
- PPC_STL r6,6*SZL(r3)
- PPC_STL r7,7*SZL(r3)
- PPC_STL r8,8*SZL(r3)
- PPC_STL r9,9*SZL(r3)
- PPC_STL r10,10*SZL(r3)
- PPC_STL r11,11*SZL(r3)
- PPC_STL r12,12*SZL(r3)
- PPC_STL r13,13*SZL(r3)
- PPC_STL r14,14*SZL(r3)
- PPC_STL r15,15*SZL(r3)
- PPC_STL r16,16*SZL(r3)
- PPC_STL r17,17*SZL(r3)
- PPC_STL r18,18*SZL(r3)
- PPC_STL r19,19*SZL(r3)
- PPC_STL r20,20*SZL(r3)
- PPC_STL r21,21*SZL(r3)
- PPC_STL r22,22*SZL(r3)
- PPC_STL r23,23*SZL(r3)
- PPC_STL r24,24*SZL(r3)
- PPC_STL r25,25*SZL(r3)
- PPC_STL r26,26*SZL(r3)
- PPC_STL r27,27*SZL(r3)
- PPC_STL r28,28*SZL(r3)
- PPC_STL r29,29*SZL(r3)
- PPC_STL r30,30*SZL(r3)
- PPC_STL r31,31*SZL(r3)
- /* go up one stack frame for SP */
- PPC_LL r4,0(r1)
- PPC_STL r4,1*SZL(r3)
- /* get caller's LR */
- PPC_LL r0,LRSAVE(r4)
- PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
- PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
- mfmsr r0
- PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
- mfctr r0
- PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
- mfxer r0
- PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
- mfcr r0
- PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
- li r0,0
- PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
- blr
diff --git a/arch/powerpc/xmon/spu-dis.c b/arch/powerpc/xmon/spu-dis.c
new file mode 100644
index 00000000000..e5f89837c82
--- /dev/null
+++ b/arch/powerpc/xmon/spu-dis.c
@@ -0,0 +1,248 @@
+/* Disassemble SPU instructions
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB, GAS, and the GNU binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <linux/string.h>
+#include "nonstdio.h"
+#include "ansidecl.h"
+#include "spu.h"
+#include "dis-asm.h"
+
+/* This file provides a disassembler function which uses
+ the disassembler interface defined in dis-asm.h. */
+
+extern const struct spu_opcode spu_opcodes[];
+extern const int spu_num_opcodes;
+
+#define SPU_DISASM_TBL_SIZE (1 << 11)
+static const struct spu_opcode *spu_disassemble_table[SPU_DISASM_TBL_SIZE];
+
+static void
+init_spu_disassemble (void)
+{
+ int i;
+
+ /* If two instructions have the same opcode then we prefer the first
+ * one. In most cases it is just an alternate mnemonic. */
+ for (i = 0; i < spu_num_opcodes; i++)
+ {
+ int o = spu_opcodes[i].opcode;
+ if (o >= SPU_DISASM_TBL_SIZE)
+ continue; /* abort (); */
+ if (spu_disassemble_table[o] == 0)
+ spu_disassemble_table[o] = &spu_opcodes[i];
+ }
+}
+
+/* Determine the instruction from the 10 least significant bits. */
+static const struct spu_opcode *
+get_index_for_opcode (unsigned int insn)
+{
+ const struct spu_opcode *index;
+ unsigned int opcode = insn >> (32-11);
+
+ /* Init the table. This assumes that element 0/opcode 0 (currently
+ * NOP) is always used */
+ if (spu_disassemble_table[0] == 0)
+ init_spu_disassemble ();
+
+ if ((index = spu_disassemble_table[opcode & 0x780]) != 0
+ && index->insn_type == RRR)
+ return index;
+
+ if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
+ && (index->insn_type == RI18 || index->insn_type == LBT))
+ return index;
+
+ if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
+ && index->insn_type == RI10)
+ return index;
+
+ if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
+ && (index->insn_type == RI16))
+ return index;
+
+ if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
+ && (index->insn_type == RI8))
+ return index;
+
+ if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
+ return index;
+
+ return NULL;
+}
+
+/* Print a Spu instruction. */
+
+int
+print_insn_spu (unsigned long insn, unsigned long memaddr)
+{
+ int value;
+ int hex_value;
+ const struct spu_opcode *index;
+ enum spu_insns tag;
+
+ index = get_index_for_opcode (insn);
+
+ if (index == 0)
+ {
+ printf(".long 0x%x", insn);
+ }
+ else
+ {
+ int i;
+ int paren = 0;
+ tag = (enum spu_insns)(index - spu_opcodes);
+ printf("%s", index->mnemonic);
+ if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
+ || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
+ || tag == M_SYNC || tag == M_HBR)
+ {
+ int fb = (insn >> (32-18)) & 0x7f;
+ if (fb & 0x40)
+ printf(tag == M_SYNC ? "c" : "p");
+ if (fb & 0x20)
+ printf("d");
+ if (fb & 0x10)
+ printf("e");
+ }
+ if (index->arg[0] != 0)
+ printf("\t");
+ hex_value = 0;
+ for (i = 1; i <= index->arg[0]; i++)
+ {
+ int arg = index->arg[i];
+ if (arg != A_P && !paren && i > 1)
+ printf(",");
+
+ switch (arg)
+ {
+ case A_T:
+ printf("$%d",
+ DECODE_INSN_RT (insn));
+ break;
+ case A_A:
+ printf("$%d",
+ DECODE_INSN_RA (insn));
+ break;
+ case A_B:
+ printf("$%d",
+ DECODE_INSN_RB (insn));
+ break;
+ case A_C:
+ printf("$%d",
+ DECODE_INSN_RC (insn));
+ break;
+ case A_S:
+ printf("$sp%d",
+ DECODE_INSN_RA (insn));
+ break;
+ case A_H:
+ printf("$ch%d",
+ DECODE_INSN_RA (insn));
+ break;
+ case A_P:
+ paren++;
+ printf("(");
+ break;
+ case A_U7A:
+ printf("%d",
+ 173 - DECODE_INSN_U8 (insn));
+ break;
+ case A_U7B:
+ printf("%d",
+ 155 - DECODE_INSN_U8 (insn));
+ break;
+ case A_S3:
+ case A_S6:
+ case A_S7:
+ case A_S7N:
+ case A_U3:
+ case A_U5:
+ case A_U6:
+ case A_U7:
+ hex_value = DECODE_INSN_I7 (insn);
+ printf("%d", hex_value);
+ break;
+ case A_S11:
+ print_address(memaddr + DECODE_INSN_I9a (insn) * 4);
+ break;
+ case A_S11I:
+ print_address(memaddr + DECODE_INSN_I9b (insn) * 4);
+ break;
+ case A_S10:
+ case A_S10B:
+ hex_value = DECODE_INSN_I10 (insn);
+ printf("%d", hex_value);
+ break;
+ case A_S14:
+ hex_value = DECODE_INSN_I10 (insn) * 16;
+ printf("%d", hex_value);
+ break;
+ case A_S16:
+ hex_value = DECODE_INSN_I16 (insn);
+ printf("%d", hex_value);
+ break;
+ case A_X16:
+ hex_value = DECODE_INSN_U16 (insn);
+ printf("%u", hex_value);
+ break;
+ case A_R18:
+ value = DECODE_INSN_I16 (insn) * 4;
+ if (value == 0)
+ printf("%d", value);
+ else
+ {
+ hex_value = memaddr + value;
+ print_address(hex_value & 0x3ffff);
+ }
+ break;
+ case A_S18:
+ value = DECODE_INSN_U16 (insn) * 4;
+ if (value == 0)
+ printf("%d", value);
+ else
+ print_address(value);
+ break;
+ case A_U18:
+ value = DECODE_INSN_U18 (insn);
+ if (value == 0 || 1)
+ {
+ hex_value = value;
+ printf("%u", value);
+ }
+ else
+ print_address(value);
+ break;
+ case A_U14:
+ hex_value = DECODE_INSN_U14 (insn);
+ printf("%u", hex_value);
+ break;
+ }
+ if (arg != A_P && paren)
+ {
+ printf(")");
+ paren--;
+ }
+ }
+ if (hex_value > 16)
+ printf("\t# %x", hex_value);
+ }
+ return 4;
+}
diff --git a/arch/powerpc/xmon/spu-insns.h b/arch/powerpc/xmon/spu-insns.h
new file mode 100644
index 00000000000..99dc452821a
--- /dev/null
+++ b/arch/powerpc/xmon/spu-insns.h
@@ -0,0 +1,410 @@
+/* SPU ELF support for BFD.
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* SPU Opcode Table
+
+-=-=-= FORMAT =-=-=-
+
+ +----+-------+-------+-------+-------+ +------------+-------+-------+-------+
+RRR | op | RC | RB | RA | RT | RI7 | op | I7 | RA | RT |
+ +----+-------+-------+-------+-------+ +------------+-------+-------+-------+
+ 0 3 1 1 2 3 0 1 1 2 3
+ 0 7 4 1 0 7 4 1
+
+ +-----------+--------+-------+-------+ +---------+----------+-------+-------+
+RI8 | op | I8 | RA | RT | RI10 | op | I10 | RA | RT |
+ +-----------+--------+-------+-------+ +---------+----------+-------+-------+
+ 0 9 1 2 3 0 7 1 2 3
+ 7 4 1 7 4 1
+
+ +----------+-----------------+-------+ +--------+-------------------+-------+
+RI16 | op | I16 | RT | RI18 | op | I18 | RT |
+ +----------+-----------------+-------+ +--------+-------------------+-------+
+ 0 8 2 3 0 6 2 3
+ 4 1 4 1
+
+ +------------+-------+-------+-------+ +-------+--+-----------------+-------+
+RR | op | RB | RA | RT | LBT | op |RO| I16 | RO |
+ +------------+-------+-------+-------+ +-------+--+-----------------+-------+
+ 0 1 1 2 3 0 6 8 2 3
+ 0 7 4 1 4 1
+
+ +------------+----+--+-------+-------+
+ LBTI | op | // |RO| RA | RO |
+ +------------+----+--+-------+-------+
+ 0 1 1 1 2 3
+ 0 5 7 4 1
+
+-=-=-= OPCODE =-=-=-
+
+OPCODE field specifies the most significant 11bit of the instruction. Some formats don't have 11bits for opcode field, and in this
+case, bit field other than op are defined as 0s. For example, opcode of fma instruction which is RRR format is defined as 0x700,
+since 0x700 -> 11'b11100000000, this means opcode is 4'b1110, and other 7bits are defined as 7'b0000000.
+
+-=-=-= ASM_FORMAT =-=-=-
+
+RRR category RI7 category
+ ASM_RRR mnemonic RC, RA, RB, RT ASM_RI4 mnemonic RT, RA, I4
+ ASM_RI7 mnemonic RT, RA, I7
+
+RI8 category RI10 category
+ ASM_RUI8 mnemonic RT, RA, UI8 ASM_AI10 mnemonic RA, I10
+ ASM_RI10 mnemonic RT, RA, R10
+ ASM_RI10IDX mnemonic RT, I10(RA)
+
+RI16 category RI18 category
+ ASM_I16W mnemonic I16W ASM_RI18 mnemonic RT, I18
+ ASM_RI16 mnemonic RT, I16
+ ASM_RI16W mnemonic RT, I16W
+
+RR category LBT category
+ ASM_MFSPR mnemonic RT, SA ASM_LBT mnemonic brinst, brtarg
+ ASM_MTSPR mnemonic SA, RT
+ ASM_NOOP mnemonic LBTI category
+ ASM_RA mnemonic RA ASM_LBTI mnemonic brinst, RA
+ ASM_RAB mnemonic RA, RB
+ ASM_RDCH mnemonic RT, CA
+ ASM_RR mnemonic RT, RA, RB
+ ASM_RT mnemonic RT
+ ASM_RTA mnemonic RT, RA
+ ASM_WRCH mnemonic CA, RT
+
+Note that RRR instructions have the names for RC and RT reversed from
+what's in the ISA, in order to put RT in the same position it appears
+for other formats.
+
+-=-=-= DEPENDENCY =-=-=-
+
+DEPENDENCY filed consists of 5 digits. This represents which register is used as source and which register is used as target.
+The first(most significant) digit is always 0. Then it is followd by RC, RB, RA and RT digits.
+If the digit is 0, this means the corresponding register is not used in the instruction.
+If the digit is 1, this means the corresponding register is used as a source in the instruction.
+If the digit is 2, this means the corresponding register is used as a target in the instruction.
+If the digit is 3, this means the corresponding register is used as both source and target in the instruction.
+For example, fms instruction has 00113 as the DEPENDENCY field. This means RC is not used in this operation, RB and RA are
+used as sources and RT is the target.
+
+-=-=-= PIPE =-=-=-
+
+This field shows which execution pipe is used for the instruction
+
+pipe0 execution pipelines:
+ FP6 SP floating pipeline
+ FP7 integer operations executed in SP floating pipeline
+ FPD DP floating pipeline
+ FX2 FXU pipeline
+ FX3 Rotate/Shift pipeline
+ FXB Byte pipeline
+ NOP No pipeline
+
+pipe1 execution pipelines:
+ BR Branch pipeline
+ LNOP No pipeline
+ LS Load/Store pipeline
+ SHUF Shuffle pipeline
+ SPR SPR/CH pipeline
+
+*/
+
+#define _A0() {0}
+#define _A1(a) {1,a}
+#define _A2(a,b) {2,a,b}
+#define _A3(a,b,c) {3,a,b,c}
+#define _A4(a,b,c,d) {4,a,b,c,d}
+
+/* TAG FORMAT OPCODE MNEMONIC ASM_FORMAT DEPENDENCY PIPE COMMENT */
+/* 0[RC][RB][RA][RT] */
+/* 1:src, 2:target */
+
+APUOP(M_BR, RI16, 0x190, "br", _A1(A_R18), 00000, BR) /* BRel IP<-IP+I16 */
+APUOP(M_BRSL, RI16, 0x198, "brsl", _A2(A_T,A_R18), 00002, BR) /* BRelSetLink RT,IP<-IP,IP+I16 */
+APUOP(M_BRA, RI16, 0x180, "bra", _A1(A_S18), 00000, BR) /* BRAbs IP<-I16 */
+APUOP(M_BRASL, RI16, 0x188, "brasl", _A2(A_T,A_S18), 00002, BR) /* BRAbsSetLink RT,IP<-IP,I16 */
+APUOP(M_FSMBI, RI16, 0x194, "fsmbi", _A2(A_T,A_X16), 00002, SHUF) /* FormSelMask%I RT<-fsm(I16) */
+APUOP(M_LQA, RI16, 0x184, "lqa", _A2(A_T,A_S18), 00002, LS) /* LoadQAbs RT<-M[I16] */
+APUOP(M_LQR, RI16, 0x19C, "lqr", _A2(A_T,A_R18), 00002, LS) /* LoadQRel RT<-M[IP+I16] */
+APUOP(M_STOP, RR, 0x000, "stop", _A0(), 00000, BR) /* STOP stop */
+APUOP(M_STOP2, RR, 0x000, "stop", _A1(A_U14), 00000, BR) /* STOP stop */
+APUOP(M_STOPD, RR, 0x140, "stopd", _A3(A_T,A_A,A_B), 00111, BR) /* STOPD stop (with register dependencies) */
+APUOP(M_LNOP, RR, 0x001, "lnop", _A0(), 00000, LNOP) /* LNOP no_operation */
+APUOP(M_SYNC, RR, 0x002, "sync", _A0(), 00000, BR) /* SYNC flush_pipe */
+APUOP(M_DSYNC, RR, 0x003, "dsync", _A0(), 00000, BR) /* DSYNC flush_store_queue */
+APUOP(M_MFSPR, RR, 0x00c, "mfspr", _A2(A_T,A_S), 00002, SPR) /* MFSPR RT<-SA */
+APUOP(M_RDCH, RR, 0x00d, "rdch", _A2(A_T,A_H), 00002, SPR) /* ReaDCHannel RT<-CA:data */
+APUOP(M_RCHCNT, RR, 0x00f, "rchcnt", _A2(A_T,A_H), 00002, SPR) /* ReaDCHanCouNT RT<-CA:count */
+APUOP(M_HBRA, LBT, 0x080, "hbra", _A2(A_S11,A_S18), 00000, LS) /* HBRA BTB[B9]<-M[I16] */
+APUOP(M_HBRR, LBT, 0x090, "hbrr", _A2(A_S11,A_R18), 00000, LS) /* HBRR BTB[B9]<-M[IP+I16] */
+APUOP(M_BRZ, RI16, 0x100, "brz", _A2(A_T,A_R18), 00001, BR) /* BRZ IP<-IP+I16_if(RT) */
+APUOP(M_BRNZ, RI16, 0x108, "brnz", _A2(A_T,A_R18), 00001, BR) /* BRNZ IP<-IP+I16_if(RT) */
+APUOP(M_BRHZ, RI16, 0x110, "brhz", _A2(A_T,A_R18), 00001, BR) /* BRHZ IP<-IP+I16_if(RT) */
+APUOP(M_BRHNZ, RI16, 0x118, "brhnz", _A2(A_T,A_R18), 00001, BR) /* BRHNZ IP<-IP+I16_if(RT) */
+APUOP(M_STQA, RI16, 0x104, "stqa", _A2(A_T,A_S18), 00001, LS) /* SToreQAbs M[I16]<-RT */
+APUOP(M_STQR, RI16, 0x11C, "stqr", _A2(A_T,A_R18), 00001, LS) /* SToreQRel M[IP+I16]<-RT */
+APUOP(M_MTSPR, RR, 0x10c, "mtspr", _A2(A_S,A_T), 00001, SPR) /* MTSPR SA<-RT */
+APUOP(M_WRCH, RR, 0x10d, "wrch", _A2(A_H,A_T), 00001, SPR) /* ChanWRite CA<-RT */
+APUOP(M_LQD, RI10, 0x1a0, "lqd", _A4(A_T,A_S14,A_P,A_A), 00012, LS) /* LoadQDisp RT<-M[Ra+I10] */
+APUOP(M_BI, RR, 0x1a8, "bi", _A1(A_A), 00010, BR) /* BI IP<-RA */
+APUOP(M_BISL, RR, 0x1a9, "bisl", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */
+APUOP(M_IRET, RR, 0x1aa, "iret", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */
+APUOP(M_IRET2, RR, 0x1aa, "iret", _A0(), 00010, BR) /* IRET IP<-SRR0 */
+APUOP(M_BISLED, RR, 0x1ab, "bisled", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */
+APUOP(M_HBR, LBTI, 0x1ac, "hbr", _A2(A_S11I,A_A), 00010, LS) /* HBR BTB[B9]<-M[Ra] */
+APUOP(M_FREST, RR, 0x1b8, "frest", _A2(A_T,A_A), 00012, SHUF) /* FREST RT<-recip(RA) */
+APUOP(M_FRSQEST, RR, 0x1b9, "frsqest", _A2(A_T,A_A), 00012, SHUF) /* FRSQEST RT<-rsqrt(RA) */
+APUOP(M_FSM, RR, 0x1b4, "fsm", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */
+APUOP(M_FSMH, RR, 0x1b5, "fsmh", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */
+APUOP(M_FSMB, RR, 0x1b6, "fsmb", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */
+APUOP(M_GB, RR, 0x1b0, "gb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */
+APUOP(M_GBH, RR, 0x1b1, "gbh", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */
+APUOP(M_GBB, RR, 0x1b2, "gbb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */
+APUOP(M_CBD, RI7, 0x1f4, "cbd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
+APUOP(M_CHD, RI7, 0x1f5, "chd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
+APUOP(M_CWD, RI7, 0x1f6, "cwd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
+APUOP(M_CDD, RI7, 0x1f7, "cdd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */
+APUOP(M_ROTQBII, RI7, 0x1f8, "rotqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* ROTQBII RT<-RA<<<I7 */
+APUOP(M_ROTQBYI, RI7, 0x1fc, "rotqbyi", _A3(A_T,A_A,A_S7N), 00012, SHUF) /* ROTQBYI RT<-RA<<<(I7*8) */
+APUOP(M_ROTQMBII, RI7, 0x1f9, "rotqmbii", _A3(A_T,A_A,A_S3), 00012, SHUF) /* ROTQMBII RT<-RA<<I7 */
+APUOP(M_ROTQMBYI, RI7, 0x1fd, "rotqmbyi", _A3(A_T,A_A,A_S6), 00012, SHUF) /* ROTQMBYI RT<-RA<<I7 */
+APUOP(M_SHLQBII, RI7, 0x1fb, "shlqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* SHLQBII RT<-RA<<I7 */
+APUOP(M_SHLQBYI, RI7, 0x1ff, "shlqbyi", _A3(A_T,A_A,A_U5), 00012, SHUF) /* SHLQBYI RT<-RA<<I7 */
+APUOP(M_STQD, RI10, 0x120, "stqd", _A4(A_T,A_S14,A_P,A_A), 00011, LS) /* SToreQDisp M[Ra+I10]<-RT */
+APUOP(M_BIHNZ, RR, 0x12b, "bihnz", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
+APUOP(M_BIHZ, RR, 0x12a, "bihz", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
+APUOP(M_BINZ, RR, 0x129, "binz", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
+APUOP(M_BIZ, RR, 0x128, "biz", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
+APUOP(M_CBX, RR, 0x1d4, "cbx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
+APUOP(M_CHX, RR, 0x1d5, "chx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
+APUOP(M_CWX, RR, 0x1d6, "cwx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
+APUOP(M_CDX, RR, 0x1d7, "cdx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */
+APUOP(M_LQX, RR, 0x1c4, "lqx", _A3(A_T,A_A,A_B), 00112, LS) /* LoadQindeX RT<-M[Ra+Rb] */
+APUOP(M_ROTQBI, RR, 0x1d8, "rotqbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBI RT<-RA<<<Rb */
+APUOP(M_ROTQMBI, RR, 0x1d9, "rotqmbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBI RT<-RA<<Rb */
+APUOP(M_SHLQBI, RR, 0x1db, "shlqbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBI RT<-RA<<Rb */
+APUOP(M_ROTQBY, RR, 0x1dc, "rotqby", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBY RT<-RA<<<(Rb*8) */
+APUOP(M_ROTQMBY, RR, 0x1dd, "rotqmby", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBY RT<-RA<<Rb */
+APUOP(M_SHLQBY, RR, 0x1df, "shlqby", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBY RT<-RA<<Rb */
+APUOP(M_ROTQBYBI, RR, 0x1cc, "rotqbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBYBI RT<-RA<<Rb */
+APUOP(M_ROTQMBYBI, RR, 0x1cd, "rotqmbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBYBI RT<-RA<<Rb */
+APUOP(M_SHLQBYBI, RR, 0x1cf, "shlqbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBYBI RT<-RA<<Rb */
+APUOP(M_STQX, RR, 0x144, "stqx", _A3(A_T,A_A,A_B), 00111, LS) /* SToreQindeX M[Ra+Rb]<-RT */
+APUOP(M_SHUFB, RRR, 0x580, "shufb", _A4(A_C,A_A,A_B,A_T), 02111, SHUF) /* SHUFfleBytes RC<-f(RA,RB,RT) */
+APUOP(M_IL, RI16, 0x204, "il", _A2(A_T,A_S16), 00002, FX2) /* ImmLoad RT<-sxt(I16) */
+APUOP(M_ILH, RI16, 0x20c, "ilh", _A2(A_T,A_X16), 00002, FX2) /* ImmLoadH RT<-I16 */
+APUOP(M_ILHU, RI16, 0x208, "ilhu", _A2(A_T,A_X16), 00002, FX2) /* ImmLoadHUpper RT<-I16<<16 */
+APUOP(M_ILA, RI18, 0x210, "ila", _A2(A_T,A_U18), 00002, FX2) /* ImmLoadAddr RT<-zxt(I18) */
+APUOP(M_NOP, RR, 0x201, "nop", _A1(A_T), 00000, NOP) /* XNOP no_operation */
+APUOP(M_NOP2, RR, 0x201, "nop", _A0(), 00000, NOP) /* XNOP no_operation */
+APUOP(M_IOHL, RI16, 0x304, "iohl", _A2(A_T,A_X16), 00003, FX2) /* AddImmeXt RT<-RT+sxt(I16) */
+APUOP(M_ANDBI, RI10, 0x0b0, "andbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* AND%I RT<-RA&I10 */
+APUOP(M_ANDHI, RI10, 0x0a8, "andhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* AND%I RT<-RA&I10 */
+APUOP(M_ANDI, RI10, 0x0a0, "andi", _A3(A_T,A_A,A_S10), 00012, FX2) /* AND%I RT<-RA&I10 */
+APUOP(M_ORBI, RI10, 0x030, "orbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* OR%I RT<-RA|I10 */
+APUOP(M_ORHI, RI10, 0x028, "orhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* OR%I RT<-RA|I10 */
+APUOP(M_ORI, RI10, 0x020, "ori", _A3(A_T,A_A,A_S10), 00012, FX2) /* OR%I RT<-RA|I10 */
+APUOP(M_ORX, RR, 0x1f0, "orx", _A2(A_T,A_A), 00012, BR) /* ORX RT<-RA.w0|RA.w1|RA.w2|RA.w3 */
+APUOP(M_XORBI, RI10, 0x230, "xorbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* XOR%I RT<-RA^I10 */
+APUOP(M_XORHI, RI10, 0x228, "xorhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* XOR%I RT<-RA^I10 */
+APUOP(M_XORI, RI10, 0x220, "xori", _A3(A_T,A_A,A_S10), 00012, FX2) /* XOR%I RT<-RA^I10 */
+APUOP(M_AHI, RI10, 0x0e8, "ahi", _A3(A_T,A_A,A_S10), 00012, FX2) /* Add%Immed RT<-RA+I10 */
+APUOP(M_AI, RI10, 0x0e0, "ai", _A3(A_T,A_A,A_S10), 00012, FX2) /* Add%Immed RT<-RA+I10 */
+APUOP(M_SFHI, RI10, 0x068, "sfhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* SubFrom%Imm RT<-I10-RA */
+APUOP(M_SFI, RI10, 0x060, "sfi", _A3(A_T,A_A,A_S10), 00012, FX2) /* SubFrom%Imm RT<-I10-RA */
+APUOP(M_CGTBI, RI10, 0x270, "cgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CGT%I RT<-(RA>I10) */
+APUOP(M_CGTHI, RI10, 0x268, "cgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */
+APUOP(M_CGTI, RI10, 0x260, "cgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */
+APUOP(M_CLGTBI, RI10, 0x2f0, "clgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CLGT%I RT<-(RA>I10) */
+APUOP(M_CLGTHI, RI10, 0x2e8, "clgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */
+APUOP(M_CLGTI, RI10, 0x2e0, "clgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */
+APUOP(M_CEQBI, RI10, 0x3f0, "ceqbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CEQ%I RT<-(RA=I10) */
+APUOP(M_CEQHI, RI10, 0x3e8, "ceqhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */
+APUOP(M_CEQI, RI10, 0x3e0, "ceqi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */
+APUOP(M_HGTI, RI10, 0x278, "hgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */
+APUOP(M_HGTI2, RI10, 0x278, "hgti", _A2(A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */
+APUOP(M_HLGTI, RI10, 0x2f8, "hlgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */
+APUOP(M_HLGTI2, RI10, 0x2f8, "hlgti", _A2(A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */
+APUOP(M_HEQI, RI10, 0x3f8, "heqi", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */
+APUOP(M_HEQI2, RI10, 0x3f8, "heqi", _A2(A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */
+APUOP(M_MPYI, RI10, 0x3a0, "mpyi", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYI RT<-RA*I10 */
+APUOP(M_MPYUI, RI10, 0x3a8, "mpyui", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYUI RT<-RA*I10 */
+APUOP(M_CFLTS, RI8, 0x3b0, "cflts", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTS RT<-int(RA,I8) */
+APUOP(M_CFLTU, RI8, 0x3b2, "cfltu", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTU RT<-int(RA,I8) */
+APUOP(M_CSFLT, RI8, 0x3b4, "csflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CSFLT RT<-flt(RA,I8) */
+APUOP(M_CUFLT, RI8, 0x3b6, "cuflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CUFLT RT<-flt(RA,I8) */
+APUOP(M_FESD, RR, 0x3b8, "fesd", _A2(A_T,A_A), 00012, FPD) /* FESD RT<-double(RA) */
+APUOP(M_FRDS, RR, 0x3b9, "frds", _A2(A_T,A_A), 00012, FPD) /* FRDS RT<-single(RA) */
+APUOP(M_FSCRRD, RR, 0x398, "fscrrd", _A1(A_T), 00002, FPD) /* FSCRRD RT<-FP_status */
+APUOP(M_FSCRWR, RR, 0x3ba, "fscrwr", _A2(A_T,A_A), 00010, FP7) /* FSCRWR FP_status<-RA */
+APUOP(M_FSCRWR2, RR, 0x3ba, "fscrwr", _A1(A_A), 00010, FP7) /* FSCRWR FP_status<-RA */
+APUOP(M_CLZ, RR, 0x2a5, "clz", _A2(A_T,A_A), 00012, FX2) /* CLZ RT<-clz(RA) */
+APUOP(M_CNTB, RR, 0x2b4, "cntb", _A2(A_T,A_A), 00012, FXB) /* CNT RT<-pop(RA) */
+APUOP(M_XSBH, RR, 0x2b6, "xsbh", _A2(A_T,A_A), 00012, FX2) /* eXtSignBtoH RT<-sign_ext(RA) */
+APUOP(M_XSHW, RR, 0x2ae, "xshw", _A2(A_T,A_A), 00012, FX2) /* eXtSignHtoW RT<-sign_ext(RA) */
+APUOP(M_XSWD, RR, 0x2a6, "xswd", _A2(A_T,A_A), 00012, FX2) /* eXtSignWtoD RT<-sign_ext(RA) */
+APUOP(M_ROTI, RI7, 0x078, "roti", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<<I7 */
+APUOP(M_ROTMI, RI7, 0x079, "rotmi", _A3(A_T,A_A,A_S7), 00012, FX3) /* ROT%MI RT<-RA<<I7 */
+APUOP(M_ROTMAI, RI7, 0x07a, "rotmai", _A3(A_T,A_A,A_S7), 00012, FX3) /* ROTMA%I RT<-RA<<I7 */
+APUOP(M_SHLI, RI7, 0x07b, "shli", _A3(A_T,A_A,A_U6), 00012, FX3) /* SHL%I RT<-RA<<I7 */
+APUOP(M_ROTHI, RI7, 0x07c, "rothi", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<<I7 */
+APUOP(M_ROTHMI, RI7, 0x07d, "rothmi", _A3(A_T,A_A,A_S6), 00012, FX3) /* ROT%MI RT<-RA<<I7 */
+APUOP(M_ROTMAHI, RI7, 0x07e, "rotmahi", _A3(A_T,A_A,A_S6), 00012, FX3) /* ROTMA%I RT<-RA<<I7 */
+APUOP(M_SHLHI, RI7, 0x07f, "shlhi", _A3(A_T,A_A,A_U5), 00012, FX3) /* SHL%I RT<-RA<<I7 */
+APUOP(M_A, RR, 0x0c0, "a", _A3(A_T,A_A,A_B), 00112, FX2) /* Add% RT<-RA+RB */
+APUOP(M_AH, RR, 0x0c8, "ah", _A3(A_T,A_A,A_B), 00112, FX2) /* Add% RT<-RA+RB */
+APUOP(M_SF, RR, 0x040, "sf", _A3(A_T,A_A,A_B), 00112, FX2) /* SubFrom% RT<-RB-RA */
+APUOP(M_SFH, RR, 0x048, "sfh", _A3(A_T,A_A,A_B), 00112, FX2) /* SubFrom% RT<-RB-RA */
+APUOP(M_CGT, RR, 0x240, "cgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */
+APUOP(M_CGTB, RR, 0x250, "cgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */
+APUOP(M_CGTH, RR, 0x248, "cgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */
+APUOP(M_CLGT, RR, 0x2c0, "clgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */
+APUOP(M_CLGTB, RR, 0x2d0, "clgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */
+APUOP(M_CLGTH, RR, 0x2c8, "clgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */
+APUOP(M_CEQ, RR, 0x3c0, "ceq", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */
+APUOP(M_CEQB, RR, 0x3d0, "ceqb", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */
+APUOP(M_CEQH, RR, 0x3c8, "ceqh", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */
+APUOP(M_HGT, RR, 0x258, "hgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */
+APUOP(M_HGT2, RR, 0x258, "hgt", _A2(A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */
+APUOP(M_HLGT, RR, 0x2d8, "hlgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */
+APUOP(M_HLGT2, RR, 0x2d8, "hlgt", _A2(A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */
+APUOP(M_HEQ, RR, 0x3d8, "heq", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */
+APUOP(M_HEQ2, RR, 0x3d8, "heq", _A2(A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */
+APUOP(M_FCEQ, RR, 0x3c2, "fceq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCEQ RT<-(RA=RB) */
+APUOP(M_FCMEQ, RR, 0x3ca, "fcmeq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMEQ RT<-(|RA|=|RB|) */
+APUOP(M_FCGT, RR, 0x2c2, "fcgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCGT RT<-(RA<RB) */
+APUOP(M_FCMGT, RR, 0x2ca, "fcmgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMGT RT<-(|RA|<|RB|) */
+APUOP(M_AND, RR, 0x0c1, "and", _A3(A_T,A_A,A_B), 00112, FX2) /* AND RT<-RA&RB */
+APUOP(M_NAND, RR, 0x0c9, "nand", _A3(A_T,A_A,A_B), 00112, FX2) /* NAND RT<-!(RA&RB) */
+APUOP(M_OR, RR, 0x041, "or", _A3(A_T,A_A,A_B), 00112, FX2) /* OR RT<-RA|RB */
+APUOP(M_NOR, RR, 0x049, "nor", _A3(A_T,A_A,A_B), 00112, FX2) /* NOR RT<-!(RA&RB) */
+APUOP(M_XOR, RR, 0x241, "xor", _A3(A_T,A_A,A_B), 00112, FX2) /* XOR RT<-RA^RB */
+APUOP(M_EQV, RR, 0x249, "eqv", _A3(A_T,A_A,A_B), 00112, FX2) /* EQuiValent RT<-!(RA^RB) */
+APUOP(M_ANDC, RR, 0x2c1, "andc", _A3(A_T,A_A,A_B), 00112, FX2) /* ANDComplement RT<-RA&!RB */
+APUOP(M_ORC, RR, 0x2c9, "orc", _A3(A_T,A_A,A_B), 00112, FX2) /* ORComplement RT<-RA|!RB */
+APUOP(M_ABSDB, RR, 0x053, "absdb", _A3(A_T,A_A,A_B), 00112, FXB) /* ABSoluteDiff RT<-|RA-RB| */
+APUOP(M_AVGB, RR, 0x0d3, "avgb", _A3(A_T,A_A,A_B), 00112, FXB) /* AVG% RT<-(RA+RB+1)/2 */
+APUOP(M_SUMB, RR, 0x253, "sumb", _A3(A_T,A_A,A_B), 00112, FXB) /* SUM% RT<-f(RA,RB) */
+APUOP(M_DFA, RR, 0x2cc, "dfa", _A3(A_T,A_A,A_B), 00112, FPD) /* DFAdd RT<-RA+RB */
+APUOP(M_DFM, RR, 0x2ce, "dfm", _A3(A_T,A_A,A_B), 00112, FPD) /* DFMul RT<-RA*RB */
+APUOP(M_DFS, RR, 0x2cd, "dfs", _A3(A_T,A_A,A_B), 00112, FPD) /* DFSub RT<-RA-RB */
+APUOP(M_FA, RR, 0x2c4, "fa", _A3(A_T,A_A,A_B), 00112, FP6) /* FAdd RT<-RA+RB */
+APUOP(M_FM, RR, 0x2c6, "fm", _A3(A_T,A_A,A_B), 00112, FP6) /* FMul RT<-RA*RB */
+APUOP(M_FS, RR, 0x2c5, "fs", _A3(A_T,A_A,A_B), 00112, FP6) /* FSub RT<-RA-RB */
+APUOP(M_MPY, RR, 0x3c4, "mpy", _A3(A_T,A_A,A_B), 00112, FP7) /* MPY RT<-RA*RB */
+APUOP(M_MPYH, RR, 0x3c5, "mpyh", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYH RT<-(RAh*RB)<<16 */
+APUOP(M_MPYHH, RR, 0x3c6, "mpyhh", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYHH RT<-RAh*RBh */
+APUOP(M_MPYHHU, RR, 0x3ce, "mpyhhu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYHHU RT<-RAh*RBh */
+APUOP(M_MPYS, RR, 0x3c7, "mpys", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYS RT<-(RA*RB)>>16 */
+APUOP(M_MPYU, RR, 0x3cc, "mpyu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYU RT<-RA*RB */
+APUOP(M_FI, RR, 0x3d4, "fi", _A3(A_T,A_A,A_B), 00112, FP7) /* FInterpolate RT<-f(RA,RB) */
+APUOP(M_ROT, RR, 0x058, "rot", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<<RB */
+APUOP(M_ROTM, RR, 0x059, "rotm", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT%M RT<-RA<<Rb */
+APUOP(M_ROTMA, RR, 0x05a, "rotma", _A3(A_T,A_A,A_B), 00112, FX3) /* ROTMA% RT<-RA<<Rb */
+APUOP(M_SHL, RR, 0x05b, "shl", _A3(A_T,A_A,A_B), 00112, FX3) /* SHL% RT<-RA<<Rb */
+APUOP(M_ROTH, RR, 0x05c, "roth", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<<RB */
+APUOP(M_ROTHM, RR, 0x05d, "rothm", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT%M RT<-RA<<Rb */
+APUOP(M_ROTMAH, RR, 0x05e, "rotmah", _A3(A_T,A_A,A_B), 00112, FX3) /* ROTMA% RT<-RA<<Rb */
+APUOP(M_SHLH, RR, 0x05f, "shlh", _A3(A_T,A_A,A_B), 00112, FX3) /* SHL% RT<-RA<<Rb */
+APUOP(M_MPYHHA, RR, 0x346, "mpyhha", _A3(A_T,A_A,A_B), 00113, FP7) /* MPYHHA RT<-RAh*RBh+RT */
+APUOP(M_MPYHHAU, RR, 0x34e, "mpyhhau", _A3(A_T,A_A,A_B), 00113, FP7) /* MPYHHAU RT<-RAh*RBh+RT */
+APUOP(M_DFMA, RR, 0x35c, "dfma", _A3(A_T,A_A,A_B), 00113, FPD) /* DFMAdd RT<-RT+RA*RB */
+APUOP(M_DFMS, RR, 0x35d, "dfms", _A3(A_T,A_A,A_B), 00113, FPD) /* DFMSub RT<-RA*RB-RT */
+APUOP(M_DFNMS, RR, 0x35e, "dfnms", _A3(A_T,A_A,A_B), 00113, FPD) /* DFNMSub RT<-RT-RA*RB */
+APUOP(M_DFNMA, RR, 0x35f, "dfnma", _A3(A_T,A_A,A_B), 00113, FPD) /* DFNMAdd RT<-(-RT)-RA*RB */
+APUOP(M_FMA, RRR, 0x700, "fma", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FMAdd RC<-RT+RA*RB */
+APUOP(M_FMS, RRR, 0x780, "fms", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FMSub RC<-RA*RB-RT */
+APUOP(M_FNMS, RRR, 0x680, "fnms", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FNMSub RC<-RT-RA*RB */
+APUOP(M_MPYA, RRR, 0x600, "mpya", _A4(A_C,A_A,A_B,A_T), 02111, FP7) /* MPYA RC<-RA*RB+RT */
+APUOP(M_SELB, RRR, 0x400, "selb", _A4(A_C,A_A,A_B,A_T), 02111, FX2) /* SELectBits RC<-RA&RT|RB&!RT */
+/* for system function call, this uses op-code of mtspr */
+APUOP(M_SYSCALL, RI7, 0x10c, "syscall", _A3(A_T,A_A,A_S7N), 00002, SPR) /* System Call */
+/*
+pseudo instruction:
+system call
+value of I9 operation
+0 halt
+1 rt[0] = open(MEM[ra[0]], ra[1])
+2 rt[0] = close(ra[0])
+3 rt[0] = read(ra[0], MEM[ra[1]], ra[2])
+4 rt[0] = write(ra[0], MEM[ra[1]], ra[2])
+5 printf(MEM[ra[0]], ra[1], ra[2], ra[3])
+42 rt[0] = clock()
+52 rt[0] = lseek(ra0, ra1, ra2)
+
+*/
+
+
+/* new multiprecision add/sub */
+APUOP(M_ADDX, RR, 0x340, "addx", _A3(A_T,A_A,A_B), 00113, FX2) /* Add_eXtended RT<-RA+RB+RT */
+APUOP(M_CG, RR, 0x0c2, "cg", _A3(A_T,A_A,A_B), 00112, FX2) /* CarryGenerate RT<-cout(RA+RB) */
+APUOP(M_CGX, RR, 0x342, "cgx", _A3(A_T,A_A,A_B), 00113, FX2) /* CarryGen_eXtd RT<-cout(RA+RB+RT) */
+APUOP(M_SFX, RR, 0x341, "sfx", _A3(A_T,A_A,A_B), 00113, FX2) /* Add_eXtended RT<-RA+RB+RT */
+APUOP(M_BG, RR, 0x042, "bg", _A3(A_T,A_A,A_B), 00112, FX2) /* CarryGenerate RT<-cout(RA+RB) */
+APUOP(M_BGX, RR, 0x343, "bgx", _A3(A_T,A_A,A_B), 00113, FX2) /* CarryGen_eXtd RT<-cout(RA+RB+RT) */
+
+/*
+
+The following ops are a subset of above except with feature bits set.
+Feature bits are bits 11-17 of the instruction:
+
+ 11 - C & P feature bit
+ 12 - disable interrupts
+ 13 - enable interrupts
+
+*/
+APUOPFB(M_BID, RR, 0x1a8, 0x20, "bid", _A1(A_A), 00010, BR) /* BI IP<-RA */
+APUOPFB(M_BIE, RR, 0x1a8, 0x10, "bie", _A1(A_A), 00010, BR) /* BI IP<-RA */
+APUOPFB(M_BISLD, RR, 0x1a9, 0x20, "bisld", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */
+APUOPFB(M_BISLE, RR, 0x1a9, 0x10, "bisle", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */
+APUOPFB(M_IRETD, RR, 0x1aa, 0x20, "iretd", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */
+APUOPFB(M_IRETD2, RR, 0x1aa, 0x20, "iretd", _A0(), 00010, BR) /* IRET IP<-SRR0 */
+APUOPFB(M_IRETE, RR, 0x1aa, 0x10, "irete", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */
+APUOPFB(M_IRETE2, RR, 0x1aa, 0x10, "irete", _A0(), 00010, BR) /* IRET IP<-SRR0 */
+APUOPFB(M_BISLEDD, RR, 0x1ab, 0x20, "bisledd", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */
+APUOPFB(M_BISLEDE, RR, 0x1ab, 0x10, "bislede", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */
+APUOPFB(M_BIHNZD, RR, 0x12b, 0x20, "bihnzd", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
+APUOPFB(M_BIHNZE, RR, 0x12b, 0x10, "bihnze", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
+APUOPFB(M_BIHZD, RR, 0x12a, 0x20, "bihzd", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
+APUOPFB(M_BIHZE, RR, 0x12a, 0x10, "bihze", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
+APUOPFB(M_BINZD, RR, 0x129, 0x20, "binzd", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
+APUOPFB(M_BINZE, RR, 0x129, 0x10, "binze", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
+APUOPFB(M_BIZD, RR, 0x128, 0x20, "bizd", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
+APUOPFB(M_BIZE, RR, 0x128, 0x10, "bize", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
+APUOPFB(M_SYNCC, RR, 0x002, 0x40, "syncc", _A0(), 00000, BR) /* SYNCC flush_pipe */
+APUOPFB(M_HBRP, LBTI, 0x1ac, 0x40, "hbrp", _A0(), 00010, LS) /* HBR BTB[B9]<-M[Ra] */
+
+/* Synonyms required by the AS manual. */
+APUOP(M_LR, RI10, 0x020, "lr", _A2(A_T,A_A), 00012, FX2) /* OR%I RT<-RA|I10 */
+APUOP(M_BIHT, RR, 0x12b, "biht", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */
+APUOP(M_BIHF, RR, 0x12a, "bihf", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
+APUOP(M_BIT, RR, 0x129, "bit", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */
+APUOP(M_BIF, RR, 0x128, "bif", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
+APUOPFB(M_BIHTD, RR, 0x12b, 0x20, "bihtd", _A2(A_T,A_A), 00011, BR) /* BIHNF IP<-RA_if(RT) */
+APUOPFB(M_BIHTE, RR, 0x12b, 0x10, "bihte", _A2(A_T,A_A), 00011, BR) /* BIHNF IP<-RA_if(RT) */
+APUOPFB(M_BIHFD, RR, 0x12a, 0x20, "bihfd", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
+APUOPFB(M_BIHFE, RR, 0x12a, 0x10, "bihfe", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */
+APUOPFB(M_BITD, RR, 0x129, 0x20, "bitd", _A2(A_T,A_A), 00011, BR) /* BINF IP<-RA_if(RT) */
+APUOPFB(M_BITE, RR, 0x129, 0x10, "bite", _A2(A_T,A_A), 00011, BR) /* BINF IP<-RA_if(RT) */
+APUOPFB(M_BIFD, RR, 0x128, 0x20, "bifd", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
+APUOPFB(M_BIFE, RR, 0x128, 0x10, "bife", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */
+
+#undef _A0
+#undef _A1
+#undef _A2
+#undef _A3
+#undef _A4
diff --git a/arch/powerpc/xmon/spu-opc.c b/arch/powerpc/xmon/spu-opc.c
new file mode 100644
index 00000000000..7d37597c4bc
--- /dev/null
+++ b/arch/powerpc/xmon/spu-opc.c
@@ -0,0 +1,45 @@
+/* SPU opcode list
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB, GAS, and the GNU binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include "spu.h"
+
+/* This file holds the Spu opcode table */
+
+
+/*
+ Example contents of spu-insn.h
+ id_tag mode mode type opcode mnemonic asmtype dependency FPU L/S? branch? instruction
+ QUAD WORD (0,RC,RB,RA,RT) latency
+ APUOP(M_LQD, 1, 0, RI9, 0x1f8, "lqd", ASM_RI9IDX, 00012, FXU, 1, 0) Load Quadword d-form
+ */
+
+const struct spu_opcode spu_opcodes[] = {
+#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
+ { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT },
+#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
+ { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT },
+#include "spu-insns.h"
+#undef APUOP
+#undef APUOPFB
+};
+
+const int spu_num_opcodes = ARRAY_SIZE(spu_opcodes);
diff --git a/arch/powerpc/xmon/spu.h b/arch/powerpc/xmon/spu.h
new file mode 100644
index 00000000000..c761fc8f35d
--- /dev/null
+++ b/arch/powerpc/xmon/spu.h
@@ -0,0 +1,126 @@
+/* SPU ELF support for BFD.
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB, GAS, and the GNU binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+
+/* These two enums are from rel_apu/common/spu_asm_format.h */
+/* definition of instruction format */
+typedef enum {
+ RRR,
+ RI18,
+ RI16,
+ RI10,
+ RI8,
+ RI7,
+ RR,
+ LBT,
+ LBTI,
+ IDATA,
+ UNKNOWN_IFORMAT
+} spu_iformat;
+
+/* These values describe assembly instruction arguments. They indicate
+ * how to encode, range checking and which relocation to use. */
+typedef enum {
+ A_T, /* register at pos 0 */
+ A_A, /* register at pos 7 */
+ A_B, /* register at pos 14 */
+ A_C, /* register at pos 21 */
+ A_S, /* special purpose register at pos 7 */
+ A_H, /* channel register at pos 7 */
+ A_P, /* parenthesis, this has to separate regs from immediates */
+ A_S3,
+ A_S6,
+ A_S7N,
+ A_S7,
+ A_U7A,
+ A_U7B,
+ A_S10B,
+ A_S10,
+ A_S11,
+ A_S11I,
+ A_S14,
+ A_S16,
+ A_S18,
+ A_R18,
+ A_U3,
+ A_U5,
+ A_U6,
+ A_U7,
+ A_U14,
+ A_X16,
+ A_U18,
+ A_MAX
+} spu_aformat;
+
+enum spu_insns {
+#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
+ TAG,
+#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
+ TAG,
+#include "spu-insns.h"
+#undef APUOP
+#undef APUOPFB
+ M_SPU_MAX
+};
+
+struct spu_opcode
+{
+ spu_iformat insn_type;
+ unsigned int opcode;
+ char *mnemonic;
+ int arg[5];
+};
+
+#define SIGNED_EXTRACT(insn,size,pos) (((int)((insn) << (32-size-pos))) >> (32-size))
+#define UNSIGNED_EXTRACT(insn,size,pos) (((insn) >> pos) & ((1 << size)-1))
+
+#define DECODE_INSN_RT(insn) (insn & 0x7f)
+#define DECODE_INSN_RA(insn) ((insn >> 7) & 0x7f)
+#define DECODE_INSN_RB(insn) ((insn >> 14) & 0x7f)
+#define DECODE_INSN_RC(insn) ((insn >> 21) & 0x7f)
+
+#define DECODE_INSN_I10(insn) SIGNED_EXTRACT(insn,10,14)
+#define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT(insn,10,14)
+
+/* For branching, immediate loads, hbr and lqa/stqa. */
+#define DECODE_INSN_I16(insn) SIGNED_EXTRACT(insn,16,7)
+#define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT(insn,16,7)
+
+/* for stop */
+#define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT(insn,14,0)
+
+/* For ila */
+#define DECODE_INSN_I18(insn) SIGNED_EXTRACT(insn,18,7)
+#define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT(insn,18,7)
+
+/* For rotate and shift and generate control mask */
+#define DECODE_INSN_I7(insn) SIGNED_EXTRACT(insn,7,14)
+#define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT(insn,7,14)
+
+/* For float <-> int conversion */
+#define DECODE_INSN_I8(insn) SIGNED_EXTRACT(insn,8,14)
+#define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT(insn,8,14)
+
+/* For hbr */
+#define DECODE_INSN_I9a(insn) ((SIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
+#define DECODE_INSN_I9b(insn) ((SIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
+#define DECODE_INSN_U9a(insn) ((UNSIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
+#define DECODE_INSN_U9b(insn) ((UNSIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
+
diff --git a/arch/powerpc/xmon/start.c b/arch/powerpc/xmon/start.c
deleted file mode 100644
index 712552c4f24..00000000000
--- a/arch/powerpc/xmon/start.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <asm/machdep.h>
-#include <asm/udbg.h>
-#include "nonstdio.h"
-
-void xmon_map_scc(void)
-{
-}
-
-int xmon_write(void *ptr, int nb)
-{
- return udbg_write(ptr, nb);
-}
-
-int xmon_readchar(void)
-{
- if (udbg_getc)
- return udbg_getc();
- return -1;
-}
-
-int xmon_read_poll(void)
-{
- if (udbg_getc_poll)
- return udbg_getc_poll();
- return -1;
-}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 8adad1444a5..d199bfa2f1f 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2,6 +2,8 @@
* Routines providing a simple monitor for use on the PowerMac.
*
* Copyright (C) 1996-2005 Paul Mackerras.
+ * Copyright (C) 2001 PPC64 Team, IBM Corp
+ * Copyrignt (C) 2006 Michael Ellerman, IBM Corp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -15,10 +17,13 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/kallsyms.h>
+#include <linux/kmsg_dump.h>
#include <linux/cpumask.h>
-#include <linux/module.h>
+#include <linux/export.h>
#include <linux/sysrq.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/bug.h>
#include <asm/ptrace.h>
#include <asm/string.h>
@@ -32,7 +37,13 @@
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/sstep.h>
-#include <asm/bug.h>
+#include <asm/irq_regs.h>
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+#include <asm/setjmp.h>
+#include <asm/reg.h>
+#include <asm/debug.h>
+#include <asm/hw_breakpoint.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -40,18 +51,18 @@
#endif
#include "nonstdio.h"
-
-#define scanhex xmon_scanhex
-#define skipbl xmon_skipbl
+#include "dis-asm.h"
#ifdef CONFIG_SMP
-cpumask_t cpus_in_xmon = CPU_MASK_NONE;
+static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
static unsigned long xmon_taken = 1;
static int xmon_owner;
static int xmon_gate;
+#else
+#define xmon_owner 0
#endif /* CONFIG_SMP */
-static unsigned long in_xmon = 0;
+static unsigned long in_xmon __read_mostly = 0;
static unsigned long adrs;
static int size = 1;
@@ -62,12 +73,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
static long bus_error_jmp[JMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -103,7 +111,7 @@ static int bsesc(void);
static void dump(void);
static void prdump(unsigned long, long);
static int ppc_inst_dump(unsigned long, long, int);
-void print_address(unsigned long);
+static void dump_log_buf(void);
static void backtrace(struct pt_regs *);
static void excprint(struct pt_regs *);
static void prregs(struct pt_regs *);
@@ -143,28 +151,31 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
const char *after);
static const char *getvecname(unsigned long vec);
-int xmon_no_auto_backtrace;
+static int do_spu_cmd(void);
+
+#ifdef CONFIG_44x
+static void dump_tlb_44x(void);
+#endif
+#ifdef CONFIG_PPC_BOOK3E
+static void dump_tlb_book3e(void);
+#endif
-extern int print_insn_powerpc(unsigned long, unsigned long, int);
+static int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
-extern void xmon_save_regs(struct pt_regs *);
-
#ifdef CONFIG_PPC64
#define REG "%.16lx"
-#define REGS_PER_LINE 4
-#define LAST_VOLATILE 13
#else
#define REG "%.8lx"
-#define REGS_PER_LINE 8
-#define LAST_VOLATILE 12
#endif
+#ifdef __LITTLE_ENDIAN__
+#define GETWORD(v) (((v)[3] << 24) + ((v)[2] << 16) + ((v)[1] << 8) + (v)[0])
+#else
#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+#endif
#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
|| ('a' <= (c) && (c) <= 'f') \
@@ -191,6 +202,13 @@ Commands:\n\
di dump instructions\n\
df dump float values\n\
dd dump double values\n\
+ dl dump the kernel log buffer\n"
+#ifdef CONFIG_PPC64
+ "\
+ dp[#] dump paca for current cpu, or cpu #\n\
+ dpa dump paca for all possible cpus\n"
+#endif
+ "\
dr dump stream of raw bytes\n\
e print exception information\n\
f flush cache\n\
@@ -205,16 +223,24 @@ Commands:\n\
mi show information about memory allocation\n\
p call a procedure\n\
r print registers\n\
- s single step\n\
- S print special registers\n\
+ s single step\n"
+#ifdef CONFIG_SPU_BASE
+" ss stop execution on all spus\n\
+ sr restore execution on stopped spus\n\
+ sf # dump spu fields for spu # (in hex)\n\
+ sd # dump spu local store for spu # (in hex)\n\
+ sdi # disassemble spu local store for spu # (in hex)\n"
+#endif
+" S print special registers\n\
t print backtrace\n\
x exit monitor and recover\n\
X exit monitor and dont recover\n"
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
" u dump segment table or SLB\n"
-#endif
-#ifdef CONFIG_PPC_STD_MMU_32
+#elif defined(CONFIG_PPC_STD_MMU_32)
" u dump segment registers\n"
+#elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E)
+" u dump TLB\n"
#endif
" ? help\n"
" zr reboot\n\
@@ -287,16 +313,23 @@ static void get_output_lock(void)
if (xmon_speaker == me)
return;
+
for (;;) {
- if (xmon_speaker == 0) {
- last_speaker = cmpxchg(&xmon_speaker, 0, me);
- if (last_speaker == 0)
- return;
- }
- timeout = 10000000;
+ last_speaker = cmpxchg(&xmon_speaker, 0, me);
+ if (last_speaker == 0)
+ return;
+
+ /*
+ * Wait a full second for the lock, we might be on a slow
+ * console, but check every 100us.
+ */
+ timeout = 10000;
while (xmon_speaker == last_speaker) {
- if (--timeout > 0)
+ if (--timeout > 0) {
+ udelay(100);
continue;
+ }
+
/* hostile takeover */
prev = cmpxchg(&xmon_speaker, last_speaker, me);
if (prev == last_speaker)
@@ -310,23 +343,37 @@ static void release_output_lock(void)
{
xmon_speaker = 0;
}
+
+int cpus_are_in_xmon(void)
+{
+ return !cpumask_empty(&cpus_in_xmon);
+}
#endif
+static inline int unrecoverable_excp(struct pt_regs *regs)
+{
+#if defined(CONFIG_4xx) || defined(CONFIG_PPC_BOOK3E)
+ /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
+ return 0;
+#else
+ return ((regs->msr & MSR_RI) == 0);
+#endif
+}
+
static int xmon_core(struct pt_regs *regs, int fromipi)
{
int cmd = 0;
- unsigned long msr;
struct bpt *bp;
long recurse_jmp[JMP_BUF_LEN];
unsigned long offset;
+ unsigned long flags;
#ifdef CONFIG_SMP
int cpu;
int secondary;
unsigned long timeout;
#endif
- msr = mfmsr();
- mtmsr(msr & ~MSR_EE); /* disable interrupts */
+ local_irq_save(flags);
bp = in_breakpoint_table(regs->nip, &offset);
if (bp != NULL) {
@@ -338,7 +385,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
#ifdef CONFIG_SMP
cpu = smp_processor_id();
- if (cpu_isset(cpu, cpus_in_xmon)) {
+ if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
get_output_lock();
excprint(regs);
printf("cpu 0x%x: Exception %lx %s in xmon, "
@@ -361,28 +408,29 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
}
xmon_fault_jmp[cpu] = recurse_jmp;
- cpu_set(cpu, cpus_in_xmon);
bp = NULL;
- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
+ if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
bp = at_breakpoint(regs->nip);
- if (bp || (regs->msr & MSR_RI) == 0)
+ if (bp || unrecoverable_excp(regs))
fromipi = 0;
if (!fromipi) {
get_output_lock();
excprint(regs);
if (bp) {
- printf("cpu 0x%x stopped at breakpoint 0x%x (",
+ printf("cpu 0x%x stopped at breakpoint 0x%lx (",
cpu, BP_NUM(bp));
xmon_print_symbol(regs->nip, " ", ")\n");
}
- if ((regs->msr & MSR_RI) == 0)
+ if (unrecoverable_excp(regs))
printf("WARNING: exception is not recoverable, "
"can't continue\n");
release_output_lock();
}
+ cpumask_set_cpu(cpu, &cpus_in_xmon);
+
waiting:
secondary = 1;
while (secondary && !xmon_gate) {
@@ -402,10 +450,10 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
xmon_owner = cpu;
mb();
if (ncpus > 1) {
- smp_send_debugger_break(MSG_ALL_BUT_SELF);
+ smp_send_debugger_break();
/* wait for other cpus to come in */
for (timeout = 100000000; timeout != 0; --timeout) {
- if (cpus_weight(cpus_in_xmon) >= ncpus)
+ if (cpumask_weight(&cpus_in_xmon) >= ncpus)
break;
barrier();
}
@@ -449,7 +497,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
}
}
leave:
- cpu_clear(cpu, cpus_in_xmon);
+ cpumask_clear_cpu(cpu, &cpus_in_xmon);
xmon_fault_jmp[cpu] = NULL;
#else
/* UP is simple... */
@@ -465,10 +513,10 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
excprint(regs);
bp = at_breakpoint(regs->nip);
if (bp) {
- printf("Stopped at breakpoint %x (", BP_NUM(bp));
+ printf("Stopped at breakpoint %lx (", BP_NUM(bp));
xmon_print_symbol(regs->nip, " ", ")\n");
}
- if ((regs->msr & MSR_RI) == 0)
+ if (unrecoverable_excp(regs))
printf("WARNING: exception is not recoverable, "
"can't continue\n");
remove_bpts();
@@ -485,7 +533,16 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
in_xmon = 0;
#endif
- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
+#ifdef CONFIG_BOOKE
+ if (regs->msr & MSR_DE) {
+ bp = at_breakpoint(regs->nip);
+ if (bp != NULL) {
+ regs->nip = (unsigned long) &bp->instr[0];
+ atomic_inc(&bp->ref_count);
+ }
+ }
+#else
+ if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
bp = at_breakpoint(regs->nip);
if (bp != NULL) {
int stepped = emulate_step(regs, bp->instr[0]);
@@ -498,12 +555,12 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
}
}
}
-
+#endif
insert_cpu_bpts();
- mtmsr(msr); /* restore interrupt enable */
+ local_irq_restore(flags);
- return cmd != 'X';
+ return cmd != 'X' && cmd != EOF;
}
int xmon(struct pt_regs *excp)
@@ -511,20 +568,20 @@ int xmon(struct pt_regs *excp)
struct pt_regs regs;
if (excp == NULL) {
- xmon_save_regs(&regs);
+ ppc_save_regs(&regs);
excp = &regs;
}
+
return xmon_core(excp, 0);
}
EXPORT_SYMBOL(xmon);
-irqreturn_t
-xmon_irq(int irq, void *d, struct pt_regs *regs)
+irqreturn_t xmon_irq(int irq, void *d)
{
unsigned long flags;
local_irq_save(flags);
printf("Keyboard interrupt\n");
- xmon(regs);
+ xmon(get_irq_regs());
local_irq_restore(flags);
return IRQ_HANDLED;
}
@@ -534,7 +591,7 @@ static int xmon_bpt(struct pt_regs *regs)
struct bpt *bp;
unsigned long offset;
- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
+ if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
return 0;
/* Are we at the trap at bp->instr[1] for some bp? */
@@ -563,9 +620,9 @@ static int xmon_sstep(struct pt_regs *regs)
return 1;
}
-static int xmon_dabr_match(struct pt_regs *regs)
+static int xmon_break_match(struct pt_regs *regs)
{
- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
+ if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
return 0;
if (dabr.enabled == 0)
return 0;
@@ -575,9 +632,9 @@ static int xmon_dabr_match(struct pt_regs *regs)
static int xmon_iabr_match(struct pt_regs *regs)
{
- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
+ if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) != (MSR_IR|MSR_64BIT))
return 0;
- if (iabr == 0)
+ if (iabr == NULL)
return 0;
xmon_core(regs, 0);
return 1;
@@ -586,7 +643,7 @@ static int xmon_iabr_match(struct pt_regs *regs)
static int xmon_ipi(struct pt_regs *regs)
{
#ifdef CONFIG_SMP
- if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
+ if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
xmon_core(regs, 1);
#endif
return 0;
@@ -600,7 +657,7 @@ static int xmon_fault_handler(struct pt_regs *regs)
if (in_xmon && catch_memory_errors)
handle_fault(regs); /* doesn't return */
- if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF)) {
+ if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) {
bp = in_breakpoint_table(regs->nip, &offset);
if (bp != NULL) {
regs->nip = bp->address + offset;
@@ -696,8 +753,14 @@ static void insert_bpts(void)
static void insert_cpu_bpts(void)
{
- if (dabr.enabled)
- set_dabr(dabr.address | (dabr.enabled & 7));
+ struct arch_hw_breakpoint brk;
+
+ if (dabr.enabled) {
+ brk.address = dabr.address;
+ brk.type = (dabr.enabled & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
+ brk.len = 8;
+ __set_breakpoint(&brk);
+ }
if (iabr && cpu_has_feature(CPU_FTR_IABR))
mtspr(SPRN_IABR, iabr->address
| (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -725,7 +788,7 @@ static void remove_bpts(void)
static void remove_cpu_bpts(void)
{
- set_dabr(0);
+ hw_breakpoint_disable();
if (cpu_has_feature(CPU_FTR_IABR))
mtspr(SPRN_IABR, 0);
}
@@ -777,7 +840,7 @@ cmds(struct pt_regs *excp)
memzcan();
break;
case 'i':
- show_mem();
+ show_mem(0);
break;
default:
termch = cmd;
@@ -806,6 +869,8 @@ cmds(struct pt_regs *excp)
cacheflush();
break;
case 's':
+ if (do_spu_cmd() == 0)
+ break;
if (do_step(excp))
return cmd;
break;
@@ -817,7 +882,7 @@ cmds(struct pt_regs *excp)
mdelay(2000);
return cmd;
case '?':
- printf(help_string);
+ xmon_puts(help_string);
break;
case 'b':
bpt_cmds();
@@ -839,22 +904,38 @@ cmds(struct pt_regs *excp)
case 'u':
dump_segments();
break;
+#elif defined(CONFIG_4xx)
+ case 'u':
+ dump_tlb_44x();
+ break;
+#elif defined(CONFIG_PPC_BOOK3E)
+ case 'u':
+ dump_tlb_book3e();
+ break;
#endif
default:
printf("Unrecognized command: ");
- do {
+ do {
if (' ' < cmd && cmd <= '~')
putchar(cmd);
else
printf("\\x%x", cmd);
cmd = inchar();
- } while (cmd != '\n');
+ } while (cmd != '\n');
printf(" (type ? for help)\n");
break;
}
}
}
+#ifdef CONFIG_BOOKE
+static int do_step(struct pt_regs *regs)
+{
+ regs->msr |= MSR_DE;
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+ return 1;
+}
+#else
/*
* Step a single instruction.
* Some instructions we emulate, others we execute with MSR_SE set.
@@ -865,7 +946,7 @@ static int do_step(struct pt_regs *regs)
int stepped;
/* check we are in 64-bit kernel mode, translation enabled */
- if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) {
+ if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) {
if (mread(regs->nip, &instr, 4) == 4) {
stepped = emulate_step(regs, instr);
if (stepped < 0) {
@@ -885,6 +966,7 @@ static int do_step(struct pt_regs *regs)
regs->msr |= MSR_SE;
return 1;
}
+#endif
static void bootcmds(void)
{
@@ -902,32 +984,32 @@ static void bootcmds(void)
static int cpu_cmd(void)
{
#ifdef CONFIG_SMP
- unsigned long cpu;
+ unsigned long cpu, first_cpu, last_cpu;
int timeout;
- int count;
if (!scanhex(&cpu)) {
/* print cpus waiting or in xmon */
printf("cpus stopped:");
- count = 0;
- for (cpu = 0; cpu < NR_CPUS; ++cpu) {
- if (cpu_isset(cpu, cpus_in_xmon)) {
- if (count == 0)
- printf(" %x", cpu);
- ++count;
- } else {
- if (count > 1)
- printf("-%x", cpu - 1);
- count = 0;
+ last_cpu = first_cpu = NR_CPUS;
+ for_each_possible_cpu(cpu) {
+ if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
+ if (cpu == last_cpu + 1) {
+ last_cpu = cpu;
+ } else {
+ if (last_cpu != first_cpu)
+ printf("-0x%lx", last_cpu);
+ last_cpu = first_cpu = cpu;
+ printf(" 0x%lx", cpu);
+ }
}
}
- if (count > 1)
- printf("-%x", NR_CPUS - 1);
+ if (last_cpu != first_cpu)
+ printf("-0x%lx", last_cpu);
printf("\n");
return 0;
}
/* try to switch to cpu specified */
- if (!cpu_isset(cpu, cpus_in_xmon)) {
+ if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
printf("cpu 0x%x isn't in xmon\n", cpu);
return 0;
}
@@ -942,7 +1024,7 @@ static int cpu_cmd(void)
/* take control back */
mb();
xmon_owner = smp_processor_id();
- printf("cpu %u didn't take control\n", cpu);
+ printf("cpu 0x%x didn't take control\n", cpu);
return 0;
}
barrier();
@@ -1004,7 +1086,7 @@ csum(void)
fcs = 0xffff;
for (i = 0; i < ncsum; ++i) {
if (mread(adrs+i, &v, 1) == 0) {
- printf("csum stopped at %x\n", adrs+i);
+ printf("csum stopped at "REG"\n", adrs+i);
break;
}
fcs = FCS(fcs, v);
@@ -1036,7 +1118,7 @@ static long check_bp_loc(unsigned long addr)
return 1;
}
-static char *breakpoint_help_string =
+static char *breakpoint_help_string =
"Breakpoint command usage:\n"
"b show breakpoints\n"
"b <addr> [cnt] set breakpoint at given instr addr\n"
@@ -1075,7 +1157,7 @@ bpt_cmds(void)
printf(badaddr);
break;
}
- dabr.address &= ~7;
+ dabr.address &= ~HW_BRK_TYPE_DABR;
dabr.enabled = mode | BP_DABR;
}
break;
@@ -1119,20 +1201,20 @@ bpt_cmds(void)
} else {
/* assume a breakpoint address */
bp = at_breakpoint(a);
- if (bp == 0) {
- printf("No breakpoint at %x\n", a);
+ if (bp == NULL) {
+ printf("No breakpoint at %lx\n", a);
break;
}
}
- printf("Cleared breakpoint %x (", BP_NUM(bp));
+ printf("Cleared breakpoint %lx (", BP_NUM(bp));
xmon_print_symbol(bp->address, " ", ")\n");
bp->enabled = 0;
break;
default:
termch = cmd;
- cmd = skipbl();
+ cmd = skipbl();
if (cmd == '?') {
printf(breakpoint_help_string);
break;
@@ -1186,11 +1268,18 @@ const char *getvecname(unsigned long vec)
case 0x700: ret = "(Program Check)"; break;
case 0x800: ret = "(FPU Unavailable)"; break;
case 0x900: ret = "(Decrementer)"; break;
+ case 0x980: ret = "(Hypervisor Decrementer)"; break;
+ case 0xa00: ret = "(Doorbell)"; break;
case 0xc00: ret = "(System Call)"; break;
case 0xd00: ret = "(Single Step)"; break;
+ case 0xe40: ret = "(Emulation Assist)"; break;
+ case 0xe60: ret = "(HMI)"; break;
+ case 0xe80: ret = "(Hypervisor Doorbell)"; break;
case 0xf00: ret = "(Performance Monitor)"; break;
case 0xf20: ret = "(Altivec Unavailable)"; break;
case 0x1300: ret = "(Instruction Breakpoint)"; break;
+ case 0x1500: ret = "(Denormalisation)"; break;
+ case 0x1700: ret = "(Altivec Assist)"; break;
default: ret = "";
}
return ret;
@@ -1201,7 +1290,6 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
{
unsigned long size, offset;
const char *name;
- char *modname;
*startp = *endp = 0;
if (pc == 0)
@@ -1209,7 +1297,7 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
if (setjmp(bus_error_jmp) == 0) {
catch_memory_errors = 1;
sync();
- name = kallsyms_lookup(pc, &size, &offset, &modname, tmpstr);
+ name = kallsyms_lookup(pc, &size, &offset, NULL, tmpstr);
if (name != NULL) {
*startp = pc - offset;
*endp = pc - offset + size;
@@ -1219,30 +1307,19 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
catch_memory_errors = 0;
}
-static int xmon_depth_to_print = 64;
-
-#ifdef CONFIG_PPC64
-#define LRSAVE_OFFSET 0x10
-#define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
-#define MARKER_OFFSET 0x60
-#define REGS_OFFSET 0x70
-#else
-#define LRSAVE_OFFSET 4
-#define REG_FRAME_MARKER 0x72656773
-#define MARKER_OFFSET 8
-#define REGS_OFFSET 16
-#endif
+#define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
+#define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
static void xmon_show_stack(unsigned long sp, unsigned long lr,
unsigned long pc)
{
+ int max_to_print = 64;
unsigned long ip;
unsigned long newsp;
unsigned long marker;
- int count = 0;
struct pt_regs regs;
- do {
+ while (max_to_print--) {
if (sp < PAGE_OFFSET) {
if (sp != 0)
printf("SP (%lx) is in userspace\n", sp);
@@ -1295,14 +1372,14 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
/* Look for "regshere" marker to see if this is
an exception frame. */
if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
- && marker == REG_FRAME_MARKER) {
- if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
+ && marker == STACK_FRAME_REGS_MARKER) {
+ if (mread(sp + STACK_FRAME_OVERHEAD, &regs, sizeof(regs))
!= sizeof(regs)) {
printf("Couldn't read registers at %lx\n",
- sp + REGS_OFFSET);
+ sp + STACK_FRAME_OVERHEAD);
break;
}
- printf("--- Exception: %lx %s at ", regs.trap,
+ printf("--- Exception: %lx %s at ", regs.trap,
getvecname(TRAP(&regs)));
pc = regs.nip;
lr = regs.link;
@@ -1313,7 +1390,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
break;
sp = newsp;
- } while (count++ < xmon_depth_to_print);
+ }
}
static void backtrace(struct pt_regs *excp)
@@ -1329,7 +1406,8 @@ static void backtrace(struct pt_regs *excp)
static void print_bug_trap(struct pt_regs *regs)
{
- struct bug_entry *bug;
+#ifdef CONFIG_BUG
+ const struct bug_entry *bug;
unsigned long addr;
if (regs->msr & MSR_PR)
@@ -1340,14 +1418,19 @@ static void print_bug_trap(struct pt_regs *regs)
bug = find_bug(regs->nip);
if (bug == NULL)
return;
- if (bug->line & BUG_WARNING_TRAP)
+ if (is_warning_bug(bug))
return;
- printf("kernel BUG in %s at %s:%d!\n",
- bug->function, bug->file, (unsigned int)bug->line);
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+ printf("kernel BUG at %s:%u!\n",
+ bug->file, bug->line);
+#else
+ printf("kernel BUG at %p!\n", (void *)bug->bug_addr);
+#endif
+#endif /* CONFIG_BUG */
}
-void excprint(struct pt_regs *fp)
+static void excprint(struct pt_regs *fp)
{
unsigned long trap;
@@ -1366,7 +1449,7 @@ void excprint(struct pt_regs *fp)
printf(" sp: %lx\n", fp->gpr[1]);
printf(" msr: %lx\n", fp->msr);
- if (trap == 0x300 || trap == 0x380 || trap == 0x600) {
+ if (trap == 0x300 || trap == 0x380 || trap == 0x600 || trap == 0x200) {
printf(" dar: %lx\n", fp->dar);
if (trap != 0x380)
printf(" dsisr: %lx\n", fp->dsisr);
@@ -1374,7 +1457,8 @@ void excprint(struct pt_regs *fp)
printf(" current = 0x%lx\n", current);
#ifdef CONFIG_PPC64
- printf(" paca = 0x%lx\n", get_paca());
+ printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
+ local_paca, local_paca->soft_enabled, local_paca->irq_happened);
#endif
if (current) {
printf(" pid = %ld, comm = %s\n",
@@ -1385,7 +1469,7 @@ void excprint(struct pt_regs *fp)
print_bug_trap(fp);
}
-void prregs(struct pt_regs *fp)
+static void prregs(struct pt_regs *fp)
{
int n, trap;
unsigned long base;
@@ -1430,6 +1514,10 @@ void prregs(struct pt_regs *fp)
#endif
printf("pc = ");
xmon_print_symbol(fp->nip, " ", "\n");
+ if (TRAP(fp) != 0xc00 && cpu_has_feature(CPU_FTR_CFAR)) {
+ printf("cfar= ");
+ xmon_print_symbol(fp->orig_gpr3, " ", "\n");
+ }
printf("lr = ");
xmon_print_symbol(fp->link, " ", "\n");
printf("msr = "REG" cr = %.8lx\n", fp->msr, fp->ccr);
@@ -1440,7 +1528,7 @@ void prregs(struct pt_regs *fp)
printf("dar = "REG" dsisr = %.8lx\n", fp->dar, fp->dsisr);
}
-void cacheflush(void)
+static void cacheflush(void)
{
int cmd;
unsigned long nflush;
@@ -1472,7 +1560,7 @@ void cacheflush(void)
catch_memory_errors = 0;
}
-unsigned long
+static unsigned long
read_spr(int n)
{
unsigned int instrs[2];
@@ -1510,7 +1598,7 @@ read_spr(int n)
return ret;
}
-void
+static void
write_spr(int n, unsigned long val)
{
unsigned int instrs[2];
@@ -1548,52 +1636,25 @@ static unsigned long regno;
extern char exc_prolog;
extern char dec_exc;
-void super_regs(void)
+static void super_regs(void)
{
int cmd;
unsigned long val;
-#ifdef CONFIG_PPC_ISERIES
- struct paca_struct *ptrPaca = NULL;
- struct lppaca *ptrLpPaca = NULL;
- struct ItLpRegSave *ptrLpRegSave = NULL;
-#endif
cmd = skipbl();
if (cmd == '\n') {
- unsigned long sp, toc;
+ unsigned long sp, toc;
asm("mr %0,1" : "=r" (sp) :);
asm("mr %0,2" : "=r" (toc) :);
printf("msr = "REG" sprg0= "REG"\n",
mfmsr(), mfspr(SPRN_SPRG0));
printf("pvr = "REG" sprg1= "REG"\n",
- mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
+ mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
printf("dec = "REG" sprg2= "REG"\n",
mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
-#ifdef CONFIG_PPC_ISERIES
- // Dump out relevant Paca data areas.
- printf("Paca: \n");
- ptrPaca = get_paca();
-
- printf(" Local Processor Control Area (LpPaca): \n");
- ptrLpPaca = ptrPaca->lppaca_ptr;
- printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
- ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
- printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
- ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
- printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
-
- printf(" Local Processor Register Save Area (LpRegSave): \n");
- ptrLpRegSave = ptrPaca->reg_save_ptr;
- printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
- ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
- printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
- ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
- printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
- ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
-#endif
return;
}
@@ -1615,7 +1676,7 @@ void super_regs(void)
/*
* Stuff for reading and writing memory safely
*/
-int
+static int
mread(unsigned long adrs, void *buf, int size)
{
volatile int n;
@@ -1652,7 +1713,7 @@ mread(unsigned long adrs, void *buf, int size)
return n;
}
-int
+static int
mwrite(unsigned long adrs, void *buf, int size)
{
volatile int n;
@@ -1685,7 +1746,7 @@ mwrite(unsigned long adrs, void *buf, int size)
__delay(200);
n = size;
} else {
- printf("*** Error writing address %x\n", adrs + n);
+ printf("*** Error writing address "REG"\n", adrs + n);
}
catch_memory_errors = 0;
return n;
@@ -1717,7 +1778,7 @@ static int handle_fault(struct pt_regs *regs)
#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
-void
+static void
byterev(unsigned char *val, int size)
{
int t;
@@ -1742,7 +1803,7 @@ byterev(unsigned char *val, int size)
static int brev;
static int mnoread;
-static char *memex_help_string =
+static char *memex_help_string =
"Memory examine command usage:\n"
"m [addr] [flags] examine/change memory\n"
" addr is optional. will start where left off.\n"
@@ -1757,7 +1818,7 @@ static char *memex_help_string =
"NOTE: flags are saved as defaults\n"
"";
-static char *memex_subcmd_help_string =
+static char *memex_subcmd_help_string =
"Memory examine subcommands:\n"
" hexval write this val to current location\n"
" 'string' write chars from string to this location\n"
@@ -1779,7 +1840,7 @@ static char *memex_subcmd_help_string =
" x exit this mode\n"
"";
-void
+static void
memex(void)
{
int cmd, inc, i, nslash;
@@ -1930,7 +1991,7 @@ memex(void)
}
}
-int
+static int
bsesc(void)
{
int c;
@@ -1967,15 +2028,116 @@ static void xmon_rawdump (unsigned long adrs, long ndump)
printf("\n");
}
+#ifdef CONFIG_PPC64
+static void dump_one_paca(int cpu)
+{
+ struct paca_struct *p;
+
+ if (setjmp(bus_error_jmp) != 0) {
+ printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
+ return;
+ }
+
+ catch_memory_errors = 1;
+ sync();
+
+ p = &paca[cpu];
+
+ printf("paca for cpu 0x%x @ %p:\n", cpu, p);
+
+ printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
+ printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
+ printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
+
+#define DUMP(paca, name, format) \
+ printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
+ offsetof(struct paca_struct, name));
+
+ DUMP(p, lock_token, "x");
+ DUMP(p, paca_index, "x");
+ DUMP(p, kernel_toc, "lx");
+ DUMP(p, kernelbase, "lx");
+ DUMP(p, kernel_msr, "lx");
+#ifdef CONFIG_PPC_STD_MMU_64
+ DUMP(p, stab_real, "lx");
+ DUMP(p, stab_addr, "lx");
+#endif
+ DUMP(p, emergency_sp, "p");
+#ifdef CONFIG_PPC_BOOK3S_64
+ DUMP(p, mc_emergency_sp, "p");
+ DUMP(p, in_mce, "x");
+#endif
+ DUMP(p, data_offset, "lx");
+ DUMP(p, hw_cpu_id, "x");
+ DUMP(p, cpu_start, "x");
+ DUMP(p, kexec_state, "x");
+ DUMP(p, __current, "p");
+ DUMP(p, kstack, "lx");
+ DUMP(p, stab_rr, "lx");
+ DUMP(p, saved_r1, "lx");
+ DUMP(p, trap_save, "x");
+ DUMP(p, soft_enabled, "x");
+ DUMP(p, irq_happened, "x");
+ DUMP(p, io_sync, "x");
+ DUMP(p, irq_work_pending, "x");
+ DUMP(p, nap_state_lost, "x");
+
+#undef DUMP
+
+ catch_memory_errors = 0;
+ sync();
+}
+
+static void dump_all_pacas(void)
+{
+ int cpu;
+
+ if (num_possible_cpus() == 0) {
+ printf("No possible cpus, use 'dp #' to dump individual cpus\n");
+ return;
+ }
+
+ for_each_possible_cpu(cpu)
+ dump_one_paca(cpu);
+}
+
+static void dump_pacas(void)
+{
+ unsigned long num;
+ int c;
+
+ c = inchar();
+ if (c == 'a') {
+ dump_all_pacas();
+ return;
+ }
+
+ termch = c; /* Put c back, it wasn't 'a' */
+
+ if (scanhex(&num))
+ dump_one_paca(num);
+ else
+ dump_one_paca(xmon_owner);
+}
+#endif
+
#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
|| ('a' <= (c) && (c) <= 'f') \
|| ('A' <= (c) && (c) <= 'F'))
-void
+static void
dump(void)
{
int c;
c = inchar();
+
+#ifdef CONFIG_PPC64
+ if (c == 'p') {
+ dump_pacas();
+ return;
+ }
+#endif
+
if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
termch = c;
scanhex((void *)&adrs);
@@ -1989,6 +2151,8 @@ dump(void)
nidump = MAX_DUMP;
adrs += ppc_inst_dump(adrs, nidump, 1);
last_cmd = "di\n";
+ } else if (c == 'l') {
+ dump_log_buf();
} else if (c == 'r') {
scanhex(&ndump);
if (ndump == 0)
@@ -2008,7 +2172,7 @@ dump(void)
}
}
-void
+static void
prdump(unsigned long adrs, long ndump)
{
long n, m, c, r, nr;
@@ -2021,7 +2185,7 @@ prdump(unsigned long adrs, long ndump)
nr = mread(adrs, temp, r);
adrs += nr;
for (m = 0; m < r; ++m) {
- if ((m & (sizeof(long) - 1)) == 0 && m > 0)
+ if ((m & (sizeof(long) - 1)) == 0 && m > 0)
putchar(' ');
if (m < nr)
printf("%.2x", temp[m]);
@@ -2029,7 +2193,7 @@ prdump(unsigned long adrs, long ndump)
printf("%s", fault_chars[fault_type]);
}
for (; m < 16; ++m) {
- if ((m & (sizeof(long) - 1)) == 0)
+ if ((m & (sizeof(long) - 1)) == 0)
putchar(' ');
printf(" ");
}
@@ -2050,8 +2214,11 @@ prdump(unsigned long adrs, long ndump)
}
}
-int
-ppc_inst_dump(unsigned long adr, long count, int praddr)
+typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
+
+static int
+generic_inst_dump(unsigned long adr, long count, int praddr,
+ instruction_dump_func dump_func)
{
int nr, dotted;
unsigned long first_adr;
@@ -2081,18 +2248,50 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
if (praddr)
printf(REG" %.8x", adr, inst);
printf("\t");
- print_insn_powerpc(inst, adr, 0); /* always returns 4 */
+ dump_func(inst, adr);
printf("\n");
}
return adr - first_adr;
}
+static int
+ppc_inst_dump(unsigned long adr, long count, int praddr)
+{
+ return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
+}
+
void
print_address(unsigned long addr)
{
xmon_print_symbol(addr, "\t# ", "");
}
+void
+dump_log_buf(void)
+{
+ struct kmsg_dumper dumper = { .active = 1 };
+ unsigned char buf[128];
+ size_t len;
+
+ if (setjmp(bus_error_jmp) != 0) {
+ printf("Error dumping printk buffer!\n");
+ return;
+ }
+
+ catch_memory_errors = 1;
+ sync();
+
+ kmsg_dump_rewind_nolock(&dumper);
+ while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
+ buf[len] = '\0';
+ printf("%s", buf);
+ }
+
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ catch_memory_errors = 0;
+}
/*
* Memory operations - move, set, print differences
@@ -2103,7 +2302,7 @@ static unsigned long mval; /* byte value to set memory to */
static unsigned long mcount; /* # bytes to affect */
static unsigned long mdiffs; /* max # differences to print */
-void
+static void
memops(int cmd)
{
scanhex((void *)&mdest);
@@ -2129,7 +2328,7 @@ memops(int cmd)
}
}
-void
+static void
memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
{
unsigned n, prt;
@@ -2147,7 +2346,7 @@ memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
static unsigned mend;
static unsigned mask;
-void
+static void
memlocate(void)
{
unsigned a, n;
@@ -2180,7 +2379,7 @@ memlocate(void)
static unsigned long mskip = 0x1000;
static unsigned long mlim = 0xffffffff;
-void
+static void
memzcan(void)
{
unsigned char v;
@@ -2207,7 +2406,7 @@ memzcan(void)
printf("%.8x\n", a - mskip);
}
-void proccall(void)
+static void proccall(void)
{
unsigned long args[8];
unsigned long ret;
@@ -2236,7 +2435,7 @@ void proccall(void)
ret = func(args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7]);
sync();
- printf("return value is %x\n", ret);
+ printf("return value is 0x%lx\n", ret);
} else {
printf("*** %x exception occurred\n", fault_except);
}
@@ -2365,7 +2564,7 @@ scanhex(unsigned long *vp)
return 1;
}
-void
+static void
scannl(void)
{
int c;
@@ -2376,7 +2575,7 @@ scannl(void)
c = inchar();
}
-int hexdigit(int c)
+static int hexdigit(int c)
{
if( '0' <= c && c <= '9' )
return c - '0';
@@ -2407,13 +2606,13 @@ getstring(char *s, int size)
static char line[256];
static char *lineptr;
-void
+static void
flush_input(void)
{
lineptr = NULL;
}
-int
+static int
inchar(void)
{
if (lineptr == NULL || *lineptr == 0) {
@@ -2426,7 +2625,7 @@ inchar(void)
return *lineptr++;
}
-void
+static void
take_input(char *str)
{
lineptr = str;
@@ -2494,29 +2693,46 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
printf("%s", after);
}
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S_64
static void dump_slb(void)
{
int i;
- unsigned long tmp;
-
- printf("SLB contents of cpu %x\n", smp_processor_id());
-
- for (i = 0; i < SLB_NUM_ENTRIES; i++) {
- asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i));
- printf("%02d %016lx ", i, tmp);
-
- asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i));
- printf("%016lx\n", tmp);
+ unsigned long esid,vsid,valid;
+ unsigned long llp;
+
+ printf("SLB contents of cpu 0x%x\n", smp_processor_id());
+
+ for (i = 0; i < mmu_slb_size; i++) {
+ asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i));
+ asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i));
+ valid = (esid & SLB_ESID_V);
+ if (valid | esid | vsid) {
+ printf("%02d %016lx %016lx", i, esid, vsid);
+ if (valid) {
+ llp = vsid & SLB_VSID_LLP;
+ if (vsid & SLB_VSID_B_1T) {
+ printf(" 1T ESID=%9lx VSID=%13lx LLP:%3lx \n",
+ GET_ESID_1T(esid),
+ (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
+ llp);
+ } else {
+ printf(" 256M ESID=%9lx VSID=%13lx LLP:%3lx \n",
+ GET_ESID(esid),
+ (vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
+ llp);
+ }
+ } else
+ printf("\n");
+ }
}
}
static void dump_stab(void)
{
int i;
- unsigned long *tmp = (unsigned long *)get_paca()->stab_addr;
+ unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
- printf("Segment table contents of cpu %x\n", smp_processor_id());
+ printf("Segment table contents of cpu 0x%x\n", smp_processor_id());
for (i = 0; i < PAGE_SIZE/16; i++) {
unsigned long a, b;
@@ -2533,7 +2749,7 @@ static void dump_stab(void)
void dump_segments(void)
{
- if (cpu_has_feature(CPU_FTR_SLB))
+ if (mmu_has_feature(MMU_FTR_SLB))
dump_slb();
else
dump_stab();
@@ -2552,7 +2768,178 @@ void dump_segments(void)
}
#endif
-void xmon_init(int enable)
+#ifdef CONFIG_44x
+static void dump_tlb_44x(void)
+{
+ int i;
+
+ for (i = 0; i < PPC44x_TLB_SIZE; i++) {
+ unsigned long w0,w1,w2;
+ asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i));
+ asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i));
+ asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i));
+ printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
+ if (w0 & PPC44x_TLB_VALID) {
+ printf("V %08x -> %01x%08x %c%c%c%c%c",
+ w0 & PPC44x_TLB_EPN_MASK,
+ w1 & PPC44x_TLB_ERPN_MASK,
+ w1 & PPC44x_TLB_RPN_MASK,
+ (w2 & PPC44x_TLB_W) ? 'W' : 'w',
+ (w2 & PPC44x_TLB_I) ? 'I' : 'i',
+ (w2 & PPC44x_TLB_M) ? 'M' : 'm',
+ (w2 & PPC44x_TLB_G) ? 'G' : 'g',
+ (w2 & PPC44x_TLB_E) ? 'E' : 'e');
+ }
+ printf("\n");
+ }
+}
+#endif /* CONFIG_44x */
+
+#ifdef CONFIG_PPC_BOOK3E
+static void dump_tlb_book3e(void)
+{
+ u32 mmucfg, pidmask, lpidmask;
+ u64 ramask;
+ int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
+ int mmu_version;
+ static const char *pgsz_names[] = {
+ " 1K",
+ " 2K",
+ " 4K",
+ " 8K",
+ " 16K",
+ " 32K",
+ " 64K",
+ "128K",
+ "256K",
+ "512K",
+ " 1M",
+ " 2M",
+ " 4M",
+ " 8M",
+ " 16M",
+ " 32M",
+ " 64M",
+ "128M",
+ "256M",
+ "512M",
+ " 1G",
+ " 2G",
+ " 4G",
+ " 8G",
+ " 16G",
+ " 32G",
+ " 64G",
+ "128G",
+ "256G",
+ "512G",
+ " 1T",
+ " 2T",
+ };
+
+ /* Gather some infos about the MMU */
+ mmucfg = mfspr(SPRN_MMUCFG);
+ mmu_version = (mmucfg & 3) + 1;
+ ntlbs = ((mmucfg >> 2) & 3) + 1;
+ pidsz = ((mmucfg >> 6) & 0x1f) + 1;
+ lpidsz = (mmucfg >> 24) & 0xf;
+ rasz = (mmucfg >> 16) & 0x7f;
+ if ((mmu_version > 1) && (mmucfg & 0x10000))
+ lrat = 1;
+ printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
+ mmu_version, ntlbs, pidsz, lpidsz, rasz);
+ pidmask = (1ul << pidsz) - 1;
+ lpidmask = (1ul << lpidsz) - 1;
+ ramask = (1ull << rasz) - 1;
+
+ for (tlb = 0; tlb < ntlbs; tlb++) {
+ u32 tlbcfg;
+ int nent, assoc, new_cc = 1;
+ printf("TLB %d:\n------\n", tlb);
+ switch(tlb) {
+ case 0:
+ tlbcfg = mfspr(SPRN_TLB0CFG);
+ break;
+ case 1:
+ tlbcfg = mfspr(SPRN_TLB1CFG);
+ break;
+ case 2:
+ tlbcfg = mfspr(SPRN_TLB2CFG);
+ break;
+ case 3:
+ tlbcfg = mfspr(SPRN_TLB3CFG);
+ break;
+ default:
+ printf("Unsupported TLB number !\n");
+ continue;
+ }
+ nent = tlbcfg & 0xfff;
+ assoc = (tlbcfg >> 24) & 0xff;
+ for (i = 0; i < nent; i++) {
+ u32 mas0 = MAS0_TLBSEL(tlb);
+ u32 mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K);
+ u64 mas2 = 0;
+ u64 mas7_mas3;
+ int esel = i, cc = i;
+
+ if (assoc != 0) {
+ cc = i / assoc;
+ esel = i % assoc;
+ mas2 = cc * 0x1000;
+ }
+
+ mas0 |= MAS0_ESEL(esel);
+ mtspr(SPRN_MAS0, mas0);
+ mtspr(SPRN_MAS1, mas1);
+ mtspr(SPRN_MAS2, mas2);
+ asm volatile("tlbre 0,0,0" : : : "memory");
+ mas1 = mfspr(SPRN_MAS1);
+ mas2 = mfspr(SPRN_MAS2);
+ mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
+ if (assoc && (i % assoc) == 0)
+ new_cc = 1;
+ if (!(mas1 & MAS1_VALID))
+ continue;
+ if (assoc == 0)
+ printf("%04x- ", i);
+ else if (new_cc)
+ printf("%04x-%c", cc, 'A' + esel);
+ else
+ printf(" |%c", 'A' + esel);
+ new_cc = 0;
+ printf(" %016llx %04x %s %c%c AS%c",
+ mas2 & ~0x3ffull,
+ (mas1 >> 16) & 0x3fff,
+ pgsz_names[(mas1 >> 7) & 0x1f],
+ mas1 & MAS1_IND ? 'I' : ' ',
+ mas1 & MAS1_IPROT ? 'P' : ' ',
+ mas1 & MAS1_TS ? '1' : '0');
+ printf(" %c%c%c%c%c%c%c",
+ mas2 & MAS2_X0 ? 'a' : ' ',
+ mas2 & MAS2_X1 ? 'v' : ' ',
+ mas2 & MAS2_W ? 'w' : ' ',
+ mas2 & MAS2_I ? 'i' : ' ',
+ mas2 & MAS2_M ? 'm' : ' ',
+ mas2 & MAS2_G ? 'g' : ' ',
+ mas2 & MAS2_E ? 'e' : ' ');
+ printf(" %016llx", mas7_mas3 & ramask & ~0x7ffull);
+ if (mas1 & MAS1_IND)
+ printf(" %s\n",
+ pgsz_names[(mas7_mas3 >> 1) & 0x1f]);
+ else
+ printf(" U%c%c%c S%c%c%c\n",
+ mas7_mas3 & MAS3_UX ? 'x' : ' ',
+ mas7_mas3 & MAS3_UW ? 'w' : ' ',
+ mas7_mas3 & MAS3_UR ? 'r' : ' ',
+ mas7_mas3 & MAS3_SX ? 'x' : ' ',
+ mas7_mas3 & MAS3_SW ? 'w' : ' ',
+ mas7_mas3 & MAS3_SR ? 'r' : ' ');
+ }
+ }
+}
+#endif /* CONFIG_PPC_BOOK3E */
+
+static void xmon_init(int enable)
{
if (enable) {
__debugger = xmon;
@@ -2560,7 +2947,7 @@ void xmon_init(int enable)
__debugger_bpt = xmon_bpt;
__debugger_sstep = xmon_sstep;
__debugger_iabr_match = xmon_iabr_match;
- __debugger_dabr_match = xmon_dabr_match;
+ __debugger_break_match = xmon_break_match;
__debugger_fault_handler = xmon_fault_handler;
} else {
__debugger = NULL;
@@ -2568,25 +2955,22 @@ void xmon_init(int enable)
__debugger_bpt = NULL;
__debugger_sstep = NULL;
__debugger_iabr_match = NULL;
- __debugger_dabr_match = NULL;
+ __debugger_break_match = NULL;
__debugger_fault_handler = NULL;
}
- xmon_map_scc();
}
#ifdef CONFIG_MAGIC_SYSRQ
-static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void sysrq_handle_xmon(int key)
{
/* ensure xmon is enabled */
xmon_init(1);
- debugger(pt_regs);
+ debugger(get_irq_regs());
}
-static struct sysrq_key_op sysrq_xmon_op =
-{
+static struct sysrq_key_op sysrq_xmon_op = {
.handler = sysrq_handle_xmon,
- .help_msg = "Xmon",
+ .help_msg = "xmon(x)",
.action_msg = "Entering xmon",
};
@@ -2597,3 +2981,294 @@ static int __init setup_xmon_sysrq(void)
}
__initcall(setup_xmon_sysrq);
#endif /* CONFIG_MAGIC_SYSRQ */
+
+static int __initdata xmon_early, xmon_off;
+
+static int __init early_parse_xmon(char *p)
+{
+ if (!p || strncmp(p, "early", 5) == 0) {
+ /* just "xmon" is equivalent to "xmon=early" */
+ xmon_init(1);
+ xmon_early = 1;
+ } else if (strncmp(p, "on", 2) == 0)
+ xmon_init(1);
+ else if (strncmp(p, "off", 3) == 0)
+ xmon_off = 1;
+ else if (strncmp(p, "nobt", 4) == 0)
+ xmon_no_auto_backtrace = 1;
+ else
+ return 1;
+
+ return 0;
+}
+early_param("xmon", early_parse_xmon);
+
+void __init xmon_setup(void)
+{
+#ifdef CONFIG_XMON_DEFAULT
+ if (!xmon_off)
+ xmon_init(1);
+#endif
+ if (xmon_early)
+ debugger(NULL);
+}
+
+#ifdef CONFIG_SPU_BASE
+
+struct spu_info {
+ struct spu *spu;
+ u64 saved_mfc_sr1_RW;
+ u32 saved_spu_runcntl_RW;
+ unsigned long dump_addr;
+ u8 stopped_ok;
+};
+
+#define XMON_NUM_SPUS 16 /* Enough for current hardware */
+
+static struct spu_info spu_info[XMON_NUM_SPUS];
+
+void xmon_register_spus(struct list_head *list)
+{
+ struct spu *spu;
+
+ list_for_each_entry(spu, list, full_list) {
+ if (spu->number >= XMON_NUM_SPUS) {
+ WARN_ON(1);
+ continue;
+ }
+
+ spu_info[spu->number].spu = spu;
+ spu_info[spu->number].stopped_ok = 0;
+ spu_info[spu->number].dump_addr = (unsigned long)
+ spu_info[spu->number].spu->local_store;
+ }
+}
+
+static void stop_spus(void)
+{
+ struct spu *spu;
+ int i;
+ u64 tmp;
+
+ for (i = 0; i < XMON_NUM_SPUS; i++) {
+ if (!spu_info[i].spu)
+ continue;
+
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+
+ spu = spu_info[i].spu;
+
+ spu_info[i].saved_spu_runcntl_RW =
+ in_be32(&spu->problem->spu_runcntl_RW);
+
+ tmp = spu_mfc_sr1_get(spu);
+ spu_info[i].saved_mfc_sr1_RW = tmp;
+
+ tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
+ spu_mfc_sr1_set(spu, tmp);
+
+ sync();
+ __delay(200);
+
+ spu_info[i].stopped_ok = 1;
+
+ printf("Stopped spu %.2d (was %s)\n", i,
+ spu_info[i].saved_spu_runcntl_RW ?
+ "running" : "stopped");
+ } else {
+ catch_memory_errors = 0;
+ printf("*** Error stopping spu %.2d\n", i);
+ }
+ catch_memory_errors = 0;
+ }
+}
+
+static void restart_spus(void)
+{
+ struct spu *spu;
+ int i;
+
+ for (i = 0; i < XMON_NUM_SPUS; i++) {
+ if (!spu_info[i].spu)
+ continue;
+
+ if (!spu_info[i].stopped_ok) {
+ printf("*** Error, spu %d was not successfully stopped"
+ ", not restarting\n", i);
+ continue;
+ }
+
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+
+ spu = spu_info[i].spu;
+ spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
+ out_be32(&spu->problem->spu_runcntl_RW,
+ spu_info[i].saved_spu_runcntl_RW);
+
+ sync();
+ __delay(200);
+
+ printf("Restarted spu %.2d\n", i);
+ } else {
+ catch_memory_errors = 0;
+ printf("*** Error restarting spu %.2d\n", i);
+ }
+ catch_memory_errors = 0;
+ }
+}
+
+#define DUMP_WIDTH 23
+#define DUMP_VALUE(format, field, value) \
+do { \
+ if (setjmp(bus_error_jmp) == 0) { \
+ catch_memory_errors = 1; \
+ sync(); \
+ printf(" %-*s = "format"\n", DUMP_WIDTH, \
+ #field, value); \
+ sync(); \
+ __delay(200); \
+ } else { \
+ catch_memory_errors = 0; \
+ printf(" %-*s = *** Error reading field.\n", \
+ DUMP_WIDTH, #field); \
+ } \
+ catch_memory_errors = 0; \
+} while (0)
+
+#define DUMP_FIELD(obj, format, field) \
+ DUMP_VALUE(format, field, obj->field)
+
+static void dump_spu_fields(struct spu *spu)
+{
+ printf("Dumping spu fields at address %p:\n", spu);
+
+ DUMP_FIELD(spu, "0x%x", number);
+ DUMP_FIELD(spu, "%s", name);
+ DUMP_FIELD(spu, "0x%lx", local_store_phys);
+ DUMP_FIELD(spu, "0x%p", local_store);
+ DUMP_FIELD(spu, "0x%lx", ls_size);
+ DUMP_FIELD(spu, "0x%x", node);
+ DUMP_FIELD(spu, "0x%lx", flags);
+ DUMP_FIELD(spu, "%d", class_0_pending);
+ DUMP_FIELD(spu, "0x%lx", class_0_dar);
+ DUMP_FIELD(spu, "0x%lx", class_1_dar);
+ DUMP_FIELD(spu, "0x%lx", class_1_dsisr);
+ DUMP_FIELD(spu, "0x%lx", irqs[0]);
+ DUMP_FIELD(spu, "0x%lx", irqs[1]);
+ DUMP_FIELD(spu, "0x%lx", irqs[2]);
+ DUMP_FIELD(spu, "0x%x", slb_replace);
+ DUMP_FIELD(spu, "%d", pid);
+ DUMP_FIELD(spu, "0x%p", mm);
+ DUMP_FIELD(spu, "0x%p", ctx);
+ DUMP_FIELD(spu, "0x%p", rq);
+ DUMP_FIELD(spu, "0x%p", timestamp);
+ DUMP_FIELD(spu, "0x%lx", problem_phys);
+ DUMP_FIELD(spu, "0x%p", problem);
+ DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
+ in_be32(&spu->problem->spu_runcntl_RW));
+ DUMP_VALUE("0x%x", problem->spu_status_R,
+ in_be32(&spu->problem->spu_status_R));
+ DUMP_VALUE("0x%x", problem->spu_npc_RW,
+ in_be32(&spu->problem->spu_npc_RW));
+ DUMP_FIELD(spu, "0x%p", priv2);
+ DUMP_FIELD(spu, "0x%p", pdata);
+}
+
+int
+spu_inst_dump(unsigned long adr, long count, int praddr)
+{
+ return generic_inst_dump(adr, count, praddr, print_insn_spu);
+}
+
+static void dump_spu_ls(unsigned long num, int subcmd)
+{
+ unsigned long offset, addr, ls_addr;
+
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+ ls_addr = (unsigned long)spu_info[num].spu->local_store;
+ sync();
+ __delay(200);
+ } else {
+ catch_memory_errors = 0;
+ printf("*** Error: accessing spu info for spu %d\n", num);
+ return;
+ }
+ catch_memory_errors = 0;
+
+ if (scanhex(&offset))
+ addr = ls_addr + offset;
+ else
+ addr = spu_info[num].dump_addr;
+
+ if (addr >= ls_addr + LS_SIZE) {
+ printf("*** Error: address outside of local store\n");
+ return;
+ }
+
+ switch (subcmd) {
+ case 'i':
+ addr += spu_inst_dump(addr, 16, 1);
+ last_cmd = "sdi\n";
+ break;
+ default:
+ prdump(addr, 64);
+ addr += 64;
+ last_cmd = "sd\n";
+ break;
+ }
+
+ spu_info[num].dump_addr = addr;
+}
+
+static int do_spu_cmd(void)
+{
+ static unsigned long num = 0;
+ int cmd, subcmd = 0;
+
+ cmd = inchar();
+ switch (cmd) {
+ case 's':
+ stop_spus();
+ break;
+ case 'r':
+ restart_spus();
+ break;
+ case 'd':
+ subcmd = inchar();
+ if (isxdigit(subcmd) || subcmd == '\n')
+ termch = subcmd;
+ case 'f':
+ scanhex(&num);
+ if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
+ printf("*** Error: invalid spu number\n");
+ return 0;
+ }
+
+ switch (cmd) {
+ case 'f':
+ dump_spu_fields(spu_info[num].spu);
+ break;
+ default:
+ dump_spu_ls(num, subcmd);
+ break;
+ }
+
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+#else /* ! CONFIG_SPU_BASE */
+static int do_spu_cmd(void)
+{
+ return -1;
+}
+#endif