aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/xmon
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-28 22:53:37 +1000
committerPaul Mackerras <paulus@samba.org>2005-10-28 22:53:37 +1000
commitf78541dcec327b0c46b150ee7d727f3db80275c4 (patch)
tree9336801742d93ffa0c84c76e2b3cdc5b50c7125b /arch/powerpc/xmon
parentc032524f0ddea5fcc3a2cece0d4a61f37e5ca9cd (diff)
powerpc: Merge xmon
The merged version follows the ppc64 version pretty closely mostly, and in fact ARCH=ppc64 now uses the arch/powerpc/xmon version. The main difference for ppc64 is that the 'p' command to call show_state (which was always pretty dodgy) has been replaced by the ppc32 'p' command, which calls a given procedure (so in fact the old 'p' command behaviour can be achieved with 'p $show_state'). Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/xmon')
-rw-r--r--arch/powerpc/xmon/Makefile11
-rw-r--r--arch/powerpc/xmon/ansidecl.h141
-rw-r--r--arch/powerpc/xmon/nonstdio.h22
-rw-r--r--arch/powerpc/xmon/ppc-dis.c184
-rw-r--r--arch/powerpc/xmon/ppc-opc.c4621
-rw-r--r--arch/powerpc/xmon/ppc.h307
-rw-r--r--arch/powerpc/xmon/setjmp.S135
-rw-r--r--arch/powerpc/xmon/start_32.c624
-rw-r--r--arch/powerpc/xmon/start_64.c187
-rw-r--r--arch/powerpc/xmon/start_8xx.c287
-rw-r--r--arch/powerpc/xmon/subr_prf.c54
-rw-r--r--arch/powerpc/xmon/xmon.c2530
12 files changed, 9103 insertions, 0 deletions
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
new file mode 100644
index 00000000000..79a784f0e7a
--- /dev/null
+++ b/arch/powerpc/xmon/Makefile
@@ -0,0 +1,11 @@
+# Makefile for xmon
+
+ifdef CONFIG_PPC64
+EXTRA_CFLAGS += -mno-minimal-toc
+endif
+
+obj-$(CONFIG_8xx) += start_8xx.o
+obj-$(CONFIG_6xx) += start_32.o
+obj-$(CONFIG_4xx) += start_32.o
+obj-$(CONFIG_PPC64) += start_64.o
+obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
diff --git a/arch/powerpc/xmon/ansidecl.h b/arch/powerpc/xmon/ansidecl.h
new file mode 100644
index 00000000000..c9b9f0929e9
--- /dev/null
+++ b/arch/powerpc/xmon/ansidecl.h
@@ -0,0 +1,141 @@
+/* ANSI and traditional C compatibility macros
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ This file is part of the GNU C 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macro ANSI C definition Traditional C definition
+ ----- ---- - ---------- ----------- - ----------
+ PTR `void *' `char *'
+ LONG_DOUBLE `long double' `double'
+ VOLATILE `volatile' `'
+ SIGNED `signed' `'
+ PTRCONST `void *const' `char *'
+ ANSI_PROTOTYPES 1 not defined
+
+ CONST is also defined, but is obsolete. Just use const.
+
+ DEFUN (name, arglist, args)
+
+ Defines function NAME.
+
+ ARGLIST lists the arguments, separated by commas and enclosed in
+ parentheses. ARGLIST becomes the argument list in traditional C.
+
+ ARGS list the arguments with their types. It becomes a prototype in
+ ANSI C, and the type declarations in traditional C. Arguments should
+ be separated with `AND'. For functions with a variable number of
+ arguments, the last thing listed should be `DOTS'.
+
+ DEFUN_VOID (name)
+
+ Defines a function NAME, which takes no arguments.
+
+ obsolete -- EXFUN (name, (prototype)) -- obsolete.
+
+ Replaced by PARAMS. Do not use; will disappear someday soon.
+ Was used in external function declarations.
+ In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+ parentheses). In traditional C it is `NAME()'.
+ For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+ PARAMS ((args))
+
+ We could use the EXFUN macro to handle prototype declarations, but
+ the name is misleading and the result is ugly. So we just define a
+ simple macro to handle the parameter lists, as in:
+
+ static int foo PARAMS ((int, char));
+
+ This produces: `static int foo();' or `static int foo (int, char);'
+
+ EXFUN would have done it like this:
+
+ static int EXFUN (foo, (int, char));
+
+ but the function is not external...and it's hard to visually parse
+ the function name out of the mess. EXFUN should be considered
+ obsolete; new code should be written to use PARAMS.
+
+ For example:
+ extern int printf PARAMS ((CONST char *format DOTS));
+ int DEFUN(fprintf, (stream, format),
+ FILE *stream AND CONST char *format DOTS) { ... }
+ void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef _ANSIDECL_H
+
+#define _ANSIDECL_H 1
+
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
+/* All known AIX compilers implement these things (but don't always
+ define __STDC__). The RISC/OS MIPS compiler defines these things
+ in SVR4 mode, but does not define __STDC__. */
+
+#define PTR void *
+#define PTRCONST void *CONST
+#define LONG_DOUBLE long double
+
+#define AND ,
+#define NOARGS void
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+#define DOTS , ...
+
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(void)
+
+#define PROTO(type, name, arglist) type name arglist
+#define PARAMS(paramlist) paramlist
+#define ANSI_PROTOTYPES 1
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define const
+#endif
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist) ()
+
+#endif /* ANSI C. */
+
+#endif /* ansidecl.h */
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h
new file mode 100644
index 00000000000..84211a21c6f
--- /dev/null
+++ b/arch/powerpc/xmon/nonstdio.h
@@ -0,0 +1,22 @@
+typedef int FILE;
+extern FILE *xmon_stdin, *xmon_stdout;
+#define EOF (-1)
+#define stdin xmon_stdin
+#define stdout xmon_stdout
+#define printf xmon_printf
+#define fprintf xmon_fprintf
+#define fputs xmon_fputs
+#define fgets xmon_fgets
+#define putchar xmon_putchar
+#define getchar xmon_getchar
+#define putc xmon_putc
+#define getc xmon_getc
+#define fopen(n, m) NULL
+#define fflush(f) do {} while (0)
+#define fclose(f) do {} while (0)
+extern char *fgets(char *, int, void *);
+extern void xmon_printf(const char *, ...);
+extern void xmon_fprintf(void *, const char *, ...);
+extern void xmon_sprintf(char *, const char *, ...);
+
+#define perror(s) printf("%s: no files!\n", (s))
diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c
new file mode 100644
index 00000000000..ac0a9d2427e
--- /dev/null
+++ b/arch/powerpc/xmon/ppc-dis.c
@@ -0,0 +1,184 @@
+/* ppc-dis.c -- Disassemble PowerPC instructions
+ Copyright 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+2, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+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 file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nonstdio.h"
+#include "ansidecl.h"
+#include "ppc.h"
+
+extern void print_address (unsigned long memaddr);
+
+/* Print a PowerPC or POWER instruction. */
+
+int
+print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect)
+{
+ const struct powerpc_opcode *opcode;
+ const struct powerpc_opcode *opcode_end;
+ unsigned long op;
+
+ if (dialect == 0)
+ dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
+ | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
+
+ /* Get the major opcode of the instruction. */
+ op = PPC_OP (insn);
+
+ /* Find the first match in the opcode table. We could speed this up
+ a bit by doing a binary search on the major opcode. */
+ opcode_end = powerpc_opcodes + powerpc_num_opcodes;
+ again:
+ for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
+ {
+ unsigned long table_op;
+ const unsigned char *opindex;
+ const struct powerpc_operand *operand;
+ int invalid;
+ int need_comma;
+ int need_paren;
+
+ table_op = PPC_OP (opcode->opcode);
+ if (op < table_op)
+ break;
+ if (op > table_op)
+ continue;
+
+ if ((insn & opcode->mask) != opcode->opcode
+ || (opcode->flags & dialect) == 0)
+ continue;
+
+ /* Make two passes over the operands. First see if any of them
+ have extraction functions, and, if they do, make sure the
+ instruction is valid. */
+ invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ operand = powerpc_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, dialect, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ /* The instruction is valid. */
+ printf("%s", opcode->name);
+ if (opcode->operands[0] != 0)
+ printf("\t");
+
+ /* Now extract and print the operands. */
+ need_comma = 0;
+ need_paren = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ long value;
+
+ operand = powerpc_operands + *opindex;
+
+ /* Operands that are marked FAKE are simply ignored. We
+ already made sure that the extract function considered
+ the instruction to be valid. */
+ if ((operand->flags & PPC_OPERAND_FAKE) != 0)
+ continue;
+
+ /* Extract the value from the instruction. */
+ if (operand->extract)
+ value = (*operand->extract) (insn, dialect, &invalid);
+ else
+ {
+ value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+ if ((operand->flags & PPC_OPERAND_SIGNED) != 0
+ && (value & (1 << (operand->bits - 1))) != 0)
+ value -= 1 << operand->bits;
+ }
+
+ /* If the operand is optional, and the value is zero, don't
+ print anything. */
+ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+ && (operand->flags & PPC_OPERAND_NEXT) == 0
+ && value == 0)
+ continue;
+
+ if (need_comma)
+ {
+ printf(",");
+ need_comma = 0;
+ }
+
+ /* Print the operand as directed by the flags. */
+ if ((operand->flags & PPC_OPERAND_GPR) != 0)
+ printf("r%ld", value);
+ else if ((operand->flags & PPC_OPERAND_FPR) != 0)
+ printf("f%ld", value);
+ else if ((operand->flags & PPC_OPERAND_VR) != 0)
+ printf("v%ld", value);
+ else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
+ print_address (memaddr + value);
+ else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+ print_address (value & 0xffffffff);
+ else if ((operand->flags & PPC_OPERAND_CR) == 0
+ || (dialect & PPC_OPCODE_PPC) == 0)
+ printf("%ld", value);
+ else
+ {
+ if (operand->bits == 3)
+ printf("cr%d", value);
+ else
+ {
+ static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+ int cr;
+ int cc;
+
+ cr = value >> 2;
+ if (cr != 0)
+ printf("4*cr%d+", cr);
+ cc = value & 3;
+ printf("%s", cbnames[cc]);
+ }
+ }
+
+ if (need_paren)
+ {
+ printf(")");
+ need_paren = 0;
+ }
+
+ if ((operand->flags & PPC_OPERAND_PARENS) == 0)
+ need_comma = 1;
+ else
+ {
+ printf("(");
+ need_paren = 1;
+ }
+ }
+
+ /* We have found and printed an instruction; return. */
+ return 4;
+ }
+
+ if ((dialect & PPC_OPCODE_ANY) != 0)
+ {
+ dialect = ~PPC_OPCODE_ANY;
+ goto again;
+ }
+
+ /* We could not find a match. */
+ printf(".long 0x%lx", insn);
+
+ return 4;
+}
diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c
new file mode 100644
index 00000000000..5ee8fc32f82
--- /dev/null
+++ b/arch/powerpc/xmon/ppc-opc.c
@@ -0,0 +1,4621 @@
+/* ppc-opc.c -- PowerPC opcode list
+ Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support
+
+ This file is part of GDB, GAS, and the GNU binutils.
+
+ GDB, GAS, and the GNU binutils are free software; you can redistribute
+ them and/or modify them under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either version
+ 2, or (at your option) any later version.
+
+ GDB, GAS, and the GNU binutils are distributed in the hope that they
+ 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 file; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include <linux/stddef.h>
+#include "nonstdio.h"
+#include "ppc.h"
+
+#define ATTRIBUTE_UNUSED
+#define _(x) x
+
+/* This file holds the PowerPC opcode table. The opcode table
+ includes almost all of the extended instruction mnemonics. This
+ permits the disassembler to use them, and simplifies the assembler
+ logic, at the cost of increasing the table size. The table is
+ strictly constant data, so the compiler should be able to put it in
+ the .text section.
+
+ This file also holds the operand table. All knowledge about
+ inserting operands into instructions and vice-versa is kept in this
+ file. */
+
+/* Local insertion and extraction functions. */
+
+static unsigned long insert_bat (unsigned long, long, int, const char **);
+static long extract_bat (unsigned long, int, int *);
+static unsigned long insert_bba (unsigned long, long, int, const char **);
+static long extract_bba (unsigned long, int, int *);
+static unsigned long insert_bd (unsigned long, long, int, const char **);
+static long extract_bd (unsigned long, int, int *);
+static unsigned long insert_bdm (unsigned long, long, int, const char **);
+static long extract_bdm (unsigned long, int, int *);
+static unsigned long insert_bdp (unsigned long, long, int, const char **);
+static long extract_bdp (unsigned long, int, int *);
+static unsigned long insert_bo (unsigned long, long, int, const char **);
+static long extract_bo (unsigned long, int, int *);
+static unsigned long insert_boe (unsigned long, long, int, const char **);
+static long extract_boe (unsigned long, int, int *);
+static unsigned long insert_dq (unsigned long, long, int, const char **);
+static long extract_dq (unsigned long, int, int *);
+static unsigned long insert_ds (unsigned long, long, int, const char **);
+static long extract_ds (unsigned long, int, int *);
+static unsigned long insert_de (unsigned long, long, int, const char **);
+static long extract_de (unsigned long, int, int *);
+static unsigned long insert_des (unsigned long, long, int, const char **);
+static long extract_des (unsigned long, int, int *);
+static unsigned long insert_fxm (unsigned long, long, int, const char **);
+static long extract_fxm (unsigned long, int, int *);
+static unsigned long insert_li (unsigned long, long, int, const char **);
+static long extract_li (unsigned long, int, int *);
+static unsigned long insert_mbe (unsigned long, long, int, const char **);
+static long extract_mbe (unsigned long, int, int *);
+static unsigned long insert_mb6 (unsigned long, long, int, const char **);
+static long extract_mb6 (unsigned long, int, int *);
+static unsigned long insert_nb (unsigned long, long, int, const char **);
+static long extract_nb (unsigned long, int, int *);
+static unsigned long insert_nsi (unsigned long, long, int, const char **);
+static long extract_nsi (unsigned long, int, int *);
+static unsigned long insert_ral (unsigned long, long, int, const char **);
+static unsigned long insert_ram (unsigned long, long, int, const char **);
+static unsigned long insert_raq (unsigned long, long, int, const char **);
+static unsigned long insert_ras (unsigned long, long, int, const char **);
+static unsigned long insert_rbs (unsigned long, long, int, const char **);
+static long extract_rbs (unsigned long, int, int *);
+static unsigned long insert_rsq (unsigned long, long, int, const char **);
+static unsigned long insert_rtq (unsigned long, long, int, const char **);
+static unsigned long insert_sh6 (unsigned long, long, int, const char **);
+static long extract_sh6 (unsigned long, int, int *);
+static unsigned long insert_spr (unsigned long, long, int, const char **);
+static long extract_spr (unsigned long, int, int *);
+static unsigned long insert_tbr (unsigned long, long, int, const char **);
+static long extract_tbr (unsigned long, int, int *);
+static unsigned long insert_ev2 (unsigned long, long, int, const char **);
+static long extract_ev2 (unsigned long, int, int *);
+static unsigned long insert_ev4 (unsigned long, long, int, const char **);
+static long extract_ev4 (unsigned long, int, int *);
+static unsigned long insert_ev8 (unsigned long, long, int, const char **);
+static long extract_ev8 (unsigned long, int, int *);
+
+/* The operands table.
+
+ The fields are bits, shift, insert, extract, flags.
+
+ We used to put parens around the various additions, like the one
+ for BA just below. However, that caused trouble with feeble
+ compilers with a limit on depth of a parenthesized expression, like
+ (reportedly) the compiler in Microsoft Developer Studio 5. So we
+ omit the parens, since the macros are never used in a context where
+ the addition will be ambiguous. */
+
+const struct powerpc_operand powerpc_operands[] =
+{
+ /* The zero index is used to indicate the end of the list of
+ operands. */
+#define UNUSED 0
+ { 0, 0, NULL, NULL, 0 },
+
+ /* The BA field in an XL form instruction. */
+#define BA UNUSED + 1
+#define BA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BA field in an XL form instruction when it must be the same
+ as the BT field in the same instruction. */
+#define BAT BA + 1
+ { 5, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE },
+
+ /* The BB field in an XL form instruction. */
+#define BB BAT + 1
+#define BB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BB field in an XL form instruction when it must be the same
+ as the BA field in the same instruction. */
+#define BBA BB + 1
+ { 5, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE },
+
+ /* The BD field in a B form instruction. The lower two bits are
+ forced to zero. */
+#define BD BBA + 1
+ { 16, 0, insert_bd, extract_bd, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when absolute addressing is
+ used. */
+#define BDA BD + 1
+ { 16, 0, insert_bd, extract_bd, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the - modifier is used.
+ This sets the y bit of the BO field appropriately. */
+#define BDM BDA + 1
+ { 16, 0, insert_bdm, extract_bdm,
+ PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the - modifier is used
+ and absolute address is used. */
+#define BDMA BDM + 1
+ { 16, 0, insert_bdm, extract_bdm,
+ PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the + modifier is used.
+ This sets the y bit of the BO field appropriately. */
+#define BDP BDMA + 1
+ { 16, 0, insert_bdp, extract_bdp,
+ PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The BD field in a B form instruction when the + modifier is used
+ and absolute addressing is used. */
+#define BDPA BDP + 1
+ { 16, 0, insert_bdp, extract_bdp,
+ PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The BF field in an X or XL form instruction. */
+#define BF BDPA + 1
+ { 3, 23, NULL, NULL, PPC_OPERAND_CR },
+
+ /* An optional BF field. This is used for comparison instructions,
+ in which an omitted BF field is taken as zero. */
+#define OBF BF + 1
+ { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+ /* The BFA field in an X or XL form instruction. */
+#define BFA OBF + 1
+ { 3, 18, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BI field in a B form or XL form instruction. */
+#define BI BFA + 1
+#define BI_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The BO field in a B form instruction. Certain values are
+ illegal. */
+#define BO BI + 1
+#define BO_MASK (0x1f << 21)
+ { 5, 21, insert_bo, extract_bo, 0 },
+
+ /* The BO field in a B form instruction when the + or - modifier is
+ used. This is like the BO field, but it must be even. */
+#define BOE BO + 1
+ { 5, 21, insert_boe, extract_boe, 0 },
+
+ /* The BT field in an X or XL form instruction. */
+#define BT BOE + 1
+ { 5, 21, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The condition register number portion of the BI field in a B form
+ or XL form instruction. This is used for the extended
+ conditional branch mnemonics, which set the lower two bits of the
+ BI field. This field is optional. */
+#define CR BT + 1
+ { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+
+ /* The CRB field in an X form instruction. */
+#define CRB CR + 1
+ { 5, 6, NULL, NULL, 0 },
+
+ /* The CRFD field in an X form instruction. */
+#define CRFD CRB + 1
+ { 3, 23, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The CRFS field in an X form instruction. */
+#define CRFS CRFD + 1
+ { 3, 0, NULL, NULL, PPC_OPERAND_CR },
+
+ /* The CT field in an X form instruction. */
+#define CT CRFS + 1
+ { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
+ /* The D field in a D form instruction. This is a displacement off
+ a register, and implies that the next operand is a register in
+ parentheses. */
+#define D CT + 1
+ { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+ /* The DE field in a DE form instruction. This is like D, but is 12
+ bits only. */
+#define DE D + 1
+ { 14, 0, insert_de, extract_de, PPC_OPERAND_PARENS },
+
+ /* The DES field in a DES form instruction. This is like DS, but is 14
+ bits only (12 stored.) */
+#define DES DE + 1
+ { 14, 0, insert_des, extract_des, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+
+ /* The DQ field in a DQ form instruction. This is like D, but the
+ lower four bits are forced to zero. */
+#define DQ DES + 1
+ { 16, 0, insert_dq, extract_dq,
+ PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ },
+
+ /* The DS field in a DS form instruction. This is like D, but the
+ lower two bits are forced to zero. */
+#define DS DQ + 1
+ { 16, 0, insert_ds, extract_ds,
+ PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS },
+
+ /* The E field in a wrteei instruction. */
+#define E DS + 1
+ { 1, 15, NULL, NULL, 0 },
+
+ /* The FL1 field in a POWER SC form instruction. */
+#define FL1 E + 1
+ { 4, 12, NULL, NULL, 0 },
+
+ /* The FL2 field in a POWER SC form instruction. */
+#define FL2 FL1 + 1
+ { 3, 2, NULL, NULL, 0 },
+
+ /* The FLM field in an XFL form instruction. */
+#define FLM FL2 + 1
+ { 8, 17, NULL, NULL, 0 },
+
+ /* The FRA field in an X or A form instruction. */
+#define FRA FLM + 1
+#define FRA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FRB field in an X or A form instruction. */
+#define FRB FRA + 1
+#define FRB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FRC field in an A form instruction. */
+#define FRC FRB + 1
+#define FRC_MASK (0x1f << 6)
+ { 5, 6, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FRS field in an X form instruction or the FRT field in a D, X
+ or A form instruction. */
+#define FRS FRC + 1
+#define FRT FRS
+ { 5, 21, NULL, NULL, PPC_OPERAND_FPR },
+
+ /* The FXM field in an XFX instruction. */
+#define FXM FRS + 1
+#define FXM_MASK (0xff << 12)
+ { 8, 12, insert_fxm, extract_fxm, 0 },
+
+ /* Power4 version for mfcr. */
+#define FXM4 FXM + 1
+ { 8, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL },
+
+ /* The L field in a D or X form instruction. */
+#define L FXM4 + 1
+ { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
+ /* The LEV field in a POWER SC form instruction. */
+#define LEV L + 1
+ { 7, 5, NULL, NULL, 0 },
+
+ /* The LI field in an I form instruction. The lower two bits are
+ forced to zero. */
+#define LI LEV + 1
+ { 26, 0, insert_li, extract_li, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED },
+
+ /* The LI field in an I form instruction when used as an absolute
+ address. */
+#define LIA LI + 1
+ { 26, 0, insert_li, extract_li, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED },
+
+ /* The LS field in an X (sync) form instruction. */
+#define LS LIA + 1
+ { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
+ /* The MB field in an M form instruction. */
+#define MB LS + 1
+#define MB_MASK (0x1f << 6)
+ { 5, 6, NULL, NULL, 0 },
+
+ /* The ME field in an M form instruction. */
+#define ME MB + 1
+#define ME_MASK (0x1f << 1)
+ { 5, 1, NULL, NULL, 0 },
+
+ /* The MB and ME fields in an M form instruction expressed a single
+ operand which is a bitmask indicating which bits to select. This
+ is a two operand form using PPC_OPERAND_NEXT. See the
+ description in opcode/ppc.h for what this means. */
+#define MBE ME + 1
+ { 5, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+ { 32, 0, insert_mbe, extract_mbe, 0 },
+
+ /* The MB or ME field in an MD or MDS form instruction. The high
+ bit is wrapped to the low end. */
+#define MB6 MBE + 2
+#define ME6 MB6
+#define MB6_MASK (0x3f << 5)
+ { 6, 5, insert_mb6, extract_mb6, 0 },
+
+ /* The MO field in an mbar instruction. */
+#define MO MB6 + 1
+ { 5, 21, NULL, NULL, 0 },
+
+ /* The NB field in an X form instruction. The value 32 is stored as
+ 0. */
+#define NB MO + 1
+ { 6, 11, insert_nb, extract_nb, 0 },
+
+ /* The NSI field in a D form instruction. This is the same as the
+ SI field, only negated. */
+#define NSI NB + 1
+ { 16, 0, insert_nsi, extract_nsi,
+ PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED },
+
+ /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction. */
+#define RA NSI + 1
+#define RA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
+
+ /* 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 },
+
+ /* 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 },
+
+ /* The RA field in an lmw instruction, which has special value
+ restrictions. */
+#define RAM RAL + 1
+ { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
+
+ /* 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 },
+
+ /* The RB field in an X, XO, M, or MDS form instruction. */
+#define RB RAS + 1
+#define RB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
+
+ /* The RB field in an X form instruction when it must be the same as
+ the RS field in the instruction. This is used for extended
+ mnemonics like mr. */
+#define RBS RB + 1
+ { 5, 1, insert_rbs, extract_rbs, PPC_OPERAND_FAKE },
+
+ /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form
+ instruction or the RT field in a D, DS, X, XFX or XO form
+ instruction. */
+#define RS RBS + 1
+#define RT RS
+#define RT_MASK (0x1f << 21)
+ { 5, 21, NULL, NULL, PPC_OPERAND_GPR },
+
+ /* 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 },
+
+ /* 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 },
+
+ /* The SH field in an X or M form instruction. */
+#define SH RTQ + 1
+#define SH_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, 0 },
+
+ /* The SH field in an MD form instruction. This is split. */
+#define SH6 SH + 1
+#define SH6_MASK ((0x1f << 11) | (1 << 1))
+ { 6, 1, insert_sh6, extract_sh6, 0 },
+
+ /* The SI field in a D form instruction. */
+#define SI SH6 + 1
+ { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
+
+ /* The SI field in a D form instruction when we accept a wide range
+ of positive values. */
+#define SISIGNOPT SI + 1
+ { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+
+ /* The SPR field in an XFX form instruction. This is flipped--the
+ lower 5 bits are stored in the upper 5 and vice- versa. */
+#define SPR SISIGNOPT + 1
+#define PMR SPR
+#define SPR_MASK (0x3ff << 11)
+ { 10, 11, insert_spr, extract_spr, 0 },
+
+ /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */
+#define SPRBAT SPR + 1
+#define SPRBAT_MASK (0x3 << 17)
+ { 2, 17, NULL, NULL, 0 },
+
+ /* 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 },
+
+ /* The SR field in an X form instruction. */
+#define SR SPRG + 1
+ { 4, 16, NULL, NULL, 0 },
+
+ /* The STRM field in an X AltiVec form instruction. */
+#define STRM SR + 1
+#define STRM_MASK (0x3 << 21)
+ { 2, 21, NULL, NULL, 0 },
+
+ /* The SV field in a POWER SC form instruction. */
+#define SV STRM + 1
+ { 14, 2, NULL, NULL, 0 },
+
+ /* The TBR field in an XFX form instruction. This is like the SPR
+ field, but it is optional. */
+#define TBR SV + 1
+ { 10, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL },
+
+ /* The TO field in a D or X form instruction. */
+#define TO TBR + 1
+#define TO_MASK (0x1f << 21)
+ { 5, 21, NULL, NULL, 0 },
+
+ /* The U field in an X form instruction. */
+#define U TO + 1
+ { 4, 12, NULL, NULL, 0 },
+
+ /* The UI field in a D form instruction. */
+#define UI U + 1
+ { 16, 0, NULL, NULL, 0 },
+
+ /* The VA field in a VA, VX or VXR form instruction. */
+#define VA UI + 1
+#define VA_MASK (0x1f << 16)
+ { 5, 16, NULL, NULL, PPC_OPERAND_VR },
+
+ /* The VB field in a VA, VX or VXR form instruction. */
+#define VB VA + 1
+#define VB_MASK (0x1f << 11)
+ { 5, 11, NULL, NULL, PPC_OPERAND_VR },
+
+ /* The VC field in a VA form instruction. */
+#define VC VB + 1
+#define VC_MASK (0x1f << 6)
+ { 5, 6, NULL, NULL, PPC_OPERAND_VR },
+
+ /* The VD or VS field in a VA, VX, VXR or X form instruction. */
+#define VD VC + 1
+#define VS VD
+#define VD_MASK (0x1f << 21)
+ { 5, 21, NULL, NULL, PPC_OPERAND_VR },
+
+ /* The SIMM field in a VX form instruction. */
+#define SIMM VD + 1
+ { 5, 16, NULL, NULL, PPC_OPERAND_SIGNED},
+
+ /* The UIMM field in a VX form instruction. */
+#define UIMM SIMM + 1
+ { 5, 16, NULL, NULL, 0 },
+
+ /* The SHB field in a VA form instruction. */
+#define SHB UIMM + 1
+ { 4, 6, NULL, NULL, 0 },
+
+ /* The other UIMM field in a EVX form instruction. */
+#define EVUIMM SHB + 1
+ { 5, 11, NULL, NULL, 0 },
+
+ /* The other UIMM field in a half word EVX form instruction. */
+#define EVUIMM_2 EVUIMM + 1
+ { 32, 11, insert_ev2, extract_ev2, PPC_OPERAND_PARENS },
+
+ /* The other UIMM field in a word EVX form instruction. */
+#define EVUIMM_4 EVUIMM_2 + 1
+ { 32, 11, insert_ev4, extract_ev4, PPC_OPERAND_PARENS },
+
+ /* The other UIMM field in a double EVX form instruction. */
+#define EVUIMM_8 EVUIMM_4 + 1
+ { 32, 11, insert_ev8, extract_ev8, PPC_OPERAND_PARENS },
+
+ /* The WS field. */
+#define WS EVUIMM_8 + 1
+#define WS_MASK (0x7 << 11)
+ { 3, 11, NULL, NULL, 0 },
+
+ /* The L field in an mtmsrd instruction */
+#define MTMSRD_L WS + 1
+ { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
+
+};
+
+/* The functions used to insert and extract complicated operands. */
+
+/* The BA field in an XL form instruction when it must be the same as
+ the BT field in the same instruction. This operand is marked FAKE.
+ The insertion 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_bat (unsigned long insn,
+ long value ATTRIBUTE_UNUSED,
+ int dialect ATTRIBUTE_UNUSED,
+ const char **errmsg ATTRIBUTE_UNUSED)
+{