Browse Source

HPPA (PA-RISC) host support

(Stuart Brady)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4199 c046a42c-6fe2-441c-8c8c-71466251a162
aurel32 17 years ago
parent
commit
f54b3f920f
17 changed files with 4505 additions and 13 deletions
  1. 8 0
      Makefile.target
  2. 7 0
      configure
  3. 10 1
      cpu-all.h
  4. 29 0
      cpu-exec.c
  5. 4 0
      dis-asm.h
  6. 2 0
      disas.c
  7. 7 0
      dyngen-exec.h
  8. 127 2
      dyngen.c
  9. 2834 0
      hppa-dis.c
  10. 214 0
      hppa.ld
  11. 980 0
      tcg/hppa/tcg-target.c
  12. 204 0
      tcg/hppa/tcg-target.h
  13. 2 1
      tcg/i386/tcg-target.c
  14. 2 1
      tcg/sparc/tcg-target.c
  15. 50 0
      tcg/tcg-dyngen.c
  16. 23 7
      tcg/tcg.c
  17. 2 1
      tcg/x86_64/tcg-target.c

+ 8 - 0
Makefile.target

@@ -128,6 +128,11 @@ ifeq ($(ARCH),alpha)
 CFLAGS+=-msmall-data
 CFLAGS+=-msmall-data
 endif
 endif
 
 
+ifeq ($(ARCH),hppa)
+OP_CFLAGS=-O1 -fno-delayed-branch
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+endif
+
 ifeq ($(ARCH),ia64)
 ifeq ($(ARCH),ia64)
 CFLAGS+=-mno-sdata
 CFLAGS+=-mno-sdata
 OP_CFLAGS+=-mno-sdata
 OP_CFLAGS+=-mno-sdata
@@ -267,6 +272,9 @@ endif
 ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
 ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
 LIBOBJS+=sh4-dis.o
 LIBOBJS+=sh4-dis.o
 endif
 endif
+ifeq ($(findstring hppa, $(TARGET_BASE_ARCH) $(ARCH)),hppa)
+LIBOBJS+=hppa-dis.o
+endif
 ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390)
 ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390)
 LIBOBJS+=s390-dis.o
 LIBOBJS+=s390-dis.o
 endif
 endif

+ 7 - 0
configure

@@ -50,6 +50,9 @@ case "$cpu" in
   cris)
   cris)
     cpu="cris"
     cpu="cris"
   ;;
   ;;
+  parisc|parisc64)
+    cpu="hppa"
+  ;;
   ia64)
   ia64)
     cpu="ia64"
     cpu="ia64"
   ;;
   ;;
@@ -576,6 +579,7 @@ else
 
 
 # if cross compiling, cannot launch a program, so make a static guess
 # if cross compiling, cannot launch a program, so make a static guess
 if test "$cpu" = "armv4b" \
 if test "$cpu" = "armv4b" \
+     -o "$cpu" = "hppa" \
      -o "$cpu" = "m68k" \
      -o "$cpu" = "m68k" \
      -o "$cpu" = "mips" \
      -o "$cpu" = "mips" \
      -o "$cpu" = "mips64" \
      -o "$cpu" = "mips64" \
@@ -865,6 +869,9 @@ elif test "$cpu" = "armv4l" ; then
 elif test "$cpu" = "cris" ; then
 elif test "$cpu" = "cris" ; then
   echo "ARCH=cris" >> $config_mak
   echo "ARCH=cris" >> $config_mak
   echo "#define HOST_CRIS 1" >> $config_h
   echo "#define HOST_CRIS 1" >> $config_h
+elif test "$cpu" = "hppa" ; then
+  echo "ARCH=hppa" >> $config_mak
+  echo "#define HOST_HPPA 1" >> $config_h
 elif test "$cpu" = "ia64" ; then
 elif test "$cpu" = "ia64" ; then
   echo "ARCH=ia64" >> $config_mak
   echo "ARCH=ia64" >> $config_mak
   echo "#define HOST_IA64 1" >> $config_h
   echo "#define HOST_IA64 1" >> $config_h

+ 10 - 1
cpu-all.h

@@ -20,7 +20,7 @@
 #ifndef CPU_ALL_H
 #ifndef CPU_ALL_H
 #define CPU_ALL_H
 #define CPU_ALL_H
 
 
-#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
 #define WORDS_ALIGNED
 #define WORDS_ALIGNED
 #endif
 #endif
 
 
@@ -952,6 +952,15 @@ static inline int64_t cpu_get_real_ticks(void)
     return val;
     return val;
 }
 }
 
 
+#elif defined(__hppa__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    int val;
+    asm volatile ("mfctl %%cr16, %0" : "=r"(val));
+    return val;
+}
+
 #elif defined(__ia64)
 #elif defined(__ia64)
 
 
 static inline int64_t cpu_get_real_ticks(void)
 static inline int64_t cpu_get_real_ticks(void)

+ 29 - 0
cpu-exec.c

@@ -657,6 +657,17 @@ int cpu_exec(CPUState *env1)
                                        "o0", "o1", "o2", "o3", "o4", "o5",
                                        "o0", "o1", "o2", "o3", "o4", "o5",
                                        "l0", "l1", "l2", "l3", "l4", "l5",
                                        "l0", "l1", "l2", "l3", "l4", "l5",
                                        "l6", "l7");
                                        "l6", "l7");
+#elif defined(__hppa__)
+                asm volatile ("ble  0(%%sr4,%1)\n"
+                              "copy %%r31,%%r18\n"
+                              "copy %%r28,%0\n"
+                              : "=r" (T0)
+                              : "r" (gen_func)
+                              : "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+                                "r8", "r9", "r10", "r11", "r12", "r13",
+                                "r18", "r19", "r20", "r21", "r22", "r23",
+                                "r24", "r25", "r26", "r27", "r28", "r29",
+                                "r30", "r31");
 #elif defined(__arm__)
 #elif defined(__arm__)
                 asm volatile ("mov pc, %0\n\t"
                 asm volatile ("mov pc, %0\n\t"
                               ".global exec_loop\n\t"
                               ".global exec_loop\n\t"
@@ -1488,6 +1499,24 @@ int cpu_signal_handler(int host_signum, void *pinfo,
                              is_write, &uc->uc_sigmask, puc);
                              is_write, &uc->uc_sigmask, puc);
 }
 }
 
 
+#elif defined(__hppa__)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+                       void *puc)
+{
+    struct siginfo *info = pinfo;
+    struct ucontext *uc = puc;
+    unsigned long pc;
+    int is_write;
+
+    pc = uc->uc_mcontext.sc_iaoq[0];
+    /* FIXME: compute is_write */
+    is_write = 0;
+    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
+                             is_write,
+                             &uc->uc_sigmask, puc);
+}
+
 #else
 #else
 
 
 #error host CPU specific signal handler needed
 #error host CPU specific signal handler needed

+ 4 - 0
dis-asm.h

@@ -157,6 +157,10 @@ enum bfd_architecture
 #define bfd_mach_ppc_7400      7400
 #define bfd_mach_ppc_7400      7400
   bfd_arch_rs6000,     /* IBM RS/6000 */
   bfd_arch_rs6000,     /* IBM RS/6000 */
   bfd_arch_hppa,       /* HP PA RISC */
   bfd_arch_hppa,       /* HP PA RISC */
+#define bfd_mach_hppa10        10
+#define bfd_mach_hppa11        11
+#define bfd_mach_hppa20        20
+#define bfd_mach_hppa20w       25
   bfd_arch_d10v,       /* Mitsubishi D10V */
   bfd_arch_d10v,       /* Mitsubishi D10V */
   bfd_arch_z8k,        /* Zilog Z8000 */
   bfd_arch_z8k,        /* Zilog Z8000 */
 #define bfd_mach_z8001         1
 #define bfd_mach_z8001         1

+ 2 - 0
disas.c

@@ -279,6 +279,8 @@ void disas(FILE *out, void *code, unsigned long size)
     print_insn = print_insn_m68k;
     print_insn = print_insn_m68k;
 #elif defined(__s390__)
 #elif defined(__s390__)
     print_insn = print_insn_s390;
     print_insn = print_insn_s390;
+#elif defined(__hppa__)
+    print_insn = print_insn_hppa;
 #else
 #else
     fprintf(out, "0x%lx: Asm output not supported on this arch\n",
     fprintf(out, "0x%lx: Asm output not supported on this arch\n",
 	    (long) code);
 	    (long) code);

+ 7 - 0
dyngen-exec.h

@@ -124,6 +124,11 @@ extern int printf(const char *, ...);
 #define AREG1 "r4"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG2 "r5"
 #define AREG3 "r6"
 #define AREG3 "r6"
+#elif defined(__hppa__)
+#define AREG0 "r17"
+#define AREG1 "r14"
+#define AREG2 "r15"
+#define AREG3 "r16"
 #elif defined(__mips__)
 #elif defined(__mips__)
 #define AREG0 "fp"
 #define AREG0 "fp"
 #define AREG1 "s0"
 #define AREG1 "s0"
@@ -279,6 +284,8 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
 #elif defined(__mips__)
 #elif defined(__mips__)
 #define EXIT_TB() asm volatile ("jr $ra")
 #define EXIT_TB() asm volatile ("jr $ra")
 #define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
 #define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
+#elif defined(__hppa__)
+#define GOTO_LABEL_PARAM(n) asm volatile ("b,n " ASM_NAME(__op_gen_label) #n)
 #else
 #else
 #error unsupported CPU
 #error unsupported CPU
 #endif
 #endif

+ 127 - 2
dyngen.c

@@ -117,6 +117,13 @@
 #define elf_check_arch(x) ((x) == EM_68K)
 #define elf_check_arch(x) ((x) == EM_68K)
 #define ELF_USES_RELOCA
 #define ELF_USES_RELOCA
 
 
+#elif defined(HOST_HPPA)
+
+#define ELF_CLASS   ELFCLASS32
+#define ELF_ARCH    EM_PARISC
+#define elf_check_arch(x) ((x) == EM_PARISC)
+#define ELF_USES_RELOCA
+
 #elif defined(HOST_MIPS)
 #elif defined(HOST_MIPS)
 
 
 #define ELF_CLASS	ELFCLASS32
 #define ELF_CLASS	ELFCLASS32
@@ -1223,7 +1230,7 @@ int get_reloc_expr(char *name, int name_size, const char *sym_name)
         snprintf(name, name_size, "param%s", p);
         snprintf(name, name_size, "param%s", p);
         return 1;
         return 1;
     } else {
     } else {
-#ifdef HOST_SPARC
+#if defined(HOST_SPARC) || defined(HOST_HPPA)
         if (sym_name[0] == '.')
         if (sym_name[0] == '.')
             snprintf(name, name_size,
             snprintf(name, name_size,
                      "(long)(&__dot_%s)",
                      "(long)(&__dot_%s)",
@@ -1661,6 +1668,43 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
             error("rts expected at the end of %s", name);
             error("rts expected at the end of %s", name);
         copy_size = p - p_start;
         copy_size = p - p_start;
     }
     }
+#elif defined(HOST_HPPA)
+    {
+        uint8_t *p;
+        p = p_start;
+        while (p < p_end) {
+            uint32_t insn = get32((uint32_t *)p);
+            if (insn == 0x6bc23fd9 ||                /* stw rp,-14(sp) */
+                insn == 0x08030241 ||                /* copy r3,r1 */
+                insn == 0x081e0243 ||                /* copy sp,r3 */
+                (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
+                (insn & 0xffffc000) == 0x6fc10000)   /* stwm r1,x(sp) */
+                p += 4;
+            else
+                break;
+        }
+        start_offset += p - p_start;
+        p_start = p;
+        p = p_end - 4;
+
+        while (p > p_start) {
+            uint32_t insn = get32((uint32_t *)p);
+            if ((insn & 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */
+                (insn & 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */
+                (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
+                insn == 0x48623fd9 ||                /* ldw -14(r3),rp */
+                insn == 0xe840c000 ||                /* bv r0(rp) */
+                insn == 0xe840c002)                  /* bv,n r0(rp) */
+                p -= 4;
+            else
+                break;
+        }
+        p += 4;
+        if (p <= p_start)
+            error("empty code for %s", name);
+
+        copy_size = p - p_start;
+    }
 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
     {
     {
 #define INSN_RETURN     0x03e00008
 #define INSN_RETURN     0x03e00008
@@ -1746,7 +1790,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
                     !strstart(sym_name, "__op_param", NULL) &&
                     !strstart(sym_name, "__op_param", NULL) &&
                     !strstart(sym_name, "__op_jmp", NULL) &&
                     !strstart(sym_name, "__op_jmp", NULL) &&
                     !strstart(sym_name, "__op_gen_label", NULL)) {
                     !strstart(sym_name, "__op_gen_label", NULL)) {
-#if defined(HOST_SPARC)
+#if defined(HOST_SPARC) || defined(HOST_HPPA)
 		    if (sym_name[0] == '.') {
 		    if (sym_name[0] == '.') {
 			fprintf(outfile,
 			fprintf(outfile,
 				"extern char __dot_%s __asm__(\"%s\");\n",
 				"extern char __dot_%s __asm__(\"%s\");\n",
@@ -1774,8 +1818,13 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
             }
             }
         }
         }
 
 
+#ifdef __hppa__
+        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
+					name, (int)(start_offset - offset), copy_size);
+#else
         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
 					name, (int)(start_offset - offset), copy_size);
 					name, (int)(start_offset - offset), copy_size);
+#endif
 
 
         /* emit code offset information */
         /* emit code offset information */
         {
         {
@@ -2581,6 +2630,82 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
                 }
                 }
                 }
                 }
             }
             }
