aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobody <>2003-06-27 17:05:59 +0000
committernobody <>2003-06-27 17:05:59 +0000
commitc8a2fad7b41a8264964233608ae10c35918243fb (patch)
tree51bfadce02ac30f808dcfb8d118e8a8dd0d2878b
parent40ea26e40a0f9e36464336daf7972612b3b5fee7 (diff)
downloadgdb-c8a2fad7b41a8264964233608ae10c35918243fb.zip
gdb-c8a2fad7b41a8264964233608ae10c35918243fb.tar.gz
gdb-c8a2fad7b41a8264964233608ae10c35918243fb.tar.bz2
This commit was manufactured by cvs2svn to create branch
'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
-rw-r--r--gdb/alpha-mdebug-tdep.c384
-rw-r--r--gdb/config/mips/mips.mt5
-rw-r--r--gdb/config/mips/mips64.mt5
-rw-r--r--gdb/config/powerpc/nm-ppc64-linux.h27
-rw-r--r--gdb/config/powerpc/ppc64-linux.mh19
-rw-r--r--gdb/dwarf2-frame.c1336
-rw-r--r--gdb/dwarf2-frame.h43
-rw-r--r--gdb/linux-nat.c219
-rw-r--r--gdb/linux-nat.h73
-rw-r--r--gdb/remote-fileio.c1379
-rw-r--r--gdb/remote-fileio.h38
-rw-r--r--gdb/stack.h27
-rw-r--r--gdb/testsuite/gdb.asm/alpha.inc62
-rw-r--r--gdb/testsuite/gdb.base/bang.exp41
-rw-r--r--gdb/testsuite/gdb.base/fileio.c503
-rw-r--r--gdb/testsuite/gdb.base/fileio.exp277
-rw-r--r--gdb/testsuite/gdb.base/gdb_history256
-rw-r--r--gdb/testsuite/gdb.base/shreloc.c18
-rw-r--r--gdb/testsuite/gdb.base/shreloc.exp257
-rw-r--r--gdb/testsuite/gdb.base/shreloc1.c10
-rw-r--r--gdb/testsuite/gdb.base/shreloc2.c10
-rw-r--r--gdb/testsuite/gdb.c++/pr-1210.cc19
-rw-r--r--gdb/testsuite/gdb.c++/pr-1210.exp76
-rw-r--r--gdb/trad-frame.c96
-rw-r--r--gdb/trad-frame.h70
-rw-r--r--include/gdb/fileio.h146
-rw-r--r--sim/h8300/sim-main.h170
-rw-r--r--sim/ppc/altivec.igen2356
-rw-r--r--sim/ppc/altivec_expression.h50
-rw-r--r--sim/ppc/altivec_registers.h63
-rw-r--r--sim/ppc/e500.igen3348
-rw-r--r--sim/ppc/e500_expression.h173
-rw-r--r--sim/ppc/e500_registers.h83
33 files changed, 11639 insertions, 0 deletions
diff --git a/gdb/alpha-mdebug-tdep.c b/gdb/alpha-mdebug-tdep.c
new file mode 100644
index 0000000..9eb9c62
--- /dev/null
+++ b/gdb/alpha-mdebug-tdep.c
@@ -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)
+
+/* 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);
+}
+
+
+/* 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;
+}
+
+
+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
index 0000000..2d08bcb
--- /dev/null
+++ b/gdb/config/mips/mips.mt
@@ -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
index 0000000..e6a19d8
--- /dev/null
+++ b/gdb/config/mips/mips64.mt
@@ -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
index 0000000..5d1c7b6
--- /dev/null
+++ b/gdb/config/powerpc/nm-ppc64-linux.h
@@ -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
index 0000000..dd81586
--- /dev/null
+++ b/gdb/config/powerpc/ppc64-linux.mh
@@ -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
index 0000000..999cef7
--- /dev/null
+++ b/gdb/dwarf2-frame.c
@@ -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);
+
+
+/* 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);
+}
+
+
+/* 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;
+}
+
+
+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;
+}
+
+
+/* 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;
+}
+
+/* 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;
+}
+
+
+/* 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");
+ }
+}
+
+
+/* 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;
+}
+
+
+/* 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
index 0000000..4b4c1a5
--- /dev/null
+++ b/gdb/dwarf2-frame.h
@@ -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
index 0000000..61931c6
--- /dev/null
+++ b/gdb/linux-nat.c
@@ -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;
+
+
+/* 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);
+}
+
+
+/* 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;
+}
+
+
+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
index 0000000..b0d9600
--- /dev/null
+++ b/gdb/linux-nat.h
@@ -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
index 0000000..fd57617
--- /dev/null
+++ b/gdb/remote-fileio.c
@@ -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
index 0000000..68c6450
--- /dev/null
+++ b/gdb/remote-fileio.h
@@ -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
index 0000000..0891c94
--- /dev/null
+++ b/gdb/stack.h
@@ -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
index 0000000..f9741c4
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/alpha.inc
@@ -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
index 0000000..f584074
--- /dev/null
+++ b/gdb/testsuite/gdb.base/bang.exp
@@ -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
index 0000000..591b3b6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/fileio.c
@@ -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
index 0000000..279f1ab
--- /dev/null
+++ b/gdb/testsuite/gdb.base/fileio.exp
@@ -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
index 0000000..cc22f69
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gdb_history
@@ -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
index 0000000..6867362
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shreloc.c
@@ -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
index 0000000..ac48774
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shreloc.exp
@@ -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
index 0000000..b1bffde
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shreloc1.c
@@ -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
index 0000000..1459093
--- /dev/null
+++ b/gdb/testsuite/gdb.base/shreloc2.c
@@ -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
index 0000000..5747e5d
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/pr-1210.cc
@@ -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
index 0000000..3ff850d
--- /dev/null
+++ b/gdb/testsuite/gdb.c++/pr-1210.exp
@@ -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
index 0000000..92e6f83
--- /dev/null
+++ b/gdb/trad-frame.c
@@ -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
index 0000000..2b04c7e
--- /dev/null
+++ b/gdb/trad-frame.h
@@ -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
index 0000000..d844781
--- /dev/null
+++ b/include/gdb/fileio.h
@@ -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
index 0000000..6acf901
--- /dev/null
+++ b/sim/h8300/sim-main.h
@@ -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
index 0000000..9f10b26
--- /dev/null
+++ b/sim/ppc/altivec.igen
@@ -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
index 0000000..6cf2e76
--- /dev/null
+++ b/sim/ppc/altivec_expression.h
@@ -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
index 0000000..923f5c4
--- /dev/null
+++ b/sim/ppc/altivec_registers.h
@@ -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
index 0000000..f4ebfc7
--- /dev/null
+++ b/sim/ppc/e500.igen
@@ -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)));
+
+#
+# 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;
+ }
+
+#
+# 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;
+
+
+#
+# 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
index 0000000..c634a1c
--- /dev/null
+++ b/sim/ppc/e500_expression.h
@@ -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
index 0000000..cd12ab5
--- /dev/null
+++ b/sim/ppc/e500_registers.h
@@ -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))