]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
This commit was manufactured by cvs2svn to create branch
authornobody <>
Fri, 27 Jun 2003 17:05:59 +0000 (17:05 +0000)
committernobody <>
Fri, 27 Jun 2003 17:05:59 +0000 (17:05 +0000)
'carlton_dictionary-branch'.

Cherrypick from master 2003-06-27 17:05:58 UTC Elena Zannoni <ezannoni@kwikemart.cygnus.com> '2003-06-27  Elena Zannoni  <ezannoni@redhat.com>':
    gdb/alpha-mdebug-tdep.c
    gdb/config/mips/mips.mt
    gdb/config/mips/mips64.mt
    gdb/config/powerpc/nm-ppc64-linux.h
    gdb/config/powerpc/ppc64-linux.mh
    gdb/dwarf2-frame.c
    gdb/dwarf2-frame.h
    gdb/linux-nat.c
    gdb/linux-nat.h
    gdb/remote-fileio.c
    gdb/remote-fileio.h
    gdb/stack.h
    gdb/testsuite/gdb.asm/alpha.inc
    gdb/testsuite/gdb.base/bang.exp
    gdb/testsuite/gdb.base/fileio.c
    gdb/testsuite/gdb.base/fileio.exp
    gdb/testsuite/gdb.base/gdb_history
    gdb/testsuite/gdb.base/shreloc.c
    gdb/testsuite/gdb.base/shreloc.exp
    gdb/testsuite/gdb.base/shreloc1.c
    gdb/testsuite/gdb.base/shreloc2.c
    gdb/testsuite/gdb.c++/pr-1210.cc
    gdb/testsuite/gdb.c++/pr-1210.exp
    gdb/trad-frame.c
    gdb/trad-frame.h
    include/gdb/fileio.h
    sim/h8300/sim-main.h
    sim/ppc/altivec.igen
    sim/ppc/altivec_expression.h
    sim/ppc/altivec_registers.h
    sim/ppc/e500.igen
    sim/ppc/e500_expression.h
    sim/ppc/e500_registers.h

33 files changed:
gdb/alpha-mdebug-tdep.c [new file with mode: 0644]
gdb/config/mips/mips.mt [new file with mode: 0644]
gdb/config/mips/mips64.mt [new file with mode: 0644]
gdb/config/powerpc/nm-ppc64-linux.h [new file with mode: 0644]
gdb/config/powerpc/ppc64-linux.mh [new file with mode: 0644]
gdb/dwarf2-frame.c [new file with mode: 0644]
gdb/dwarf2-frame.h [new file with mode: 0644]
gdb/linux-nat.c [new file with mode: 0644]
gdb/linux-nat.h [new file with mode: 0644]
gdb/remote-fileio.c [new file with mode: 0644]
gdb/remote-fileio.h [new file with mode: 0644]
gdb/stack.h [new file with mode: 0644]
gdb/testsuite/gdb.asm/alpha.inc [new file with mode: 0644]
gdb/testsuite/gdb.base/bang.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/fileio.c [new file with mode: 0644]
gdb/testsuite/gdb.base/fileio.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/gdb_history [new file with mode: 0644]
gdb/testsuite/gdb.base/shreloc.c [new file with mode: 0644]
gdb/testsuite/gdb.base/shreloc.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/shreloc1.c [new file with mode: 0644]
gdb/testsuite/gdb.base/shreloc2.c [new file with mode: 0644]
gdb/testsuite/gdb.c++/pr-1210.cc [new file with mode: 0644]
gdb/testsuite/gdb.c++/pr-1210.exp [new file with mode: 0644]
gdb/trad-frame.c [new file with mode: 0644]
gdb/trad-frame.h [new file with mode: 0644]
include/gdb/fileio.h [new file with mode: 0644]
sim/h8300/sim-main.h [new file with mode: 0644]
sim/ppc/altivec.igen [new file with mode: 0644]
sim/ppc/altivec_expression.h [new file with mode: 0644]
sim/ppc/altivec_registers.h [new file with mode: 0644]
sim/ppc/e500.igen [new file with mode: 0644]
sim/ppc/e500_expression.h [new file with mode: 0644]
sim/ppc/e500_registers.h [new file with mode: 0644]

diff --git a/gdb/alpha-mdebug-tdep.c b/gdb/alpha-mdebug-tdep.c
new file mode 100644 (file)
index 0000000..9eb9c62
--- /dev/null
@@ -0,0 +1,384 @@
+/* Target-dependent mdebug code for the ALPHA architecture.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "symtab.h"
+#include "gdbcore.h"
+#include "block.h"
+#include "gdb_assert.h"
+
+#include "alpha-tdep.h"
+
+/* FIXME: Some of this code should perhaps be merged with mips.  */
+
+/* *INDENT-OFF* */
+/* Layout of a stack frame on the alpha:
+
+                |                              |
+ pdr members:  |  7th ... nth arg,             |
+                |  `pushed' by caller.         |
+                |                              |
+----------------|-------------------------------|<--  old_sp == vfp
+   ^  ^  ^  ^  |                               |
+   |  |  |  |  |                               |
+   |  |localoff        |  Copies of 1st .. 6th         |
+   |  |  |  |  |  argument if necessary.       |
+   |  |  |  v  |                               |
+   |  |  |  ---        |-------------------------------|<-- LOCALS_ADDRESS
+   |  |  |      |                              |
+   |  |  |      |  Locals and temporaries.     |
+   |  |  |      |                              |
+   |  |  |      |-------------------------------|
+   |  |  |      |                              |
+   |-fregoffset        |  Saved float registers.       |
+   |  |  |      |  F9                          |
+   |  |  |      |   .                          |
+   |  |  |      |   .                          |
+   |  |  |      |  F2                          |
+   |  |  v      |                              |
+   |  |  -------|-------------------------------|
+   |  |         |                              |
+   |  |         |  Saved registers.            |
+   |  |         |  S6                          |
+   |-regoffset |   .                           |
+   |  |         |   .                          |
+   |  |         |  S0                          |
+   |  |         |  pdr.pcreg                   |
+   |  v         |                              |
+   |  ----------|-------------------------------|
+   |            |                              |
+ frameoffset    |  Argument build area, gets   |
+   |            |  7th ... nth arg for any     |
+   |            |  called procedure.           |
+   v            |                              |
+   -------------|-------------------------------|<-- sp
+                |                              |
+*/
+/* *INDENT-ON* */
+
+#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
+#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
+#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
+#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
+#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
+#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
+#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
+#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
+#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
+\f
+/* Locate the mdebug PDR for the given PC.  Return null if one can't
+   be found; you'll have to fall back to other methods in that case.  */
+
+static alpha_extra_func_info_t
+find_proc_desc (CORE_ADDR pc)
+{
+  struct block *b = block_for_pc (pc);
+  alpha_extra_func_info_t proc_desc = NULL;
+  struct symbol *sym = NULL;
+
+  if (b)
+    {
+      CORE_ADDR startaddr;
+      find_pc_partial_function (pc, NULL, &startaddr, NULL);
+
+      if (startaddr > BLOCK_START (b))
+       /* This is the "pathological" case referred to in a comment in
+          print_frame_info.  It might be better to move this check into
+          symbol reading.  */
+       sym = NULL;
+      else
+       sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
+    }
+
+  if (sym)
+    {
+      proc_desc = (alpha_extra_func_info_t) SYMBOL_VALUE (sym);
+
+      /* If we never found a PDR for this function in symbol reading,
+        then examine prologues to find the information.  */
+      if (proc_desc->pdr.framereg == -1)
+       proc_desc = NULL;
+    }
+
+  return proc_desc;
+}
+
+/* This returns the PC of the first inst after the prologue.  If we can't
+   find the prologue, then return 0.  */
+
+static CORE_ADDR
+alpha_mdebug_after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
+{
+  if (proc_desc)
+    {
+      /* If function is frameless, then we need to do it the hard way.  I
+         strongly suspect that frameless always means prologueless... */
+      if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM
+         && PROC_FRAME_OFFSET (proc_desc) == 0)
+       return 0;
+    }
+
+  return alpha_after_prologue (pc);
+}
+
+/* Return non-zero if we *might* be in a function prologue.  Return zero
+   if we are definitively *not* in a function prologue.  */
+
+static int
+alpha_mdebug_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
+{
+  CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc);
+  return (after_prologue_pc == 0 || pc < after_prologue_pc);
+}
+
+\f
+/* Frame unwinder that reads mdebug PDRs.  */
+
+struct alpha_mdebug_unwind_cache
+{
+  alpha_extra_func_info_t proc_desc;
+  CORE_ADDR vfp;
+  CORE_ADDR *saved_regs;
+};
+
+/* Extract all of the information about the frame from PROC_DESC
+   and store the resulting register save locations in the structure.  */
+
+static struct alpha_mdebug_unwind_cache *
+alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame, 
+                                void **this_prologue_cache)
+{
+  struct alpha_mdebug_unwind_cache *info;
+  alpha_extra_func_info_t proc_desc;
+  ULONGEST vfp;
+  CORE_ADDR pc, reg_position;
+  unsigned long mask;
+  int ireg, returnreg;
+
+  if (*this_prologue_cache)
+    return *this_prologue_cache;
+
+  info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache);
+  *this_prologue_cache = info;
+  pc = frame_pc_unwind (next_frame);
+
+  /* ??? We don't seem to be able to cache the lookup of the PDR
+     from alpha_mdebug_frame_p.  It'd be nice if we could change
+     the arguments to that function.  Oh well.  */
+  proc_desc = find_proc_desc (pc);
+  info->proc_desc = proc_desc;
+  gdb_assert (proc_desc != NULL);
+
+  info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
+
+  /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET.  */
+  frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp);
+  vfp += PROC_FRAME_OFFSET (info->proc_desc);
+  info->vfp = vfp;
+
+  /* Fill in the offsets for the registers which gen_mask says were saved.  */
+
+  reg_position = vfp + PROC_REG_OFFSET (proc_desc);
+  mask = PROC_REG_MASK (proc_desc);
+  returnreg = PROC_PC_REG (proc_desc);
+
+  /* Note that RA is always saved first, regardless of its actual
+     register number.  */
+  if (mask & (1 << returnreg))
+    {
+      /* Clear bit for RA so we don't save it again later. */
+      mask &= ~(1 << returnreg);
+
+      info->saved_regs[returnreg] = reg_position;
+      reg_position += 8;
+    }
+
+  for (ireg = 0; ireg <= 31; ++ireg)
+    if (mask & (1 << ireg))
+      {
+       info->saved_regs[ireg] = reg_position;
+       reg_position += 8;
+      }
+
+  reg_position = vfp + PROC_FREG_OFFSET (proc_desc);
+  mask = PROC_FREG_MASK (proc_desc);
+
+  for (ireg = 0; ireg <= 31; ++ireg)
+    if (mask & (1 << ireg))
+      {
+       info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position;
+       reg_position += 8;
+      }
+
+  return info;
+}
+
+/* Given a GDB frame, determine the address of the calling function's
+   frame.  This will be used to create a new GDB frame struct.  */
+
+static void
+alpha_mdebug_frame_this_id (struct frame_info *next_frame,
+                           void **this_prologue_cache,
+                           struct frame_id *this_id)
+{
+  struct alpha_mdebug_unwind_cache *info
+    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+
+  *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame));
+}
+
+/* Retrieve the value of REGNUM in FRAME.  Don't give up!  */
+
+static void
+alpha_mdebug_frame_prev_register (struct frame_info *next_frame,
+                                 void **this_prologue_cache,
+                                 int regnum, int *optimizedp,
+                                 enum lval_type *lvalp, CORE_ADDR *addrp,
+                                 int *realnump, void *bufferp)
+{
+  struct alpha_mdebug_unwind_cache *info
+    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+
+  /* The PC of the previous frame is stored in the link register of
+     the current frame.  Frob regnum so that we pull the value from
+     the correct place.  */
+  if (regnum == ALPHA_PC_REGNUM)
+    regnum = PROC_PC_REG (info->proc_desc);
+  
+  /* For all registers known to be saved in the current frame, 
+     do the obvious and pull the value out.  */
+  if (info->saved_regs[regnum])
+    {
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = info->saved_regs[regnum];
+      *realnump = -1;
+      if (bufferp != NULL)
+       get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
+      return;
+    }
+
+  /* The stack pointer of the previous frame is computed by popping
+     the current stack frame.  */
+  if (regnum == ALPHA_SP_REGNUM)
+    {
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (bufferp != NULL)
+       store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp);
+      return;
+    }
+
+  /* Otherwise assume the next frame has the same register value.  */
+  frame_register (next_frame, regnum, optimizedp, lvalp, addrp,
+                 realnump, bufferp);
+}
+
+static const struct frame_unwind alpha_mdebug_frame_unwind = {
+  NORMAL_FRAME,
+  alpha_mdebug_frame_this_id,
+  alpha_mdebug_frame_prev_register
+};
+
+const struct frame_unwind *
+alpha_mdebug_frame_p (CORE_ADDR pc)
+{
+  alpha_extra_func_info_t proc_desc;
+
+  /* If this PC does not map to a PDR, then clearly this isn't an
+     mdebug frame.  */
+  proc_desc = find_proc_desc (pc);
+  if (proc_desc == NULL)
+    return NULL;
+
+  /* If we're in the prologue, the PDR for this frame is not yet valid.
+     Say no here and we'll fall back on the heuristic unwinder.  */
+  if (alpha_mdebug_in_prologue (pc, proc_desc))
+    return NULL;
+
+  return &alpha_mdebug_frame_unwind;
+}
+
+static CORE_ADDR
+alpha_mdebug_frame_base_address (struct frame_info *next_frame,
+                                void **this_prologue_cache)
+{
+  struct alpha_mdebug_unwind_cache *info
+    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+
+  return info->vfp;
+}
+
+static CORE_ADDR
+alpha_mdebug_frame_locals_address (struct frame_info *next_frame,
+                                  void **this_prologue_cache)
+{
+  struct alpha_mdebug_unwind_cache *info
+    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+
+  return info->vfp - PROC_LOCALOFF (info->proc_desc);
+}
+
+static CORE_ADDR
+alpha_mdebug_frame_args_address (struct frame_info *next_frame,
+                                void **this_prologue_cache)
+{
+  struct alpha_mdebug_unwind_cache *info
+    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
+
+  return info->vfp - ALPHA_NUM_ARG_REGS * 8;
+}
+
+static const struct frame_base alpha_mdebug_frame_base = {
+  &alpha_mdebug_frame_unwind,
+  alpha_mdebug_frame_base_address,
+  alpha_mdebug_frame_locals_address,
+  alpha_mdebug_frame_args_address
+};
+
+static const struct frame_base *
+alpha_mdebug_frame_base_p (CORE_ADDR pc)
+{
+  alpha_extra_func_info_t proc_desc;
+
+  /* If this PC does not map to a PDR, then clearly this isn't an
+     mdebug frame.  */
+  proc_desc = find_proc_desc (pc);
+  if (proc_desc == NULL)
+    return NULL;
+
+  return &alpha_mdebug_frame_base;
+}
+
+\f
+void
+alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  frame_unwind_append_predicate (gdbarch, alpha_mdebug_frame_p);
+  frame_base_append_predicate (gdbarch, alpha_mdebug_frame_base_p);
+}
diff --git a/gdb/config/mips/mips.mt b/gdb/config/mips/mips.mt
new file mode 100644 (file)
index 0000000..2d08bcb
--- /dev/null
@@ -0,0 +1,5 @@
+# Target: Big-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-mips.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/mips/mips64.mt b/gdb/config/mips/mips64.mt
new file mode 100644 (file)
index 0000000..e6a19d8
--- /dev/null
@@ -0,0 +1,5 @@
+# Target: Big-endian SIM monitor board.
+TDEPFILES= mips-tdep.o remote-mips.o
+TM_FILE= tm-mips64.h
+SIM_OBS = remote-sim.o
+SIM = ../sim/mips/libsim.a
diff --git a/gdb/config/powerpc/nm-ppc64-linux.h b/gdb/config/powerpc/nm-ppc64-linux.h
new file mode 100644 (file)
index 0000000..5d1c7b6
--- /dev/null
@@ -0,0 +1,27 @@
+/* IBM PowerPC64 native-dependent macros for GDB, the GNU debugger.
+   Copyright 2003 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef NM_PPC64_LINUX_H
+
+#include "config/powerpc/nm-linux.h"
+
+#define PTRACE_ARG3_TYPE void *
+#define PTRACE_XFER_TYPE long
+
+#endif /* NM_PPC64_LINUX_H */
diff --git a/gdb/config/powerpc/ppc64-linux.mh b/gdb/config/powerpc/ppc64-linux.mh
new file mode 100644 (file)
index 0000000..dd81586
--- /dev/null
@@ -0,0 +1,19 @@
+# Host: PowerPC64, running Linux
+
+XM_FILE= xm-linux.h
+XM_CLIBS=
+
+NAT_FILE= nm-ppc64-linux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o linux-proc.o \
+       ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o \
+       gcore.o linux-nat.o
+
+# The PowerPC has severe limitations on TOC size, and uses them even
+# for non-PIC code.  GDB overflows those tables when compiling with
+# -mfull-toc (the default), so we need to ask GCC to use as few TOC
+# entries as possible.
+MH_CFLAGS= -mminimal-toc
+
+# The dynamically loaded libthread_db needs access to symbols in the
+# gdb executable.
+LOADLIBES= -ldl -rdynamic
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
new file mode 100644 (file)
index 0000000..999cef7
--- /dev/null
@@ -0,0 +1,1336 @@
+/* Frame unwinder for frames with DWARF Call Frame Information.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Mark Kettenis.
+
+   This file is part of GDB.
+
+   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.  */
+
+#include "defs.h"
+#include "dwarf2expr.h"
+#include "elf/dwarf2.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "regcache.h"
+
+#include "gdb_assert.h"
+#include "gdb_string.h"
+
+#include "dwarf2-frame.h"
+
+/* Call Frame Information (CFI).  */
+
+/* Common Information Entry (CIE).  */
+
+struct dwarf2_cie
+{
+  /* Offset into the .debug_frame section where this CIE was found.
+     Used to identify this CIE.  */
+  ULONGEST cie_pointer;
+
+  /* Constant that is factored out of all advance location
+     instructions.  */
+  ULONGEST code_alignment_factor;
+
+  /* Constants that is factored out of all offset instructions.  */
+  LONGEST data_alignment_factor;
+
+  /* Return address column.  */
+  ULONGEST return_address_register;
+
+  /* Instruction sequence to initialize a register set.  */
+  unsigned char *initial_instructions;
+  unsigned char *end;
+
+  /* Encoding of addresses.  */
+  unsigned char encoding;
+
+  /* True if a 'z' augmentation existed.  */
+  unsigned char saw_z_augmentation;
+
+  struct dwarf2_cie *next;
+};
+
+/* Frame Description Entry (FDE).  */
+
+struct dwarf2_fde
+{
+  /* CIE for this FDE.  */
+  struct dwarf2_cie *cie;
+
+  /* First location associated with this FDE.  */
+  CORE_ADDR initial_location;
+
+  /* Number of bytes of program instructions described by this FDE.  */
+  CORE_ADDR address_range;
+
+  /* Instruction sequence.  */
+  unsigned char *instructions;
+  unsigned char *end;
+
+  struct dwarf2_fde *next;
+};
+
+static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc);
+\f
+
+/* Structure describing a frame state.  */
+
+struct dwarf2_frame_state
+{
+  /* Each register save state can be described in terms of a CFA slot,
+     another register, or a location expression.  */
+  struct dwarf2_frame_state_reg_info
+  {
+    struct dwarf2_frame_state_reg
+    {
+      union {
+       LONGEST offset;
+       ULONGEST reg;
+       unsigned char *exp;
+      } loc;
+      ULONGEST exp_len;
+      enum {
+       REG_UNSAVED,
+       REG_SAVED_OFFSET,
+       REG_SAVED_REG,
+       REG_SAVED_EXP,
+       REG_UNMODIFIED
+      } how;
+    } *reg;
+    int num_regs;
+
+    /* Used to implement DW_CFA_remember_state.  */
+    struct dwarf2_frame_state_reg_info *prev;
+  } regs;
+
+  LONGEST cfa_offset;
+  ULONGEST cfa_reg;
+  unsigned char *cfa_exp;
+  enum {
+    CFA_UNSET,
+    CFA_REG_OFFSET,
+    CFA_EXP
+  } cfa_how;
+
+  /* The PC described by the current frame state.  */
+  CORE_ADDR pc;
+
+  /* Initial register set from the CIE.
+     Used to implement DW_CFA_restore.  */
+  struct dwarf2_frame_state_reg_info initial;
+
+  /* The information we care about from the CIE.  */
+  LONGEST data_align;
+  ULONGEST code_align;
+  ULONGEST retaddr_column;
+};
+
+/* Store the length the expression for the CFA in the `cfa_reg' field,
+   which is unused in that case.  */
+#define cfa_exp_len cfa_reg
+
+/* Assert that the register set RS is large enough to store NUM_REGS
+   columns.  If necessary, enlarge the register set.  */
+
+static void
+dwarf2_frame_state_alloc_regs (struct dwarf2_frame_state_reg_info *rs,
+                              int num_regs)
+{
+  size_t size = sizeof (struct dwarf2_frame_state_reg);
+
+  if (num_regs <= rs->num_regs)
+    return;
+
+  rs->reg = (struct dwarf2_frame_state_reg *)
+    xrealloc (rs->reg, num_regs * size);
+
+  /* Initialize newly allocated registers.  */
+  memset (rs->reg + rs->num_regs, 0, (num_regs - rs->num_regs) * size);
+  rs->num_regs = num_regs;
+}
+
+/* Copy the register columns in register set RS into newly allocated
+   memory and return a pointer to this newly created copy.  */
+
+static struct dwarf2_frame_state_reg *
+dwarf2_frame_state_copy_regs (struct dwarf2_frame_state_reg_info *rs)
+{
+  size_t size = rs->num_regs * sizeof (struct dwarf2_frame_state_reg_info);
+  struct dwarf2_frame_state_reg *reg;
+
+  reg = (struct dwarf2_frame_state_reg *) xmalloc (size);
+  memcpy (reg, rs->reg, size);
+
+  return reg;
+}
+
+/* Release the memory allocated to register set RS.  */
+
+static void
+dwarf2_frame_state_free_regs (struct dwarf2_frame_state_reg_info *rs)
+{
+  if (rs)
+    {
+      dwarf2_frame_state_free_regs (rs->prev);
+
+      xfree (rs->reg);
+      xfree (rs);
+    }
+}
+
+/* Release the memory allocated to the frame state FS.  */
+
+static void
+dwarf2_frame_state_free (void *p)
+{
+  struct dwarf2_frame_state *fs = p;
+
+  dwarf2_frame_state_free_regs (fs->initial.prev);
+  dwarf2_frame_state_free_regs (fs->regs.prev);
+  xfree (fs->initial.reg);
+  xfree (fs->regs.reg);
+  xfree (fs);
+}
+\f
+
+/* Helper functions for execute_stack_op.  */
+
+static CORE_ADDR
+read_reg (void *baton, int reg)
+{
+  struct frame_info *next_frame = (struct frame_info *) baton;
+  int regnum;
+  char *buf;
+
+  regnum = DWARF2_REG_TO_REGNUM (reg);
+
+  buf = (char *) alloca (register_size (current_gdbarch, regnum));
+  frame_unwind_register (next_frame, regnum, buf);
+  return extract_typed_address (buf, builtin_type_void_data_ptr);
+}
+
+static void
+read_mem (void *baton, char *buf, CORE_ADDR addr, size_t len)
+{
+  read_memory (addr, buf, len);
+}
+
+static void
+no_get_frame_base (void *baton, unsigned char **start, size_t *length)
+{
+  internal_error (__FILE__, __LINE__,
+                 "Support for DW_OP_fbreg is unimplemented");
+}
+
+static CORE_ADDR
+no_get_tls_address (void *baton, CORE_ADDR offset)
+{
+  internal_error (__FILE__, __LINE__,
+                 "Support for DW_OP_GNU_push_tls_address is unimplemented");
+}
+
+static CORE_ADDR
+execute_stack_op (unsigned char *exp, ULONGEST len,
+                 struct frame_info *next_frame, CORE_ADDR initial)
+{
+  struct dwarf_expr_context *ctx;
+  CORE_ADDR result;
+
+  ctx = new_dwarf_expr_context ();
+  ctx->baton = next_frame;
+  ctx->read_reg = read_reg;
+  ctx->read_mem = read_mem;
+  ctx->get_frame_base = no_get_frame_base;
+  ctx->get_tls_address = no_get_tls_address;
+
+  dwarf_expr_push (ctx, initial);
+  dwarf_expr_eval (ctx, exp, len);
+  result = dwarf_expr_fetch (ctx, 0);
+
+  if (ctx->in_reg)
+    result = read_reg (next_frame, result);
+
+  free_dwarf_expr_context (ctx);
+
+  return result;
+}
+\f
+
+static void
+execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
+                    struct frame_info *next_frame,
+                    struct dwarf2_frame_state *fs)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  int bytes_read;
+
+  while (insn_ptr < insn_end && fs->pc <= pc)
+    {
+      unsigned char insn = *insn_ptr++;
+      ULONGEST utmp, reg;
+      LONGEST offset;
+
+      if ((insn & 0xc0) == DW_CFA_advance_loc)
+       fs->pc += (insn & 0x3f) * fs->code_align;
+      else if ((insn & 0xc0) == DW_CFA_offset)
+       {
+         reg = insn & 0x3f;
+         insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+         offset = utmp * fs->data_align;
+         dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+         fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+         fs->regs.reg[reg].loc.offset = offset;
+       }
+      else if ((insn & 0xc0) == DW_CFA_restore)
+       {
+         gdb_assert (fs->initial.reg);
+         reg = insn & 0x3f;
+         dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+         fs->regs.reg[reg] = fs->initial.reg[reg];
+       }
+      else
+       {
+         switch (insn)
+           {
+           case DW_CFA_set_loc:
+             fs->pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read);
+             insn_ptr += bytes_read;
+             break;
+
+           case DW_CFA_advance_loc1:
+             utmp = extract_unsigned_integer (insn_ptr, 1);
+             fs->pc += utmp * fs->code_align;
+             insn_ptr++;
+             break;
+           case DW_CFA_advance_loc2:
+             utmp = extract_unsigned_integer (insn_ptr, 2);
+             fs->pc += utmp * fs->code_align;
+             insn_ptr += 2;
+             break;
+           case DW_CFA_advance_loc4:
+             utmp = extract_unsigned_integer (insn_ptr, 4);
+             fs->pc += utmp * fs->code_align;
+             insn_ptr += 4;
+             break;
+
+           case DW_CFA_offset_extended:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             offset = utmp * fs->data_align;
+             dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+             fs->regs.reg[reg].how = REG_SAVED_OFFSET;
+             fs->regs.reg[reg].loc.offset = offset;
+             break;
+
+           case DW_CFA_restore_extended:
+             gdb_assert (fs->initial.reg);
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+             fs->regs.reg[reg] = fs->initial.reg[reg];
+             break;
+
+           case DW_CFA_undefined:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+             fs->regs.reg[reg].how = REG_UNSAVED;
+             break;
+
+           case DW_CFA_same_value:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+             fs->regs.reg[reg].how = REG_UNMODIFIED;
+             break;
+
+           case DW_CFA_register:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+             fs->regs.reg[reg].loc.reg = utmp;
+             break;
+
+           case DW_CFA_remember_state:
+             {
+               struct dwarf2_frame_state_reg_info *new_rs;
+
+               new_rs = XMALLOC (struct dwarf2_frame_state_reg_info);
+               *new_rs = fs->regs;
+               fs->regs.reg = dwarf2_frame_state_copy_regs (&fs->regs);
+               fs->regs.prev = new_rs;
+             }
+             break;
+
+           case DW_CFA_restore_state:
+             {
+               struct dwarf2_frame_state_reg_info *old_rs = fs->regs.prev;
+
+               gdb_assert (old_rs);
+
+               xfree (fs->regs.reg);
+               fs->regs = *old_rs;
+               xfree (old_rs);
+             }
+             break;
+
+           case DW_CFA_def_cfa:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             fs->cfa_offset = utmp;
+             fs->cfa_how = CFA_REG_OFFSET;
+             break;
+
+           case DW_CFA_def_cfa_register:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg);
+             fs->cfa_how = CFA_REG_OFFSET;
+             break;
+
+           case DW_CFA_def_cfa_offset:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_offset);
+             /* cfa_how deliberately not set.  */
+             break;
+
+           case DW_CFA_def_cfa_expression:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_exp_len);
+             fs->cfa_exp = insn_ptr;
+             fs->cfa_how = CFA_EXP;
+             insn_ptr += fs->cfa_exp_len;
+             break;
+
+           case DW_CFA_expression:
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+             dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             fs->regs.reg[reg].loc.exp = insn_ptr;
+             fs->regs.reg[reg].exp_len = utmp;
+             fs->regs.reg[reg].how = REG_SAVED_EXP;
+             insn_ptr += utmp;
+             break;
+
+           case DW_CFA_nop:
+             break;
+
+           case DW_CFA_GNU_args_size:
+             /* Ignored.  */
+             insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+             break;
+
+           default:
+             internal_error (__FILE__, __LINE__, "Unknown CFI encountered.");
+           }
+       }
+    }
+
+  /* Don't allow remember/restore between CIE and FDE programs.  */
+  dwarf2_frame_state_free_regs (fs->regs.prev);
+  fs->regs.prev = NULL;
+}
+
+struct dwarf2_frame_cache
+{
+  /* DWARF Call Frame Address.  */
+  CORE_ADDR cfa;
+
+  /* Saved registers, indexed by GDB register number, not by DWARF
+     register number.  */
+  struct dwarf2_frame_state_reg *reg;
+};
+
+static struct dwarf2_frame_cache *
+dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct cleanup *old_chain;
+  int num_regs = NUM_REGS + NUM_PSEUDO_REGS;
+  struct dwarf2_frame_cache *cache;
+  struct dwarf2_frame_state *fs;
+  struct dwarf2_fde *fde;
+  int reg;
+
+  if (*this_cache)
+    return *this_cache;
+
+  /* Allocate a new cache.  */
+  cache = FRAME_OBSTACK_ZALLOC (struct dwarf2_frame_cache);
+  cache->reg = FRAME_OBSTACK_CALLOC (num_regs, struct dwarf2_frame_state_reg);
+
+  /* Allocate and initialize the frame state.  */
+  fs = XMALLOC (struct dwarf2_frame_state);
+  memset (fs, 0, sizeof (struct dwarf2_frame_state));
+  old_chain = make_cleanup (dwarf2_frame_state_free, fs);
+
+  /* Unwind the PC.
+
+     Note that if NEXT_FRAME is never supposed to return (i.e. a call
+     to abort), the compiler might optimize away the instruction at
+     NEXT_FRAME's return address.  As a result the return address will
+     point at some random instruction, and the CFI for that
+     instruction is probably wortless to us.  GCC's unwinder solves
+     this problem by substracting 1 from the return address to get an
+     address in the middle of a presumed call instruction (or the
+     instruction in the associated delay slot).  This should only be
+     done for "normal" frames and not for resume-type frames (signal
+     handlers, sentinel frames, dummy frames).
+
+     We don't do what GCC's does here (yet).  It's not clear how
+     reliable the method is.  There's also a problem with finding the
+     right FDE; see the comment in dwarf_frame_p.  If dwarf_frame_p
+     selected this frame unwinder because it found the FDE for the
+     next function, using the adjusted return address might not yield
+     a FDE at all.  The problem isn't specific to DWARF CFI; other
+     unwinders loose in similar ways.  Therefore it's probably
+     acceptable to leave things slightly broken for now.  */
+  fs->pc = frame_pc_unwind (next_frame);
+
+  /* Find the correct FDE.  */
+  fde = dwarf2_frame_find_fde (&fs->pc);
+  gdb_assert (fde != NULL);
+
+  /* Extract any interesting information from the CIE.  */
+  fs->data_align = fde->cie->data_alignment_factor;
+  fs->code_align = fde->cie->code_alignment_factor;
+  fs->retaddr_column = fde->cie->return_address_register;
+
+  /* First decode all the insns in the CIE.  */
+  execute_cfa_program (fde->cie->initial_instructions,
+                      fde->cie->end, next_frame, fs);
+
+  /* Save the initialized register set.  */
+  fs->initial = fs->regs;
+  fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs);
+
+  /* Then decode the insns in the FDE up to our target PC.  */
+  execute_cfa_program (fde->instructions, fde->end, next_frame, fs);
+
+  /* Caclulate the CFA.  */
+  switch (fs->cfa_how)
+    {
+    case CFA_REG_OFFSET:
+      cache->cfa = read_reg (next_frame, fs->cfa_reg);
+      cache->cfa += fs->cfa_offset;
+      break;
+
+    case CFA_EXP:
+      cache->cfa =
+       execute_stack_op (fs->cfa_exp, fs->cfa_exp_len, next_frame, 0);
+      break;
+
+    default:
+      internal_error (__FILE__, __LINE__, "Unknown CFA rule.");
+    }
+
+  /* Save the register info in the cache.  */
+  for (reg = 0; reg < fs->regs.num_regs; reg++)
+    {
+      int regnum;
+
+      /* Skip the return address column.  */
+      if (reg == fs->retaddr_column)
+       /* NOTE: cagney/2003-06-07: Is this right?  What if the
+           RETADDR_COLUM corresponds to a real register (and, worse,
+           that isn't the PC_REGNUM)?  I'm guessing that the PC_REGNUM
+           further down is trying to handle this.  That can't be right
+           though - PC_REGNUM may not be valid (it can be -ve).  I
+           think, instead when RETADDR_COLUM isn't a real register, it
+           should map itself onto frame_pc_unwind.  */
+       continue;
+
+      /* Use the GDB register number as index.  */
+      regnum = DWARF2_REG_TO_REGNUM (reg);
+
+      if (regnum >= 0 && regnum < num_regs)
+       cache->reg[regnum] = fs->regs.reg[reg];
+    }
+
+  /* Store the location of the return addess.  If the return address
+     column (adjusted) is not the same as gdb's PC_REGNUM, then this
+     implies a copy from the ra column register.  */
+  if (fs->retaddr_column < fs->regs.num_regs
+      && fs->regs.reg[fs->retaddr_column].how != REG_UNSAVED)
+    {
+      /* See comment above about a possibly -ve PC_REGNUM.  If this
+         assertion fails, it's a problem with this code and not the
+         architecture.  */
+      gdb_assert (PC_REGNUM >= 0);
+      cache->reg[PC_REGNUM] = fs->regs.reg[fs->retaddr_column];
+    }
+  else
+    {
+      reg = DWARF2_REG_TO_REGNUM (fs->retaddr_column);
+      if (reg != PC_REGNUM)
+       {
+         /* See comment above about PC_REGNUM being -ve.  If this
+            assertion fails, it's a problem with this code and not
+            the architecture.  */
+         gdb_assert (PC_REGNUM >= 0);
+         cache->reg[PC_REGNUM].loc.reg = reg;
+         cache->reg[PC_REGNUM].how = REG_SAVED_REG;
+       }
+    }
+
+  do_cleanups (old_chain);
+
+  *this_cache = cache;
+  return cache;
+}
+
+static void
+dwarf2_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                     struct frame_id *this_id)
+{
+  struct dwarf2_frame_cache *cache =
+    dwarf2_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->cfa, frame_func_unwind (next_frame));
+}
+
+static void
+dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+                           int regnum, int *optimizedp,
+                           enum lval_type *lvalp, CORE_ADDR *addrp,
+                           int *realnump, void *valuep)
+{
+  struct dwarf2_frame_cache *cache =
+    dwarf2_frame_cache (next_frame, this_cache);
+
+  switch (cache->reg[regnum].how)
+    {
+    case REG_UNSAVED:
+      *optimizedp = 1;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (regnum == SP_REGNUM)
+       {
+         /* GCC defines the CFA as the value of the stack pointer
+            just before the call instruction is executed.  Do other
+            compilers use the same definition?  */
+         /* DWARF V3 Draft 7 p102: Typically, the CFA is defined to
+            be the value of the stack pointer at the call site in the
+            previous frame (which may be different from its value on
+            entry to the current frame).  */
+         /* DWARF V3 Draft 7 p103: The first column of the rules
+             defines the rule which computes the CFA value; it may be
+             either a register and a signed offset that are added
+             together or a DWARF expression that is evaluated.  */
+         /* FIXME: cagney/2003-07-07: I don't understand this.  The
+             CFI info should have provided unwind information for the
+             SP register and then pointed ->cfa_reg at it, not the
+             reverse.  Assuming that SP_REGNUM is !-ve, there is a
+             very real posibility that CFA is an offset from some
+             other register, having nothing to do with the unwound SP
+             value.  */
+         *optimizedp = 0;
+         if (valuep)
+           {
+             /* Store the value.  */
+             store_typed_address (valuep, builtin_type_void_data_ptr,
+                                  cache->cfa);
+           }
+       }
+      else if (valuep)
+       {
+         /* In some cases, for example %eflags on the i386, we have
+            to provide a sane value, even though this register wasn't
+            saved.  Assume we can get it from NEXT_FRAME.  */
+         frame_unwind_register (next_frame, regnum, valuep);
+       }
+      break;
+
+    case REG_SAVED_OFFSET:
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = cache->cfa + cache->reg[regnum].loc.offset;
+      *realnump = -1;
+      if (valuep)
+       {
+         /* Read the value in from memory.  */
+         read_memory (*addrp, valuep,
+                      register_size (current_gdbarch, regnum));
+       }
+      break;
+
+    case REG_SAVED_REG:
+      regnum = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg);
+      frame_register_unwind (next_frame, regnum,
+                            optimizedp, lvalp, addrp, realnump, valuep);
+      break;
+
+    case REG_SAVED_EXP:
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = execute_stack_op (cache->reg[regnum].loc.exp,
+                                cache->reg[regnum].exp_len,
+                                next_frame, cache->cfa);
+      *realnump = -1;
+      if (valuep)
+       {
+         /* Read the value in from memory.  */
+         read_memory (*addrp, valuep,
+                      register_size (current_gdbarch, regnum));
+       }
+      break;
+
+    case REG_UNMODIFIED:
+      frame_register_unwind (next_frame, regnum,
+                            optimizedp, lvalp, addrp, realnump, valuep);
+      break;
+
+    default:
+      internal_error (__FILE__, __LINE__, "Unknown register rule.");
+    }
+}
+
+static const struct frame_unwind dwarf2_frame_unwind =
+{
+  NORMAL_FRAME,
+  dwarf2_frame_this_id,
+  dwarf2_frame_prev_register
+};
+
+const struct frame_unwind *
+dwarf2_frame_p (CORE_ADDR pc)
+{
+  /* The way GDB works, this function can be called with PC just after
+     the last instruction of the function we're supposed to return the
+     unwind methods for.  In that case we won't find the correct FDE;
+     instead we find the FDE for the next function, or we won't find
+     an FDE at all.  There is a possible solution (see the comment in
+     dwarf2_frame_cache), GDB doesn't pass us enough information to
+     implement it.  */
+  if (dwarf2_frame_find_fde (&pc))
+    return &dwarf2_frame_unwind;
+
+  return NULL;
+}
+\f
+
+/* There is no explicitly defined relationship between the CFA and the
+   location of frame's local variables and arguments/parameters.
+   Therefore, frame base methods on this page should probably only be
+   used as a last resort, just to avoid printing total garbage as a
+   response to the "info frame" command.  */
+
+static CORE_ADDR
+dwarf2_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct dwarf2_frame_cache *cache =
+    dwarf2_frame_cache (next_frame, this_cache);
+
+  return cache->cfa;
+}
+
+static const struct frame_base dwarf2_frame_base =
+{
+  &dwarf2_frame_unwind,
+  dwarf2_frame_base_address,
+  dwarf2_frame_base_address,
+  dwarf2_frame_base_address
+};
+
+const struct frame_base *
+dwarf2_frame_base_p (CORE_ADDR pc)
+{
+  if (dwarf2_frame_find_fde (&pc))
+    return &dwarf2_frame_base;
+
+  return NULL;
+}
+\f
+/* A minimal decoding of DWARF2 compilation units.  We only decode
+   what's needed to get to the call frame information.  */
+
+struct comp_unit
+{
+  /* Keep the bfd convenient.  */
+  bfd *abfd;
+
+  struct objfile *objfile;
+
+  /* Linked list of CIEs for this object.  */
+  struct dwarf2_cie *cie;
+
+  /* Address size for this unit - from unit header.  */
+  unsigned char addr_size;
+
+  /* Pointer to the .debug_frame section loaded into memory.  */
+  char *dwarf_frame_buffer;
+
+  /* Length of the loaded .debug_frame section.  */
+  unsigned long dwarf_frame_size;
+
+  /* Pointer to the .debug_frame section.  */
+  asection *dwarf_frame_section;
+
+  /* Base for DW_EH_PE_datarel encodings.  */
+  bfd_vma dbase;
+};
+
+static unsigned int
+read_1_byte (bfd *bfd, char *buf)
+{
+  return bfd_get_8 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned int
+read_4_bytes (bfd *abfd, char *buf)
+{
+  return bfd_get_32 (abfd, (bfd_byte *) buf);
+}
+
+static ULONGEST
+read_8_bytes (bfd *abfd, char *buf)
+{
+  return bfd_get_64 (abfd, (bfd_byte *) buf);
+}
+
+static ULONGEST
+read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
+{
+  ULONGEST result;
+  unsigned int num_read;
+  int shift;
+  unsigned char byte;
+
+  result = 0;
+  shift = 0;
+  num_read = 0;
+
+  do
+    {
+      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+      buf++;
+      num_read++;
+      result |= ((byte & 0x7f) << shift);
+      shift += 7;
+    }
+  while (byte & 0x80);
+
+  *bytes_read_ptr = num_read;
+
+  return result;
+}
+
+static LONGEST
+read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
+{
+  LONGEST result;
+  int shift;
+  unsigned int num_read;
+  unsigned char byte;
+
+  result = 0;
+  shift = 0;
+  num_read = 0;
+
+  do
+    {
+      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+      buf++;
+      num_read++;
+      result |= ((byte & 0x7f) << shift);
+      shift += 7;
+    }
+  while (byte & 0x80);
+
+  if ((shift < 32) && (byte & 0x40))
+    result |= -(1 << shift);
+
+  *bytes_read_ptr = num_read;
+
+  return result;
+}
+
+static ULONGEST
+read_initial_length (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
+{
+  LONGEST result;
+
+  result = bfd_get_32 (abfd, (bfd_byte *) buf);
+  if (result == 0xffffffff)
+    {
+      result = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+      *bytes_read_ptr = 12;
+    }
+  else
+    *bytes_read_ptr = 4;
+
+  return result;
+}
+\f
+
+/* Pointer encoding helper functions.  */
+
+/* GCC supports exception handling based on DWARF2 CFI.  However, for
+   technical reasons, it encodes addresses in its FDE's in a different
+   way.  Several "pointer encodings" are supported.  The encoding
+   that's used for a particular FDE is determined by the 'R'
+   augmentation in the associated CIE.  The argument of this
+   augmentation is a single byte.  
+
+   The address can be encoded as 2 bytes, 4 bytes, 8 bytes, or as a
+   LEB128.  This is encoded in bits 0, 1 and 2.  Bit 3 encodes whether
+   the address is signed or unsigned.  Bits 4, 5 and 6 encode how the
+   address should be interpreted (absolute, relative to the current
+   position in the FDE, ...).  Bit 7, indicates that the address
+   should be dereferenced.  */
+
+static unsigned char
+encoding_for_size (unsigned int size)
+{
+  switch (size)
+    {
+    case 2:
+      return DW_EH_PE_udata2;
+    case 4:
+      return DW_EH_PE_udata4;
+    case 8:
+      return DW_EH_PE_udata8;
+    default:
+      internal_error (__FILE__, __LINE__, "Unsupported address size");
+    }
+}
+
+static unsigned int
+size_of_encoded_value (unsigned char encoding)
+{
+  if (encoding == DW_EH_PE_omit)
+    return 0;
+
+  switch (encoding & 0x07)
+    {
+    case DW_EH_PE_absptr:
+      return TYPE_LENGTH (builtin_type_void_data_ptr);
+    case DW_EH_PE_udata2:
+      return 2;
+    case DW_EH_PE_udata4:
+      return 4;
+    case DW_EH_PE_udata8:
+      return 8;
+    default:
+      internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
+    }
+}
+
+static CORE_ADDR
+read_encoded_value (struct comp_unit *unit, unsigned char encoding,
+                   char *buf, unsigned int *bytes_read_ptr)
+{
+  CORE_ADDR base;
+
+  /* GCC currently doesn't generate DW_EH_PE_indirect encodings for
+     FDE's.  */
+  if (encoding & DW_EH_PE_indirect)
+    internal_error (__FILE__, __LINE__, 
+                   "Unsupported encoding: DW_EH_PE_indirect");
+
+  switch (encoding & 0x70)
+    {
+    case DW_EH_PE_absptr:
+      base = 0;
+      break;
+    case DW_EH_PE_pcrel:
+      base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section);
+      base += (buf - unit->dwarf_frame_buffer);
+      break;
+    case DW_EH_PE_datarel:
+      base = unit->dbase;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
+    }
+
+  if ((encoding & 0x0f) == 0x00)
+    encoding |= encoding_for_size (TYPE_LENGTH(builtin_type_void_data_ptr));
+
+  switch (encoding & 0x0f)
+    {
+    case DW_EH_PE_udata2:
+      *bytes_read_ptr = 2;
+      return (base + bfd_get_16 (unit->abfd, (bfd_byte *) buf));
+    case DW_EH_PE_udata4:
+      *bytes_read_ptr = 4;
+      return (base + bfd_get_32 (unit->abfd, (bfd_byte *) buf));
+    case DW_EH_PE_udata8:
+      *bytes_read_ptr = 8;
+      return (base + bfd_get_64 (unit->abfd, (bfd_byte *) buf));
+    case DW_EH_PE_sdata2:
+      *bytes_read_ptr = 2;
+      return (base + bfd_get_signed_16 (unit->abfd, (bfd_byte *) buf));
+    case DW_EH_PE_sdata4:
+      *bytes_read_ptr = 4;
+      return (base + bfd_get_signed_32 (unit->abfd, (bfd_byte *) buf));
+    case DW_EH_PE_sdata8:
+      *bytes_read_ptr = 8;
+      return (base + bfd_get_signed_64 (unit->abfd, (bfd_byte *) buf));
+    default:
+      internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
+    }
+}
+\f
+
+/* GCC uses a single CIE for all FDEs in a .debug_frame section.
+   That's why we use a simple linked list here.  */
+
+static struct dwarf2_cie *
+find_cie (struct comp_unit *unit, ULONGEST cie_pointer)
+{
+  struct dwarf2_cie *cie = unit->cie;
+
+  while (cie)
+    {
+      if (cie->cie_pointer == cie_pointer)
+       return cie;
+
+      cie = cie->next;
+    }
+
+  return NULL;
+}
+
+static void
+add_cie (struct comp_unit *unit, struct dwarf2_cie *cie)
+{
+  cie->next = unit->cie;
+  unit->cie = cie;
+}
+
+/* Find the FDE for *PC.  Return a pointer to the FDE, and store the
+   inital location associated with it into *PC.  */
+
+static struct dwarf2_fde *
+dwarf2_frame_find_fde (CORE_ADDR *pc)
+{
+  struct objfile *objfile;
+
+  ALL_OBJFILES (objfile)
+    {
+      struct dwarf2_fde *fde;
+      CORE_ADDR offset;
+
+      offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+      
+      fde = objfile->sym_private;
+      while (fde)
+       {
+         if (*pc >= fde->initial_location + offset
+             && *pc < fde->initial_location + offset + fde->address_range)
+           {
+             *pc = fde->initial_location + offset;
+             return fde;
+           }
+
+         fde = fde->next;
+       }
+    }
+
+  return NULL;
+}
+
+static void
+add_fde (struct comp_unit *unit, struct dwarf2_fde *fde)
+{
+  fde->next = unit->objfile->sym_private;
+  unit->objfile->sym_private = fde;
+}
+
+#ifdef CC_HAS_LONG_LONG
+#define DW64_CIE_ID 0xffffffffffffffffULL
+#else
+#define DW64_CIE_ID ~0
+#endif
+
+/* Read a CIE or FDE in BUF and decode it.  */
+
+static char *
+decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
+{
+  LONGEST length;
+  unsigned int bytes_read;
+  int dwarf64_p = 0;
+  ULONGEST cie_id = DW_CIE_ID;
+  ULONGEST cie_pointer;
+  char *start = buf;
+  char *end;
+
+  length = read_initial_length (unit->abfd, buf, &bytes_read);
+  buf += bytes_read;
+  end = buf + length;
+
+  if (length == 0)
+    return end;
+
+  if (bytes_read == 12)
+    dwarf64_p = 1;
+
+  /* In a .eh_frame section, zero is used to distinguish CIEs from
+     FDEs.  */
+  if (eh_frame_p)
+    cie_id = 0;
+  else if (dwarf64_p)
+    cie_id = DW64_CIE_ID;
+
+  if (dwarf64_p)
+    {
+      cie_pointer = read_8_bytes (unit->abfd, buf);
+      buf += 8;
+    }
+  else
+    {
+      cie_pointer = read_4_bytes (unit->abfd, buf);
+      buf += 4;
+    }
+
+  if (cie_pointer == cie_id)
+    {
+      /* This is a CIE.  */
+      struct dwarf2_cie *cie;
+      char *augmentation;
+
+      /* Record the offset into the .debug_frame section of this CIE.  */
+      cie_pointer = start - unit->dwarf_frame_buffer;
+
+      /* Check whether we've already read it.  */
+      if (find_cie (unit, cie_pointer))
+       return end;
+
+      cie = (struct dwarf2_cie *)
+       obstack_alloc (&unit->objfile->psymbol_obstack,
+                      sizeof (struct dwarf2_cie));
+      cie->initial_instructions = NULL;
+      cie->cie_pointer = cie_pointer;
+
+      /* The encoding for FDE's in a normal .debug_frame section
+         depends on the target address size as specified in the
+         Compilation Unit Header.  */
+      cie->encoding = encoding_for_size (unit->addr_size);
+
+      /* Check version number.  */
+      gdb_assert (read_1_byte (unit->abfd, buf) == DW_CIE_VERSION);
+      buf += 1;
+
+      /* Interpret the interesting bits of the augmentation.  */
+      augmentation = buf;
+      buf = augmentation + strlen (augmentation) + 1;
+
+      /* The GCC 2.x "eh" augmentation has a pointer immediately
+         following the augmentation string, so it must be handled
+         first.  */
+      if (augmentation[0] == 'e' && augmentation[1] == 'h')
+       {
+         /* Skip.  */
+         buf += TYPE_LENGTH (builtin_type_void_data_ptr);
+         augmentation += 2;
+       }
+
+      cie->code_alignment_factor =
+       read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
+      buf += bytes_read;
+
+      cie->data_alignment_factor =
+       read_signed_leb128 (unit->abfd, buf, &bytes_read);
+      buf += bytes_read;
+
+      cie->return_address_register = read_1_byte (unit->abfd, buf);
+      buf += 1;
+
+      cie->saw_z_augmentation = (*augmentation == 'z');
+      if (cie->saw_z_augmentation)
+       {
+         ULONGEST length;
+
+         length = read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
+         buf += bytes_read;
+         cie->initial_instructions = buf + length;
+         augmentation++;
+       }
+
+      while (*augmentation)
+       {
+         /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+         if (*augmentation == 'L')
+           {
+             /* Skip.  */
+             buf++;
+             augmentation++;
+           }
+
+         /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+         else if (*augmentation == 'R')
+           {
+             cie->encoding = *buf++;
+             augmentation++;
+           }
+
+         /* "P" indicates a personality routine in the CIE augmentation.  */
+         else if (*augmentation == 'P')
+           {
+             /* Skip.  */
+             buf += size_of_encoded_value (*buf++);
+             augmentation++;
+           }
+
+         /* Otherwise we have an unknown augmentation.
+            Bail out unless we saw a 'z' prefix.  */
+         else
+           {
+             if (cie->initial_instructions == NULL)
+               return end;
+
+             /* Skip unknown augmentations.  */
+             buf = cie->initial_instructions;
+             break;
+           }
+       }
+
+      cie->initial_instructions = buf;
+      cie->end = end;
+
+      add_cie (unit, cie);
+    }
+  else
+    {
+      /* This is a FDE.  */
+      struct dwarf2_fde *fde;
+
+      if (eh_frame_p)
+       {
+         /* In an .eh_frame section, the CIE pointer is the delta
+             between the address within the FDE where the CIE pointer
+             is stored and the address of the CIE.  Convert it to an
+             offset into the .eh_frame section.  */
+         cie_pointer = buf - unit->dwarf_frame_buffer - cie_pointer;
+         cie_pointer -= (dwarf64_p ? 8 : 4);
+       }
+
+      fde = (struct dwarf2_fde *)
+       obstack_alloc (&unit->objfile->psymbol_obstack,
+                      sizeof (struct dwarf2_fde));
+      fde->cie = find_cie (unit, cie_pointer);
+      if (fde->cie == NULL)
+       {
+         decode_frame_entry (unit, unit->dwarf_frame_buffer + cie_pointer,
+                             eh_frame_p);
+         fde->cie = find_cie (unit, cie_pointer);
+       }
+
+      gdb_assert (fde->cie != NULL);
+
+      fde->initial_location =
+       read_encoded_value (unit, fde->cie->encoding, buf, &bytes_read);
+      buf += bytes_read;
+
+      fde->address_range =
+       read_encoded_value (unit, fde->cie->encoding & 0x0f, buf, &bytes_read);
+      buf += bytes_read;
+
+      /* A 'z' augmentation in the CIE implies the presence of an
+        augmentation field in the FDE as well.  The only thing known
+        to be in here at present is the LSDA entry for EH.  So we
+        can skip the whole thing.  */
+      if (fde->cie->saw_z_augmentation)
+       {
+         ULONGEST length;
+
+         length = read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
+         buf += bytes_read + length;
+       }
+
+      fde->instructions = buf;
+      fde->end = end;
+
+      add_fde (unit, fde);
+    }
+
+  return end;
+}
+\f
+
+/* FIXME: kettenis/20030504: This still needs to be integrated with
+   dwarf2read.c in a better way.  */
+
+/* Imported from dwarf2read.c.  */
+extern file_ptr dwarf_frame_offset;
+extern unsigned int dwarf_frame_size;
+extern asection *dwarf_frame_section;
+extern file_ptr dwarf_eh_frame_offset;
+extern unsigned int dwarf_eh_frame_size;
+extern asection *dwarf_eh_frame_section;
+
+/* Imported from dwarf2read.c.  */
+extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset,
+                                 unsigned int size, asection *sectp);
+
+void
+dwarf2_build_frame_info (struct objfile *objfile)
+{
+  struct comp_unit unit;
+  char *frame_ptr;
+
+  /* Build a minimal decoding of the DWARF2 compilation unit.  */
+  unit.abfd = objfile->obfd;
+  unit.objfile = objfile;
+  unit.addr_size = objfile->obfd->arch_info->bits_per_address / 8;
+  unit.dbase = 0;
+
+  /* First add the information from the .eh_frame section.  That way,
+     the FDEs from that section are searched last.  */
+  if (dwarf_eh_frame_offset)
+    {
+      asection *got;
+
+      unit.cie = NULL;
+      unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
+                                                    dwarf_eh_frame_offset,
+                                                    dwarf_eh_frame_size,
+                                                    dwarf_eh_frame_section);
+
+      unit.dwarf_frame_size = dwarf_eh_frame_size;
+      unit.dwarf_frame_section = dwarf_eh_frame_section;
+
+      /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base
+         that for the i386/amd64 target, which currently is the only
+         target in GCC that supports/uses the DW_EH_PE_datarel
+         encoding.  */
+      got = bfd_get_section_by_name (unit.abfd, ".got");
+      if (got)
+       unit.dbase = got->vma;
+
+      frame_ptr = unit.dwarf_frame_buffer;
+      while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size)
+       frame_ptr = decode_frame_entry (&unit, frame_ptr, 1);
+    }
+
+  if (dwarf_frame_offset)
+    {
+      unit.cie = NULL;
+      unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
+                                                    dwarf_frame_offset,
+                                                    dwarf_frame_size,
+                                                    dwarf_frame_section);
+      unit.dwarf_frame_size = dwarf_frame_size;
+      unit.dwarf_frame_section = dwarf_frame_section;
+
+      frame_ptr = unit.dwarf_frame_buffer;
+      while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size)
+       frame_ptr = decode_frame_entry (&unit, frame_ptr, 0);
+    }
+}
diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h
new file mode 100644 (file)
index 0000000..4b4c1a5
--- /dev/null
@@ -0,0 +1,43 @@
+/* Frame unwinder for frames with DWARF Call Frame Information.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Mark Kettenis.
+
+   This file is part of GDB.
+
+   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.  */
+
+#ifndef DWARF2_FRAME_H
+#define DWARF2_FRAME_H 1
+
+struct objfile;
+
+/* Return the frame unwind methods for the function that contains PC,
+   or NULL if it can't be handled by DWARF CFI frame unwinder.  */
+
+const struct frame_unwind *dwarf2_frame_p (CORE_ADDR pc);
+
+/* Return the frame base methods for the function that contains PC, or
+   NULL if it can't be handled by the DWARF CFI frame unwinder.  */
+
+const struct frame_base *dwarf2_frame_base_p (CORE_ADDR pc);
+
+/* Register the DWARF CFI for OBJFILE.  */
+
+void dwarf2_frame_build_info (struct objfile *objfile);
+
+#endif /* dwarf2-frame.h */
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
new file mode 100644 (file)
index 0000000..61931c6
--- /dev/null
@@ -0,0 +1,219 @@
+/* GNU/Linux native-dependent code common to multiple platforms.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+
+#include "gdb_wait.h"
+#include <sys/ptrace.h>
+
+#include "linux-nat.h"
+
+/* If the system headers did not provide the constants, hard-code the normal
+   values.  */
+#ifndef PTRACE_EVENT_FORK
+
+#define PTRACE_SETOPTIONS      0x4200
+#define PTRACE_GETEVENTMSG     0x4201
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD  0x00000001
+#define PTRACE_O_TRACEFORK     0x00000002
+#define PTRACE_O_TRACEVFORK    0x00000004
+#define PTRACE_O_TRACECLONE    0x00000008
+#define PTRACE_O_TRACEEXEC     0x00000010
+
+/* Wait extended result codes for the above trace options.  */
+#define PTRACE_EVENT_FORK      1
+#define PTRACE_EVENT_VFORK     2
+#define PTRACE_EVENT_CLONE     3
+#define PTRACE_EVENT_EXEC      4
+
+#endif /* PTRACE_EVENT_FORK */
+
+/* We can't always assume that this flag is available, but all systems
+   with the ptrace event handlers also have __WALL, so it's safe to use
+   here.  */
+#ifndef __WALL
+#define __WALL          0x40000000 /* Wait for any child.  */
+#endif
+
+struct simple_pid_list
+{
+  int pid;
+  struct simple_pid_list *next;
+};
+struct simple_pid_list *stopped_pids;
+
+/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACEFORK
+   can not be used, 1 if it can.  */
+
+static int linux_supports_tracefork_flag = -1;
+
+\f
+/* Trivial list manipulation functions to keep track of a list of
+   new stopped processes.  */
+static void
+add_to_pid_list (struct simple_pid_list **listp, int pid)
+{
+  struct simple_pid_list *new_pid = xmalloc (sizeof (struct simple_pid_list));
+  new_pid->pid = pid;
+  new_pid->next = *listp;
+  *listp = new_pid;
+}
+
+static int
+pull_pid_from_list (struct simple_pid_list **listp, int pid)
+{
+  struct simple_pid_list **p;
+
+  for (p = listp; *p != NULL; p = &(*p)->next)
+    if ((*p)->pid == pid)
+      {
+       struct simple_pid_list *next = (*p)->next;
+       xfree (*p);
+       *p = next;
+       return 1;
+      }
+  return 0;
+}
+
+void
+linux_record_stopped_pid (int pid)
+{
+  add_to_pid_list (&stopped_pids, pid);
+}
+
+\f
+/* A helper function for linux_test_for_tracefork, called after fork ().  */
+
+static void
+linux_tracefork_child (void)
+{
+  int ret;
+
+  ptrace (PTRACE_TRACEME, 0, 0, 0);
+  kill (getpid (), SIGSTOP);
+  fork ();
+  exit (0);
+}
+
+/* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.  We
+   create a child process, attach to it, use PTRACE_SETOPTIONS to enable
+   fork tracing, and let it fork.  If the process exits, we assume that
+   we can't use TRACEFORK; if we get the fork notification, and we can
+   extract the new child's PID, then we assume that we can.  */
+
+static void
+linux_test_for_tracefork (void)
+{
+  int child_pid, ret, status;
+  long second_pid;
+
+  child_pid = fork ();
+  if (child_pid == -1)
+    perror_with_name ("linux_test_for_tracefork: fork");
+
+  if (child_pid == 0)
+    linux_tracefork_child ();
+
+  ret = waitpid (child_pid, &status, 0);
+  if (ret == -1)
+    perror_with_name ("linux_test_for_tracefork: waitpid");
+  else if (ret != child_pid)
+    error ("linux_test_for_tracefork: waitpid: unexpected result %d.", ret);
+  if (! WIFSTOPPED (status))
+    error ("linux_test_for_tracefork: waitpid: unexpected status %d.", status);
+
+  linux_supports_tracefork_flag = 0;
+
+  ret = ptrace (PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACEFORK);
+  if (ret != 0)
+    {
+      ptrace (PTRACE_KILL, child_pid, 0, 0);
+      waitpid (child_pid, &status, 0);
+      return;
+    }
+
+  ptrace (PTRACE_CONT, child_pid, 0, 0);
+  ret = waitpid (child_pid, &status, 0);
+  if (ret == child_pid && WIFSTOPPED (status)
+      && status >> 16 == PTRACE_EVENT_FORK)
+    {
+      second_pid = 0;
+      ret = ptrace (PTRACE_GETEVENTMSG, child_pid, 0, &second_pid);
+      if (ret == 0 && second_pid != 0)
+       {
+         int second_status;
+
+         linux_supports_tracefork_flag = 1;
+         waitpid (second_pid, &second_status, 0);
+         ptrace (PTRACE_DETACH, second_pid, 0, 0);
+       }
+    }
+
+  if (WIFSTOPPED (status))
+    {
+      ptrace (PTRACE_DETACH, child_pid, 0, 0);
+      waitpid (child_pid, &status, 0);
+    }
+}
+
+/* Return non-zero iff we have tracefork functionality available.
+   This function also sets linux_supports_tracefork_flag.  */
+
+static int
+linux_supports_tracefork (void)
+{
+  if (linux_supports_tracefork_flag == -1)
+    linux_test_for_tracefork ();
+  return linux_supports_tracefork_flag;
+}
+
+\f
+int
+child_insert_fork_catchpoint (int pid)
+{
+  if (linux_supports_tracefork ())
+    error ("Fork catchpoints have not been implemented yet.");
+  else
+    error ("Your system does not support fork catchpoints.");
+}
+
+int
+child_insert_vfork_catchpoint (int pid)
+{
+  if (linux_supports_tracefork ())
+    error ("Vfork catchpoints have not been implemented yet.");
+  else
+    error ("Your system does not support vfork catchpoints.");
+}
+
+int
+child_insert_exec_catchpoint (int pid)
+{
+  if (linux_supports_tracefork ())
+    error ("Exec catchpoints have not been implemented yet.");
+  else
+    error ("Your system does not support exec catchpoints.");
+}
+
+
diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
new file mode 100644 (file)
index 0000000..b0d9600
--- /dev/null
@@ -0,0 +1,73 @@
+/* Native debugging support for GNU/Linux (LWP layer).
+   Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* Structure describing an LWP.  */
+
+struct lwp_info
+{
+  /* The process id of the LWP.  This is a combination of the LWP id
+     and overall process id.  */
+  ptid_t ptid;
+
+  /* Non-zero if this LWP is cloned.  In this context "cloned" means
+     that the LWP is reporting to its parent using a signal other than
+     SIGCHLD.  */
+  int cloned;
+
+  /* Non-zero if we sent this LWP a SIGSTOP (but the LWP didn't report
+     it back yet).  */
+  int signalled;
+
+  /* Non-zero if this LWP is stopped.  */
+  int stopped;
+
+  /* Non-zero if this LWP will be/has been resumed.  Note that an LWP
+     can be marked both as stopped and resumed at the same time.  This
+     happens if we try to resume an LWP that has a wait status
+     pending.  We shouldn't let the LWP run until that wait status has
+     been processed, but we should not report that wait status if GDB
+     didn't try to let the LWP run.  */
+  int resumed;
+
+  /* If non-zero, a pending wait status.  */
+  int status;
+
+  /* Non-zero if we were stepping this LWP.  */
+  int step;
+
+  /* Next LWP in list.  */
+  struct lwp_info *next;
+};
+
+/* Read/write to target memory via the Linux kernel's "proc file
+   system".  */
+struct mem_attrib;
+struct target_ops;
+
+extern int linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len,
+                                  int write, struct mem_attrib *attrib,
+                                  struct target_ops *target);
+
+extern void linux_record_stopped_pid (int pid);
+
+/* Iterator function for lin-lwp's lwp list.  */
+struct lwp_info *iterate_over_lwps (int (*callback) (struct lwp_info *, 
+                                                    void *), 
+                                   void *data);
diff --git a/gdb/remote-fileio.c b/gdb/remote-fileio.c
new file mode 100644 (file)
index 0000000..fd57617
--- /dev/null
@@ -0,0 +1,1379 @@
+/* Remote File-I/O communications
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* See the GDB User Guide for details of the GDB remote protocol. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include "remote.h"
+#include "gdb/fileio.h"
+#include "gdb_wait.h"
+#include "gdb_stat.h"
+#include "remote-fileio.h"
+
+#include <fcntl.h>
+#include <sys/time.h>
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>                /* For cygwin_conv_to_full_posix_path.  */
+#endif
+#include <signal.h>
+
+static struct {
+  int *fd_map;
+  int fd_map_size;
+} remote_fio_data;
+
+#define FIO_FD_INVALID         -1
+#define FIO_FD_CONSOLE_IN      -2
+#define FIO_FD_CONSOLE_OUT     -3
+
+static int remote_fio_system_call_allowed = 0;
+
+static int
+remote_fileio_init_fd_map (void)
+{
+  int i;
+
+  if (!remote_fio_data.fd_map)
+    {
+      remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int));
+      remote_fio_data.fd_map_size = 10;
+      remote_fio_data.fd_map[0] = FIO_FD_CONSOLE_IN;
+      remote_fio_data.fd_map[1] = FIO_FD_CONSOLE_OUT;
+      remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT;
+      for (i = 3; i < 10; ++i)
+        remote_fio_data.fd_map[i] = FIO_FD_INVALID;
+    }
+  return 3;
+}
+
+static int
+remote_fileio_resize_fd_map (void)
+{
+  if (!remote_fio_data.fd_map)
+    return remote_fileio_init_fd_map ();
+  remote_fio_data.fd_map_size += 10;
+  remote_fio_data.fd_map =
+    (int *) xrealloc (remote_fio_data.fd_map,
+                     remote_fio_data.fd_map_size * sizeof (int));
+  return remote_fio_data.fd_map_size - 10;
+}
+
+static int
+remote_fileio_next_free_fd (void)
+{
+  int i;
+
+  for (i = 0; i < remote_fio_data.fd_map_size; ++i)
+    if (remote_fio_data.fd_map[i] == FIO_FD_INVALID)
+      return i;
+  return remote_fileio_resize_fd_map ();
+}
+
+static int
+remote_fileio_fd_to_targetfd (int fd)
+{
+  int target_fd = remote_fileio_next_free_fd ();
+  remote_fio_data.fd_map[target_fd] = fd;
+  return target_fd;
+}
+
+static int
+remote_fileio_map_fd (int target_fd)
+{
+  remote_fileio_init_fd_map ();
+  if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size)
+    return FIO_FD_INVALID;
+  return remote_fio_data.fd_map[target_fd];
+}
+
+static void
+remote_fileio_close_target_fd (int target_fd)
+{
+  remote_fileio_init_fd_map ();
+  if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size)
+    remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID;
+}
+
+static int
+remote_fileio_oflags_to_host (long flags)
+{
+  int hflags = 0;
+
+  if (flags & FILEIO_O_CREAT)
+    hflags |= O_CREAT;
+  if (flags & FILEIO_O_EXCL)
+    hflags |= O_EXCL;
+  if (flags & FILEIO_O_TRUNC)
+    hflags |= O_TRUNC;
+  if (flags & FILEIO_O_APPEND)
+    hflags |= O_APPEND;
+  if (flags & FILEIO_O_RDONLY)
+    hflags |= O_RDONLY;
+  if (flags & FILEIO_O_WRONLY)
+    hflags |= O_WRONLY;
+  if (flags & FILEIO_O_RDWR)
+    hflags |= O_RDWR;
+/* On systems supporting binary and text mode, always open files in
+   binary mode. */
+#ifdef O_BINARY
+  hflags |= O_BINARY;
+#endif
+  return hflags;
+}
+
+static mode_t
+remote_fileio_mode_to_host (long mode, int open_call)
+{
+  mode_t hmode = 0;
+
+  if (!open_call)
+    {
+      if (mode & FILEIO_S_IFREG)
+       hmode |= S_IFREG;
+      if (mode & FILEIO_S_IFDIR)
+       hmode |= S_IFDIR;
+      if (mode & FILEIO_S_IFCHR)
+       hmode |= S_IFCHR;
+    }
+  if (mode & FILEIO_S_IRUSR)
+    hmode |= S_IRUSR;
+  if (mode & FILEIO_S_IWUSR)
+    hmode |= S_IWUSR;
+  if (mode & FILEIO_S_IXUSR)
+    hmode |= S_IXUSR;
+  if (mode & FILEIO_S_IRGRP)
+    hmode |= S_IRGRP;
+  if (mode & FILEIO_S_IWGRP)
+    hmode |= S_IWGRP;
+  if (mode & FILEIO_S_IXGRP)
+    hmode |= S_IXGRP;
+  if (mode & FILEIO_S_IROTH)
+    hmode |= S_IROTH;
+  if (mode & FILEIO_S_IWOTH)
+    hmode |= S_IWOTH;
+  if (mode & FILEIO_S_IXOTH)
+    hmode |= S_IXOTH;
+  return hmode;
+}
+
+static LONGEST
+remote_fileio_mode_to_target (mode_t mode)
+{
+  mode_t tmode = 0;
+
+  if (mode & S_IFREG)
+    tmode |= FILEIO_S_IFREG;
+  if (mode & S_IFDIR)
+    tmode |= FILEIO_S_IFDIR;
+  if (mode & S_IFCHR)
+    tmode |= FILEIO_S_IFCHR;
+  if (mode & S_IRUSR)
+    tmode |= FILEIO_S_IRUSR;
+  if (mode & S_IWUSR)
+    tmode |= FILEIO_S_IWUSR;
+  if (mode & S_IXUSR)
+    tmode |= FILEIO_S_IXUSR;
+  if (mode & S_IRGRP)
+    tmode |= FILEIO_S_IRGRP;
+  if (mode & S_IWGRP)
+    tmode |= FILEIO_S_IWGRP;
+  if (mode & S_IXGRP)
+    tmode |= FILEIO_S_IXGRP;
+  if (mode & S_IROTH)
+    tmode |= FILEIO_S_IROTH;
+  if (mode & S_IWOTH)
+    tmode |= FILEIO_S_IWOTH;
+  if (mode & S_IXOTH)
+    tmode |= FILEIO_S_IXOTH;
+  return tmode;
+}
+
+static int
+remote_fileio_errno_to_target (int error)
+{
+  switch (error)
+    {
+      case EPERM:
+        return FILEIO_EPERM;
+      case ENOENT:
+        return FILEIO_ENOENT;
+      case EINTR:
+        return FILEIO_EINTR;
+      case EIO:
+        return FILEIO_EIO;
+      case EBADF:
+        return FILEIO_EBADF;
+      case EACCES:
+        return FILEIO_EACCES;
+      case EFAULT:
+        return FILEIO_EFAULT;
+      case EBUSY:
+        return FILEIO_EBUSY;
+      case EEXIST:
+        return FILEIO_EEXIST;
+      case ENODEV:
+        return FILEIO_ENODEV;
+      case ENOTDIR:
+        return FILEIO_ENOTDIR;
+      case EISDIR:
+        return FILEIO_EISDIR;
+      case EINVAL:
+        return FILEIO_EINVAL;
+      case ENFILE:
+        return FILEIO_ENFILE;
+      case EMFILE:
+        return FILEIO_EMFILE;
+      case EFBIG:
+        return FILEIO_EFBIG;
+      case ENOSPC:
+        return FILEIO_ENOSPC;
+      case ESPIPE:
+        return FILEIO_ESPIPE;
+      case EROFS:
+        return FILEIO_EROFS;
+      case ENOSYS:
+        return FILEIO_ENOSYS;
+      case ENAMETOOLONG:
+        return FILEIO_ENAMETOOLONG;
+    }
+  return FILEIO_EUNKNOWN;
+}
+
+static int
+remote_fileio_seek_flag_to_host (long num, int *flag)
+{
+  if (!flag)
+    return 0;
+  switch (num)
+    {
+      case FILEIO_SEEK_SET:
+        *flag = SEEK_SET;
+       break;
+      case FILEIO_SEEK_CUR:
+        *flag =  SEEK_CUR;
+       break;
+      case FILEIO_SEEK_END:
+        *flag =  SEEK_END;
+       break;
+      default:
+        return -1;
+    }
+  return 0;
+}
+
+static int
+remote_fileio_extract_long (char **buf, LONGEST *retlong)
+{
+  char *c;
+  int sign = 1;
+
+  if (!buf || !*buf || !**buf || !retlong)
+    return -1;
+  c = strchr (*buf, ',');
+  if (c)
+    *c++ = '\0';
+  else
+    c = strchr (*buf, '\0');
+  while (strchr ("+-", **buf))
+    {
+      if (**buf == '-')
+       sign = -sign;
+      ++*buf;
+    }
+  for (*retlong = 0; **buf; ++*buf)
+    {
+      *retlong <<= 4;
+      if (**buf >= '0' && **buf <= '9')
+        *retlong += **buf - '0';
+      else if (**buf >= 'a' && **buf <= 'f')
+        *retlong += **buf - 'a' + 10;
+      else if (**buf >= 'A' && **buf <= 'F')
+        *retlong += **buf - 'A' + 10;
+      else
+        return -1;
+    }
+  *retlong *= sign;
+  *buf = c;
+  return 0;
+}
+
+static int
+remote_fileio_extract_int (char **buf, long *retint)
+{
+  int ret;
+  LONGEST retlong;
+
+  if (!retint)
+    return -1;
+  ret = remote_fileio_extract_long (buf, &retlong);
+  if (!ret)
+    *retint = (long) retlong;
+  return ret;
+}
+
+static int
+remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length)
+{
+  char *c;
+  LONGEST retlong;
+
+  if (!buf || !*buf || !**buf || !ptrval || !length)
+    return -1;
+  c = strchr (*buf, '/');
+  if (!c)
+    return -1;
+  *c++ = '\0';
+  if (remote_fileio_extract_long (buf, &retlong))
+    return -1;
+  *ptrval = (CORE_ADDR) retlong;
+  *buf = c;
+  if (remote_fileio_extract_long (buf, &retlong))
+    return -1;
+  *length = (int) retlong;
+  return 0;
+}
+
+/* Convert to big endian */
+static void
+remote_fileio_to_be (LONGEST num, char *buf, int bytes)
+{
+  int i;
+
+  for (i = 0; i < bytes; ++i)
+    buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff;
+}
+
+static void
+remote_fileio_to_fio_int (long num, fio_int_t fnum)
+{
+  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_uint (long num, fio_uint_t fnum)
+{
+  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_mode (mode_t num, fio_mode_t fnum)
+{
+  remote_fileio_to_be (remote_fileio_mode_to_target(num), (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_time (time_t num, fio_time_t fnum)
+{
+  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_long (LONGEST num, fio_long_t fnum)
+{
+  remote_fileio_to_be (num, (char *) fnum, 8);
+}
+
+static void
+remote_fileio_to_fio_ulong (LONGEST num, fio_ulong_t fnum)
+{
+  remote_fileio_to_be (num, (char *) fnum, 8);
+}
+
+static void
+remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst)
+{
+  /* `st_dev' is set in the calling function */
+  remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino);
+  remote_fileio_to_fio_mode (st->st_mode, fst->fst_mode);
+  remote_fileio_to_fio_uint ((long) st->st_nlink, fst->fst_nlink);
+  remote_fileio_to_fio_uint ((long) st->st_uid, fst->fst_uid);
+  remote_fileio_to_fio_uint ((long) st->st_gid, fst->fst_gid);
+  remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev);
+  remote_fileio_to_fio_ulong ((LONGEST) st->st_size, fst->fst_size);
+  remote_fileio_to_fio_ulong ((LONGEST) st->st_blksize, fst->fst_blksize);
+  remote_fileio_to_fio_ulong ((LONGEST) st->st_blocks, fst->fst_blocks);
+  remote_fileio_to_fio_time (st->st_atime, fst->fst_atime);
+  remote_fileio_to_fio_time (st->st_mtime, fst->fst_mtime);
+  remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime);
+}
+
+static void
+remote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv)
+{
+  remote_fileio_to_fio_time (tv->tv_sec, ftv->ftv_sec);
+  remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec);
+}
+
+static int remote_fio_ctrl_c_flag = 0;
+static int remote_fio_no_longjmp = 0;
+
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+static struct sigaction remote_fio_sa;
+static struct sigaction remote_fio_osa;
+#else
+static void (*remote_fio_ofunc)(int);
+#endif
+
+static void
+remote_fileio_sig_init (void)
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  remote_fio_sa.sa_handler = SIG_IGN;
+  sigemptyset (&remote_fio_sa.sa_mask);
+  remote_fio_sa.sa_flags = 0;
+  sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa);
+#else
+  remote_fio_ofunc = signal (SIGINT, SIG_IGN);
+#endif
+}
+
+static void
+remote_fileio_sig_set (void (*sigint_func)(int))
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  remote_fio_sa.sa_handler = sigint_func;
+  sigemptyset (&remote_fio_sa.sa_mask);
+  remote_fio_sa.sa_flags = 0;
+  sigaction (SIGINT, &remote_fio_sa, NULL);
+#else
+  signal (SIGINT, sigint_func);
+#endif
+}
+
+static void
+remote_fileio_sig_exit (void)
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  sigaction (SIGINT, &remote_fio_osa, NULL);
+#else
+  signal (SIGINT, remote_fio_ofunc);
+#endif
+}
+
+static void
+remote_fileio_ctrl_c_signal_handler (int signo)
+{
+  remote_fileio_sig_set (SIG_IGN);
+  remote_fio_ctrl_c_flag = 1;
+  if (!remote_fio_no_longjmp)
+    throw_exception (RETURN_QUIT);
+  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
+}
+
+static void
+remote_fileio_reply (int retcode, int error)
+{
+  char buf[32];
+
+  remote_fileio_sig_set (SIG_IGN);
+  strcpy (buf, "F");
+  if (retcode < 0)
+    {
+      strcat (buf, "-");
+      retcode = -retcode;
+    }
+  sprintf (buf + strlen (buf), "%x", retcode);
+  if (error || remote_fio_ctrl_c_flag)
+    {
+      if (error && remote_fio_ctrl_c_flag)
+        error = FILEIO_EINTR;
+      if (error < 0)
+        {
+         strcat (buf, "-");
+         error = -error;
+       }
+      sprintf (buf + strlen (buf), ",%x", error);
+      if (remote_fio_ctrl_c_flag)
+        strcat (buf, ",C");
+    }
+  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
+  putpkt (buf);
+}
+
+static void
+remote_fileio_ioerror (void)
+{
+  remote_fileio_reply (-1, FILEIO_EIO);
+}
+
+static void
+remote_fileio_badfd (void)
+{
+  remote_fileio_reply (-1, FILEIO_EBADF);
+}
+
+static void
+remote_fileio_return_errno (int retcode)
+{
+  remote_fileio_reply (retcode,
+                      retcode < 0 ? remote_fileio_errno_to_target (errno) : 0);
+}
+
+static void
+remote_fileio_return_success (int retcode)
+{
+  remote_fileio_reply (retcode, 0);
+}
+
+/* Wrapper function for remote_write_bytes() which has the disadvantage to
+   write only one packet, regardless of the requested number of bytes to
+   transfer.  This wrapper calls remote_write_bytes() as often as needed. */
+static int
+remote_fileio_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
+{
+  int ret = 0, written;
+
+  while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0)
+    {
+      len -= written;
+      memaddr += written;
+      myaddr += written;
+      ret += written;
+    }
+  return ret;
+}
+
+static void
+remote_fileio_func_open (char *buf)
+{
+  CORE_ADDR ptrval;
+  int length, retlength;
+  long num;
+  int flags, fd;
+  mode_t mode;
+  char *pathname;
+  struct stat st;
+
+  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* 2. Parameter: open flags */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  flags = remote_fileio_oflags_to_host (num);
+  /* 3. Parameter: open mode */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  mode = remote_fileio_mode_to_host (num, 1);
+
+  /* Request pathname using 'm' packet */
+  pathname = alloca (length);
+  retlength = remote_read_bytes (ptrval, pathname, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  /* Check if pathname exists and is not a regular file or directory.  If so,
+     return an appropriate error code.  Same for trying to open directories
+     for writing. */
+  if (!stat (pathname, &st))
+    {
+      if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
+       {
+         remote_fileio_reply (-1, FILEIO_ENODEV);
+         return;
+       }
+      if (S_ISDIR (st.st_mode)
+         && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR))
+       {
+         remote_fileio_reply (-1, FILEIO_EISDIR);
+         return;
+       }
+    }
+
+  remote_fio_no_longjmp = 1;
+  fd = open (pathname, flags, mode);
+  if (fd < 0)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+
+  fd = remote_fileio_fd_to_targetfd (fd);
+  remote_fileio_return_success (fd);
+}
+
+static void
+remote_fileio_func_close (char *buf)
+{
+  long num;
+  int fd;
+
+  /* Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  fd = remote_fileio_map_fd ((int) num);
+  if (fd == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd))
+    remote_fileio_return_errno (-1);
+  remote_fileio_close_target_fd ((int) num);
+  remote_fileio_return_success (0);
+}
+
+static void
+remote_fileio_func_read (char *buf)
+{
+  long target_fd, num;
+  LONGEST lnum;
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  char *buffer;
+  size_t length;
+  off_t old_offset, new_offset;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  fd = remote_fileio_map_fd ((int) target_fd);
+  if (fd == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  /* 2. Parameter: buffer pointer */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+  /* 3. Parameter: buffer length */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  length = (size_t) num;
+
+  switch (fd)
+    {
+      case FIO_FD_CONSOLE_OUT:
+       remote_fileio_badfd ();
+       return;
+      case FIO_FD_CONSOLE_IN:
+       {
+         static char *remaining_buf = NULL;
+         static int remaining_length = 0;
+
+         buffer = (char *) xmalloc (32768);
+         if (remaining_buf)
+           {
+             remote_fio_no_longjmp = 1;
+             if (remaining_length > length)
+               {
+                 memcpy (buffer, remaining_buf, length);
+                 memmove (remaining_buf, remaining_buf + length,
+                          remaining_length - length);
+                 remaining_length -= length;
+                 ret = length;
+               }
+             else
+               {
+                 memcpy (buffer, remaining_buf, remaining_length);
+                 xfree (remaining_buf);
+                 remaining_buf = NULL;
+                 ret = remaining_length;
+               }
+           }
+         else
+           {
+             ret = ui_file_read (gdb_stdtargin, buffer, 32767);
+             remote_fio_no_longjmp = 1;
+             if (ret > 0 && (size_t)ret > length)
+               {
+                 remaining_buf = (char *) xmalloc (ret - length);
+                 remaining_length = ret - length;
+                 memcpy (remaining_buf, buffer + length, remaining_length);
+                 ret = length;
+               }
+           }
+       }
+       break;
+      default:
+       buffer = (char *) xmalloc (length);
+       /* POSIX defines EINTR behaviour of read in a weird way.  It's allowed
+          for read() to return -1 even if "some" bytes have been read.  It
+          has been corrected in SUSv2 but that doesn't help us much...
+          Therefore a complete solution must check how many bytes have been
+          read on EINTR to return a more reliable value to the target */
+       old_offset = lseek (fd, 0, SEEK_CUR);
+       remote_fio_no_longjmp = 1;
+       ret = read (fd, buffer, length);
+       if (ret < 0 && errno == EINTR)
+         {
+           new_offset = lseek (fd, 0, SEEK_CUR);
+           /* If some data has been read, return the number of bytes read.
+              The Ctrl-C flag is set in remote_fileio_reply() anyway */
+           if (old_offset != new_offset)
+             ret = new_offset - old_offset;
+         }
+       break;
+    }
+
+  if (ret > 0)
+    {
+      retlength = remote_fileio_write_bytes (ptrval, buffer, ret);
+      if (retlength != ret)
+       ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */
+    }
+
+  if (ret < 0)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+
+  xfree (buffer);
+}
+
+static void
+remote_fileio_func_write (char *buf)
+{
+  long target_fd, num;
+  LONGEST lnum;
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  char *buffer;
+  size_t length;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  fd = remote_fileio_map_fd ((int) target_fd);
+  if (fd == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  /* 2. Parameter: buffer pointer */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+  /* 3. Parameter: buffer length */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  length = (size_t) num;
+    
+  buffer = (char *) xmalloc (length);
+  retlength = remote_read_bytes (ptrval, buffer, length);
+  if (retlength != length)
+    {
+      xfree (buffer);
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  switch (fd)
+    {
+      case FIO_FD_CONSOLE_IN:
+       remote_fileio_badfd ();
+       return;
+      case FIO_FD_CONSOLE_OUT:
+       ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr, buffer,
+                      length);
+       gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr);
+       ret = length;
+       break;
+      default:
+       ret = write (fd, buffer, length);
+       if (ret < 0 && errno == EACCES)
+         errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/
+       break;
+    }
+
+  if (ret < 0)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+
+  xfree (buffer);
+}
+
+static void
+remote_fileio_func_lseek (char *buf)
+{
+  long num;
+  LONGEST lnum;
+  int fd, flag;
+  off_t offset, ret;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  fd = remote_fileio_map_fd ((int) num);
+  if (fd == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
+    {
+      remote_fileio_reply (-1, FILEIO_ESPIPE);
+      return;
+    }
+
+  /* 2. Parameter: offset */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  offset = (off_t) lnum;
+  /* 3. Parameter: flag */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if (remote_fileio_seek_flag_to_host (num, &flag))
+    {
+      remote_fileio_reply (-1, FILEIO_EINVAL);
+      return;
+    }
+  
+  remote_fio_no_longjmp = 1;
+  ret = lseek (fd, offset, flag);
+
+  if (ret == (off_t) -1)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_rename (char *buf)
+{
+  CORE_ADDR ptrval;
+  int length, retlength;
+  char *oldpath, *newpath;
+  int ret, of, nf;
+  struct stat ost, nst;
+
+  /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request oldpath using 'm' packet */
+  oldpath = alloca (length);
+  retlength = remote_read_bytes (ptrval, oldpath, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* 2. Parameter: Ptr to newpath / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request newpath using 'm' packet */
+  newpath = alloca (length);
+  retlength = remote_read_bytes (ptrval, newpath, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  
+  /* Only operate on regular files and directories */
+  of = stat (oldpath, &ost);
+  nf = stat (newpath, &nst);
+  if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
+      || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
+    {
+      remote_fileio_reply (-1, FILEIO_EACCES);
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = rename (oldpath, newpath);
+
+  if (ret == -1)
+    {
+      /* Special case: newpath is a non-empty directory.  Some systems
+         return ENOTEMPTY, some return EEXIST.  We coerce that to be
+        always EEXIST. */
+      if (errno == ENOTEMPTY)
+        errno = EEXIST;
+#ifdef __CYGWIN__
+      /* Workaround some Cygwin problems with correct errnos. */
+      if (errno == EACCES)
+        {
+         if (!of && !nf && S_ISDIR (nst.st_mode))
+           {
+             if (S_ISREG (ost.st_mode))
+               errno = EISDIR;
+             else
+               {
+                 char oldfullpath[PATH_MAX + 1];
+                 char newfullpath[PATH_MAX + 1];
+                 int len;
+
+                 cygwin_conv_to_full_posix_path (oldpath, oldfullpath);
+                 cygwin_conv_to_full_posix_path (newpath, newfullpath);
+                 len = strlen (oldfullpath);
+                 if (newfullpath[len] == '/'
+                     && !strncmp (oldfullpath, newfullpath, len))
+                   errno = EINVAL;
+                 else
+                   errno = EEXIST;
+               }
+           }
+       }
+#endif
+
+      remote_fileio_return_errno (-1);
+    }
+  else
+    remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_unlink (char *buf)
+{
+  CORE_ADDR ptrval;
+  int length, retlength;
+  char *pathname;
+  int ret;
+  struct stat st;
+
+  /* Parameter: Ptr to pathname / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request pathname using 'm' packet */
+  pathname = alloca (length);
+  retlength = remote_read_bytes (ptrval, pathname, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  /* Only operate on regular files (and directories, which allows to return
+     the correct return code) */
+  if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
+    {
+      remote_fileio_reply (-1, FILEIO_ENODEV);
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = unlink (pathname);
+
+  if (ret == -1)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_stat (char *buf)
+{
+  CORE_ADDR ptrval;
+  int ret, length, retlength;
+  char *pathname;
+  LONGEST lnum;
+  struct stat st;
+  struct fio_stat fst;
+
+  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request pathname using 'm' packet */
+  pathname = alloca (length);
+  retlength = remote_read_bytes (ptrval, pathname, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  /* 2. Parameter: Ptr to struct stat */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+
+  remote_fio_no_longjmp = 1;
+  ret = stat (pathname, &st);
+
+  if (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+  /* Only operate on regular files and directories */
+  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
+    {
+      remote_fileio_reply (-1, FILEIO_EACCES);
+      return;
+    }
+  if (ptrval)
+    {
+      remote_fileio_to_fio_stat (&st, &fst);
+      remote_fileio_to_fio_uint (0, fst.fst_dev);
+      
+      retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst);
+      if (retlength != sizeof fst)
+       {
+         remote_fileio_return_errno (-1);
+         return;
+       }
+    }
+  remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_fstat (char *buf)
+{
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  long target_fd;
+  LONGEST lnum;
+  struct stat st;
+  struct fio_stat fst;
+  struct timeval tv;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  fd = remote_fileio_map_fd ((int) target_fd);
+  if (fd == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  /* 2. Parameter: Ptr to struct stat */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+
+  remote_fio_no_longjmp = 1;
+  if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
+    {
+      remote_fileio_to_fio_uint (1, fst.fst_dev);
+      st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
+      st.st_nlink = 1;
+      st.st_uid = getuid ();
+      st.st_gid = getgid ();
+      st.st_rdev = 0;
+      st.st_size = 0;
+      st.st_blksize = 512;
+      st.st_blocks = 0;
+      if (!gettimeofday (&tv, NULL))
+       st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
+      else
+        st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
+      ret = 0;
+    }
+  else
+    ret = fstat (fd, &st);
+
+  if (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+  if (ptrval)
+    {
+      remote_fileio_to_fio_stat (&st, &fst);
+
+      retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst);
+      if (retlength != sizeof fst)
+       {
+         remote_fileio_return_errno (-1);
+         return;
+       }
+    }
+  remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_gettimeofday (char *buf)
+{
+  LONGEST lnum;
+  CORE_ADDR ptrval;
+  int ret, retlength;
+  struct timeval tv;
+  struct fio_timeval ftv;
+
+  /* 1. Parameter: struct timeval pointer */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+  /* 2. Parameter: some pointer value... */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* ...which has to be NULL */
+  if (lnum)
+    {
+      remote_fileio_reply (-1, FILEIO_EINVAL);
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = gettimeofday (&tv, NULL);
+
+  if (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+
+  if (ptrval)
+    {
+      remote_fileio_to_fio_timeval (&tv, &ftv);
+
+      retlength = remote_fileio_write_bytes (ptrval, (char *) &ftv, sizeof ftv);
+      if (retlength != sizeof ftv)
+       {
+         remote_fileio_return_errno (-1);
+         return;
+       }
+    }
+  remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_isatty (char *buf)
+{
+  long target_fd;
+  int fd;
+
+  /* Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  remote_fio_no_longjmp = 1;
+  fd = remote_fileio_map_fd ((int) target_fd);
+  remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN ||
+                               fd == FIO_FD_CONSOLE_OUT ? 1 : 0);
+}
+
+static void
+remote_fileio_func_system (char *buf)
+{
+  CORE_ADDR ptrval;
+  int ret, length, retlength;
+  char *cmdline;
+
+  /* Check if system(3) has been explicitely allowed using the
+     `set remote system-call-allowed 1' command.  If not, return
+     EPERM */
+  if (!remote_fio_system_call_allowed)
+    {
+      remote_fileio_reply (-1, FILEIO_EPERM);
+      return;
+    }
+
+  /* Parameter: Ptr to commandline / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request commandline using 'm' packet */
+  cmdline = alloca (length);
+  retlength = remote_read_bytes (ptrval, cmdline, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = system (cmdline);
+
+  if (ret == -1)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (WEXITSTATUS (ret));
+}
+
+static struct {
+  char *name;
+  void (*func)(char *);
+} remote_fio_func_map[] = {
+  "open", remote_fileio_func_open,
+  "close", remote_fileio_func_close,
+  "read", remote_fileio_func_read,
+  "write", remote_fileio_func_write,
+  "lseek", remote_fileio_func_lseek,
+  "rename", remote_fileio_func_rename,
+  "unlink", remote_fileio_func_unlink,
+  "stat", remote_fileio_func_stat,
+  "fstat", remote_fileio_func_fstat,
+  "gettimeofday", remote_fileio_func_gettimeofday,
+  "isatty", remote_fileio_func_isatty,
+  "system", remote_fileio_func_system,
+  NULL, NULL
+};
+
+static int
+do_remote_fileio_request (struct ui_out *uiout, void *buf_arg)
+{
+  char *buf = buf_arg;
+  char *c;
+  int idx;
+
+  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
+
+  c = strchr (++buf, ',');
+  if (c)
+    *c++ = '\0';
+  else
+    c = strchr (buf, '\0');
+  for (idx = 0; remote_fio_func_map[idx].name; ++idx)
+    if (!strcmp (remote_fio_func_map[idx].name, buf))
+      break;
+  if (!remote_fio_func_map[idx].name)  /* ERROR: No such function. */
+    return RETURN_ERROR;
+  remote_fio_func_map[idx].func (c);
+  return 0;
+}
+
+void
+remote_fileio_request (char *buf)
+{
+  int ex;
+
+  remote_fileio_sig_init ();
+
+  remote_fio_ctrl_c_flag = 0;
+  remote_fio_no_longjmp = 0;
+
+  ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf,
+                        NULL, RETURN_MASK_ALL);
+  switch (ex)
+    {
+      case RETURN_ERROR:
+       remote_fileio_reply (-1, FILEIO_ENOSYS);
+        break;
+      case RETURN_QUIT:
+        remote_fileio_reply (-1, FILEIO_EINTR);
+       break;
+      default:
+        break;
+    }
+
+  remote_fileio_sig_exit ();
+}
+
+static void
+set_system_call_allowed (char *args, int from_tty)
+{
+  if (args)
+    {
+      char *arg_end;
+      int val = strtoul (args, &arg_end, 10);
+      if (*args && *arg_end == '\0')
+        {
+         remote_fio_system_call_allowed = !!val;
+         return;
+       }
+    }
+  error ("Illegal argument for \"set remote system-call-allowed\" command");
+}
+
+static void
+show_system_call_allowed (char *args, int from_tty)
+{
+  if (args)
+    error ("Garbage after \"show remote system-call-allowed\" command: `%s'", args);
+  printf_unfiltered ("Calling host system(3) call from target is %sallowed\n",
+                    remote_fio_system_call_allowed ? "" : "not ");
+}
+
+void
+initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
+                         struct cmd_list_element *remote_show_cmdlist)
+{
+  add_cmd ("system-call-allowed", no_class,
+          set_system_call_allowed,
+          "Set if the host system(3) call is allowed for the target.\n",
+          &remote_set_cmdlist);
+  add_cmd ("system-call-allowed", no_class,
+          show_system_call_allowed,
+          "Show if the host system(3) call is allowed for the target.\n",
+          &remote_show_cmdlist);
+}
diff --git a/gdb/remote-fileio.h b/gdb/remote-fileio.h
new file mode 100644 (file)
index 0000000..68c6450
--- /dev/null
@@ -0,0 +1,38 @@
+/* Remote File-I/O communications
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* See the GDB User Guide for details of the GDB remote protocol. */
+
+#ifndef REMOTE_FILEIO_H
+#define REMOTE_FILEIO_H
+
+struct cmd_list_element;
+
+/* Unified interface to remote fileio, called in remote.c from
+   remote_wait () and remote_async_wait () */
+extern void remote_fileio_request (char *buf);
+
+/* Called from _initialize_remote () */
+extern void initialize_remote_fileio (
+  struct cmd_list_element *remote_set_cmdlist,
+  struct cmd_list_element *remote_show_cmdlist);
+
+#endif
diff --git a/gdb/stack.h b/gdb/stack.h
new file mode 100644 (file)
index 0000000..0891c94
--- /dev/null
@@ -0,0 +1,27 @@
+/* Stack manipulation commands, for GDB the GNU Debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+#ifndef STACK_H
+#define STACK_H
+
+void select_frame_command (char *level_exp, int from_tty);
+
+#endif /* #ifndef STACK_H */
diff --git a/gdb/testsuite/gdb.asm/alpha.inc b/gdb/testsuite/gdb.asm/alpha.inc
new file mode 100644 (file)
index 0000000..f9741c4
--- /dev/null
@@ -0,0 +1,62 @@
+       comment "subroutine declare"
+       .macro gdbasm_declare name
+       .ent    \name
+\name:
+       .endm
+
+       comment "subroutine prologue"
+       .macro gdbasm_enter
+       .frame  $30, 16, $26, 0
+       .mask   0x04000000, -16
+       ldgp    $gp, 0($27)
+       subq    $sp, 16, $sp
+       stq     $26, 0($sp)
+       .prologue 1
+       .endm
+
+       comment "subroutine epilogue"
+       .macro gdbasm_leave
+       ldq     $26, 0($sp)
+       addq    $sp, 16, $sp
+       ret
+       .endm
+
+       comment "subroutine end"
+       .macro gdbasm_end name
+       .end    \name
+       .endm
+
+       comment "subroutine call"
+       /* Can't use ldgp here because the finish-frame test expects the
+          pc to wind up on the next line.  That's ok, we're all local.  */
+       .macro gdbasm_call subr
+       jsr     $26, \subr
+       .endm
+
+       .macro gdbasm_several_nops
+       nop
+       nop
+       nop
+       nop
+       .endm
+
+       comment "exit (0)"
+       .macro gdbasm_exit0
+       lda     $16, 0($31)
+       lda     $0, 1($31)
+       callsys
+       .endm
+
+       comment "crt0 startup"
+       .macro gdbasm_startup
+       .frame  $31, 0, $31, 0
+       .prologue
+       ldgp    $gp, 0($27)
+       .endm
+
+       comment "Declare a data variable"
+       .macro gdbasm_datavar name value
+       .data
+\name:
+       .long   \value
+       .endm
diff --git a/gdb/testsuite/gdb.base/bang.exp b/gdb/testsuite/gdb.base/bang.exp
new file mode 100644 (file)
index 0000000..f584074
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright 2003 Free Software Foundation, Inc.
+
+# 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.
+
+# This is a test that verifies that GDB is able to "run" when the name
+# of the executable file contains a '!'.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set testfile "args"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/bang!
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
+    gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Verify that we can run the program and that it terminates normally.
+gdb_test "run" \
+         ".*Program exited normally\." \
+         "run program"
+
diff --git a/gdb/testsuite/gdb.base/fileio.c b/gdb/testsuite/gdb.base/fileio.c
new file mode 100644 (file)
index 0000000..591b3b6
--- /dev/null
@@ -0,0 +1,503 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <sys/wait.h>
+/* TESTS :
+ * - open(const char *pathname, int flags, mode_t mode);
+1) Attempt to create file that already exists - EEXIST
+2) Attempt to open a directory for writing - EISDIR
+3) Pathname does not exist - ENOENT
+4) Open for write but no write permission - EACCES   
+
+read(int fd, void *buf, size_t count);
+1) Read using invalid file descriptor - EBADF
+
+write(int fd, const void *buf, size_t count);
+1) Write using invalid file descriptor - EBADF
+2) Attempt to write to read-only file - EBADF
+
+lseek(int fildes, off_t offset, int whence);
+1) Seeking on an invalid file descriptor - EBADF
+2) Invalid "whence" (3rd param) value -  EINVAL
+
+close(int fd);
+1) Attempt to close an invalid file descriptor - EBADF
+
+stat(const char *file_name, struct stat *buf);
+1) Pathname is a null string -  ENOENT
+2) Pathname does not exist - ENOENT
+
+fstat(int filedes, struct stat *buf);
+1) Attempt to stat using an invalid file descriptor - EBADF
+
+isatty (int desc);
+Not applicable. We will test that it returns 1 when expected and a case
+where it should return 0.
+
+rename(const char *oldpath, const char *newpath);
+1) newpath is an existing directory, but oldpath is not a directory. - EISDIR
+2) newpath is a non-empty directory. - ENOTEMPTY or EEXIST
+3) newpath is a subdirectory of old path. - EINVAL
+4) oldpath does not exist. - ENOENT
+
+unlink(const char *pathname);
+1) pathname does not have write access. - EACCES
+2) pathname does not exist. - ENOENT
+
+time(time_t *t);
+Not applicable.
+
+system (const char * string);
+1) Invalid string/command. -  returns 127.  */
+
+static const char *strerrno (int err);
+
+#define FILENAME    "foo.fileio.test"
+#define RENAMED     "bar.fileio.test"
+#define NONEXISTANT "nofoo.fileio.test"
+#define NOWRITE     "nowrt.fileio.test"
+#define TESTDIR1     "dir1.fileio.test"
+#define TESTDIR2     "dir2.fileio.test"
+#define TESTSUBDIR   "dir1.fileio.test/subdir.fileio.test"
+
+#define STRING      "Hello World"
+
+int
+test_open ()
+{
+  int ret;
+
+  /* Test opening */
+  errno = 0;
+  ret = open (FILENAME, O_CREAT | O_TRUNC | O_RDONLY, S_IWUSR | S_IRUSR);
+  printf ("open 1: ret = %d, errno = %d %s\n", ret, errno,
+         ret >= 0 ? "OK" : "");
+  if (ret >= 0)
+    close (ret);
+  /* Creating an already existing file (created by fileio.exp) */
+  errno = 0;
+  ret = open (FILENAME, O_CREAT | O_EXCL | O_WRONLY, S_IWUSR | S_IRUSR);
+  printf ("open 2: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  if (ret >= 0)
+    close (ret);
+  /* Open directory (for writing) */
+  errno = 0;
+  ret = open (".", O_WRONLY);
+  printf ("open 3: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  if (ret >= 0)
+    close (ret);
+  /* Opening nonexistant file */
+  errno = 0;
+  ret = open (NONEXISTANT, O_RDONLY);
+  printf ("open 4: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  if (ret >= 0)
+    close (ret);
+  /* Open for write but no write permission */
+  errno = 0;
+  ret = open (NOWRITE, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
+  if (ret >= 0)
+    {
+      close (ret);
+      errno = 0;
+      ret = open (NOWRITE, O_WRONLY);
+      printf ("open 5: ret = %d, errno = %d %s\n", ret, errno,
+             strerrno (errno));
+      if (ret >= 0)
+       close (ret);
+    }
+  else
+    printf ("open 5: ret = %d, errno = %d\n", ret, errno);
+}
+
+int
+test_write ()
+{
+  int fd, ret;
+
+  /* Test writing */
+  errno = 0;
+  fd = open (FILENAME, O_WRONLY);
+  if (fd >= 0)
+    {
+      errno = 0;
+      ret = write (fd, STRING, strlen (STRING));
+      printf ("write 1: ret = %d, errno = %d %s\n", ret, errno,
+              ret == strlen (STRING) ? "OK" : "");
+      close (fd);
+    }
+  else
+    printf ("write 1: ret = %d, errno = %d\n", ret, errno);
+  /* Write using invalid file descriptor */
+  errno = 0;
+  ret = write (999, STRING, strlen (STRING));
+  printf ("write 2: ret = %d, errno = %d, %s\n", ret, errno,
+         strerrno (errno));
+  /* Write to a read-only file */
+  errno = 0;
+  fd = open (FILENAME, O_RDONLY);
+  if (fd >= 0)
+    {
+      errno = 0;
+      ret = write (fd, STRING, strlen (STRING));
+      printf ("write 3: ret = %d, errno = %d %s\n", ret, errno,
+             strerrno (errno));
+    }
+  else
+    printf ("write 3: ret = %d, errno = %d\n", ret, errno);
+}
+
+int
+test_read ()
+{
+  int fd, ret;
+  char buf[16];
+
+  /* Test reading */
+  errno = 0;
+  fd = open (FILENAME, O_RDONLY);
+  if (fd >= 0)
+    {
+      memset (buf, 0, 16);
+      errno = 0;
+      ret = read (fd, buf, 16);
+      buf[15] = '\0'; /* Don't trust anybody... */
+      if (ret == strlen (STRING))
+        printf ("read 1: %s %s\n", buf, !strcmp (buf, STRING) ? "OK" : "");
+      else
+       printf ("read 1: ret = %d, errno = %d\n", ret, errno);
+      close (fd);
+    }
+  else
+    printf ("read 1: ret = %d, errno = %d\n", ret, errno);
+  /* Read using invalid file descriptor */
+  errno = 0;
+  ret = read (999, buf, 16);
+  printf ("read 2: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+}
+
+int
+test_lseek ()
+{
+  int fd;
+  off_t ret = 0;
+
+  /* Test seeking */
+  errno = 0;
+  fd = open (FILENAME, O_RDONLY);
+  if (fd >= 0)
+    {
+      errno = 0;
+      ret = lseek (fd, 0, SEEK_CUR);
+      printf ("lseek 1: ret = %ld, errno = %d, %s\n", (long) ret, errno,
+              ret == 0 ? "OK" : "");
+      errno = 0;
+      ret = lseek (fd, 0, SEEK_END);
+      printf ("lseek 2: ret = %ld, errno = %d, %s\n", (long) ret, errno,
+              ret == 11 ? "OK" : "");
+      errno = 0;
+      ret = lseek (fd, 3, SEEK_SET);
+      printf ("lseek 3: ret = %ld, errno = %d, %s\n", (long) ret, errno,
+              ret == 3 ? "OK" : "");
+      close (fd);
+    }
+  else
+    {
+      printf ("lseek 1: ret = %d, errno = %d\n", ret, errno);
+      printf ("lseek 2: ret = %d, errno = %d\n", ret, errno);
+      printf ("lseek 3: ret = %d, errno = %d\n", ret, errno);
+    }
+  /* Seeking on an invalid file descriptor */
+
+}
+
+int
+test_close ()
+{
+  int fd, ret;
+
+  /* Test close */
+  errno = 0;
+  fd = open (FILENAME, O_RDONLY);
+  if (fd >= 0)
+    {
+      errno = 0;
+      ret = close (fd);
+      printf ("close 1: ret = %d, errno = %d, %s\n", ret, errno,
+              ret == 0 ? "OK" : "");
+    }
+  else
+    printf ("close 1: ret = %d, errno = %d\n", ret, errno);
+  /* Close an invalid file descriptor */
+  errno = 0;
+  ret = close (999);
+  printf ("close 2: ret = %d, errno = %d, %s\n", ret, errno,
+         strerrno (errno));
+}
+
+int
+test_stat ()
+{
+  int ret;
+  struct stat st;
+
+  /* Test stat */
+  errno = 0;
+  ret = stat (FILENAME, &st);
+  if (!ret)
+    printf ("stat 1: ret = %d, errno = %d %s\n", ret, errno,
+           st.st_size == 11 ? "OK" : "");
+  else
+    printf ("stat 1: ret = %d, errno = %d\n", ret, errno);
+  /* NULL pathname */
+  errno = 0;
+  ret = stat (NULL, &st);
+  printf ("stat 2: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  /* Empty pathname */
+  errno = 0;
+  ret = stat ("", &st);
+  printf ("stat 3: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  /* Nonexistant file */
+  errno = 0;
+  ret = stat (NONEXISTANT, &st);
+  printf ("stat 4: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+}
+
+int
+test_fstat ()
+{
+  int fd, ret;
+  struct stat st;
+
+  /* Test fstat */
+  errno = 0;
+  fd = open (FILENAME, O_RDONLY);
+  if (fd >= 0)
+    {
+      errno = 0;
+      ret = fstat (fd, &st);
+      if (!ret)
+       printf ("fstat 1: ret = %d, errno = %d %s\n", ret, errno,
+               st.st_size == 11 ? "OK" : "");
+      else
+       printf ("fstat 1: ret = %d, errno = %d\n", ret, errno);
+      close (fd);
+    }
+  else
+    printf ("fstat 1: ret = %d, errno = %d\n", ret, errno);
+  /* Fstat using invalid file descriptor */
+  errno = 0;
+  ret = fstat (999, &st);
+  printf ("fstat 2: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+}
+
+int
+test_isatty ()
+{
+  int fd;
+
+  /* Check std I/O */
+  printf ("isatty 1: stdin %s\n", isatty (0) ? "yes OK" : "no");
+  printf ("isatty 2: stdout %s\n", isatty (1) ? "yes OK" : "no");
+  printf ("isatty 3: stderr %s\n", isatty (2) ? "yes OK" : "no");
+  /* Check invalid fd */
+  printf ("isatty 4: invalid %s\n", isatty (999) ? "yes" : "no OK");
+  /* Check open file */
+  fd = open (FILENAME, O_RDONLY);
+  if (fd >= 0)
+    {
+      printf ("isatty 5: file %s\n", isatty (fd) ? "yes" : "no OK");
+      close (fd);
+    }
+  else
+    printf ("isatty 5: file couldn't open\n");
+}
+
+
+int
+test_system ()
+{
+  /*
+   * Requires test framework to switch on "set remote system-call-allowed 1"
+   */
+  int ret;
+  char sys[512];
+
+  /* This test prepares the directory for test_rename() */
+  sprintf (sys, "mkdir -p %s %s", TESTSUBDIR, TESTDIR2);
+  ret = system (sys);
+  if (ret == 127)
+    printf ("system 1: ret = %d /bin/sh unavailable???\n", ret);
+  else
+    printf ("system 1: ret = %d %s\n", ret, ret == 0 ? "OK" : "");
+  /* Invalid command (just guessing ;-) ) */
+  ret = system ("wrtzlpfrmpft");
+  printf ("system 2: ret = %d %s\n", ret, WEXITSTATUS (ret) == 127 ? "OK" : "");
+}
+
+int
+test_rename ()
+{
+  int ret;
+  struct stat st;
+
+  /* Test rename */
+  errno = 0;
+  ret = rename (FILENAME, RENAMED);
+  if (!ret)
+    {
+      errno = 0;
+      ret = stat (FILENAME, &st);
+      if (ret && errno == ENOENT)
+        {
+         errno = 0;
+         ret = stat (RENAMED, &st);
+         printf ("rename 1: ret = %d, errno = %d %s\n", ret, errno,
+                 strerrno (errno));
+         errno = 0;
+       }
+      else
+       printf ("rename 1: ret = %d, errno = %d\n", ret, errno);
+    }
+  else
+    printf ("rename 1: ret = %d, errno = %d\n", ret, errno);
+  /* newpath is existing directory, oldpath is not a directory */
+  errno = 0;
+  ret = rename (RENAMED, TESTDIR2);
+  printf ("rename 2: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  /* newpath is a non-empty directory */
+  errno = 0;
+  ret = rename (TESTDIR2, TESTDIR1);
+  printf ("rename 3: ret = %d, errno = %d %s\n", ret, errno,
+          strerrno (errno));
+  /* newpath is a subdirectory of old path */
+  errno = 0;
+  ret = rename (TESTDIR1, TESTSUBDIR);
+  printf ("rename 4: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  /* oldpath does not exist */
+  errno = 0;
+  ret = rename (NONEXISTANT, FILENAME);
+  printf ("rename 5: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+}
+
+int
+test_unlink ()
+{
+  int ret;
+  char name[256];
+  char sys[512];
+
+  /* Test unlink */
+  errno = 0;
+  ret = unlink (RENAMED);
+  printf ("unlink 1: ret = %d, errno = %d %s\n", ret, errno,
+         strerrno (errno));
+  /* No write access */
+  sprintf (name, "%s/%s", TESTDIR2, FILENAME);
+  errno = 0;
+  ret = open (name, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
+  if (ret >= 0)
+    {
+      sprintf (sys, "chmod -w %s", TESTDIR2);
+      ret = system (sys);
+      if (!ret)
+        {
+         errno = 0;
+         ret = unlink (name);
+         printf ("unlink 2: ret = %d, errno = %d %s\n", ret, errno,
+                 strerrno (errno));
+        }
+      else
+       printf ("unlink 2: ret = %d chmod failed\n", ret, errno);
+    }
+  else
+    printf ("unlink 2: ret = %d, errno = %d\n", ret, errno);
+  /* pathname doesn't exist */
+  errno = 0;
+  ret = unlink (NONEXISTANT);
+  printf ("unlink 3: ret = %d, errno = %d %s\n", ret, errno,
+          strerrno (errno));
+}
+
+int
+test_time ()
+{
+  time_t ret, t;
+
+  errno = 0;
+  ret = time (&t);
+  printf ("time 1: ret = %ld, errno = %d, t = %ld %s\n", (long) ret, errno, (long) t, ret == t ? "OK" : "");
+  errno = 0;
+  ret = time (NULL);
+  printf ("time 2: ret = %ld, errno = %d, t = %ld %s\n",
+         (long) ret, errno, (long) t, ret >= t && ret < t + 10 ? "OK" : "");
+}
+
+static const char *
+strerrno (int err)
+{
+  switch (err)
+    {
+    case 0: return "OK";
+#ifdef EACCES
+    case EACCES: return "EACCES";
+#endif
+#ifdef EBADF
+    case EBADF: return "EBADF";
+#endif
+#ifdef EEXIST
+    case EEXIST: return "EEXIST";
+#endif
+#ifdef EFAULT
+    case EFAULT: return "EFAULT";
+#endif
+#ifdef EINVAL
+    case EINVAL: return "EINVAL";
+#endif
+#ifdef EISDIR
+    case EISDIR: return "EISDIR";
+#endif
+#ifdef ENOENT
+    case ENOENT: return "ENOENT";
+#endif
+#ifdef ENOTEMPTY
+    case ENOTEMPTY: return "ENOTEMPTY";
+#endif
+    default: return "E??";
+    }
+}
+
+int
+main ()
+{
+  /* Don't change the order of the calls.  They partly depend on each other */
+  test_open ();
+  test_write ();
+  test_read ();
+  test_lseek ();
+  test_close ();
+  test_stat ();
+  test_fstat ();
+  test_isatty ();
+  test_system ();
+  test_rename ();
+  test_unlink ();
+  test_time ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/fileio.exp b/gdb/testsuite/gdb.base/fileio.exp
new file mode 100644 (file)
index 0000000..279f1ab
--- /dev/null
@@ -0,0 +1,277 @@
+#   Copyright 2002
+#   Free Software Foundation, Inc.
+
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Corinna Vinschen <vinschen@redhat.com>
+
+if [target_info exists gdb,nointerrupts] {
+    verbose "Skipping interrupt.exp because of nointerrupts."
+    continue
+}
+
+if [target_info exists gdb,noinferiorio] {
+    verbose "Skipping interrupt.exp because of noinferiorio."
+    return
+}
+
+if $tracelevel then {
+        strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "fileio"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+
+if [get_compiler_info ${binfile}] {
+    return -1;
+}
+
+remote_exec build "test -r dir2.fileio.test && chmod -f +w dir2.fileio.test"
+remote_exec build "rm -rf *.fileio.test"
+
+set oldtimeout $timeout
+set timeout [expr "$timeout + 60"]
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set print address off\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "set width 0\n" ; gdb_expect -re "$gdb_prompt $"
+
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint"
+    continue
+}
+
+send_gdb "tbreak 81\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*open 1:.*OK.*test_open \\(\\) at.*$srcfile:81.*" \
+"Open a file"
+
+send_gdb "tbreak 88\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*open 2:.*EEXIST.*test_open \\(\\) at.*$srcfile:88.*" \
+"Creating already existing file returns EEXIST"
+
+send_gdb "tbreak 95\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*open 3:.*EISDIR.*test_open \\(\\) at.*$srcfile:95.*" \
+"Open directory for writing returns EISDIR"
+
+send_gdb "tbreak 102\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*open 4:.*ENOENT.*test_open \\(\\) at.*$srcfile:102.*" \
+"Opening nonexistant file returns ENOENT"
+
+send_gdb "tbreak 109\n" ; gdb_expect -re "$gdb_prompt $"
+send_gdb "continue\n" ; gdb_expect -re "$gdb_prompt $"
+catch "system \"chmod -f -w nowrt.fileio.test\""
+
+send_gdb "tbreak 119\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*open 5:.*EACCES.*test_open \\(\\) at.*$srcfile:119.*" \
+"Open for write but no write permission returns EACCES"
+
+send_gdb "tbreak 140\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*write 1:.*OK.*test_write \\(\\) at.*$srcfile:140.*" \
+"Writing to a file"
+
+send_gdb "tbreak 145\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*write 2:.*EBADF.*test_write \\(\\) at.*$srcfile:145.*" \
+"Write using invalid file descriptor returns EBADF"
+
+send_gdb "tbreak 156\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*write 3:.*EBADF.*test_write \\(\\) at.*$srcfile:156.*" \
+"Writing to a read-only file returns EBADF"
+
+send_gdb "tbreak 182\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*read 1:.*OK.*test_read \\(\\) at.*$srcfile:182.*" \
+"Reading from a file"
+
+send_gdb "tbreak 186\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*read 2:.*EBADF.*test_read \\(\\) at.*$srcfile:186.*" \
+"Read using invalid file descriptor returns EBADF"
+
+send_gdb "tbreak 221\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*lseek 1:.*OK.*lseek 2:.*OK.*lseek 3:.*OK.*test_lseek \\(\\) at.*$srcfile:221.*" \
+"Lseeking a file"
+
+send_gdb "tbreak 241\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*close 1:.*OK.*test_close \\(\\) at.*$srcfile:241.*" \
+"Closing a file"
+
+send_gdb "tbreak 245\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*close 2:.*EBADF.*test_close \\(\\) at.*$srcfile:245.*" \
+"Closing an invalid file descriptor returns EBADF"
+
+send_gdb "tbreak 262\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*stat 1:.*OK.*test_stat \\(\\) at.*$srcfile:262.*" \
+"Stat a file"
+
+send_gdb "tbreak 267\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+       "Continuing\\..*stat 2:.*(ENOENT|EFAULT).*test_stat \\(\\) at.*$srcfile:267.*" \
+"Stat a NULL pathname returns ENOENT or EFAULT"
+
+send_gdb "tbreak 272\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*stat 3:.*ENOENT.*test_stat \\(\\) at.*$srcfile:272.*" \
+"Stat an empty pathname returns ENOENT"
+
+send_gdb "tbreak 276\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*stat 4:.*ENOENT.*test_stat \\(\\) at.*$srcfile:276.*" \
+"Stat a nonexistant file returns ENOENT"
+
+send_gdb "tbreak 301\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*fstat 1:.*OK.*test_fstat \\(\\) at.*$srcfile:301.*" \
+"Fstat an open file"
+
+send_gdb "tbreak 305\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*fstat 2:.*EBADF.*test_fstat \\(\\) at.*$srcfile:305.*" \
+"Fstat an invalid file descriptor returns EBADF"
+
+send_gdb "tbreak 314\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*isatty 1:.*OK.*test_isatty \\(\\) at.*$srcfile:314.*" \
+"Isatty (stdin)"
+
+send_gdb "tbreak 315\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*isatty 2:.*OK.*test_isatty \\(\\) at.*$srcfile:315.*" \
+"Isatty (stdout)"
+
+send_gdb "tbreak 317\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*isatty 3:.*OK.*test_isatty \\(\\) at.*$srcfile:317.*" \
+"Isatty (stderr)"
+
+send_gdb "tbreak 319\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*isatty 4:.*OK.*test_isatty \\(\\) at.*$srcfile:319.*" \
+"Isatty (invalid fd)"
+
+send_gdb "tbreak 327\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*isatty 5:.*OK.*test_isatty \\(\\) at.*$srcfile:327.*" \
+"Isatty (open file)"
+
+send_gdb "set remote system-call-allowed 1\n"; gdb_expect -re ".*$gdb_prompt $"
+send_gdb "tbreak 347\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*system 1:.*OK.*test_system \\(\\) at.*$srcfile:347.*" \
+"System(3) call"
+
+# Is this ok?  POSIX says system returns a waitpid status?
+send_gdb "tbreak 349\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*system 2:.*OK.*test_system \\(\\) at.*$srcfile:349.*" \
+"System with invalid command returns 127"
+
+send_gdb "tbreak 378\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*rename 1:.*OK.*test_rename \\(\\) at.*$srcfile:378.*" \
+"Rename a file"
+
+send_gdb "tbreak 383\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*rename 2:.*EISDIR.*test_rename \\(\\) at.*$srcfile:383.*" \
+"Renaming a file to existing directory returns EISDIR"
+
+send_gdb "tbreak 388\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+       "Continuing\\..*rename 3:.*(ENOTEMPTY|EEXIST).*test_rename \\(\\) at.*$srcfile:388.*" \
+"Renaming a directory to a non-empty directory returns ENOTEMPTY or EEXIST"
+
+send_gdb "tbreak 393\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*rename 4:.*EINVAL.*test_rename \\(\\) at.*$srcfile:393.*" \
+"Renaming a directory to a subdir of itself returns EINVAL"
+
+send_gdb "tbreak 397\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*rename 5:.*ENOENT.*test_rename \\(\\) at.*$srcfile:397.*" \
+"Renaming a nonexistant file returns ENOENT"
+
+send_gdb "tbreak 412\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*unlink 1:.*OK.*test_unlink \\(\\) at.*$srcfile:412.*" \
+"Unlink a file"
+
+send_gdb "tbreak 432\n" ; gdb_expect -re "$gdb_prompt $"
+# This test fails on Cygwin because unlink() succeeds on Win32 systems
+# in that situation.
+if [ishost *cygwin*] {
+    setup_xfail "*-*-*"
+}
+gdb_test continue \
+"Continuing\\..*unlink 2:.*EACCES.*test_unlink \\(\\) at.*$srcfile:432.*" \
+"Unlinking a file in a directory w/o write access returns EACCES"
+
+send_gdb "tbreak 436\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*unlink 3:.*ENOENT.*test_unlink \\(\\) at.*$srcfile:436.*" \
+"Unlinking a nonexistant file returns ENOENT"
+
+send_gdb "tbreak 446\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*time 1:.*OK.*test_time \\(\\) at.*$srcfile:446.*" \
+"Time(2) call returns the same value as in parameter"
+
+sleep 2
+send_gdb "tbreak 450\n" ; gdb_expect -re "$gdb_prompt $"
+gdb_test continue \
+"Continuing\\..*time 2:.*OK.*test_time \\(\\) at.*$srcfile:450.*" \
+"Time(2) returns feasible values"
+
+send_gdb "quit\n"
+send_gdb "y\n"
+
+remote_exec build "test -r dir2.fileio.test && chmod -f +w dir2.fileio.test"
+remote_exec build "rm -rf *.fileio.test"
+
+set timeout $oldtimeout
+return 0
+
diff --git a/gdb/testsuite/gdb.base/gdb_history b/gdb/testsuite/gdb.base/gdb_history
new file mode 100644 (file)
index 0000000..cc22f69
--- /dev/null
@@ -0,0 +1,256 @@
+add-symbol-file
+append
+append binary
+append memory
+append value
+append binary memory
+append binary value
+attach
+break
+b
+br
+bre
+brea
+backtrace
+bt
+ba
+bac
+continue
+c
+call
+catch
+cd
+clear
+commands
+condition
+core-file
+d
+delete
+define
+delete breakpoints
+delete display
+detach
+directory
+dis
+disa
+disable
+disable breakpoints
+disable display
+disassemble
+display
+do
+document
+down
+down-silently
+dump
+dump binary
+dump ihex
+dump memory
+dump srec
+dump tekhex
+dump value
+dump binary memory
+dump binary value
+dump ihex memory
+dump ihex value
+dump srec memory
+dump srec value
+dump tekhex memory
+dump tekhex value
+echo
+enable breakpoints delete
+enable breakpoints once
+enable breakpoints
+enable delete
+enable display
+enable once
+enable
+exec-file
+f
+frame
+fg
+file
+finish
+forward-search
+gcore
+generate-core-file
+h
+help
+handle
+i
+info
+ignore
+info address
+info all-registers
+info args
+info bogus-gdb-command
+info breakpoints
+info catch
+info copying
+info display
+info f
+info frame
+info files
+info float
+info functions
+info locals
+info program
+info registers
+info s
+info stack
+info set
+info symbol
+info source
+info sources
+info target
+info terminal
+info types
+info variables
+info warranty
+info watchpoints
+inspect
+jump
+kill
+l
+list
+load
+n
+next
+ni
+nexti
+output
+overlay
+overlay on
+overlay manual
+overlay auto
+overlay off
+overlay list
+overlay map
+overlay unmap
+overlay manual
+overlay map
+overlay unmap
+p
+print
+printf
+ptype
+pwd
+r
+run
+rbreak
+restore
+return
+reverse-search
+s
+step
+search
+section
+set annotate
+set args
+set c
+set ch
+set check
+set check range
+set check type
+set complaints
+set confirm
+set environment
+set height
+set history expansion
+set history filename
+set history save
+set history size
+set history
+set language
+set listsize
+set p
+set pr
+set print
+set print address
+set print array
+set print asm-demangle
+set print demangle
+set print elements
+set print object
+set print pretty
+set print sevenbit-strings
+set print union
+set print vtbl
+set radix
+set symbol-reloading
+set variable
+set verbose
+set width
+set write
+set
+shell echo Hi dad!
+show annotate
+show args
+show c
+show ch
+show check
+show check range
+show check type
+show commands
+show complaints
+show confirm
+show convenience
+show directories
+show editing
+show height
+show history expansion
+show history filename
+show history save
+show history size
+show history
+show language
+show listsize
+show p
+show pr
+show print
+show paths
+show print address
+show print array
+show print asm-demangle
+show print demangle
+show print elements
+show print object
+show print pretty
+show print sevenbit-strings
+show print union
+show print vtbl
+show prompt
+show radix
+show symbol-reloading
+show user
+show values
+show verbose
+show version
+show width
+show write
+show
+si
+stepi
+signal
+source
+s
+step
+symbol-file
+target child
+target procfs
+target core
+target exec
+target remote
+target
+tbreak
+tty
+u
+until
+undisplay
+unset environment
+unset
+up-silently
+watch
+whatis
+where
+x
diff --git a/gdb/testsuite/gdb.base/shreloc.c b/gdb/testsuite/gdb.base/shreloc.c
new file mode 100644 (file)
index 0000000..6867362
--- /dev/null
@@ -0,0 +1,18 @@
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define ATTRIBUTES __attribute((__dllimport__))
+#else
+# define ATTRIBUTES
+#endif
+
+extern ATTRIBUTES void fn_1 (int);
+extern ATTRIBUTES void fn_2 (int);
+extern ATTRIBUTES int extern_var_1;
+extern ATTRIBUTES int extern_var_2;
+
+int main ()
+{
+  fn_1 (extern_var_1);
+  fn_2 (extern_var_2);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/shreloc.exp b/gdb/testsuite/gdb.base/shreloc.exp
new file mode 100644 (file)
index 0000000..ac48774
--- /dev/null
@@ -0,0 +1,257 @@
+# Copyright (C) 2003 Free Software Foundation, Inc.
+#
+# 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.
+#
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# Tests for shared object file relocation. If two shared objects have
+# the same load address (actually, overlapping load spaces), one of
+# them gets relocated at load-time. Check that gdb gets the right
+# values for the debugging and minimal symbols.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+#
+# This file uses shreloc.c, shreloc1.c and shreloc2.c
+#
+
+set prms_id 0
+set bug_id 0
+
+set workdir ${objdir}/${subdir}
+
+foreach module [list "shreloc" "shreloc1" "shreloc2"] {
+    if {[gdb_compile "${srcdir}/${subdir}/${module}.c" "${workdir}/${module}.o" object {debug}] != ""} {
+       untested "Couldn't compile ${module}.c"
+       return -1
+    }
+}
+
+set additional_flags "additional_flags=-shared"
+
+if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } {
+    set additional_flags "${additional_flags} -Wl,--image-base,0x04000000"
+}
+
+foreach module [list "shreloc1" "shreloc2"] {
+    if {[gdb_compile "${workdir}/${module}.o" "${workdir}/${module}.dll" executable [list debug $additional_flags]] != ""} {
+       untested "Couldn't link ${module}.dll"
+       return -1
+    }
+}
+
+if {[gdb_compile [list "${workdir}/shreloc.o" "${workdir}/shreloc1.dll" "${workdir}/shreloc2.dll"] "${workdir}/shreloc" executable debug] != ""} {
+    untested "Couldn't link shreloc executable"
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${workdir}/shreloc
+
+# Load up the shared objects
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+proc get_var_address { var } {
+  global gdb_prompt hex
+
+  send_gdb "print &${var}\n"
+  # Match output like:
+  # $1 = (int *) 0x0
+  # $5 = (int (*)()) 0
+  # $6 = (int (*)()) 0x24 <function_bar>
+  gdb_expect {
+    -re "\\\$\[0-9\]+ = \\(.*\\) (0|$hex)( <${var}>)?\[\r\n\]+${gdb_prompt} $"
+       {
+         pass "get address of ${var}"
+         if { $expect_out(1,string) == "0" } {
+           return "0x0"
+         } else {
+           return $expect_out(1,string)
+         }
+       }
+    -re "${gdb_prompt} $"
+       { fail "get address of ${var} (unknown output)" }
+    timeout
+       { fail "get address of ${var} (timeout)" }
+  }
+  return ""
+}
+
+#
+# Check debugging symbol relocations
+#
+
+# Check extern function for relocation
+set fn_1_addr [get_var_address fn_1]
+set fn_2_addr [get_var_address fn_2]
+
+if { "${fn_1_addr}" == "${fn_2_addr}" } {
+  fail "relocated extern functions have different addresses"
+} else {
+  pass "relocated extern functions have different addresses"
+}
+
+# Check extern var for relocation
+set extern_var_1_addr [get_var_address extern_var_1]
+set extern_var_2_addr [get_var_address extern_var_2]
+
+if { "${extern_var_1_addr}" == "${extern_var_2_addr}" } {
+  fail "relocated extern variables have different addresses"
+} else {
+  pass "relocated extern variables have different addresses"
+}
+
+# Check static var for relocation
+set static_var_1_addr [get_var_address static_var_1]
+set static_var_2_addr [get_var_address static_var_2]
+
+if { "${static_var_1_addr}" == "${static_var_2_addr}" } {
+  fail "relocated static variables have different addresses"
+} else {
+  pass "relocated static variables have different addresses"
+}
+
+#
+# Check minimal symbol relocations
+#
+
+proc send_gdb_discard { command } {
+    # Send a command to gdb and discard output up to the next prompt
+
+    global gdb_prompt
+
+    send_gdb "${command}\n"
+
+    # Discard output
+    gdb_expect {
+       -re ".*\[\r\n]+${gdb_prompt} $" {
+           return 1
+       }
+       timeout {
+           fail "{$command} (timeout)"
+           return 0
+       }
+    }
+}
+
+proc get_msym_addrs { var msymfile } {
+    # Extract the list of values for symbols matching var in the
+    # minimal symbol output file
+
+    global gdb_prompt hex
+    set result ""
+
+    send_gdb "shell grep -E \" ${var}(\[ \t\]+.*)?\$\" ${msymfile}\n"
+
+    while 1 {
+       gdb_expect {
+           -re "\[\[\]\[ 0-9\]+\] . (${hex}) ${var}(\[ \t\]+\[^\r\n\]*)?\[\r\n\]+" {
+               set result [concat $result $expect_out(1,string)]
+           }
+
+           -re "$gdb_prompt $" {
+               pass "get_msym_addrs ${var} (${result})"
+               return "${result}"
+           }
+
+           -re "\[^\r\n\]*\[\r\n\]+" {
+               # Skip
+           }
+
+           timeout {
+               fail "get_msym_addrs ${var} (timeout)"
+               return -1
+           }
+       }
+    }
+}
+
+proc check_same {var msymfile} {
+    # Check that the minimal symbol values matching var are the same
+
+    set len [llength [lsort -unique [get_msym_addrs "${var}" "${msymfile}"]]]
+
+    if { $len == 1 } {
+       return 1
+    } else {
+       return 0
+    }
+}
+
+proc check_different {var msymfile} {
+    # Check that the minimal symbol values matching var are different
+
+    set addr_list [lsort [get_msym_addrs "${var}" "${msymfile}"]]
+    set prev ""
+
+    if { [llength ${addr_list}] < 2 } {
+       return 0
+    }
+
+    foreach addr ${addr_list} {
+       if { ${prev} == ${addr} } {
+         return 0
+       }
+       set prev ${addr}
+    }
+
+    return 1
+}
+
+set msymfile "${workdir}/shreloc.txt"
+
+if [send_gdb_discard "maint print msymbols ${msymfile}"] {
+    if {[check_different "static_var_\[12\]" "${msymfile}"]} {
+       pass "(msymbol) relocated static vars have different addresses"
+    } else {
+       fail "(msymbol) relocated static vars have different addresses"
+    }
+
+    if {[check_different "extern_var_\[12\]" "${msymfile}"]} {
+       pass "(msymbol) relocated extern vars have different addresses"
+    } else {
+       fail "(msymbol) relocated extern vars have different addresses"
+    }
+
+    if {[check_different "fn_\[12\]" "${msymfile}"]} {
+       pass "(msymbol) relocated functions have different addresses"
+    } else {
+       fail "(msymbol) relocated functions have different addresses"
+    }
+}
+
+if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } {
+    #
+    # We know the names of some absolute symbols included in the
+    # portable-executable (DLL) format. Check that they didn't get
+    # relocated.
+    #
+    # A better approach would be include absolute symbols via the assembler.
+    #
+    if {[check_same "_minor_os_version__" "${msymfile}"]} {
+       pass "Absolute symbols not relocated"
+    } else {
+       fail "Absolute symbols not relocated"
+    }
+}
diff --git a/gdb/testsuite/gdb.base/shreloc1.c b/gdb/testsuite/gdb.base/shreloc1.c
new file mode 100644 (file)
index 0000000..b1bffde
--- /dev/null
@@ -0,0 +1,10 @@
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define ATTRIBUTES __attribute((__dllexport__))
+#else
+# define ATTRIBUTES
+#endif
+
+static int static_var_1;
+
+ATTRIBUTES void fn_1 (int unused) { }
+ATTRIBUTES int extern_var_1 = 0;
diff --git a/gdb/testsuite/gdb.base/shreloc2.c b/gdb/testsuite/gdb.base/shreloc2.c
new file mode 100644 (file)
index 0000000..1459093
--- /dev/null
@@ -0,0 +1,10 @@
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define ATTRIBUTES __attribute((__dllexport__))
+#else
+# define ATTRIBUTES
+#endif
+
+static int static_var_2;
+
+ATTRIBUTES void fn_2 (int unused) { }
+ATTRIBUTES int extern_var_2 = 0;
diff --git a/gdb/testsuite/gdb.c++/pr-1210.cc b/gdb/testsuite/gdb.c++/pr-1210.cc
new file mode 100644 (file)
index 0000000..5747e5d
--- /dev/null
@@ -0,0 +1,19 @@
+class A
+{
+};
+
+class B : virtual public A
+{
+};
+
+class C : public A
+{
+     protected:
+         B myB;
+};
+
+int main()
+{
+     C *obj = new C();
+     return 0;
+}
diff --git a/gdb/testsuite/gdb.c++/pr-1210.exp b/gdb/testsuite/gdb.c++/pr-1210.exp
new file mode 100644 (file)
index 0000000..3ff850d
--- /dev/null
@@ -0,0 +1,76 @@
+# Copyright 2003 Free Software Foundation, Inc.
+
+# 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.  
+
+# Tests for PR gdb/1210.
+
+# This file is part of the gdb testsuite.
+
+if $tracelevel then {
+       strace $tracelevel
+}
+
+if { [skip_cplus_tests] } { continue }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "pr-1210"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+if [get_compiler_info ${binfile} "c++"] {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint"
+    continue
+}
+
+gdb_test "next" ".*return 0;" "step past initialization"
+
+gdb_test_multiple "print *obj" "" {
+  -re "Cannot access memory.*$gdb_prompt $" {
+    fail "print *obj"
+  }
+  -re " = {<A> = {<No data fields>}, myB = {<A> = {<No data fields>}.*}}\r\n$gdb_prompt $" {
+    pass "print *obj"
+  }
+}
+
+gdb_test_multiple "print obj->myB" "" {
+  -re "Cannot access memory.*$gdb_prompt $" {
+    fail "print obj->myB"
+  }
+  -re " = {<A> = {<No data fields>}.*}\r\n$gdb_prompt $" {
+    pass "print obj->myB"
+  }
+}
+
+gdb_exit
+return 0
diff --git a/gdb/trad-frame.c b/gdb/trad-frame.c
new file mode 100644 (file)
index 0000000..92e6f83
--- /dev/null
@@ -0,0 +1,96 @@
+/* Traditional frame unwind support, for GDB the GNU Debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "trad-frame.h"
+#include "regcache.h"
+
+/* A traditional frame is unwound by analysing the function prologue
+   and using the information gathered to track registers.  For
+   non-optimized frames, the technique is reliable (just need to check
+   for all potential instruction sequences).  */
+
+struct trad_frame_saved_reg *
+trad_frame_alloc_saved_regs (struct frame_info *next_frame)
+{
+  int regnum;
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  int numregs = NUM_REGS + NUM_PSEUDO_REGS;
+  struct trad_frame_saved_reg *this_saved_regs
+    = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
+  for (regnum = 0; regnum < numregs; regnum++)
+    this_saved_regs[regnum].realnum = regnum;
+  return this_saved_regs;
+}
+
+void
+trad_frame_register_value (struct trad_frame_saved_reg this_saved_regs[],
+                          int regnum, LONGEST val)
+{
+  /* Make the REALNUM invalid, indicating that the ADDR contains the
+     register's value.  */
+  this_saved_regs[regnum].realnum = -1;
+  this_saved_regs[regnum].addr = val;
+}
+
+void
+trad_frame_prev_register (struct frame_info *next_frame,
+                         struct trad_frame_saved_reg this_saved_regs[],
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *bufferp)
+{
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  if (this_saved_regs[regnum].realnum >= 0
+      && this_saved_regs[regnum].addr != 0)
+    {
+      /* The register was saved in memory.  */
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = this_saved_regs[regnum].addr;
+      *realnump = -1;
+      if (bufferp != NULL)
+       {
+         /* Read the value in from memory.  */
+         get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
+                           register_size (gdbarch, regnum));
+       }
+    }
+  else if (this_saved_regs[regnum].realnum >= 0
+          && this_saved_regs[regnum].addr == 0)
+    {
+      /* As the next frame to return the value of the register.  */
+      frame_register_unwind (next_frame, this_saved_regs[regnum].realnum,
+                            optimizedp, lvalp, addrp, realnump, bufferp);
+    }
+  else
+    {
+      /* The register's value is available.  */
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (bufferp != NULL)
+       store_unsigned_integer (bufferp, register_size (gdbarch, regnum),
+                               this_saved_regs[regnum].addr);
+    }
+}
diff --git a/gdb/trad-frame.h b/gdb/trad-frame.h
new file mode 100644 (file)
index 0000000..2b04c7e
--- /dev/null
@@ -0,0 +1,70 @@
+/* Traditional frame unwind support, for GDB the GNU Debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+#ifndef TRAD_FRAME_H
+#define TRAD_FRAME_H
+
+struct frame_info;
+
+/* A traditional saved regs table, indexed by REGNUM, encoding where
+   the value of REGNUM for the previous frame can be found in this
+   frame.
+
+   The table is initialized with an identity encoding (ADDR == 0,
+   REALNUM == REGNUM) indicating that the value of REGNUM in the
+   previous frame can be found in register REGNUM (== REALNUM) in this
+   frame.
+
+   The initial encoding can then be changed:
+
+   Modify ADDR (REALNUM >= 0, ADDR != 0) to indicate that the value of
+   register REGNUM in the previous frame can be found in memory at
+   ADDR in this frame.
+
+   Modify REALNUM (REALNUM >= 0, ADDR == 0) to indicate that the value
+   of register REGNUM in the previous frame is found in register
+   REALNUM in this frame.
+
+   Call trad_frame_register_value (REALNUM < 0) to indicate that the
+   value of register REGNUM in the previous frame is found in ADDR.  */
+
+struct trad_frame_saved_reg
+{
+  LONGEST addr; /* A CORE_ADDR fits in a longest.  */
+  int realnum;
+};
+
+/* Convenience function, encode REGNUM's location in the trad-frame.  */
+void trad_frame_register_value (struct trad_frame_saved_reg this_saved_regs[],
+                               int regnum, LONGEST val);
+
+/* Return a freshly allocated (and initialized) trad_frame array.  */
+struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct frame_info *next_frame);
+
+/* Given the trad_frame info, return the location of the specified
+   register.  */
+void trad_frame_prev_register (struct frame_info *next_frame,
+                              struct trad_frame_saved_reg this_saved_regs[],
+                              int regnum, int *optimizedp,
+                              enum lval_type *lvalp, CORE_ADDR *addrp,
+                              int *realnump, void *bufferp);
+
+#endif
diff --git a/include/gdb/fileio.h b/include/gdb/fileio.h
new file mode 100644 (file)
index 0000000..d844781
--- /dev/null
@@ -0,0 +1,146 @@
+/* Hosted File I/O interface definitions, for GDB, the GNU Debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   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.  */
+
+#ifndef GDB_FILEIO_H_
+#define GDB_FILEIO_H_
+
+/* The following flags are defined to be independent of the host
+   as well as the target side implementation of these constants.
+   All constants are defined with a leading FILEIO_ in the name
+   to allow the usage of these constants together with the
+   corresponding implementation dependent constants in one module. */
+
+/* open(2) flags */
+#define FILEIO_O_RDONLY           0x0
+#define FILEIO_O_WRONLY           0x1
+#define FILEIO_O_RDWR             0x2
+#define FILEIO_O_APPEND           0x8
+#define FILEIO_O_CREAT          0x200
+#define FILEIO_O_TRUNC          0x400
+#define FILEIO_O_EXCL           0x800
+#define FILEIO_O_SUPPORTED     (FILEIO_O_RDONLY | FILEIO_O_WRONLY| \
+                                FILEIO_O_RDWR   | FILEIO_O_APPEND| \
+                                FILEIO_O_CREAT  | FILEIO_O_TRUNC| \
+                                FILEIO_O_EXCL)
+
+/* mode_t bits */
+#define FILEIO_S_IFREG        0100000
+#define FILEIO_S_IFDIR         040000
+#define FILEIO_S_IFCHR         020000
+#define FILEIO_S_IRUSR           0400
+#define FILEIO_S_IWUSR           0200
+#define FILEIO_S_IXUSR           0100
+#define FILEIO_S_IRWXU           0700
+#define FILEIO_S_IRGRP            040
+#define FILEIO_S_IWGRP            020
+#define FILEIO_S_IXGRP            010
+#define FILEIO_S_IRWXG            070
+#define FILEIO_S_IROTH             04
+#define FILEIO_S_IWOTH             02
+#define FILEIO_S_IXOTH             01
+#define FILEIO_S_IRWXO             07
+#define FILEIO_S_SUPPORTED         (FILEIO_S_IFREG|FILEIO_S_IFDIR|  \
+                                   FILEIO_S_IRWXU|FILEIO_S_IRWXG|  \
+                                    FILEIO_S_IRWXO)
+
+/* lseek(2) flags */
+#define FILEIO_SEEK_SET             0
+#define FILEIO_SEEK_CUR             1
+#define FILEIO_SEEK_END             2
+
+/* errno values */
+#define FILEIO_EPERM                1
+#define FILEIO_ENOENT               2
+#define FILEIO_EINTR                4
+#define FILEIO_EIO                  5
+#define FILEIO_EBADF                9
+#define FILEIO_EACCES              13
+#define FILEIO_EFAULT              14
+#define FILEIO_EBUSY               16
+#define FILEIO_EEXIST              17
+#define FILEIO_ENODEV              19
+#define FILEIO_ENOTDIR             20
+#define FILEIO_EISDIR              21
+#define FILEIO_EINVAL              22
+#define FILEIO_ENFILE              23
+#define FILEIO_EMFILE              24
+#define FILEIO_EFBIG               27
+#define FILEIO_ENOSPC              28
+#define FILEIO_ESPIPE              29
+#define FILEIO_EROFS               30
+#define FILEIO_ENOSYS             88
+#define FILEIO_ENAMETOOLONG        91
+#define FILEIO_EUNKNOWN          9999
+
+/* limits */
+#define FILEIO_INT_MIN    -2147483648L
+#define FILEIO_INT_MAX     2147483647L
+#define FILEIO_UINT_MAX    4294967295UL
+#define FILEIO_LONG_MIN   -9223372036854775808LL
+#define FILEIO_LONG_MAX    9223372036854775807LL
+#define FILEIO_ULONG_MAX   18446744073709551615ULL
+
+/* Integral types as used in protocol. */
+#if 0
+typedef __int32_t fio_int_t;
+typedef __uint32_t fio_uint_t, fio_mode_t, fio_time_t;
+typedef __int64_t fio_long_t;
+typedef __uint64_t fio_ulong_t;
+#endif
+
+#define FIO_INT_LEN   4
+#define FIO_UINT_LEN  4
+#define FIO_MODE_LEN  4
+#define FIO_TIME_LEN  4
+#define FIO_LONG_LEN  8
+#define FIO_ULONG_LEN 8
+
+typedef char fio_int_t[FIO_INT_LEN];   
+typedef char fio_uint_t[FIO_UINT_LEN];
+typedef char fio_mode_t[FIO_MODE_LEN];
+typedef char fio_time_t[FIO_TIME_LEN];
+typedef char fio_long_t[FIO_LONG_LEN];
+typedef char fio_ulong_t[FIO_ULONG_LEN];
+
+/* Struct stat as used in protocol.  For complete independence
+   of host/target systems, it's defined as an array with offsets
+   to the members. */
+
+struct fio_stat {
+  fio_uint_t  fst_dev;
+  fio_uint_t  fst_ino;
+  fio_mode_t  fst_mode;
+  fio_uint_t  fst_nlink;
+  fio_uint_t  fst_uid;
+  fio_uint_t  fst_gid;
+  fio_uint_t  fst_rdev;
+  fio_ulong_t fst_size;
+  fio_ulong_t fst_blksize;
+  fio_ulong_t fst_blocks;
+  fio_time_t  fst_atime;
+  fio_time_t  fst_mtime;
+  fio_time_t  fst_ctime;
+};
+
+struct fio_timeval {
+  fio_time_t  ftv_sec;
+  fio_long_t  ftv_usec;
+};
+
+#endif /* GDB_FILEIO_H_ */
diff --git a/sim/h8300/sim-main.h b/sim/h8300/sim-main.h
new file mode 100644 (file)
index 0000000..6acf901
--- /dev/null
@@ -0,0 +1,170 @@
+/* Main header for the Hitachi h8/300 architecture.  */
+
+#include "bfd.h"
+
+#ifndef SIM_MAIN_H
+#define SIM_MAIN_H
+
+#define DEBUG
+
+/* These define the size of main memory for the simulator.
+
+   Note the size of main memory for the H8/300H is only 256k.  Keeping it
+   small makes the simulator run much faster and consume less memory.
+
+   The linker knows about the limited size of the simulator's main memory
+   on the H8/300H (via the h8300h.sc linker script).  So if you change
+   H8300H_MSIZE, be sure to fix the linker script too.
+
+   Also note that there's a separate "eightbit" area aside from main
+   memory.  For simplicity, the simulator assumes any data memory reference
+   outside of main memory refers to the eightbit area (in theory, this
+   can only happen when simulating H8/300H programs).  We make no attempt
+   to catch overlapping addresses, wrapped addresses, etc etc.  */
+
+#define H8300_MSIZE (1 << 16)
+
+/* avolkov: 
+   Next 2 macros are ugly for any workstation, but while they're work.
+   Memory size MUST be configurable.  */
+#define H8300H_MSIZE (1 << 18) 
+#define H8300S_MSIZE (1 << 24) 
+
+#define CSIZE 1024
+
+enum h8_regnum {
+  R0_REGNUM = 0,
+  R1_REGNUM = 1,
+  R2_REGNUM = 2,
+  R3_REGNUM = 3,
+  R4_REGNUM = 4,
+  R5_REGNUM = 5,
+  R6_REGNUM = 6,
+  R7_REGNUM = 7,
+
+  SP_REGNUM = R7_REGNUM,       /* Contains address of top of stack */
+  FP_REGNUM = R6_REGNUM,       /* Contains address of executing
+                                  stack frame */
+  CCR_REGNUM = 8,              /* Contains processor status */
+  PC_REGNUM  = 9,              /* Contains program counter */
+  CYCLE_REGNUM = 10,
+  EXR_REGNUM  = 11,
+  INST_REGNUM = 12,
+  TICK_REGNUM = 13,
+  MACH_REGNUM = 14,
+  MACL_REGNUM = 15,
+  SBR_REGNUM =  16,
+  VBR_REGNUM =  17,
+
+  ZERO_REGNUM = 18
+};
+
+enum h8_typecodes {
+  OP_NULL,
+  OP_REG,              /* Register direct.  */
+  OP_LOWREG,           /* Special reg syntax for "bra".  */
+  OP_DISP,             /* Register indirect w/displacement.  */
+  /* Note: h8300, h8300h, and h8300s permit only pre-decr and post-incr.  */
+  OP_PREDEC,           /* Register indirect w/pre-decrement.  */
+  OP_POSTDEC,          /* Register indirect w/post-decrement.  */
+  OP_PREINC,           /* Register indirect w/pre-increment.  */
+  OP_POSTINC,          /* Register indirect w/post-increment.  */
+  OP_PCREL,            /* PC Relative.  */
+  OP_MEM,              /* Absolute memory address.  */
+  OP_CCR,              /* Condition Code Register.  */
+  OP_IMM,              /* Immediate value.  */
+  /*OP_ABS*/           /* Un-used (duplicates op_mem?).  */
+  OP_EXR,              /* EXtended control Register.  */
+  OP_SBR,              /* Vector Base Register.  */
+  OP_VBR,              /* Short-address Base Register.  */
+  OP_MACH,             /* Multiply Accumulator - high.  */
+  OP_MACL,             /* Multiply Accumulator - low.   */
+  /* FIXME: memory indirect?  */
+  OP_INDEXB,           /* Byte index mode */
+  OP_INDEXW,           /* Word index mode */
+  OP_INDEXL            /* Long index mode */
+};
+
+#include "sim-basics.h"
+
+/* Define sim_cia.  */
+typedef unsigned32 sim_cia;
+
+#include "sim-base.h"
+
+/* Structure used to describe addressing */
+
+typedef struct
+{
+  int type;
+  int reg;
+  int literal;
+} ea_type;
+
+/* Struct for instruction decoder.  */
+typedef struct
+{
+  ea_type src;
+  ea_type dst;
+  ea_type op3;
+  int opcode;
+  int next_pc;
+  int oldpc;
+  int cycles;
+#ifdef DEBUG
+  struct h8_opcode *op;
+#endif
+} decoded_inst;
+
+struct _sim_cpu {
+  unsigned int regs[20];       /* 8 GR's plus ZERO, SBR, and VBR.  */
+  unsigned int pc;
+
+  int macS;                    /* MAC Saturating mode */
+  int macV;                    /* MAC Overflow */
+  int macN;                    /* MAC Negative */
+  int macZ;                    /* MAC Zero     */
+
+  int delayed_branch;
+  char **command_line;         /* Pointer to command line arguments.  */
+
+  unsigned char *memory;
+  unsigned char *eightbit;
+  int mask;
+  
+  sim_cpu_base base;
+};
+
+/* The sim_state struct.  */
+struct sim_state {
+  struct _sim_cpu *cpu;
+  unsigned int sim_cache_size;
+  decoded_inst *sim_cache;
+  unsigned short *cache_idx;
+  unsigned long memory_size;
+  int cache_top;
+  int compiles;
+#ifdef ADEBUG
+  int stats[O_LAST];
+#endif
+  sim_state_base base;
+};
+
+/* The current state of the processor; registers, memory, etc.  */
+
+#define CIA_GET(CPU)           (cpu_get_pc (CPU))
+#define CIA_SET(CPU, VAL)      (cpu_set_pc ((CPU), (VAL)))
+#define STATE_CPU(SD, N)       ((SD)->cpu)     /* Single Processor.  */
+#define cpu_set_pc(CPU, VAL)   (((CPU)->pc)  = (VAL))
+#define cpu_get_pc(CPU)                (((CPU)->pc))
+
+/* Magic numbers used to distinguish an exit from a breakpoint.  */
+#define LIBC_EXIT_MAGIC1 0xdead        
+#define LIBC_EXIT_MAGIC2 0xbeef        
+/* Local version of macros for decoding exit status.  
+   (included here rather than try to find target version of wait.h)
+*/
+#define SIM_WIFEXITED(V) (((V) & 0xff) == 0)
+#define SIM_WEXITSTATUS(V) ((V) >> 8)
+
+#endif /* SIM_MAIN_H */
diff --git a/sim/ppc/altivec.igen b/sim/ppc/altivec.igen
new file mode 100644 (file)
index 0000000..9f10b26
--- /dev/null
@@ -0,0 +1,2356 @@
+# Altivec instruction set, for PSIM, the PowerPC simulator.
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# Contributed by Red Hat Inc; developed under contract from Motorola.
+# Written by matthew green <mrg@redhat.com>.
+
+# This file is part of GDB.
+
+# 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.  */
+
+
+#
+# Motorola AltiVec instructions.
+#
+
+:cache:av:::VS:VS:
+:cache:av::vreg *:vS:VS:(cpu_registers(processor)->altivec.vr + VS)
+:cache:av::unsigned32:VS_BITMASK:VS:(1 << VS)
+:cache:av:::VA:VA:
+:cache:av::vreg *:vA:VA:(cpu_registers(processor)->altivec.vr + VA)
+:cache:av::unsigned32:VA_BITMASK:VA:(1 << VA)
+:cache:av:::VB:VB:
+:cache:av::vreg *:vB:VB:(cpu_registers(processor)->altivec.vr + VB)
+:cache:av::unsigned32:VB_BITMASK:VB:(1 << VB)
+:cache:av:::VC:VC:
+:cache:av::vreg *:vC:VC:(cpu_registers(processor)->altivec.vr + VC)
+:cache:av::unsigned32:VC_BITMASK:VC:(1 << VC)
+
+# Flags for model.h
+::model-macro:::
+       #define PPC_INSN_INT_VR(OUT_MASK, IN_MASK, OUT_VMASK, IN_VMASK) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_int_vr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, OUT_VMASK, IN_VMASK); \
+               } while (0)
+
+       #define PPC_INSN_VR(OUT_VMASK, IN_VMASK) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_vr(MY_INDEX, cpu_model(processor), OUT_VMASK, IN_VMASK); \
+               } while (0)
+
+       #define PPC_INSN_VR_CR(OUT_VMASK, IN_VMASK, CR_MASK) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_vr_cr(MY_INDEX, cpu_model(processor), OUT_VMASK, IN_VMASK, CR_MASK); \
+               } while (0)
+
+       #define PPC_INSN_VR_VSCR(OUT_VMASK, IN_VMASK) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_vr_vscr(MY_INDEX, cpu_model(processor), OUT_VMASK, IN_VMASK); \
+               } while (0)
+
+       #define PPC_INSN_FROM_VSCR(VR_MASK) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_from_vscr(MY_INDEX, cpu_model(processor), VR_MASK); \
+               } while (0)
+
+       #define PPC_INSN_TO_VSCR(VR_MASK) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_to_vscr(MY_INDEX, cpu_model(processor), VR_MASK); \
+               } while (0)
+
+# Trace waiting for AltiVec registers to become available
+void::model-static::model_trace_altivec_busy_p:model_data *model_ptr, unsigned32 vr_busy
+       int i;
+       if (vr_busy) {
+         vr_busy &= model_ptr->vr_busy;
+         for(i = 0; i < 32; i++) {
+           if (((1 << i) & vr_busy) != 0) {
+             TRACE(trace_model, ("Waiting for register v%d.\n", i));
+           }
+         }
+       }
+       if (model_ptr->vscr_busy)
+         TRACE(trace_model, ("Waiting for VSCR\n"));
+
+# Trace making AltiVec registers busy
+void::model-static::model_trace_altivec_make_busy:model_data *model_ptr, unsigned32 vr_mask, unsigned32 cr_mask
+       int i;
+       if (vr_mask) {
+         for(i = 0; i < 32; i++) {
+           if (((1 << i) & vr_mask) != 0) {
+             TRACE(trace_model, ("Register v%d is now busy.\n", i));
+           }
+         }
+       }
+       if (cr_mask) {
+         for(i = 0; i < 8; i++) {
+           if (((1 << i) & cr_mask) != 0) {
+             TRACE(trace_model, ("Register cr%d is now busy.\n", i));
+           }
+         }
+       }
+
+# Schedule an AltiVec instruction that takes integer input registers and produces output registers
+void::model-function::ppc_insn_int_vr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 out_vmask, const unsigned32 in_vmask
+       const unsigned32 int_mask = out_mask | in_mask;
+       const unsigned32 vr_mask = out_vmask | in_vmask;
+       model_busy *busy_ptr;
+
+       if ((model_ptr->int_busy & int_mask) != 0 || (model_ptr->vr_busy & vr_mask)) {
+         model_new_cycle(model_ptr);                   /* don't count first dependency as a stall */
+
+         while ((model_ptr->int_busy & int_mask) != 0 || (model_ptr->vr_busy & vr_mask)) {
+           if (WITH_TRACE && ppc_trace[trace_model]) {
+             model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+             model_trace_altivec_busy_p(model_ptr, vr_mask);
+           }
+
+           model_ptr->nr_stalls_data++;
+           model_new_cycle(model_ptr);
+         }
+       }
+
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       model_ptr->int_busy |= out_mask;
+       busy_ptr->int_busy |= out_mask;
+       model_ptr->vr_busy |= out_vmask;
+       busy_ptr->vr_busy |= out_vmask;
+
+       if (out_mask)
+         busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_vmask)) ? 1 : 2;
+
+       if (out_vmask)
+         busy_ptr->nr_writebacks += (PPC_ONE_BIT_SET_P(out_vmask)) ? 1 : 2;
+
+       if (WITH_TRACE && ppc_trace[trace_model]) {
+         model_trace_make_busy(model_ptr, out_mask, 0, 0);
+         model_trace_altivec_make_busy(model_ptr, vr_mask, 0);
+       }
+
+# Schedule an AltiVec instruction that takes vector input registers and produces vector output registers
+void::model-function::ppc_insn_vr:itable_index index, model_data *model_ptr, const unsigned32 out_vmask, const unsigned32 in_vmask
+       const unsigned32 vr_mask = out_vmask | in_vmask;
+       model_busy *busy_ptr;
+
+       if (model_ptr->vr_busy & vr_mask) {
+         model_new_cycle(model_ptr);                   /* don't count first dependency as a stall */
+
+         while (model_ptr->vr_busy & vr_mask) {
+           if (WITH_TRACE && ppc_trace[trace_model]) {
+             model_trace_altivec_busy_p(model_ptr, vr_mask);
+           }
+
+           model_ptr->nr_stalls_data++;
+           model_new_cycle(model_ptr);
+         }
+       }
+
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       model_ptr->vr_busy |= out_vmask;
+       busy_ptr->vr_busy |= out_vmask;
+       if (out_vmask)
+         busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_vmask)) ? 1 : 2;
+
+       if (WITH_TRACE && ppc_trace[trace_model]) {
+         model_trace_altivec_make_busy(model_ptr, vr_mask, 0);
+       }
+
+# Schedule an AltiVec instruction that takes vector input registers and produces vector output registers, touches CR
+void::model-function::ppc_insn_vr_cr:itable_index index, model_data *model_ptr, const unsigned32 out_vmask, const unsigned32 in_vmask, const unsigned32 cr_mask
+       const unsigned32 vr_mask = out_vmask | in_vmask;
+       model_busy *busy_ptr;
+
+       if ((model_ptr->vr_busy & vr_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+         model_new_cycle(model_ptr);                   /* don't count first dependency as a stall */
+
+         while ((model_ptr->vr_busy & vr_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+           if (WITH_TRACE && ppc_trace[trace_model]) {
+             model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
+             model_trace_altivec_busy_p(model_ptr, vr_mask);
+           }
+
+           model_ptr->nr_stalls_data++;
+           model_new_cycle(model_ptr);
+         }
+       }
+
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       model_ptr->cr_fpscr_busy |= cr_mask;
+       busy_ptr->cr_fpscr_busy |= cr_mask;
+       model_ptr->vr_busy |= out_vmask;
+       busy_ptr->vr_busy |= out_vmask;
+
+       if (out_vmask)
+         busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_vmask)) ? 1 : 2;
+
+       if (cr_mask)
+         busy_ptr->nr_writebacks++;
+
+       if (WITH_TRACE && ppc_trace[trace_model])
+         model_trace_altivec_make_busy(model_ptr, vr_mask, cr_mask);
+
+# Schedule an AltiVec instruction that takes vector input registers and produces vector output registers, touches VSCR
+void::model-function::ppc_insn_vr_vscr:itable_index index, model_data *model_ptr, const unsigned32 out_vmask, const unsigned32 in_vmask
+       const unsigned32 vr_mask = out_vmask | in_vmask;
+       model_busy *busy_ptr;
+
+       if ((model_ptr->vr_busy & vr_mask) != 0 || model_ptr->vscr_busy != 0) {
+         model_new_cycle(model_ptr);                   /* don't count first dependency as a stall */
+
+         while ((model_ptr->vr_busy & vr_mask) != 0 || model_ptr->vscr_busy != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_altivec_busy_p(model_ptr, vr_mask);
+
+           model_ptr->nr_stalls_data++;
+           model_new_cycle(model_ptr);
+         }
+       }
+
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       model_ptr->vr_busy |= out_vmask;
+       busy_ptr->vr_busy |= out_vmask;
+       model_ptr->vscr_busy = 1;
+       busy_ptr->vscr_busy = 1;
+
+       if (out_vmask)
+         busy_ptr->nr_writebacks = 1 + (PPC_ONE_BIT_SET_P(out_vmask)) ? 1 : 2;
+
+       if (WITH_TRACE && ppc_trace[trace_model])
+         model_trace_altivec_make_busy(model_ptr, vr_mask, 0);
+
+# Schedule an MFVSCR instruction that VSCR input register and produces an AltiVec output register
+void::model-function::ppc_insn_from_vscr:itable_index index, model_data *model_ptr, const unsigned32 vr_mask
+       model_busy *busy_ptr;
+
+       while ((model_ptr->vr_busy & vr_mask) != 0 || model_ptr->vscr_busy != 0) {
+         if (WITH_TRACE && ppc_trace[trace_model])
+           model_trace_altivec_busy_p(model_ptr, vr_mask);
+
+         model_ptr->nr_stalls_data++;
+         model_new_cycle(model_ptr);
+       }
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       model_ptr->cr_fpscr_busy |= vr_mask;
+       busy_ptr->cr_fpscr_busy |= vr_mask;
+
+       if (vr_mask)
+         busy_ptr->nr_writebacks = 1;
+
+       model_ptr->vr_busy |= vr_mask;
+       if (WITH_TRACE && ppc_trace[trace_model])
+         model_trace_altivec_make_busy(model_ptr, vr_mask, 0);
+
+# Schedule an MTVSCR instruction that one AltiVec input register and produces a vscr output register
+void::model-function::ppc_insn_to_vscr:itable_index index, model_data *model_ptr, const unsigned32 vr_mask
+       model_busy *busy_ptr;
+
+       while ((model_ptr->vr_busy & vr_mask) != 0 || model_ptr->vscr_busy != 0) {
+         if (WITH_TRACE && ppc_trace[trace_model])
+           model_trace_altivec_busy_p(model_ptr, vr_mask);
+
+         model_ptr->nr_stalls_data++;
+         model_new_cycle(model_ptr);
+       }
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       busy_ptr ->vscr_busy = 1;
+       model_ptr->vscr_busy = 1;
+       busy_ptr->nr_writebacks = 1;
+
+       TRACE(trace_model,("Making VSCR busy.\n"));
+
+# The follow are AltiVec saturate operations
+
+signed8::model-function::altivec_signed_saturate_8:signed16 val, int *sat
+         signed8 rv;
+         if (val > 127) {
+           rv = 127;
+           *sat = 1;
+         } else if (val < -128) {
+           rv = -128;
+           *sat = 1;
+         } else {
+           rv = val;
+           *sat = 0;
+         }
+         return rv;
+
+signed16::model-function::altivec_signed_saturate_16:signed32 val, int *sat
+         signed16 rv;
+         if (val > 32767) {
+           rv = 32767;
+           *sat = 1;
+         } else if (val < -32768) {
+           rv = -32768;
+           *sat = 1;
+         } else {
+           rv = val;
+           *sat = 0;
+         }
+         return rv;
+
+signed32::model-function::altivec_signed_saturate_32:signed64 val, int *sat
+         signed32 rv;
+         if (val > 2147483647) {
+           rv = 2147483647;
+           *sat = 1;
+         } else if (val < -2147483648LL) {
+           rv = -2147483648LL;
+           *sat = 1;
+         } else {
+           rv = val;
+           *sat = 0;
+         }
+         return rv;
+
+unsigned8::model-function::altivec_unsigned_saturate_8:signed16 val, int *sat
+         unsigned8 rv;
+         if (val > 255) {
+           rv = 255;
+           *sat = 1;
+         } else if (val < 0) {
+           rv = 0;
+           *sat = 1;
+         } else {
+           rv = val;
+           *sat = 0;
+         }
+         return rv;
+
+unsigned16::model-function::altivec_unsigned_saturate_16:signed32 val, int *sat
+         unsigned16 rv;
+         if (val > 65535) {
+           rv = 65535;
+           *sat = 1;
+         } else if (val < 0) {
+           rv = 0;
+           *sat = 1;
+         } else {
+           rv = val;
+           *sat = 0;
+         }
+         return rv;
+
+unsigned32::model-function::altivec_unsigned_saturate_32:signed64 val, int *sat
+         unsigned32 rv;
+         if (val > 4294967295LL) {
+           rv = 4294967295LL;
+           *sat = 1;
+         } else if (val < 0) {
+           rv = 0;
+           *sat = 1;
+         } else {
+           rv = val;
+           *sat = 0;
+         }
+         return rv;
+
+#
+# Load instructions, 6-14 ... 6-22.
+#
+
+0.31,6.VS,11.RA,16.RB,21.7,31.0:X:av:lvebx %VD, %RA, %RB:Load Vector Element Byte Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned_word eb;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       eb = EA & 0xf;
+       (*vS).b[AV_BINDEX(eb)] = MEM(unsigned, EA, 1);
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.39,31.0:X:av:lvehx %VD, %RA, %RB:Load Vector Element Half Word Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned_word eb;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~1;
+       eb = EA & 0xf;
+       (*vS).h[AV_HINDEX(eb/2)] = MEM(unsigned, EA, 2);
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.71,31.0:X:av:lvewx %VD, %RA, %RB:Load Vector Element Word Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned_word eb;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~3;
+       eb = EA & 0xf;
+       (*vS).w[eb/4] = MEM(unsigned, EA, 4);
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+
+0.31,6.VS,11.RA,16.RB,21.6,31.0:X:av:lvsl %VD, %RA, %RB:Load Vector for Shift Left
+       unsigned_word b;
+       unsigned_word addr;
+       int i, j;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       addr = b + *rB;
+       j = addr & 0xf;
+       for (i = 0; i < 16; i++)
+         if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+           (*vS).b[AV_BINDEX(i)] = j++;
+         else
+           (*vS).b[AV_BINDEX(15 - i)] = j++;
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.38,31.0:X:av:lvsr %VD, %RA, %RB:Load Vector for Shift Right
+       unsigned_word b;
+       unsigned_word addr;
+       int i, j;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       addr = b + *rB;
+       j = 0x10 - (addr & 0xf);
+       for (i = 0; i < 16; i++)
+         if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+           (*vS).b[AV_BINDEX(i)] = j++;
+         else
+           (*vS).b[AV_BINDEX(15 - i)] = j++;
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+
+0.31,6.VS,11.RA,16.RB,21.103,31.0:X:av:lvx %VD, %RA, %RB:Load Vector Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) {
+         (*vS).w[0] = MEM(unsigned, EA + 0, 4);
+         (*vS).w[1] = MEM(unsigned, EA + 4, 4);
+         (*vS).w[2] = MEM(unsigned, EA + 8, 4);
+         (*vS).w[3] = MEM(unsigned, EA + 12, 4);
+       } else {
+         (*vS).w[0] = MEM(unsigned, EA + 12, 4);
+         (*vS).w[1] = MEM(unsigned, EA + 8, 4);
+         (*vS).w[2] = MEM(unsigned, EA + 4, 4);
+         (*vS).w[3] = MEM(unsigned, EA + 0, 4);
+       }
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.359,31.0:X:av:lvxl %VD, %RA, %RB:Load Vector Indexed LRU
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) {
+         (*vS).w[0] = MEM(unsigned, EA + 0, 4);
+         (*vS).w[1] = MEM(unsigned, EA + 4, 4);
+         (*vS).w[2] = MEM(unsigned, EA + 8, 4);
+         (*vS).w[3] = MEM(unsigned, EA + 12, 4);
+       } else {
+         (*vS).w[0] = MEM(unsigned, EA + 12, 4);
+         (*vS).w[1] = MEM(unsigned, EA + 8, 4);
+         (*vS).w[2] = MEM(unsigned, EA + 4, 4);
+         (*vS).w[3] = MEM(unsigned, EA + 0, 4);
+       }
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+#
+# Move to/from VSCR instructions, 6-23 & 6-24.
+#
+
+0.4,6.VS,11.0,16.0,21.1540:VX:av:mfvscr %VS:Move from Vector Status and Control Register
+       (*vS).w[0] = 0;
+       (*vS).w[1] = 0;
+       (*vS).w[2] = 0;
+       (*vS).w[3] = VSCR;
+       PPC_INSN_FROM_VSCR(VS_BITMASK);
+
+0.4,6.0,11.0,16.VB,21.1604:VX:av:mtvscr %VB:Move to Vector Status and Control Register
+       VSCR = (*vB).w[3];
+       PPC_INSN_TO_VSCR(VB_BITMASK);
+
+#
+# Store instructions, 6-25 ... 6-29.
+#
+
+0.31,6.VS,11.RA,16.RB,21.135,31.0:X:av:stvebx %VD, %RA, %RB:Store Vector Element Byte Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned_word eb;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       eb = EA & 0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+         STORE(EA, 1, (*vS).b[eb]);
+       else
+         STORE(EA, 1, (*vS).b[15-eb]);
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.167,31.0:X:av:stvehx %VD, %RA, %RB:Store Vector Element Half Word Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned_word eb;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~1;
+       eb = EA & 0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+         STORE(EA, 2, (*vS).h[eb/2]);
+       else
+         STORE(EA, 2, (*vS).h[7-eb]);
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.199,31.0:X:av:stvewx %VD, %RA, %RB:Store Vector Element Word Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned_word eb;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~3;
+       eb = EA & 0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+         STORE(EA, 4, (*vS).w[eb/4]);
+       else
+         STORE(EA, 4, (*vS).w[3-(eb/4)]);
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.231,31.0:X:av:stvx %VD, %RA, %RB:Store Vector Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) {
+         STORE(EA + 0, 4, (*vS).w[0]);
+         STORE(EA + 4, 4, (*vS).w[1]);
+         STORE(EA + 8, 4, (*vS).w[2]);
+         STORE(EA + 12, 4, (*vS).w[3]);
+       } else {
+         STORE(EA + 12, 4, (*vS).w[0]);
+         STORE(EA + 8, 4, (*vS).w[1]);
+         STORE(EA + 4, 4, (*vS).w[2]);
+         STORE(EA + 0, 4, (*vS).w[3]);
+       }
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+0.31,6.VS,11.RA,16.RB,21.487,31.0:X:av:stvxl %VD, %RA, %RB:Store Vector Indexed LRU
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = (b + *rB) & ~0xf;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) {
+         STORE(EA + 0, 4, (*vS).w[0]);
+         STORE(EA + 4, 4, (*vS).w[1]);
+         STORE(EA + 8, 4, (*vS).w[2]);
+         STORE(EA + 12, 4, (*vS).w[3]);
+       } else {
+         STORE(EA + 12, 4, (*vS).w[0]);
+         STORE(EA + 8, 4, (*vS).w[1]);
+         STORE(EA + 4, 4, (*vS).w[2]);
+         STORE(EA + 0, 4, (*vS).w[3]);
+       }
+       PPC_INSN_INT_VR(0, RA_BITMASK | RB_BITMASK, VS_BITMASK, 0);
+
+#
+# Vector Add instructions, 6-30 ... 6-40.
+#
+
+0.4,6.VS,11.VA,16.VB,21.384:VX:av:vaddcuw %VD, %VA, %VB:Vector Add Carryout Unsigned Word
+       unsigned64 temp;
+       int i;
+       for (i = 0; i < 4; i++) {
+         temp = (unsigned64)(*vA).w[i] + (unsigned64)(*vB).w[i];
+         (*vS).w[i] = temp >> 32;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.10:VX:av:vaddfp %VD, %VA, %VB:Vector Add Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu a, b, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_add (&d, &a, &b);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+       
+0.4,6.VS,11.VA,16.VB,21.768:VX:av:vaddsbs %VD, %VA, %VB:Vector Add Signed Byte Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       for (i = 0; i < 16; i++) {
+         temp = (signed16)(signed8)(*vA).b[i] + (signed16)(signed8)(*vB).b[i];
+         (*vS).b[i] = altivec_signed_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.832:VX:av:vaddshs %VD, %VA, %VB:Vector Add Signed Half Word Saturate
+       int i, sat, tempsat;
+       signed32 temp, a, b;
+       for (i = 0; i < 8; i++) {
+         a = (signed32)(signed16)(*vA).h[i];
+         b = (signed32)(signed16)(*vB).h[i];
+         temp = a + b;
+         (*vS).h[i] = altivec_signed_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.896:VX:av:vaddsws %VD, %VA, %VB:Vector Add Signed Word Saturate
+       int i, sat, tempsat;
+       signed64 temp;
+       for (i = 0; i < 4; i++) {
+         temp = (signed64)(signed32)(*vA).w[i] + (signed64)(signed32)(*vB).w[i];
+         (*vS).w[i] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.0:VX:av:vaddubm %VD, %VA, %VB:Vector Add Unsigned Byte Modulo
+       int i;
+       for (i = 0; i < 16; i++)
+         (*vS).b[i] = ((*vA).b[i] + (*vB).b[i]) & 0xff;
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.512:VX:av:vaddubs %VD, %VA, %VB:Vector Add Unsigned Byte Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       sat = 0;
+       for (i = 0; i < 16; i++) {
+         temp = (signed16)(unsigned8)(*vA).b[i] + (signed16)(unsigned8)(*vB).b[i];
+         (*vS).b[i] = altivec_unsigned_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.64:VX:av:vadduhm %VD, %VA, %VB:Vector Add Unsigned Half Word Modulo
+       int i;
+       for (i = 0; i < 8; i++)
+         (*vS).h[i] = ((*vA).h[i] + (*vB).h[i]) & 0xffff;
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.576:VX:av:vadduhs %VD, %VA, %VB:Vector Add Unsigned Half Word Saturate
+       int i, sat, tempsat;
+       signed32 temp;
+       for (i = 0; i < 8; i++) {
+         temp = (signed32)(unsigned16)(*vA).h[i] + (signed32)(unsigned16)(*vB).h[i];
+         (*vS).h[i] = altivec_unsigned_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.128:VX:av:vadduwm %VD, %VA, %VB:Vector Add Unsigned Word Modulo
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (*vA).w[i] + (*vB).w[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.640:VX:av:vadduws %VD, %VA, %VB:Vector Add Unsigned Word Saturate
+       int i, sat, tempsat;
+       signed64 temp;
+       for (i = 0; i < 4; i++) {
+         temp = (signed64)(unsigned32)(*vA).w[i] + (signed64)(unsigned32)(*vB).w[i];
+         (*vS).w[i] = altivec_unsigned_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+#
+# Vector AND instructions, 6-41, 6-42
+#
+
+0.4,6.VS,11.VA,16.VB,21.1028:VX:av:vand %VD, %VA, %VB:Vector Logical AND
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (*vA).w[i] & (*vB).w[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1092:VX:av:vandc %VD, %VA, %VB:Vector Logical AND with Compliment
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (*vA).w[i] & ~((*vB).w[i]);
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Average instructions, 6-43, 6-48
+#
+
+0.4,6.VS,11.VA,16.VB,21.1282:VX:av:vavgsb %VD, %VA, %VB:Vector Average Signed Byte
+       int i;
+       signed16 temp, a, b;
+       for (i = 0; i < 16; i++) {
+         a = (signed16)(signed8)(*vA).b[i];
+         b = (signed16)(signed8)(*vB).b[i];
+         temp = a + b + 1;
+         (*vS).b[i] = (temp >> 1) & 0xff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1346:VX:av:vavgsh %VD, %VA, %VB:Vector Average Signed Half Word
+       int i;
+       signed32 temp, a, b;
+       for (i = 0; i < 8; i++) {
+         a = (signed32)(signed16)(*vA).h[i];
+         b = (signed32)(signed16)(*vB).h[i];
+         temp = a + b + 1;
+         (*vS).h[i] = (temp >> 1) & 0xffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1410:VX:av:vavgsw %VD, %VA, %VB:Vector Average Signed Word
+       int i;
+       signed64 temp, a, b;
+       for (i = 0; i < 4; i++) {
+         a = (signed64)(signed32)(*vA).w[i];
+         b = (signed64)(signed32)(*vB).w[i];
+         temp = a + b + 1;
+         (*vS).w[i] = (temp >> 1) & 0xffffffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1026:VX:av:vavgub %VD, %VA, %VB:Vector Average Unsigned Byte
+       int i;
+       unsigned16 temp, a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         temp = a + b + 1;
+         (*vS).b[i] = (temp >> 1) & 0xff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1090:VX:av:vavguh %VD, %VA, %VB:Vector Average Unsigned Half Word
+       int i;
+       unsigned32 temp, a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         temp = a + b + 1;
+         (*vS).h[i] = (temp >> 1) & 0xffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1154:VX:av:vavguw %VD, %VA, %VB:Vector Average Unsigned Word
+       int i;
+       unsigned64 temp, a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         temp = a + b + 1;
+         (*vS).w[i] = (temp >> 1) & 0xffffffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+#
+# Vector Fixed Point Convert instructions, 6-49, 6-50
+#
+
+0.4,6.VS,11.UIMM,16.VB,21.842:VX:av:vcfsx %VD, %VB, %UIMM:Vector Convert From Signed Fixed-Point Word
+       int i;
+       unsigned32 f;
+       sim_fpu b, div, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_u32to (&div, 2 << UIMM, sim_fpu_round_default);
+         sim_fpu_div (&d, &b, &div);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.UIMM,16.VB,21.778:VX:av:vcfux %VD, %VA, %UIMM:Vector Convert From Unsigned Fixed-Point Word
+       int i;
+       unsigned32 f;
+       sim_fpu b, d, div;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_u32to (&div, 2 << UIMM, sim_fpu_round_default);
+         sim_fpu_div (&d, &b, &div);
+         sim_fpu_to32u (&f, &d, sim_fpu_round_default);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+#
+# Vector Compare instructions, 6-51 ... 6-64
+#
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.966:VXR:av:vcmpbpfpx %VD, %VA, %VB:Vector Compare Bounds Floating Point
+       int i, le, ge;
+       sim_fpu a, b, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         le = sim_fpu_is_le(&a, &b);
+         ge = sim_fpu_is_ge(&a, &b);
+         (*vS).w[i] = (le ? 0 : 1 << 31) | (ge ? 0 : 1 << 30);
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 0);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.198:VXR:av:vcmpeqfpx %VD, %VA, %VB:Vector Compare Equal-to-Floating Point
+       int i;
+       sim_fpu a, b;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         if (sim_fpu_is_eq(&a, &b))
+           (*vS).w[i] = 0xffffffff;
+         else
+           (*vS).w[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.6:VXR:av:vcmpequbx %VD, %VA, %VB:Vector Compare Equal-to Unsigned Byte
+       int i;
+       for (i = 0; i < 16; i++)
+         if ((*vA).b[i] == (*vB).b[i])
+           (*vS).b[i] = 0xff;
+         else
+           (*vS).b[i] = 0;
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.70:VXR:av:vcmpequhx %VD, %VA, %VB:Vector Compare Equal-to Unsigned Half Word
+       int i;
+       for (i = 0; i < 8; i++)
+         if ((*vA).h[i] == (*vB).h[i])
+           (*vS).h[i] = 0xffff;
+         else
+           (*vS).h[i] = 0;
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.134:VXR:av:vcmpequwx %VD, %VA, %VB:Vector Compare Equal-to Unsigned Word
+       int i;
+       for (i = 0; i < 4; i++)
+         if ((*vA).w[i] == (*vB).w[i])
+           (*vS).w[i] = 0xffffffff;
+         else
+           (*vS).w[i] = 0;
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.454:VXR:av:vcmpgefpx %VD, %VA, %VB:Vector Compare Greater-Than-or-Equal-to Floating Point
+       int i;
+       sim_fpu a, b;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         if (sim_fpu_is_ge(&a, &b))
+           (*vS).w[i] = 0xffffffff;
+         else
+           (*vS).w[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.710:VXR:av:vcmpgtfpx %VD, %VA, %VB:Vector Compare Greater-Than Floating Point
+       int i;
+       sim_fpu a, b;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         if (sim_fpu_is_gt(&a, &b))
+           (*vS).w[i] = 0xffffffff;
+         else
+           (*vS).w[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.774:VXR:av:vcmpgtsbx %VD, %VA, %VB:Vector Compare Greater-Than Signed Byte
+       int i;
+       signed8 a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         if (a > b)
+           (*vS).b[i] = 0xff;
+         else
+           (*vS).b[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.838:VXR:av:vcmpgtshx %VD, %VA, %VB:Vector Compare Greater-Than Signed Half Word
+       int i;
+       signed16 a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         if (a > b)
+           (*vS).h[i] = 0xffff;
+         else
+           (*vS).h[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.902:VXR:av:vcmpgtswx %VD, %VA, %VB:Vector Compare Greater-Than Signed Word
+       int i;
+       signed32 a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         if (a > b)
+           (*vS).w[i] = 0xffffffff;
+         else
+           (*vS).w[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.518:VXR:av:vcmpgtubx %VD, %VA, %VB:Vector Compare Greater-Than Unsigned Byte
+       int i;
+       unsigned8 a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         if (a > b)
+           (*vS).b[i] = 0xff;
+         else
+           (*vS).b[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.582:VXR:av:vcmpgtuhx %VD, %VA, %VB:Vector Compare Greater-Than Unsigned Half Word
+       int i;
+       unsigned16 a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         if (a > b)
+           (*vS).h[i] = 0xffff;
+         else
+           (*vS).h[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+0.4,6.VS,11.VA,16.VB,21.RC,22.646:VXR:av:vcmpgtuwx %VD, %VA, %VB:Vector Compare Greater-Than Unsigned Word
+       int i;
+       unsigned32 a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         if (a > b)
+           (*vS).w[i] = 0xffffffff;
+         else
+           (*vS).w[i] = 0;
+       }
+       if (RC)
+         ALTIVEC_SET_CR6(vS, 1);
+       PPC_INSN_VR_CR(VS_BITMASK, VA_BITMASK | VB_BITMASK, RC ? 0x000000f0 : 0);
+
+#
+# Vector Convert instructions, 6-65, 6-66.
+#
+
+0.4,6.VS,11.UIMM,16.VB,21.970:VX:av:vctsxs %VD, %VB, %UIMM:Vector Convert to Signed Fixed-Point Word Saturate
+       int i, sat, tempsat;
+       signed64 temp;
+       sim_fpu a, b, m;
+       sat = 0;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_u32to (&m, 2 << UIMM, sim_fpu_round_default);
+         sim_fpu_mul (&a, &b, &m);
+         sim_fpu_to64i (&temp, &a, sim_fpu_round_default);
+         (*vS).w[i] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.UIMM,16.VB,21.906:VX:av:vctuxs %VD, %VB, %UIMM:Vector Convert to Unsigned Fixed-Point Word Saturate
+       int i, sat, tempsat;
+       signed64 temp;
+       sim_fpu a, b, m;
+       sat = 0;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_u32to (&m, 2 << UIMM, sim_fpu_round_default);
+         sim_fpu_mul (&a, &b, &m);
+         sim_fpu_to64u (&temp, &a, sim_fpu_round_default);
+         (*vS).w[i] = altivec_unsigned_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VB_BITMASK);
+
+#
+# Vector Estimate instructions, 6-67 ... 6-70.
+#
+
+0.4,6.VS,11.0,16.VB,21.394:VX:av:vexptefp %VD, %VB:Vector 2 Raised to the Exponent Estimate Floating Point
+       int i;
+       unsigned32 f;
+       signed32 bi;
+       sim_fpu b, d;
+       for (i = 0; i < 4; i++) {
+         /*HACK!*/
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_to32i (&bi, &b, sim_fpu_round_default);
+         bi = 2 ^ bi;
+         sim_fpu_32to (&d, bi);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR_VSCR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.458:VX:av:vlogefp %VD, %VB:Vector Log2 Estimate Floating Point
+       int i;
+       unsigned32 c, u, f;
+       sim_fpu b, cfpu, d;
+       for (i = 0; i < 4; i++) {
+         /*HACK!*/
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_to32u (&u, &b, sim_fpu_round_default);
+         for (c = 0; (u /= 2) > 1; c++)
+           ;
+         sim_fpu_32to (&cfpu, c);
+         sim_fpu_add (&d, &b, &cfpu);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR_VSCR(VS_BITMASK, VB_BITMASK);
+
+#
+# Vector Multiply Add instruction, 6-71
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.46:VAX:av:vmaddfp %VD, %VA, %VB, %VC:Vector Multiply Add Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu a, b, c, d, e;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_32to (&c, (*vC).w[i]);
+         sim_fpu_mul (&e, &a, &c);
+         sim_fpu_add (&d, &e, &b);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+
+#
+# Vector Maximum instructions, 6-72 ... 6-78.
+#
+
+0.4,6.VS,11.VA,16.VB,21.1034:VX:av:vmaxfp %VD, %VA, %VB:Vector Maximum Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu a, b, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_max (&d, &a, &b);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.258:VX:av:vmaxsb %VD, %VA, %VB:Vector Maximum Signed Byte
+       int i;
+       signed8 a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         if (a > b)
+           (*vS).b[i] = a;
+         else
+           (*vS).b[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.322:VX:av:vmaxsh %VD, %VA, %VB:Vector Maximum Signed Half Word
+       int i;
+       signed16 a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         if (a > b)
+           (*vS).h[i] = a;
+         else
+           (*vS).h[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.386:VX:av:vmaxsw %VD, %VA, %VB:Vector Maximum Signed Word
+       int i;
+       signed32 a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         if (a > b)
+           (*vS).w[i] = a;
+         else
+           (*vS).w[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.2:VX:av:vmaxub %VD, %VA, %VB:Vector Maximum Unsigned Byte
+       int i;
+       unsigned8 a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         if (a > b)
+           (*vS).b[i] = a;
+         else
+           (*vS).b[i] = b;
+       };
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.66:VX:av:vmaxus %VD, %VA, %VB:Vector Maximum Unsigned Half Word
+       int i;
+       unsigned16 a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         if (a > b)
+           (*vS).h[i] = a;
+         else
+           (*vS).h[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.130:VX:av:vmaxuw %VD, %VA, %VB:Vector Maximum Unsigned Word
+       int i;
+       unsigned32 a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         if (a > b)
+           (*vS).w[i] = a;
+         else
+           (*vS).w[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Multiple High instructions, 6-79, 6-80.
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.32:VAX:av:vmhaddshs %VD, %VA, %VB, %VC:Vector Multiple High and Add Signed Half Word Saturate
+       int i, sat, tempsat;
+       signed16 a, b;
+       signed32 prod, temp, c;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         c = (signed32)(signed16)(*vC).h[i];
+         prod = (signed32)a * (signed32)b;
+         temp = (prod >> 15) + c;
+         (*vS).h[i] = altivec_signed_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.33:VAX:av:vmhraddshs %VD, %VA, %VB, %VC:Vector Multiple High Round and Add Signed Half Word Saturate
+       int i, sat, tempsat;
+       signed16 a, b;
+       signed32 prod, temp, c;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         c = (signed32)(signed16)(*vC).h[i];
+         prod = (signed32)a * (signed32)b;
+         prod += 0x4000;
+         temp = (prod >> 15) + c;
+         (*vS).h[i] = altivec_signed_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+
+#
+# Vector Minimum instructions, 6-81 ... 6-87
+#
+
+0.4,6.VS,11.VA,16.VB,21.1098:VX:av:vminfp %VD, %VA, %VB:Vector Minimum Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu a, b, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_min (&d, &a, &b);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.770:VX:av:vminsb %VD, %VA, %VB:Vector Minimum Signed Byte
+       int i;
+       signed8 a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         if (a < b)
+           (*vS).b[i] = a;
+         else
+           (*vS).b[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.834:VX:av:vminsh %VD, %VA, %VB:Vector Minimum Signed Half Word
+       int i;
+       signed16 a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         if (a < b)
+           (*vS).h[i] = a;
+         else
+           (*vS).h[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.898:VX:av:vminsw %VD, %VA, %VB:Vector Minimum Signed Word
+       int i;
+       signed32 a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         if (a < b)
+           (*vS).w[i] = a;
+         else
+           (*vS).w[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.514:VX:av:vminub %VD, %VA, %VB:Vector Minimum Unsigned Byte
+       int i;
+       unsigned8 a, b;
+       for (i = 0; i < 16; i++) {
+         a = (*vA).b[i];
+         b = (*vB).b[i];
+         if (a < b)
+           (*vS).b[i] = a;
+         else
+           (*vS).b[i] = b;
+       };
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.578:VX:av:vminuh %VD, %VA, %VB:Vector Minimum Unsigned Half Word
+       int i;
+       unsigned16 a, b;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         if (a < b)
+           (*vS).h[i] = a;
+         else
+           (*vS).h[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.642:VX:av:vminuw %VD, %VA, %VB:Vector Minimum Unsigned Word
+       int i;
+       unsigned32 a, b;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).w[i];
+         b = (*vB).w[i];
+         if (a < b)
+           (*vS).w[i] = a;
+         else
+           (*vS).w[i] = b;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Multiply Low instruction, 6-88
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.34:VAX:av:vmladduhm %VD, %VA, %VB, %VC:Vector Multiply Low and Add Unsigned Half Word Modulo
+       int i;
+       unsigned16 a, b, c;
+       unsigned32 prod;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).h[i];
+         b = (*vB).h[i];
+         c = (*vC).h[i];
+         prod = (unsigned32)a * (unsigned32)b;
+         (*vS).h[i] = (prod + c) & 0xffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+
+#
+# Vector Merge instructions, 6-89 ... 6-94
+#
+
+0.4,6.VS,11.VA,16.VB,21.12:VX:av:vmrghb %VD, %VA, %VB:Vector Merge High Byte
+       int i;
+       for (i = 0; i < 16; i += 2) {
+         (*vS).b[AV_BINDEX(i)] = (*vA).b[AV_BINDEX(i/2)];
+         (*vS).b[AV_BINDEX(i+1)] = (*vB).b[AV_BINDEX(i/2)]; 
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.76:VX:av:vmrghh %VD, %VA, %VB:Vector Merge High Half Word
+       int i;
+       for (i = 0; i < 8; i += 2) {
+         (*vS).h[AV_HINDEX(i)] = (*vA).h[AV_HINDEX(i/2)];
+         (*vS).h[AV_HINDEX(i+1)] = (*vB).h[AV_HINDEX(i/2)]; 
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.140:VX:av:vmrghw %VD, %VA, %VB:Vector Merge High Word
+       int i;
+       for (i = 0; i < 4; i += 2) {
+         (*vS).w[i] = (*vA).w[i/2];
+         (*vS).w[i+1] = (*vB).w[i/2]; 
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.268:VX:av:vmrglb %VD, %VA, %VB:Vector Merge Low Byte
+       int i;
+       for (i = 0; i < 16; i += 2) {
+         (*vS).b[AV_BINDEX(i)] = (*vA).b[AV_BINDEX((i/2) + 8)];
+         (*vS).b[AV_BINDEX(i+1)] = (*vB).b[AV_BINDEX((i/2) + 8)]; 
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.332:VX:av:vmrglh %VD, %VA, %VB:Vector Merge Low Half Word
+       int i;
+       for (i = 0; i < 8; i += 2) {
+         (*vS).h[AV_HINDEX(i)] = (*vA).h[AV_HINDEX((i/2) + 4)];
+         (*vS).h[AV_HINDEX(i+1)] = (*vB).h[AV_HINDEX((i/2) + 4)]; 
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.396:VX:av:vmrglw %VD, %VA, %VB:Vector Merge Low Word
+       int i;
+       for (i = 0; i < 4; i += 2) {
+         (*vS).w[i] = (*vA).w[(i/2) + 2];
+         (*vS).w[i+1] = (*vB).w[(i/2) + 2]; 
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Multiply Sum instructions, 6-95 ... 6-100
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.37:VAX:av:vmsummbm %VD, %VA, %VB, %VC:Vector Multiply Sum Mixed-Sign Byte Modulo
+       int i, j;
+       signed32 temp;
+       signed16 prod, a;
+       unsigned16 b;
+       for (i = 0; i < 4; i++) {
+         temp = (*vC).w[i];
+         for (j = 0; j < 4; j++) {
+           a = (signed16)(signed8)(*vA).b[i*4+j]; 
+           b = (*vB).b[i*4+j];
+           prod = a * b;
+           temp += (signed32)prod;
+         }
+         (*vS).w[i] = temp;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.40:VAX:av:vmsumshm %VD, %VA, %VB, %VC:Vector Multiply Sum Signed Half Word Modulo
+       int i, j;
+       signed32 temp, prod, a, b;
+       for (i = 0; i < 4; i++) {
+         temp = (*vC).w[i];
+         for (j = 0; j < 2; j++) {
+           a = (signed32)(signed16)(*vA).h[i*2+j]; 
+           b = (signed32)(signed16)(*vB).h[i*2+j];
+           prod = a * b;
+           temp += prod;
+         }
+         (*vS).w[i] = temp;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.41:VAX:av:vmsumshs %VD, %VA, %VB, %VC:Vector Multiply Sum Signed Half Word Saturate
+       int i, j, sat, tempsat;
+       signed64 temp;
+       signed32 prod, a, b;
+       sat = 0;
+       for (i = 0; i < 4; i++) {
+         temp = (signed64)(signed32)(*vC).w[i];
+         for (j = 0; j < 2; j++) {
+           a = (signed32)(signed16)(*vA).h[i*2+j]; 
+           b = (signed32)(signed16)(*vB).h[i*2+j];
+           prod = a * b;
+           temp += (signed64)prod;
+         }
+         (*vS).w[i] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.36:VAX:av:vmsumubm %VD, %VA, %VB, %VC:Vector Multiply Sum Unsigned Byte Modulo
+       int i, j;
+       unsigned32 temp;
+       unsigned16 prod, a, b;
+       for (i = 0; i < 4; i++) {
+         temp = (*vC).w[i];
+         for (j = 0; j < 4; j++) {
+           a = (*vA).b[i*4+j]; 
+           b = (*vB).b[i*4+j];
+           prod = a * b;
+           temp += prod;
+         }
+         (*vS).w[i] = temp;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.38:VAX:av:vmsumuhm %VD, %VA, %VB, %VC:Vector Multiply Sum Unsigned Half Word Modulo
+       int i, j;
+       unsigned32 temp, prod, a, b;
+       for (i = 0; i < 4; i++) {
+         temp = (*vC).w[i];
+         for (j = 0; j < 2; j++) {
+           a = (*vA).h[i*2+j]; 
+           b = (*vB).h[i*2+j];
+           prod = a * b;
+           temp += prod;
+         }
+         (*vS).w[i] = temp;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.39:VAX:av:vmsumuhs %VD, %VA, %VB, %VC:Vector Multiply Sum Unsigned Half Word Saturate
+       int i, j, sat, tempsat;
+       unsigned32 temp, prod, a, b;
+       sat = 0;
+       for (i = 0; i < 4; i++) {
+         temp = (*vC).w[i];
+         for (j = 0; j < 2; j++) {
+           a = (*vA).h[i*2+j]; 
+           b = (*vB).h[i*2+j];
+           prod = a * b;
+           temp += prod;
+         }
+         (*vS).w[i] = altivec_unsigned_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+
+#
+# Vector Multiply Even/Odd instructions, 6-101 ... 6-108
+#
+
+0.4,6.VS,11.VA,16.VB,21.776:VX:av:vmulesb %VD, %VA, %VB:Vector Multiply Even Signed Byte
+       int i;
+       signed8 a, b;
+       signed16 prod;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).b[AV_BINDEX(i*2)]; 
+         b = (*vB).b[AV_BINDEX(i*2)];
+         prod = a * b;
+         (*vS).h[AV_HINDEX(i)] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.840:VX:av:vmulesh %VD, %VA, %VB:Vector Multiply Even Signed Half Word
+       int i;
+       signed16 a, b;
+       signed32 prod;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).h[AV_HINDEX(i*2)]; 
+         b = (*vB).h[AV_HINDEX(i*2)];
+         prod = a * b;
+         (*vS).w[i] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.520:VX:av:vmuleub %VD, %VA, %VB:Vector Multiply Even Unsigned Byte
+       int i;
+       unsigned8 a, b;
+       unsigned16 prod;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).b[AV_BINDEX(i*2)]; 
+         b = (*vB).b[AV_BINDEX(i*2)];
+         prod = a * b;
+         (*vS).h[AV_HINDEX(i)] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.584:VX:av:vmuleuh %VD, %VA, %VB:Vector Multiply Even Unsigned Half Word
+       int i;
+       unsigned16 a, b;
+       unsigned32 prod;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).h[AV_HINDEX(i*2)]; 
+         b = (*vB).h[AV_HINDEX(i*2)];
+         prod = a * b;
+         (*vS).w[i] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.264:VX:av:vmulosb %VD, %VA, %VB:Vector Multiply Odd Signed Byte
+       int i;
+       signed8 a, b;
+       signed16 prod;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).b[AV_BINDEX((i*2)+1)]; 
+         b = (*vB).b[AV_BINDEX((i*2)+1)];
+         prod = a * b;
+         (*vS).h[AV_HINDEX(i)] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.328:VX:av:vmulosh %VD, %VA, %VB:Vector Multiply Odd Signed Half Word
+       int i;
+       signed16 a, b;
+       signed32 prod;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).h[AV_HINDEX((i*2)+1)]; 
+         b = (*vB).h[AV_HINDEX((i*2)+1)];
+         prod = a * b;
+         (*vS).w[i] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.8:VX:av:vmuloub %VD, %VA, %VB:Vector Multiply Odd Unsigned Byte
+       int i;
+       unsigned8 a, b;
+       unsigned16 prod;
+       for (i = 0; i < 8; i++) {
+         a = (*vA).b[AV_BINDEX((i*2)+1)]; 
+         b = (*vB).b[AV_BINDEX((i*2)+1)];
+         prod = a * b;
+         (*vS).h[AV_HINDEX(i)] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.72:VX:av:vmulouh %VD, %VA, %VB:Vector Multiply Odd Unsigned Half Word
+       int i;
+       unsigned16 a, b;
+       unsigned32 prod;
+       for (i = 0; i < 4; i++) {
+         a = (*vA).h[AV_HINDEX((i*2)+1)]; 
+         b = (*vB).h[AV_HINDEX((i*2)+1)];
+         prod = a * b;
+         (*vS).w[i] = prod;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Negative Multiply-Subtract instruction, 6-109
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.47:VX:av:vnmsubfp %VD, %VA, %VB, %VC:Vector Negative Multiply-Subtract Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu a, b, c, d, i1, i2;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_32to (&c, (*vC).w[i]);
+         sim_fpu_mul (&i1, &a, &c);
+         sim_fpu_sub (&i2, &i1, &b);
+         sim_fpu_neg (&d, &i2);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+
+#
+# Vector Logical OR instructions, 6-110, 6-111, 6-177
+#
+
+0.4,6.VS,11.VA,16.VB,21.1284:VX:av:vnor %VD, %VA, %VB:Vector Logical NOR
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = ~((*vA).w[i] | (*vB).w[i]);
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1156:VX:av:vor %VD, %VA, %VB:Vector Logical OR
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (*vA).w[i] | (*vB).w[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1220:VX:av:vxor %VD, %VA, %VB:Vector Logical XOR
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (*vA).w[i] ^ (*vB).w[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Permute instruction, 6-112
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.43:VX:av:vperm %VD, %VA, %VB, %VC:Vector Permute
+       int i, who;
+       for (i = 0; i < 16; i++) {
+         who = (*vC).b[AV_BINDEX(i)] & 0x1f;
+         if (who & 0x10)
+           (*vS).b[AV_BINDEX(i)] = (*vB).b[AV_BINDEX(who & 0xf)];
+         else
+           (*vS).b[AV_BINDEX(i)] = (*vA).b[AV_BINDEX(who & 0xf)];
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+
+#
+# Vector Pack instructions, 6-113 ... 6-121
+#
+
+0.4,6.VS,11.VA,16.VB,21.782:VX:av:vpkpx %VD, %VA, %VB:Vector Pack Pixel32
+       int i;
+       for (i = 0; i < 4; i++) {
+         (*vS).h[AV_HINDEX(i+4)] = ((((*vB).w[i]) >> 9) & 0xfc00)
+                      | ((((*vB).w[i]) >> 6) & 0x03e0)
+                      | ((((*vB).w[i]) >> 3) & 0x001f);
+         (*vS).h[AV_HINDEX(i)] = ((((*vA).w[i]) >> 9) & 0xfc00)
+                    | ((((*vA).w[i]) >> 6) & 0x03e0)
+                    | ((((*vA).w[i]) >> 3) & 0x001f);
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.398:VX:av:vpkshss %VD, %VA, %VB:Vector Pack Signed Half Word Signed Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       sat = 0;
+       for (i = 0; i < 16; i++) {
+         if (i < 8)
+           temp = (*vA).h[AV_HINDEX(i)];
+         else
+           temp = (*vB).h[AV_HINDEX(i-8)];
+         (*vS).b[AV_BINDEX(i)] = altivec_signed_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.270:VX:av:vpkshus %VD, %VA, %VB:Vector Pack Signed Half Word Unsigned Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       sat = 0;
+       for (i = 0; i < 16; i++) {
+         if (i < 8)
+           temp = (*vA).h[AV_HINDEX(i)];
+         else
+           temp = (*vB).h[AV_HINDEX(i-8)];
+         (*vS).b[AV_BINDEX(i)] = altivec_unsigned_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.462:VX:av:vpkswss %VD, %VA, %VB:Vector Pack Signed Word Signed Saturate
+       int i, sat, tempsat;
+       signed32 temp;
+       sat = 0;
+       for (i = 0; i < 8; i++) {
+         if (i < 4)
+           temp = (*vA).w[i];
+         else
+           temp = (*vB).w[i-4];
+         (*vS).h[AV_HINDEX(i)] = altivec_signed_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.334:VX:av:vpkswus %VD, %VA, %VB:Vector Pack Signed Word Unsigned Saturate
+       int i, sat, tempsat;
+       signed32 temp;
+       sat = 0;
+       for (i = 0; i < 8; i++) {
+         if (i < 4)
+           temp = (*vA).w[i];
+         else
+           temp = (*vB).w[i-4];
+         (*vS).h[AV_HINDEX(i)] = altivec_unsigned_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.14:VX:av:vpkuhum %VD, %VA, %VB:Vector Pack Unsigned Half Word Unsigned Modulo
+       int i;
+       for (i = 0; i < 16; i++)
+         if (i < 8)
+           (*vS).b[AV_BINDEX(i)] = (*vA).h[AV_HINDEX(i)];
+         else
+           (*vS).b[AV_BINDEX(i)] = (*vB).h[AV_HINDEX(i-8)];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.142:VX:av:vpkuhus %VD, %VA, %VB:Vector Pack Unsigned Half Word Unsigned Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       sat = 0;
+       for (i = 0; i < 16; i++) {
+         if (i < 8)
+           temp = (*vA).h[AV_HINDEX(i)];
+         else
+           temp = (*vB).h[AV_HINDEX(i-8)];
+         /* force positive in signed16, ok as we'll toss the bit away anyway */
+         temp &= ~0x8000;
+         (*vS).b[AV_BINDEX(i)] = altivec_unsigned_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.78:VX:av:vpkuwum %VD, %VA, %VB:Vector Pack Unsigned Word Unsigned Modulo
+       int i;
+       for (i = 0; i < 8; i++)
+         if (i < 8)
+           (*vS).h[AV_HINDEX(i)] = (*vA).w[i];
+         else
+           (*vS).h[AV_HINDEX(i)] = (*vB).w[i-8];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.206:VX:av:vpkuwus %VD, %VA, %VB:Vector Pack Unsigned Word Unsigned Saturate
+       int i, sat, tempsat;
+       signed32 temp;
+       sat = 0;
+       for (i = 0; i < 8; i++) {
+         if (i < 4)
+           temp = (*vA).w[i];
+         else
+           temp = (*vB).w[i-4];
+         /* force positive in signed32, ok as we'll toss the bit away anyway */
+         temp &= ~0x80000000;
+         (*vS).h[AV_HINDEX(i)] = altivec_unsigned_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Reciprocal instructions, 6-122, 6-123, 6-131
+#
+
+0.4,6.VS,11.0,16.VB,21.266:VX:av:vrefp %VD, %VB:Vector Reciprocal Estimate Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu op, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&op, (*vB).w[i]);
+         sim_fpu_div (&d, &sim_fpu_one, &op);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.330:VX:av:vrsqrtefp %VD, %VB:Vector Reciprocal Square Root Estimate Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu op, i1, one, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&op, (*vB).w[i]);
+         sim_fpu_sqrt (&i1, &op);
+         sim_fpu_div (&d, &sim_fpu_one, &i1);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+
+#
+# Vector Round instructions, 6-124 ... 6-127
+#
+
+0.4,6.VS,11.0,16.VB,21.714:VX:av:vrfim %VD, %VB:Vector Round to Floating-Point Integer towards Minus Infinity
+       int i;
+       unsigned32 f;
+       sim_fpu op;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&op, (*vB).w[i]);
+         sim_fpu_round_32(&op, sim_fpu_round_down, sim_fpu_denorm_default);
+         sim_fpu_to32 (&f, &op);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.522:VX:av:vrfin %VD, %VB:Vector Round to Floating-Point Integer Nearest
+       int i;
+       unsigned32 f;
+       sim_fpu op;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&op, (*vB).w[i]);
+         sim_fpu_round_32(&op, sim_fpu_round_near, sim_fpu_denorm_default);
+         sim_fpu_to32 (&f, &op);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.650:VX:av:vrfip %VD, %VB:Vector Round to Floating-Point Integer towards Plus Infinity
+       int i;
+       unsigned32 f;
+       sim_fpu op;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&op, (*vB).w[i]);
+         sim_fpu_round_32(&op, sim_fpu_round_up, sim_fpu_denorm_default);
+         sim_fpu_to32 (&f, &op);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.586:VX:av:vrfiz %VD, %VB:Vector Round to Floating-Point Integer towards Zero
+       int i;
+       unsigned32 f;
+       sim_fpu op;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&op, (*vB).w[i]);
+         sim_fpu_round_32(&op, sim_fpu_round_zero, sim_fpu_denorm_default);
+         sim_fpu_to32 (&f, &op);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+
+#
+# Vector Rotate Left instructions, 6-128 ... 6-130
+#
+
+0.4,6.VS,11.VA,16.VB,21.4:VX:av:vrlb %VD, %VA, %VB:Vector Rotate Left Integer Byte
+       int i;
+       unsigned16 temp;
+       for (i = 0; i < 16; i++) {
+         temp = (unsigned16)(*vA).b[i] << (((*vB).b[i]) & 7);
+         (*vS).b[i] = (temp & 0xff) | ((temp >> 8) & 0xff);
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.68:VX:av:vrlh %VD, %VA, %VB:Vector Rotate Left Integer Half Word
+       int i;
+       unsigned32 temp;
+       for (i = 0; i < 8; i++) {
+         temp = (unsigned32)(*vA).h[i] << (((*vB).h[i]) & 0xf);
+         (*vS).h[i] = (temp & 0xffff) | ((temp >> 16) & 0xffff);
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.132:VX:av:vrlw %VD, %VA, %VB:Vector Rotate Left Integer Word
+       int i;
+       unsigned64 temp;
+       for (i = 0; i < 4; i++) {
+         temp = (unsigned64)(*vA).w[i] << (((*vB).w[i]) & 0x1f);
+         (*vS).w[i] = (temp & 0xffffffff) | ((temp >> 32) & 0xffffffff);
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Conditional Select instruction, 6-133
+#
+
+0.4,6.VS,11.VA,16.VB,21.VC,26.42:VAX:av:vsel %VD, %VA, %VB, %VC:Vector Conditional Select
+       int i;
+       unsigned32 c;
+       for (i = 0; i < 4; i++) {
+         c = (*vC).w[i];
+         (*vS).w[i] = ((*vB).w[i] & c) | ((*vA).w[i] & ~c);
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK | VC_BITMASK);
+
+#
+# Vector Shift Left instructions, 6-134 ... 6-139
+#
+
+0.4,6.VS,11.VA,16.VB,21.452:VX:av:vsl %VD, %VA, %VB:Vector Shift Left
+       int sh, i, j, carry, new_carry;
+       sh = (*vB).b[0] & 7;    /* don't bother checking everything */
+       carry = 0;
+       for (j = 3; j >= 0; j--) {
+         if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+           i = j;
+         else
+           i = (j + 2) % 4;
+         new_carry = (*vA).w[i] >> (32 - sh);
+         (*vS).w[i] = ((*vA).w[i] << sh) | carry;
+         carry = new_carry;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.260:VX:av:vslb %VD, %VA, %VB:Vector Shift Left Integer Byte
+       int i, sh;
+       for (i = 0; i < 16; i++) {
+         sh = ((*vB).b[i]) & 7;
+         (*vS).b[i] = (*vA).b[i] << sh;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.0,22.SH,26.44:VX:av:vsldol %VD, %VA, %VB:Vector Shift Left Double by Octet Immediate
+       int i, j;
+       for (j = 0, i = SH; i < 16; i++)
+         (*vS).b[j++] = (*vA).b[i];
+       for (i = 0; i < SH; i++)
+         (*vS).b[j++] = (*vB).b[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.324:VX:av:vslh %VD, %VA, %VB:Vector Shift Left Half Word
+       int i, sh;
+       for (i = 0; i < 8; i++) {
+         sh = ((*vB).h[i]) & 0xf;
+         (*vS).h[i] = (*vA).h[i] << sh;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1036:VX:av:vslo %VD, %VA, %VB:Vector Shift Left by Octet
+       int i, sh;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+         sh = ((*vB).b[AV_BINDEX(15)] >> 3) & 0xf;
+       else
+         sh = ((*vB).b[AV_BINDEX(0)] >> 3) & 0xf;
+       for (i = 0; i < 16; i++) {
+         if (15 - i > sh)
+           (*vS).b[AV_BINDEX(i)] = (*vA).b[AV_BINDEX(i + sh)];
+         else
+           (*vS).b[AV_BINDEX(i)] = 0;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.388:VX:av:vslw %VD, %VA, %VB:Vector Shift Left Integer Word
+       int i, sh;
+       for (i = 0; i < 4; i++) {
+         sh = ((*vB).w[i]) & 0x1f;
+         (*vS).w[i] = (*vA).w[i] << sh;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Splat instructions, 6-140 ... 6-145
+#
+
+0.4,6.VS,11.UIMM,16.VB,21.524:VX:av:vspltb %VD, %VB, %UIMM:Vector Splat Byte
+       int i;
+       unsigned8 b;
+       b = (*vB).b[AV_BINDEX(UIMM & 0xf)];
+       for (i = 0; i < 16; i++)
+         (*vS).b[i] = b;
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.UIMM,16.VB,21.588:VX:av:vsplth %VD, %VB, %UIMM:Vector Splat Half Word
+       int i;
+       unsigned16 h;
+       h = (*vB).h[AV_HINDEX(UIMM & 0x7)];
+       for (i = 0; i < 8; i++)
+         (*vS).h[i] = h;
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.SIMM,16.0,21.780:VX:av:vspltisb %VD, %SIMM:Vector Splat Immediate Signed Byte
+       int i;
+       signed8 b = SIMM;
+       /* manual 5-bit signed extension */
+       if (b & 0x10)
+         b -= 0x20;
+       for (i = 0; i < 16; i++)
+         (*vS).b[i] = b;
+       PPC_INSN_VR(VS_BITMASK, 0);
+
+0.4,6.VS,11.SIMM,16.0,21.844:VX:av:vspltish %VD, %SIMM:Vector Splat Immediate Signed Half Word
+       int i;
+       signed16 h = SIMM;
+       /* manual 5-bit signed extension */
+       if (h & 0x10)
+         h -= 0x20;
+       for (i = 0; i < 8; i++)
+         (*vS).h[i] = h;
+       PPC_INSN_VR(VS_BITMASK, 0);
+
+0.4,6.VS,11.SIMM,16.0,21.908:VX:av:vspltisw %VD, %SIMM:Vector Splat Immediate Signed Word
+       int i;
+       signed32 w = SIMM;
+       /* manual 5-bit signed extension */
+       if (w & 0x10)
+         w -= 0x20;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = w;
+       PPC_INSN_VR(VS_BITMASK, 0);
+
+0.4,6.VS,11.UIMM,16.VB,21.652:VX:av:vspltw %VD, %VB, %UIMM:Vector Splat Word
+       int i;
+       unsigned32 w;
+       w = (*vB).w[UIMM & 0x3];
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = w;
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+
+#
+# Vector Shift Right instructions, 6-146 ... 6-154
+#
+
+0.4,6.VS,11.VA,16.VB,21.708:VX:av:vsr %VD, %VA, %VB:Vector Shift Right
+       int sh, i, j, carry, new_carry;
+       sh = (*vB).b[0] & 7;    /* don't bother checking everything */
+       carry = 0;
+       for (j = 0; j < 4; j++) {
+         if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+           i = j;
+         else
+           i = (j + 2) % 4;
+         new_carry = (*vA).w[i] << (32 - sh);
+         (*vS).w[i] = ((*vA).w[i] >> sh) | carry;
+         carry = new_carry;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.772:VX:av:vsrab %VD, %VA, %VB:Vector Shift Right Algebraic Byte
+       int i, sh;
+       signed16 a;
+       for (i = 0; i < 16; i++) {
+         sh = ((*vB).b[i]) & 7;
+         a = (signed16)(signed8)(*vA).b[i];
+         (*vS).b[i] = (a >> sh) & 0xff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.836:VX:av:vsrah %VD, %VA, %VB:Vector Shift Right Algebraic Half Word
+       int i, sh;
+       signed32 a;
+       for (i = 0; i < 8; i++) {
+         sh = ((*vB).h[i]) & 0xf;
+         a = (signed32)(signed16)(*vA).h[i];
+         (*vS).h[i] = (a >> sh) & 0xffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.900:VX:av:vsraw %VD, %VA, %VB:Vector Shift Right Algebraic Word
+       int i, sh;
+       signed64 a;
+       for (i = 0; i < 4; i++) {
+         sh = ((*vB).w[i]) & 0xf;
+         a = (signed64)(signed32)(*vA).w[i];
+         (*vS).w[i] = (a >> sh) & 0xffffffff;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.516:VX:av:vsrb %VD, %VA, %VB:Vector Shift Right Byte
+       int i, sh;
+       for (i = 0; i < 16; i++) {
+         sh = ((*vB).b[i]) & 7;
+         (*vS).b[i] = (*vA).b[i] >> sh;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.580:VX:av:vsrh %VD, %VA, %VB:Vector Shift Right Half Word
+       int i, sh;
+       for (i = 0; i < 8; i++) {
+         sh = ((*vB).h[i]) & 0xf;
+         (*vS).h[i] = (*vA).h[i] >> sh;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1100:VX:av:vsro %VD, %VA, %VB:Vector Shift Right Octet
+       int i, sh;
+       if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+         sh = ((*vB).b[AV_BINDEX(15)] >> 3) & 0xf;
+       else
+         sh = ((*vB).b[AV_BINDEX(0)] >> 3) & 0xf;
+       for (i = 0; i < 16; i++) {
+         if (i < sh)
+           (*vS).b[AV_BINDEX(i)] = 0;
+         else
+           (*vS).b[AV_BINDEX(i)] = (*vA).b[AV_BINDEX(i - sh)];
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.644:VX:av:vsrw %VD, %VA, %VB:Vector Shift Right Word
+       int i, sh;
+       for (i = 0; i < 4; i++) {
+         sh = ((*vB).w[i]) & 0x1f;
+         (*vS).w[i] = (*vA).w[i] >> sh;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Subtract instructions, 6-155 ... 6-165
+#
+
+0.4,6.VS,11.VA,16.VB,21.1408:VX:av:vsubcuw %VD, %VA, %VB:Vector Subtract Carryout Unsigned Word
+       int i;
+       signed64 temp, a, b;
+       for (i = 0; i < 4; i++) {
+         a = (signed64)(unsigned32)(*vA).w[i];
+         b = (signed64)(unsigned32)(*vB).w[i];
+         temp = a - b;
+         (*vS).w[i] = ~(temp >> 32) & 1;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.74:VX:av:vsubfp %VD, %VA, %VB:Vector Subtract Floating Point
+       int i;
+       unsigned32 f;
+       sim_fpu a, b, d;
+       for (i = 0; i < 4; i++) {
+         sim_fpu_32to (&a, (*vA).w[i]);
+         sim_fpu_32to (&b, (*vB).w[i]);
+         sim_fpu_sub (&d, &a, &b);
+         sim_fpu_to32 (&f, &d);
+         (*vS).w[i] = f;
+       }
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1792:VX:av:vsubsbs %VD, %VA, %VB:Vector Subtract Signed Byte Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       sat = 0;
+       for (i = 0; i < 16; i++) {
+         temp = (signed16)(signed8)(*vA).b[i] - (signed16)(signed8)(*vB).b[i];
+         (*vS).b[i] = altivec_signed_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1856:VX:av:vsubshs %VD, %VA, %VB:Vector Subtract Signed Half Word Saturate
+       int i, sat, tempsat;
+       signed32 temp;
+       sat = 0;
+       for (i = 0; i < 8; i++) {
+         temp = (signed32)(signed16)(*vA).h[i] - (signed32)(signed16)(*vB).h[i];
+         (*vS).h[i] = altivec_signed_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1920:VX:av:vsubsws %VD, %VA, %VB:Vector Subtract Signed Word Saturate
+       int i, sat, tempsat;
+       signed64 temp;
+       sat = 0;
+       for (i = 0; i < 4; i++) {
+         temp = (signed64)(signed32)(*vA).w[i] - (signed64)(signed32)(*vB).w[i];
+         (*vS).w[i] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1024:VX:av:vsububm %VD, %VA, %VB:Vector Subtract Unsigned Byte Modulo
+       int i;
+       for (i = 0; i < 16; i++)
+         (*vS).b[i] = (*vA).b[i] - (*vB).b[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1536:VX:av:vsububs %VD, %VA, %VB:Vector Subtract Unsigned Byte Saturate
+       int i, sat, tempsat;
+       signed16 temp;
+       sat = 0;
+       for (i = 0; i < 16; i++) {
+         temp = (signed16)(unsigned8)(*vA).b[i] - (signed16)(unsigned8)(*vB).b[i];
+         (*vS).b[i] = altivec_unsigned_saturate_8(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1088:VX:av:vsubuhm %VD, %VA, %VB:Vector Subtract Unsigned Half Word Modulo
+       int i;
+       for (i = 0; i < 8; i++)
+         (*vS).h[i] = ((*vA).h[i] - (*vB).h[i]) & 0xffff;
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1600:VX:av:vsubuhs %VD, %VA, %VB:Vector Subtract Unsigned Half Word Saturate
+       int i, sat, tempsat;
+       signed32 temp;
+       for (i = 0; i < 8; i++) {
+         temp = (signed32)(unsigned16)(*vA).h[i] - (signed32)(unsigned16)(*vB).h[i];
+         (*vS).h[i] = altivec_unsigned_saturate_16(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1152:VX:av:vsubuwm %VD, %VA, %VB:Vector Subtract Unsigned Word Modulo
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (*vA).w[i] - (*vB).w[i];
+       PPC_INSN_VR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1664:VX:av:vsubuws %VD, %VA, %VB:Vector Subtract Unsigned Word Saturate
+       int i, sat, tempsat;
+       signed64 temp;
+       for (i = 0; i < 4; i++) {
+         temp = (signed64)(unsigned32)(*vA).w[i] - (signed64)(unsigned32)(*vB).w[i];
+         (*vS).w[i] = altivec_unsigned_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Sum instructions, 6-166 ... 6-170
+#
+
+0.4,6.VS,11.VA,16.VB,21.1928:VX:av:vsumsws %VD, %VA, %VB:Vector Sum Across Signed Word Saturate
+       int i, sat;
+       signed64 temp;
+       temp = (signed64)(signed32)(*vB).w[3];
+       for (i = 0; i < 4; i++)
+         temp += (signed64)(signed32)(*vA).w[i];
+       (*vS).w[3] = altivec_signed_saturate_32(temp, &sat);
+       (*vS).w[0] = (*vS).w[1] = (*vS).w[2] = 0;
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1672:VX:av:vsum2sws %VD, %VA, %VB:Vector Sum Across Partial (1/2) Signed Word Saturate
+       int i, j, sat, tempsat;
+       signed64 temp;
+       for (j = 0; j < 4; j += 2) {
+         temp = (signed64)(signed32)(*vB).w[j+1];
+         temp += (signed64)(signed32)(*vA).w[j] + (signed64)(signed32)(*vA).w[j+1];
+         (*vS).w[j+1] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       (*vS).w[0] = (*vS).w[2] = 0;
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1800:VX:av:vsum4sbs %VD, %VA, %VB:Vector Sum Across Partial (1/4) Signed Byte Saturate
+       int i, j, sat, tempsat;
+       signed64 temp;
+       for (j = 0; j < 4; j++) {
+         temp = (signed64)(signed32)(*vB).w[j];
+         for (i = 0; i < 4; i++)
+           temp += (signed64)(signed8)(*vA).b[i+(j*4)];
+         (*vS).w[j] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1608:VX:av:vsum4shs %VD, %VA, %VB:Vector Sum Across Partial (1/4) Signed Half Word Saturate
+       int i, j, sat, tempsat;
+       signed64 temp;
+       for (j = 0; j < 4; j++) {
+         temp = (signed64)(signed32)(*vB).w[j];
+         for (i = 0; i < 2; i++)
+           temp += (signed64)(signed16)(*vA).h[i+(j*2)];
+         (*vS).w[j] = altivec_signed_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+0.4,6.VS,11.VA,16.VB,21.1544:VX:av:vsum4ubs %VD, %VA, %VB:Vector Sum Across Partial (1/4) Unsigned Byte Saturate
+       int i, j, sat, tempsat;
+       signed64 utemp;
+       signed64 temp;
+       for (j = 0; j < 4; j++) {
+         utemp = (signed64)(unsigned32)(*vB).w[j];
+         for (i = 0; i < 4; i++)
+           utemp += (signed64)(unsigned16)(*vA).b[i+(j*4)];
+         temp = utemp;
+         (*vS).w[j] = altivec_unsigned_saturate_32(temp, &tempsat);
+         sat |= tempsat;
+       }
+       ALTIVEC_SET_SAT(sat);
+       PPC_INSN_VR_VSCR(VS_BITMASK, VA_BITMASK | VB_BITMASK);
+
+
+#
+# Vector Unpack instructions, 6-171 ... 6-176
+#
+
+0.4,6.VS,11.0,16.VB,21.846:VX:av:vupkhpx %VD, %VB:Vector Unpack High Pixel16
+       int i;
+       unsigned16 h;
+       for (i = 0; i < 4; i++) {
+         h = (*vB).h[AV_HINDEX(i)];
+         (*vS).w[i] = ((h & 0x8000) ? 0xff000000 : 0)
+                    | ((h & 0x7c00) << 6)
+                    | ((h & 0x03e0) << 3)
+                    | ((h & 0x001f));
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.526:VX:av:vupkhsb %VD, %VB:Vector Unpack High Signed Byte
+       int i;
+       for (i = 0; i < 8; i++)
+         (*vS).h[AV_HINDEX(i)] = (signed16)(signed8)(*vB).b[AV_BINDEX(i)];
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.590:VX:av:vupkhsh %VD, %VB:Vector Unpack High Signed Half Word
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (signed32)(signed16)(*vB).h[AV_HINDEX(i)];
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.974:VX:av:vupklpx %VD, %VB:Vector Unpack Low Pixel16
+       int i;
+       unsigned16 h;
+       for (i = 0; i < 4; i++) {
+         h = (*vB).h[AV_HINDEX(i + 4)];
+         (*vS).w[i] = ((h & 0x8000) ? 0xff000000 : 0)
+                    | ((h & 0x7c00) << 6)
+                    | ((h & 0x03e0) << 3)
+                    | ((h & 0x001f));
+       }
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.654:VX:av:vupklsb %VD, %VB:Vector Unpack Low Signed Byte
+       int i;
+       for (i = 0; i < 8; i++)
+         (*vS).h[AV_HINDEX(i)] = (signed16)(signed8)(*vB).b[AV_BINDEX(i + 8)];
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
+
+0.4,6.VS,11.0,16.VB,21.718:VX:av:vupklsh %VD, %VB:Vector Unpack Low Signed Half Word
+       int i;
+       for (i = 0; i < 4; i++)
+         (*vS).w[i] = (signed32)(signed16)(*vB).h[AV_HINDEX(i + 4)];
+       PPC_INSN_VR(VS_BITMASK, VB_BITMASK);
diff --git a/sim/ppc/altivec_expression.h b/sim/ppc/altivec_expression.h
new file mode 100644 (file)
index 0000000..6cf2e76
--- /dev/null
@@ -0,0 +1,50 @@
+/* Altivec expression macros, for PSIM, the PowerPC simulator.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Red Hat Inc; developed under contract from Motorola.
+   Written by matthew green <mrg@redhat.com>.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* AltiVec macro helpers.  */
+
+#define ALTIVEC_SET_CR6(vS, checkone) \
+do { \
+  if (checkone && ((*vS).w[0] == 0xffffffff && \
+                  (*vS).w[1] == 0xffffffff && \
+                  (*vS).w[2] == 0xffffffff && \
+                  (*vS).w[3] == 0xffffffff)) \
+    CR_SET(6, 1 << 3); \
+  else if ((*vS).w[0] == 0 && \
+           (*vS).w[1] == 0 && \
+           (*vS).w[2] == 0 && \
+           (*vS).w[3] == 0) \
+    CR_SET(6, 1 << 1); \
+  else \
+    CR_SET(6, 0); \
+} while (0)
+
+#define        VSCR_SAT        0x00000001
+#define        VSCR_NJ         0x00010000
+
+#define ALTIVEC_SET_SAT(sat) \
+do { \
+  if (sat) \
+    VSCR |= VSCR_SAT; \
+} while (0)
diff --git a/sim/ppc/altivec_registers.h b/sim/ppc/altivec_registers.h
new file mode 100644 (file)
index 0000000..923f5c4
--- /dev/null
@@ -0,0 +1,63 @@
+/* Altivec registers, for PSIM, the PowerPC simulator.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Red Hat Inc; developed under contract from Motorola.
+   Written by matthew green <mrg@redhat.com>.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* Manage this as 4 32-bit entities, 8 16-bit entities or 16 8-bit
+   entities.  */
+typedef union
+{
+  unsigned8 b[16];
+  unsigned16 h[8];
+  unsigned32 w[4];
+} vreg;
+
+typedef unsigned32 vscreg;
+
+struct altivec_regs {
+  /* AltiVec Registers */
+  vreg vr[32];
+  vscreg vscr;
+};
+
+/* AltiVec registers */
+#define VR(N)          cpu_registers(processor)->altivec.vr[N]
+
+/* AltiVec vector status and control register */
+#define VSCR           cpu_registers(processor)->altivec.vscr
+
+/* AltiVec endian helpers, wrong endian hosts vs targets need to be
+   sure to get the right bytes/halfs/words when the order matters.
+   Note that many AltiVec instructions do not depend on byte order and
+   work on N independant bits of data.  This is only for the
+   instructions that actually move data around.  */
+
+#if (WITH_HOST_BYTE_ORDER == BIG_ENDIAN)
+#define AV_BINDEX(x)   ((x) & 15)
+#define AV_HINDEX(x)   ((x) & 7)
+#else
+static char endian_b2l_bindex[16] = { 3, 2, 1, 0, 7, 6, 5, 4,
+                            11, 10, 9, 8, 15, 14, 13, 12 };
+static char endian_b2l_hindex[16] = { 1, 0, 3, 2, 5, 4, 7, 6 };
+#define AV_BINDEX(x)   endian_b2l_bindex[(x) & 15]
+#define AV_HINDEX(x)   endian_b2l_hindex[(x) & 7]
+#endif
diff --git a/sim/ppc/e500.igen b/sim/ppc/e500.igen
new file mode 100644 (file)
index 0000000..f4ebfc7
--- /dev/null
@@ -0,0 +1,3348 @@
+# e500 core instructions, for PSIM, the PowerPC simulator.
+
+# Copyright 2003  Free Software Foundation, Inc.
+
+# Contributed by Red Hat Inc; developed under contract from Motorola.
+# Written by matthew green <mrg@redhat.com>.
+
+# This file is part of GDB.
+
+# 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, 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; see the file COPYING.  If not, write to
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+#
+# e500 Core Complex Instructions
+#
+
+:cache:e500::signed_word *:rAh:RA:(cpu_registers(processor)->e500.gprh + RA)
+:cache:e500::signed_word *:rSh:RS:(cpu_registers(processor)->e500.gprh + RS)
+:cache:e500::signed_word *:rBh:RB:(cpu_registers(processor)->e500.gprh + RB)
+
+# Flags for model.h
+::model-macro:::
+       #define PPC_INSN_INT_SPR(OUT_MASK, IN_MASK, SPR) \
+               do { \
+                 if (CURRENT_MODEL_ISSUE > 0) \
+                   ppc_insn_int_spr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, SPR); \
+               } while (0)
+
+# Schedule an instruction that takes 2 integer register and produces a special purpose output register plus an integer output register
+void::model-function::ppc_insn_int_spr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned nSPR
+       const unsigned32 int_mask = out_mask | in_mask;
+       model_busy *busy_ptr;
+
+       while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
+         if (WITH_TRACE && ppc_trace[trace_model])
+           model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
+
+         model_ptr->nr_stalls_data++;
+         model_new_cycle(model_ptr);
+       }
+
+       busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+       busy_ptr->int_busy |= out_mask;
+       model_ptr->int_busy |= out_mask;
+       busy_ptr->spr_busy = nSPR;
+       model_ptr->spr_busy[nSPR] = 1;
+       busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 3 : 2;
+       TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR)));
+\f
+#
+# SPE Modulo Fractional Multiplication handling support
+#
+:function:e500::unsigned64:ev_multiply16_smf:signed16 a, signed16 b, int *sat
+       signed32 a32 = a, b32 = b, rv32;
+       rv32 = a * b;
+       *sat = (rv32 & (3<<30)) == (3<<30);
+       return (signed64)rv32 << 1;
+
+:function:e500::unsigned64:ev_multiply32_smf:signed32 a, signed32 b, int *sat
+       signed64 rv64, a64 = a, b64 = b;
+       rv64 = a64 * b64;
+       *sat = (rv64 & ((signed64)3<<62)) == ((signed64)3<<62);
+       /* Loses top sign bit.  */
+       return rv64 << 1;
+#
+# SPE Saturation handling support
+#
+:function:e500::signed32:ev_multiply16_ssf:signed16 a, signed16 b, int *sat
+       signed32 rv32;
+       if (a == 0xffff8000 && b == 0xffff8000)
+         {
+           rv32 = 0x7fffffffL;
+           * sat = 1;
+           return rv32;
+         }
+       else
+         {
+           signed32 a32 = a, b32 = b;
+           
+           rv32 = a * b;
+           * sat = (rv32 & (3<<30)) == (3<<30);
+           return (signed64)rv32 << 1;
+         }
+
+:function:e500::signed64:ev_multiply32_ssf:signed32 a, signed32 b, int *sat
+       signed64 rv64;
+       if (a == 0x80000000 && b == 0x80000000)
+         {
+           rv64 = 0x7fffffffffffffffLL;
+           * sat = 1;
+           return rv64;
+         }
+       else
+         {
+           signed64 a64 = a, b64 = b;
+           rv64 = a64 * b64;
+           *sat = (rv64 & ((signed64)3<<62)) == ((signed64)3<<62);
+           /* Loses top sign bit.  */
+           return rv64 << 1;
+         }
+\f
+#
+# SPE FP handling support
+#
+
+:function:e500::void:ev_check_guard:sim_fpu *a, int fg, int fx, cpu *processor
+       unsigned64 guard;
+       guard = sim_fpu_guard(a, 0);
+       if (guard & 1)
+         EV_SET_SPEFSCR_BITS(fg);
+       if (guard & ~1)
+         EV_SET_SPEFSCR_BITS(fx);
+
+:function:e500::void:booke_sim_fpu_32to:sim_fpu *dst, unsigned32 packed
+       sim_fpu_32to (dst, packed);
+
+       /* Set normally unused fields to allow booke arithmetic.  */
+       if (dst->class == sim_fpu_class_infinity)
+         {
+           dst->normal_exp = 128;
+           dst->fraction = ((unsigned64)1 << 60);
+         }
+       else if (dst->class == sim_fpu_class_qnan
+                || dst->class == sim_fpu_class_snan)
+         {
+           dst->normal_exp = 128;
+           /* This is set, but without the implicit bit, so we have to or
+              in the implicit bit.  */
+           dst->fraction |= ((unsigned64)1 << 60);
+         }
+
+:function:e500::int:booke_sim_fpu_add:sim_fpu *d, sim_fpu *a, sim_fpu *b, int inv, int over, int under, cpu *processor
+       int invalid_operand, overflow_result, underflow_result;
+       int dest_exp;
+
+       invalid_operand = 0;
+       overflow_result = 0;
+       underflow_result = 0;
+
+       /* Treat NaN, Inf, and denorm like normal numbers, and signal invalid
+          operand if it hasn't already been done.  */
+       if (EV_IS_INFDENORMNAN (a))
+         {
+           a->class = sim_fpu_class_number;
+
+           EV_SET_SPEFSCR_BITS (inv);
+           invalid_operand = 1;
+         }
+       if (EV_IS_INFDENORMNAN (b))
+         {
+           b->class = sim_fpu_class_number;
+
+           if (! invalid_operand)
+             {
+               EV_SET_SPEFSCR_BITS (inv);
+               invalid_operand = 1;
+             }
+         }
+
+       sim_fpu_add (d, a, b);
+
+       dest_exp = booke_sim_fpu_exp (d);
+       /* If this is a denorm, force to zero, and signal underflow if
+          we haven't already indicated invalid operand.  */
+       if (dest_exp <= -127)
+         {
+           int sign = d->sign;
+
+           *d = sim_fpu_zero;
+           d->sign = sign;
+           if (! invalid_operand)
+             {
+               EV_SET_SPEFSCR_BITS (under);
+               underflow_result = 1;
+             }
+         }
+       /* If this is Inf/NaN, force to pmax/nmax, and signal overflow if
+          we haven't already indicated invalid operand.  */
+       else if (dest_exp >= 127)
+         {
+           int sign = d->sign;
+
+           *d = sim_fpu_max32;
+           d->sign = sign;
+           if (! invalid_operand)
+             {
+               EV_SET_SPEFSCR_BITS (over);
+               overflow_result = 1;
+             }
+         }
+       /* Destination sign is sign of operand with larger magnitude, or
+          the sign of the first operand if operands have the same
+          magnitude.  Thus if the result is zero, we force it to have
+          the sign of the first operand.  */
+       else if (d->fraction == 0)
+         d->sign = a->sign;
+
+       return invalid_operand || overflow_result || underflow_result;
+
+:function:e500::unsigned32:ev_fs_add:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int fg, int fx, cpu *processor
+       sim_fpu a, b, d;
+       unsigned32 w;
+       int exception;
+
+       booke_sim_fpu_32to (&a, aa);
+       booke_sim_fpu_32to (&b, bb);
+
+       exception = booke_sim_fpu_add (&d, &a, &b, inv, over, under,
+                                      processor);
+
+       sim_fpu_to32 (&w, &d);
+       if (! exception)
+         ev_check_guard(&d, fg, fx, processor);
+       return w;
+
+:function:e500::unsigned32:ev_fs_sub:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int fg, int fx, cpu *processor
+       sim_fpu a, b, d;
+       unsigned32 w;
+       int exception;
+
+       booke_sim_fpu_32to (&a, aa);
+       booke_sim_fpu_32to (&b, bb);
+
+       /* Invert sign of second operand, and add.  */
+       b.sign = ! b.sign;
+       exception = booke_sim_fpu_add (&d, &a, &b, inv, over, under,
+                                      processor);
+
+       sim_fpu_to32 (&w, &d);
+       if (! exception)
+         ev_check_guard(&d, fg, fx, processor);
+       return w;
+
+# sim_fpu_exp leaves the normal_exp field undefined for Inf and NaN.
+# The booke algorithms require exp values, so we fake them here.
+# fixme: It also apparently does the same for zero, but should not.
+:function:e500::unsigned32:booke_sim_fpu_exp:sim_fpu *x
+       int y = sim_fpu_is (x);
+       if (y == SIM_FPU_IS_PZERO || y == SIM_FPU_IS_NZERO)
+         return 0;
+       else if (y == SIM_FPU_IS_SNAN || y == SIM_FPU_IS_QNAN
+                || y == SIM_FPU_IS_NINF || y == SIM_FPU_IS_PINF)
+         return 128;
+       else
+         return sim_fpu_exp (x);
+
+:function:e500::unsigned32:ev_fs_mul:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int fg, int fx, cpu *processor
+       sim_fpu a, b, d;
+       unsigned32 w;
+       int sa, sb, ea, eb, ei;
+       sim_fpu_32to (&a, aa);
+       sim_fpu_32to (&b, bb);
+       sa = sim_fpu_sign(&a);
+       sb = sim_fpu_sign(&b);
+       ea = booke_sim_fpu_exp(&a);
+       eb = booke_sim_fpu_exp(&b);
+       ei = ea + eb + 127;
+       if (sim_fpu_is_zero (&a) || sim_fpu_is_zero (&b))
+         w = 0;
+       else if (sa == sb) {
+         if (ei >= 254) {
+           w = EV_PMAX;
+           EV_SET_SPEFSCR_BITS(over);
+         } else if (ei < 1) {
+           d = sim_fpu_zero;
+           sim_fpu_to32 (&w, &d);
+           w &= 0x7fffffff;    /* Clear sign bit.  */
+         } else {
+           goto normal_mul;
+         }
+       } else {
+         if (ei >= 254) {
+           w = EV_NMAX;
+           EV_SET_SPEFSCR_BITS(over);
+         } else if (ei < 1) {
+           d = sim_fpu_zero;
+           sim_fpu_to32 (&w, &d);
+           w |= 0x80000000;    /* Set sign bit.  */
+         } else {
+       normal_mul:
+           if (EV_IS_INFDENORMNAN(&a) || EV_IS_INFDENORMNAN(&b))
+             EV_SET_SPEFSCR_BITS(inv);
+           sim_fpu_mul (&d, &a, &b);
+           sim_fpu_to32 (&w, &d);
+         }
+       }
+       return w;
+
+:function:e500::unsigned32:ev_fs_div:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int dbz, int fg, int fx, cpu *processor
+       sim_fpu a, b, d;
+       unsigned32 w;
+       int sa, sb, ea, eb, ei;
+       
+       sim_fpu_32to (&a, aa);
+       sim_fpu_32to (&b, bb);
+       sa = sim_fpu_sign(&a);
+       sb = sim_fpu_sign(&b);
+       ea = booke_sim_fpu_exp(&a);
+       eb = booke_sim_fpu_exp(&b);
+       ei = ea - eb + 127;
+
+       /* Special cases to handle behaviour of e500 hardware.
+          cf case 107543.  */
+       if (sim_fpu_is_nan (&a) || sim_fpu_is_nan (&b)
+         || sim_fpu_is_zero (&a) || sim_fpu_is_zero (&b))
+       {
+         if (sim_fpu_is_snan (&a) || sim_fpu_is_snan (&b))
+           {
+             if (bb == 0x3f800000)
+               w = EV_PMAX;
+             else if (aa == 0x7fc00001)
+               w = 0x3fbffffe;
+             else
+               goto normal_div;
+           }
+         else
+           goto normal_div;
+       }
+       else if (sim_fpu_is_infinity (&a) && sim_fpu_is_infinity (&b))
+       {
+         if (sa == sb)
+           sim_fpu_32to (&d, 0x3f800000);
+         else
+           sim_fpu_32to (&d, 0xbf800000);
+         sim_fpu_to32 (&w, &d);
+       }
+       else if (sa == sb) {
+         if (ei > 254) {
+           w = EV_PMAX;
+           EV_SET_SPEFSCR_BITS(over);
+         } else if (ei <= 1) {
+           d = sim_fpu_zero;
+           sim_fpu_to32 (&w, &d);
+           w &= 0x7fffffff;    /* Clear sign bit.  */
+         } else {
+           goto normal_div;
+         }
+       } else {
+         if (ei > 254) {
+           w = EV_NMAX;
+           EV_SET_SPEFSCR_BITS(over);
+         } else if (ei <= 1) {
+           d = sim_fpu_zero;
+           sim_fpu_to32 (&w, &d);
+           w |= 0x80000000;    /* Set sign bit.  */
+         } else {
+       normal_div:
+           if (EV_IS_INFDENORMNAN(&a) || EV_IS_INFDENORMNAN(&b))
+             EV_SET_SPEFSCR_BITS(inv);
+           if (sim_fpu_is_zero (&b))
+             {
+               if (sim_fpu_is_zero (&a))
+                 EV_SET_SPEFSCR_BITS(dbz);
+               else 
+                 EV_SET_SPEFSCR_BITS(inv);
+               w = sa ? EV_NMAX : EV_PMAX;
+             }
+           else
+             {
+               sim_fpu_div (&d, &a, &b);
+               sim_fpu_to32 (&w, &d);
+               ev_check_guard(&d, fg, fx, processor);
+             }
+         }
+       }
+       return w;
+       
+\f
+#
+# A.2.7 Integer SPE Simple Instructions
+#
+
+0.4,6.RS,11.RA,16.RB,21.512:X:e500:evaddw %RS,%RA,%RB:Vector Add Word
+       unsigned32 w1, w2;
+       w1 = *rBh + *rAh;
+       w2 = *rB + *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evaddw: *rSh = %08x; *rS = %08x; w1 = %08x w2 = %08x\n", *rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.IMM,16.RB,21.514:X:e500:evaddiw %RS,%RB,%IMM:Vector Add Immediate Word
+       unsigned32 w1, w2;
+       w1 = *rBh + IMM;
+       w2 = *rB + IMM;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evaddiw: *rSh = %08x; *rS = %08x; w1 = %08x w2 = %08x\n", *rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.516:X:e500:evsubfw %RS,%RA,%RB:Vector Subtract from Word
+       unsigned32 w1, w2;
+       w1 = *rBh - *rAh;
+       w2 = *rB - *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evsubfw: *rSh = %08x; *rS = %08x; w1 = %08x w2 = %08x\n", *rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.IMM,16.RB,21.518:X:e500:evsubifw %RS,%RB,%IMM:Vector Subtract Immediate from Word
+       unsigned32 w1, w2;
+       w1 = *rBh - IMM;
+       w2 = *rB - IMM;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evsubifw: *rSh = %08x; *rS = %08x; IMM = %d\n", *rSh, *rS, IMM);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.520:X:e500:evabs %RS,%RA:Vector Absolute Value
+       signed32 w1, w2;
+       w1 = *rAh;
+       if (w1 < 0 && w1 != 0x80000000)
+         w1 = -w1;
+       w2 = *rA;
+       if (w2 < 0 && w2 != 0x80000000)
+         w2 = -w2;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.521:X:e500:evneg %RS,%RA:Vector Negate
+       signed32 w1, w2;
+       w1 = *rAh;
+       /* the negative most negative number is the most negative number */
+       if (w1 != 0x80000000)
+         w1 = -w1;
+       w2 = *rA;
+       if (w2 != 0x80000000)
+         w2 = -w2;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.522:X:e500:evextsb %RS,%RA:Vector Extend Signed Byte
+       unsigned64 w1, w2;
+       w1 = *rAh & 0xff;
+       if (w1 & 0x80)
+         w1 |= 0xffffff00;
+       w2 = *rA & 0xff;
+       if (w2 & 0x80)
+         w2 |= 0xffffff00;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK , 0);
+
+0.4,6.RS,11.RA,16.0,21.523:X:e500:evextsb %RS,%RA:Vector Extend Signed Half Word
+       unsigned64 w1, w2;
+       w1 = *rAh & 0xffff;
+       if (w1 & 0x8000)
+         w1 |= 0xffff0000;
+       w2 = *rA & 0xffff;
+       if (w2 & 0x8000)
+         w2 |= 0xffff0000;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.529:X:e500:evand %RS,%RA,%RB:Vector AND
+       unsigned32 w1, w2;
+       w1 = *rBh & *rAh;
+       w2 = *rB & *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.535:X:e500:evor %RS,%RA,%RB:Vector OR
+       unsigned32 w1, w2;
+       w1 = *rBh | *rAh;
+       w2 = *rB | *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.534:X:e500:evxor %RS,%RA,%RB:Vector XOR
+       unsigned32 w1, w2;
+       w1 = *rBh ^ *rAh;
+       w2 = *rB ^ *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.542:X:e500:evnand %RS,%RA,%RB:Vector NAND
+       unsigned32 w1, w2;
+       w1 = ~(*rBh & *rAh);
+       w2 = ~(*rB & *rA);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.536:X:e500:evnor %RS,%RA,%RB:Vector NOR
+       unsigned32 w1, w2;
+       w1 = ~(*rBh | *rAh);
+       w2 = ~(*rB | *rA);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.537:X:e500:eveqv %RS,%RA,%RB:Vector Equivalent
+       unsigned32 w1, w2;
+       w1 = (~*rBh) ^ *rAh;
+       w2 = (~*rB) ^ *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.530:X:e500:evandc %RS,%RA,%RB:Vector AND with Compliment
+       unsigned32 w1, w2;
+       w1 = (~*rBh) & *rAh;
+       w2 = (~*rB) & *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evandc: *rSh = %08x; *rS = %08x\n", *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.539:X:e500:evorc %RS,%RA,%RB:Vector OR with Compliment
+       unsigned32 w1, w2;
+       w1 = (~*rBh) | *rAh;
+       w2 = (~*rB) | *rA;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evorc: *rSh = %08x; *rS = %08x\n", *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.552:X:e500:evrlw %RS,%RA,%RB:Vector Rotate Left Word
+       unsigned32 nh, nl, w1, w2;
+       nh = *rBh & 0x1f;
+       nl = *rB & 0x1f;
+       w1 = ((unsigned32)*rAh) << nh | ((unsigned32)*rAh) >> (32 - nh);
+       w2 = ((unsigned32)*rA) << nl | ((unsigned32)*rA) >> (32 - nl);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evrlw: nh %d nl %d *rSh = %08x; *rS = %08x\n", nh, nl, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.554:X:e500:evrlwi %RS,%RA,%UIMM:Vector Rotate Left Word Immediate
+       unsigned32 w1, w2, imm;
+       imm = (unsigned32)UIMM;
+       w1 = ((unsigned32)*rAh) << imm | ((unsigned32)*rAh) >> (32 - imm);
+       w2 = ((unsigned32)*rA) << imm | ((unsigned32)*rA) >> (32 - imm);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.548:X:e500:evslw %RS,%RA,%RB:Vector Shift Left Word
+       unsigned32 nh, nl, w1, w2;
+       nh = *rBh & 0x1f;
+       nl = *rB & 0x1f;
+       w1 = ((unsigned32)*rAh) << nh;
+       w2 = ((unsigned32)*rA) << nl;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.550:X:e500:evslwi %RS,%RA,%UIMM:Vector Shift Left Word Immediate
+       unsigned32 w1, w2, imm = UIMM;
+       w1 = ((unsigned32)*rAh) << imm;
+       w2 = ((unsigned32)*rA) << imm;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.545:X:e500:evsrws %RS,%RA,%RB:Vector Shift Right Word Signed
+       signed32 w1, w2;
+       unsigned32 nh, nl;
+       nh = *rBh & 0x1f;
+       nl = *rB & 0x1f;
+       w1 = ((signed32)*rAh) >> nh;
+       w2 = ((signed32)*rA) >> nl;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evsrws: nh %d nl %d *rSh = %08x; *rS = %08x\n", nh, nl, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.544:X:e500:evsrwu %RS,%RA,%RB:Vector Shift Right Word Unsigned
+       unsigned32 w1, w2, nh, nl;
+       nh = *rBh & 0x1f;
+       nl = *rB & 0x1f;
+       w1 = ((unsigned32)*rAh) >> nh;
+       w2 = ((unsigned32)*rA) >> nl;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.547:X:e500:evsrwis %RS,%RA,%UIMM:Vector Shift Right Word Immediate Signed
+       signed32 w1, w2;
+       unsigned32 imm = UIMM;
+       w1 = ((signed32)*rAh) >> imm;
+       w2 = ((signed32)*rA) >> imm;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.546:X:e500:evsrwiu %RS,%RA,%UIMM:Vector Shift Right Word Immediate Unsigned
+       unsigned32 w1, w2, imm = UIMM;
+       w1 = ((unsigned32)*rAh) >> imm;
+       w2 = ((unsigned32)*rA) >> imm;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.525:X:e500:evcntlzw %RS,%RA:Vector Count Leading Zeros Word
+       unsigned32 w1, w2, mask, c1, c2;
+       for (c1 = 0, mask = 0x80000000, w1 = *rAh;
+             !(w1 & mask) && mask != 0; mask >>= 1)
+         c1++;
+       for (c2 = 0, mask = 0x80000000, w2 = *rA;
+             !(w2 & mask) && mask != 0; mask >>= 1)
+         c2++;
+       EV_SET_REG2(*rSh, *rS, c1, c2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.526:X:e500:evcntlsw %RS,%RA:Vector Count Leading Sign Bits Word
+       unsigned32 w1, w2, mask, sign_bit, c1, c2;
+       for (c1 = 0, mask = 0x80000000, w1 = *rAh, sign_bit = w1 & mask;
+            ((w1 & mask) == sign_bit) && mask != 0;
+            mask >>= 1, sign_bit >>= 1)
+         c1++;
+       for (c2 = 0, mask = 0x80000000, w2 = *rA, sign_bit = w2 & mask;
+            ((w2 & mask) == sign_bit) && mask != 0;
+            mask >>= 1, sign_bit >>= 1)
+         c2++;
+       EV_SET_REG2(*rSh, *rS, c1, c2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.524:X:e500:evrndw %RS,%RA:Vector Round Word
+       unsigned32 w1, w2;
+       w1 = ((unsigned32)*rAh + 0x8000) & 0xffff0000;
+       w2 = ((unsigned32)*rA + 0x8000) & 0xffff0000;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+               //printf("evrndw: *rSh = %08x; *rS = %08x\n", *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.556:X:e500:evmergehi %RS,%RA,%RB:Vector Merge Hi
+       unsigned32 w1, w2;
+       w1 = *rAh;
+       w2 = *rBh;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.557:X:e500:evmergelo %RS,%RA,%RB:Vector Merge Low
+       unsigned32 w1, w2;
+       w1 = *rA;
+       w2 = *rB;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.559:X:e500:evmergelohi %RS,%RA,%RB:Vector Merge Low Hi
+       unsigned32 w1, w2;
+       w1 = *rA;
+       w2 = *rBh;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.558:X:e500:evmergehilo %RS,%RA,%RB:Vector Merge Hi Low
+       unsigned32 w1, w2;
+       w1 = *rAh;
+       w2 = *rB;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.SIMM,16.0,21.553:X:e500:evsplati %RS,%SIMM:Vector Splat Immediate
+       unsigned32 w;
+       w = SIMM & 0x1f;
+       if (w & 0x10)
+         w |= 0xffffffe0;
+       EV_SET_REG2(*rSh, *rS, w, w);
+       PPC_INSN_INT(RS_BITMASK, 0, 0);
+
+0.4,6.RS,11.SIMM,16.0,21.555:X:e500:evsplatfi %RS,%SIMM:Vector Splat Fractional Immediate
+       unsigned32 w;
+       w = SIMM << 27;
+       EV_SET_REG2(*rSh, *rS, w, w);
+       PPC_INSN_INT(RS_BITMASK, 0, 0);
+
+0.4,6.BF,9.0,11.RA,16.RB,21.561:X:e500:evcmpgts %BF,%RA,%RB:Vector Compare Greater Than Signed
+       signed32 ah, al, bh, bl;
+       int w, ch, cl;
+       ah = *rAh;
+       al = *rA;
+       bh = *rBh;
+       bl = *rB;
+       if (ah > bh)
+         ch = 1;
+       else
+         ch = 0;
+       if (al > bl)
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9.0,11.RA,16.RB,21.560:X:e500:evcmpgtu %BF,%RA,%RB:Vector Compare Greater Than Unsigned
+       unsigned32 ah, al, bh, bl;
+       int w, ch, cl;
+       ah = *rAh;
+       al = *rA;
+       bh = *rBh;
+       bl = *rB;
+       if (ah > bh)
+         ch = 1;
+       else
+         ch = 0;
+       if (al > bl)
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9.0,11.RA,16.RB,21.563:X:e500:evcmplts %BF,%RA,%RB:Vector Compare Less Than Signed
+       signed32 ah, al, bh, bl;
+       int w, ch, cl;
+       ah = *rAh;
+       al = *rA;
+       bh = *rBh;
+       bl = *rB;
+       if (ah < bh)
+         ch = 1;
+       else
+         ch = 0;
+       if (al < bl)
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9.0,11.RA,16.RB,21.562:X:e500:evcmpltu %BF,%RA,%RB:Vector Compare Less Than Unsigned
+       unsigned32 ah, al, bh, bl;
+       int w, ch, cl;
+       ah = *rAh;
+       al = *rA;
+       bh = *rBh;
+       bl = *rB;
+       if (ah < bh)
+         ch = 1;
+       else
+         ch = 0;
+       if (al < bl)
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9.0,11.RA,16.RB,21.564:X:e500:evcmpeq %BF,%RA,%RB:Vector Compare Equal
+       unsigned32 ah, al, bh, bl;
+       int w, ch, cl;
+       ah = *rAh;
+       al = *rA;
+       bh = *rBh;
+       bl = *rB;
+       if (ah == bh)
+         ch = 1;
+       else
+         ch = 0;
+       if (al == bl)
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+               //printf("evcmpeq: ch %d cl %d BF %d, CR is now %08x\n", ch, cl, BF, CR);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.RS,11.RA,16.RB,21.79,29.CRFS:X:e500:evsel %RS,%RA,%RB,%CRFS:Vector Select
+       unsigned32 w1, w2;
+       int cr;
+       cr = CR_FIELD(CRFS);
+       if (cr & 8)
+         w1 = *rAh;
+       else
+         w1 = *rBh;
+       if (cr & 4)
+         w2 = *rA;
+       else
+         w2 = *rB;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.527:X:e500:brinc %RS,%RA,%RB:Bit Reversed Increment
+       unsigned32 w1, w2, a, d, mask;
+       mask = (*rB) & 0xffff;
+       a = (*rA) & 0xffff;
+       d = EV_BITREVERSE16(1 + EV_BITREVERSE16(a | ~mask));
+       *rS = ((*rA) & 0xffff0000) | (d & 0xffff);
+               //printf("brinc: *rS = %08x\n", *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+#
+# A.2.8 Integer SPE Complex Instructions
+#
+
+0.4,6.RS,11.RA,16.RB,21.1031:EVX:e500:evmhossf %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Saturate Fractional
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       int movl, movh;
+       
+       al = (signed16) EV_LOHALF (*rA);
+       ah = (signed16) EV_LOHALF (*rAh);
+       bl = (signed16) EV_LOHALF (*rB);
+       bh = (signed16) EV_LOHALF (*rBh);
+       tl = ev_multiply16_ssf (al, bl, &movl);
+       th = ev_multiply16_ssf (ah, bh, &movh);
+       EV_SET_REG2 (*rSh, *rS, EV_SATURATE (movh, 0x7fffffff, th),
+                               EV_SATURATE (movl, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl, movh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1063:EVX:e500:evmhossfa %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Saturate Fractional Accumulate
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       int movl, movh;
+       
+       al = (signed16) EV_LOHALF (*rA);
+       ah = (signed16) EV_LOHALF (*rAh);
+       bl = (signed16) EV_LOHALF (*rB);
+       bh = (signed16) EV_LOHALF (*rBh);
+       tl = ev_multiply16_ssf (al, bl, &movl);
+       th = ev_multiply16_ssf (ah, bh, &movh);
+       EV_SET_REG2 (*rSh, *rS, EV_SATURATE (movh, 0x7fffffff, th),
+                               EV_SATURATE (movl, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl, movh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1039:EVX:e500:evmhosmf %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Fractional
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       int dummy;
+       
+       al = (signed16) EV_LOHALF (*rA);
+       ah = (signed16) EV_LOHALF (*rAh);
+       bl = (signed16) EV_LOHALF (*rB);
+       bh = (signed16) EV_LOHALF (*rBh);
+       tl = ev_multiply16_smf (al, bl, & dummy);
+       th = ev_multiply16_smf (ah, bh, & dummy);
+       EV_SET_REG2 (*rSh, *rS, th, tl);
+       PPC_INSN_INT (RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1071:EVX:e500:evmhosmfa %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Fractional Accumulate
+       signed32 al, ah, bl, bh;
+       signed32 tl, th;
+       int dummy;
+       
+       al = (signed16) EV_LOHALF (*rA);
+       ah = (signed16) EV_LOHALF (*rAh);
+       bl = (signed16) EV_LOHALF (*rB);
+       bh = (signed16) EV_LOHALF (*rBh);
+       tl = ev_multiply16_smf (al, bl, & dummy);
+       th = ev_multiply16_smf (ah, bh, & dummy);
+       EV_SET_REG2_ACC (*rSh, *rS, th, tl);
+       PPC_INSN_INT (RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1037:EVX:e500:evmhosmi %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Integer
+       signed32 al, ah, bl, bh, tl, th;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2(*rSh, *rS, th, tl);
+               //printf("evmhosmi: *rSh = %08x; *rS = %08x\n", *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1069:EVX:e500:evmhosmia %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Integer Accumulate
+       signed32 al, ah, bl, bh, tl, th;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2_ACC(*rSh, *rS, th, tl);
+               //printf("evmhosmia: ACC = %08x; *rSh = %08x; *rS = %08x\n", ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1036:EVX:e500:evmhoumi %RS,%RA,%RB:Vector Multiply Half Words Odd Unsigned Modulo Integer
+       unsigned32 al, ah, bl, bh, tl, th;
+       al = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_LOHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_LOHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2(*rSh, *rS, th, tl);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1068:EVX:e500:evmhoumia %RS,%RA,%RB:Vector Multiply Half Words Odd Unsigned Modulo Integer Accumulate
+       unsigned32 al, ah, bl, bh, tl, th;
+       al = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_LOHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_LOHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2_ACC(*rSh, *rS, th, tl);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1027:EVX:e500:evmhessf %RS,%RA,%RB:Vector Multiply Half Words Even Signed Saturate Fractional
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       int movl, movh;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       tl = ev_multiply16_ssf (al, bl, &movl);
+       th = ev_multiply16_ssf (ah, bh, &movh);
+       EV_SET_REG2 (*rSh, *rS, EV_SATURATE (movh, 0x7fffffff, th),
+                              EV_SATURATE (movl, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl, movh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1059:EVX:e500:evmhessfa %RS,%RA,%RB:Vector Multiply Half Words Even Signed Saturate Fractional Accumulate
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       int movl, movh;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       tl = ev_multiply16_ssf (al, bl, &movl);
+       th = ev_multiply16_ssf (ah, bh, &movh);
+       EV_SET_REG2_ACC (*rSh, *rS, EV_SATURATE (movh, 0x7fffffff, th),
+                                   EV_SATURATE (movl, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl, movh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1035:EVX:e500:evmhesmf %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Fractional
+       signed16 al, ah, bl, bh;
+       signed64 tl, th;
+       int movl, movh;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       tl = ev_multiply16_smf (al, bl, &movl);
+       th = ev_multiply16_smf (ah, bh, &movh);
+       EV_SET_REG2 (*rSh, *rS, th, tl);
+       EV_SET_SPEFSCR_OV (movl, movh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1067:EVX:e500:evmhesmfa %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Fractional Accumulate
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       int dummy;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       tl = ev_multiply16_smf (al, bl, & dummy);
+       th = ev_multiply16_smf (ah, bh, & dummy);
+       EV_SET_REG2_ACC (*rSh, *rS, th, tl);
+       PPC_INSN_INT (RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1033:EVX:e500:evmhesmi %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Integer
+       signed16 al, ah, bl, bh;
+       signed32 tl, th;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2 (*rSh, *rS, th, tl);
+       PPC_INSN_INT (RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1065:EVX:e500:evmhesmia %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Integer Accumulate
+       signed32 al, ah, bl, bh, tl, th;
+       al = (signed32)(signed16)EV_HIHALF(*rA);
+       ah = (signed32)(signed16)EV_HIHALF(*rAh);
+       bl = (signed32)(signed16)EV_HIHALF(*rB);
+       bh = (signed32)(signed16)EV_HIHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2_ACC(*rSh, *rS, th, tl);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1032:EVX:e500:evmheumi %RS,%RA,%RB:Vector Multiply Half Words Even Unsigned Modulo Integer
+       unsigned32 al, ah, bl, bh, tl, th;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2(*rSh, *rS, th, tl);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1064:EVX:e500:evmheumia %RS,%RA,%RB:Vector Multiply Half Words Even Unsigned Modulo Integer Accumulate
+       unsigned32 al, ah, bl, bh, tl, th;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       tl = al * bl;
+       th = ah * bh;
+       EV_SET_REG2_ACC(*rSh, *rS, th, tl);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1287:EVX:e500:evmhossfaaw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Saturate Fractional and Accumulate into Words
+       signed16 al, ah, bl, bh;
+       signed32 t1, t2;
+       signed64 tl, th;
+       int movl, movh, ovl, ovh;
+       
+       al = (signed16) EV_LOHALF (*rA);
+       ah = (signed16) EV_LOHALF (*rAh);
+       bl = (signed16) EV_LOHALF (*rB);
+       bh = (signed16) EV_LOHALF (*rBh);
+       t1 = ev_multiply16_ssf (ah, bh, &movh);
+       t2 = ev_multiply16_ssf (al, bl, &movl);
+       th = EV_ACCHIGH + EV_SATURATE (movh, 0x7fffffff, t1);
+       tl = EV_ACCLOW  + EV_SATURATE (movl, 0x7fffffff, t2);
+       ovh = EV_SAT_P_S32 (th);
+       ovl = EV_SAT_P_S32 (tl);
+       EV_SET_REG2_ACC (*rSh, *rS, EV_SATURATE_ACC (ovh, th, 0x80000000, 0x7fffffff, th),
+                                   EV_SATURATE_ACC (ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl | ovl, movh | ovh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1285:EVX:e500:evmhossiaaw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Saturate Integer and Accumulate into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+               //printf("evmhossiaaw: ovh %d ovl %d al %d ah %d bl %d bh %d t1 %qd t2 %qd tl %qd th %qd\n", ovh, ovl, al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmhossiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1295:EVX:e500:evmhosmfaaw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Fractional and Accumulate into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       t1 = ((signed64)ah * bh) << 1;
+       t2 = ((signed64)al * bl) << 1;
+       th = EV_ACCHIGH + (t1 & 0xffffffff);
+       tl = EV_ACCLOW + (t2 & 0xffffffff);
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1293:EVX:e500:evmhosmiaaw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Integer and Accumulate into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+               //printf("evmhosmiaaw: al %d ah %d bl %d bh %d t1 %qd t2 %qd tl %qd th %qd\n", al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmhosmiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1284:EVX:e500:evmhousiaaw %RS,%RA,%RB:Vector Multiply Half Words Odd Unsigned Saturate Integer and Accumulate into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       signed64 tl, th;
+       int ovl, ovh;
+       al = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_LOHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = (signed64)EV_ACCHIGH + (signed64)t1;
+       tl = (signed64)EV_ACCLOW + (signed64)t2;
+       ovh = EV_SAT_P_U32(th);
+       ovl = EV_SAT_P_U32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0, 0xffffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0, 0xffffffff, tl));
+               //printf("evmhousiaaw: al %u ah %u bl %u bh %u t1 %qu t2 %qu tl %qu th %qu\n", al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmhousiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1292:EVX:e500:evmhoumiaaw %RS,%RA,%RB:Vector Multiply Half Words Odd Unsigned Modulo Integer and Accumulate into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned32 t1, t2;
+       signed64 tl, th;
+       al = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_LOHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+               //printf("evmhoumiaaw: al %u ah %u bl %u bh %u t1 %qu t2 %qu tl %qu th %qu\n", al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmhoumiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1283:EVX:e500:evmhessfaaw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Saturate Fractional and Accumulate into Words
+       signed16 al, ah, bl, bh;
+       signed32 t1, t2;
+       signed64 tl, th;
+       int movl, movh, ovl, ovh;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       t1 = ev_multiply16_ssf (ah, bh, &movh);
+       t2 = ev_multiply16_ssf (al, bl, &movl);
+       th = EV_ACCHIGH + EV_SATURATE (movh, 0x7fffffff, t1);
+       tl = EV_ACCLOW  + EV_SATURATE (movl, 0x7fffffff, t2);
+       ovh = EV_SAT_P_S32 (th);
+       ovl = EV_SAT_P_S32 (tl);
+       EV_SET_REG2_ACC (*rSh, *rS, EV_SATURATE_ACC (ovh, th, 0x80000000, 0x7fffffff, th),
+                                   EV_SATURATE_ACC (ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl | ovl, movh | ovh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1281:EVX:e500:evmhessiaaw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Saturate Integer and Accumulate into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = (signed32)(signed16)EV_HIHALF(*rA);
+       ah = (signed32)(signed16)EV_HIHALF(*rAh);
+       bl = (signed32)(signed16)EV_HIHALF(*rB);
+       bh = (signed32)(signed16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+               //printf("evmhessiaaw: ovh %d ovl %d al %d ah %d bl %d bh %d t1 %qd t2 %qd tl %qd th %qd\n", ovh, ovl, al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmhessiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1291:EVX:e500:evmhesmfaaw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Fractional and Accumulate into Words
+       signed16 al, ah, bl, bh;
+       signed32 t1, t2, th, tl;
+       int dummy;
+
+       al = (signed16)EV_HIHALF(*rA);
+       ah = (signed16)EV_HIHALF(*rAh);
+       bl = (signed16)EV_HIHALF(*rB);
+       bh = (signed16)EV_HIHALF(*rBh);
+       t1 = ev_multiply16_smf (ah, bh, &dummy);
+       t2 = ev_multiply16_smf (al, bl, &dummy);
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th, tl);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1289:EVX:e500:evmhesmiaaw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Integer and Accumulate into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (signed32)(signed16)EV_HIHALF(*rA);
+       ah = (signed32)(signed16)EV_HIHALF(*rAh);
+       bl = (signed32)(signed16)EV_HIHALF(*rB);
+       bh = (signed32)(signed16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1280:EVX:e500:evmheusiaaw %RS,%RA,%RB:Vector Multiply Half Words Even Unsigned Saturate Integer and Accumulate into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       signed64 tl, th;
+       int ovl, ovh;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = (signed64)EV_ACCHIGH + (signed64)t1;
+       tl = (signed64)EV_ACCLOW + (signed64)t2;
+       ovh = EV_SAT_P_U32(th);
+       ovl = EV_SAT_P_U32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0, 0xffffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0, 0xffffffff, tl));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1288:EVX:e500:evmheumiaaw %RS,%RA,%RB:Vector Multiply Half Words Even Unsigned Modulo Integer and Accumulate into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned32 t1, t2;
+       unsigned64 tl, th;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH + t1;
+       tl = EV_ACCLOW + t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1415:EVX:e500:evmhossfanw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Saturate Fractional and Accumulate Negative into Words
+       signed16 al, ah, bl, bh;
+       signed32 t1, t2;
+       signed64 tl, th;
+       int movl, movh, ovl, ovh;
+       
+       al = (signed16) EV_LOHALF (*rA);
+       ah = (signed16) EV_LOHALF (*rAh);
+       bl = (signed16) EV_LOHALF (*rB);
+       bh = (signed16) EV_LOHALF (*rBh);
+       t1 = ev_multiply16_ssf (ah, bh, &movh);
+       t2 = ev_multiply16_ssf (al, bl, &movl);
+       th = EV_ACCHIGH - EV_SATURATE (movh, 0x7fffffff, t1);
+       tl = EV_ACCLOW  - EV_SATURATE (movl, 0x7fffffff, t2);
+       ovh = EV_SAT_P_S32 (th);
+       ovl = EV_SAT_P_S32 (tl);
+       EV_SET_REG2_ACC (*rSh, *rS, EV_SATURATE_ACC (ovh, th, 0x80000000, 0x7fffffff, th),
+                                   EV_SATURATE_ACC (ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl | ovl, movh | ovh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1413:EVX:e500:evmhossianw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Saturate Integer and Accumulate Negative into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH - t1;
+       tl = EV_ACCLOW - t2;
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+               //printf("evmhossianw: ACC = %08x; *rSh = %08x; *rS = %08x\n", ACC, *rSh, *rS);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1423:EVX:e500:evmhosmfanw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Fractional and Accumulate Negative into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       t1 = ((signed64)ah * bh) << 1;
+       t2 = ((signed64)al * bl) << 1;
+       th = EV_ACCHIGH - (t1 & 0xffffffff);
+       tl = EV_ACCLOW - (t2 & 0xffffffff);
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1421:EVX:e500:evmhosmianw %RS,%RA,%RB:Vector Multiply Half Words Odd Signed Modulo Integer and Accumulate Negative into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (signed32)(signed16)EV_LOHALF(*rA);
+       ah = (signed32)(signed16)EV_LOHALF(*rAh);
+       bl = (signed32)(signed16)EV_LOHALF(*rB);
+       bh = (signed32)(signed16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH - t1;
+       tl = EV_ACCLOW - t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1412:EVX:e500:evmhousianw %RS,%RA,%RB:Vector Multiply Half Words Odd Unsigned Saturate Integer and Accumulate Negative into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       signed64 tl, th;
+       int ovl, ovh;
+       al = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_LOHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = (signed64)EV_ACCHIGH - (signed64)t1;
+       tl = (signed64)EV_ACCLOW - (signed64)t2;
+       ovl = EV_SAT_P_U32(tl);
+       ovh = EV_SAT_P_U32(th);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0, 0xffffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0, 0xffffffff, tl));
+               //printf("evmhousianw: ovh %d ovl %d al %d ah %d bl %d bh %d t1 %qd t2 %qd tl %qd th %qd\n", ovh, ovl, al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmoussianw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1420:EVX:e500:evmhoumianw %RS,%RA,%RB:Vector Multiply Half Words Odd Unsigned Modulo Integer and Accumulate Negative into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned32 t1, t2;
+       unsigned64 tl, th;
+       al = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_LOHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_LOHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH - t1;
+       tl = EV_ACCLOW - t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1411:EVX:e500:evmhessfanw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Saturate Fractional and Accumulate Negative into Words
+       signed16 al, ah, bl, bh;
+       signed32 t1, t2;
+       signed64 tl, th;
+       int movl, movh, ovl, ovh;
+       
+       al = (signed16) EV_HIHALF (*rA);
+       ah = (signed16) EV_HIHALF (*rAh);
+       bl = (signed16) EV_HIHALF (*rB);
+       bh = (signed16) EV_HIHALF (*rBh);
+       t1 = ev_multiply16_ssf (ah, bh, &movh);
+       t2 = ev_multiply16_ssf (al, bl, &movl);
+       th = EV_ACCHIGH - EV_SATURATE (movh, 0x7fffffff, t1);
+       tl = EV_ACCLOW  - EV_SATURATE (movl, 0x7fffffff, t2);
+       ovh = EV_SAT_P_S32 (th);
+       ovl = EV_SAT_P_S32 (tl);
+       EV_SET_REG2_ACC (*rSh, *rS, EV_SATURATE_ACC (ovh, th, 0x80000000, 0x7fffffff, th),
+                                   EV_SATURATE_ACC (ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV (movl | ovl, movh | ovh);
+       PPC_INSN_INT_SPR (RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1409:EVX:e500:evmhessianw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Saturate Integer and Accumulate Negative into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = (signed32)(signed16)EV_HIHALF(*rA);
+       ah = (signed32)(signed16)EV_HIHALF(*rAh);
+       bl = (signed32)(signed16)EV_HIHALF(*rB);
+       bh = (signed32)(signed16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH - t1;
+       tl = EV_ACCLOW - t2;
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1419:EVX:e500:evmhesmfanw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Fractional and Accumulate Negative into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       t1 = ((signed64)ah * bh) << 1;
+       t2 = ((signed64)al * bl) << 1;
+       th = EV_ACCHIGH - (t1 & 0xffffffff);
+       tl = EV_ACCLOW - (t2 & 0xffffffff);
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1417:EVX:e500:evmhesmianw %RS,%RA,%RB:Vector Multiply Half Words Even Signed Modulo Integer and Accumulate Negative into Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       al = (signed32)(signed16)EV_HIHALF(*rA);
+       ah = (signed32)(signed16)EV_HIHALF(*rAh);
+       bl = (signed32)(signed16)EV_HIHALF(*rB);
+       bh = (signed32)(signed16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH - t1;
+       tl = EV_ACCLOW - t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+               //printf("evmhesmianw: al %d ah %d bl %d bh %d t1 %qd t2 %qd tl %qd th %qd\n", al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmhesmianw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1408:EVX:e500:evmheusianw %RS,%RA,%RB:Vector Multiply Half Words Even Unsigned Saturate Integer and Accumulate Negative into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       signed64 tl, th;
+       int ovl, ovh;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = (signed64)EV_ACCHIGH - (signed64)t1;
+       tl = (signed64)EV_ACCLOW - (signed64)t2;
+       ovl = EV_SAT_P_U32(tl);
+       ovh = EV_SAT_P_U32(th);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0, 0xffffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0, 0xffffffff, tl));
+               //printf("evmheusianw: ovh %d ovl %d al %u ah %u bl %u bh %u t1 %qu t2 %qu tl %qd th %qd\n", ovh, ovl, al, ah, bl, bh, t1, t2, tl, th);
+               //printf("evmheusianw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1416:EVX:e500:evmheumianw %RS,%RA,%RB:Vector Multiply Half Words Even Unsigned Modulo Integer and Accumulate Negative into Words
+       unsigned32 al, ah, bl, bh;
+       unsigned32 t1, t2;
+       unsigned64 tl, th;
+       al = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       ah = (unsigned32)(unsigned16)EV_HIHALF(*rAh);
+       bl = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       bh = (unsigned32)(unsigned16)EV_HIHALF(*rBh);
+       t1 = ah * bh;
+       t2 = al * bl;
+       th = EV_ACCHIGH - t1;
+       tl = EV_ACCLOW - t2;
+       EV_SET_REG2_ACC(*rSh, *rS, th & 0xffffffff, tl & 0xffffffff);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1327:EVX:e500:evmhogsmfaa %RS,%RA,%RB:Multiply Half Words Odd Guarded Signed Modulo Fractional and Accumulate
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_LOHALF(*rA);
+       b = (signed32)(signed16)EV_LOHALF(*rB);
+       t1 = EV_MUL16_SSF(a, b);
+       if (t1 & ((unsigned64)1 << 32))
+         t1 |= 0xfffffffe00000000;
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1325:EVX:e500:evmhogsmiaa %RS,%RA,%RB:Multiply Half Words Odd Guarded Signed Modulo Integer and Accumulate
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_LOHALF(*rA);
+       b = (signed32)(signed16)EV_LOHALF(*rB);
+       t1 = (signed64)a * (signed64)b;
+       t2 = (signed64)ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+               //printf("evmhogsmiaa: a %d b %d t1 %qd t2 %qd\n", a, b, t1, t2);
+               //printf("evmhogsmiaa: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1324:EVX:e500:evmhogumiaa %RS,%RA,%RB:Multiply Half Words Odd Guarded Unsigned Modulo Integer and Accumulate
+       unsigned32 a, b;
+       unsigned64 t1, t2;
+       a = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       b = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       t1 = a * b;
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1323:EVX:e500:evmhegsmfaa %RS,%RA,%RB:Multiply Half Words Even Guarded Signed Modulo Fractional and Accumulate
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_HIHALF(*rA);
+       b = (signed32)(signed16)EV_HIHALF(*rB);
+       t1 = EV_MUL16_SSF(a, b);
+       if (t1 & ((unsigned64)1 << 32))
+         t1 |= 0xfffffffe00000000;
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1321:EVX:e500:evmhegsmiaa %RS,%RA,%RB:Multiply Half Words Even Guarded Signed Modulo Integer and Accumulate
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_HIHALF(*rA);
+       b = (signed32)(signed16)EV_HIHALF(*rB);
+       t1 = (signed64)(a * b);
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1320:EVX:e500:evmhegumiaa %RS,%RA,%RB:Multiply Half Words Even Guarded Unsigned Modulo Integer and Accumulate
+       unsigned32 a, b;
+       unsigned64 t1, t2;
+       a = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       b = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       t1 = a * b;
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1455:EVX:e500:evmhogsmfan %RS,%RA,%RB:Multiply Half Words Odd Guarded Signed Modulo Fractional and Accumulate Negative
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_LOHALF(*rA);
+       b = (signed32)(signed16)EV_LOHALF(*rB);
+       t1 = EV_MUL16_SSF(a, b);
+       if (t1 & ((unsigned64)1 << 32))
+         t1 |= 0xfffffffe00000000;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1453:EVX:e500:evmhogsmian %RS,%RA,%RB:Multiply Half Words Odd Guarded Signed Modulo Integer and Accumulate Negative
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_LOHALF(*rA);
+       b = (signed32)(signed16)EV_LOHALF(*rB);
+       t1 = (signed64)a * (signed64)b;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+               //printf("evmhogsmian: a %d b %d t1 %qd t2 %qd\n", a, b, t1, t2);
+               //printf("evmhogsmian: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1452:EVX:e500:evmhogumian %RS,%RA,%RB:Multiply Half Words Odd Guarded Unsigned Modulo Integer and Accumulate Negative
+       unsigned32 a, b;
+       unsigned64 t1, t2;
+       a = (unsigned32)(unsigned16)EV_LOHALF(*rA);
+       b = (unsigned32)(unsigned16)EV_LOHALF(*rB);
+       t1 = (unsigned64)a * (unsigned64)b;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1451:EVX:e500:evmhegsmfan %RS,%RA,%RB:Multiply Half Words Even Guarded Signed Modulo Fractional and Accumulate Negative
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_HIHALF(*rA);
+       b = (signed32)(signed16)EV_HIHALF(*rB);
+       t1 = EV_MUL16_SSF(a, b);
+       if (t1 & ((unsigned64)1 << 32))
+         t1 |= 0xfffffffe00000000;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1449:EVX:e500:evmhegsmian %RS,%RA,%RB:Multiply Half Words Even Guarded Signed Modulo Integer and Accumulate Negative
+       signed32 a, b;
+       signed64 t1, t2;
+       a = (signed32)(signed16)EV_HIHALF(*rA);
+       b = (signed32)(signed16)EV_HIHALF(*rB);
+       t1 = (signed64)a * (signed64)b;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1448:EVX:e500:evmhegumian %RS,%RA,%RB:Multiply Half Words Even Guarded Unsigned Modulo Integer and Accumulate Negative
+       unsigned32 a, b;
+       unsigned64 t1, t2;
+       a = (unsigned32)(unsigned16)EV_HIHALF(*rA);
+       b = (unsigned32)(unsigned16)EV_HIHALF(*rB);
+       t1 = (unsigned64)a * (unsigned64)b;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1095:EVX:e500:evmwhssf %RS,%RA,%RB:Vector Multiply Word High Signed Saturate Fractional
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       int movl, movh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_ssf(al, bl, &movl);
+       t2 = ev_multiply32_ssf(ah, bh, &movh);
+       EV_SET_REG2(*rSh, *rS, EV_SATURATE(movh, 0x7fffffff, t2 >> 32),
+                              EV_SATURATE(movl, 0x7fffffff, t1 >> 32));
+       EV_SET_SPEFSCR_OV(movl, movh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1127:EVX:e500:evmwhssfa %RS,%RA,%RB:Vector Multiply Word High Signed Saturate Fractional and Accumulate
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       int movl, movh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_ssf(al, bl, &movl);
+       t2 = ev_multiply32_ssf(ah, bh, &movh);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE(movh, 0x7fffffff, t2 >> 32),
+                                  EV_SATURATE(movl, 0x7fffffff, t1 >> 32));
+       EV_SET_SPEFSCR_OV(movl, movh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1103:EVX:e500:evmwhsmf %RS,%RA,%RB:Vector Multiply Word High Signed Modulo Fractional
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = EV_MUL32_SSF(al, bl);
+       t2 = EV_MUL32_SSF(ah, bh);
+       EV_SET_REG2(*rSh, *rS, t2 >> 32, t1 >> 32);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+       
+0.4,6.RS,11.RA,16.RB,21.1135:EVX:e500:evmwhsmfa %RS,%RA,%RB:Vector Multiply Word High Signed Modulo Fractional and Accumulate
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = EV_MUL32_SSF(al, bl);
+       t2 = EV_MUL32_SSF(ah, bh);
+       EV_SET_REG2_ACC(*rSh, *rS, t2 >> 32, t1 >> 32);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1101:EVX:e500:evmwhsmi %RS,%RA,%RB:Vector Multiply Word High Signed Modulo Integer
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (signed64)al * (signed64)bl;
+       t2 = (signed64)ah * (signed64)bh;
+       EV_SET_REG2(*rSh, *rS, t2 >> 32, t1 >> 32);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1133:EVX:e500:evmwhsmia %RS,%RA,%RB:Vector Multiply Word High Signed Modulo Integer and Accumulate
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (signed64)al * (signed64)bl;
+       t2 = (signed64)ah * (signed64)bh;
+       EV_SET_REG2_ACC(*rSh, *rS, t2 >> 32, t1 >> 32);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1100:EVX:e500:evmwhumi %RS,%RA,%RB:Vector Multiply Word High Unsigned Modulo Integer
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)al * (unsigned64)bl;
+       t2 = (unsigned64)ah * (unsigned64)bh;
+       EV_SET_REG2(*rSh, *rS, t2 >> 32, t1 >> 32);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1132:EVX:e500:evmwhumia %RS,%RA,%RB:Vector Multiply Word High Unsigned Modulo Integer and Accumulate
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)al * (unsigned64)bl;
+       t2 = (unsigned64)ah * (unsigned64)bh;
+       EV_SET_REG2_ACC(*rSh, *rS, t2 >> 32, t1 >> 32);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1091:EVX:e500:evmwlssf %RS,%RA,%RB:Vector Multiply Word Low Signed Saturate Fractional
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       int movl, movh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_ssf(al, bl, &movl);
+       t2 = ev_multiply32_ssf(ah, bh, &movh);
+       EV_SET_REG2(*rSh, *rS, EV_SATURATE(movh, 0xffffffff, t2),
+                              EV_SATURATE(movl, 0xffffffff, t1));
+       EV_SET_SPEFSCR_OV(movl, movh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1123:EVX:e500:evmwlssfa %RS,%RA,%RB:Vector Multiply Word Low Signed Saturate Fractional and Accumulate
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       int movl, movh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_ssf(al, bl, &movl);
+       t2 = ev_multiply32_ssf(ah, bh, &movh);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE(movh, 0xffffffff, t2),
+                                  EV_SATURATE(movl, 0xffffffff, t1));
+       EV_SET_SPEFSCR_OV(movl, movh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1099:EVX:e500:evmwlsmf %RS,%RA,%RB:Vector Multiply Word Low Signed Modulo Fractional
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = EV_MUL32_SSF(al, bl);
+       t2 = EV_MUL32_SSF(ah, bh);
+       EV_SET_REG2(*rSh, *rS, t2, t1);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1131:EVX:e500:evmwlsmfa %RS,%RA,%RB:Vector Multiply Word Low Signed Modulo Fractional and Accumulate
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = EV_MUL32_SSF(al, bl);
+       t2 = EV_MUL32_SSF(ah, bh);
+       EV_SET_REG2_ACC(*rSh, *rS, t2, t1);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1096:EVX:e500:evmwlumi %RS,%RA,%RB:Vector Multiply Word Low Unsigned Modulo Integer
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)al * (unsigned64)bl;
+       t2 = (unsigned64)ah * (unsigned64)bh;
+       EV_SET_REG2(*rSh, *rS, t2, t1);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1128:EVX:e500:evmwlumia %RS,%RA,%RB:Vector Multiply Word Low Unsigned Modulo Integer and Accumulate
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)al * (unsigned64)bl;
+       t2 = (unsigned64)ah * (unsigned64)bh;
+       EV_SET_REG2_ACC(*rSh, *rS, t2, t1);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1347:EVX:e500:evmwlssfaaw %RS,%RA,%RB:Vector Multiply Word Low Signed Saturate Fractional and Accumulate in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int movl, movh, ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_ssf(ah, bh, &movh);
+       t2 = ev_multiply32_ssf(al, bl, &movl);
+       th = EV_ACCHIGH + EV_SATURATE(movh, 0xffffffff, t1);
+       tl = EV_ACCLOW + EV_SATURATE(movl, 0xffffffff, t2);
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV(movl | ovl, movh | ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1345:EVX:e500:evmwlssiaaw %RS,%RA,%RB:Vector Multiply Word Low Signed Saturate Integer and Accumulate in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (signed64)ah * (signed64)bh;
+       t2 = (signed64)al * (signed64)bl;
+       th = EV_ACCHIGH + (t1 & 0xffffffff);
+       tl = EV_ACCLOW + (t2 & 0xffffffff);
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1355:EVX:e500:evmwlsmfaaw %RS,%RA,%RB:Vector Multiply Word Low Signed Modulo Fractional and Accumulate in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       int mov;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_smf(ah, bh, &mov);
+       t2 = ev_multiply32_smf(al, bl, &mov);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_ACCHIGH + (t1 & 0xffffffff),
+                                EV_ACCLOW + (t2 & 0xffffffff));
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1353:EVX:e500:evmwlsmiaaw %RS,%RA,%RB:Vector Multiply Word Low Signed Modulo Integer and Accumulate in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (signed64)ah * (signed64)bh;
+       t2 = (signed64)al * (signed64)bl;
+       EV_SET_REG2_ACC(*rSh, *rS, EV_ACCHIGH + (t1 & 0xffffffff),
+                                EV_ACCLOW + (t2 & 0xffffffff));
+               //printf("evmwlsmiaaw: al %d ah %d bl %d bh %d t1 %qd t2 %qd\n", al, ah, bl, bh, t1, t2);
+               //printf("evmwlsmiaaw: *rSh = %08x; *rS = %08x\n", *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1344:EVX:e500:evmwlusiaaw %RS,%RA,%RB:Vector Multiply Word Low Unsigned Saturate Integer and Accumulate in Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)ah * (unsigned64)bh;
+       t2 = (unsigned64)al * (unsigned64)bl;
+       th = EV_ACCHIGH + (t1 & 0xffffffff);
+       tl = EV_ACCLOW + (t2 & 0xffffffff);
+       ovh = (th >> 32);
+       ovl = (tl >> 32);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE(ovh, 0xffffffff, th),
+                                  EV_SATURATE(ovl, 0xffffffff, tl));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1352:EVX:e500:evmwlumiaaw %RS,%RA,%RB:Vector Multiply Word Low Unsigned Modulo Integer and Accumulate in Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)ah * (unsigned64)bh;
+       t2 = (unsigned64)al * (unsigned64)bl;
+       EV_SET_REG2_ACC(*rSh, *rS, EV_ACCHIGH + (t1 & 0xffffffff),
+                                EV_ACCLOW + (t2 & 0xffffffff));
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1475:EVX:e500:evmwlssfanw %RS,%RA,%RB:Vector Multiply Word Low Signed Saturate Fractional and Accumulate Negative in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int movl, movh, ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_ssf(ah, bh, &movh);
+       t2 = ev_multiply32_ssf(al, bl, &movl);
+       th = EV_ACCHIGH - EV_SATURATE(movh, 0xffffffff, t1);
+       tl = EV_ACCLOW - EV_SATURATE(movl, 0xffffffff, t2);
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV(movl | ovl, movh | ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1473:EVX:e500:evmwlssianw %RS,%RA,%RB:Vector Multiply Word Low Signed Saturate Integer and Accumulate Negative in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (signed64)ah * (signed64)bh;
+       t2 = (signed64)al * (signed64)bl;
+       th = EV_ACCHIGH - (t1 & 0xffffffff);
+       tl = EV_ACCLOW - (t2 & 0xffffffff);
+       ovh = EV_SAT_P_S32(th);
+       ovl = EV_SAT_P_S32(tl);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, th, 0x80000000, 0x7fffffff, th),
+                                  EV_SATURATE_ACC(ovl, tl, 0x80000000, 0x7fffffff, tl));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1483:EVX:e500:evmwlsmfanw %RS,%RA,%RB:Vector Multiply Word Low Signed Modulo Fractional and Accumulate Negative in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       int mov;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = ev_multiply32_smf(ah, bh, &mov);
+       t2 = ev_multiply32_smf(al, bl, &mov);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_ACCHIGH - (t1 & 0xffffffff),
+                                EV_ACCLOW - (t2 & 0xffffffff));
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1481:EVX:e500:evmwlsmianw %RS,%RA,%RB:Vector Multiply Word Low Signed Modulo Integer and Accumulate Negative in Words
+       signed32 al, ah, bl, bh;
+       signed64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (signed64)ah * (signed64)bh;
+       t2 = (signed64)al * (signed64)bl;
+       EV_SET_REG2_ACC(*rSh, *rS, EV_ACCHIGH - (t1 & 0xffffffff),
+                                EV_ACCLOW - (t2 & 0xffffffff));
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1472:EVX:e500:evmwlusianw %RS,%RA,%RB:Vector Multiply Word Low Unsigned Saturate Integer and Accumulate Negative in Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2, tl, th;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)ah * (unsigned64)bh;
+       t2 = (unsigned64)al * (unsigned64)bl;
+       th = EV_ACCHIGH - (t1 & 0xffffffff);
+       tl = EV_ACCLOW - (t2 & 0xffffffff);
+       ovh = (th >> 32);
+       ovl = (tl >> 32);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE(ovh, 0xffffffff, th),
+                                  EV_SATURATE(ovl, 0xffffffff, tl));
+               //printf("evmwlusianw: ovl %d ovh %d al %d ah %d bl %d bh %d t1 %qd t2 %qd th %qd tl %qd\n", ovl, ovh, al, ah, al, bh, t1, t2, th, tl);
+               //printf("evmwlusianw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1480:EVX:e500:evmwlumianw %RS,%RA,%RB:Vector Multiply Word Low Unsigned Modulo Integer and Accumulate Negative in Words
+       unsigned32 al, ah, bl, bh;
+       unsigned64 t1, t2;
+       al = *rA;
+       ah = *rAh;
+       bl = *rB;
+       bh = *rBh;
+       t1 = (unsigned64)ah * (unsigned64)bh;
+       t2 = (unsigned64)al * (unsigned64)bl;
+       EV_SET_REG2_ACC(*rSh, *rS, EV_ACCHIGH - (t1 & 0xffffffff),
+                                  EV_ACCLOW - (t2 & 0xffffffff));
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1107:EVX:e500:evmwssf %RS,%RA,%RB:Vector Multiply Word Signed Saturate Fractional
+       signed32 a, b;
+       signed64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = ev_multiply32_ssf(a, b, &movl);
+       EV_SET_REG1(*rSh, *rS, EV_SATURATE(movl, 0x7fffffffffffffff, t));
+       EV_SET_SPEFSCR_OV(movl, 0);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1139:EVX:e500:evmwssfa %RS,%RA,%RB:Vector Multiply Word Signed Saturate Fractional and Accumulate
+       signed32 a, b;
+       signed64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = ev_multiply32_ssf(a, b, &movl);
+       EV_SET_REG1_ACC(*rSh, *rS, EV_SATURATE(movl, 0x7fffffffffffffff, t));
+       EV_SET_SPEFSCR_OV(movl, 0);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1115:EVX:e500:evmwsmf %RS,%RA,%RB:Vector Multiply Word Signed Modulo Fractional
+       signed32 a, b;
+       signed64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = ev_multiply32_smf(a, b, &movl);
+       EV_SET_REG1(*rSh, *rS, t);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1147:EVX:e500:evmwsmfa %RS,%RA,%RB:Vector Multiply Word Signed Modulo Fractional and Accumulate
+       signed32 a, b;
+       signed64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = ev_multiply32_smf(a, b, &movl);
+       EV_SET_REG1_ACC(*rSh, *rS, t);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1113:EVX:e500:evmwsmi %RS,%RA,%RB:Vector Multiply Word Signed Modulo Integer
+       signed32 a, b;
+       signed64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = (signed64)a * (signed64)b;
+       EV_SET_REG1(*rSh, *rS, t);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1145:EVX:e500:evmwsmia %RS,%RA,%RB:Vector Multiply Word Signed Modulo Integer and Accumulate
+       signed32 a, b;
+       signed64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = (signed64)a * (signed64)b;
+       EV_SET_REG1_ACC(*rSh, *rS, t);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1112:EVX:e500:evmwumi %RS,%RA,%RB:Vector Multiply Word Unigned Modulo Integer
+       unsigned32 a, b;
+       unsigned64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = (signed64)a * (signed64)b;
+       EV_SET_REG1(*rSh, *rS, t);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1144:EVX:e500:evmwumia %RS,%RA,%RB:Vector Multiply Word Unigned Modulo Integer and Accumulate
+       unsigned32 a, b;
+       unsigned64 t;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t = (signed64)a * (signed64)b;
+       EV_SET_REG1_ACC(*rSh, *rS, t);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1363:EVX:e500:evmwssfaa %RS,%RA,%RB:Vector Multiply Word Signed Saturate Fractional Add and Accumulate
+       signed64 t1, t2;
+       signed32 a, b;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t1 = ev_multiply32_ssf(a, b, &movl);
+       t2 = ACC + EV_SATURATE(movl, 0x7fffffffffffffff, t1);
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       EV_SET_SPEFSCR_OV(movl, 0);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1371:EVX:e500:evmwsmfaa %RS,%RA,%RB:Vector Multiply Word Signed Modulo Fractional Add and Accumulate
+       signed64 t1, t2;
+       signed32 a, b;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t1 = ev_multiply32_smf(a, b, &movl);
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1369:EVX:e500:evmwsmiaa %RS,%RA,%RB:Vector Multiply Word Signed Modulo Integer And and Accumulate
+       signed64 t1, t2;
+       signed32 a, b;
+       a = *rA;
+       b = *rB;
+       t1 = (signed64)a * (signed64)b;
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1368:EVX:e500:evmwumiaa %RS,%RA,%RB:Vector Multiply Word Unsigned Modulo Integer Add and Accumulate
+       unsigned64 t1, t2;
+       unsigned32 a, b;
+       a = *rA;
+       b = *rB;
+       t1 = (unsigned64)a * (unsigned64)b;
+       t2 = ACC + t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.RB,21.1491:EVX:e500:evmwssfan %RS,%RA,%RB:Vector Multiply Word Signed Saturate Fractional and Accumulate Negative
+       signed64 t1, t2;
+       signed32 a, b;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t1 = ev_multiply32_ssf(a, b, &movl);
+       t2 = ACC - EV_SATURATE(movl, 0x7fffffffffffffff, t1);
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       EV_SET_SPEFSCR_OV(movl, 0);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.1499:EVX:e500:evmwsmfan %RS,%RA,%RB:Vector Multiply Word Signed Modulo Fractional and Accumulate Negative
+       signed64 t1, t2;
+       signed32 a, b;
+       int movl;
+       a = *rA;
+       b = *rB;
+       t1 = ev_multiply32_smf(a, b, &movl);
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1497:EVX:e500:evmwsmian %RS,%RA,%RB:Vector Multiply Word Signed Modulo Integer and Accumulate Negative
+       signed64 t1, t2;
+       signed32 a, b;
+       a = *rA;
+       b = *rB;
+       t1 = (signed64)a * (signed64)b;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1496:EVX:e500:evmwumian %RS,%RA,%RB:Vector Multiply Word Unsigned Modulo Integer and Accumulate Negative
+       unsigned64 t1, t2;
+       unsigned32 a, b;
+       a = *rA;
+       b = *rB;
+       t1 = (unsigned64)a * (unsigned64)b;
+       t2 = ACC - t1;
+       EV_SET_REG1_ACC(*rSh, *rS, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.0,21.1217:EVX:e500:evaddssiaaw %RS,%RA:Vector Add Signed Saturate Integer to Accumulator Word
+       signed64 t1, t2;
+       signed32 al, ah;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       t1 = (signed64)EV_ACCHIGH + (signed64)ah;
+       t2 = (signed64)EV_ACCLOW + (signed64)al;
+       ovh = EV_SAT_P_S32(t1);
+       ovl = EV_SAT_P_S32(t2);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, t1 & ((unsigned64)1 << 32), 0x80000000, 0x7fffffff, t1),
+                                  EV_SATURATE_ACC(ovl, t2 & ((unsigned64)1 << 32), 0x80000000, 0x7fffffff, t2));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.0,21.1225:EVX:e500:evaddsmiaaw %RS,%RA:Vector Add Signed Modulo Integer to Accumulator Word
+       signed64 t1, t2;
+       signed32 al, ah;
+       al = *rA;
+       ah = *rAh;
+       t1 = (signed64)EV_ACCHIGH + (signed64)ah;
+       t2 = (signed64)EV_ACCLOW + (signed64)al;
+       EV_SET_REG2_ACC(*rSh, *rS, t1, t2);
+               //printf("evaddsmiaaw: al %d ah %d t1 %qd t2 %qd\n", al, ah, t1, t2);
+               //printf("evaddsmiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.1216:EVX:e500:evaddusiaaw %RS,%RA:Vector Add Unsigned Saturate Integer to Accumulator Word
+       signed64 t1, t2;
+       unsigned32 al, ah;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       t1 = (signed64)EV_ACCHIGH + (signed64)ah;
+       t2 = (signed64)EV_ACCLOW + (signed64)al;
+       ovh = EV_SAT_P_U32(t1);
+       ovl = EV_SAT_P_U32(t2);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE(ovh, 0xffffffff, t1),
+                                  EV_SATURATE(ovl, 0xffffffff, t2));
+               //printf("evaddusiaaw: ovl %d ovh %d al %d ah %d t1 %qd t2 %qd\n", ovl, ovh, al, ah, t1, t2);
+               //printf("evaddusiaaw: ACC = %08x.%08x; *rSh = %08x; *rS = %08x\n", (int)(ACC >> 32), (int)ACC, *rSh, *rS);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.0,21.1224:EVX:e500:evaddumiaaw %RS,%RA:Vector Add Unsigned Modulo Integer to Accumulator Word
+       unsigned64 t1, t2;
+       unsigned32 al, ah;
+       al = *rA;
+       ah = *rAh;
+       t1 = (unsigned64)EV_ACCHIGH + (unsigned64)ah;
+       t2 = EV_ACCLOW + al;
+       EV_SET_REG2_ACC(*rSh, *rS, t1, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.0,21.1219:EVX:e500:evsubfssiaaw %RS,%RA:Vector Subtract Signed Saturate Integer to Accumulator Word
+       signed64 t1, t2;
+       signed32 al, ah;
+       int ovl, ovh;
+       al = *rA;
+       ah = *rAh;
+       t1 = (signed64)EV_ACCHIGH - (signed64)ah;
+       t2 = (signed64)EV_ACCLOW - (signed64)al;
+       ovh = EV_SAT_P_S32(t1);
+       ovl = EV_SAT_P_S32(t2);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE_ACC(ovh, t1, 0x80000000, 0x7fffffff, t1),
+                                  EV_SATURATE_ACC(ovl, t2, 0x80000000, 0x7fffffff, t2));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.0,21.1227:EVX:e500:evsubfsmiaaw %RS,%RA:Vector Subtract Signed Modulo Integer to Accumulator Word
+       signed64 t1, t2;
+       signed32 al, ah;
+       al = *rA;
+       ah = *rAh;
+       t1 = (signed64)EV_ACCHIGH - (signed64)ah;
+       t2 = (signed64)EV_ACCLOW - (signed64)al;
+       EV_SET_REG2_ACC(*rSh, *rS, t1, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.1218:EVX:e500:evsubfusiaaw %RS,%RA:Vector Subtract Unsigned Saturate Integer to Accumulator Word
+       signed64 t1, t2;
+       unsigned32 al, ah;
+       int ovl, ovh;
+       
+       al = *rA;
+       ah = *rAh;
+       t1 = (signed64)EV_ACCHIGH - (signed64)ah;
+       t2 = (signed64)EV_ACCLOW - (signed64)al;
+       ovh = EV_SAT_P_U32(t1);
+       ovl = EV_SAT_P_U32(t2);
+       EV_SET_REG2_ACC(*rSh, *rS, EV_SATURATE(ovh, 0, t1),
+                                  EV_SATURATE(ovl, 0, t2));
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.0,21.1226:EVX:e500:evsubfumiaaw %RS,%RA:Vector Subtract Unsigned Modulo Integer to Accumulator Word
+       unsigned64 t1, t2;
+       unsigned32 al, ah;
+       al = *rA;
+       ah = *rAh;
+       t1 = (unsigned64)EV_ACCHIGH - (unsigned64)ah;
+       t2 = (unsigned64)EV_ACCLOW - (unsigned64)al;
+       EV_SET_REG2_ACC(*rSh, *rS, t1, t2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.0,21.1220:EVX:e500:evmra %RS,%RA:Initialize Accumulator
+       EV_SET_REG2_ACC(*rSh, *rS, *rAh, *rA);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.1222:EVX:e500:evdivws %RS,%RA,%RB:Vector Divide Word Signed
+       signed32 dividendh, dividendl, divisorh, divisorl;
+       signed32 w1, w2;
+       int ovh, ovl;
+       dividendh = *rAh;
+       dividendl = *rA;
+       divisorh = *rBh;
+       divisorl = *rB;
+       if (dividendh < 0 && divisorh == 0) {
+         w1 = 0x80000000;
+         ovh = 1;
+       } else if (dividendh > 0 && divisorh == 0) {
+         w1 = 0x7fffffff;
+         ovh = 1;
+       } else if (dividendh == 0x80000000 && divisorh == -1) {
+         w1 = 0x7fffffff;
+         ovh = 1;
+       } else {
+         w1 = dividendh / divisorh;
+         ovh = 0;
+       }
+       if (dividendl < 0 && divisorl == 0) {
+         w2 = 0x80000000;
+         ovl = 1;
+       } else if (dividendl > 0 && divisorl == 0) {
+         w2 = 0x7fffffff;
+         ovl = 1;
+       } else if (dividendl == 0x80000000 && divisorl == -1) {
+         w2 = 0x7fffffff;
+         ovl = 1;
+       } else {
+         w2 = dividendl / divisorl;
+         ovl = 0;
+       }
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK, spr_spefscr);
+       
+
+0.4,6.RS,11.RA,16.RB,21.1223:EVX:e500:evdivwu %RS,%RA,%RB:Vector Divide Word Unsigned
+       unsigned32 dividendh, dividendl, divisorh, divisorl;
+       unsigned32 w1, w2;
+       int ovh, ovl;
+       dividendh = *rAh;
+       dividendl = *rA;
+       divisorh = *rBh;
+       divisorl = *rB;
+       if (divisorh == 0) {
+         w1 = 0xffffffff;
+         ovh = 1;
+       } else {
+         w1 = dividendh / divisorh;
+         ovh = 0;
+       }
+       if (divisorl == 0) {
+         w2 = 0xffffffff;
+         ovl = 1;
+       } else {
+         w2 = dividendl / divisorl;
+         ovl = 0;
+       }
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       EV_SET_SPEFSCR_OV(ovl, ovh);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK, spr_spefscr);
+
+
+#
+# A.2.9 Floating Point SPE Instructions
+#
+
+0.4,6.RS,11.RA,16.0,21.644:EVX:e500:evfsabs %RS,%RA:Vector Floating-Point Absolute Value
+       unsigned32 w1, w2;
+       w1 = *rAh & 0x7fffffff;
+       w2 = *rA & 0x7fffffff;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.645:EVX:e500:evfsnabs %RS,%RA:Vector Floating-Point Negative Absolute Value
+       unsigned32 w1, w2;
+       w1 = *rAh | 0x80000000;
+       w2 = *rA | 0x80000000;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.646:EVX:e500:evfsneg %RS,%RA:Vector Floating-Point Negate
+       unsigned32 w1, w2;
+       w1 = *rAh;
+       w2 = *rA;
+       w1 = (w1 & 0x7fffffff) | ((~w1) & 0x80000000);
+       w2 = (w2 & 0x7fffffff) | ((~w2) & 0x80000000);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.640:EVX:e500:evfsadd %RS,%RA,%RB:Vector Floating-Point Add
+       unsigned32 w1, w2;
+       w1 = ev_fs_add (*rAh, *rBh, spefscr_finvh, spefscr_fovfh, spefscr_funfh, spefscr_fgh, spefscr_fxh, processor);
+       w2 = ev_fs_add (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fgh, spefscr_fxh, processor);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.641:EVX:e500:evfssub %RS,%RA,%RB:Vector Floating-Point Subtract
+       unsigned32 w1, w2;
+       w1 = ev_fs_sub (*rAh, *rBh, spefscr_finvh, spefscr_fovfh, spefscr_funfh, spefscr_fgh, spefscr_fxh, processor);
+       w2 = ev_fs_sub (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fgh, spefscr_fxh, processor);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.648:EVX:e500:evfsmul %RS,%RA,%RB:Vector Floating-Point Multiply
+       unsigned32 w1, w2;
+       w1 = ev_fs_mul (*rAh, *rBh, spefscr_finvh, spefscr_fovfh, spefscr_funfh, spefscr_fgh, spefscr_fxh, processor);
+       w2 = ev_fs_mul (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fgh, spefscr_fxh, processor);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.649:EVX:e500:evfsdiv %RS,%RA,%RB:Vector Floating-Point Divide
+       signed32 w1, w2;
+       w1 = ev_fs_div (*rAh, *rBh, spefscr_finvh, spefscr_fovfh, spefscr_funfh, spefscr_fdbzh, spefscr_fgh, spefscr_fxh, processor);
+       w2 = ev_fs_div (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fdbz, spefscr_fg, spefscr_fx, processor);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.652:EVX:e500:evfscmpgt %BF,%RA,%RB:Vector Floating-Point Compare Greater Than
+       sim_fpu al, ah, bl, bh;
+       int w, ch, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&ah, *rAh);
+       sim_fpu_32to (&bl, *rB);
+       sim_fpu_32to (&bh, *rBh);
+       if (EV_IS_INFDENORMNAN(&al) || EV_IS_INFDENORMNAN(&bl))
+         EV_SET_SPEFSCR_BITS(spefscr_finv);
+       if (EV_IS_INFDENORMNAN(&ah) || EV_IS_INFDENORMNAN(&bh))
+         EV_SET_SPEFSCR_BITS(spefscr_finvh);
+       if (sim_fpu_is_gt(&ah, &bh))
+         ch = 1;
+       else
+         ch = 0;
+       if (sim_fpu_is_gt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_SPR(0, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.653:EVX:e500:evfscmplt %BF,%RA,%RB:Vector Floating-Point Compare Less Than
+       sim_fpu al, ah, bl, bh;
+       int w, ch, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&ah, *rAh);
+       sim_fpu_32to (&bl, *rB);
+       sim_fpu_32to (&bh, *rBh);
+       if (EV_IS_INFDENORMNAN(&al) || EV_IS_INFDENORMNAN(&bl))
+         EV_SET_SPEFSCR_BITS(spefscr_finv);
+       if (EV_IS_INFDENORMNAN(&ah) || EV_IS_INFDENORMNAN(&bh))
+         EV_SET_SPEFSCR_BITS(spefscr_finvh);
+       if (sim_fpu_is_lt(&ah, &bh))
+         ch = 1;
+       else
+         ch = 0;
+       if (sim_fpu_is_lt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_SPR(0, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.654:EVX:e500:evfscmpeq %BF,%RA,%RB:Vector Floating-Point Compare Equal
+       sim_fpu al, ah, bl, bh;
+       int w, ch, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&ah, *rAh);
+       sim_fpu_32to (&bl, *rB);
+       sim_fpu_32to (&bh, *rBh);
+       if (EV_IS_INFDENORMNAN(&al) || EV_IS_INFDENORMNAN(&bl))
+         EV_SET_SPEFSCR_BITS(spefscr_finv);
+       if (EV_IS_INFDENORMNAN(&ah) || EV_IS_INFDENORMNAN(&bh))
+         EV_SET_SPEFSCR_BITS(spefscr_finvh);
+       if (sim_fpu_is_eq(&ah, &bh))
+         ch = 1;
+       else
+         ch = 0;
+       if (sim_fpu_is_eq(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_SPR(0, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.668:EVX:e500:evfststgt %BF,%RA,%RB:Vector Floating-Point Test Greater Than
+       sim_fpu al, ah, bl, bh;
+       int w, ch, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&ah, *rAh);
+       sim_fpu_32to (&bl, *rB);
+       sim_fpu_32to (&bh, *rBh);
+       if (sim_fpu_is_gt(&ah, &bh))
+         ch = 1;
+       else
+         ch = 0;
+       if (sim_fpu_is_gt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9./,11.RA,16.RB,21.669:EVX:e500:evfststlt %BF,%RA,%RB:Vector Floating-Point Test Less Than
+       sim_fpu al, ah, bl, bh;
+       int w, ch, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&ah, *rAh);
+       sim_fpu_32to (&bl, *rB);
+       sim_fpu_32to (&bh, *rBh);
+       if (sim_fpu_is_lt(&ah, &bh))
+         ch = 1;
+       else
+         ch = 0;
+       if (sim_fpu_is_lt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9./,11.RA,16.RB,21.670:EVX:e500:evfststeq %BF,%RA,%RB:Vector Floating-Point Test Equal
+       sim_fpu al, ah, bl, bh;
+       int w, ch, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&ah, *rAh);
+       sim_fpu_32to (&bl, *rB);
+       sim_fpu_32to (&bh, *rBh);
+       if (sim_fpu_is_eq(&ah, &bh))
+         ch = 1;
+       else
+         ch = 0;
+       if (sim_fpu_is_eq(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = ch << 3 | cl << 2 | (ch | cl) << 1 | (ch & cl);
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.RS,11.0,16.RB,21.656:EVX:e500:evfscfui %RS,%RB:Vector Convert Floating-Point from Unsigned Integer
+       unsigned32 f, w1, w2;
+       sim_fpu b;
+       
+       sim_fpu_u32to (&b, *rBh, sim_fpu_round_default);
+       sim_fpu_to32 (&w1, &b);
+       sim_fpu_u32to (&b, *rB, sim_fpu_round_default);
+       sim_fpu_to32 (&w2, &b);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.664:EVX:e500:evfsctuiz %RS,%RB:Vector Convert Floating-Point to Unsigned Integer with Round toward Zero
+       unsigned32 w1, w2;
+       sim_fpu b;
+       
+       sim_fpu_32to (&b, *rBh);
+       sim_fpu_to32u (&w1, &b, sim_fpu_round_zero);
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32u (&w2, &b, sim_fpu_round_zero);
+
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.657:EVX:e500:evfscfsi %RS,%RB:Vector Convert Floating-Point from Signed Integer 
+       signed32 w1, w2;
+       sim_fpu b, x, y;
+       
+       sim_fpu_i32to (&b, *rBh, sim_fpu_round_default);
+       sim_fpu_to32 (&w1, &b);
+       sim_fpu_i32to (&b, *rB, sim_fpu_round_default);
+       sim_fpu_to32 (&w2, &b);
+
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.658:EVX:e500:evfscfuf %RS,%RB:Vector Convert Floating-Point from Unsigned Fraction
+       unsigned32 w1, w2, bh, bl;
+       sim_fpu b, x, y;
+       bh = *rBh;
+       if (bh == 0xffffffff)
+         sim_fpu_to32 (&w1, &sim_fpu_one);
+       else {
+         sim_fpu_u64to (&x, 0x100000000, sim_fpu_round_default);
+         sim_fpu_u32to (&y, bh, sim_fpu_round_default);
+         sim_fpu_div (&b, &y, &x);
+         sim_fpu_to32 (&w1, &b);
+       }
+       bl = *rB;
+       if (bl == 0xffffffff)
+         sim_fpu_to32 (&w2, &sim_fpu_one);
+       else {
+         sim_fpu_u64to (&x, 0x100000000, sim_fpu_round_default);
+         sim_fpu_u32to (&y, bl, sim_fpu_round_default);
+         sim_fpu_div (&b, &y, &x);
+         sim_fpu_to32 (&w2, &b);
+       }
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.659:EVX:e500:evfscfsf %RS,%RB:Vector Convert Floating-Point from Signed Fraction
+       unsigned32 w1, w2;
+       sim_fpu b, x, y;
+       
+       sim_fpu_u32to (&x, 0x80000000, sim_fpu_round_default);
+       sim_fpu_i32to (&y, *rBh, sim_fpu_round_default);
+       sim_fpu_div (&b, &y, &x);
+       sim_fpu_to32 (&w1, &b);
+       
+       sim_fpu_u32to (&x, 0x80000000, sim_fpu_round_default);
+       sim_fpu_i32to (&y, *rB, sim_fpu_round_default);
+       sim_fpu_div (&b, &y, &x);
+       sim_fpu_to32 (&w2, &b);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.660:EVX:e500:evfsctui %RS,%RB:Vector Convert Floating-Point to Unsigned Integer
+       unsigned32 w1, w2;
+       sim_fpu b;
+       
+       sim_fpu_32to (&b, *rBh);
+       sim_fpu_to32u (&w1, &b, sim_fpu_round_default);
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32u (&w2, &b, sim_fpu_round_default);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.661:EVX:e500:evfsctsi %RS,%RB:Vector Convert Floating-Point to Signed Integer
+       signed32 w1, w2;
+       sim_fpu b;
+       
+       sim_fpu_32to (&b, *rBh);
+       sim_fpu_to32i (&w1, &b, sim_fpu_round_default);
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32i (&w2, &b, sim_fpu_round_default);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.666:EVX:e500:evfsctsiz %RS,%RB:Vector Convert Floating-Point to Signed Integer with Round toward Zero
+       signed32 w1, w2;
+       sim_fpu b;
+       
+       sim_fpu_32to (&b, *rBh);
+       sim_fpu_to32i (&w1, &b, sim_fpu_round_zero);
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32i (&w2, &b, sim_fpu_round_zero);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.662:EVX:e500:evfsctuf %RS,%RB:Vector Convert Floating-Point to Unsigned Fraction
+       unsigned32 w1, w2;
+       sim_fpu b, x, y;
+       
+       sim_fpu_u64to (&x, 0x100000000, sim_fpu_round_default);
+       sim_fpu_32to (&y, *rBh);
+       sim_fpu_mul (&b, &y, &x);
+       sim_fpu_to32u (&w1, &b, sim_fpu_round_default);
+       
+       sim_fpu_u64to (&x, 0x100000000, sim_fpu_round_default);
+       sim_fpu_32to (&y, *rB);
+       sim_fpu_mul (&b, &y, &x);
+       sim_fpu_to32u (&w2, &b, sim_fpu_round_default);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.663:EVX:e500:evfsctsf %RS,%RB:Vector Convert Floating-Point to Signed Fraction
+       signed32 w1, w2;
+       sim_fpu b, x, y;
+       
+       sim_fpu_32to (&y, *rBh);
+       sim_fpu_u32to (&x, 0x80000000, sim_fpu_round_default);
+       sim_fpu_mul (&b, &y, &x);
+       sim_fpu_to32i (&w1, &b, sim_fpu_round_near);
+       
+       sim_fpu_32to (&y, *rB);
+       sim_fpu_u32to (&x, 0x80000000, sim_fpu_round_default);
+       sim_fpu_mul (&b, &y, &x);
+       sim_fpu_to32i (&w2, &b, sim_fpu_round_near);
+       
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.0,21.708:EVX:e500:efsabs %RS,%RA:Floating-Point Absolute Value
+       unsigned32 w1, w2;
+       w1 = *rSh;
+       w2 = *rA & 0x7fffffff;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.709:EVX:e500:efsnabs %RS,%RA:Floating-Point Negative Absolute Value
+       unsigned32 w1, w2;
+       w1 = *rSh;
+       w2 = *rA | 0x80000000;
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.0,21.710:EVX:e500:efsneg %RS,%RA:Floating-Point Negate
+       unsigned32 w1, w2;
+       w1 = *rSh;
+       w2 = (*rA & 0x7fffffff) | ((~*rA) & 0x80000000);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.RB,21.704:EVX:e500:efsadd %RS,%RA,%RB:Floating-Point Add
+       unsigned32 w;
+       w = ev_fs_add (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fgh, spefscr_fxh, processor);
+       EV_SET_REG(*rS, w);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.705:EVX:e500:efssub %RS,%RA,%RB:Floating-Point Subtract
+       unsigned32 w;
+       w = ev_fs_sub (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fgh, spefscr_fxh, processor);
+       EV_SET_REG(*rS, w);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.712:EVX:e500:efsmul %RS,%RA,%RB:Floating-Point Multiply
+       unsigned32 w;
+       w = ev_fs_mul (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fgh, spefscr_fxh, processor);
+       EV_SET_REG(*rS, w);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.RS,11.RA,16.RB,21.713:EVX:e500:efsdiv %RS,%RA,%RB:Floating-Point Divide
+       unsigned32 w;
+       w = ev_fs_div (*rA, *rB, spefscr_finv, spefscr_fovf, spefscr_funf, spefscr_fdbz, spefscr_fg, spefscr_fx, processor);
+       EV_SET_REG(*rS, w);
+       PPC_INSN_INT_SPR(RS_BITMASK, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.716:EVX:e500:efscmpgt %BF,%RA,%RB:Floating-Point Compare Greater Than
+       sim_fpu a, b;
+       int w, cl;
+       sim_fpu_32to (&a, *rA);
+       sim_fpu_32to (&b, *rB);
+       if (EV_IS_INFDENORMNAN(&a) || EV_IS_INFDENORMNAN(&b))
+         EV_SET_SPEFSCR_BITS(spefscr_finv);
+       if (sim_fpu_is_gt(&a, &b))
+         cl = 1;
+       else
+         cl = 0;
+       w = cl << 2 | cl << 1;
+       CR_SET(BF, w);
+       PPC_INSN_INT_SPR(0, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.717:EVX:e500:efscmplt %BF,%RA,%RB:Floating-Point Compare Less Than
+       sim_fpu al, bl;
+       int w, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&bl, *rB);
+       if (EV_IS_INFDENORMNAN(&al) || EV_IS_INFDENORMNAN(&bl))
+         EV_SET_SPEFSCR_BITS(spefscr_finv);
+       if (sim_fpu_is_lt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = cl << 2 | cl << 1;
+       CR_SET(BF, w);
+       PPC_INSN_INT_SPR(0, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.718:EVX:e500:efscmpeq %BF,%RA,%RB:Floating-Point Compare Equal
+       sim_fpu al, bl;
+       int w, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&bl, *rB);
+       if (EV_IS_INFDENORMNAN(&al) || EV_IS_INFDENORMNAN(&bl))
+         EV_SET_SPEFSCR_BITS(spefscr_finv);
+       if (sim_fpu_is_eq(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = cl << 2 | cl << 1;
+       CR_SET(BF, w);
+       PPC_INSN_INT_SPR(0, RA_BITMASK | RB_BITMASK, spr_spefscr);
+
+0.4,6.BF,9./,11.RA,16.RB,21.732:EVX:e500:efststgt %BF,%RA,%RB:Floating-Point Test Greater Than
+       sim_fpu al, bl;
+       int w, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&bl, *rB);
+       if (sim_fpu_is_gt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = cl << 2 | cl << 1;
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9./,11.RA,16.RB,21.733:EVX:e500:efststlt %BF,%RA,%RB:Floating-Point Test Less Than
+       sim_fpu al, bl;
+       int w, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&bl, *rB);
+       if (sim_fpu_is_lt(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = cl << 2 | cl << 1;
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.BF,9./,11.RA,16.RB,21.734:EVX:e500:efststeq %BF,%RA,%RB:Floating-Point Test Equal
+       sim_fpu al, bl;
+       int w, cl;
+       sim_fpu_32to (&al, *rA);
+       sim_fpu_32to (&bl, *rB);
+       if (sim_fpu_is_eq(&al, &bl))
+         cl = 1;
+       else
+         cl = 0;
+       w = cl << 2 | cl << 1;
+       CR_SET(BF, w);
+       PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
+
+0.4,6.RS,11.0,16.RB,21.721:EVX:e500:efscfsi %RS,%RB:Convert Floating-Point from Signed Integer
+       signed32 f, w1, w2;
+       sim_fpu b;
+       w1 = *rSh;
+       sim_fpu_i32to (&b, *rB, sim_fpu_round_default);
+       sim_fpu_to32 (&w2, &b);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.720:EVX:e500:efscfui %RS,%RB:Convert Floating-Point from Unsigned Integer
+       unsigned32 w1, w2;
+       sim_fpu b;
+       w1 = *rSh;
+       sim_fpu_u32to (&b, *rB, sim_fpu_round_default);
+       sim_fpu_to32 (&w2, &b);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.723:EVX:e500:efscfsf %RS,%RB:Convert Floating-Point from Signed Fraction
+       unsigned32 w1, w2;
+       sim_fpu b, x, y;
+       w1 = *rSh;
+       sim_fpu_u32to (&x, 0x80000000, sim_fpu_round_default);
+       sim_fpu_i32to (&y, *rB, sim_fpu_round_default);
+       sim_fpu_div (&b, &y, &x);
+       sim_fpu_to32 (&w2, &b);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.722:EVX:e500:efscfuf %RS,%RB:Convert Floating-Point from Unsigned Fraction
+       unsigned32 w1, w2, bl;
+       sim_fpu b, x, y;
+       w1 = *rSh;
+       bl = *rB;
+       if (bl == 0xffffffff)
+         sim_fpu_to32 (&w2, &sim_fpu_one);
+       else {
+         sim_fpu_u64to (&x, 0x100000000, sim_fpu_round_default);
+         sim_fpu_u32to (&y, bl, sim_fpu_round_default);
+         sim_fpu_div (&b, &y, &x);
+         sim_fpu_to32 (&w2, &b);
+       }
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.725:EVX:e500:efsctsi %RS,%RB:Convert Floating-Point to Signed Integer
+       signed64 temp;
+       signed32 w1, w2;
+       sim_fpu b;
+       w1 = *rSh;
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32i (&w2, &b, sim_fpu_round_default);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.730:EVX:e500:efsctsiz %RS,%RB:Convert Floating-Point to Signed Integer with Round toward Zero
+       signed64 temp;
+       signed32 w1, w2;
+       sim_fpu b;
+       w1 = *rSh;
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32i (&w2, &b, sim_fpu_round_zero);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.724:EVX:e500:efsctui %RS,%RB:Convert Floating-Point to Unsigned Integer
+       unsigned64 temp;
+       signed32 w1, w2;
+       sim_fpu b;
+       w1 = *rSh;
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32u (&w2, &b, sim_fpu_round_default);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.728:EVX:e500:efsctuiz %RS,%RB:Convert Floating-Point to Unsigned Integer with Round toward Zero
+       unsigned64 temp;
+       signed32 w1, w2;
+       sim_fpu b;
+       w1 = *rSh;
+       sim_fpu_32to (&b, *rB);
+       sim_fpu_to32u (&w2, &b, sim_fpu_round_zero);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.727:EVX:e500:efsctsf %RS,%RB:Convert Floating-Point to Signed Fraction
+       unsigned32 w1, w2;
+       sim_fpu b, x, y;
+       w1 = *rSh;
+       sim_fpu_32to (&y, *rB);
+       sim_fpu_u32to (&x, 0x80000000, sim_fpu_round_default);
+       sim_fpu_mul (&b, &y, &x);
+       sim_fpu_to32i (&w2, &b, sim_fpu_round_default);
+       sim_fpu_to32 (&w2, &b);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+0.4,6.RS,11.0,16.RB,21.726:EVX:e500:efsctuf %RS,%RB:Convert Floating-Point to Unsigned Fraction
+       unsigned32 w1, w2;
+       sim_fpu b, x, y;
+       w1 = *rSh;
+       sim_fpu_u64to (&x, 0x100000000, sim_fpu_round_default);
+       sim_fpu_32to (&y, *rB);
+       sim_fpu_mul (&b, &y, &x);
+       sim_fpu_to32u (&w2, &b, sim_fpu_round_default);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, RB_BITMASK, 0);
+
+
+#
+# A.2.10 Vector Load/Store Instructions
+#
+
+0.4,6.RS,11.RA,16.UIMM,21.769:EVX:e500:evldd %RS,%RA,%UIMM:Vector Load Double Word into Double Word
+       unsigned64 m;
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       m = MEM(unsigned, EA, 8);
+       EV_SET_REG1(*rSh, *rS, m);
+               //printf("evldd(%d<-%d + %u): m %08x.%08x, *rSh %x *rS %x\n", RS, RA, UIMM, (int)(m >> 32), (int)m, *rSh, *rS);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.768:EVX:e500:evlddx %RS,%RA,%RB:Vector Load Double Word into Double Word Indexed
+       unsigned64 m;
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       m = MEM(unsigned, EA, 8);
+       EV_SET_REG1(*rSh, *rS, m);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.771:EVX:e500:evldw %RS,%RA,%UIMM:Vector Load Double into Two Words
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w1, w2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       w1 = MEM(unsigned, EA, 4);
+       w2 = MEM(unsigned, EA + 4, 4);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.770:EVX:e500:evldwx %RS,%RA,%RB:Vector Load Double into Two Words Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w1, w2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       w1 = MEM(unsigned, EA, 4);
+       w2 = MEM(unsigned, EA + 4, 4);
+       EV_SET_REG2(*rSh, *rS, w1, w2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.773:EVX:e500:evldh %RS,%RA,%UIMM:Vector Load Double into 4 Half Words
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       h1 = MEM(unsigned, EA, 2);
+       h2 = MEM(unsigned, EA + 2, 2);
+       h3 = MEM(unsigned, EA + 4, 2);
+       h4 = MEM(unsigned, EA + 6, 2);
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.772:EVX:e500:evldhx %RS,%RA,%RB:Vector Load Double into 4 Half Words Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = MEM(unsigned, EA, 2);
+       h2 = MEM(unsigned, EA + 2, 2);
+       h3 = MEM(unsigned, EA + 4, 2);
+       h4 = MEM(unsigned, EA + 6, 2);
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.785:EVX:e500:evlwhe %RS,%RA,%UIMM:Vector Load Word into Two Half Words Even
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 2);
+       h1 = MEM(unsigned, EA, 2);
+       h2 = 0;
+       h3 = MEM(unsigned, EA + 2, 2);
+       h4 = 0;
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.784:EVX:e500:evlwhex %RS,%RA,%RB:Vector Load Word into Two Half Words Even Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = MEM(unsigned, EA, 2);
+       h2 = 0;
+       h3 = MEM(unsigned, EA + 2, 2);
+       h4 = 0;
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.789:EVX:e500:evlwhou %RS,%RA,%UIMM:Vector Load Word into Two Half Words Odd Unsigned zero-extended
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 2);
+       h1 = 0;
+       h2 = MEM(unsigned, EA, 2);
+       h3 = 0;
+       h4 = MEM(unsigned, EA + 2, 2);
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.788:EVX:e500:evlwhoux %RS,%RA,%RB:Vector Load Word into Two Half Words Odd Unsigned Indexed zero-extended
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = 0;
+       h2 = MEM(unsigned, EA, 2);
+       h3 = 0;
+       h4 = MEM(unsigned, EA + 2, 2);
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.791:EVX:e500:evlwhos %RS,%RA,%UIMM:Vector Load Word into Half Words Odd Signed with sign extension
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 2);
+       h2 = MEM(unsigned, EA, 2);
+       if (h2 & 0x8000)
+         h1 = 0xffff;
+       else
+         h1 = 0;
+       h4 = MEM(unsigned, EA + 2, 2);
+       if (h4 & 0x8000)
+         h3 = 0xffff;
+       else
+         h3 = 0;
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.790:EVX:e500:evlwhosx %RS,%RA,%RB:Vector Load Word into Half Words Odd Signed Indexed with sign extension
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h2 = MEM(unsigned, EA, 2);
+       if (h2 & 0x8000)
+         h1 = 0xffff;
+       else
+         h1 = 0;
+       h4 = MEM(unsigned, EA + 2, 2);
+       if (h4 & 0x8000)
+         h3 = 0xffff;
+       else
+         h3 = 0;
+       EV_SET_REG4(*rSh, *rS, h1, h2, h3, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.793:EVX:e500:evlwwsplat %RS,%RA,%UIMM:Vector Load Word into Word and Splat
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w1;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 2);
+       w1 = MEM(unsigned, EA, 4);
+       EV_SET_REG2(*rSh, *rS, w1, w1);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.792:EVX:e500:evlwwsplatx %RS,%RA,%RB:Vector Load Word into Word and Splat Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w1;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       w1 = MEM(unsigned, EA, 4);
+       EV_SET_REG2(*rSh, *rS, w1, w1);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.797:EVX:e500:evlwhsplat %RS,%RA,%UIMM:Vector Load Word into 2 Half Words and Splat
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 2);
+       h1 = MEM(unsigned, EA, 2);
+       h2 = MEM(unsigned, EA + 2, 2);
+       EV_SET_REG4(*rSh, *rS, h1, h1, h2, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.796:EVX:e500:evlwhsplatx %RS,%RA,%RB:Vector Load Word into 2 Half Words and Splat Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = MEM(unsigned, EA, 2);
+       h2 = MEM(unsigned, EA + 2, 2);
+       EV_SET_REG4(*rSh, *rS, h1, h1, h2, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.777:EVX:e500:evlhhesplat %RS,%RA,%UIMM:Vector Load Half Word into Half Words Even and Splat
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 1);
+       h = MEM(unsigned, EA, 2);
+       EV_SET_REG4(*rSh, *rS, h, 0, h, 0);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.776:EVX:e500:evlhhesplatx %RS,%RA,%RB:Vector Load Half Word into Half Words Even and Splat Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h = MEM(unsigned, EA, 2);
+       EV_SET_REG4(*rSh, *rS, h, 0, h, 0);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.781:EVX:e500:evlhhousplat %RS,%RA,%UIMM:Vector Load Half Word into Half Word Odd Unsigned and Splat
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 1);
+       h = MEM(unsigned, EA, 2);
+       EV_SET_REG4(*rSh, *rS, 0, h, 0, h);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.780:EVX:e500:evlhhousplatx %RS,%RA,%RB:Vector Load Half Word into Half Word Odd Unsigned and Splat Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h = MEM(unsigned, EA, 2);
+       EV_SET_REG4(*rSh, *rS, 0, h, 0, h);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.783:EVX:e500:evlhhossplat %RS,%RA,%UIMM:Vector Load Half Word into Half Word Odd Signed and Splat
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 1);
+       h2 = MEM(unsigned, EA, 2);
+       if (h2 & 0x8000)
+         h1 = 0xffff;
+       else
+         h1 = 0;
+       EV_SET_REG4(*rSh, *rS, h1, h2, h1, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.782:EVX:e500:evlhhossplatx %RS,%RA,%RB:Vector Load Half Word into Half Word Odd Signed and Splat Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h2 = MEM(unsigned, EA, 2);
+       if (h2 & 0x8000)
+         h1 = 0xffff;
+       else
+         h1 = 0;
+       EV_SET_REG4(*rSh, *rS, h1, h2, h1, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+
+0.4,6.RS,11.RA,16.UIMM,21.801:EVX:e500:evstdd %RS,%RA,%UIMM:Vector Store Double of Double
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       STORE(EA, 4, (*rSh));
+       STORE(EA + 4, 4, (*rS));
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.800:EVX:e500:evstddx %RS,%RA,%RB:Vector Store Double of Double Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       STORE(EA, 4, (*rSh));
+       STORE(EA + 4, 4, (*rS));
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.803:EVX:e500:evstdw %RS,%RA,%UIMM:Vector Store Double of Two Words
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w1, w2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       w1 = *rSh;
+       w2 = *rS;
+       STORE(EA + 0, 4, w1);
+       STORE(EA + 4, 4, w2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.802:EVX:e500:evstdwx %RS,%RA,%RB:Vector Store Double of Two Words Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w1, w2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       w1 = *rSh;
+       w2 = *rS;
+       STORE(EA + 0, 4, w1);
+       STORE(EA + 4, 4, w2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.805:EVX:e500:evstdh %RS,%RA,%UIMM:Vector Store Double of Four Half Words
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       h1 = EV_HIHALF(*rSh);
+       h2 = EV_LOHALF(*rSh);
+       h3 = EV_HIHALF(*rS);
+       h4 = EV_LOHALF(*rS);
+       STORE(EA + 0, 2, h1);
+       STORE(EA + 2, 2, h2);
+       STORE(EA + 4, 2, h3);
+       STORE(EA + 6, 2, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.804:EVX:e500:evstdhx %RS,%RA,%RB:Vector Store Double of Four Half Words Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2, h3, h4;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = EV_HIHALF(*rSh);
+       h2 = EV_LOHALF(*rSh);
+       h3 = EV_HIHALF(*rS);
+       h4 = EV_LOHALF(*rS);
+       STORE(EA + 0, 2, h1);
+       STORE(EA + 2, 2, h2);
+       STORE(EA + 4, 2, h3);
+       STORE(EA + 6, 2, h4);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.825:EVX:e500:evstwwe %RS,%RA,%UIMM:Vector Store Word of Word from Even
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       w = *rSh;
+       STORE(EA, 4, w);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.824:EVX:e500:evstwwex %RS,%RA,%RB:Vector Store Word of Word from Even Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       w = *rSh;
+       STORE(EA, 4, w);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.829:EVX:e500:evstwwo %RS,%RA,%UIMM:Vector Store Word of Word from Odd
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       w = *rS;
+       STORE(EA, 4, w);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.828:EVX:e500:evstwwox %RS,%RA,%RB:Vector Store Word of Word from Odd Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned32 w;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       w = *rS;
+       STORE(EA, 4, w);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.817:EVX:e500:evstwhe %RS,%RA,%UIMM:Vector Store Word of Two Half Words from Even
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       h1 = EV_HIHALF(*rSh);
+       h2 = EV_HIHALF(*rS);
+       STORE(EA + 0, 2, h1);
+       STORE(EA + 2, 2, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.816:EVX:e500:evstwhex %RS,%RA,%RB:Vector Store Word of Two Half Words from Even Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = EV_HIHALF(*rSh);
+       h2 = EV_HIHALF(*rS);
+       STORE(EA + 0, 2, h1);
+       STORE(EA + 2, 2, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+0.4,6.RS,11.RA,16.UIMM,21.821:EVX:e500:evstwho %RS,%RA,%UIMM:Vector Store Word of Two Half Words from Odd
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + (UIMM << 3);
+       h1 = EV_LOHALF(*rSh);
+       h2 = EV_LOHALF(*rS);
+       STORE(EA + 0, 2, h1);
+       STORE(EA + 2, 2, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1), 0);
+
+0.4,6.RS,11.RA,16.RB,21.820:EVX:e500:evstwhox %RS,%RA,%RB:Vector Store Word of Two Half Words from Odd Indexed
+       unsigned_word b;
+       unsigned_word EA;
+       unsigned16 h1, h2;
+       if (RA_is_0) b = 0;
+       else         b = *rA;
+       EA = b + *rB;
+       h1 = EV_LOHALF(*rSh);
+       h2 = EV_LOHALF(*rS);
+       STORE(EA + 0, 2, h1);
+       STORE(EA + 2, 2, h2);
+       PPC_INSN_INT(RS_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
+
+
+#
+# 4.5.1 Integer Select Instruction
+#
+
+0.31,6.RS,11.RA,16.RB,21.CRB,26.30:X:e500:isel %RS,%RA,%RB,%CRB:Integer Select
+       if (CR & (1 << (31 - (unsigned)CRB)))
+         if (RA_is_0)
+           EV_SET_REG1(*rSh, *rS, 0);
+         else
+           EV_SET_REG2(*rSh, *rS, *rAh, *rA);
+       else
+         EV_SET_REG2(*rSh, *rS, *rBh, *rB);
+       PPC_INSN_INT(RS_BITMASK, RA_BITMASK | RB_BITMASK, 0);
diff --git a/sim/ppc/e500_expression.h b/sim/ppc/e500_expression.h
new file mode 100644 (file)
index 0000000..c634a1c
--- /dev/null
@@ -0,0 +1,173 @@
+/* e500 expression macros, for PSIM, the PowerPC simulator.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Red Hat Inc; developed under contract from Motorola.
+   Written by matthew green <mrg@redhat.com>.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* e500 register dance */
+#define EV_SET_REG4(sh, sl, h0, h1, h2, h3) do { \
+       (sh) = (((h0) & 0xffff) << 16) | ((h1) & 0xffff); \
+       (sl) = (((h2) & 0xffff) << 16) | ((h3) & 0xffff); \
+} while (0)
+#define EV_SET_REG4_ACC(sh, sl, h0, h1, h2, h3) do { \
+       (sh) = (((h0) & 0xffff) << 16) | ((h1) & 0xffff); \
+       (sl) = (((h2) & 0xffff) << 16) | ((h3) & 0xffff); \
+       ACC = ((unsigned64)(sh) << 32) | (sl & 0xffffffff); \
+} while (0)
+
+#define EV_SET_REG2(sh, sl, dh, dl) do { \
+       (sh) = (dh) & 0xffffffff; \
+       (sl) = (dl) & 0xffffffff; \
+} while (0)
+#define EV_SET_REG2_ACC(sh, sl, dh, dl) do { \
+       (sh) = (dh) & 0xffffffff; \
+       (sl) = (dl) & 0xffffffff; \
+       ACC = ((unsigned64)(sh) << 32) | ((sl) & 0xffffffff); \
+} while (0)
+
+#define EV_SET_REG1(sh, sl, d) do { \
+       (sh) = ((unsigned64)(d) >> 32) & 0xffffffff; \
+       (sl) = (d) & 0xffffffff; \
+} while (0)
+#define EV_SET_REG1_ACC(sh, sl, d) do { \
+       (sh) = ((unsigned64)(d) >> 32) & 0xffffffff; \
+       (sl) = (d) & 0xffffffff; \
+       ACC = (d); \
+} while (0)
+
+#define EV_SET_REG(s, d) do { \
+       (s) = (d) & 0xffffffff; \
+} while (0)
+
+/* get the low or high half word of a word */
+#define EV_LOHALF(x)   ((unsigned32)(x) & 0xffff)
+#define EV_HIHALF(x)   (((unsigned32)(x) >> 16) & 0xffff)
+
+/* partially visible accumulator accessors */
+#define EV_SET_ACC(rh, rl) \
+       ACC = ((unsigned64)(rh) << 32) | ((rl) & 0xffffffff)
+
+#define EV_ACCLOW      (ACC & 0xffffffff)
+#define EV_ACCHIGH     ((ACC >> 32) & 0xffffffff)
+
+/* bit manipulation macros needed for e500 SPE */
+#define EV_BITREVERSE16(x) \
+                 (((x) & 0x0001) << 15) \
+               | (((x) & 0x0002) << 13) \
+               | (((x) & 0x0004) << 11) \
+               | (((x) & 0x0008) << 9) \
+               | (((x) & 0x0010) << 7) \
+               | (((x) & 0x0020) << 5) \
+               | (((x) & 0x0040) << 3) \
+               | (((x) & 0x0080) << 1) \
+               | (((x) & 0x0100) >> 1) \
+               | (((x) & 0x0200) >> 3) \
+               | (((x) & 0x0400) >> 5) \
+               | (((x) & 0x0800) >> 7) \
+               | (((x) & 0x1000) >> 9) \
+               | (((x) & 0x2000) >> 11) \
+               | (((x) & 0x4000) >> 13) \
+               | (((x) & 0x8000) >> 15)
+
+/* saturation helpers */
+#define EV_MUL16_SSF(a,b)      ((signed64)((signed32)(signed16)(a) * (signed32)(signed16)(b)) << 1)
+/* this one loses the top sign bit; be careful */
+#define EV_MUL32_SSF(a,b)      (((signed64)(signed32)(a) * (signed64)(signed32)(b)) << 1)
+#define EV_SAT_P_S32(x)                ((((signed64)(x)) < -0x80000000LL) || (((signed64)(x)) > 0x7fffffffLL))
+#define EV_SAT_P_U32(x)                ((((signed64)(x)) < -0LL) || (((signed64)(x)) > 0xffffffffLL))
+
+#define EV_SATURATE(flag, sat_val, val) \
+       ((flag) ? (sat_val) : (val))
+
+#define EV_SATURATE_ACC(flag, sign, negative_sat_val, positive_sat_val, val) \
+       ((flag) ? ((((sign) >> 63) & 1) ? (negative_sat_val) : (positive_sat_val)) : (val))
+
+/* SPEFSCR handling.  */
+
+/* These bits must be clear.  */
+#define EV_SPEFSCR_MASK (BIT(40) | BIT(41) | spefscr_mode | BIT(56))
+
+/* The Inexact and Divide by zero sticky bits are based on others.  */
+#define EV_SET_SPEFSCR(bits) do { \
+  int finxs = (bits) & (spefscr_fgh|spefscr_fxh|spefscr_fg|spefscr_fx); \
+  int fdbzs = (bits) & (spefscr_fdbzh|spefscr_fdbz); \
+  SPREG(spr_spefscr) = ((bits) & ~EV_SPEFSCR_MASK) | \
+                      (finxs ? spefscr_finxs : 0) | \
+                      (fdbzs ? spefscr_fdbzs : 0); \
+} while (0)
+
+#define EV_SET_SPEFSCR_BITS(s) \
+  EV_SET_SPEFSCR(SPREG(spr_spefscr) | (s))
+
+#define EV_SET_SPEFSCR_OV(l,h) do { \
+       unsigned32 _sPefScR = SPREG(spr_spefscr); \
+       if (l) \
+         _sPefScR |= spefscr_ov | spefscr_sov; \
+       else \
+         _sPefScR &= ~spefscr_ov; \
+       if (h) \
+         _sPefScR |= spefscr_ovh | spefscr_sovh; \
+       else \
+         _sPefScR &= ~spefscr_ovh; \
+       EV_SET_SPEFSCR(_sPefScR); \
+} while (0)
+
+/* SPE floating point helpers.  */
+
+#define EV_PMAX        0x7f7fffff
+#define EV_NMAX        0xff7fffff
+#define EV_PMIN        0x00800001
+#define EV_NMIN        0x80800001
+
+#define        EV_IS_INFDENORMNAN(x) \
+       (sim_fpu_is_infinity(x) || sim_fpu_is_denorm(x) || sim_fpu_is_nan(x))
+
+/* These aren't used (yet?)  For now, SPU is always enabled.
+   Would be nice if they were generated by igen for e500.  */
+#define SPU_BEGIN \
+{ \
+  if (MSR & msr_e500_spu_enable) { \
+
+#define SPU_END \
+  } else { \
+    /* FIXME: raise SPU unavailable.  */ \
+  } \
+}
+
+/* These are also not yet used.  */
+#define SPU_FP_BEGIN \
+{
+
+#define SPU_FP_END \
+  { \
+     unsigned s = SPEFSCR; \
+     /* Check SPEFSCR; raise exceptions if any required.  */ \
+     if (((spefscr_finxe || spefscr_finve) \
+        && (s & (spefscr_finvh|spefscr_finv))) \
+      || ((spefscr_finxe || spefscr_fdbze) \
+        && (s & (spefscr_fdbzh|spefscr_fdbz))) \
+      || ((spefscr_finxe || spefscr_funfe) \
+        && (s & (spefscr_funfh|spefscr_funf))) \
+      || ((spefscr_finxe || spefscr_fovfe) \
+        && (s & (spefscr_fovfh|spefscr_fovf)))) \
+       /* FIXME: raise exceptions.  */; \
+   } \
+}
diff --git a/sim/ppc/e500_registers.h b/sim/ppc/e500_registers.h
new file mode 100644 (file)
index 0000000..cd12ab5
--- /dev/null
@@ -0,0 +1,83 @@
+/* e500 registers, for PSIM, the PowerPC simulator.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Red Hat Inc; developed under contract from Motorola.
+   Written by matthew green <mrg@redhat.com>.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* e500 accumulator.  */
+
+typedef unsigned64 accreg;
+
+enum {
+  msr_e500_spu_enable = BIT(38)
+};
+
+/* E500 regsiters.  */
+
+enum
+  {
+  spefscr_sovh = BIT(32),      /* summary integer overlow (high) */
+  spefscr_ovh = BIT(33),       /* int overflow (high) */
+  spefscr_fgh = BIT(34),       /* FP guard (high) */
+  spefscr_fxh = BIT(35),       /* FP sticky (high) */
+  spefscr_finvh = BIT(36),     /* FP invalid operand (high) */
+  spefscr_fdbzh = BIT(37),     /* FP divide by zero (high) */
+  spefscr_funfh = BIT(38),     /* FP underflow (high) */
+  spefscr_fovfh = BIT(39),     /* FP overflow (high) */
+  spefscr_finxs = BIT(42),     /* FP inexact sticky */
+  spefscr_finvs = BIT(43),     /* FP invalid operand sticky */
+  spefscr_fdbzs = BIT(44),     /* FP divide by zero sticky */
+  spefscr_funfs = BIT(45),     /* FP underflow sticky */
+  spefscr_fovfs = BIT(46),     /* FP overflow sticky */
+  spefscr_mode = BIT(47),      /* SPU MODE (read only) */
+  spefscr_sov = BIT(48),       /* Summary integer overlow (low) */
+  spefscr_ov = BIT(49),                /* int overflow (low) */
+  spefscr_fg = BIT(50),                /* FP guard (low) */
+  spefscr_fx = BIT(51),                /* FP sticky (low) */
+  spefscr_finv = BIT(52),      /* FP invalid operand (low) */
+  spefscr_fdbz = BIT(53),      /* FP divide by zero (low) */
+  spefscr_funf = BIT(54),      /* FP underflow (low) */
+  spefscr_fovf = BIT(55),      /* FP overflow (low) */
+  spefscr_finxe = BIT(57),     /* FP inexact enable */
+  spefscr_finve = BIT(58),     /* FP invalid operand enable */
+  spefscr_fdbze = BIT(59),     /* FP divide by zero enable */
+  spefscr_funfe = BIT(60),     /* FP underflow enable */
+  spefscr_fovfe = BIT(61),     /* FP overflow enable */
+  spefscr_frmc0 = BIT(62),     /* FP round mode control */
+  spefscr_frmc1 = BIT(63),
+  spefscr_frmc = (spefscr_frmc0 | spefscr_frmc1),
+};
+
+struct e500_regs {
+  /* e500 high bits.  */
+  signed_word gprh[32];
+  /* Accumulator */
+  accreg acc;
+};
+
+/* SPE partially visible acculator */
+#define ACC            cpu_registers(processor)->e500.acc
+
+/* e500 register high bits */
+#define GPRH(N)                cpu_registers(processor)->e500.gprh[N]
+
+/* e500 unified vector register */
+#define EVR(N)         ((((unsigned64)GPRH(N)) << 32) | GPR(N))