+#elif defined(HOST_HPPA)
+            {
+                char relname[256];
+                int type, is_label;
+                int addend;
+                int reloc_offset;
+                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
+                if (rel->r_offset >= start_offset &&
+                    rel->r_offset < start_offset + copy_size) {
+                    sym_name = get_rel_sym_name(rel);
+                    sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
+                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
+                    type = ELF32_R_TYPE(rel->r_info);
+                    addend = rel->r_addend;
+                    reloc_offset = rel->r_offset - start_offset;
+
+                    if (is_label) {
+                        switch (type) {
+                        case R_PARISC_PCREL17F:
+                            fprintf(outfile,
+"    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
+                                    reloc_offset, type, relname, addend);
+                            break;
+                        default:
+                            error("unsupported hppa label relocation (%d)", type);
+                        }
+                    } else {
+                        switch (type) {
+                        case R_PARISC_DIR21L:
+                            fprintf(outfile,
+"    hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
+                                    reloc_offset, relname, addend);
+                            break;
+                        case R_PARISC_DIR14R:
+                            fprintf(outfile,
+"    hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
+                                    reloc_offset, relname, addend);
+                            break;
+                        case R_PARISC_PCREL17F:
+                            if (strstart(sym_name, "__op_gen_label", NULL)) {
+                                fprintf(outfile,
+"    hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
+                                        reloc_offset, relname, addend);
+                            } else {
+                                fprintf(outfile,
+"    HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
+                                        reloc_offset, relname);
+                            }
+                            break;
+                        case R_PARISC_DPREL21L:
+                            if (strstart(sym_name, "__op_param", &p))
+                                fprintf(outfile,
+"    hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
+                                        reloc_offset, p, addend);
+                            else
+                                fprintf(outfile,
+"    hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
+                                        reloc_offset, relname, addend);
+                            break;
+                        case R_PARISC_DPREL14R:
+                            if (strstart(sym_name, "__op_param", &p))
+                                fprintf(outfile,
+"    hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
+                                        reloc_offset, p, addend);
+                            else
+                                fprintf(outfile,
+"    hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
+                                        reloc_offset, relname, addend);
+                            break;
+                        default:
+                            error("unsupported hppa relocation (%d)", type);
+                        }
+                    }
+                }
+                }
+            }
 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
             {
             {
                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {

+ 2834 - 0
hppa-dis.c

@@ -0,0 +1,2834 @@
+/* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
+   Copyright 1989, 1990, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2003,
+   2005 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "dis-asm.h"
+
+/* HP PA-RISC SOM object file format:  definitions internal to BFD.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+   2003 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _LIBHPPA_H
+#define _LIBHPPA_H
+
+#define BYTES_IN_WORD 4
+#define PA_PAGESIZE 0x1000
+
+/* The PA instruction set variants.  */
+enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
+
+/* HP PA-RISC relocation types */
+
+enum hppa_reloc_field_selector_type
+  {
+    R_HPPA_FSEL = 0x0,
+    R_HPPA_LSSEL = 0x1,
+    R_HPPA_RSSEL = 0x2,
+    R_HPPA_LSEL = 0x3,
+    R_HPPA_RSEL = 0x4,
+    R_HPPA_LDSEL = 0x5,
+    R_HPPA_RDSEL = 0x6,
+    R_HPPA_LRSEL = 0x7,
+    R_HPPA_RRSEL = 0x8,
+    R_HPPA_NSEL  = 0x9,
+    R_HPPA_NLSEL  = 0xa,
+    R_HPPA_NLRSEL  = 0xb,
+    R_HPPA_PSEL = 0xc,
+    R_HPPA_LPSEL = 0xd,
+    R_HPPA_RPSEL = 0xe,
+    R_HPPA_TSEL = 0xf,
+    R_HPPA_LTSEL = 0x10,
+    R_HPPA_RTSEL = 0x11,
+    R_HPPA_LTPSEL = 0x12,
+    R_HPPA_RTPSEL = 0x13
+  };
+
+/* /usr/include/reloc.h defines these to constants.  We want to use
+   them in enums, so #undef them before we start using them.  We might
+   be able to fix this another way by simply managing not to include
+   /usr/include/reloc.h, but currently GDB picks up these defines
+   somewhere.  */
+#undef e_fsel
+#undef e_lssel
+#undef e_rssel
+#undef e_lsel
+#undef e_rsel
+#undef e_ldsel
+#undef e_rdsel
+#undef e_lrsel
+#undef e_rrsel
+#undef e_nsel
+#undef e_nlsel
+#undef e_nlrsel
+#undef e_psel
+#undef e_lpsel
+#undef e_rpsel
+#undef e_tsel
+#undef e_ltsel
+#undef e_rtsel
+#undef e_one
+#undef e_two
+#undef e_pcrel
+#undef e_con
+#undef e_plabel
+#undef e_abs
+
+/* for compatibility */
+enum hppa_reloc_field_selector_type_alt
+  {
+    e_fsel = R_HPPA_FSEL,
+    e_lssel = R_HPPA_LSSEL,
+    e_rssel = R_HPPA_RSSEL,
+    e_lsel = R_HPPA_LSEL,
+    e_rsel = R_HPPA_RSEL,
+    e_ldsel = R_HPPA_LDSEL,
+    e_rdsel = R_HPPA_RDSEL,
+    e_lrsel = R_HPPA_LRSEL,
+    e_rrsel = R_HPPA_RRSEL,
+    e_nsel = R_HPPA_NSEL,
+    e_nlsel = R_HPPA_NLSEL,
+    e_nlrsel = R_HPPA_NLRSEL,
+    e_psel = R_HPPA_PSEL,
+    e_lpsel = R_HPPA_LPSEL,
+    e_rpsel = R_HPPA_RPSEL,
+    e_tsel = R_HPPA_TSEL,
+    e_ltsel = R_HPPA_LTSEL,
+    e_rtsel = R_HPPA_RTSEL,
+    e_ltpsel = R_HPPA_LTPSEL,
+    e_rtpsel = R_HPPA_RTPSEL
+  };
+
+enum hppa_reloc_expr_type
+  {
+    R_HPPA_E_ONE = 0,
+    R_HPPA_E_TWO = 1,
+    R_HPPA_E_PCREL = 2,
+    R_HPPA_E_CON = 3,
+    R_HPPA_E_PLABEL = 7,
+    R_HPPA_E_ABS = 18
+  };
+
+/* for compatibility */
+enum hppa_reloc_expr_type_alt
+  {
+    e_one = R_HPPA_E_ONE,
+    e_two = R_HPPA_E_TWO,
+    e_pcrel = R_HPPA_E_PCREL,
+    e_con = R_HPPA_E_CON,
+    e_plabel = R_HPPA_E_PLABEL,
+    e_abs = R_HPPA_E_ABS
+  };
+
+
+/* Relocations for function calls must be accompanied by parameter
+   relocation bits.  These bits describe exactly where the caller has
+   placed the function's arguments and where it expects to find a return
+   value.
+
+   Both ELF and SOM encode this information within the addend field
+   of the call relocation.  (Note this could break very badly if one
+   was to make a call like bl foo + 0x12345678).
+
+   The high order 10 bits contain parameter relocation information,
+   the low order 22 bits contain the constant offset.  */
+
+#define HPPA_R_ARG_RELOC(a)	\
+  (((a) >> 22) & 0x3ff)
+#define HPPA_R_CONSTANT(a)	\
+  ((((bfd_signed_vma)(a)) << (BFD_ARCH_SIZE-22)) >> (BFD_ARCH_SIZE-22))
+#define HPPA_R_ADDEND(r, c)	\
+  (((r) << 22) + ((c) & 0x3fffff))
+
+
+/* Some functions to manipulate PA instructions.  */
+
+/* Declare the functions with the unused attribute to avoid warnings.  */
+static inline int sign_extend (int, int) ATTRIBUTE_UNUSED;
+static inline int low_sign_extend (int, int) ATTRIBUTE_UNUSED;
+static inline int sign_unext (int, int) ATTRIBUTE_UNUSED;
+static inline int low_sign_unext (int, int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_3 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_12 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_14 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_16 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_17 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_21 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_22 (int) ATTRIBUTE_UNUSED;
+static inline bfd_signed_vma hppa_field_adjust
+  (bfd_vma, bfd_signed_vma, enum hppa_reloc_field_selector_type_alt)
+  ATTRIBUTE_UNUSED;
+static inline int hppa_rebuild_insn (int, int, int) ATTRIBUTE_UNUSED;
+
+
+/* The *sign_extend functions are used to assemble various bitfields
+   taken from an instruction and return the resulting immediate
+   value.  */
+
+static inline int
+sign_extend (int x, int len)
+{
+  int signbit = (1 << (len - 1));
+  int mask = (signbit << 1) - 1;
+  return ((x & mask) ^ signbit) - signbit;
+}
+
+static inline int
+low_sign_extend (int x, int len)
+{
+  return (x >> 1) - ((x & 1) << (len - 1));
+}
+
+
+/* The re_assemble_* functions prepare an immediate value for
+   insertion into an opcode. pa-risc uses all sorts of weird bitfields
+   in the instruction to hold the value.  */
+
+static inline int
+sign_unext (int x, int len)
+{
+  int len_ones;
+
+  len_ones = (1 << len) - 1;
+
+  return x & len_ones;
+}
+
+static inline int
+low_sign_unext (int x, int len)
+{
+  int temp;
+  int sign;
+
+  sign = (x >> (len-1)) & 1;
+
+  temp = sign_unext (x, len-1);
+
+  return (temp << 1) | sign;
+}
+
+static inline int
+re_assemble_3 (int as3)
+{
+  return ((  (as3 & 4) << (13-2))
+	  | ((as3 & 3) << (13+1)));
+}
+
+static inline int
+re_assemble_12 (int as12)
+{
+  return ((  (as12 & 0x800) >> 11)
+	  | ((as12 & 0x400) >> (10 - 2))
+	  | ((as12 & 0x3ff) << (1 + 2)));
+}
+
+static inline int
+re_assemble_14 (int as14)
+{
+  return ((  (as14 & 0x1fff) << 1)
+	  | ((as14 & 0x2000) >> 13));
+}
+
+static inline int
+re_assemble_16 (int as16)
+{
+  int s, t;
+
+  /* Unusual 16-bit encoding, for wide mode only.  */
+  t = (as16 << 1) & 0xffff;
+  s = (as16 & 0x8000);
+  return (t ^ s ^ (s >> 1)) | (s >> 15);
+}
+
+static inline int
+re_assemble_17 (int as17)
+{
+  return ((  (as17 & 0x10000) >> 16)
+	  | ((as17 & 0x0f800) << (16 - 11))
+	  | ((as17 & 0x00400) >> (10 - 2))
+	  | ((as17 & 0x003ff) << (1 + 2)));
+}
+
+static inline int
+re_assemble_21 (int as21)
+{
+  return ((  (as21 & 0x100000) >> 20)
+	  | ((as21 & 0x0ffe00) >> 8)
+	  | ((as21 & 0x000180) << 7)
+	  | ((as21 & 0x00007c) << 14)
+	  | ((as21 & 0x000003) << 12));
+}
+
+static inline int
+re_assemble_22 (int as22)
+{
+  return ((  (as22 & 0x200000) >> 21)
+	  | ((as22 & 0x1f0000) << (21 - 16))
+	  | ((as22 & 0x00f800) << (16 - 11))
+	  | ((as22 & 0x000400) >> (10 - 2))
+	  | ((as22 & 0x0003ff) << (1 + 2)));
+}
+
+
+/* Handle field selectors for PA instructions.
+   The L and R (and LS, RS etc.) selectors are used in pairs to form a
+   full 32 bit address.  eg.
+
+   LDIL	L'start,%r1		; put left part into r1
+   LDW	R'start(%r1),%r2	; add r1 and right part to form address
+
+   This function returns sign extended values in all cases.
+*/
+
+static inline bfd_signed_vma
+hppa_field_adjust (bfd_vma sym_val,
+		   bfd_signed_vma addend,
+		   enum hppa_reloc_field_selector_type_alt r_field)
+{
+  bfd_signed_vma value;
+
+  value = sym_val + addend;
+  switch (r_field)
+    {
+    case e_fsel:
+      /* F: No change.  */
+      break;
+
+    case e_nsel:
+      /* N: null selector.  I don't really understand what this is all
+	 about, but HP's documentation says "this indicates that zero
+	 bits are to be used for the displacement on the instruction.
+	 This fixup is used to identify three-instruction sequences to
+	 access data (for importing shared library data)."  */
+      value = 0;
+      break;
+
+    case e_lsel:
+    case e_nlsel:
+      /* L:  Select top 21 bits.  */
+      value = value >> 11;
+      break;
+
+    case e_rsel:
+      /* R:  Select bottom 11 bits.  */
+      value = value & 0x7ff;
+      break;
+
+    case e_lssel:
+      /* LS:  Round to nearest multiple of 2048 then select top 21 bits.  */
+      value = value + 0x400;
+      value = value >> 11;
+      break;
+
+    case e_rssel:
+      /* RS:  Select bottom 11 bits for LS.
+	 We need to return a value such that 2048 * LS'x + RS'x == x.
+	 ie. RS'x = x - ((x + 0x400) & -0x800)
+	 this is just a sign extension from bit 21.  */
+      value = ((value & 0x7ff) ^ 0x400) - 0x400;
+      break;
+
+    case e_ldsel:
+      /* LD:  Round to next multiple of 2048 then select top 21 bits.
+	 Yes, if we are already on a multiple of 2048, we go up to the
+	 next one.  RD in this case will be -2048.  */
+      value = value + 0x800;
+      value = value >> 11;
+      break;
+
+    case e_rdsel:
+      /* RD:  Set bits 0-20 to one.  */
+      value = value | -0x800;
+      break;
+
+    case e_lrsel:
+    case e_nlrsel:
+      /* LR:  L with rounding of the addend to nearest 8k.  */
+      value = sym_val + ((addend + 0x1000) & -0x2000);
+      value = value >> 11;
+      break;
+
+    case e_rrsel:
+      /* RR:  R with rounding of the addend to nearest 8k.
+	 We need to return a value such that 2048 * LR'x + RR'x == x
+	 ie. RR'x = s+a - (s + (((a + 0x1000) & -0x2000) & -0x800))
+	 .	  = s+a - ((s & -0x800) + ((a + 0x1000) & -0x2000))
+	 .	  = (s & 0x7ff) + a - ((a + 0x1000) & -0x2000)  */
+      value = (sym_val & 0x7ff) + (((addend & 0x1fff) ^ 0x1000) - 0x1000);
+      break;
+
+    default:
+      abort ();
+    }
+  return value;
+}
+
+/* PA-RISC OPCODES */
+#define get_opcode(insn)	(((insn) >> 26) & 0x3f)
+
+enum hppa_opcode_type
+{
+  /* None of the opcodes in the first group generate relocs, so we
+     aren't too concerned about them.  */
+  OP_SYSOP   = 0x00,
+  OP_MEMMNG  = 0x01,
+  OP_ALU     = 0x02,
+  OP_NDXMEM  = 0x03,
+  OP_SPOP    = 0x04,
+  OP_DIAG    = 0x05,
+  OP_FMPYADD = 0x06,
+  OP_UNDEF07 = 0x07,
+  OP_COPRW   = 0x09,
+  OP_COPRDW  = 0x0b,
+  OP_COPR    = 0x0c,
+  OP_FLOAT   = 0x0e,
+  OP_PRDSPEC = 0x0f,
+  OP_UNDEF15 = 0x15,
+  OP_UNDEF1d = 0x1d,
+  OP_FMPYSUB = 0x26,
+  OP_FPFUSED = 0x2e,
+  OP_SHEXDP0 = 0x34,
+  OP_SHEXDP1 = 0x35,
+  OP_SHEXDP2 = 0x36,
+  OP_UNDEF37 = 0x37,
+  OP_SHEXDP3 = 0x3c,
+  OP_SHEXDP4 = 0x3d,
+  OP_MULTMED = 0x3e,
+  OP_UNDEF3f = 0x3f,
+
+  OP_LDIL    = 0x08,
+  OP_ADDIL   = 0x0a,
+
+  OP_LDO     = 0x0d,
+  OP_LDB     = 0x10,
+  OP_LDH     = 0x11,
+  OP_LDW     = 0x12,
+  OP_LDWM    = 0x13,
+  OP_STB     = 0x18,
+  OP_STH     = 0x19,
+  OP_STW     = 0x1a,
+  OP_STWM    = 0x1b,
+
+  OP_LDD     = 0x14,
+  OP_STD     = 0x1c,
+
+  OP_FLDW    = 0x16,
+  OP_LDWL    = 0x17,
+  OP_FSTW    = 0x1e,
+  OP_STWL    = 0x1f,
+
+  OP_COMBT   = 0x20,
+  OP_COMIBT  = 0x21,
+  OP_COMBF   = 0x22,
+  OP_COMIBF  = 0x23,
+  OP_CMPBDT  = 0x27,
+  OP_ADDBT   = 0x28,
+  OP_ADDIBT  = 0x29,
+  OP_ADDBF   = 0x2a,
+  OP_ADDIBF  = 0x2b,
+  OP_CMPBDF  = 0x2f,
+  OP_BVB     = 0x30,
+  OP_BB      = 0x31,
+  OP_MOVB    = 0x32,
+  OP_MOVIB   = 0x33,
+  OP_CMPIBD  = 0x3b,
+
+  OP_COMICLR = 0x24,
+  OP_SUBI    = 0x25,
+  OP_ADDIT   = 0x2c,
+  OP_ADDI    = 0x2d,
+
+  OP_BE      = 0x38,
+  OP_BLE     = 0x39,
+  OP_BL      = 0x3a
+};
+
+
+/* Insert VALUE into INSN using R_FORMAT to determine exactly what
+   bits to change.  */
+
+static inline int
+hppa_rebuild_insn (int insn, int value, int r_format)
+{
+  switch (r_format)
+    {
+    case 11:
+      return (insn & ~ 0x7ff) | low_sign_unext (value, 11);
+
+    case 12:
+      return (insn & ~ 0x1ffd) | re_assemble_12 (value);
+
+
+    case 10:
+      return (insn & ~ 0x3ff1) | re_assemble_14 (value & -8);
+
+    case -11:
+      return (insn & ~ 0x3ff9) | re_assemble_14 (value & -4);
+
+    case 14:
+      return (insn & ~ 0x3fff) | re_assemble_14 (value);
+
+
+    case -10:
+      return (insn & ~ 0xfff1) | re_assemble_16 (value & -8);
+
+    case -16:
+      return (insn & ~ 0xfff9) | re_assemble_16 (value & -4);
+
+    case 16:
+      return (insn & ~ 0xffff) | re_assemble_16 (value);
+
+
+    case 17:
+      return (insn & ~ 0x1f1ffd) | re_assemble_17 (value);
+
+    case 21:
+      return (insn & ~ 0x1fffff) | re_assemble_21 (value);
+
+    case 22:
+      return (insn & ~ 0x3ff1ffd) | re_assemble_22 (value);
+
+    case 32:
+      return value;
+
+    default:
+      abort ();
+    }
+  return insn;
+}
+
+#endif /* _LIBHPPA_H */
+/* Table of opcodes for the PA-RISC.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+   2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB 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 1, or (at your option)
+any later version.
+
+GAS/GDB 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 GAS or GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+
+/* There are two kinds of delay slot nullification: normal which is
+ * controled by the nullification bit, and conditional, which depends
+ * on the direction of the branch and its success or failure.
+ *
+ * NONE is unfortunately #defined in the hiux system include files.
+ * #undef it away.
+ */
+#undef NONE
+struct pa_opcode
+{
+    const char *name;
+    unsigned long int match;	/* Bits that must be set...  */
+    unsigned long int mask;	/* ... in these bits. */
+    char *args;
+    enum pa_arch arch;
+    char flags;
+};
+
+/* Enables strict matching.  Opcodes with match errors are skipped
+   when this bit is set.  */
+#define FLAG_STRICT 0x1
+
+/*
+   All hppa opcodes are 32 bits.
+
+   The match component is a mask saying which bits must match a
+   particular opcode in order for an instruction to be an instance
+   of that opcode.
+
+   The args component is a string containing one character for each operand of
+   the instruction.  Characters used as a prefix allow any second character to
+   be used without conflicting with the main operand characters.
+
+   Bit positions in this description follow HP usage of lsb = 31,
+   "at" is lsb of field.
+
+   In the args field, the following characters must match exactly:
+
+	'+,() '
+
+   In the args field, the following characters are unused:
+
+	'  "         -  /   34 6789:;    '
+	'@  C         M             [\]  '
+	'`    e g                     }  '
+
+   Here are all the characters:
+
+	' !"#$%&'()*+-,./0123456789:;<=>?'
+	'@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'
+	'`abcdefghijklmnopqrstuvwxyz{|}~ '
+
+Kinds of operands:
+   x    integer register field at 15.
+   b    integer register field at 10.
+   t    integer register field at 31.
+   a	integer register field at 10 and 15 (for PERMH)
+   5    5 bit immediate at 15.
+   s    2 bit space specifier at 17.
+   S    3 bit space specifier at 18.
+   V    5 bit immediate value at 31
+   i    11 bit immediate value at 31
+   j    14 bit immediate value at 31
+   k    21 bit immediate value at 31
+   l    16 bit immediate value at 31 (wide mode only, unusual encoding).
+   n	nullification for branch instructions
+   N	nullification for spop and copr instructions
+   w    12 bit branch displacement
+   W    17 bit branch displacement (PC relative)
+   X    22 bit branch displacement (PC relative)
+   z    17 bit branch displacement (just a number, not an address)
+
+Also these:
+
+   .    2 bit shift amount at 25
+   *    4 bit shift amount at 25
+   p    5 bit shift count at 26 (to support the SHD instruction) encoded as
+        31-p
+   ~    6 bit shift count at 20,22:26 encoded as 63-~.
+   P    5 bit bit position at 26
+   q    6 bit bit position at 20,22:26
+   T    5 bit field length at 31 (encoded as 32-T)
+   %	6 bit field length at 23,27:31 (variable extract/deposit)
+   |	6 bit field length at 19,27:31 (fixed extract/deposit)
+   A    13 bit immediate at 18 (to support the BREAK instruction)
+   ^	like b, but describes a control register
+   !    sar (cr11) register
+   D    26 bit immediate at 31 (to support the DIAG instruction)
+   $    9 bit immediate at 28 (to support POPBTS)
+
+   v    3 bit Special Function Unit identifier at 25
+   O    20 bit Special Function Unit operation split between 15 bits at 20
+        and 5 bits at 31
+   o    15 bit Special Function Unit operation at 20
+   2    22 bit Special Function Unit operation split between 17 bits at 20
+        and 5 bits at 31
+   1    15 bit Special Function Unit operation split between 10 bits at 20
+        and 5 bits at 31
+   0    10 bit Special Function Unit operation split between 5 bits at 20
+        and 5 bits at 31
+   u    3 bit coprocessor unit identifier at 25
+   F    Source Floating Point Operand Format Completer encoded 2 bits at 20
+   I    Source Floating Point Operand Format Completer encoded 1 bits at 20
+	(for 0xe format FP instructions)
+   G    Destination Floating Point Operand Format Completer encoded 2 bits at 18
+   H    Floating Point Operand Format at 26 for 'fmpyadd' and 'fmpysub'
+        (very similar to 'F')
+
+   r	5 bit immediate value at 31 (for the break instruction)
+	(very similar to V above, except the value is unsigned instead of
+	low_sign_ext)
+   R	5 bit immediate value at 15 (for the ssm, rsm, probei instructions)
+	(same as r above, except the value is in a different location)
+   U	10 bit immediate value at 15 (for SSM, RSM on pa2.0)
+   Q	5 bit immediate value at 10 (a bit position specified in
+	the bb instruction. It's the same as r above, except the
+        value is in a different location)
+   B	5 bit immediate value at 10 (a bit position specified in
+	the bb instruction. Similar to Q, but 64 bit handling is
+	different.
+   Z    %r1 -- implicit target of addil instruction.
+   L    ,%r2 completer for new syntax branch
+   {    Source format completer for fcnv
+   _    Destination format completer for fcnv
+   h    cbit for fcmp
+   =    gfx tests for ftest
+   d    14 bit offset for single precision FP long load/store.
+   #    14 bit offset for double precision FP load long/store.
+   J    Yet another 14 bit offset for load/store with ma,mb completers.
+   K    Yet another 14 bit offset for load/store with ma,mb completers.
+   y    16 bit offset for word aligned load/store (PA2.0 wide).
+   &    16 bit offset for dword aligned load/store (PA2.0 wide).
+   <    16 bit offset for load/store with ma,mb completers (PA2.0 wide).
+   >    16 bit offset for load/store with ma,mb completers (PA2.0 wide).
+   Y    %sr0,%r31 -- implicit target of be,l instruction.
+   @	implicit immediate value of 0
+
+Completer operands all have 'c' as the prefix:
+
+   cx   indexed load and store completer.
+   cX   indexed load and store completer.  Like cx, but emits a space
+	after in disassembler.
+   cm   short load and store completer.
+   cM   short load and store completer.  Like cm, but emits a space
+        after in disassembler.
+   cq   long load and store completer (like cm, but inserted into a
+	different location in the target instruction).
+   cs   store bytes short completer.
+   cA   store bytes short completer.  Like cs, but emits a space
+        after in disassembler.
+   ce   long load/store completer for LDW/STW with a different encoding
+	than the others
+   cc   load cache control hint
+   cd   load and clear cache control hint
+   cC   store cache control hint
+   co	ordered access
+
+   cp	branch link and push completer
+   cP	branch pop completer
+   cl	branch link completer
+   cg	branch gate completer
+
+   cw	read/write completer for PROBE
+   cW	wide completer for MFCTL
+   cL	local processor completer for cache control
+   cZ   System Control Completer (to support LPA, LHA, etc.)
+
+   ci	correction completer for DCOR
+   ca	add completer
+   cy	32 bit add carry completer
+   cY	64 bit add carry completer
+   cv	signed overflow trap completer
+   ct	trap on condition completer for ADDI, SUB
+   cT	trap on condition completer for UADDCM
+   cb	32 bit borrow completer for SUB
+   cB	64 bit borrow completer for SUB
+
+   ch	left/right half completer
+   cH	signed/unsigned saturation completer
+   cS	signed/unsigned completer at 21
+   cz	zero/sign extension completer.
+   c*	permutation completer
+
+Condition operands all have '?' as the prefix:
+
+   ?f   Floating point compare conditions (encoded as 5 bits at 31)
+
+   ?a	add conditions
+   ?A	64 bit add conditions
+   ?@   add branch conditions followed by nullify
+   ?d	non-negated add branch conditions
+   ?D	negated add branch conditions
+   ?w	wide mode non-negated add branch conditions
+   ?W	wide mode negated add branch conditions
+
+   ?s   compare/subtract conditions
+   ?S	64 bit compare/subtract conditions
+   ?t   non-negated compare and branch conditions
+   ?n   32 bit compare and branch conditions followed by nullify
+   ?N   64 bit compare and branch conditions followed by nullify
+   ?Q	64 bit compare and branch conditions for CMPIB instruction
+
+   ?l   logical conditions
+   ?L	64 bit logical conditions
+
+   ?b   branch on bit conditions
+   ?B	64 bit branch on bit conditions
+
+   ?x   shift/extract/deposit conditions
+   ?X	64 bit shift/extract/deposit conditions
+   ?y   shift/extract/deposit conditions followed by nullify for conditional
+        branches
+
+   ?u   unit conditions
+   ?U   64 bit unit conditions
+
+Floating point registers all have 'f' as a prefix:
+
+   ft	target register at 31
+   fT	target register with L/R halves at 31
+   fa	operand 1 register at 10
+   fA   operand 1 register with L/R halves at 10
+   fX   Same as fA, except prints a space before register during disasm
+   fb	operand 2 register at 15
+   fB   operand 2 register with L/R halves at 15
+   fC   operand 3 register with L/R halves at 16:18,21:23
+   fe   Like fT, but encoding is different.
+   fE   Same as fe, except prints a space before register during disasm.
+   fx	target register at 15 (only for PA 2.0 long format FLDD/FSTD).
+
+Float registers for fmpyadd and fmpysub:
+
+   fi	mult operand 1 register at 10
+   fj	mult operand 2 register at 15
+   fk	mult target register at 20
+   fl	add/sub operand register at 25
+   fm	add/sub target register at 31
+
+*/
+
+
+#if 0
+/* List of characters not to put a space after.  Note that
+   "," is included, as the "spopN" operations use literal
+   commas in their completer sections.  */
+static const char *const completer_chars = ",CcY<>?!@+&U~FfGHINnOoZMadu|/=0123%e$m}";
+#endif
+
+/* The order of the opcodes in this table is significant:
+
+   * The assembler requires that all instances of the same mnemonic be
+     consecutive.  If they aren't, the assembler will bomb at runtime.
+
+   * Immediate fields use pa_get_absolute_expression to parse the
+     string.  It will generate a "bad expression" error if passed
+     a register name.  Thus, register index variants of an opcode
+     need to precede immediate variants.
+
+   * The disassembler does not care about the order of the opcodes
+     except in cases where implicit addressing is used.
+
+   Here are the rules for ordering the opcodes of a mnemonic:
+
+   1) Opcodes with FLAG_STRICT should precede opcodes without
+      FLAG_STRICT.
+
+   2) Opcodes with FLAG_STRICT should be ordered as follows:
+      register index opcodes, short immediate opcodes, and finally
+      long immediate opcodes.  When both pa10 and pa11 variants
+      of the same opcode are available, the pa10 opcode should
+      come first for correct architectural promotion.
+
+   3) When implicit addressing is available for an opcode, the
+      implicit opcode should precede the explicit opcode.
+
+   4) Opcodes without FLAG_STRICT should be ordered as follows:
+      register index opcodes, long immediate opcodes, and finally
+      short immediate opcodes.  */
+
+static const struct pa_opcode pa_opcodes[] =
+{
+
+/* Pseudo-instructions.  */
+
+{ "ldi",	0x34000000, 0xffe00000, "l,x", pa20w, 0},/* ldo val(r0),r */
+{ "ldi",	0x34000000, 0xffe0c000, "j,x", pa10, 0},/* ldo val(r0),r */
+
+{ "cmpib",	0xec000000, 0xfc000000, "?Qn5,b,w", pa20, FLAG_STRICT},
+{ "cmpib", 	0x84000000, 0xf4000000, "?nn5,b,w", pa10, FLAG_STRICT},
+{ "comib", 	0x84000000, 0xfc000000, "?nn5,b,w", pa10, 0}, /* comib{tf}*/
+/* This entry is for the disassembler only.  It will never be used by
+   assembler.  */
+{ "comib", 	0x8c000000, 0xfc000000, "?nn5,b,w", pa10, 0}, /* comib{tf}*/
+{ "cmpb",	0x9c000000, 0xdc000000, "?Nnx,b,w", pa20, FLAG_STRICT},
+{ "cmpb",	0x80000000, 0xf4000000, "?nnx,b,w", pa10, FLAG_STRICT},
+{ "comb",	0x80000000, 0xfc000000, "?nnx,b,w", pa10, 0}, /* comb{tf} */
+/* This entry is for the disassembler only.  It will never be used by
+   assembler.  */
+{ "comb",	0x88000000, 0xfc000000, "?nnx,b,w", pa10, 0}, /* comb{tf} */
+{ "addb",	0xa0000000, 0xf4000000, "?Wnx,b,w", pa20w, FLAG_STRICT},
+{ "addb",	0xa0000000, 0xfc000000, "?@nx,b,w", pa10, 0}, /* addb{tf} */
+/* This entry is for the disassembler only.  It will never be used by
+   assembler.  */
+{ "addb",	0xa8000000, 0xfc000000, "?@nx,b,w", pa10, 0},
+{ "addib",	0xa4000000, 0xf4000000, "?Wn5,b,w", pa20w, FLAG_STRICT},
+{ "addib",	0xa4000000, 0xfc000000, "?@n5,b,w", pa10, 0}, /* addib{tf}*/
+/* This entry is for the disassembler only.  It will never be used by
+   assembler.  */
+{ "addib",	0xac000000, 0xfc000000, "?@n5,b,w", pa10, 0}, /* addib{tf}*/
+{ "nop",	0x08000240, 0xffffffff, "", pa10, 0},      /* or 0,0,0 */
+{ "copy",	0x08000240, 0xffe0ffe0, "x,t", pa10, 0},   /* or r,0,t */
+{ "mtsar",	0x01601840, 0xffe0ffff, "x", pa10, 0}, /* mtctl r,cr11 */
+
+/* Loads and Stores for integer registers.  */
+
+{ "ldd",	0x0c0000c0, 0xfc00d3c0, "cxccx(b),t", pa20, FLAG_STRICT},
+{ "ldd",	0x0c0000c0, 0xfc0013c0, "cxccx(s,b),t", pa20, FLAG_STRICT},
+{ "ldd",	0x0c0010e0, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldd",	0x0c0010e0, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldd",	0x0c0010c0, 0xfc00d3c0, "cmcc5(b),t", pa20, FLAG_STRICT},
+{ "ldd",	0x0c0010c0, 0xfc0013c0, "cmcc5(s,b),t", pa20, FLAG_STRICT},
+{ "ldd",	0x50000000, 0xfc000002, "cq&(b),x", pa20w, FLAG_STRICT},
+{ "ldd",	0x50000000, 0xfc00c002, "cq#(b),x", pa20, FLAG_STRICT},
+{ "ldd",	0x50000000, 0xfc000002, "cq#(s,b),x", pa20, FLAG_STRICT},
+{ "ldw",	0x0c000080, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldw",	0x0c000080, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldw",	0x0c000080, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldw",	0x0c000080, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldw",	0x0c0010a0, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldw",	0x0c0010a0, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldw",	0x0c001080, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldw",	0x0c001080, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldw",	0x0c001080, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldw",	0x0c001080, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldw",	0x4c000000, 0xfc000000, "ce<(b),x", pa20w, FLAG_STRICT},
+{ "ldw",	0x5c000004, 0xfc000006, "ce>(b),x", pa20w, FLAG_STRICT},
+{ "ldw",	0x48000000, 0xfc000000, "l(b),x", pa20w, FLAG_STRICT},
+{ "ldw",	0x5c000004, 0xfc00c006, "ceK(b),x", pa20, FLAG_STRICT},
+{ "ldw",	0x5c000004, 0xfc000006, "ceK(s,b),x", pa20, FLAG_STRICT},
+{ "ldw",	0x4c000000, 0xfc00c000, "ceJ(b),x", pa10, FLAG_STRICT},
+{ "ldw",	0x4c000000, 0xfc000000, "ceJ(s,b),x", pa10, FLAG_STRICT},
+{ "ldw",	0x48000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldw",	0x48000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "ldh",	0x0c000040, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldh",	0x0c000040, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldh",	0x0c000040, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldh",	0x0c000040, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldh",	0x0c001060, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldh",	0x0c001060, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldh",	0x0c001040, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldh",	0x0c001040, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldh",	0x0c001040, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldh",	0x0c001040, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldh",	0x44000000, 0xfc000000, "l(b),x", pa20w, FLAG_STRICT},
+{ "ldh",	0x44000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldh",	0x44000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "ldb",	0x0c000000, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldb",	0x0c000000, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldb",	0x0c000000, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldb",	0x0c000000, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldb",	0x0c001020, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldb",	0x0c001020, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldb",	0x0c001000, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldb",	0x0c001000, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldb",	0x0c001000, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldb",	0x0c001000, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldb",	0x40000000, 0xfc000000, "l(b),x", pa20w, FLAG_STRICT},
+{ "ldb",	0x40000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldb",	0x40000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "std",	0x0c0012e0, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "std",	0x0c0012e0, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "std",	0x0c0012c0, 0xfc00d3c0, "cmcCx,V(b)", pa20, FLAG_STRICT},
+{ "std",	0x0c0012c0, 0xfc0013c0, "cmcCx,V(s,b)", pa20, FLAG_STRICT},
+{ "std",	0x70000000, 0xfc000002, "cqx,&(b)", pa20w, FLAG_STRICT},
+{ "std",	0x70000000, 0xfc00c002, "cqx,#(b)", pa20, FLAG_STRICT},
+{ "std",	0x70000000, 0xfc000002, "cqx,#(s,b)", pa20, FLAG_STRICT},
+{ "stw",	0x0c0012a0, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stw",	0x0c0012a0, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "stw",	0x0c001280, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stw",	0x0c001280, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stw",	0x0c001280, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stw",	0x0c001280, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stw",	0x6c000000, 0xfc000000, "cex,<(b)", pa20w, FLAG_STRICT},
+{ "stw",	0x7c000004, 0xfc000006, "cex,>(b)", pa20w, FLAG_STRICT},
+{ "stw",	0x68000000, 0xfc000000, "x,l(b)", pa20w, FLAG_STRICT},
+{ "stw",	0x7c000004, 0xfc00c006, "cex,K(b)", pa20, FLAG_STRICT},
+{ "stw",	0x7c000004, 0xfc000006, "cex,K(s,b)", pa20, FLAG_STRICT},
+{ "stw",	0x6c000000, 0xfc00c000, "cex,J(b)", pa10, FLAG_STRICT},
+{ "stw",	0x6c000000, 0xfc000000, "cex,J(s,b)", pa10, FLAG_STRICT},
+{ "stw",	0x68000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "stw",	0x68000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "sth",	0x0c001260, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "sth",	0x0c001260, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "sth",	0x0c001240, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "sth",	0x0c001240, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "sth",	0x0c001240, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "sth",	0x0c001240, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "sth",	0x64000000, 0xfc000000, "x,l(b)", pa20w, FLAG_STRICT},
+{ "sth",	0x64000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "sth",	0x64000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "stb",	0x0c001220, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stb",	0x0c001220, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "stb",	0x0c001200, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stb",	0x0c001200, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stb",	0x0c001200, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stb",	0x0c001200, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stb",	0x60000000, 0xfc000000, "x,l(b)", pa20w, FLAG_STRICT},
+{ "stb",	0x60000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "stb",	0x60000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "ldwm",	0x4c000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldwm",	0x4c000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "stwm",	0x6c000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "stwm",	0x6c000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "ldwx",	0x0c000080, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldwx",	0x0c000080, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldwx",	0x0c000080, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldwx",	0x0c000080, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldwx",	0x0c000080, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldwx",	0x0c000080, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldhx",	0x0c000040, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldhx",	0x0c000040, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldhx",	0x0c000040, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldhx",	0x0c000040, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldhx",	0x0c000040, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldhx",	0x0c000040, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldbx",	0x0c000000, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldbx",	0x0c000000, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldbx",	0x0c000000, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldbx",	0x0c000000, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldbx",	0x0c000000, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldbx",	0x0c000000, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldwa",	0x0c000180, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldwa",	0x0c000180, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldwa",	0x0c0011a0, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldwa",	0x0c001180, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldwa",	0x0c001180, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldcw",	0x0c0001c0, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldcw",	0x0c0001c0, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldcw",	0x0c0001c0, 0xfc00d3c0, "cxcdx(b),t", pa11, FLAG_STRICT},
+{ "ldcw",	0x0c0001c0, 0xfc0013c0, "cxcdx(s,b),t", pa11, FLAG_STRICT},
+{ "ldcw",	0x0c0011c0, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldcw",	0x0c0011c0, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldcw",	0x0c0011c0, 0xfc00d3c0, "cmcd5(b),t", pa11, FLAG_STRICT},
+{ "ldcw",	0x0c0011c0, 0xfc0013c0, "cmcd5(s,b),t", pa11, FLAG_STRICT},
+{ "stwa",	0x0c0013a0, 0xfc00d3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stwa",	0x0c001380, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stwa",	0x0c001380, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stby",	0x0c001300, 0xfc00dfc0, "cAx,V(b)", pa10, FLAG_STRICT},
+{ "stby",	0x0c001300, 0xfc001fc0, "cAx,V(s,b)", pa10, FLAG_STRICT},
+{ "stby",	0x0c001300, 0xfc00d3c0, "cscCx,V(b)", pa11, FLAG_STRICT},
+{ "stby",	0x0c001300, 0xfc0013c0, "cscCx,V(s,b)", pa11, FLAG_STRICT},
+{ "ldda",	0x0c000100, 0xfc00d3c0, "cxccx(b),t", pa20, FLAG_STRICT},
+{ "ldda",	0x0c001120, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldda",	0x0c001100, 0xfc00d3c0, "cmcc5(b),t", pa20, FLAG_STRICT},
+{ "ldcd",	0x0c000140, 0xfc00d3c0, "cxcdx(b),t", pa20, FLAG_STRICT},
+{ "ldcd",	0x0c000140, 0xfc0013c0, "cxcdx(s,b),t", pa20, FLAG_STRICT},
+{ "ldcd",	0x0c001140, 0xfc00d3c0, "cmcd5(b),t", pa20, FLAG_STRICT},
+{ "ldcd",	0x0c001140, 0xfc0013c0, "cmcd5(s,b),t", pa20, FLAG_STRICT},
+{ "stda",	0x0c0013e0, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stda",	0x0c0013c0, 0xfc00d3c0, "cmcCx,V(b)", pa20, FLAG_STRICT},
+{ "ldwax",	0x0c000180, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldwax",	0x0c000180, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldwax",	0x0c000180, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldcwx",	0x0c0001c0, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldcwx",	0x0c0001c0, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldcwx",	0x0c0001c0, 0xfc00d3c0, "cxcdx(b),t", pa11, FLAG_STRICT},
+{ "ldcwx",	0x0c0001c0, 0xfc0013c0, "cxcdx(s,b),t", pa11, FLAG_STRICT},
+{ "ldcwx",	0x0c0001c0, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldcwx",	0x0c0001c0, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldws",	0x0c001080, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldws",	0x0c001080, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldws",	0x0c001080, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldws",	0x0c001080, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldws",	0x0c001080, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldws",	0x0c001080, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "ldhs",	0x0c001040, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldhs",	0x0c001040, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldhs",	0x0c001040, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldhs",	0x0c001040, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldhs",	0x0c001040, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldhs",	0x0c001040, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "ldbs",	0x0c001000, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldbs",	0x0c001000, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldbs",	0x0c001000, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldbs",	0x0c001000, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldbs",	0x0c001000, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldbs",	0x0c001000, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "ldwas",	0x0c001180, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldwas",	0x0c001180, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldwas",	0x0c001180, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldcws",	0x0c0011c0, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldcws",	0x0c0011c0, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldcws",	0x0c0011c0, 0xfc00d3c0, "cmcd5(b),t", pa11, FLAG_STRICT},
+{ "ldcws",	0x0c0011c0, 0xfc0013c0, "cmcd5(s,b),t", pa11, FLAG_STRICT},
+{ "ldcws",	0x0c0011c0, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldcws",	0x0c0011c0, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "stws",	0x0c001280, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stws",	0x0c001280, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stws",	0x0c001280, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stws",	0x0c001280, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stws",	0x0c001280, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "stws",	0x0c001280, 0xfc001fc0, "cMx,V(s,b)", pa10, 0},
+{ "sths",	0x0c001240, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "sths",	0x0c001240, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "sths",	0x0c001240, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "sths",	0x0c001240, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "sths",	0x0c001240, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "sths",	0x0c001240, 0xfc001fc0, "cMx,V(s,b)", pa10, 0},
+{ "stbs",	0x0c001200, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stbs",	0x0c001200, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stbs",	0x0c001200, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stbs",	0x0c001200, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stbs",	0x0c001200, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "stbs",	0x0c001200, 0xfc001fc0, "cMx,V(s,b)", pa10, 0},
+{ "stwas",	0x0c001380, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stwas",	0x0c001380, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stwas",	0x0c001380, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "stdby",	0x0c001340, 0xfc00d3c0, "cscCx,V(b)", pa20, FLAG_STRICT},
+{ "stdby",	0x0c001340, 0xfc0013c0, "cscCx,V(s,b)", pa20, FLAG_STRICT},
+{ "stbys",	0x0c001300, 0xfc00dfc0, "cAx,V(b)", pa10, FLAG_STRICT},
+{ "stbys",	0x0c001300, 0xfc001fc0, "cAx,V(s,b)", pa10, FLAG_STRICT},
+{ "stbys",	0x0c001300, 0xfc00d3c0, "cscCx,V(b)", pa11, FLAG_STRICT},
+{ "stbys",	0x0c001300, 0xfc0013c0, "cscCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stbys",	0x0c001300, 0xfc00dfc0, "cAx,V(b)", pa10, 0},
+{ "stbys",	0x0c001300, 0xfc001fc0, "cAx,V(s,b)", pa10, 0},
+
+/* Immediate instructions.  */
+{ "ldo",	0x34000000, 0xfc000000, "l(b),x", pa20w, 0},
+{ "ldo",	0x34000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldil",	0x20000000, 0xfc000000, "k,b", pa10, 0},
+{ "addil",	0x28000000, 0xfc000000, "k,b,Z", pa10, 0},
+{ "addil",	0x28000000, 0xfc000000, "k,b", pa10, 0},
+
+/* Branching instructions.  */
+{ "b",		0xe8008000, 0xfc00e000, "cpnXL", pa20, FLAG_STRICT},
+{ "b",		0xe800a000, 0xfc00e000, "clnXL", pa20, FLAG_STRICT},
+{ "b",		0xe8000000, 0xfc00e000, "clnW,b", pa10, FLAG_STRICT},
+{ "b",		0xe8002000, 0xfc00e000, "cgnW,b", pa10, FLAG_STRICT},
+{ "b",		0xe8000000, 0xffe0e000, "nW", pa10, 0},  /* b,l foo,r0 */
+{ "bl",		0xe8000000, 0xfc00e000, "nW,b", pa10, 0},
+{ "gate",	0xe8002000, 0xfc00e000, "nW,b", pa10, 0},
+{ "blr",	0xe8004000, 0xfc00e001, "nx,b", pa10, 0},
+{ "bv",		0xe800c000, 0xfc00fffd, "nx(b)", pa10, 0},
+{ "bv",		0xe800c000, 0xfc00fffd, "n(b)", pa10, 0},
+{ "bve",	0xe800f001, 0xfc1ffffd, "cpn(b)L", pa20, FLAG_STRICT},
+{ "bve",	0xe800f000, 0xfc1ffffd, "cln(b)L", pa20, FLAG_STRICT},
+{ "bve",	0xe800d001, 0xfc1ffffd, "cPn(b)", pa20, FLAG_STRICT},
+{ "bve",	0xe800d000, 0xfc1ffffd, "n(b)", pa20, FLAG_STRICT},
+{ "be",		0xe4000000, 0xfc000000, "clnz(S,b),Y", pa10, FLAG_STRICT},
+{ "be",		0xe4000000, 0xfc000000, "clnz(b),Y", pa10, FLAG_STRICT},
+{ "be",		0xe0000000, 0xfc000000, "nz(S,b)", pa10, 0},
+{ "be",		0xe0000000, 0xfc000000, "nz(b)", pa10, 0},
+{ "ble",	0xe4000000, 0xfc000000, "nz(S,b)", pa10, 0},
+{ "movb",	0xc8000000, 0xfc000000, "?ynx,b,w", pa10, 0},
+{ "movib",	0xcc000000, 0xfc000000, "?yn5,b,w", pa10, 0},
+{ "combt",	0x80000000, 0xfc000000, "?tnx,b,w", pa10, 0},
+{ "combf",	0x88000000, 0xfc000000, "?tnx,b,w", pa10, 0},
+{ "comibt",	0x84000000, 0xfc000000, "?tn5,b,w", pa10, 0},
+{ "comibf",	0x8c000000, 0xfc000000, "?tn5,b,w", pa10, 0},
+{ "addbt",	0xa0000000, 0xfc000000, "?dnx,b,w", pa10, 0},
+{ "addbf",	0xa8000000, 0xfc000000, "?dnx,b,w", pa10, 0},
+{ "addibt",	0xa4000000, 0xfc000000, "?dn5,b,w", pa10, 0},
+{ "addibf",	0xac000000, 0xfc000000, "?dn5,b,w", pa10, 0},
+{ "bb",		0xc0004000, 0xffe06000, "?bnx,!,w", pa10, FLAG_STRICT},
+{ "bb",		0xc0006000, 0xffe06000, "?Bnx,!,w", pa20, FLAG_STRICT},
+{ "bb",		0xc4004000, 0xfc006000, "?bnx,Q,w", pa10, FLAG_STRICT},
+{ "bb",		0xc4004000, 0xfc004000, "?Bnx,B,w", pa20, FLAG_STRICT},
+{ "bvb",	0xc0004000, 0xffe04000, "?bnx,w", pa10, 0},
+{ "clrbts",	0xe8004005, 0xffffffff, "", pa20, FLAG_STRICT},
+{ "popbts",	0xe8004005, 0xfffff007, "$", pa20, FLAG_STRICT},
+{ "pushnom",	0xe8004001, 0xffffffff, "", pa20, FLAG_STRICT},
+{ "pushbts",	0xe8004001, 0xffe0ffff, "x", pa20, FLAG_STRICT},
+
+/* Computation Instructions.  */
+
+{ "cmpclr",	0x080008a0, 0xfc000fe0, "?Sx,b,t", pa20, FLAG_STRICT},
+{ "cmpclr",	0x08000880, 0xfc000fe0, "?sx,b,t", pa10, FLAG_STRICT},
+{ "comclr",	0x08000880, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "or",		0x08000260, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "or",		0x08000240, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "xor",	0x080002a0, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "xor",	0x08000280, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "and",	0x08000220, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "and",	0x08000200, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "andcm",	0x08000020, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "andcm",	0x08000000, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "uxor",	0x080003a0, 0xfc000fe0, "?Ux,b,t", pa20, FLAG_STRICT},
+{ "uxor",	0x08000380, 0xfc000fe0, "?ux,b,t", pa10, 0},
+{ "uaddcm",	0x080009a0, 0xfc000fa0, "cT?Ux,b,t", pa20, FLAG_STRICT},
+{ "uaddcm",	0x08000980, 0xfc000fa0, "cT?ux,b,t", pa10, FLAG_STRICT},
+{ "uaddcm",	0x08000980, 0xfc000fe0, "?ux,b,t", pa10, 0},
+{ "uaddcmt",	0x080009c0, 0xfc000fe0, "?ux,b,t", pa10, 0},
+{ "dcor",	0x08000ba0, 0xfc1f0fa0, "ci?Ub,t", pa20, FLAG_STRICT},
+{ "dcor",	0x08000b80, 0xfc1f0fa0, "ci?ub,t", pa10, FLAG_STRICT},
+{ "dcor",	0x08000b80, 0xfc1f0fe0, "?ub,t",   pa10, 0},
+{ "idcor",	0x08000bc0, 0xfc1f0fe0, "?ub,t",   pa10, 0},
+{ "addi",	0xb0000000, 0xfc000000, "ct?ai,b,x", pa10, FLAG_STRICT},
+{ "addi",	0xb4000000, 0xfc000000, "cv?ai,b,x", pa10, FLAG_STRICT},
+{ "addi",	0xb4000000, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "addio",	0xb4000800, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "addit",	0xb0000000, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "addito",	0xb0000800, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "add",	0x08000720, 0xfc0007e0, "cY?Ax,b,t", pa20, FLAG_STRICT},
+{ "add",	0x08000700, 0xfc0007e0, "cy?ax,b,t", pa10, FLAG_STRICT},
+{ "add",	0x08000220, 0xfc0003e0, "ca?Ax,b,t", pa20, FLAG_STRICT},
+{ "add",	0x08000200, 0xfc0003e0, "ca?ax,b,t", pa10, FLAG_STRICT},
+{ "add",	0x08000600, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addl",	0x08000a00, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addo",	0x08000e00, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addc",	0x08000700, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addco",	0x08000f00, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sub",	0x080004e0, 0xfc0007e0, "ct?Sx,b,t", pa20, FLAG_STRICT},
+{ "sub",	0x080004c0, 0xfc0007e0, "ct?sx,b,t", pa10, FLAG_STRICT},
+{ "sub",	0x08000520, 0xfc0007e0, "cB?Sx,b,t", pa20, FLAG_STRICT},
+{ "sub",	0x08000500, 0xfc0007e0, "cb?sx,b,t", pa10, FLAG_STRICT},
+{ "sub",	0x08000420, 0xfc0007e0, "cv?Sx,b,t", pa20, FLAG_STRICT},
+{ "sub",	0x08000400, 0xfc0007e0, "cv?sx,b,t", pa10, FLAG_STRICT},
+{ "sub",	0x08000400, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subo",	0x08000c00, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subb",	0x08000500, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subbo",	0x08000d00, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subt",	0x080004c0, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subto",	0x08000cc0, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "ds",		0x08000440, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subi",	0x94000000, 0xfc000000, "cv?si,b,x", pa10, FLAG_STRICT},
+{ "subi",	0x94000000, 0xfc000800, "?si,b,x", pa10, 0},
+{ "subio",	0x94000800, 0xfc000800, "?si,b,x", pa10, 0},
+{ "cmpiclr",	0x90000800, 0xfc000800, "?Si,b,x", pa20, FLAG_STRICT},
+{ "cmpiclr",	0x90000000, 0xfc000800, "?si,b,x", pa10, FLAG_STRICT},
+{ "comiclr",	0x90000000, 0xfc000800, "?si,b,x", pa10, 0},
+{ "shladd",	0x08000220, 0xfc000320, "ca?Ax,.,b,t", pa20, FLAG_STRICT},
+{ "shladd",	0x08000200, 0xfc000320, "ca?ax,.,b,t", pa10, FLAG_STRICT},
+{ "sh1add",	0x08000640, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh1addl",	0x08000a40, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh1addo",	0x08000e40, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh2add",	0x08000680, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh2addl",	0x08000a80, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh2addo",	0x08000e80, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh3add",	0x080006c0, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh3addl",	0x08000ac0, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh3addo",	0x08000ec0, 0xfc000fe0, "?ax,b,t", pa10, 0},
+
+/* Subword Operation Instructions.  */
+
+{ "hadd",	0x08000300, 0xfc00ff20, "cHx,b,t", pa20, FLAG_STRICT},
+{ "havg",	0x080002c0, 0xfc00ffe0, "x,b,t", pa20, FLAG_STRICT},
+{ "hshl",	0xf8008800, 0xffe0fc20, "x,*,t", pa20, FLAG_STRICT},
+{ "hshladd",	0x08000700, 0xfc00ff20, "x,.,b,t", pa20, FLAG_STRICT},
+{ "hshr",	0xf800c800, 0xfc1ff820, "cSb,*,t", pa20, FLAG_STRICT},
+{ "hshradd",	0x08000500, 0xfc00ff20, "x,.,b,t", pa20, FLAG_STRICT},
+{ "hsub",	0x08000100, 0xfc00ff20, "cHx,b,t", pa20, FLAG_STRICT},
+{ "mixh",	0xf8008400, 0xfc009fe0, "chx,b,t", pa20, FLAG_STRICT},
+{ "mixw",	0xf8008000, 0xfc009fe0, "chx,b,t", pa20, FLAG_STRICT},
+{ "permh",	0xf8000000, 0xfc009020, "c*a,t", pa20, FLAG_STRICT},
+
+
+/* Extract and Deposit Instructions.  */
+
+{ "shrpd",	0xd0000200, 0xfc001fe0, "?Xx,b,!,t", pa20, FLAG_STRICT},
+{ "shrpd",	0xd0000400, 0xfc001400, "?Xx,b,~,t", pa20, FLAG_STRICT},
+{ "shrpw",	0xd0000000, 0xfc001fe0, "?xx,b,!,t", pa10, FLAG_STRICT},
+{ "shrpw",	0xd0000800, 0xfc001c00, "?xx,b,p,t", pa10, FLAG_STRICT},
+{ "vshd",	0xd0000000, 0xfc001fe0, "?xx,b,t", pa10, 0},
+{ "shd",	0xd0000800, 0xfc001c00, "?xx,b,p,t", pa10, 0},
+{ "extrd",	0xd0001200, 0xfc001ae0, "cS?Xb,!,%,x", pa20, FLAG_STRICT},
+{ "extrd",	0xd8000000, 0xfc000000, "cS?Xb,q,|,x", pa20, FLAG_STRICT},
+{ "extrw",	0xd0001000, 0xfc001be0, "cS?xb,!,T,x", pa10, FLAG_STRICT},
+{ "extrw",	0xd0001800, 0xfc001800, "cS?xb,P,T,x", pa10, FLAG_STRICT},
+{ "vextru",	0xd0001000, 0xfc001fe0, "?xb,T,x", pa10, 0},
+{ "vextrs",	0xd0001400, 0xfc001fe0, "?xb,T,x", pa10, 0},
+{ "extru",	0xd0001800, 0xfc001c00, "?xb,P,T,x", pa10, 0},
+{ "extrs",	0xd0001c00, 0xfc001c00, "?xb,P,T,x", pa10, 0},
+{ "depd",	0xd4000200, 0xfc001ae0, "cz?Xx,!,%,b", pa20, FLAG_STRICT},
+{ "depd",	0xf0000000, 0xfc000000, "cz?Xx,~,|,b", pa20, FLAG_STRICT},
+{ "depdi",	0xd4001200, 0xfc001ae0, "cz?X5,!,%,b", pa20, FLAG_STRICT},
+{ "depdi",	0xf4000000, 0xfc000000, "cz?X5,~,|,b", pa20, FLAG_STRICT},
+{ "depw",	0xd4000000, 0xfc001be0, "cz?xx,!,T,b", pa10, FLAG_STRICT},
+{ "depw",	0xd4000800, 0xfc001800, "cz?xx,p,T,b", pa10, FLAG_STRICT},
+{ "depwi",	0xd4001000, 0xfc001be0, "cz?x5,!,T,b", pa10, FLAG_STRICT},
+{ "depwi",	0xd4001800, 0xfc001800, "cz?x5,p,T,b", pa10, FLAG_STRICT},
+{ "zvdep",	0xd4000000, 0xfc001fe0, "?xx,T,b", pa10, 0},
+{ "vdep",	0xd4000400, 0xfc001fe0, "?xx,T,b", pa10, 0},
+{ "zdep",	0xd4000800, 0xfc001c00, "?xx,p,T,b", pa10, 0},
+{ "dep",	0xd4000c00, 0xfc001c00, "?xx,p,T,b", pa10, 0},
+{ "zvdepi",	0xd4001000, 0xfc001fe0, "?x5,T,b", pa10, 0},
+{ "vdepi",	0xd4001400, 0xfc001fe0, "?x5,T,b", pa10, 0},
+{ "zdepi",	0xd4001800, 0xfc001c00, "?x5,p,T,b", pa10, 0},
+{ "depi",	0xd4001c00, 0xfc001c00, "?x5,p,T,b", pa10, 0},
+
+/* System Control Instructions.  */
+
+{ "break",	0x00000000, 0xfc001fe0, "r,A", pa10, 0},
+{ "rfi",	0x00000c00, 0xffffff1f, "cr", pa10, FLAG_STRICT},
+{ "rfi",	0x00000c00, 0xffffffff, "", pa10, 0},
+{ "rfir",	0x00000ca0, 0xffffffff, "", pa11, 0},
+{ "ssm",	0x00000d60, 0xfc00ffe0, "U,t", pa20, FLAG_STRICT},
+{ "ssm",	0x00000d60, 0xffe0ffe0, "R,t", pa10, 0},
+{ "rsm",	0x00000e60, 0xfc00ffe0, "U,t", pa20, FLAG_STRICT},
+{ "rsm",	0x00000e60, 0xffe0ffe0, "R,t", pa10, 0},
+{ "mtsm",	0x00001860, 0xffe0ffff, "x", pa10, 0},
+{ "ldsid",	0x000010a0, 0xfc1fffe0, "(b),t", pa10, 0},
+{ "ldsid",	0x000010a0, 0xfc1f3fe0, "(s,b),t", pa10, 0},
+{ "mtsp",	0x00001820, 0xffe01fff, "x,S", pa10, 0},
+{ "mtctl",	0x00001840, 0xfc00ffff, "x,^", pa10, 0},
+{ "mtsarcm",	0x016018C0, 0xffe0ffff, "x", pa20, FLAG_STRICT},
+{ "mfia",	0x000014A0, 0xffffffe0, "t", pa20, FLAG_STRICT},
+{ "mfsp",	0x000004a0, 0xffff1fe0, "S,t", pa10, 0},
+{ "mfctl",	0x016048a0, 0xffffffe0, "cW!,t", pa20, FLAG_STRICT},
+{ "mfctl",	0x000008a0, 0xfc1fffe0, "^,t", pa10, 0},
+{ "sync",	0x00000400, 0xffffffff, "", pa10, 0},
+{ "syncdma",	0x00100400, 0xffffffff, "", pa10, 0},
+{ "probe",	0x04001180, 0xfc00ffa0, "cw(b),x,t", pa10, FLAG_STRICT},
+{ "probe",	0x04001180, 0xfc003fa0, "cw(s,b),x,t", pa10, FLAG_STRICT},
+{ "probei",	0x04003180, 0xfc00ffa0, "cw(b),R,t", pa10, FLAG_STRICT},
+{ "probei",	0x04003180, 0xfc003fa0, "cw(s,b),R,t", pa10, FLAG_STRICT},
+{ "prober",	0x04001180, 0xfc00ffe0, "(b),x,t", pa10, 0},
+{ "prober",	0x04001180, 0xfc003fe0, "(s,b),x,t", pa10, 0},
+{ "proberi",	0x04003180, 0xfc00ffe0, "(b),R,t", pa10, 0},
+{ "proberi",	0x04003180, 0xfc003fe0, "(s,b),R,t", pa10, 0},
+{ "probew",	0x040011c0, 0xfc00ffe0, "(b),x,t", pa10, 0},
+{ "probew",	0x040011c0, 0xfc003fe0, "(s,b),x,t", pa10, 0},
+{ "probewi",	0x040031c0, 0xfc00ffe0, "(b),R,t", pa10, 0},
+{ "probewi",	0x040031c0, 0xfc003fe0, "(s,b),R,t", pa10, 0},
+{ "lpa",	0x04001340, 0xfc00ffc0, "cZx(b),t", pa10, 0},
+{ "lpa",	0x04001340, 0xfc003fc0, "cZx(s,b),t", pa10, 0},
+{ "lci",	0x04001300, 0xfc00ffe0, "x(b),t", pa11, 0},
+{ "lci",	0x04001300, 0xfc003fe0, "x(s,b),t", pa11, 0},
+{ "pdtlb",	0x04001600, 0xfc00ffdf, "cLcZx(b)", pa20, FLAG_STRICT},
+{ "pdtlb",	0x04001600, 0xfc003fdf, "cLcZx(s,b)", pa20, FLAG_STRICT},
+{ "pdtlb",	0x04001600, 0xfc1fffdf, "cLcZ@(b)", pa20, FLAG_STRICT},
+{ "pdtlb",	0x04001600, 0xfc1f3fdf, "cLcZ@(s,b)", pa20, FLAG_STRICT},
+{ "pdtlb",	0x04001200, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "pdtlb",	0x04001200, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "pitlb",	0x04000600, 0xfc001fdf, "cLcZx(S,b)", pa20, FLAG_STRICT},
+{ "pitlb",	0x04000600, 0xfc1f1fdf, "cLcZ@(S,b)", pa20, FLAG_STRICT},
+{ "pitlb",	0x04000200, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "pdtlbe",	0x04001240, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "pdtlbe",	0x04001240, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "pitlbe",	0x04000240, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "idtlba",	0x04001040, 0xfc00ffff, "x,(b)", pa10, 0},
+{ "idtlba",	0x04001040, 0xfc003fff, "x,(s,b)", pa10, 0},
+{ "iitlba",	0x04000040, 0xfc001fff, "x,(S,b)", pa10, 0},
+{ "idtlbp",	0x04001000, 0xfc00ffff, "x,(b)", pa10, 0},
+{ "idtlbp",	0x04001000, 0xfc003fff, "x,(s,b)", pa10, 0},
+{ "iitlbp",	0x04000000, 0xfc001fff, "x,(S,b)", pa10, 0},
+{ "pdc",	0x04001380, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "pdc",	0x04001380, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "fdc",	0x04001280, 0xfc00ffdf, "cZx(b)", pa10, FLAG_STRICT},
+{ "fdc",	0x04001280, 0xfc003fdf, "cZx(s,b)", pa10, FLAG_STRICT},
+{ "fdc",	0x04003280, 0xfc00ffff, "5(b)", pa20, FLAG_STRICT},
+{ "fdc",	0x04003280, 0xfc003fff, "5(s,b)", pa20, FLAG_STRICT},
+{ "fdc",	0x04001280, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "fdc",	0x04001280, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "fic",	0x040013c0, 0xfc00dfdf, "cZx(b)", pa20, FLAG_STRICT},
+{ "fic",	0x04000280, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "fdce",	0x040012c0, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "fdce",	0x040012c0, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "fice",	0x040002c0, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "diag",	0x14000000, 0xfc000000, "D", pa10, 0},
+{ "idtlbt",	0x04001800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT},
+{ "iitlbt",	0x04000800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT},
+
+/* These may be specific to certain versions of the PA.  Joel claimed
+   they were 72000 (7200?) specific.  However, I'm almost certain the
+   mtcpu/mfcpu were undocumented, but available in the older 700 machines.  */
+{ "mtcpu",	0x14001600, 0xfc00ffff, "x,^", pa10, 0},
+{ "mfcpu",	0x14001A00, 0xfc00ffff, "^,x", pa10, 0},
+{ "tocen",	0x14403600, 0xffffffff, "", pa10, 0},
+{ "tocdis",	0x14401620, 0xffffffff, "", pa10, 0},
+{ "shdwgr",	0x14402600, 0xffffffff, "", pa10, 0},
+{ "grshdw",	0x14400620, 0xffffffff, "", pa10, 0},
+
+/* gfw and gfr are not in the HP PA 1.1 manual, but they are in either
+   the Timex FPU or the Mustang ERS (not sure which) manual.  */
+{ "gfw",	0x04001680, 0xfc00ffdf, "cZx(b)", pa11, 0},
+{ "gfw",	0x04001680, 0xfc003fdf, "cZx(s,b)", pa11, 0},
+{ "gfr",	0x04001a80, 0xfc00ffdf, "cZx(b)", pa11, 0},
+{ "gfr",	0x04001a80, 0xfc003fdf, "cZx(s,b)", pa11, 0},
+
+/* Floating Point Coprocessor Instructions.  */
+
+{ "fldw",	0x24000000, 0xfc00df80, "cXx(b),fT", pa10, FLAG_STRICT},
+{ "fldw",	0x24000000, 0xfc001f80, "cXx(s,b),fT", pa10, FLAG_STRICT},
+{ "fldw",	0x24000000, 0xfc00d380, "cxccx(b),fT", pa11, FLAG_STRICT},
+{ "fldw",	0x24000000, 0xfc001380, "cxccx(s,b),fT", pa11, FLAG_STRICT},
+{ "fldw",	0x24001020, 0xfc1ff3a0, "cocc@(b),fT", pa20, FLAG_STRICT},
+{ "fldw",	0x24001020, 0xfc1f33a0, "cocc@(s,b),fT", pa20, FLAG_STRICT},
+{ "fldw",	0x24001000, 0xfc00df80, "cM5(b),fT", pa10, FLAG_STRICT},
+{ "fldw",	0x24001000, 0xfc001f80, "cM5(s,b),fT", pa10, FLAG_STRICT},
+{ "fldw",	0x24001000, 0xfc00d380, "cmcc5(b),fT", pa11, FLAG_STRICT},
+{ "fldw",	0x24001000, 0xfc001380, "cmcc5(s,b),fT", pa11, FLAG_STRICT},
+{ "fldw",	0x5c000000, 0xfc000004, "y(b),fe", pa20w, FLAG_STRICT},
+{ "fldw",	0x58000000, 0xfc000000, "cJy(b),fe", pa20w, FLAG_STRICT},
+{ "fldw",	0x5c000000, 0xfc00c004, "d(b),fe", pa20, FLAG_STRICT},
+{ "fldw",	0x5c000000, 0xfc000004, "d(s,b),fe", pa20, FLAG_STRICT},
+{ "fldw",	0x58000000, 0xfc00c000, "cJd(b),fe", pa20, FLAG_STRICT},
+{ "fldw",	0x58000000, 0xfc000000, "cJd(s,b),fe", pa20, FLAG_STRICT},
+{ "fldd",	0x2c000000, 0xfc00dfc0, "cXx(b),ft", pa10, FLAG_STRICT},
+{ "fldd",	0x2c000000, 0xfc001fc0, "cXx(s,b),ft", pa10, FLAG_STRICT},
+{ "fldd",	0x2c000000, 0xfc00d3c0, "cxccx(b),ft", pa11, FLAG_STRICT},
+{ "fldd",	0x2c000000, 0xfc0013c0, "cxccx(s,b),ft", pa11, FLAG_STRICT},
+{ "fldd",	0x2c001020, 0xfc1ff3e0, "cocc@(b),ft", pa20, FLAG_STRICT},
+{ "fldd",	0x2c001020, 0xfc1f33e0, "cocc@(s,b),ft", pa20, FLAG_STRICT},
+{ "fldd",	0x2c001000, 0xfc00dfc0, "cM5(b),ft", pa10, FLAG_STRICT},
+{ "fldd",	0x2c001000, 0xfc001fc0, "cM5(s,b),ft", pa10, FLAG_STRICT},
+{ "fldd",	0x2c001000, 0xfc00d3c0, "cmcc5(b),ft", pa11, FLAG_STRICT},
+{ "fldd",	0x2c001000, 0xfc0013c0, "cmcc5(s,b),ft", pa11, FLAG_STRICT},
+{ "fldd",	0x50000002, 0xfc000002, "cq&(b),fx", pa20w, FLAG_STRICT},
+{ "fldd",	0x50000002, 0xfc00c002, "cq#(b),fx", pa20, FLAG_STRICT},
+{ "fldd",	0x50000002, 0xfc000002, "cq#(s,b),fx", pa20, FLAG_STRICT},
+{ "fstw",	0x24000200, 0xfc00df80, "cXfT,x(b)", pa10, FLAG_STRICT},
+{ "fstw",	0x24000200, 0xfc001f80, "cXfT,x(s,b)", pa10, FLAG_STRICT},
+{ "fstw",	0x24000200, 0xfc00d380, "cxcCfT,x(b)", pa11, FLAG_STRICT},
+{ "fstw",	0x24000200, 0xfc001380, "cxcCfT,x(s,b)", pa11, FLAG_STRICT},
+{ "fstw",	0x24001220, 0xfc1ff3a0, "cocCfT,@(b)", pa20, FLAG_STRICT},
+{ "fstw",	0x24001220, 0xfc1f33a0, "cocCfT,@(s,b)", pa20, FLAG_STRICT},
+{ "fstw",	0x24001200, 0xfc00df80, "cMfT,5(b)", pa10, FLAG_STRICT},
+{ "fstw",	0x24001200, 0xfc001f80, "cMfT,5(s,b)", pa10, FLAG_STRICT},
+{ "fstw",	0x24001200, 0xfc00df80, "cMfT,5(b)", pa10, FLAG_STRICT},
+{ "fstw",	0x24001200, 0xfc001f80, "cMfT,5(s,b)", pa10, FLAG_STRICT},
+{ "fstw",	0x7c000000, 0xfc000004, "fE,y(b)", pa20w, FLAG_STRICT},
+{ "fstw",	0x78000000, 0xfc000000, "cJfE,y(b)", pa20w, FLAG_STRICT},
+{ "fstw",	0x7c000000, 0xfc00c004, "fE,d(b)", pa20, FLAG_STRICT},
+{ "fstw",	0x7c000000, 0xfc000004, "fE,d(s,b)", pa20, FLAG_STRICT},
+{ "fstw",	0x78000000, 0xfc00c000, "cJfE,d(b)", pa20, FLAG_STRICT},
+{ "fstw",	0x78000000, 0xfc000000, "cJfE,d(s,b)", pa20, FLAG_STRICT},
+{ "fstd",	0x2c000200, 0xfc00dfc0, "cXft,x(b)", pa10, FLAG_STRICT},
+{ "fstd",	0x2c000200, 0xfc001fc0, "cXft,x(s,b)", pa10, FLAG_STRICT},
+{ "fstd",	0x2c000200, 0xfc00d3c0, "cxcCft,x(b)", pa11, FLAG_STRICT},
+{ "fstd",	0x2c000200, 0xfc0013c0, "cxcCft,x(s,b)", pa11, FLAG_STRICT},
+{ "fstd",	0x2c001220, 0xfc1ff3e0, "cocCft,@(b)", pa20, FLAG_STRICT},
+{ "fstd",	0x2c001220, 0xfc1f33e0, "cocCft,@(s,b)", pa20, FLAG_STRICT},
+{ "fstd",	0x2c001200, 0xfc00dfc0, "cMft,5(b)", pa10, FLAG_STRICT},
+{ "fstd",	0x2c001200, 0xfc001fc0, "cMft,5(s,b)", pa10, FLAG_STRICT},
+{ "fstd",	0x2c001200, 0xfc00d3c0, "cmcCft,5(b)", pa11, FLAG_STRICT},
+{ "fstd",	0x2c001200, 0xfc0013c0, "cmcCft,5(s,b)", pa11, FLAG_STRICT},
+{ "fstd",	0x70000002, 0xfc000002, "cqfx,&(b)", pa20w, FLAG_STRICT},
+{ "fstd",	0x70000002, 0xfc00c002, "cqfx,#(b)", pa20, FLAG_STRICT},
+{ "fstd",	0x70000002, 0xfc000002, "cqfx,#(s,b)", pa20, FLAG_STRICT},
+{ "fldwx",	0x24000000, 0xfc00df80, "cXx(b),fT", pa10, FLAG_STRICT},
+{ "fldwx",	0x24000000, 0xfc001f80, "cXx(s,b),fT", pa10, FLAG_STRICT},
+{ "fldwx",	0x24000000, 0xfc00d380, "cxccx(b),fT", pa11, FLAG_STRICT},
+{ "fldwx",	0x24000000, 0xfc001380, "cxccx(s,b),fT", pa11, FLAG_STRICT},
+{ "fldwx",	0x24000000, 0xfc00df80, "cXx(b),fT", pa10, 0},
+{ "fldwx",	0x24000000, 0xfc001f80, "cXx(s,b),fT", pa10, 0},
+{ "flddx",	0x2c000000, 0xfc00dfc0, "cXx(b),ft", pa10, FLAG_STRICT},
+{ "flddx",	0x2c000000, 0xfc001fc0, "cXx(s,b),ft", pa10, FLAG_STRICT},
+{ "flddx",	0x2c000000, 0xfc00d3c0, "cxccx(b),ft", pa11, FLAG_STRICT},
+{ "flddx",	0x2c000000, 0xfc0013c0, "cxccx(s,b),ft", pa11, FLAG_STRICT},
+{ "flddx",	0x2c000000, 0xfc00dfc0, "cXx(b),ft", pa10, 0},
+{ "flddx",	0x2c000000, 0xfc001fc0, "cXx(s,b),ft", pa10, 0},
+{ "fstwx",	0x24000200, 0xfc00df80, "cxfT,x(b)", pa10, FLAG_STRICT},
+{ "fstwx",	0x24000200, 0xfc001f80, "cxfT,x(s,b)", pa10, FLAG_STRICT},
+{ "fstwx",	0x24000200, 0xfc00d380, "cxcCfT,x(b)", pa11, FLAG_STRICT},
+{ "fstwx",	0x24000200, 0xfc001380, "cxcCfT,x(s,b)", pa11, FLAG_STRICT},
+{ "fstwx",	0x24000200, 0xfc00df80, "cxfT,x(b)", pa10, 0},
+{ "fstwx",	0x24000200, 0xfc001f80, "cxfT,x(s,b)", pa10, 0},
+{ "fstdx",	0x2c000200, 0xfc00dfc0, "cxft,x(b)", pa10, FLAG_STRICT},
+{ "fstdx",	0x2c000200, 0xfc001fc0, "cxft,x(s,b)", pa10, FLAG_STRICT},
+{ "fstdx",	0x2c000200, 0xfc00d3c0, "cxcCft,x(b)", pa11, FLAG_STRICT},
+{ "fstdx",	0x2c000200, 0xfc0013c0, "cxcCft,x(s,b)", pa11, FLAG_STRICT},
+{ "fstdx",	0x2c000200, 0xfc00dfc0, "cxft,x(b)", pa10, 0},
+{ "fstdx",	0x2c000200, 0xfc001fc0, "cxft,x(s,b)", pa10, 0},
+{ "fstqx",	0x3c000200, 0xfc00dfc0, "cxft,x(b)", pa10, 0},
+{ "fstqx",	0x3c000200, 0xfc001fc0, "cxft,x(s,b)", pa10, 0},
+{ "fldws",	0x24001000, 0xfc00df80, "cm5(b),fT", pa10, FLAG_STRICT},
+{ "fldws",	0x24001000, 0xfc001f80, "cm5(s,b),fT", pa10, FLAG_STRICT},
+{ "fldws",	0x24001000, 0xfc00d380, "cmcc5(b),fT", pa11, FLAG_STRICT},
+{ "fldws",	0x24001000, 0xfc001380, "cmcc5(s,b),fT", pa11, FLAG_STRICT},
+{ "fldws",	0x24001000, 0xfc00df80, "cm5(b),fT", pa10, 0},
+{ "fldws",	0x24001000, 0xfc001f80, "cm5(s,b),fT", pa10, 0},
+{ "fldds",	0x2c001000, 0xfc00dfc0, "cm5(b),ft", pa10, FLAG_STRICT},
+{ "fldds",	0x2c001000, 0xfc001fc0, "cm5(s,b),ft", pa10, FLAG_STRICT},
+{ "fldds",	0x2c001000, 0xfc00d3c0, "cmcc5(b),ft", pa11, FLAG_STRICT},
+{ "fldds",	0x2c001000, 0xfc0013c0, "cmcc5(s,b),ft", pa11, FLAG_STRICT},
+{ "fldds",	0x2c001000, 0xfc00dfc0, "cm5(b),ft", pa10, 0},
+{ "fldds",	0x2c001000, 0xfc001fc0, "cm5(s,b),ft", pa10, 0},
+{ "fstws",	0x24001200, 0xfc00df80, "cmfT,5(b)", pa10, FLAG_STRICT},
+{ "fstws",	0x24001200, 0xfc001f80, "cmfT,5(s,b)", pa10, FLAG_STRICT},
+{ "fstws",	0x24001200, 0xfc00d380, "cmcCfT,5(b)", pa11, FLAG_STRICT},
+{ "fstws",	0x24001200, 0xfc001380, "cmcCfT,5(s,b)", pa11, FLAG_STRICT},
+{ "fstws",	0x24001200, 0xfc00df80, "cmfT,5(b)", pa10, 0},
+{ "fstws",	0x24001200, 0xfc001f80, "cmfT,5(s,b)", pa10, 0},
+{ "fstds",	0x2c001200, 0xfc00dfc0, "cmft,5(b)", pa10, FLAG_STRICT},
+{ "fstds",	0x2c001200, 0xfc001fc0, "cmft,5(s,b)", pa10, FLAG_STRICT},
+{ "fstds",	0x2c001200, 0xfc00d3c0, "cmcCft,5(b)", pa11, FLAG_STRICT},
+{ "fstds",	0x2c001200, 0xfc0013c0, "cmcCft,5(s,b)", pa11, FLAG_STRICT},
+{ "fstds",	0x2c001200, 0xfc00dfc0, "cmft,5(b)", pa10, 0},
+{ "fstds",	0x2c001200, 0xfc001fc0, "cmft,5(s,b)", pa10, 0},
+{ "fstqs",	0x3c001200, 0xfc00dfc0, "cmft,5(b)", pa10, 0},
+{ "fstqs",	0x3c001200, 0xfc001fc0, "cmft,5(s,b)", pa10, 0},
+{ "fadd",	0x30000600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fadd",	0x38000600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fsub",	0x30002600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fsub",	0x38002600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fmpy",	0x30004600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fmpy",	0x38004600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fdiv",	0x30006600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fdiv",	0x38006600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fsqrt",	0x30008000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "fsqrt",	0x38008000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "fabs",	0x30006000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "fabs",	0x38006000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "frem",	0x30008600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "frem",	0x38008600, 0xfc00e720, "FfA,fB,fT", pa10, 0},
+{ "frnd",	0x3000a000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "frnd",	0x3800a000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "fcpy",	0x30004000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "fcpy",	0x38004000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "fcnvff",	0x30000200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvff",	0x38000200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fcnvxf",	0x30008200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvxf",	0x38008200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fcnvfx",	0x30010200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvfx",	0x38010200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fcnvfxt",	0x30018200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvfxt",	0x38018200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fmpyfadd",	0xb8000000, 0xfc000020, "IfA,fB,fC,fT", pa20, FLAG_STRICT},
+{ "fmpynfadd",	0xb8000020, 0xfc000020, "IfA,fB,fC,fT", pa20, FLAG_STRICT},
+{ "fneg",	0x3000c000, 0xfc1fe7e0, "Ffa,fT", pa20, FLAG_STRICT},
+{ "fneg",	0x3800c000, 0xfc1fe720, "IfA,fT", pa20, FLAG_STRICT},
+{ "fnegabs",	0x3000e000, 0xfc1fe7e0, "Ffa,fT", pa20, FLAG_STRICT},
+{ "fnegabs",	0x3800e000, 0xfc1fe720, "IfA,fT", pa20, FLAG_STRICT},
+{ "fcnv",	0x30000200, 0xfc1c0720, "{_fa,fT", pa20, FLAG_STRICT},
+{ "fcnv",	0x38000200, 0xfc1c0720, "FGfA,fT", pa20, FLAG_STRICT},
+{ "fcmp",	0x30000400, 0xfc00e7e0, "F?ffa,fb", pa10, FLAG_STRICT},
+{ "fcmp",	0x38000400, 0xfc00e720, "I?ffA,fB", pa10, FLAG_STRICT},
+{ "fcmp",	0x30000400, 0xfc0007e0, "F?ffa,fb,h", pa20, FLAG_STRICT},
+{ "fcmp",	0x38000400, 0xfc000720, "I?ffA,fB,h", pa20, FLAG_STRICT},
+{ "fcmp",	0x30000400, 0xfc00e7e0, "F?ffa,fb", pa10, 0},
+{ "fcmp",	0x38000400, 0xfc00e720, "I?ffA,fB", pa10, 0},
+{ "xmpyu",	0x38004700, 0xfc00e720, "fX,fB,fT", pa11, 0},
+{ "fmpyadd",	0x18000000, 0xfc000000, "Hfi,fj,fk,fl,fm", pa11, 0},
+{ "fmpysub",	0x98000000, 0xfc000000, "Hfi,fj,fk,fl,fm", pa11, 0},
+{ "ftest",	0x30002420, 0xffffffff, "", pa10, FLAG_STRICT},
+{ "ftest",	0x30002420, 0xffffffe0, ",=", pa20, FLAG_STRICT},
+{ "ftest",	0x30000420, 0xffff1fff, "m", pa20, FLAG_STRICT},
+{ "fid",	0x30000000, 0xffffffff, "", pa11, 0},
+
+/* Performance Monitor Instructions.  */
+
+{ "pmdis",	0x30000280, 0xffffffdf, "N", pa20, FLAG_STRICT},
+{ "pmenb",	0x30000680, 0xffffffff, "", pa20, FLAG_STRICT},
+
+/* Assist Instructions.  */
+
+{ "spop0",	0x10000000, 0xfc000600, "v,ON", pa10, 0},
+{ "spop1",	0x10000200, 0xfc000600, "v,oNt", pa10, 0},
+{ "spop2",	0x10000400, 0xfc000600, "v,1Nb", pa10, 0},
+{ "spop3",	0x10000600, 0xfc000600, "v,0Nx,b", pa10, 0},
+{ "copr",	0x30000000, 0xfc000000, "u,2N", pa10, 0},
+{ "cldw",	0x24000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "cldw",	0x24000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "cldw",	0x24000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "cldw",	0x24000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "cldw",	0x24001000, 0xfc00d200, "ucocc@(b),t", pa20, FLAG_STRICT},
+{ "cldw",	0x24001000, 0xfc001200, "ucocc@(s,b),t", pa20, FLAG_STRICT},
+{ "cldw",	0x24001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldw",	0x24001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldw",	0x24001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldw",	0x24001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cldd",	0x2c000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "cldd",	0x2c000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "cldd",	0x2c000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "cldd",	0x2c000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "cldd",	0x2c001000, 0xfc00d200, "ucocc@(b),t", pa20, FLAG_STRICT},
+{ "cldd",	0x2c001000, 0xfc001200, "ucocc@(s,b),t", pa20, FLAG_STRICT},
+{ "cldd",	0x2c001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldd",	0x2c001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldd",	0x2c001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldd",	0x2c001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cstw",	0x24000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstw",	0x24000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstw",	0x24000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstw",	0x24000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstw",	0x24001200, 0xfc00d200, "ucocCt,@(b)", pa20, FLAG_STRICT},
+{ "cstw",	0x24001200, 0xfc001200, "ucocCt,@(s,b)", pa20, FLAG_STRICT},
+{ "cstw",	0x24001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstw",	0x24001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstw",	0x24001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstw",	0x24001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cstd",	0x2c000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstd",	0x2c000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstd",	0x2c000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstd",	0x2c000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstd",	0x2c001200, 0xfc00d200, "ucocCt,@(b)", pa20, FLAG_STRICT},
+{ "cstd",	0x2c001200, 0xfc001200, "ucocCt,@(s,b)", pa20, FLAG_STRICT},
+{ "cstd",	0x2c001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstd",	0x2c001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstd",	0x2c001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstd",	0x2c001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cldwx",	0x24000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "cldwx",	0x24000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "cldwx",	0x24000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "cldwx",	0x24000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "cldwx",	0x24000000, 0xfc00de00, "ucXx(b),t", pa10, 0},
+{ "cldwx",	0x24000000, 0xfc001e00, "ucXx(s,b),t", pa10, 0},
+{ "clddx",	0x2c000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "clddx",	0x2c000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "clddx",	0x2c000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "clddx",	0x2c000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "clddx",	0x2c000000, 0xfc00de00, "ucXx(b),t", pa10, 0},
+{ "clddx",	0x2c000000, 0xfc001e00, "ucXx(s,b),t", pa10, 0},
+{ "cstwx",	0x24000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstwx",	0x24000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstwx",	0x24000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstwx",	0x24000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstwx",	0x24000200, 0xfc00de00, "ucXt,x(b)", pa10, 0},
+{ "cstwx",	0x24000200, 0xfc001e00, "ucXt,x(s,b)", pa10, 0},
+{ "cstdx",	0x2c000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstdx",	0x2c000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstdx",	0x2c000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstdx",	0x2c000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstdx",	0x2c000200, 0xfc00de00, "ucXt,x(b)", pa10, 0},
+{ "cstdx",	0x2c000200, 0xfc001e00, "ucXt,x(s,b)", pa10, 0},
+{ "cldws",	0x24001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldws",	0x24001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldws",	0x24001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldws",	0x24001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cldws",	0x24001000, 0xfc00de00, "ucM5(b),t", pa10, 0},
+{ "cldws",	0x24001000, 0xfc001e00, "ucM5(s,b),t", pa10, 0},
+{ "cldds",	0x2c001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldds",	0x2c001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldds",	0x2c001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldds",	0x2c001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cldds",	0x2c001000, 0xfc00de00, "ucM5(b),t", pa10, 0},
+{ "cldds",	0x2c001000, 0xfc001e00, "ucM5(s,b),t", pa10, 0},
+{ "cstws",	0x24001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstws",	0x24001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstws",	0x24001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstws",	0x24001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cstws",	0x24001200, 0xfc00de00, "ucMt,5(b)", pa10, 0},
+{ "cstws",	0x24001200, 0xfc001e00, "ucMt,5(s,b)", pa10, 0},
+{ "cstds",	0x2c001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstds",	0x2c001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstds",	0x2c001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstds",	0x2c001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cstds",	0x2c001200, 0xfc00de00, "ucMt,5(b)", pa10, 0},
+{ "cstds",	0x2c001200, 0xfc001e00, "ucMt,5(s,b)", pa10, 0},
+
+/* More pseudo instructions which must follow the main table.  */
+{ "call",	0xe800f000, 0xfc1ffffd, "n(b)", pa20, FLAG_STRICT},
+{ "call",	0xe800a000, 0xffe0e000, "nW", pa10, FLAG_STRICT},
+{ "ret",	0xe840d000, 0xfffffffd, "n", pa20, FLAG_STRICT},
+
+};
+
+#define NUMOPCODES ((sizeof pa_opcodes)/(sizeof pa_opcodes[0]))
+
+/* SKV 12/18/92. Added some denotations for various operands.  */
+
+#define PA_IMM11_AT_31 'i'
+#define PA_IMM14_AT_31 'j'
+#define PA_IMM21_AT_31 'k'
+#define PA_DISP12 'w'
+#define PA_DISP17 'W'
+
+#define N_HPPA_OPERAND_FORMATS 5
+
+/* Integer register names, indexed by the numbers which appear in the
+   opcodes.  */
+static const char *const reg_names[] =
+{
+  "flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+  "r20", "r21", "r22", "r23", "r24", "r25", "r26", "dp", "ret0", "ret1",
+  "sp", "r31"
+};
+
+/* Floating point register names, indexed by the numbers which appear in the
+   opcodes.  */
+static const char *const fp_reg_names[] =
+{
+  "fpsr", "fpe2", "fpe4", "fpe6",
+  "fr4", "fr5", "fr6", "fr7", "fr8",
+  "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
+  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31"
+};
+
+typedef unsigned int CORE_ADDR;
+
+/* Get at various relevent fields of an instruction word.  */
+
+#define MASK_5  0x1f
+#define MASK_10 0x3ff
+#define MASK_11 0x7ff
+#define MASK_14 0x3fff
+#define MASK_16 0xffff
+#define MASK_21 0x1fffff
+
+/* These macros get bit fields using HP's numbering (MSB = 0).  */
+
+#define GET_FIELD(X, FROM, TO) \
+  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
+
+#define GET_BIT(X, WHICH) \
+  GET_FIELD (X, WHICH, WHICH)
+
+/* Some of these have been converted to 2-d arrays because they
+   consume less storage this way.  If the maintenance becomes a
+   problem, convert them back to const 1-d pointer arrays.  */
+static const char *const control_reg[] =
+{
+  "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+  "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
+  "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
+  "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
+  "tr4", "tr5", "tr6", "tr7"
+};
+
+static const char *const compare_cond_names[] =
+{
+  "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv", ",od",
+  ",tr", ",<>", ",>=", ",>", ",>>=", ",>>", ",nsv", ",ev"
+};
+static const char *const compare_cond_64_names[] =
+{
+  "", ",*=", ",*<", ",*<=", ",*<<", ",*<<=", ",*sv", ",*od",
+  ",*tr", ",*<>", ",*>=", ",*>", ",*>>=", ",*>>", ",*nsv", ",*ev"
+};
+static const char *const cmpib_cond_64_names[] =
+{
+  ",*<<", ",*=", ",*<", ",*<=", ",*>>=", ",*<>", ",*>=", ",*>"
+};
+static const char *const add_cond_names[] =
+{
+  "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv", ",od",
+  ",tr", ",<>", ",>=", ",>", ",uv", ",vnz", ",nsv", ",ev"
+};
+static const char *const add_cond_64_names[] =
+{
+  "", ",*=", ",*<", ",*<=", ",*nuv", ",*znv", ",*sv", ",*od",
+  ",*tr", ",*<>", ",*>=", ",*>", ",*uv", ",*vnz", ",*nsv", ",*ev"
+};
+static const char *const wide_add_cond_names[] =
+{
+  "", ",=", ",<", ",<=", ",nuv", ",*=", ",*<", ",*<=",
+  ",tr", ",<>", ",>=", ",>", ",uv", ",*<>", ",*>=", ",*>"
+};
+static const char *const logical_cond_names[] =
+{
+  "", ",=", ",<", ",<=", 0, 0, 0, ",od",
+  ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
+static const char *const logical_cond_64_names[] =
+{
+  "", ",*=", ",*<", ",*<=", 0, 0, 0, ",*od",
+  ",*tr", ",*<>", ",*>=", ",*>", 0, 0, 0, ",*ev"};
+static const char *const unit_cond_names[] =
+{
+  "", ",swz", ",sbz", ",shz", ",sdc", ",swc", ",sbc", ",shc",
+  ",tr", ",nwz", ",nbz", ",nhz", ",ndc", ",nwc", ",nbc", ",nhc"
+};
+static const char *const unit_cond_64_names[] =
+{
+  "", ",*swz", ",*sbz", ",*shz", ",*sdc", ",*swc", ",*sbc", ",*shc",
+  ",*tr", ",*nwz", ",*nbz", ",*nhz", ",*ndc", ",*nwc", ",*nbc", ",*nhc"
+};
+static const char *const shift_cond_names[] =
+{
+  "", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"
+};
+static const char *const shift_cond_64_names[] =
+{
+  "", ",*=", ",*<", ",*od", ",*tr", ",*<>", ",*>=", ",*ev"
+};
+static const char *const bb_cond_64_names[] =
+{
+  ",*<", ",*>="
+};
+static const char *const index_compl_names[] = {"", ",m", ",s", ",sm"};
+static const char *const short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
+static const char *const short_bytes_compl_names[] =
+{
+  "", ",b,m", ",e", ",e,m"
+};
+static const char *const float_format_names[] = {",sgl", ",dbl", "", ",quad"};
+static const char *const fcnv_fixed_names[] = {",w", ",dw", "", ",qw"};
+static const char *const fcnv_ufixed_names[] = {",uw", ",udw", "", ",uqw"};
+static const char *const float_comp_names[] =
+{
+  ",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
+  ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
+  ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
+  ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
+};
+static const char *const signed_unsigned_names[] = {",u", ",s"};
+static const char *const mix_half_names[] = {",l", ",r"};
+static const char *const saturation_names[] = {",us", ",ss", 0, ""};
+static const char *const read_write_names[] = {",r", ",w"};
+static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
+
+/* For a bunch of different instructions form an index into a
+   completer name table.  */
+#define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
+			 GET_FIELD (insn, 18, 18) << 1)
+
+#define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
+			(GET_FIELD ((insn), 19, 19) ? 8 : 0))
+
+/* Utility function to print registers.  Put these first, so gcc's function
+   inlining can do its stuff.  */
+
+#define fputs_filtered(STR,F)	(*info->fprintf_func) (info->stream, "%s", STR)
+
+static void
+fput_reg (unsigned reg, disassemble_info *info)
+{
+  (*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
+}
+
+static void
+fput_fp_reg (unsigned reg, disassemble_info *info)
+{
+  (*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
+}
+
+static void
+fput_fp_reg_r (unsigned reg, disassemble_info *info)
+{
+  /* Special case floating point exception registers.  */
+  if (reg < 4)
+    (*info->fprintf_func) (info->stream, "fpe%d", reg * 2 + 1);
+  else
+    (*info->fprintf_func) (info->stream, "%sR",
+			   reg ? fp_reg_names[reg] : "fr0");
+}
+
+static void
+fput_creg (unsigned reg, disassemble_info *info)
+{
+  (*info->fprintf_func) (info->stream, control_reg[reg]);
+}
+
+/* Print constants with sign.  */
+
+static void
+fput_const (unsigned num, disassemble_info *info)
+{
+  if ((int) num < 0)
+    (*info->fprintf_func) (info->stream, "-%x", - (int) num);
+  else
+    (*info->fprintf_func) (info->stream, "%x", num);
+}
+
+/* Routines to extract various sized constants out of hppa
+   instructions.  */
+
+/* Extract a 3-bit space register number from a be, ble, mtsp or mfsp.  */
+static int
+extract_3 (unsigned word)
+{
+  return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+
+static int
+extract_5_load (unsigned word)
+{
+  return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+/* Extract the immediate field from a st{bhw}s instruction.  */
+
+static int
+extract_5_store (unsigned word)
+{
+  return low_sign_extend (word & MASK_5, 5);
+}
+
+/* Extract the immediate field from a break instruction.  */
+
+static unsigned
+extract_5r_store (unsigned word)
+{
+  return (word & MASK_5);
+}
+
+/* Extract the immediate field from a {sr}sm instruction.  */
+
+static unsigned
+extract_5R_store (unsigned word)
+{
+  return (word >> 16 & MASK_5);
+}
+
+/* Extract the 10 bit immediate field from a {sr}sm instruction.  */
+
+static unsigned
+extract_10U_store (unsigned word)
+{
+  return (word >> 16 & MASK_10);
+}
+
+/* Extract the immediate field from a bb instruction.  */
+
+static unsigned
+extract_5Q_store (unsigned word)
+{
+  return (word >> 21 & MASK_5);
+}
+
+/* Extract an 11 bit immediate field.  */
+
+static int
+extract_11 (unsigned word)
+{
+  return low_sign_extend (word & MASK_11, 11);
+}
+
+/* Extract a 14 bit immediate field.  */
+
+static int
+extract_14 (unsigned word)
+{
+  return low_sign_extend (word & MASK_14, 14);
+}
+
+/* Extract a 16 bit immediate field (PA2.0 wide only).  */
+
+static int
+extract_16 (unsigned word)
+{
+  int m15, m0, m1;
+
+  m0 = GET_BIT (word, 16);
+  m1 = GET_BIT (word, 17);
+  m15 = GET_BIT (word, 31);
+  word = (word >> 1) & 0x1fff;
+  word = word | (m15 << 15) | ((m15 ^ m0) << 14) | ((m15 ^ m1) << 13);
+  return sign_extend (word, 16);
+}
+
+/* Extract a 21 bit constant.  */
+
+static int
+extract_21 (unsigned word)
+{
+  int val;
+
+  word &= MASK_21;
+  word <<= 11;
+  val = GET_FIELD (word, 20, 20);
+  val <<= 11;
+  val |= GET_FIELD (word, 9, 19);
+  val <<= 2;
+  val |= GET_FIELD (word, 5, 6);
+  val <<= 5;
+  val |= GET_FIELD (word, 0, 4);
+  val <<= 2;
+  val |= GET_FIELD (word, 7, 8);
+  return sign_extend (val, 21) << 11;
+}
+
+/* Extract a 12 bit constant from branch instructions.  */
+
+static int
+extract_12 (unsigned word)
+{
+  return sign_extend (GET_FIELD (word, 19, 28)
+		      | GET_FIELD (word, 29, 29) << 10
+		      | (word & 0x1) << 11, 12) << 2;
+}
+
+/* Extract a 17 bit constant from branch instructions, returning the
+   19 bit signed value.  */
+
+static int
+extract_17 (unsigned word)
+{
+  return sign_extend (GET_FIELD (word, 19, 28)
+		      | GET_FIELD (word, 29, 29) << 10
+		      | GET_FIELD (word, 11, 15) << 11
+		      | (word & 0x1) << 16, 17) << 2;
+}
+
+static int
+extract_22 (unsigned word)
+{
+  return sign_extend (GET_FIELD (word, 19, 28)
+		      | GET_FIELD (word, 29, 29) << 10
+		      | GET_FIELD (word, 11, 15) << 11
+		      | GET_FIELD (word, 6, 10) << 16
+		      | (word & 0x1) << 21, 22) << 2;
+}
+
+/* Print one instruction.  */
+
+int
+print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
+{
+  bfd_byte buffer[4];
+  unsigned int insn, i;
+
+  {
+    int status =
+      (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
+    if (status != 0)
+      {
+	(*info->memory_error_func) (status, memaddr, info);
+	return -1;
+      }
+  }
+
+  insn = bfd_getb32 (buffer);
+
+  for (i = 0; i < NUMOPCODES; ++i)
+    {
+      const struct pa_opcode *opcode = &pa_opcodes[i];
+
+      if ((insn & opcode->mask) == opcode->match)
+	{
+	  const char *s;
+#ifndef BFD64
+	  if (opcode->arch == pa20w)
+	    continue;
+#endif
+	  (*info->fprintf_func) (info->stream, "%s", opcode->name);
+
+	  if (!strchr ("cfCY?-+nHNZFIuv{", opcode->args[0]))
+	    (*info->fprintf_func) (info->stream, " ");
+	  for (s = opcode->args; *s != '\0'; ++s)
+	    {
+	      switch (*s)
+		{
+		case 'x':
+		  fput_reg (GET_FIELD (insn, 11, 15), info);
+		  break;
+		case 'a':
+		case 'b':
+		  fput_reg (GET_FIELD (insn, 6, 10), info);
+		  break;
+		case '^':
+		  fput_creg (GET_FIELD (insn, 6, 10), info);
+		  break;
+		case 't':
+		  fput_reg (GET_FIELD (insn, 27, 31), info);
+		  break;
+
+		  /* Handle floating point registers.  */
+		case 'f':
+		  switch (*++s)
+		    {
+		    case 't':
+		      fput_fp_reg (GET_FIELD (insn, 27, 31), info);
+		      break;
+		    case 'T':
+		      if (GET_FIELD (insn, 25, 25))
+			fput_fp_reg_r (GET_FIELD (insn, 27, 31), info);
+		      else
+			fput_fp_reg (GET_FIELD (insn, 27, 31), info);
+		      break;
+		    case 'a':
+		      if (GET_FIELD (insn, 25, 25))
+			fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
+		      else
+			fput_fp_reg (GET_FIELD (insn, 6, 10), info);
+		      break;
+
+		      /* 'fA' will not generate a space before the regsiter
+			 name.  Normally that is fine.  Except that it
+			 causes problems with xmpyu which has no FP format
+			 completer.  */
+		    case 'X':
+		      fputs_filtered (" ", info);
+		      /* FALLTHRU */
+
+		    case 'A':
+		      if (GET_FIELD (insn, 24, 24))
+			fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
+		      else
+			fput_fp_reg (GET_FIELD (insn, 6, 10), info);
+		      break;
+		    case 'b':
+		      if (GET_FIELD (insn, 25, 25))
+			fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
+		      else
+			fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+		      break;
+		    case 'B':
+		      if (GET_FIELD (insn, 19, 19))
+			fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
+		      else
+			fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+		      break;
+		    case 'C':
+		      {
+			int reg = GET_FIELD (insn, 21, 22);
+			reg |= GET_FIELD (insn, 16, 18) << 2;
+			if (GET_FIELD (insn, 23, 23) != 0)
+			  fput_fp_reg_r (reg, info);
+			else
+			  fput_fp_reg (reg, info);
+			break;
+		      }
+		    case 'i':
+		      {
+			int reg = GET_FIELD (insn, 6, 10);
+
+			reg |= (GET_FIELD (insn, 26, 26) << 4);
+			fput_fp_reg (reg, info);
+			break;
+		      }
+		    case 'j':
+		      {
+			int reg = GET_FIELD (insn, 11, 15);
+
+			reg |= (GET_FIELD (insn, 26, 26) << 4);
+			fput_fp_reg (reg, info);
+			break;
+		      }
+		    case 'k':
+		      {
+			int reg = GET_FIELD (insn, 27, 31);
+
+			reg |= (GET_FIELD (insn, 26, 26) << 4);
+			fput_fp_reg (reg, info);
+			break;
+		      }
+		    case 'l':
+		      {
+			int reg = GET_FIELD (insn, 21, 25);
+
+			reg |= (GET_FIELD (insn, 26, 26) << 4);
+			fput_fp_reg (reg, info);
+			break;
+		      }
+		    case 'm':
+		      {
+			int reg = GET_FIELD (insn, 16, 20);
+
+			reg |= (GET_FIELD (insn, 26, 26) << 4);
+			fput_fp_reg (reg, info);
+			break;
+		      }
+
+		      /* 'fe' will not generate a space before the register
+			 name.  Normally that is fine.  Except that it
+			 causes problems with fstw fe,y(b) which has no FP
+			 format completer.  */
+		    case 'E':
+		      fputs_filtered (" ", info);
+		      /* FALLTHRU */
+
+		    case 'e':
+		      if (GET_FIELD (insn, 30, 30))
+			fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
+		      else
+			fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+		      break;
+		    case 'x':
+		      fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+		      break;
+		    }
+		  break;
+
+		case '5':
+		  fput_const (extract_5_load (insn), info);
+		  break;
+		case 's':
+		  {
+		    int space = GET_FIELD (insn, 16, 17);
+		    /* Zero means implicit addressing, not use of sr0.  */
+		    if (space != 0)
+		      (*info->fprintf_func) (info->stream, "sr%d", space);
+		  }
+		  break;
+
+		case 'S':
+		  (*info->fprintf_func) (info->stream, "sr%d",
+					 extract_3 (insn));
+		  break;
+
+		  /* Handle completers.  */
+		case 'c':
+		  switch (*++s)
+		    {
+		    case 'x':
+		      (*info->fprintf_func)
+			(info->stream, "%s",
+			 index_compl_names[GET_COMPL (insn)]);
+		      break;
+		    case 'X':
+		      (*info->fprintf_func)
+			(info->stream, "%s ",
+			 index_compl_names[GET_COMPL (insn)]);
+		      break;
+		    case 'm':
+		      (*info->fprintf_func)
+			(info->stream, "%s",
+			 short_ldst_compl_names[GET_COMPL (insn)]);
+		      break;
+		    case 'M':
+		      (*info->fprintf_func)
+			(info->stream, "%s ",
+			 short_ldst_compl_names[GET_COMPL (insn)]);
+		      break;
+		    case 'A':
+		      (*info->fprintf_func)
+			(info->stream, "%s ",
+			 short_bytes_compl_names[GET_COMPL (insn)]);
+		      break;
+		    case 's':
+		      (*info->fprintf_func)
+			(info->stream, "%s",
+			 short_bytes_compl_names[GET_COMPL (insn)]);
+		      break;
+		    case 'c':
+		    case 'C':
+		      switch (GET_FIELD (insn, 20, 21))
+			{
+			case 1:
+			  (*info->fprintf_func) (info->stream, ",bc ");
+			  break;
+			case 2:
+			  (*info->fprintf_func) (info->stream, ",sl ");
+			  break;
+			default:
+			  (*info->fprintf_func) (info->stream, " ");
+			}
+		      break;
+		    case 'd':
+		      switch (GET_FIELD (insn, 20, 21))
+			{
+			case 1:
+			  (*info->fprintf_func) (info->stream, ",co ");
+			  break;
+			default:
+			  (*info->fprintf_func) (info->stream, " ");
+			}
+		      break;
+		    case 'o':
+		      (*info->fprintf_func) (info->stream, ",o");
+		      break;
+		    case 'g':
+		      (*info->fprintf_func) (info->stream, ",gate");
+		      break;
+		    case 'p':
+		      (*info->fprintf_func) (info->stream, ",l,push");
+		      break;
+		    case 'P':
+		      (*info->fprintf_func) (info->stream, ",pop");
+		      break;
+		    case 'l':
+		    case 'L':
+		      (*info->fprintf_func) (info->stream, ",l");
+		      break;
+		    case 'w':
+		      (*info->fprintf_func)
+			(info->stream, "%s ",
+			 read_write_names[GET_FIELD (insn, 25, 25)]);
+		      break;
+		    case 'W':
+		      (*info->fprintf_func) (info->stream, ",w ");
+		      break;
+		    case 'r':
+		      if (GET_FIELD (insn, 23, 26) == 5)
+			(*info->fprintf_func) (info->stream, ",r");
+		      break;
+		    case 'Z':
+		      if (GET_FIELD (insn, 26, 26))
+			(*info->fprintf_func) (info->stream, ",m ");
+		      else
+			(*info->fprintf_func) (info->stream, " ");
+		      break;
+		    case 'i':
+		      if (GET_FIELD (insn, 25, 25))
+			(*info->fprintf_func) (info->stream, ",i");
+		      break;
+		    case 'z':
+		      if (!GET_FIELD (insn, 21, 21))
+			(*info->fprintf_func) (info->stream, ",z");
+		      break;
+		    case 'a':
+		      (*info->fprintf_func)
+			(info->stream, "%s",
+			 add_compl_names[GET_FIELD (insn, 20, 21)]);
+		      break;
+		    case 'Y':
+		      (*info->fprintf_func)
+			(info->stream, ",dc%s",
+			 add_compl_names[GET_FIELD (insn, 20, 21)]);
+		      break;
+		    case 'y':
+		      (*info->fprintf_func)
+			(info->stream, ",c%s",
+			 add_compl_names[GET_FIELD (insn, 20, 21)]);
+		      break;
+		    case 'v':
+		      if (GET_FIELD (insn, 20, 20))
+			(*info->fprintf_func) (info->stream, ",tsv");
+		      break;
+		    case 't':
+		      (*info->fprintf_func) (info->stream, ",tc");
+		      if (GET_FIELD (insn, 20, 20))
+			(*info->fprintf_func) (info->stream, ",tsv");
+		      break;
+		    case 'B':
+		      (*info->fprintf_func) (info->stream, ",db");
+		      if (GET_FIELD (insn, 20, 20))
+			(*info->fprintf_func) (info->stream, ",tsv");
+		      break;
+		    case 'b':
+		      (*info->fprintf_func) (info->stream, ",b");
+		      if (GET_FIELD (insn, 20, 20))
+			(*info->fprintf_func) (info->stream, ",tsv");
+		      break;
+		    case 'T':
+		      if (GET_FIELD (insn, 25, 25))
+			(*info->fprintf_func) (info->stream, ",tc");
+		      break;
+		    case 'S':
+		      /* EXTRD/W has a following condition.  */
+		      if (*(s + 1) == '?')
+			(*info->fprintf_func)
+			  (info->stream, "%s",
+			   signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
+		      else
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
+		      break;
+		    case 'h':
+		      (*info->fprintf_func)
+			(info->stream, "%s",
+			 mix_half_names[GET_FIELD (insn, 17, 17)]);
+		      break;
+		    case 'H':
+		      (*info->fprintf_func)
+			(info->stream, "%s ",
+			 saturation_names[GET_FIELD (insn, 24, 25)]);
+		      break;
+		    case '*':
+		      (*info->fprintf_func)
+			(info->stream, ",%d%d%d%d ",
+			 GET_FIELD (insn, 17, 18), GET_FIELD (insn, 20, 21),
+			 GET_FIELD (insn, 22, 23), GET_FIELD (insn, 24, 25));
+		      break;
+
+		    case 'q':
+		      {
+			int m, a;
+
+			m = GET_FIELD (insn, 28, 28);
+			a = GET_FIELD (insn, 29, 29);
+
+			if (m && !a)
+			  fputs_filtered (",ma ", info);
+			else if (m && a)
+			  fputs_filtered (",mb ", info);
+			else
+			  fputs_filtered (" ", info);
+			break;
+		      }
+
+		    case 'J':
+		      {
+			int opc = GET_FIELD (insn, 0, 5);
+
+			if (opc == 0x16 || opc == 0x1e)
+			  {
+			    if (GET_FIELD (insn, 29, 29) == 0)
+			      fputs_filtered (",ma ", info);
+			    else
+			      fputs_filtered (",mb ", info);
+			  }
+			else
+			  fputs_filtered (" ", info);
+			break;
+		      }
+
+		    case 'e':
+		      {
+			int opc = GET_FIELD (insn, 0, 5);
+
+			if (opc == 0x13 || opc == 0x1b)
+			  {
+			    if (GET_FIELD (insn, 18, 18) == 1)
+			      fputs_filtered (",mb ", info);
+			    else
+			      fputs_filtered (",ma ", info);
+			  }
+			else if (opc == 0x17 || opc == 0x1f)
+			  {
+			    if (GET_FIELD (insn, 31, 31) == 1)
+			      fputs_filtered (",ma ", info);
+			    else
+			      fputs_filtered (",mb ", info);
+			  }
+			else
+			  fputs_filtered (" ", info);
+
+			break;
+		      }
+		    }
+		  break;
+
+		  /* Handle conditions.  */
+		case '?':
+		  {
+		    s++;
+		    switch (*s)
+		      {
+		      case 'f':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   float_comp_names[GET_FIELD (insn, 27, 31)]);
+			break;
+
+			/* These four conditions are for the set of instructions
+			   which distinguish true/false conditions by opcode
+			   rather than by the 'f' bit (sigh): comb, comib,
+			   addb, addib.  */
+		      case 't':
+			fputs_filtered
+			  (compare_cond_names[GET_FIELD (insn, 16, 18)], info);
+			break;
+		      case 'n':
+			fputs_filtered
+			  (compare_cond_names[GET_FIELD (insn, 16, 18)
+					      + GET_FIELD (insn, 4, 4) * 8],
+			   info);
+			break;
+		      case 'N':
+			fputs_filtered
+			  (compare_cond_64_names[GET_FIELD (insn, 16, 18)
+						 + GET_FIELD (insn, 2, 2) * 8],
+			   info);
+			break;
+		      case 'Q':
+			fputs_filtered
+			  (cmpib_cond_64_names[GET_FIELD (insn, 16, 18)],
+			   info);
+			break;
+		      case '@':
+			fputs_filtered
+			  (add_cond_names[GET_FIELD (insn, 16, 18)
+					  + GET_FIELD (insn, 4, 4) * 8],
+			   info);
+			break;
+		      case 's':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   compare_cond_names[GET_COND (insn)]);
+			break;
+		      case 'S':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   compare_cond_64_names[GET_COND (insn)]);
+			break;
+		      case 'a':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   add_cond_names[GET_COND (insn)]);
+			break;
+		      case 'A':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   add_cond_64_names[GET_COND (insn)]);
+			break;
+		      case 'd':
+			(*info->fprintf_func)
+			  (info->stream, "%s",
+			   add_cond_names[GET_FIELD (insn, 16, 18)]);
+			break;
+
+		      case 'W':
+			(*info->fprintf_func)
+			  (info->stream, "%s",
+			   wide_add_cond_names[GET_FIELD (insn, 16, 18) +
+					       GET_FIELD (insn, 4, 4) * 8]);
+			break;
+
+		      case 'l':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   logical_cond_names[GET_COND (insn)]);
+			break;
+		      case 'L':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   logical_cond_64_names[GET_COND (insn)]);
+			break;
+		      case 'u':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   unit_cond_names[GET_COND (insn)]);
+			break;
+		      case 'U':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   unit_cond_64_names[GET_COND (insn)]);
+			break;
+		      case 'y':
+		      case 'x':
+		      case 'b':
+			(*info->fprintf_func)
+			  (info->stream, "%s",
+			   shift_cond_names[GET_FIELD (insn, 16, 18)]);
+
+			/* If the next character in args is 'n', it will handle
+			   putting out the space.  */
+			if (s[1] != 'n')
+			  (*info->fprintf_func) (info->stream, " ");
+			break;
+		      case 'X':
+			(*info->fprintf_func)
+			  (info->stream, "%s ",
+			   shift_cond_64_names[GET_FIELD (insn, 16, 18)]);
+			break;
+		      case 'B':
+			(*info->fprintf_func)
+			  (info->stream, "%s",
+			   bb_cond_64_names[GET_FIELD (insn, 16, 16)]);
+
+			/* If the next character in args is 'n', it will handle
+			   putting out the space.  */
+			if (s[1] != 'n')
+			  (*info->fprintf_func) (info->stream, " ");
+			break;
+		      }
+		    break;
+		  }
+
+		case 'V':
+		  fput_const (extract_5_store (insn), info);
+		  break;
+		case 'r':
+		  fput_const (extract_5r_store (insn), info);
+		  break;
+		case 'R':
+		  fput_const (extract_5R_store (insn), info);
+		  break;
+		case 'U':
+		  fput_const (extract_10U_store (insn), info);
+		  break;
+		case 'B':
+		case 'Q':
+		  fput_const (extract_5Q_store (insn), info);
+		  break;
+		case 'i':
+		  fput_const (extract_11 (insn), info);
+		  break;
+		case 'j':
+		  fput_const (extract_14 (insn), info);
+		  break;
+		case 'k':
+		  fputs_filtered ("L%", info);
+		  fput_const (extract_21 (insn), info);
+		  break;
+		case '<':
+		case 'l':
+		  /* 16-bit long disp., PA2.0 wide only.  */
+		  fput_const (extract_16 (insn), info);
+		  break;
+		case 'n':
+		  if (insn & 0x2)
+		    (*info->fprintf_func) (info->stream, ",n ");
+		  else
+		    (*info->fprintf_func) (info->stream, " ");
+		  break;
+		case 'N':
+		  if ((insn & 0x20) && s[1])
+		    (*info->fprintf_func) (info->stream, ",n ");
+		  else if (insn & 0x20)
+		    (*info->fprintf_func) (info->stream, ",n");
+		  else if (s[1])
+		    (*info->fprintf_func) (info->stream, " ");
+		  break;
+		case 'w':
+		  (*info->print_address_func)
+		    (memaddr + 8 + extract_12 (insn), info);
+		  break;
+		case 'W':
+		  /* 17 bit PC-relative branch.  */
+		  (*info->print_address_func)
+		    ((memaddr + 8 + extract_17 (insn)), info);
+		  break;
+		case 'z':
+		  /* 17 bit displacement.  This is an offset from a register
+		     so it gets disasssembled as just a number, not any sort
+		     of address.  */
+		  fput_const (extract_17 (insn), info);
+		  break;
+
+		case 'Z':
+		  /* addil %r1 implicit output.  */
+		  fputs_filtered ("r1", info);
+		  break;
+
+		case 'Y':
+		  /* be,l %sr0,%r31 implicit output.  */
+		  fputs_filtered ("sr0,r31", info);
+		  break;
+
+		case '@':
+		  (*info->fprintf_func) (info->stream, "0");
+		  break;
+
+		case '.':
+		  (*info->fprintf_func) (info->stream, "%d",
+					 GET_FIELD (insn, 24, 25));
+		  break;
+		case '*':
+		  (*info->fprintf_func) (info->stream, "%d",
+					 GET_FIELD (insn, 22, 25));
+		  break;
+		case '!':
+		  fputs_filtered ("sar", info);
+		  break;
+		case 'p':
+		  (*info->fprintf_func) (info->stream, "%d",
+					 31 - GET_FIELD (insn, 22, 26));
+		  break;
+		case '~':
+		  {
+		    int num;
+		    num = GET_FIELD (insn, 20, 20) << 5;
+		    num |= GET_FIELD (insn, 22, 26);
+		    (*info->fprintf_func) (info->stream, "%d", 63 - num);
+		    break;
+		  }
+		case 'P':
+		  (*info->fprintf_func) (info->stream, "%d",
+					 GET_FIELD (insn, 22, 26));
+		  break;
+		case 'q':
+		  {
+		    int num;
+		    num = GET_FIELD (insn, 20, 20) << 5;
+		    num |= GET_FIELD (insn, 22, 26);
+		    (*info->fprintf_func) (info->stream, "%d", num);
+		    break;
+		  }
+		case 'T':
+		  (*info->fprintf_func) (info->stream, "%d",
+					 32 - GET_FIELD (insn, 27, 31));
+		  break;
+		case '%':
+		  {
+		    int num;
+		    num = (GET_FIELD (insn, 23, 23) + 1) * 32;
+		    num -= GET_FIELD (insn, 27, 31);
+		    (*info->fprintf_func) (info->stream, "%d", num);
+		    break;
+		  }
+		case '|':
+		  {
+		    int num;
+		    num = (GET_FIELD (insn, 19, 19) + 1) * 32;
+		    num -= GET_FIELD (insn, 27, 31);
+		    (*info->fprintf_func) (info->stream, "%d", num);
+		    break;
+		  }
+		case '$':
+		  fput_const (GET_FIELD (insn, 20, 28), info);
+		  break;
+		case 'A':
+		  fput_const (GET_FIELD (insn, 6, 18), info);
+		  break;
+		case 'D':
+		  fput_const (GET_FIELD (insn, 6, 31), info);
+		  break;
+		case 'v':
+		  (*info->fprintf_func) (info->stream, ",%d",
+					 GET_FIELD (insn, 23, 25));
+		  break;
+		case 'O':
+		  fput_const ((GET_FIELD (insn, 6,20) << 5 |
+			       GET_FIELD (insn, 27, 31)), info);
+		  break;
+		case 'o':
+		  fput_const (GET_FIELD (insn, 6, 20), info);
+		  break;
+		case '2':
+		  fput_const ((GET_FIELD (insn, 6, 22) << 5 |
+			       GET_FIELD (insn, 27, 31)), info);
+		  break;
+		case '1':
+		  fput_const ((GET_FIELD (insn, 11, 20) << 5 |
+			       GET_FIELD (insn, 27, 31)), info);
+		  break;
+		case '0':
+		  fput_const ((GET_FIELD (insn, 16, 20) << 5 |
+			       GET_FIELD (insn, 27, 31)), info);
+		  break;
+		case 'u':
+		  (*info->fprintf_func) (info->stream, ",%d",
+					 GET_FIELD (insn, 23, 25));
+		  break;
+		case 'F':
+		  /* If no destination completer and not before a completer
+		     for fcmp, need a space here.  */
+		  if (s[1] == 'G' || s[1] == '?')
+		    fputs_filtered
+		      (float_format_names[GET_FIELD (insn, 19, 20)], info);
+		  else
+		    (*info->fprintf_func)
+		      (info->stream, "%s ",
+		       float_format_names[GET_FIELD (insn, 19, 20)]);
+		  break;
+		case 'G':
+		  (*info->fprintf_func)
+		    (info->stream, "%s ",
+		     float_format_names[GET_FIELD (insn, 17, 18)]);
+		  break;
+		case 'H':
+		  if (GET_FIELD (insn, 26, 26) == 1)
+		    (*info->fprintf_func) (info->stream, "%s ",
+					   float_format_names[0]);
+		  else
+		    (*info->fprintf_func) (info->stream, "%s ",
+					   float_format_names[1]);
+		  break;
+		case 'I':
+		  /* If no destination completer and not before a completer
+		     for fcmp, need a space here.  */
+		  if (s[1] == '?')
+		    fputs_filtered
+		      (float_format_names[GET_FIELD (insn, 20, 20)], info);
+		  else
+		    (*info->fprintf_func)
+		      (info->stream, "%s ",
+		       float_format_names[GET_FIELD (insn, 20, 20)]);
+		  break;
+
+		case 'J':
+		  fput_const (extract_14 (insn), info);
+		  break;
+
+		case '#':
+		  {
+		    int sign = GET_FIELD (insn, 31, 31);
+		    int imm10 = GET_FIELD (insn, 18, 27);
+		    int disp;
+
+		    if (sign)
+		      disp = (-1 << 10) | imm10;
+		    else
+		      disp = imm10;
+
+		    disp <<= 3;
+		    fput_const (disp, info);
+		    break;
+		  }
+		case 'K':
+		case 'd':
+		  {
+		    int sign = GET_FIELD (insn, 31, 31);
+		    int imm11 = GET_FIELD (insn, 18, 28);
+		    int disp;
+
+		    if (sign)
+		      disp = (-1 << 11) | imm11;
+		    else
+		      disp = imm11;
+
+		    disp <<= 2;
+		    fput_const (disp, info);
+		    break;
+		  }
+
+		case '>':
+		case 'y':
+		  {
+		    /* 16-bit long disp., PA2.0 wide only.  */
+		    int disp = extract_16 (insn);
+		    disp &= ~3;
+		    fput_const (disp, info);
+		    break;
+		  }
+
+		case '&':
+		  {
+		    /* 16-bit long disp., PA2.0 wide only.  */
+		    int disp = extract_16 (insn);
+		    disp &= ~7;
+		    fput_const (disp, info);
+		    break;
+		  }
+
+		case '_':
+		  break; /* Dealt with by '{' */
+
+		case '{':
+		  {
+		    int sub = GET_FIELD (insn, 14, 16);
+		    int df = GET_FIELD (insn, 17, 18);
+		    int sf = GET_FIELD (insn, 19, 20);
+		    const char * const * source = float_format_names;
+		    const char * const * dest = float_format_names;
+		    char *t = "";
+
+		    if (sub == 4)
+		      {
+			fputs_filtered (",UND ", info);
+			break;
+		      }
+		    if ((sub & 3) == 3)
+		      t = ",t";
+		    if ((sub & 3) == 1)
+		      source = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
+		    if (sub & 2)
+		      dest = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
+
+		    (*info->fprintf_func) (info->stream, "%s%s%s ",
+					   t, source[sf], dest[df]);
+		    break;
+		  }
+
+		case 'm':
+		  {
+		    int y = GET_FIELD (insn, 16, 18);
+
+		    if (y != 1)
+		      fput_const ((y ^ 1) - 1, info);
+		  }
+		  break;
+
+		case 'h':
+		  {
+		    int cbit;
+
+		    cbit = GET_FIELD (insn, 16, 18);
+
+		    if (cbit > 0)
+		      (*info->fprintf_func) (info->stream, ",%d", cbit - 1);
+		    break;
+		  }
+
+		case '=':
+		  {
+		    int cond = GET_FIELD (insn, 27, 31);
+
+		    switch (cond)
+		      {
+		      case  0: fputs_filtered (" ", info); break;
+		      case  1: fputs_filtered ("acc ", info); break;
+		      case  2: fputs_filtered ("rej ", info); break;
+		      case  5: fputs_filtered ("acc8 ", info); break;
+		      case  6: fputs_filtered ("rej8 ", info); break;
+		      case  9: fputs_filtered ("acc6 ", info); break;
+		      case 13: fputs_filtered ("acc4 ", info); break;
+		      case 17: fputs_filtered ("acc2 ", info); break;
+		      default: break;
+		      }
+		    break;
+		  }
+
+		case 'X':
+		  (*info->print_address_func)
+		    (memaddr + 8 + extract_22 (insn), info);
+		  break;
+		case 'L':
+		  fputs_filtered (",rp", info);
+		  break;
+		default:
+		  (*info->fprintf_func) (info->stream, "%c", *s);
+		  break;
+		}
+	    }
+	  return sizeof (insn);
+	}
+    }
+  (*info->fprintf_func) (info->stream, "#%8x", insn);
+  return sizeof (insn);
+}

+ 214 - 0
hppa.ld

@@ -0,0 +1,214 @@
+/* Default linker script, for normal executables */
+OUTPUT_FORMAT("elf32-hppa-linux", "elf32-hppa-linux",
+	      "elf32-hppa-linux")
+OUTPUT_ARCH(hppa:hppa1.1)
+ENTRY(_start)
+SEARCH_DIR("/usr/hppa-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.init       : { *(.rel.init) }
+  .rela.init      : { *(.rela.init) }
+  .rel.text       : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+  .rela.text      : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+  .rel.fini       : { *(.rel.fini) }
+  .rela.fini      : { *(.rela.fini) }
+  .rel.rodata     : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+  .rela.rodata    : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+  .rel.data.rel.ro   : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
+  .rela.data.rel.ro   : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
+  .rel.data       : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+  .rela.data      : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+  .rel.tdata	  : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+  .rela.tdata	  : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+  .rel.tbss	  : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+  .rela.tbss	  : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+  .rel.ctors      : { *(.rel.ctors) }
+  .rela.ctors     : { *(.rela.ctors) }
+  .rel.dtors      : { *(.rel.dtors) }
+  .rela.dtors     : { *(.rela.dtors) }
+  .rel.got        : { *(.rel.got) }
+  .rela.got       : { *(.rela.got) }
+  .rel.sdata      : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
+  .rela.sdata     : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
+  .rel.sbss       : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
+  .rela.sbss      : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
+  .rel.sdata2     : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
+  .rela.sdata2    : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
+  .rel.sbss2      : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
+  .rela.sbss2     : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
+  .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+  .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x08000240
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    KEEP (*(.text.*personality*))
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x08000240
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x08000240
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .sdata2         :
+  {
+    *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+  }
+  .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+  .PARISC.unwind   : { *(.PARISC.unwind) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN(0x10000) + (. & (0x10000 - 1));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+     PROVIDE_HIDDEN (__init_array_start = .);
+     KEEP (*(SORT(.init_array.*)))
+     KEEP (*(.init_array))
+     PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(.fini_array))
+    KEEP (*(SORT(.fini_array.*)))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin*.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin*.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .data           :
+  {
+    PROVIDE ($global$ = .);
+    *(.data .data.* .gnu.linkonce.d.*)
+    KEEP (*(.gnu.linkonce.d.*personality*))
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .plt            : { *(.plt) }
+  .got            : { *(.got.plt) *(.got) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata          :
+  {
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+  }
+  _edata = .; PROVIDE (edata = .);
+  __bss_start = .;
+  .sbss           :
+  {
+    *(.dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+  }
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 32 / 8 : 1);
+  }
+  . = ALIGN(32 / 8);
+  . = ALIGN(32 / 8);
+  _end = .; PROVIDE (end = .);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}

+ 980 - 0
tcg/hppa/tcg-target.c

@@ -0,0 +1,980 @@
+/*
+ * Tiny Code Generator for QEMU
+ *
+ * Copyright (c) 2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+    "%r0",
+    "%r1",
+    "%rp",
+    "%r3",
+    "%r4",
+    "%r5",
+    "%r6",
+    "%r7",
+    "%r8",
+    "%r9",
+    "%r10",
+    "%r11",
+    "%r12",
+    "%r13",
+    "%r14",
+    "%r15",
+    "%r16",
+    "%r17",
+    "%r18",
+    "%r19",
+    "%r20",
+    "%r21",
+    "%r22",
+    "%r23",
+    "%r24",
+    "%r25",
+    "%r26",
+    "%dp",
+    "%ret0",
+    "%ret1",
+    "%sp",
+    "%r31",
+};
+
+static const int tcg_target_reg_alloc_order[] = {
+    TCG_REG_R4,
+    TCG_REG_R5,
+    TCG_REG_R6,
+    TCG_REG_R7,
+    TCG_REG_R8,
+    TCG_REG_R9,
+    TCG_REG_R10,
+    TCG_REG_R11,
+    TCG_REG_R12,
+    TCG_REG_R13,
+
+    TCG_REG_R17,
+    TCG_REG_R14,
+    TCG_REG_R15,
+    TCG_REG_R16,
+};
+
+static const int tcg_target_call_iarg_regs[4] = {
+    TCG_REG_R26,
+    TCG_REG_R25,
+    TCG_REG_R24,
+    TCG_REG_R23,
+};
+
+static const int tcg_target_call_oarg_regs[2] = {
+    TCG_REG_RET0,
+    TCG_REG_RET1,
+};
+
+static void patch_reloc(uint8_t *code_ptr, int type,
+                        tcg_target_long value, tcg_target_long addend)
+{
+    switch (type) {
+    case R_PARISC_PCREL17F:
+        hppa_patch17f((uint32_t *)code_ptr, value, addend);
+        break;
+    default:
+        tcg_abort();
+    }
+}
+
+/* maximum number of register used for input function arguments */
+static inline int tcg_target_get_call_iarg_regs_count(int flags)
+{
+    return 4;
+}
+
+/* parse target specific constraints */
+int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+{
+    const char *ct_str;
+
+    ct_str = *pct_str;
+    switch (ct_str[0]) {
+    case 'r':
+        ct->ct |= TCG_CT_REG;
+        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
+        break;
+    case 'L': /* qemu_ld/st constraint */
+        ct->ct |= TCG_CT_REG;
+        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R26);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R25);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R24);
+        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R23);
+        break;
+    default:
+        return -1;
+    }
+    ct_str++;
+    *pct_str = ct_str;
+    return 0;
+}
+
+/* test if a constant matches the constraint */
+static inline int tcg_target_const_match(tcg_target_long val,
+                                         const TCGArgConstraint *arg_ct)
+{
+    int ct;
+
+    ct = arg_ct->ct;
+
+    /* TODO */
+
+    return 0;
+}
+
+#define INSN_OP(x)       ((x) << 26)
+#define INSN_EXT3BR(x)   ((x) << 13)
+#define INSN_EXT3SH(x)   ((x) << 10)
+#define INSN_EXT4(x)     ((x) << 6)
+#define INSN_EXT5(x)     (x)
+#define INSN_EXT6(x)     ((x) << 6)
+#define INSN_EXT7(x)     ((x) << 6)
+#define INSN_EXT8A(x)    ((x) << 6)
+#define INSN_EXT8B(x)    ((x) << 5)
+#define INSN_T(x)        (x)
+#define INSN_R1(x)       ((x) << 16)
+#define INSN_R2(x)       ((x) << 21)
+#define INSN_DEP_LEN(x)  (32 - (x))
+#define INSN_SHDEP_CP(x) ((31 - (x)) << 5)
+#define INSN_SHDEP_P(x)  ((x) << 5)
+#define INSN_COND(x)     ((x) << 13)
+
+#define COND_NEVER 0
+#define COND_EQUAL 1
+#define COND_LT    2
+#define COND_LTEQ  3
+#define COND_LTU   4
+#define COND_LTUEQ 5
+#define COND_SV    6
+#define COND_OD    7
+
+
+/* Logical ADD */
+#define ARITH_ADD  (INSN_OP(0x02) | INSN_EXT6(0x28))
+#define ARITH_AND  (INSN_OP(0x02) | INSN_EXT6(0x08))
+#define ARITH_OR   (INSN_OP(0x02) | INSN_EXT6(0x09))
+#define ARITH_XOR  (INSN_OP(0x02) | INSN_EXT6(0x0a))
+#define ARITH_SUB  (INSN_OP(0x02) | INSN_EXT6(0x10))
+
+#define SHD        (INSN_OP(0x34) | INSN_EXT3SH(2))
+#define VSHD       (INSN_OP(0x34) | INSN_EXT3SH(0))
+#define DEP        (INSN_OP(0x35) | INSN_EXT3SH(3))
+#define ZDEP       (INSN_OP(0x35) | INSN_EXT3SH(2))
+#define ZVDEP      (INSN_OP(0x35) | INSN_EXT3SH(0))
+#define EXTRU      (INSN_OP(0x34) | INSN_EXT3SH(6))
+#define EXTRS      (INSN_OP(0x34) | INSN_EXT3SH(7))
+#define VEXTRS     (INSN_OP(0x34) | INSN_EXT3SH(5))
+
+#define SUBI       (INSN_OP(0x25))
+#define MTCTL      (INSN_OP(0x00) | INSN_EXT8B(0xc2))
+
+#define BL         (INSN_OP(0x3a) | INSN_EXT3BR(0))
+#define BLE_SR4    (INSN_OP(0x39) | (1 << 13))
+#define BV         (INSN_OP(0x3a) | INSN_EXT3BR(6))
+#define BV_N       (INSN_OP(0x3a) | INSN_EXT3BR(6) | 2)
+#define LDIL       (INSN_OP(0x08))
+#define LDO        (INSN_OP(0x0d))
+
+#define LDB        (INSN_OP(0x10))
+#define LDH        (INSN_OP(0x11))
+#define LDW        (INSN_OP(0x12))
+#define LDWM       (INSN_OP(0x13))
+
+#define STB        (INSN_OP(0x18))
+#define STH        (INSN_OP(0x19))
+#define STW        (INSN_OP(0x1a))
+#define STWM       (INSN_OP(0x1b))
+
+#define COMBT      (INSN_OP(0x20))
+#define COMBF      (INSN_OP(0x22))
+
+static int lowsignext(uint32_t val, int start, int length)
+{
+    return (((val << 1) & ~(~0 << length)) |
+            ((val >> (length - 1)) & 1)) << start;
+}
+
+static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+{
+    /* PA1.1 defines COPY as OR r,0,t */
+    tcg_out32(s, ARITH_OR | INSN_T(ret) | INSN_R1(arg) | INSN_R2(TCG_REG_R0));
+
+    /* PA2.0 defines COPY as LDO 0(r),t
+     * but hppa-dis.c is unaware of this definition */
+    /* tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(arg) | reassemble_14(0)); */
+}
+
+static inline void tcg_out_movi(TCGContext *s, TCGType type,
+                                int ret, tcg_target_long arg)
+{
+    if (arg == (arg & 0x1fff)) {
+        tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(TCG_REG_R0) |
+                     reassemble_14(arg));
+    } else {
+        tcg_out32(s, LDIL | INSN_R2(ret) |
+                     reassemble_21(lrsel((uint32_t)arg, 0)));
+        if (arg & 0x7ff)
+            tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(ret) |
+                         reassemble_14(rrsel((uint32_t)arg, 0)));
+    }
+}
+
+static inline void tcg_out_ld_raw(TCGContext *s, int ret,
+                                  tcg_target_long arg)
+{
+    tcg_out32(s, LDIL | INSN_R2(ret) |
+                 reassemble_21(lrsel((uint32_t)arg, 0)));
+    tcg_out32(s, LDW | INSN_R1(ret) | INSN_R2(ret) |
+                 reassemble_14(rrsel((uint32_t)arg, 0)));
+}
+
+static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
+                                  tcg_target_long arg)
+{
+    tcg_out_ld_raw(s, ret, arg);
+}
+
+static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset,
+                                int op)
+{
+    if (offset == (offset & 0xfff))
+        tcg_out32(s, op | INSN_R1(ret) | INSN_R2(addr) |
+                 reassemble_14(offset));
+    else {
+        fprintf(stderr, "unimplemented %s with offset %d\n", __func__, offset);
+        tcg_abort();
+    }
+}
+
+static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
+                              int arg1, tcg_target_long arg2)
+{
+    fprintf(stderr, "unimplemented %s\n", __func__);
+    tcg_abort();
+}
+
+static inline void tcg_out_st(TCGContext *s, TCGType type, int ret,
+                              int arg1, tcg_target_long arg2)
+{
+    fprintf(stderr, "unimplemented %s\n", __func__);
+    tcg_abort();
+}
+
+static inline void tcg_out_arith(TCGContext *s, int t, int r1, int r2, int op)
+{
+    tcg_out32(s, op | INSN_T(t) | INSN_R1(r1) | INSN_R2(r2));
+}
+
+static inline void tcg_out_arithi(TCGContext *s, int t, int r1,
+                                  tcg_target_long val, int op)
+{
+    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, val);
+    tcg_out_arith(s, t, r1, TCG_REG_R20, op);
+}
+
+static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
+{
+    tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
+}
+
+static inline void tcg_out_nop(TCGContext *s)
+{
+    tcg_out32(s, ARITH_OR | INSN_T(TCG_REG_R0) | INSN_R1(TCG_REG_R0) |
+                 INSN_R2(TCG_REG_R0));
+}
+
+static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) {
+    tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) |
+                 INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
+}
+
+static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) {
+    tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) |
+                 INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
+}
+
+static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg) {
+    if(ret != arg)
+        tcg_out_mov(s, ret, arg);
+    tcg_out32(s, DEP | INSN_R2(ret) | INSN_R1(ret) |
+                 INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
+    tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(TCG_REG_R0) |
+                 INSN_R2(ret) | INSN_SHDEP_CP(8));
+}
+
+static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp) {
+    tcg_out32(s, SHD | INSN_T(temp) | INSN_R1(arg) |
+                 INSN_R2(arg) | INSN_SHDEP_CP(16));
+    tcg_out32(s, DEP | INSN_R2(temp) | INSN_R1(temp) |
+                 INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
+    tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(arg) |
+                 INSN_R2(temp) | INSN_SHDEP_CP(8));
+}
+
+static inline void tcg_out_call(TCGContext *s, void *func)
+{
+    uint32_t val = (uint32_t)__canonicalize_funcptr_for_compare(func);
+    tcg_out32(s, LDIL | INSN_R2(TCG_REG_R20) |
+                 reassemble_21(lrsel(val, 0)));
+    tcg_out32(s, BLE_SR4 | INSN_R2(TCG_REG_R20) |
+                 reassemble_17(rrsel(val, 0) >> 2));
+    tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
+}
+
+#if defined(CONFIG_SOFTMMU)
+extern void __ldb_mmu(void);
+extern void __ldw_mmu(void);
+extern void __ldl_mmu(void);
+extern void __ldq_mmu(void);
+
+extern void __stb_mmu(void);
+extern void __stw_mmu(void);
+extern void __stl_mmu(void);
+extern void __stq_mmu(void);
+
+static void *qemu_ld_helpers[4] = {
+    __ldb_mmu,
+    __ldw_mmu,
+    __ldl_mmu,
+    __ldq_mmu,
+};
+
+static void *qemu_st_helpers[4] = {
+    __stb_mmu,
+    __stw_mmu,
+    __stl_mmu,
+    __stq_mmu,
+};
+#endif
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+{
+    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
+#if defined(CONFIG_SOFTMMU)
+    uint32_t *label1_ptr, *label2_ptr;
+#endif
+#if TARGET_LONG_BITS == 64
+#if defined(CONFIG_SOFTMMU)
+    uint32_t *label3_ptr;
+#endif
+    int addr_reg2;
+#endif
+
+    data_reg = *args++;
+    if (opc == 3)
+        data_reg2 = *args++;
+    else
+        data_reg2 = 0; /* surpress warning */
+    addr_reg = *args++;
+#if TARGET_LONG_BITS == 64
+    addr_reg2 = *args++;
+#endif
+    mem_index = *args;
+    s_bits = opc & 3;
+
+    r0 = TCG_REG_R26;
+    r1 = TCG_REG_R25;
+
+#if defined(CONFIG_SOFTMMU)
+    tcg_out_mov(s, r1, addr_reg);
+
+    tcg_out_mov(s, r0, addr_reg);
+
+    tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) |
+                 INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS));
+
+    tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
+                   ARITH_AND);
+
+    tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
+                   ARITH_AND);
+
+    tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD);
+    tcg_out_arithi(s, r1, r1,
+                   offsetof(CPUState, tlb_table[mem_index][0].addr_read),
+                   ARITH_ADD);
+
+    tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW);
+
+#if TARGET_LONG_BITS == 32
+    /* if equal, jump to label1 */
+    label1_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
+                 INSN_COND(COND_EQUAL));
+    tcg_out_mov(s, r0, addr_reg); /* delay slot */
+#else
+    /* if not equal, jump to label3 */
+    label3_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
+                 INSN_COND(COND_EQUAL));
+    tcg_out_mov(s, r0, addr_reg); /* delay slot */
+
+    tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW);
+
+    /* if equal, jump to label1 */
+    label1_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) |
+                 INSN_COND(COND_EQUAL));
+    tcg_out_nop(s); /* delay slot */
+
+    /* label3: */
+    *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2);
+#endif
+
+#if TARGET_LONG_BITS == 32
+    tcg_out_mov(s, TCG_REG_R26, addr_reg);
+    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R25, mem_index);
+#else
+    tcg_out_mov(s, TCG_REG_R26, addr_reg);
+    tcg_out_mov(s, TCG_REG_R25, addr_reg2);
+    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index);
+#endif
+
+    tcg_out_call(s, qemu_ld_helpers[s_bits]);
+
+    switch(opc) {
+        case 0 | 4:
+            tcg_out_ext8s(s, data_reg, TCG_REG_RET0);
+            break;
+        case 1 | 4:
+            tcg_out_ext16s(s, data_reg, TCG_REG_RET0);
+            break;
+        case 0:
+        case 1:
+        case 2:
+        default:
+            tcg_out_mov(s, data_reg, TCG_REG_RET0);
+            break;
+        case 3:
+            tcg_abort();
+            tcg_out_mov(s, data_reg, TCG_REG_RET0);
+            tcg_out_mov(s, data_reg2, TCG_REG_RET1);
+            break;
+    }
+
+    /* jump to label2 */
+    label2_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2);
+
+    /* label1: */
+    *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2);
+
+    tcg_out_arithi(s, TCG_REG_R20, r1,
+                   offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read),
+                   ARITH_ADD);
+    tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW);
+    tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD);
+#else
+    r0 = addr_reg;
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    bswap = 0;
+#else
+    bswap = 1;
+#endif
+    switch (opc) {
+        case 0:
+            tcg_out_ldst(s, data_reg, r0, 0, LDB);
+            break;
+        case 0 | 4:
+            tcg_out_ldst(s, data_reg, r0, 0, LDB);
+            tcg_out_ext8s(s, data_reg, data_reg);
+            break;
+        case 1:
+            tcg_out_ldst(s, data_reg, r0, 0, LDH);
+            if (bswap)
+                tcg_out_bswap16(s, data_reg, data_reg);
+            break;
+        case 1 | 4:
+            tcg_out_ldst(s, data_reg, r0, 0, LDH);
+            if (bswap)
+                tcg_out_bswap16(s, data_reg, data_reg);
+            tcg_out_ext16s(s, data_reg, data_reg);
+            break;
+        case 2:
+            tcg_out_ldst(s, data_reg, r0, 0, LDW);
+            if (bswap)
+                tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
+            break;
+        case 3:
+            tcg_abort();
+            if (!bswap) {
+                tcg_out_ldst(s, data_reg, r0, 0, LDW);
+                tcg_out_ldst(s, data_reg2, r0, 4, LDW);
+            } else {
+                tcg_out_ldst(s, data_reg, r0, 4, LDW);
+                tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
+                tcg_out_ldst(s, data_reg2, r0, 0, LDW);
+                tcg_out_bswap32(s, data_reg2, data_reg2, TCG_REG_R20);
+            }
+            break;
+        default:
+            tcg_abort();
+    }
+
+#if defined(CONFIG_SOFTMMU)
+    /* label2: */
+    *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2);
+#endif
+}
+
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+{
+    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
+#if defined(CONFIG_SOFTMMU)
+    uint32_t *label1_ptr, *label2_ptr;
+#endif
+#if TARGET_LONG_BITS == 64
+#if defined(CONFIG_SOFTMMU)
+    uint32_t *label3_ptr;
+#endif
+    int addr_reg2;
+#endif
+
+    data_reg = *args++;
+    if (opc == 3)
+        data_reg2 = *args++;
+    else
+        data_reg2 = 0; /* surpress warning */
+    addr_reg = *args++;
+#if TARGET_LONG_BITS == 64
+    addr_reg2 = *args++;
+#endif
+    mem_index = *args;
+
+    s_bits = opc;
+
+    r0 = TCG_REG_R26;
+    r1 = TCG_REG_R25;
+
+#if defined(CONFIG_SOFTMMU)
+    tcg_out_mov(s, r1, addr_reg);
+
+    tcg_out_mov(s, r0, addr_reg);
+
+    tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) |
+                 INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS));
+
+    tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
+                   ARITH_AND);
+
+    tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
+                   ARITH_AND);
+
+    tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD);
+    tcg_out_arithi(s, r1, r1,
+                   offsetof(CPUState, tlb_table[mem_index][0].addr_write),
+                   ARITH_ADD);
+
+    tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW);
+
+#if TARGET_LONG_BITS == 32
+    /* if equal, jump to label1 */
+    label1_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
+                 INSN_COND(COND_EQUAL));
+    tcg_out_mov(s, r0, addr_reg); /* delay slot */
+#else
+    /* if not equal, jump to label3 */
+    label3_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
+                 INSN_COND(COND_EQUAL));
+    tcg_out_mov(s, r0, addr_reg); /* delay slot */
+
+    tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW);
+
+    /* if equal, jump to label1 */
+    label1_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) |
+                 INSN_COND(COND_EQUAL));
+    tcg_out_nop(s); /* delay slot */
+
+    /* label3: */
+    *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2);
+#endif
+
+    tcg_out_mov(s, TCG_REG_R26, addr_reg);
+#if TARGET_LONG_BITS == 64
+    tcg_out_mov(s, TCG_REG_R25, addr_reg2);
+    if (opc == 3) {
+        tcg_abort();
+        tcg_out_mov(s, TCG_REG_R24, data_reg);
+        tcg_out_mov(s, TCG_REG_R23, data_reg2);
+        /* TODO: push mem_index */
+        tcg_abort();
+    } else {
+        switch(opc) {
+        case 0:
+            tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) |
+                         INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
+            break;
+        case 1:
+            tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) |
+                         INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
+            break;
+        case 2:
+            tcg_out_mov(s, TCG_REG_R24, data_reg);
+            break;
+        }
+        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index);
+    }
+#else
+    if (opc == 3) {
+        tcg_abort();
+        tcg_out_mov(s, TCG_REG_R25, data_reg);
+        tcg_out_mov(s, TCG_REG_R24, data_reg2);
+        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index);
+    } else {
+        switch(opc) {
+        case 0:
+            tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) |
+                         INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
+            break;
+        case 1:
+            tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) |
+                         INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
+            break;
+        case 2:
+            tcg_out_mov(s, TCG_REG_R25, data_reg);
+            break;
+        }
+        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index);
+    }
+#endif
+    tcg_out_call(s, qemu_st_helpers[s_bits]);
+
+    /* jump to label2 */
+    label2_ptr = (uint32_t *)s->code_ptr;
+    tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2);
+
+    /* label1: */
+    *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2);
+
+    tcg_out_arithi(s, TCG_REG_R20, r1,
+                   offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write),
+                   ARITH_ADD);
+    tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW);
+    tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD);
+#else
+    r0 = addr_reg;
+#endif
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    bswap = 0;
+#else
+    bswap = 1;
+#endif
+    switch (opc) {
+    case 0:
+        tcg_out_ldst(s, data_reg, r0, 0, STB);
+        break;
+    case 1:
+        if (bswap) {
+            tcg_out_bswap16(s, TCG_REG_R20, data_reg);
+            data_reg = TCG_REG_R20;
+        }
+        tcg_out_ldst(s, data_reg, r0, 0, STH);
+        break;
+    case 2:
+        if (bswap) {
+            tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
+            data_reg = TCG_REG_R20;
+        }
+        tcg_out_ldst(s, data_reg, r0, 0, STW);
+        break;
+    case 3:
+        tcg_abort();
+        if (!bswap) {
+            tcg_out_ldst(s, data_reg, r0, 0, STW);
+            tcg_out_ldst(s, data_reg2, r0, 4, STW);
+        } else {
+            tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
+            tcg_out_ldst(s, TCG_REG_R20, r0, 4, STW);
+            tcg_out_bswap32(s, TCG_REG_R20, data_reg2, TCG_REG_R20);
+            tcg_out_ldst(s, TCG_REG_R20, r0, 0, STW);
+        }
+        break;
+    default:
+        tcg_abort();
+    }
+
+#if defined(CONFIG_SOFTMMU)
+    /* label2: */
+    *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2);
+#endif
+}
+
+static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
+                              const int *const_args)
+{
+    int c;
+
+    switch (opc) {
+    case INDEX_op_exit_tb:
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RET0, args[0]);
+        tcg_out32(s, BV_N | INSN_R2(TCG_REG_R18));
+        break;
+    case INDEX_op_goto_tb:
+        if (s->tb_jmp_offset) {
+            /* direct jump method */
+            fprintf(stderr, "goto_tb direct\n");
+            tcg_abort();
+            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, args[0]);
+            tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20));
+            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+        } else {
+            /* indirect jump method */
+            tcg_out_ld_ptr(s, TCG_REG_R20,
+                           (tcg_target_long)(s->tb_next + args[0]));
+            tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20));
+        }
+        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
+        break;
+    case INDEX_op_call:
+        tcg_out32(s, BLE_SR4 | INSN_R2(args[0]));
+        tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
+        break;
+    case INDEX_op_jmp:
+        fprintf(stderr, "unimplemented jmp\n");
+        tcg_abort();
+        break;
+    case INDEX_op_br:
+        fprintf(stderr, "unimplemented br\n");
+        tcg_abort();
+        break;
+    case INDEX_op_movi_i32:
+        tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
+        break;
+
+    case INDEX_op_ld8u_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], LDB);
+        break;
+    case INDEX_op_ld8s_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], LDB);
+        tcg_out_ext8s(s, args[0], args[0]);
+        break;
+    case INDEX_op_ld16u_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], LDH);
+        break;
+    case INDEX_op_ld16s_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], LDH);
+        tcg_out_ext16s(s, args[0], args[0]);
+        break;
+    case INDEX_op_ld_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], LDW);
+        break;
+
+    case INDEX_op_st8_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], STB);
+        break;
+    case INDEX_op_st16_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], STH);
+        break;
+    case INDEX_op_st_i32:
+        tcg_out_ldst(s, args[0], args[1], args[2], STW);
+        break;
+
+    case INDEX_op_sub_i32:
+        c = ARITH_SUB;
+        goto gen_arith;
+    case INDEX_op_and_i32:
+        c = ARITH_AND;
+        goto gen_arith;
+    case INDEX_op_or_i32:
+        c = ARITH_OR;
+        goto gen_arith;
+    case INDEX_op_xor_i32:
+        c = ARITH_XOR;
+        goto gen_arith;
+    case INDEX_op_add_i32:
+        c = ARITH_ADD;
+        goto gen_arith;
+
+    case INDEX_op_shl_i32:
+        tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) |
+                     lowsignext(0x1f, 0, 11));
+        tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20));
+        tcg_out32(s, ZVDEP | INSN_R2(args[0]) | INSN_R1(args[1]) |
+                     INSN_DEP_LEN(32));
+        break;
+    case INDEX_op_shr_i32:
+        tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(args[2]));
+        tcg_out32(s, VSHD | INSN_T(args[0]) | INSN_R1(TCG_REG_R0) |
+                     INSN_R2(args[1]));
+        break;
+    case INDEX_op_sar_i32:
+        tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) |
+                     lowsignext(0x1f, 0, 11));
+        tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20));
+        tcg_out32(s, VEXTRS | INSN_R1(args[0]) | INSN_R2(args[1]) |
+                     INSN_DEP_LEN(32));
+        break;
+
+    case INDEX_op_mul_i32:
+        fprintf(stderr, "unimplemented mul\n");
+        tcg_abort();
+        break;
+    case INDEX_op_mulu2_i32:
+        fprintf(stderr, "unimplemented mulu2\n");
+        tcg_abort();
+        break;
+    case INDEX_op_div2_i32:
+        fprintf(stderr, "unimplemented div2\n");
+        tcg_abort();
+        break;
+    case INDEX_op_divu2_i32:
+        fprintf(stderr, "unimplemented divu2\n");
+        tcg_abort();
+        break;
+
+    case INDEX_op_brcond_i32:
+        fprintf(stderr, "unimplemented brcond\n");
+        tcg_abort();
+        break;
+
+    case INDEX_op_qemu_ld8u:
+        tcg_out_qemu_ld(s, args, 0);
+        break;
+    case INDEX_op_qemu_ld8s:
+        tcg_out_qemu_ld(s, args, 0 | 4);
+        break;
+    case INDEX_op_qemu_ld16u:
+        tcg_out_qemu_ld(s, args, 1);
+        break;
+    case INDEX_op_qemu_ld16s:
+        tcg_out_qemu_ld(s, args, 1 | 4);
+        break;
+    case INDEX_op_qemu_ld32u:
+        tcg_out_qemu_ld(s, args, 2);
+        break;
+
+    case INDEX_op_qemu_st8:
+        tcg_out_qemu_st(s, args, 0);
+        break;
+    case INDEX_op_qemu_st16:
+        tcg_out_qemu_st(s, args, 1);
+        break;
+    case INDEX_op_qemu_st32:
+        tcg_out_qemu_st(s, args, 2);
+        break;
+
+    default:
+        fprintf(stderr, "unknown opcode 0x%x\n", opc);
+        tcg_abort();
+    }
+    return;
+
+gen_arith:
+    tcg_out_arith(s, args[0], args[1], args[2], c);
+}
+
+static const TCGTargetOpDef hppa_op_defs[] = {
+    { INDEX_op_exit_tb, { } },
+    { INDEX_op_goto_tb, { } },
+
+    { INDEX_op_call, { "r" } },
+    { INDEX_op_jmp, { "r" } },
+    { INDEX_op_br, { } },
+
+    { INDEX_op_mov_i32, { "r", "r" } },
+    { INDEX_op_movi_i32, { "r" } },
+    { INDEX_op_ld8u_i32, { "r", "r" } },
+    { INDEX_op_ld8s_i32, { "r", "r" } },
+    { INDEX_op_ld16u_i32, { "r", "r" } },
+    { INDEX_op_ld16s_i32, { "r", "r" } },
+    { INDEX_op_ld_i32, { "r", "r" } },
+    { INDEX_op_st8_i32, { "r", "r" } },
+    { INDEX_op_st16_i32, { "r", "r" } },
+    { INDEX_op_st_i32, { "r", "r" } },
+
+    { INDEX_op_add_i32, { "r", "r", "r" } },
+    { INDEX_op_sub_i32, { "r", "r", "r" } },
+    { INDEX_op_and_i32, { "r", "r", "r" } },
+    { INDEX_op_or_i32, { "r", "r", "r" } },
+    { INDEX_op_xor_i32, { "r", "r", "r" } },
+
+    { INDEX_op_shl_i32, { "r", "r", "r" } },
+    { INDEX_op_shr_i32, { "r", "r", "r" } },
+    { INDEX_op_sar_i32, { "r", "r", "r" } },
+
+    { INDEX_op_brcond_i32, { "r", "r" } },
+
+#if TARGET_LONG_BITS == 32
+    { INDEX_op_qemu_ld8u, { "r", "L" } },
+    { INDEX_op_qemu_ld8s, { "r", "L" } },
+    { INDEX_op_qemu_ld16u, { "r", "L" } },
+    { INDEX_op_qemu_ld16s, { "r", "L" } },
+    { INDEX_op_qemu_ld32u, { "r", "L" } },
+    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
+
+    { INDEX_op_qemu_st8, { "L", "L" } },
+    { INDEX_op_qemu_st16, { "L", "L" } },
+    { INDEX_op_qemu_st32, { "L", "L" } },
+    { INDEX_op_qemu_st64, { "L", "L", "L" } },
+#else
+    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
+    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
+
+    { INDEX_op_qemu_st8, { "L", "L", "L" } },
+    { INDEX_op_qemu_st16, { "L", "L", "L" } },
+    { INDEX_op_qemu_st32, { "L", "L", "L" } },
+    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
+#endif
+    { -1 },
+};
+
+void tcg_target_init(TCGContext *s)
+{
+    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
+    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
+                     (1 << TCG_REG_R20) |
+                     (1 << TCG_REG_R21) |
+                     (1 << TCG_REG_R22) |
+                     (1 << TCG_REG_R23) |
+                     (1 << TCG_REG_R24) |
+                     (1 << TCG_REG_R25) |
+                     (1 << TCG_REG_R26));
+
+    tcg_regset_clear(s->reserved_regs);
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);  /* hardwired to zero */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);  /* addil target */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RP);  /* link register */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3);  /* frame pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R18); /* return pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP);  /* data pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);  /* stack pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
+
+    tcg_add_target_add_op_defs(hppa_op_defs);
+}

+ 204 - 0
tcg/hppa/tcg-target.h

@@ -0,0 +1,204 @@
+/*
+ * Tiny Code Generator for QEMU
+ *
+ * Copyright (c) 2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define TCG_TARGET_HPPA 1
+
+#if defined(_PA_RISC1_1)
+#define TCG_TARGET_REG_BITS 32
+#else
+#error unsupported
+#endif
+
+#define TCG_TARGET_WORDS_BIGENDIAN
+
+#define TCG_TARGET_NB_REGS 32
+
+enum {
+    TCG_REG_R0 = 0,
+    TCG_REG_R1,
+    TCG_REG_RP,
+    TCG_REG_R3,
+    TCG_REG_R4,
+    TCG_REG_R5,
+    TCG_REG_R6,
+    TCG_REG_R7,
+    TCG_REG_R8,
+    TCG_REG_R9,
+    TCG_REG_R10,
+    TCG_REG_R11,
+    TCG_REG_R12,
+    TCG_REG_R13,
+    TCG_REG_R14,
+    TCG_REG_R15,
+    TCG_REG_R16,
+    TCG_REG_R17,
+    TCG_REG_R18,
+    TCG_REG_R19,
+    TCG_REG_R20,
+    TCG_REG_R21,
+    TCG_REG_R22,
+    TCG_REG_R23,
+    TCG_REG_R24,
+    TCG_REG_R25,
+    TCG_REG_R26,
+    TCG_REG_DP,
+    TCG_REG_RET0,
+    TCG_REG_RET1,
+    TCG_REG_SP,
+    TCG_REG_R31,
+};
+
+/* used for function call generation */
+#define TCG_REG_CALL_STACK TCG_REG_SP
+#define TCG_TARGET_STACK_ALIGN 16
+#define TCG_TARGET_STACK_GROWSUP
+
+/* optional instructions */
+//#define TCG_TARGET_HAS_ext8s_i32
+//#define TCG_TARGET_HAS_ext16s_i32
+//#define TCG_TARGET_HAS_bswap16_i32
+//#define TCG_TARGET_HAS_bswap_i32
+
+/* Note: must be synced with dyngen-exec.h */
+#define TCG_AREG0 TCG_REG_R17
+#define TCG_AREG1 TCG_REG_R14
+#define TCG_AREG2 TCG_REG_R15
+#define TCG_AREG3 TCG_REG_R16
+
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+    start &= ~31;
+    while (start <= stop)
+    {
+        asm volatile ("fdc 0(%0)\n"
+                      "sync\n"
+                      "fic 0(%%sr4, %0)\n"
+                      "sync\n"
+                      : : "r"(start) : "memory");
+        start += 32;
+    }
+}
+
+/* supplied by libgcc */
+extern void *__canonicalize_funcptr_for_compare(void *);
+
+/* Field selection types defined by hppa */
+#define rnd(x)                  (((x)+0x1000)&~0x1fff)
+/* lsel: select left 21 bits */
+#define lsel(v,a)               (((v)+(a))>>11)
+/* rsel: select right 11 bits */
+#define rsel(v,a)               (((v)+(a))&0x7ff)
+/* lrsel with rounding of addend to nearest 8k */
+#define lrsel(v,a)              (((v)+rnd(a))>>11)
+/* rrsel with rounding of addend to nearest 8k */
+#define rrsel(v,a)              ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
+
+#define mask(x,sz)              ((x) & ~((1<<(sz))-1))
+
+static inline int reassemble_12(int as12)
+{
+    return (((as12 & 0x800) >> 11) |
+            ((as12 & 0x400) >> 8) |
+            ((as12 & 0x3ff) << 3));
+}
+
+static inline int reassemble_14(int as14)
+{
+    return (((as14 & 0x1fff) << 1) |
+            ((as14 & 0x2000) >> 13));
+}
+
+static inline int reassemble_17(int as17)
+{
+    return (((as17 & 0x10000) >> 16) |
+            ((as17 & 0x0f800) << 5) |
+            ((as17 & 0x00400) >> 8) |
+            ((as17 & 0x003ff) << 3));
+}
+
+static inline int reassemble_21(int as21)
+{
+    return (((as21 & 0x100000) >> 20) |
+            ((as21 & 0x0ffe00) >> 8) |
+            ((as21 & 0x000180) << 7) |
+            ((as21 & 0x00007c) << 14) |
+            ((as21 & 0x000003) << 12));
+}
+
+static inline void hppa_patch21l(uint32_t *insn, int val, int addend)
+{
+    val = lrsel(val, addend);
+    *insn = mask(*insn, 21) | reassemble_21(val);
+}
+
+static inline void hppa_patch14r(uint32_t *insn, int val, int addend)
+{
+    val = rrsel(val, addend);
+    *insn = mask(*insn, 14) | reassemble_14(val);
+}
+
+static inline void hppa_patch17r(uint32_t *insn, int val, int addend)
+{
+    val = rrsel(val, addend);
+    *insn = (*insn & ~0x1f1ffd) | reassemble_17(val);
+}
+
+
+static inline void hppa_patch21l_dprel(uint32_t *insn, int val, int addend)
+{
+    register unsigned int dp asm("r27");
+    hppa_patch21l(insn, val - dp, addend);
+}
+
+static inline void hppa_patch14r_dprel(uint32_t *insn, int val, int addend)
+{
+    register unsigned int dp asm("r27");
+    hppa_patch14r(insn, val - dp, addend);
+}
+
+static inline void hppa_patch17f(uint32_t *insn, int val, int addend)
+{
+    int dot = (int)insn & ~0x3;
+    int v = ((val + addend) - dot - 8) / 4;
+    if (v > (1 << 16) || v < -(1 << 16)) {
+        printf("cannot fit branch to offset %d [%08x->%08x]\n", v, dot, val);
+        abort();
+    }
+    *insn = (*insn & ~0x1f1ffd) | reassemble_17(v);
+}
+
+static inline void hppa_load_imm21l(uint32_t *insn, int val, int addend)
+{
+    /* Transform addil L'sym(%dp) to ldil L'val, %r1 */
+    *insn = 0x20200000 | reassemble_21(lrsel(val, 0));
+}
+
+static inline void hppa_load_imm14r(uint32_t *insn, int val, int addend)
+{
+    /* Transform ldw R'sym(%r1), %rN to ldo R'sym(%r1), %rN */
+    hppa_patch14r(insn, val, addend);
+    /* HACK */
+    if (addend == 0)
+        *insn = (*insn & ~0xfc000000) | (0x0d << 26);
+}

+ 2 - 1
tcg/i386/tcg-target.c

@@ -47,8 +47,9 @@ const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX
 const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
 const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
 
 
 static void patch_reloc(uint8_t *code_ptr, int type, 
 static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value)
+                        tcg_target_long value, tcg_target_long addend)
 {
 {
+    value += addend;
     switch(type) {
     switch(type) {
     case R_386_32:
     case R_386_32:
         *(uint32_t *)code_ptr = value;
         *(uint32_t *)code_ptr = value;

+ 2 - 1
tcg/sparc/tcg-target.c

@@ -88,8 +88,9 @@ static const int tcg_target_call_oarg_regs[2] = {
 };
 };
 
 
 static void patch_reloc(uint8_t *code_ptr, int type,
 static void patch_reloc(uint8_t *code_ptr, int type,
-                        tcg_target_long value)
+                        tcg_target_long value, tcg_target_long addend)
 {
 {
+    value += addend;
     switch (type) {
     switch (type) {
     case R_SPARC_32:
     case R_SPARC_32:
         if (value != (uint32_t)value)
         if (value != (uint32_t)value)

+ 50 - 0
tcg/tcg-dyngen.c

@@ -465,10 +465,55 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
 #endif
 #endif
 
 
 #ifndef CONFIG_NO_DYNGEN_OP
 #ifndef CONFIG_NO_DYNGEN_OP
+
+#if defined __hppa__
+struct hppa_branch_stub {
+    uint32_t *location;
+    long target;
+    struct hppa_branch_stub *next;
+};
+
+#define HPPA_RECORD_BRANCH(LIST, LOC, TARGET) \
+do { \
+    struct hppa_branch_stub *stub = alloca(sizeof(struct hppa_branch_stub)); \
+    stub->location = LOC; \
+    stub->target = TARGET; \
+    stub->next = LIST; \
+    LIST = stub; \
+} while (0)
+
+static inline void hppa_process_stubs(struct hppa_branch_stub *stub,
+                                      uint8_t **gen_code_pp)
+{
+    uint32_t *s = (uint32_t *)*gen_code_pp;
+    uint32_t *p = s + 1;
+
+    if (!stub) return;
+
+    for (; stub != NULL; stub = stub->next) {
+        unsigned long l = (unsigned long)p;
+        /* stub:
+         * ldil L'target, %r1
+         * be,n R'target(%sr4,%r1)
+         */
+        *p++ = 0x20200000 | reassemble_21(lrsel(stub->target, 0));
+        *p++ = 0xe0202002 | (reassemble_17(rrsel(stub->target, 0) >> 2));
+        hppa_patch17f(stub->location, l, 0);
+    }
+    /* b,l,n stub,%r0 */
+    *s = 0xe8000002 | reassemble_17((p - s) - 2);
+    *gen_code_pp = (uint8_t *)p;
+}
+#endif /* __hppa__ */
+
 const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr)
 const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr)
 {
 {
     uint8_t *gen_code_ptr;
     uint8_t *gen_code_ptr;
 
 
+#ifdef __hppa__
+    struct hppa_branch_stub *hppa_stubs = NULL;
+#endif
+
     gen_code_ptr = s->code_ptr;
     gen_code_ptr = s->code_ptr;
     switch(opc) {
     switch(opc) {
 
 
@@ -478,6 +523,11 @@ const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr)
     default:
     default:
         tcg_abort();
         tcg_abort();
     }
     }
+
+#ifdef __hppa__
+    hppa_process_stubs(hppa_stubs, &gen_code_ptr);
+#endif
+
     s->code_ptr = gen_code_ptr;
     s->code_ptr = gen_code_ptr;
     return opparam_ptr;
     return opparam_ptr;
 }
 }

+ 23 - 7
tcg/tcg.c

@@ -53,7 +53,7 @@
 
 
 
 
 static void patch_reloc(uint8_t *code_ptr, int type, 
 static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value);
+                        tcg_target_long value, tcg_target_long addend);
 
 
 TCGOpDef tcg_op_defs[] = {
 TCGOpDef tcg_op_defs[] = {
 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
@@ -100,7 +100,7 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
         /* FIXME: This may break relocations on RISC targets that
         /* FIXME: This may break relocations on RISC targets that
            modify instruction fields in place.  The caller may not have 
            modify instruction fields in place.  The caller may not have 
            written the initial value.  */
            written the initial value.  */
-        patch_reloc(code_ptr, type, l->u.value + addend);
+        patch_reloc(code_ptr, type, l->u.value, addend);
     } else {
     } else {
         /* add a new relocation entry */
         /* add a new relocation entry */
         r = tcg_malloc(sizeof(TCGRelocation));
         r = tcg_malloc(sizeof(TCGRelocation));
@@ -123,7 +123,7 @@ static void tcg_out_label(TCGContext *s, int label_index,
         tcg_abort();
         tcg_abort();
     r = l->u.first_reloc;
     r = l->u.first_reloc;
     while (r != NULL) {
     while (r != NULL) {
-        patch_reloc(r->ptr, r->type, value + r->addend);
+        patch_reloc(r->ptr, r->type, value, r->addend);
         r = r->next;
         r = r->next;
     }
     }
     l->has_value = 1;
     l->has_value = 1;
@@ -1442,7 +1442,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
     int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
     int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
     TCGArg arg, func_arg;
     TCGArg arg, func_arg;
     TCGTemp *ts;
     TCGTemp *ts;
-    tcg_target_long stack_offset, call_stack_size;
+    tcg_target_long stack_offset, call_stack_size, func_addr;
     int const_func_arg;
     int const_func_arg;
     TCGRegSet allocated_regs;
     TCGRegSet allocated_regs;
     const TCGArgConstraint *arg_ct;
     const TCGArgConstraint *arg_ct;
@@ -1464,7 +1464,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
     call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
     call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
     call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
     call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
         ~(TCG_TARGET_STACK_ALIGN - 1);
         ~(TCG_TARGET_STACK_ALIGN - 1);
+#ifdef TCG_TARGET_STACK_GROWSUP
+    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
+#else
     tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
     tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
+#endif
 
 
     stack_offset = 0;
     stack_offset = 0;
     for(i = nb_regs; i < nb_params; i++) {
     for(i = nb_regs; i < nb_params; i++) {
@@ -1487,7 +1491,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
         } else {
         } else {
             tcg_abort();
             tcg_abort();
         }
         }
+#ifdef TCG_TARGET_STACK_GROWSUP
+        stack_offset -= sizeof(tcg_target_long);
+#else
         stack_offset += sizeof(tcg_target_long);
         stack_offset += sizeof(tcg_target_long);
+#endif
     }
     }
     
     
     /* assign input registers */
     /* assign input registers */
@@ -1516,6 +1524,10 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
     func_arg = args[nb_oargs + nb_iargs - 1];
     func_arg = args[nb_oargs + nb_iargs - 1];
     arg_ct = &def->args_ct[0];
     arg_ct = &def->args_ct[0];
     ts = &s->temps[func_arg];
     ts = &s->temps[func_arg];
+    func_addr = ts->val;
+#ifdef HOST_HPPA
+    func_addr = (tcg_target_long)__canonicalize_funcptr_for_compare((void *)func_addr);
+#endif
     const_func_arg = 0;
     const_func_arg = 0;
     if (ts->val_type == TEMP_VAL_MEM) {
     if (ts->val_type == TEMP_VAL_MEM) {
         reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
         reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
@@ -1529,12 +1541,12 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
         }
         }
         func_arg = reg;
         func_arg = reg;
     } else if (ts->val_type == TEMP_VAL_CONST) {
     } else if (ts->val_type == TEMP_VAL_CONST) {
-        if (tcg_target_const_match(ts->val, arg_ct)) {
+        if (tcg_target_const_match(func_addr, arg_ct)) {
             const_func_arg = 1;
             const_func_arg = 1;
-            func_arg = ts->val;
+            func_arg = func_addr;
         } else {
         } else {
             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-            tcg_out_movi(s, ts->type, reg, ts->val);
+            tcg_out_movi(s, ts->type, reg, func_addr);
             func_arg = reg;
             func_arg = reg;
         }
         }
     } else {
     } else {
@@ -1574,7 +1586,11 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
 
 
     tcg_out_op(s, opc, &func_arg, &const_func_arg);
     tcg_out_op(s, opc, &func_arg, &const_func_arg);
     
     
+#ifdef TCG_TARGET_STACK_GROWSUP
+    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
+#else
     tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
     tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
+#endif
 
 
     /* assign output registers and emit moves if needed */
     /* assign output registers and emit moves if needed */
     for(i = 0; i < nb_oargs; i++) {
     for(i = 0; i < nb_oargs; i++) {

+ 2 - 1
tcg/x86_64/tcg-target.c

@@ -74,8 +74,9 @@ const int tcg_target_call_oarg_regs[2] = {
 };
 };
 
 
 static void patch_reloc(uint8_t *code_ptr, int type, 
 static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value)
+                        tcg_target_long value, tcg_target_long addend)
 {
 {
+    value += addend;
     switch(type) {
     switch(type) {
     case R_X86_64_32:
     case R_X86_64_32:
         if (value != (uint32_t)value)
         if (value != (uint32_t)value)