public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Improve insn endianness support in CGEN ports
@ 2020-05-29 17:08 Jose E. Marchesi
  2020-05-29 17:08 ` [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open Jose E. Marchesi
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Jose E. Marchesi @ 2020-05-29 17:08 UTC (permalink / raw)
  To: binutils

Hi people!

This patch series improves the support for CGEN-based architectures
having different data endianness and instruction endianness.  This is
the case of the BPF port.

The first patch adds support for a new argument for cgen_cpu_open,
that ports can use in order to specify an instruction endianness.  If
the argument is not provided then the instruction endianness is
assumed to be the general endian.  This patch depends on a CGEN patch
that should be applied simultaneously, and that has been pre-approved
upstream already.  See the patch description for more information.

The second patch adapts the opcodes CGEN support code in order to use
the right endianness parameter (instruction or data) depending on
whether it is reading/writing instruction opcodes or the contents of
instruction operands.  See the patch description for more information.

The third patch is specific to the BPF port, and removes some
workarounds that are no longer necessary, because the underlying
problem has been solved by this series.

The series has been regression-tested in the following targets, which
cover both cgen and non-cgen ports:

  i386-darwin i386-lynxos i586-linux i686-nacl i686-pc-beos
  i686-pc-elf i686-pe i686-vxworks x86_64-linux x86_64-w64-mingw32
  x86_64-nacl sparc-aout sparc-linux sparc-vxworks sparc64-linux
  sparc-sun-solaris2.12 mips-linux mips-vxworks mips64-linux
  mipsel-linux-gnu mipsisa32el-linux mips64-openbsd mipstx39-elf
  aarch64-linux arm-linuxeabi arm-nacl arm-netbsdelf arm-nto arm-pe
  arm-symbianelf arm-vxworks arm-wince-pe bpf-unknown-none
  alpha-dec-vms alpha-linux alpha-linuxecoff alpha-netbsd
  alpha-unknown-freebsd4.7 am33_2.0-linux arc-linux-uclibc avr-elf
  bfin-elf cr16-elf cris-elf crisv32-linux crx-elf d10v-elf d30v-elf
  dlx-elf epiphany-elf fr30-elf frv-elf frv-linux ft32-elf h8300-elf
  hppa-linux hppa-hp-hpux10 hppa64-hp-hpux11.23 hppa64-linux
  $MIPS_TARGETS ia64-elf ia64-freebsd5 ia64-hpux ia64-linux
  ia64-netbsd ia64-vms ip2k-elf iq2000-elf lm32-elf m32c-elf m32r-elf
  m68hc11-elf m68hc12-elf m68k-elf m68k-linux m68k-netbsd mcore-elf
  mcore-pe mep-elf metag-linux microblaze-elf $MIPS_TARGETS mmix
  mn10200-elf mn10300-elf moxie-elf ms1-elf msp430-elf mt-elf
  nds32le-elf nios2-linux or1k-elf pdp11-dec-aout pj-elf
  powerpc-eabisim powerpc-eabivle powerpc-linux powerpc-nto
  powerpc-wrs-vxworks powerpc64-linux powerpcle-cygwin powerpcle-elf
  powerpc64le-linux ppc-lynxos pru-elf riscv32-elf riscv64-elf
  rl78-elf rs6000-aix4.3.3 rs6000-aix5.1 rx-elf s390-linux s390x-linux
  score-elf sh-linux sh-nto sh-pe sh-rtems sh-vxworks
  shl-unknown-netbsdelf $SPARC_TARGETS spu-elf tic30-unknown-aout
  tic30-unknown-coff tic4x-coff tic54x-coff tic6x-elf tilegx-linux
  tilepro-linux v850-elf vax-netbsdelf visium-elf $X86_TARGETS
  xgate-elf xstormy16-elf xtensa-elf z8k-coff z80-coff

No regressions observed.
This has also been tested with --enable-targets=all.

Salud!

Jose E. Marchesi (3):
  opcodes: support insn endianness in cgen_cpu_open
  opcodes: discriminate endianness and insn-endianness in CGEN ports
  cpu,gas,opcodes: remove no longer needed workaround from the BPF port

 binutils/ChangeLog       |  6 +++
 binutils/objdump.c       |  2 +
 cpu/ChangeLog            | 10 +++++
 cpu/bpf.cpu              | 10 ++---
 cpu/bpf.opc              |  1 -
 cpu/mep.opc              |  2 +-
 gas/ChangeLog            | 17 ++++++++
 gas/cgen.c               |  9 +++--
 gas/config/tc-bpf.c      |  9 ++---
 gas/config/tc-mep.c      |  2 +-
 include/ChangeLog        | 10 +++++
 include/opcode/cgen.h    | 11 +++++-
 opcodes/ChangeLog        | 84 ++++++++++++++++++++++++++++++++++++++++
 opcodes/bpf-desc.c       | 32 +++++++--------
 opcodes/bpf-dis.c        | 10 ++++-
 opcodes/bpf-ibld.c       | 10 ++---
 opcodes/bpf-opc.c        | 48 +++++++++++------------
 opcodes/cgen-dis.in      |  9 ++++-
 opcodes/cgen-ibld.in     | 10 ++---
 opcodes/cgen-opc.c       | 18 +++++----
 opcodes/disassemble.c    |  1 +
 opcodes/epiphany-desc.c  | 12 +++---
 opcodes/epiphany-dis.c   |  9 ++++-
 opcodes/epiphany-ibld.c  | 10 ++---
 opcodes/fr30-desc.c      | 12 +++---
 opcodes/fr30-dis.c       |  9 ++++-
 opcodes/fr30-ibld.c      | 10 ++---
 opcodes/frv-desc.c       | 12 +++---
 opcodes/frv-dis.c        |  9 ++++-
 opcodes/frv-ibld.c       | 10 ++---
 opcodes/ip2k-desc.c      | 12 +++---
 opcodes/ip2k-dis.c       |  9 ++++-
 opcodes/ip2k-ibld.c      | 10 ++---
 opcodes/iq2000-desc.c    | 12 +++---
 opcodes/iq2000-dis.c     |  9 ++++-
 opcodes/iq2000-ibld.c    | 10 ++---
 opcodes/lm32-desc.c      | 12 +++---
 opcodes/lm32-dis.c       |  9 ++++-
 opcodes/lm32-ibld.c      | 10 ++---
 opcodes/m32c-desc.c      | 12 +++---
 opcodes/m32c-dis.c       |  9 ++++-
 opcodes/m32c-ibld.c      | 10 ++---
 opcodes/m32r-desc.c      | 12 +++---
 opcodes/m32r-dis.c       |  9 ++++-
 opcodes/m32r-ibld.c      | 10 ++---
 opcodes/mep-desc.c       | 12 +++---
 opcodes/mep-dis.c        | 11 +++++-
 opcodes/mep-ibld.c       | 10 ++---
 opcodes/mt-desc.c        | 12 +++---
 opcodes/mt-dis.c         |  9 ++++-
 opcodes/mt-ibld.c        | 10 ++---
 opcodes/or1k-desc.c      | 12 +++---
 opcodes/or1k-dis.c       |  9 ++++-
 opcodes/or1k-ibld.c      | 10 ++---
 opcodes/xc16x-desc.c     | 12 +++---
 opcodes/xc16x-dis.c      |  9 ++++-
 opcodes/xc16x-ibld.c     | 10 ++---
 opcodes/xstormy16-desc.c | 12 +++---
 opcodes/xstormy16-dis.c  |  9 ++++-
 opcodes/xstormy16-ibld.c | 10 ++---
 60 files changed, 489 insertions(+), 227 deletions(-)

-- 
2.25.0.2.g232378479e


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open
  2020-05-29 17:08 [PATCH 0/3] Improve insn endianness support in CGEN ports Jose E. Marchesi
@ 2020-05-29 17:08 ` Jose E. Marchesi
  2020-06-01  7:19   ` Alan Modra
  2020-05-29 17:08 ` [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports Jose E. Marchesi
  2020-05-29 17:08 ` [PATCH 3/3] cpu, gas, opcodes: remove no longer needed workaround from the BPF port Jose E. Marchesi
  2 siblings, 1 reply; 9+ messages in thread
From: Jose E. Marchesi @ 2020-05-29 17:08 UTC (permalink / raw)
  To: binutils

This patch adds support for a new CGEN_OPEN_INSN_ENDIAN argument
for @arch@_cgen_cpu_open.  This is useful for architectures in
which the endianness of the instruction words is not the same
than the endianness used for data.

An accompanying patch has been sent to the CGEN mailing list that
adds support for this argument on the CGEN side [1].  Its been
already pre-approved [2], and will be applied simultaneously with
this binutils series.

[1] https://sourceware.org/pipermail/cgen/2020q2/002733.html
[2] https://sourceware.org/pipermail/cgen/2020q2/002737.html

include/ChangeLog:

2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>

	* opcode/cgen.h (enum cgen_cpu_open_arg): New value
	CGEN_CPU_OPEN_INSN_ENDIAN.

opcodes/ChangeLog:

2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>

	* cgen-dis.in (cpu_desc_list): New field `insn_endian'.
	(print_insn_): Handle instruction endian.
	* bpf-dis.c: Regenerate.
	* bpf-desc.c: Regenerate.
	* epiphany-dis.c: Likewise.
	* epiphany-desc.c: Likewise.
	* fr30-dis.c: Likewise.
	* fr30-desc.c: Likewise.
	* frv-dis.c: Likewise.
	* frv-desc.c: Likewise.
	* ip2k-dis.c: Likewise.
	* ip2k-desc.c: Likewise.
	* iq2000-dis.c: Likewise.
	* iq2000-desc.c: Likewise.
	* lm32-dis.c: Likewise.
	* lm32-desc.c: Likewise.
	* m32c-dis.c: Likewise.
	* m32c-desc.c: Likewise.
	* m32r-dis.c: Likewise.
	* m32r-desc.c: Likewise.
	* mep-dis.c: Likewise.
	* mep-desc.c: Likewise.
	* mt-dis.c: Likewise.
	* mt-desc.c: Likewise.
	* or1k-dis.c: Likewise.
	* or1k-desc.c: Likewise.
	* xc16x-dis.c: Likewise.
	* xc16x-desc.c: Likewise.
	* xstormy16-dis.c: Likewise.
	* xstormy16-desc.c: Likewise.

binutils/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* objdump.c (disassemble_data): Set disasm_info.endian_code to
	disasm_info.endian after the later is initialized to the
	endianness reported by BFD.
---
 binutils/ChangeLog       |  6 ++++++
 binutils/objdump.c       |  2 ++
 include/ChangeLog        |  5 +++++
 include/opcode/cgen.h    |  9 ++++++++-
 opcodes/ChangeLog        | 33 +++++++++++++++++++++++++++++++++
 opcodes/bpf-desc.c       | 12 +++++++-----
 opcodes/bpf-dis.c        |  7 +++++++
 opcodes/cgen-dis.in      |  7 +++++++
 opcodes/epiphany-desc.c  | 28 +++++++++++++++++++---------
 opcodes/epiphany-dis.c   |  7 +++++++
 opcodes/fr30-desc.c      | 28 +++++++++++++++++++---------
 opcodes/fr30-dis.c       |  7 +++++++
 opcodes/frv-desc.c       | 28 +++++++++++++++++++---------
 opcodes/frv-dis.c        |  7 +++++++
 opcodes/ip2k-desc.c      | 28 +++++++++++++++++++---------
 opcodes/ip2k-dis.c       |  7 +++++++
 opcodes/iq2000-desc.c    | 28 +++++++++++++++++++---------
 opcodes/iq2000-dis.c     |  7 +++++++
 opcodes/lm32-desc.c      | 28 +++++++++++++++++++---------
 opcodes/lm32-dis.c       |  7 +++++++
 opcodes/m32c-desc.c      | 28 +++++++++++++++++++---------
 opcodes/m32c-dis.c       |  7 +++++++
 opcodes/m32r-desc.c      | 28 +++++++++++++++++++---------
 opcodes/m32r-dis.c       |  7 +++++++
 opcodes/mep-desc.c       | 28 +++++++++++++++++++---------
 opcodes/mep-dis.c        |  7 +++++++
 opcodes/mt-desc.c        | 28 +++++++++++++++++++---------
 opcodes/mt-dis.c         |  7 +++++++
 opcodes/or1k-desc.c      | 28 +++++++++++++++++++---------
 opcodes/or1k-dis.c       |  7 +++++++
 opcodes/xc16x-desc.c     | 28 +++++++++++++++++++---------
 opcodes/xc16x-dis.c      |  7 +++++++
 opcodes/xstormy16-desc.c | 28 +++++++++++++++++++---------
 opcodes/xstormy16-dis.c  |  7 +++++++
 34 files changed, 413 insertions(+), 123 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 101255de21..eb3eb6102d 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* objdump.c (disassemble_data): Set disasm_info.endian_code to
+	disasm_info.endian after the later is initialized to the
+	endianness reported by BFD.
+
 2020-05-28  Max Filippov  <jcmvbkbc@gmail.com>
 
 	* MAINTAINERS (Xtensa): Add myself as maintainer.
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 99e6df6eb1..9b3d5b7acb 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -3479,6 +3479,8 @@ disassemble_data (bfd *abfd)
        instead.  */
     disasm_info.endian = BFD_ENDIAN_UNKNOWN;
 
+  disasm_info.endian_code = disasm_info.endian;
+
   /* Allow the target to customize the info structure.  */
   disassemble_init_for_target (& disasm_info);
 
diff --git a/include/ChangeLog b/include/ChangeLog
index 08eadb6cbd..adadc49fef 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>
+
+	* opcode/cgen.h (enum cgen_cpu_open_arg): New value
+	CGEN_CPU_OPEN_INSN_ENDIAN.
+
 2020-05-28  Alan Modra  <amodra@gmail.com>
 
 	PR 26044
diff --git a/include/opcode/cgen.h b/include/opcode/cgen.h
index 95bbdf43e3..3f325447b9 100644
--- a/include/opcode/cgen.h
+++ b/include/opcode/cgen.h
@@ -1392,7 +1392,9 @@ enum cgen_cpu_open_arg {
      Multiple machines can be specified by repeated use.  */
   CGEN_CPU_OPEN_BFDMACH,
   /* Select endian, arg is CGEN_ENDIAN_*.  */
-  CGEN_CPU_OPEN_ENDIAN
+  CGEN_CPU_OPEN_ENDIAN,
+  /* Select instruction endian, arg is CGEN_ENDIAN_*.  */
+  CGEN_CPU_OPEN_INSN_ENDIAN,
 };
 
 /* Open a cpu descriptor table for use.
@@ -1465,6 +1467,11 @@ extern CGEN_INSN_INT cgen_get_insn_value
 extern void cgen_put_insn_value
   (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT);
 
+extern CGEN_INSN_INT cgen_get_base_insn_value
+  (CGEN_CPU_DESC, unsigned char *, int);
+extern void cgen_put_base_insn_value
+  (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT);
+
 /* Read in a cpu description file.
    ??? For future concerns, including adding instructions to the assembler/
    disassembler at run-time.  */
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 15405a5215..bb639637aa 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,36 @@
+2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>
+
+	* cgen-dis.in (cpu_desc_list): New field `insn_endian'.
+	(print_insn_): Handle instruction endian.
+	* bpf-dis.c: Regenerate.
+	* bpf-desc.c: Regenerate.
+	* epiphany-dis.c: Likewise.
+	* epiphany-desc.c: Likewise.
+	* fr30-dis.c: Likewise.
+	* fr30-desc.c: Likewise.
+	* frv-dis.c: Likewise.
+	* frv-desc.c: Likewise.
+	* ip2k-dis.c: Likewise.
+	* ip2k-desc.c: Likewise.
+	* iq2000-dis.c: Likewise.
+	* iq2000-desc.c: Likewise.
+	* lm32-dis.c: Likewise.
+	* lm32-desc.c: Likewise.
+	* m32c-dis.c: Likewise.
+	* m32c-desc.c: Likewise.
+	* m32r-dis.c: Likewise.
+	* m32r-desc.c: Likewise.
+	* mep-dis.c: Likewise.
+	* mep-desc.c: Likewise.
+	* mt-dis.c: Likewise.
+	* mt-desc.c: Likewise.
+	* or1k-dis.c: Likewise.
+	* or1k-desc.c: Likewise.
+	* xc16x-dis.c: Likewise.
+	* xc16x-desc.c: Likewise.
+	* xstormy16-dis.c: Likewise.
+	* xstormy16-desc.c: Likewise.
+
 2020-05-28  Jose E. Marchesi  <jose.marchesi@oracle.com>
 	    David Faust <david.faust@oracle.com>
 
diff --git a/opcodes/bpf-desc.c b/opcodes/bpf-desc.c
index ddd55b9fb6..986810254c 100644
--- a/opcodes/bpf-desc.c
+++ b/opcodes/bpf-desc.c
@@ -1701,6 +1701,7 @@ bpf_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1714,6 +1715,7 @@ bpf_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1748,6 +1750,9 @@ bpf_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1777,11 +1782,8 @@ bpf_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = bpf_cgen_rebuild_tables;
diff --git a/opcodes/bpf-dis.c b/opcodes/bpf-dis.c
index 60e0d960c8..21d9308be0 100644
--- a/opcodes/bpf-dis.c
+++ b/opcodes/bpf-dis.c
@@ -507,6 +507,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -519,12 +520,16 @@ print_insn_bpf (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -590,9 +595,11 @@ print_insn_bpf (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = bpf_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/cgen-dis.in b/opcodes/cgen-dis.in
index 5f448fbd3f..378b984551 100644
--- a/opcodes/cgen-dis.in
+++ b/opcodes/cgen-dis.in
@@ -341,6 +341,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -353,12 +354,16 @@ print_insn_@arch@ (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -424,9 +429,11 @@ print_insn_@arch@ (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = @arch@_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/epiphany-desc.c b/opcodes/epiphany-desc.c
index 3776ebba5b..5c0695fed9 100644
--- a/opcodes/epiphany-desc.c
+++ b/opcodes/epiphany-desc.c
@@ -2139,6 +2139,7 @@ epiphany_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -2152,6 +2153,7 @@ epiphany_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -2186,6 +2188,9 @@ epiphany_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -2215,11 +2220,8 @@ epiphany_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = epiphany_cgen_rebuild_tables;
@@ -2269,10 +2271,18 @@ epiphany_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/epiphany-dis.c b/opcodes/epiphany-dis.c
index 1621d08e3e..966b39fe09 100644
--- a/opcodes/epiphany-dis.c
+++ b/opcodes/epiphany-dis.c
@@ -582,6 +582,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -594,12 +595,16 @@ print_insn_epiphany (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -665,9 +670,11 @@ print_insn_epiphany (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/fr30-desc.c b/opcodes/fr30-desc.c
index 5fe16b781a..7b8b495cb4 100644
--- a/opcodes/fr30-desc.c
+++ b/opcodes/fr30-desc.c
@@ -1616,6 +1616,7 @@ fr30_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1629,6 +1630,7 @@ fr30_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1663,6 +1665,9 @@ fr30_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1692,11 +1697,8 @@ fr30_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = fr30_cgen_rebuild_tables;
@@ -1746,10 +1748,18 @@ fr30_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/fr30-dis.c b/opcodes/fr30-dis.c
index 331b5fb06e..b98ea94a1a 100644
--- a/opcodes/fr30-dis.c
+++ b/opcodes/fr30-dis.c
@@ -603,6 +603,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -615,12 +616,16 @@ print_insn_fr30 (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -686,9 +691,11 @@ print_insn_fr30 (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/frv-desc.c b/opcodes/frv-desc.c
index 869237e674..e210c3b06f 100644
--- a/opcodes/frv-desc.c
+++ b/opcodes/frv-desc.c
@@ -6356,6 +6356,7 @@ frv_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -6369,6 +6370,7 @@ frv_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -6403,6 +6405,9 @@ frv_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -6432,11 +6437,8 @@ frv_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = frv_cgen_rebuild_tables;
@@ -6486,10 +6488,18 @@ frv_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/frv-dis.c b/opcodes/frv-dis.c
index 6f3d6cc6fd..60f1a6141e 100644
--- a/opcodes/frv-dis.c
+++ b/opcodes/frv-dis.c
@@ -700,6 +700,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -712,12 +713,16 @@ print_insn_frv (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -783,9 +788,11 @@ print_insn_frv (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/ip2k-desc.c b/opcodes/ip2k-desc.c
index 9e5cf6ce23..744431f988 100644
--- a/opcodes/ip2k-desc.c
+++ b/opcodes/ip2k-desc.c
@@ -1045,6 +1045,7 @@ ip2k_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1058,6 +1059,7 @@ ip2k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1092,6 +1094,9 @@ ip2k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1121,11 +1126,8 @@ ip2k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = ip2k_cgen_rebuild_tables;
@@ -1175,10 +1177,18 @@ ip2k_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/ip2k-dis.c b/opcodes/ip2k-dis.c
index 5f79b804fe..4a53a7c246 100644
--- a/opcodes/ip2k-dis.c
+++ b/opcodes/ip2k-dis.c
@@ -592,6 +592,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -604,12 +605,16 @@ print_insn_ip2k (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -675,9 +680,11 @@ print_insn_ip2k (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/iq2000-desc.c b/opcodes/iq2000-desc.c
index b14842767e..bba3a4b055 100644
--- a/opcodes/iq2000-desc.c
+++ b/opcodes/iq2000-desc.c
@@ -2050,6 +2050,7 @@ iq2000_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -2063,6 +2064,7 @@ iq2000_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -2097,6 +2099,9 @@ iq2000_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -2126,11 +2131,8 @@ iq2000_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = iq2000_cgen_rebuild_tables;
@@ -2180,10 +2182,18 @@ iq2000_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/iq2000-dis.c b/opcodes/iq2000-dis.c
index 64f18aea2c..3aab139c51 100644
--- a/opcodes/iq2000-dis.c
+++ b/opcodes/iq2000-dis.c
@@ -493,6 +493,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -505,12 +506,16 @@ print_insn_iq2000 (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -576,9 +581,11 @@ print_insn_iq2000 (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = iq2000_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/lm32-desc.c b/opcodes/lm32-desc.c
index 7470c3f9f1..9ea02502c9 100644
--- a/opcodes/lm32-desc.c
+++ b/opcodes/lm32-desc.c
@@ -1032,6 +1032,7 @@ lm32_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1045,6 +1046,7 @@ lm32_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1079,6 +1081,9 @@ lm32_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1108,11 +1113,8 @@ lm32_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = lm32_cgen_rebuild_tables;
@@ -1162,10 +1164,18 @@ lm32_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/lm32-dis.c b/opcodes/lm32-dis.c
index 7c53c400b6..7ba84b3a66 100644
--- a/opcodes/lm32-dis.c
+++ b/opcodes/lm32-dis.c
@@ -451,6 +451,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -463,12 +464,16 @@ print_insn_lm32 (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -534,9 +539,11 @@ print_insn_lm32 (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = lm32_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/m32c-desc.c b/opcodes/m32c-desc.c
index d79d2f49df..ac158e44c2 100644
--- a/opcodes/m32c-desc.c
+++ b/opcodes/m32c-desc.c
@@ -63063,6 +63063,7 @@ m32c_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -63076,6 +63077,7 @@ m32c_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -63110,6 +63112,9 @@ m32c_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -63139,11 +63144,8 @@ m32c_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = m32c_cgen_rebuild_tables;
@@ -63193,10 +63195,18 @@ m32c_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/m32c-dis.c b/opcodes/m32c-dis.c
index 9df688e943..41afca3cc0 100644
--- a/opcodes/m32c-dis.c
+++ b/opcodes/m32c-dis.c
@@ -1195,6 +1195,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -1207,12 +1208,16 @@ print_insn_m32c (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -1278,9 +1283,11 @@ print_insn_m32c (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = m32c_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/m32r-desc.c b/opcodes/m32r-desc.c
index 142cea3408..d1ee2e8bdf 100644
--- a/opcodes/m32r-desc.c
+++ b/opcodes/m32r-desc.c
@@ -1395,6 +1395,7 @@ m32r_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1408,6 +1409,7 @@ m32r_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1442,6 +1444,9 @@ m32r_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1471,11 +1476,8 @@ m32r_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = m32r_cgen_rebuild_tables;
@@ -1525,10 +1527,18 @@ m32r_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/m32r-dis.c b/opcodes/m32r-dis.c
index 59402220f9..e666739801 100644
--- a/opcodes/m32r-dis.c
+++ b/opcodes/m32r-dis.c
@@ -583,6 +583,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -595,12 +596,16 @@ print_insn_m32r (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -666,9 +671,11 @@ print_insn_m32r (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = m32r_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/mep-desc.c b/opcodes/mep-desc.c
index 305f744707..e2e62b7be7 100644
--- a/opcodes/mep-desc.c
+++ b/opcodes/mep-desc.c
@@ -6256,6 +6256,7 @@ mep_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -6269,6 +6270,7 @@ mep_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -6303,6 +6305,9 @@ mep_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -6332,11 +6337,8 @@ mep_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = mep_cgen_rebuild_tables;
@@ -6386,10 +6388,18 @@ mep_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/mep-dis.c b/opcodes/mep-dis.c
index 71da5a73ab..d2df588303 100644
--- a/opcodes/mep-dis.c
+++ b/opcodes/mep-dis.c
@@ -1491,6 +1491,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -1503,12 +1504,16 @@ print_insn_mep (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -1574,9 +1579,11 @@ print_insn_mep (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = mep_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/mt-desc.c b/opcodes/mt-desc.c
index ca1f50c4af..44d1f81acc 100644
--- a/opcodes/mt-desc.c
+++ b/opcodes/mt-desc.c
@@ -1176,6 +1176,7 @@ mt_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1189,6 +1190,7 @@ mt_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1223,6 +1225,9 @@ mt_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1252,11 +1257,8 @@ mt_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = mt_cgen_rebuild_tables;
@@ -1306,10 +1308,18 @@ mt_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/mt-dis.c b/opcodes/mt-dis.c
index 2cbca8cbf7..3d552e8acb 100644
--- a/opcodes/mt-dis.c
+++ b/opcodes/mt-dis.c
@@ -594,6 +594,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -606,12 +607,16 @@ print_insn_mt (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -677,9 +682,11 @@ print_insn_mt (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = mt_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/or1k-desc.c b/opcodes/or1k-desc.c
index 8bf986d9e0..dcbe4c0884 100644
--- a/opcodes/or1k-desc.c
+++ b/opcodes/or1k-desc.c
@@ -2070,6 +2070,7 @@ or1k_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -2083,6 +2084,7 @@ or1k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -2117,6 +2119,9 @@ or1k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -2146,11 +2151,8 @@ or1k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = or1k_cgen_rebuild_tables;
@@ -2200,10 +2202,18 @@ or1k_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/or1k-dis.c b/opcodes/or1k-dis.c
index dcb02c08ca..d350d2bbae 100644
--- a/opcodes/or1k-dis.c
+++ b/opcodes/or1k-dis.c
@@ -478,6 +478,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -490,12 +491,16 @@ print_insn_or1k (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -561,9 +566,11 @@ print_insn_or1k (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = or1k_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/xc16x-desc.c b/opcodes/xc16x-desc.c
index 621f2eb738..7495d16bd3 100644
--- a/opcodes/xc16x-desc.c
+++ b/opcodes/xc16x-desc.c
@@ -3379,6 +3379,7 @@ xc16x_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -3392,6 +3393,7 @@ xc16x_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -3426,6 +3428,9 @@ xc16x_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -3455,11 +3460,8 @@ xc16x_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = xc16x_cgen_rebuild_tables;
@@ -3509,10 +3511,18 @@ xc16x_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/xc16x-dis.c b/opcodes/xc16x-dis.c
index 84bc1e02ee..2cf926b68f 100644
--- a/opcodes/xc16x-dis.c
+++ b/opcodes/xc16x-dis.c
@@ -724,6 +724,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -736,12 +737,16 @@ print_insn_xc16x (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -807,9 +812,11 @@ print_insn_xc16x (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = xc16x_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
diff --git a/opcodes/xstormy16-desc.c b/opcodes/xstormy16-desc.c
index c1669c06e6..feecd8e282 100644
--- a/opcodes/xstormy16-desc.c
+++ b/opcodes/xstormy16-desc.c
@@ -1347,6 +1347,7 @@ xstormy16_cgen_rebuild_tables (CGEN_CPU_TABLE *cd)
    CGEN_CPU_OPEN_MACHS:   bitmap of values in enum mach_attr
    CGEN_CPU_OPEN_BFDMACH: specify 1 mach using bfd name
    CGEN_CPU_OPEN_ENDIAN:  specify endian choice
+   CGEN_CPU_OPEN_INSN_ENDIAN: specify instruction endian choice
    CGEN_CPU_OPEN_END:     terminates arguments
 
    ??? Simultaneous multiple isas might not make sense, but it's not (yet)
@@ -1360,6 +1361,7 @@ xstormy16_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   CGEN_BITSET *isas = 0;  /* 0 = "unspecified" */
   unsigned int machs = 0; /* 0 = "unspecified" */
   enum cgen_endian endian = CGEN_ENDIAN_UNKNOWN;
+  enum cgen_endian insn_endian = CGEN_ENDIAN_UNKNOWN;
   va_list ap;
 
   if (! init_p)
@@ -1394,6 +1396,9 @@ xstormy16_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
 	case CGEN_CPU_OPEN_ENDIAN :
 	  endian = va_arg (ap, enum cgen_endian);
 	  break;
+	case CGEN_CPU_OPEN_INSN_ENDIAN :
+	  insn_endian = va_arg (ap, enum cgen_endian);
+	  break;
 	default :
 	  opcodes_error_handler
 	    (/* xgettext:c-format */
@@ -1423,11 +1428,8 @@ xstormy16_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  /* FIXME: for the sparc case we can determine insn-endianness statically.
-     The worry here is where both data and insn endian can be independently
-     chosen, in which case this function will need another argument.
-     Actually, will want to allow for more arguments in the future anyway.  */
-  cd->insn_endian = endian;
+  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
+    cd->insn_endian = endian;
 
   /* Table (re)builder.  */
   cd->rebuild_tables = xstormy16_cgen_rebuild_tables;
@@ -1477,10 +1479,18 @@ xstormy16_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-  free ((CGEN_INSN *) cd->insn_table.init_entries);
-  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+  if (cd->macro_insn_table.init_entries)
+    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+
+  if (cd->insn_table.init_entries)
+    free ((CGEN_INSN *) cd->insn_table.init_entries);
+
+  if (cd->hw_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+
+  if (cd->operand_table.entries)
+    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
+
   free (cd);
 }
 
diff --git a/opcodes/xstormy16-dis.c b/opcodes/xstormy16-dis.c
index 07e025fd3b..8382c3da85 100644
--- a/opcodes/xstormy16-dis.c
+++ b/opcodes/xstormy16-dis.c
@@ -472,6 +472,7 @@ typedef struct cpu_desc_list
   CGEN_BITSET *isa;
   int mach;
   int endian;
+  int insn_endian;
   CGEN_CPU_DESC cd;
 } cpu_desc_list;
 
@@ -484,12 +485,16 @@ print_insn_xstormy16 (bfd_vma pc, disassemble_info *info)
   static CGEN_BITSET *prev_isa;
   static int prev_mach;
   static int prev_endian;
+  static int prev_insn_endian;
   int length;
   CGEN_BITSET *isa;
   int mach;
   int endian = (info->endian == BFD_ENDIAN_BIG
 		? CGEN_ENDIAN_BIG
 		: CGEN_ENDIAN_LITTLE);
+  int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
+                     ? CGEN_ENDIAN_BIG
+                     : CGEN_ENDIAN_LITTLE);
   enum bfd_architecture arch;
 
   /* ??? gdb will set mach but leave the architecture as "unknown" */
@@ -555,9 +560,11 @@ print_insn_xstormy16 (bfd_vma pc, disassemble_info *info)
       prev_isa = cgen_bitset_copy (isa);
       prev_mach = mach;
       prev_endian = endian;
+      prev_insn_endian = insn_endian;
       cd = xstormy16_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
+                                 CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
 				 CGEN_CPU_OPEN_END);
       if (!cd)
 	abort ();
-- 
2.25.0.2.g232378479e


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports
  2020-05-29 17:08 [PATCH 0/3] Improve insn endianness support in CGEN ports Jose E. Marchesi
  2020-05-29 17:08 ` [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open Jose E. Marchesi
@ 2020-05-29 17:08 ` Jose E. Marchesi
  2020-06-01  7:31   ` Alan Modra
  2020-05-29 17:08 ` [PATCH 3/3] cpu, gas, opcodes: remove no longer needed workaround from the BPF port Jose E. Marchesi
  2 siblings, 1 reply; 9+ messages in thread
From: Jose E. Marchesi @ 2020-05-29 17:08 UTC (permalink / raw)
  To: binutils

The CGEN support code in opcodes accesses instruction contents using a
couple of functions defined in cgen-opc.c: cgen_get_insn_value and
cgen_put_insn_value.  These functions use the "instruction endianness"
in the CPU description to order the read/written bytes.

The process of writing an instruction to the object file is:

  a) cgen_put_insn_value        ;; Writes out the opcodes.
  b) ARCH_cgen_insert_operand
       insert_normal
         insert_1
           cgen_put_insn_value  ;; Writes out the bytes of the
                                ;; operand.

Likewise, the process of reading an instruction from the object file
is:

  a) cgen_get_insn_value        ;; Reads the opcodes.
  b) ARCH_cgen_extract_operand
       extract_normal
         extract_1
           cgen_get_insn_value  ;; Reads in the bytes of the
                                ;; operand.

As can be seen above, cgen_{get,put}_insn_value are used to both
process the instruction opcodes (the constant fields conforming the
base instruction) and also the values of the instruction operands,
such as immediates.

This is problematic for architectures in which the endianness of
instructions is different to the endianness of data.  An example is
BPF, where instructions are always encoded big-endian but the data may
be either big or little.

This patch changes the cgen_{get,put}_insn_value functions in order to
get an extra argument with the endianness to use, and adapts the
existin callers to these functions in order to provide cd->endian or
cd->insn_endian, whatever appropriate.  Callers like extract_1 and
insert_1 pass cd->endian (since they are reading/writing operand
values) while callers reading/writing the base instruction pass
cd->insn_endian instead.

A few little adjustments have been needed in some existing CGEN based
ports:
* The BPF assembler uses cgen_put_insn_value.  It has been adapted to
  pass the new endian argument.
* The mep port has code in mep.opc that uses cgen_{get,put}_insn_value.
  It has been adapted to pass the new endianargument.  Ditto for a
  call in the assembler.

Tested with --enable-targets=all.
Regested in all supported targets.
No regressions.

include/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* opcode/cgen.h: Get an `endian' argument in both
	cgen_get_insn_value and cgen_put_insn_value.

opcodes/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* cgen-opc.c (cgen_get_insn_value): Get an `endian' argument.
	(cgen_put_insn_value): Likewise.
	(cgen_lookup_insn): Pass endianness to cgen_{get,put}_insn_value.
	* cgen-dis.in (print_insn): Likewise.
	* cgen-ibld.in (insert_1): Likewise.
	(insert_1): Likewise.
	(insert_insn_normal): Likewise.
	(extract_1): Likewise.
	* bpf-dis.c: Regenerate.
	* bpf-ibld.c: Likewise.
	* bpf-ibld.c: Likewise.
	* cgen-dis.in: Likewise.
	* cgen-ibld.in: Likewise.
	* cgen-opc.c: Likewise.
	* epiphany-dis.c: Likewise.
	* epiphany-ibld.c: Likewise.
	* fr30-dis.c: Likewise.
	* fr30-ibld.c: Likewise.
	* frv-dis.c: Likewise.
	* frv-ibld.c: Likewise.
	* ip2k-dis.c: Likewise.
	* ip2k-ibld.c: Likewise.
	* iq2000-dis.c: Likewise.
	* iq2000-ibld.c: Likewise.
	* lm32-dis.c: Likewise.
	* lm32-ibld.c: Likewise.
	* m32c-dis.c: Likewise.
	* m32c-ibld.c: Likewise.
	* m32r-dis.c: Likewise.
	* m32r-ibld.c: Likewise.
	* mep-dis.c: Likewise.
	* mep-ibld.c: Likewise.
	* mt-dis.c: Likewise.
	* mt-ibld.c: Likewise.
	* or1k-dis.c: Likewise.
	* or1k-ibld.c: Likewise.
	* xc16x-dis.c: Likewise.
	* xc16x-ibld.c: Likewise.
	* xstormy16-dis.c: Likewise.
	* xstormy16-ibld.c: Likewise.

gas/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* cgen.c (gas_cgen_finish_insn): Pass the endianness to
	cgen_put_insn_value.
	(gas_cgen_md_apply_fix): Likewise.
	(gas_cgen_md_apply_fix): Likewise.
	* config/tc-bpf.c (md_apply_fix): Pass data endianness to
	cgen_put_insn_value.
	* config/tc-mep.c (mep_check_ivc2_scheduling): Pass endianness to
	cgen_put_insn_value.

cpu/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* mep.opc (print_slot_insn): Pass the insn endianness to
	cgen_get_insn_value.
---
 cpu/ChangeLog            |  5 +++++
 cpu/mep.opc              |  2 +-
 gas/ChangeLog            | 11 ++++++++++
 gas/cgen.c               |  9 ++++++---
 gas/config/tc-bpf.c      |  3 ++-
 gas/config/tc-mep.c      |  2 +-
 include/ChangeLog        |  5 +++++
 include/opcode/cgen.h    |  4 ++--
 opcodes/ChangeLog        | 43 ++++++++++++++++++++++++++++++++++++++++
 opcodes/bpf-desc.c       | 20 ++++++-------------
 opcodes/bpf-dis.c        |  2 +-
 opcodes/bpf-ibld.c       | 10 +++++-----
 opcodes/cgen-dis.in      |  2 +-
 opcodes/cgen-ibld.in     | 10 +++++-----
 opcodes/cgen-opc.c       | 18 ++++++++++-------
 opcodes/epiphany-desc.c  | 20 ++++++-------------
 opcodes/epiphany-dis.c   |  2 +-
 opcodes/epiphany-ibld.c  | 10 +++++-----
 opcodes/fr30-desc.c      | 20 ++++++-------------
 opcodes/fr30-dis.c       |  2 +-
 opcodes/fr30-ibld.c      | 10 +++++-----
 opcodes/frv-desc.c       | 20 ++++++-------------
 opcodes/frv-dis.c        |  2 +-
 opcodes/frv-ibld.c       | 10 +++++-----
 opcodes/ip2k-desc.c      | 20 ++++++-------------
 opcodes/ip2k-dis.c       |  2 +-
 opcodes/ip2k-ibld.c      | 10 +++++-----
 opcodes/iq2000-desc.c    | 20 ++++++-------------
 opcodes/iq2000-dis.c     |  2 +-
 opcodes/iq2000-ibld.c    | 10 +++++-----
 opcodes/lm32-desc.c      | 20 ++++++-------------
 opcodes/lm32-dis.c       |  2 +-
 opcodes/lm32-ibld.c      | 10 +++++-----
 opcodes/m32c-desc.c      | 20 ++++++-------------
 opcodes/m32c-dis.c       |  2 +-
 opcodes/m32c-ibld.c      | 10 +++++-----
 opcodes/m32r-desc.c      | 20 ++++++-------------
 opcodes/m32r-dis.c       |  2 +-
 opcodes/m32r-ibld.c      | 10 +++++-----
 opcodes/mep-desc.c       | 20 ++++++-------------
 opcodes/mep-dis.c        |  4 ++--
 opcodes/mep-ibld.c       | 10 +++++-----
 opcodes/mt-desc.c        | 20 ++++++-------------
 opcodes/mt-dis.c         |  2 +-
 opcodes/mt-ibld.c        | 10 +++++-----
 opcodes/or1k-desc.c      | 20 ++++++-------------
 opcodes/or1k-dis.c       |  2 +-
 opcodes/or1k-ibld.c      | 10 +++++-----
 opcodes/xc16x-desc.c     | 20 ++++++-------------
 opcodes/xc16x-dis.c      |  2 +-
 opcodes/xc16x-ibld.c     | 10 +++++-----
 opcodes/xstormy16-desc.c | 20 ++++++-------------
 opcodes/xstormy16-dis.c  |  2 +-
 opcodes/xstormy16-ibld.c | 10 +++++-----
 54 files changed, 262 insertions(+), 302 deletions(-)

diff --git a/cpu/ChangeLog b/cpu/ChangeLog
index 30b884c951..907b44f07f 100644
--- a/cpu/ChangeLog
+++ b/cpu/ChangeLog
@@ -1,3 +1,8 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* mep.opc (print_slot_insn): Pass the insn endianness to
+	cgen_get_insn_value.
+
 2020-05-28  Jose E. Marchesi  <jose.marchesi@oracle.com>
 	    David Faust <david.faust@oracle.com>
 
diff --git a/cpu/mep.opc b/cpu/mep.opc
index 34e279d98e..5a4c93dc3a 100644
--- a/cpu/mep.opc
+++ b/cpu/mep.opc
@@ -1271,7 +1271,7 @@ print_slot_insn (CGEN_CPU_DESC cd,
   CGEN_INSN_INT insn_value;
   CGEN_EXTRACT_INFO ex_info;
 
-  insn_value = cgen_get_insn_value (cd, buf, 32);
+  insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
      read_insn, since the incoming buffer is already read (and possibly
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 07509cc737..cf1e9f5349 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,14 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* cgen.c (gas_cgen_finish_insn): Pass the endianness to
+	cgen_put_insn_value.
+	(gas_cgen_md_apply_fix): Likewise.
+	(gas_cgen_md_apply_fix): Likewise.
+	* config/tc-bpf.c (md_apply_fix): Pass data endianness to
+	cgen_put_insn_value.
+	* config/tc-mep.c (mep_check_ivc2_scheduling): Pass endianness to
+	cgen_put_insn_value.
+
 2020-05-28  Stephen Casner  <casner@acm.org>
 
 	Fix unexpected failures in gas testsuite for pdp11-aout target.
diff --git a/gas/cgen.c b/gas/cgen.c
index b94802ebc8..813f60fd8a 100644
--- a/gas/cgen.c
+++ b/gas/cgen.c
@@ -621,7 +621,8 @@ gas_cgen_finish_insn (const CGEN_INSN *insn, CGEN_INSN_BYTES_PTR buf,
   /* If we're recording insns as numbers (rather than a string of bytes),
      target byte order handling is deferred until now.  */
 #if CGEN_INT_INSN_P
-  cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf);
+  cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf,
+                       gas_cgen_cpu_desc->insn_endian);
 #else
   memcpy (f, buf, byte_len);
 #endif
@@ -906,13 +907,15 @@ gas_cgen_md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	  {
 	    CGEN_INSN_INT insn_value =
 	      cgen_get_insn_value (cd, (unsigned char *) where,
-				   CGEN_INSN_BITSIZE (insn));
+				   CGEN_INSN_BITSIZE (insn),
+                                   cd->endian);
 
 	    /* ??? 0 is passed for `pc'.  */
 	    errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
 						   &insn_value, (bfd_vma) 0);
 	    cgen_put_insn_value (cd, (unsigned char *) where,
-				 CGEN_INSN_BITSIZE (insn), insn_value);
+				 CGEN_INSN_BITSIZE (insn), insn_value,
+                                 cd->endian);
 	  }
 #else
 	  /* ??? 0 is passed for `pc'.  */
diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
index a379acbbed..7c7d22e477 100644
--- a/gas/config/tc-bpf.c
+++ b/gas/config/tc-bpf.c
@@ -324,7 +324,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
              this code is executed only once per instruction.  */
           where = fixP->fx_frag->fr_literal + fixP->fx_where;
           cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) where + 1, 8,
-                               target_big_endian ? 0x01 : 0x10);
+                               target_big_endian ? 0x01 : 0x10,
+                               gas_cgen_cpu_desc->endian);
           /* Fallthrough.  */
         case BPF_OPERAND_DISP16:
           /* The PC-relative displacement fields in jump instructions
diff --git a/gas/config/tc-mep.c b/gas/config/tc-mep.c
index 26fb80ec8a..aa2533784a 100644
--- a/gas/config/tc-mep.c
+++ b/gas/config/tc-mep.c
@@ -1111,7 +1111,7 @@ mep_check_ivc2_scheduling (void)
 
 #if CGEN_INT_INSN_P
       cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) temp, 32,
-			   m->buffer[0]);
+			   m->buffer[0], gas_cgen_cpu_desc->endian);
 #else
       memcpy (temp, m->buffer, byte_len);
 #endif
diff --git a/include/ChangeLog b/include/ChangeLog
index adadc49fef..f376db771a 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* opcode/cgen.h: Get an `endian' argument in both
+	cgen_get_insn_value and cgen_put_insn_value.
+
 2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>
 
 	* opcode/cgen.h (enum cgen_cpu_open_arg): New value
diff --git a/include/opcode/cgen.h b/include/opcode/cgen.h
index 3f325447b9..cae279541f 100644
--- a/include/opcode/cgen.h
+++ b/include/opcode/cgen.h
@@ -1463,9 +1463,9 @@ extern const CGEN_INSN * cgen_lookup_get_insn_operands
 /* Cover fns to bfd_get/set.  */
 
 extern CGEN_INSN_INT cgen_get_insn_value
-  (CGEN_CPU_DESC, unsigned char *, int);
+  (CGEN_CPU_DESC, unsigned char *, int, int);
 extern void cgen_put_insn_value
-  (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT);
+  (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT, int);
 
 extern CGEN_INSN_INT cgen_get_base_insn_value
   (CGEN_CPU_DESC, unsigned char *, int);
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index bb639637aa..e90a812397 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,46 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* cgen-opc.c (cgen_get_insn_value): Get an `endian' argument.
+	(cgen_put_insn_value): Likewise.
+	(cgen_lookup_insn): Pass endianness to cgen_{get,put}_insn_value.
+	* cgen-dis.in (print_insn): Likewise.
+	* cgen-ibld.in (insert_1): Likewise.
+	(insert_1): Likewise.
+	(insert_insn_normal): Likewise.
+	(extract_1): Likewise.
+	* bpf-dis.c: Regenerate.
+	* bpf-ibld.c: Likewise.
+	* bpf-ibld.c: Likewise.
+	* cgen-dis.in: Likewise.
+	* cgen-ibld.in: Likewise.
+	* cgen-opc.c: Likewise.
+	* epiphany-dis.c: Likewise.
+	* epiphany-ibld.c: Likewise.
+	* fr30-dis.c: Likewise.
+	* fr30-ibld.c: Likewise.
+	* frv-dis.c: Likewise.
+	* frv-ibld.c: Likewise.
+	* ip2k-dis.c: Likewise.
+	* ip2k-ibld.c: Likewise.
+	* iq2000-dis.c: Likewise.
+	* iq2000-ibld.c: Likewise.
+	* lm32-dis.c: Likewise.
+	* lm32-ibld.c: Likewise.
+	* m32c-dis.c: Likewise.
+	* m32c-ibld.c: Likewise.
+	* m32r-dis.c: Likewise.
+	* m32r-ibld.c: Likewise.
+	* mep-dis.c: Likewise.
+	* mep-ibld.c: Likewise.
+	* mt-dis.c: Likewise.
+	* mt-ibld.c: Likewise.
+	* or1k-dis.c: Likewise.
+	* or1k-ibld.c: Likewise.
+	* xc16x-dis.c: Likewise.
+	* xc16x-ibld.c: Likewise.
+	* xstormy16-dis.c: Likewise.
+	* xstormy16-ibld.c: Likewise.
+
 2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>
 
 	* cgen-dis.in (cpu_desc_list): New field `insn_endian'.
diff --git a/opcodes/bpf-desc.c b/opcodes/bpf-desc.c
index 986810254c..abd8c41006 100644
--- a/opcodes/bpf-desc.c
+++ b/opcodes/bpf-desc.c
@@ -1782,8 +1782,8 @@ bpf_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = bpf_cgen_rebuild_tables;
@@ -1833,18 +1833,10 @@ bpf_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/bpf-dis.c b/opcodes/bpf-dis.c
index 21d9308be0..4d01112d25 100644
--- a/opcodes/bpf-dis.c
+++ b/opcodes/bpf-dis.c
@@ -376,7 +376,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/bpf-ibld.c b/opcodes/bpf-ibld.c
index d5fa57a1c4..392dcebdd2 100644
--- a/opcodes/bpf-ibld.c
+++ b/opcodes/bpf-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/cgen-dis.in b/opcodes/cgen-dis.in
index 378b984551..2d5feebdb8 100644
--- a/opcodes/cgen-dis.in
+++ b/opcodes/cgen-dis.in
@@ -210,7 +210,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/cgen-ibld.in b/opcodes/cgen-ibld.in
index 6a9b97fcb5..ae9d20d6f4 100644
--- a/opcodes/cgen-ibld.in
+++ b/opcodes/cgen-ibld.in
@@ -87,7 +87,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -97,7 +97,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -268,8 +268,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -386,7 +386,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/cgen-opc.c b/opcodes/cgen-opc.c
index f3cfa9d9c3..18f9aae971 100644
--- a/opcodes/cgen-opc.c
+++ b/opcodes/cgen-opc.c
@@ -357,9 +357,10 @@ cgen_macro_insn_count (CGEN_CPU_DESC cd)
 /* Cover function to read and properly byteswap an insn value.  */
 
 CGEN_INSN_INT
-cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length)
+cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length,
+                     int endian)
 {
-  int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
+  int big_p = (endian == CGEN_ENDIAN_BIG);
   int insn_chunk_bitsize = cd->insn_chunk_bitsize;
   CGEN_INSN_INT value = 0;
 
@@ -385,7 +386,7 @@ cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length)
     }
   else
     {
-      value = bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG);
+      value = bfd_get_bits (buf, length, endian == CGEN_ENDIAN_BIG);
     }
 
   return value;
@@ -397,9 +398,10 @@ void
 cgen_put_insn_value (CGEN_CPU_DESC cd,
 		     unsigned char *buf,
 		     int length,
-		     CGEN_INSN_INT value)
+		     CGEN_INSN_INT value,
+                     int endian)
 {
-  int big_p = (cd->insn_endian == CGEN_ENDIAN_BIG);
+  int big_p = (endian == CGEN_ENDIAN_BIG);
   int insn_chunk_bitsize = cd->insn_chunk_bitsize;
 
   if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length)
@@ -459,7 +461,8 @@ cgen_lookup_insn (CGEN_CPU_DESC cd,
     {
       info = NULL;
       insn_bytes_value = (unsigned char *) xmalloc (cd->max_insn_bitsize / 8);
-      cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value);
+      cgen_put_insn_value (cd, insn_bytes_value, length, insn_int_value,
+                           cd->insn_endian);
     }
   else
     {
@@ -467,7 +470,8 @@ cgen_lookup_insn (CGEN_CPU_DESC cd,
       ex_info.dis_info = NULL;
       ex_info.insn_bytes = insn_bytes_value;
       ex_info.valid = -1;
-      insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length);
+      insn_int_value = cgen_get_insn_value (cd, insn_bytes_value, length,
+                                            cd->insn_endian);
     }
 
   if (!insn)
diff --git a/opcodes/epiphany-desc.c b/opcodes/epiphany-desc.c
index 5c0695fed9..fbd1f8b9f6 100644
--- a/opcodes/epiphany-desc.c
+++ b/opcodes/epiphany-desc.c
@@ -2220,8 +2220,8 @@ epiphany_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = epiphany_cgen_rebuild_tables;
@@ -2271,18 +2271,10 @@ epiphany_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/epiphany-dis.c b/opcodes/epiphany-dis.c
index 966b39fe09..83f8d7969e 100644
--- a/opcodes/epiphany-dis.c
+++ b/opcodes/epiphany-dis.c
@@ -451,7 +451,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/epiphany-ibld.c b/opcodes/epiphany-ibld.c
index c23a969294..4a974edccd 100644
--- a/opcodes/epiphany-ibld.c
+++ b/opcodes/epiphany-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/fr30-desc.c b/opcodes/fr30-desc.c
index 7b8b495cb4..836b1b9e4b 100644
--- a/opcodes/fr30-desc.c
+++ b/opcodes/fr30-desc.c
@@ -1697,8 +1697,8 @@ fr30_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = fr30_cgen_rebuild_tables;
@@ -1748,18 +1748,10 @@ fr30_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/fr30-dis.c b/opcodes/fr30-dis.c
index b98ea94a1a..ed89926cef 100644
--- a/opcodes/fr30-dis.c
+++ b/opcodes/fr30-dis.c
@@ -472,7 +472,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/fr30-ibld.c b/opcodes/fr30-ibld.c
index 5544d550f5..6816154ab2 100644
--- a/opcodes/fr30-ibld.c
+++ b/opcodes/fr30-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/frv-desc.c b/opcodes/frv-desc.c
index e210c3b06f..5c90bb4297 100644
--- a/opcodes/frv-desc.c
+++ b/opcodes/frv-desc.c
@@ -6437,8 +6437,8 @@ frv_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = frv_cgen_rebuild_tables;
@@ -6488,18 +6488,10 @@ frv_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/frv-dis.c b/opcodes/frv-dis.c
index 60f1a6141e..48b33596d0 100644
--- a/opcodes/frv-dis.c
+++ b/opcodes/frv-dis.c
@@ -569,7 +569,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/frv-ibld.c b/opcodes/frv-ibld.c
index 0421884908..43bccbac59 100644
--- a/opcodes/frv-ibld.c
+++ b/opcodes/frv-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/ip2k-desc.c b/opcodes/ip2k-desc.c
index 744431f988..9e6b4e27ab 100644
--- a/opcodes/ip2k-desc.c
+++ b/opcodes/ip2k-desc.c
@@ -1126,8 +1126,8 @@ ip2k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = ip2k_cgen_rebuild_tables;
@@ -1177,18 +1177,10 @@ ip2k_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/ip2k-dis.c b/opcodes/ip2k-dis.c
index 4a53a7c246..6cc08ba9d4 100644
--- a/opcodes/ip2k-dis.c
+++ b/opcodes/ip2k-dis.c
@@ -461,7 +461,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/ip2k-ibld.c b/opcodes/ip2k-ibld.c
index 9258f7d3ad..605d0bde04 100644
--- a/opcodes/ip2k-ibld.c
+++ b/opcodes/ip2k-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/iq2000-desc.c b/opcodes/iq2000-desc.c
index bba3a4b055..db5ce60f58 100644
--- a/opcodes/iq2000-desc.c
+++ b/opcodes/iq2000-desc.c
@@ -2131,8 +2131,8 @@ iq2000_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = iq2000_cgen_rebuild_tables;
@@ -2182,18 +2182,10 @@ iq2000_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/iq2000-dis.c b/opcodes/iq2000-dis.c
index 3aab139c51..fbe70c02b4 100644
--- a/opcodes/iq2000-dis.c
+++ b/opcodes/iq2000-dis.c
@@ -362,7 +362,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/iq2000-ibld.c b/opcodes/iq2000-ibld.c
index 319e994d84..2a87c709af 100644
--- a/opcodes/iq2000-ibld.c
+++ b/opcodes/iq2000-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/lm32-desc.c b/opcodes/lm32-desc.c
index 9ea02502c9..0270333a73 100644
--- a/opcodes/lm32-desc.c
+++ b/opcodes/lm32-desc.c
@@ -1113,8 +1113,8 @@ lm32_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = lm32_cgen_rebuild_tables;
@@ -1164,18 +1164,10 @@ lm32_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/lm32-dis.c b/opcodes/lm32-dis.c
index 7ba84b3a66..e66ad06ba4 100644
--- a/opcodes/lm32-dis.c
+++ b/opcodes/lm32-dis.c
@@ -320,7 +320,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/lm32-ibld.c b/opcodes/lm32-ibld.c
index 9b594e8e0e..2b0efdaa3f 100644
--- a/opcodes/lm32-ibld.c
+++ b/opcodes/lm32-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/m32c-desc.c b/opcodes/m32c-desc.c
index ac158e44c2..2dcccec3b6 100644
--- a/opcodes/m32c-desc.c
+++ b/opcodes/m32c-desc.c
@@ -63144,8 +63144,8 @@ m32c_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = m32c_cgen_rebuild_tables;
@@ -63195,18 +63195,10 @@ m32c_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/m32c-dis.c b/opcodes/m32c-dis.c
index 41afca3cc0..19135fa0b2 100644
--- a/opcodes/m32c-dis.c
+++ b/opcodes/m32c-dis.c
@@ -1064,7 +1064,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/m32c-ibld.c b/opcodes/m32c-ibld.c
index c1fca2e169..6ad4da967d 100644
--- a/opcodes/m32c-ibld.c
+++ b/opcodes/m32c-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/m32r-desc.c b/opcodes/m32r-desc.c
index d1ee2e8bdf..bb96818c94 100644
--- a/opcodes/m32r-desc.c
+++ b/opcodes/m32r-desc.c
@@ -1476,8 +1476,8 @@ m32r_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = m32r_cgen_rebuild_tables;
@@ -1527,18 +1527,10 @@ m32r_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/m32r-dis.c b/opcodes/m32r-dis.c
index e666739801..e15d3c3b94 100644
--- a/opcodes/m32r-dis.c
+++ b/opcodes/m32r-dis.c
@@ -452,7 +452,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/m32r-ibld.c b/opcodes/m32r-ibld.c
index ddebc32428..559f47135f 100644
--- a/opcodes/m32r-ibld.c
+++ b/opcodes/m32r-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/mep-desc.c b/opcodes/mep-desc.c
index e2e62b7be7..e255641f27 100644
--- a/opcodes/mep-desc.c
+++ b/opcodes/mep-desc.c
@@ -6337,8 +6337,8 @@ mep_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = mep_cgen_rebuild_tables;
@@ -6388,18 +6388,10 @@ mep_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/mep-dis.c b/opcodes/mep-dis.c
index d2df588303..1292d830cb 100644
--- a/opcodes/mep-dis.c
+++ b/opcodes/mep-dis.c
@@ -467,7 +467,7 @@ print_slot_insn (CGEN_CPU_DESC cd,
   CGEN_INSN_INT insn_value;
   CGEN_EXTRACT_INFO ex_info;
 
-  insn_value = cgen_get_insn_value (cd, buf, 32);
+  insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
      read_insn, since the incoming buffer is already read (and possibly
@@ -1360,7 +1360,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/mep-ibld.c b/opcodes/mep-ibld.c
index 6a73f419c9..66a30e1b45 100644
--- a/opcodes/mep-ibld.c
+++ b/opcodes/mep-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/mt-desc.c b/opcodes/mt-desc.c
index 44d1f81acc..37a02c9b8d 100644
--- a/opcodes/mt-desc.c
+++ b/opcodes/mt-desc.c
@@ -1257,8 +1257,8 @@ mt_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = mt_cgen_rebuild_tables;
@@ -1308,18 +1308,10 @@ mt_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/mt-dis.c b/opcodes/mt-dis.c
index 3d552e8acb..b0358e34e2 100644
--- a/opcodes/mt-dis.c
+++ b/opcodes/mt-dis.c
@@ -463,7 +463,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/mt-ibld.c b/opcodes/mt-ibld.c
index 53a0775f7a..683b76b2b4 100644
--- a/opcodes/mt-ibld.c
+++ b/opcodes/mt-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/or1k-desc.c b/opcodes/or1k-desc.c
index dcbe4c0884..a4f32d67b3 100644
--- a/opcodes/or1k-desc.c
+++ b/opcodes/or1k-desc.c
@@ -2151,8 +2151,8 @@ or1k_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = or1k_cgen_rebuild_tables;
@@ -2202,18 +2202,10 @@ or1k_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/or1k-dis.c b/opcodes/or1k-dis.c
index d350d2bbae..87ff206488 100644
--- a/opcodes/or1k-dis.c
+++ b/opcodes/or1k-dis.c
@@ -347,7 +347,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/or1k-ibld.c b/opcodes/or1k-ibld.c
index 2e476cb152..7b89260bf5 100644
--- a/opcodes/or1k-ibld.c
+++ b/opcodes/or1k-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/xc16x-desc.c b/opcodes/xc16x-desc.c
index 7495d16bd3..4532c1720e 100644
--- a/opcodes/xc16x-desc.c
+++ b/opcodes/xc16x-desc.c
@@ -3460,8 +3460,8 @@ xc16x_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = xc16x_cgen_rebuild_tables;
@@ -3511,18 +3511,10 @@ xc16x_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/xc16x-dis.c b/opcodes/xc16x-dis.c
index 2cf926b68f..d4c24f033d 100644
--- a/opcodes/xc16x-dis.c
+++ b/opcodes/xc16x-dis.c
@@ -593,7 +593,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/xc16x-ibld.c b/opcodes/xc16x-ibld.c
index 6b228bcdfc..b2802fecb6 100644
--- a/opcodes/xc16x-ibld.c
+++ b/opcodes/xc16x-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
diff --git a/opcodes/xstormy16-desc.c b/opcodes/xstormy16-desc.c
index feecd8e282..a62d1f7ecc 100644
--- a/opcodes/xstormy16-desc.c
+++ b/opcodes/xstormy16-desc.c
@@ -1428,8 +1428,8 @@ xstormy16_cgen_cpu_open (enum cgen_cpu_open_arg arg_type, ...)
   cd->isas = cgen_bitset_copy (isas);
   cd->machs = machs;
   cd->endian = endian;
-  if (insn_endian == CGEN_ENDIAN_UNKNOWN)
-    cd->insn_endian = endian;
+  cd->insn_endian
+    = (insn_endian == CGEN_ENDIAN_UNKNOWN ? endian : insn_endian);
 
   /* Table (re)builder.  */
   cd->rebuild_tables = xstormy16_cgen_rebuild_tables;
@@ -1479,18 +1479,10 @@ xstormy16_cgen_cpu_close (CGEN_CPU_DESC cd)
 	  regfree (CGEN_INSN_RX (insns));
     }
 
-  if (cd->macro_insn_table.init_entries)
-    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
-
-  if (cd->insn_table.init_entries)
-    free ((CGEN_INSN *) cd->insn_table.init_entries);
-
-  if (cd->hw_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
-
-  if (cd->operand_table.entries)
-    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
-
+  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
+  free ((CGEN_INSN *) cd->insn_table.init_entries);
+  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
+  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
   free (cd);
 }
 
diff --git a/opcodes/xstormy16-dis.c b/opcodes/xstormy16-dis.c
index 8382c3da85..c2723167fa 100644
--- a/opcodes/xstormy16-dis.c
+++ b/opcodes/xstormy16-dis.c
@@ -341,7 +341,7 @@ print_insn (CGEN_CPU_DESC cd,
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
   basesize = cd->base_insn_bitsize < buflen * 8 ?
                                      cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
+  insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
 
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
diff --git a/opcodes/xstormy16-ibld.c b/opcodes/xstormy16-ibld.c
index 70cf88d546..eaffbeef90 100644
--- a/opcodes/xstormy16-ibld.c
+++ b/opcodes/xstormy16-ibld.c
@@ -88,7 +88,7 @@ insert_1 (CGEN_CPU_DESC cd,
   unsigned long x,mask;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   /* Written this way to avoid undefined behaviour.  */
   mask = (((1L << (length - 1)) - 1) << 1) | 1;
@@ -98,7 +98,7 @@ insert_1 (CGEN_CPU_DESC cd,
     shift = (word_length - (start + length));
   x = (x & ~(mask << shift)) | ((value & mask) << shift);
 
-  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
+  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
 }
 
 #endif /* ! CGEN_INT_INSN_P */
@@ -269,8 +269,8 @@ insert_insn_normal (CGEN_CPU_DESC cd,
 #else
 
   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
+                                        (unsigned) CGEN_FIELDS_BITSIZE (fields)),
+		       value, cd->insn_endian);
 
 #endif /* ! CGEN_INT_INSN_P */
 
@@ -387,7 +387,7 @@ extract_1 (CGEN_CPU_DESC cd,
   unsigned long x;
   int shift;
 
-  x = cgen_get_insn_value (cd, bufp, word_length);
+  x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
 
   if (CGEN_INSN_LSB0_P)
     shift = (start + 1) - length;
-- 
2.25.0.2.g232378479e


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/3] cpu, gas, opcodes: remove no longer needed workaround from the BPF port
  2020-05-29 17:08 [PATCH 0/3] Improve insn endianness support in CGEN ports Jose E. Marchesi
  2020-05-29 17:08 ` [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open Jose E. Marchesi
  2020-05-29 17:08 ` [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports Jose E. Marchesi
@ 2020-05-29 17:08 ` Jose E. Marchesi
  2020-06-01  7:34   ` Alan Modra
  2 siblings, 1 reply; 9+ messages in thread
From: Jose E. Marchesi @ 2020-05-29 17:08 UTC (permalink / raw)
  To: binutils

cpu/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* bpf.cpu (define-bpf-isa): Set base-insn-bitsize to 64.
	* bpf.opc (bpf_print_insn): Do not set endian_code here.

gas/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* config/tc-bpf.c (md_begin): Pass CGEN_CPU_OPEN_INSN_ENDIAN to
	bpf_cgen_cpu_open.
	(md_assemble): Remove no longer needed hack.

opcodes/ChangeLog:

2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* disassemble.c (disassemble_init_for_target): Set endian_code for
	bpf targets.
	* bpf-desc.c: Regenerate.
	* bpf-opc.c: Likewise.
	* bpf-dis.c: Likewise.
---
 cpu/ChangeLog         |  5 +++++
 cpu/bpf.cpu           | 10 +++------
 cpu/bpf.opc           |  1 -
 gas/ChangeLog         |  6 ++++++
 gas/config/tc-bpf.c   |  6 ++----
 opcodes/ChangeLog     |  8 ++++++++
 opcodes/bpf-desc.c    |  4 ++--
 opcodes/bpf-dis.c     |  1 -
 opcodes/bpf-opc.c     | 48 +++++++++++++++++++++----------------------
 opcodes/disassemble.c |  1 +
 10 files changed, 51 insertions(+), 39 deletions(-)

diff --git a/cpu/ChangeLog b/cpu/ChangeLog
index 907b44f07f..12072c4166 100644
--- a/cpu/ChangeLog
+++ b/cpu/ChangeLog
@@ -1,3 +1,8 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* bpf.cpu (define-bpf-isa): Set base-insn-bitsize to 64.
+	* bpf.opc (bpf_print_insn): Do not set endian_code here.
+
 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
 	* mep.opc (print_slot_insn): Pass the insn endianness to
diff --git a/cpu/bpf.cpu b/cpu/bpf.cpu
index 47d7cb0f15..dcfb0ca8cf 100644
--- a/cpu/bpf.cpu
+++ b/cpu/bpf.cpu
@@ -98,13 +98,9 @@
     ;; Length of an unknown instruction.  Used by disassembly and by the
     ;; simulator's invalid insn handler.
     (default-insn-bitsize 64)
-    ;; Number of bits of insn that can be initially fetched.  XXX this
-    ;; should be 64 (the size of the smallest insn) but until CGEN
-    ;; gets fixed to place constant fields in their own words, we have
-    ;; to use this workaround to avoid the opcode byte to be placed at
-    ;; the wrong side of the instruction when assembling in
-    ;; big-endian.
-    (base-insn-bitsize 8)))
+    ;; Number of bits of insn that can be initially fetched.  This is
+    ;; the size of the smallest insn.
+    (base-insn-bitsize 64)))
 
 (define-bpf-isa le)
 (define-bpf-isa be)
diff --git a/cpu/bpf.opc b/cpu/bpf.opc
index e2acaa4341..e70ee04841 100644
--- a/cpu/bpf.opc
+++ b/cpu/bpf.opc
@@ -129,7 +129,6 @@ bpf_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
 
   info->bytes_per_chunk = 1;
   info->bytes_per_line = 8;
-  info->endian_code = BFD_ENDIAN_BIG;
 
   /* Attempt to read the base part of the insn.  */
   buflen = cd->base_insn_bitsize / 8;
diff --git a/gas/ChangeLog b/gas/ChangeLog
index cf1e9f5349..62a4f37dd1 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* config/tc-bpf.c (md_begin): Pass CGEN_CPU_OPEN_INSN_ENDIAN to
+	bpf_cgen_cpu_open.
+	(md_assemble): Remove no longer needed hack.
+
 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
 	* cgen.c (gas_cgen_finish_insn): Pass the endianness to
diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
index 7c7d22e477..b742f426a1 100644
--- a/gas/config/tc-bpf.c
+++ b/gas/config/tc-bpf.c
@@ -174,6 +174,8 @@ md_begin (void)
   gas_cgen_cpu_desc = bpf_cgen_cpu_open (CGEN_CPU_OPEN_ENDIAN,
                                          target_big_endian ?
                                          CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE,
+                                         CGEN_CPU_OPEN_INSN_ENDIAN,
+                                         CGEN_ENDIAN_LITTLE,
                                          CGEN_CPU_OPEN_ISAS,
                                          bpf_isa,
                                          CGEN_CPU_OPEN_END);
@@ -354,10 +356,6 @@ md_assemble (char *str)
   CGEN_INSN_INT buffer[CGEN_MAX_INSN_SIZE / sizeof (CGEN_INT_INSN_P)];
 #else
   unsigned char buffer[CGEN_MAX_INSN_SIZE];
-  memset (buffer, 0, CGEN_MAX_INSN_SIZE); /* XXX to remove when CGEN
-                                             is fixed to handle
-                                             opcodes-in-words
-                                             properly.  */
 #endif
 
   gas_cgen_init_parse ();
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index e90a812397..07e4cc5c17 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,11 @@
+2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* disassemble.c (disassemble_init_for_target): Set endian_code for
+	bpf targets.
+	* bpf-desc.c: Regenerate.
+	* bpf-opc.c: Likewise.
+	* bpf-dis.c: Likewise.
+
 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
 	* cgen-opc.c (cgen_get_insn_value): Get an `endian' argument.
diff --git a/opcodes/bpf-desc.c b/opcodes/bpf-desc.c
index abd8c41006..6319f100f3 100644
--- a/opcodes/bpf-desc.c
+++ b/opcodes/bpf-desc.c
@@ -119,8 +119,8 @@ const CGEN_ATTR_TABLE bpf_cgen_insn_attr_table[] =
 /* Instruction set variants.  */
 
 static const CGEN_ISA bpf_cgen_isa_table[] = {
-  { "ebpfle", 64, 8, 64, 128 },
-  { "ebpfbe", 64, 8, 64, 128 },
+  { "ebpfle", 64, 64, 64, 128 },
+  { "ebpfbe", 64, 64, 64, 128 },
   { 0, 0, 0, 0, 0 }
 };
 
diff --git a/opcodes/bpf-dis.c b/opcodes/bpf-dis.c
index 4d01112d25..9425ee7f3c 100644
--- a/opcodes/bpf-dis.c
+++ b/opcodes/bpf-dis.c
@@ -75,7 +75,6 @@ bpf_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
 
   info->bytes_per_chunk = 1;
   info->bytes_per_line = 8;
-  info->endian_code = BFD_ENDIAN_BIG;
 
   /* Attempt to read the base part of the insn.  */
   buflen = cd->base_insn_bitsize / 8;
diff --git a/opcodes/bpf-opc.c b/opcodes/bpf-opc.c
index 3ecd35d8bc..00f3b25f76 100644
--- a/opcodes/bpf-opc.c
+++ b/opcodes/bpf-opc.c
@@ -50,99 +50,99 @@ static const CGEN_IFMT ifmt_empty ATTRIBUTE_UNUSED = {
 };
 
 static const CGEN_IFMT ifmt_addile ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_addrle ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_negle ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_addibe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_addrbe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_negbe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_endlele ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_endlebe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_lddwle ATTRIBUTE_UNUSED = {
-  8, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_lddwbe ATTRIBUTE_UNUSED = {
-  8, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_ldabsw ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_ldindwle ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_ldindwbe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_ldxwle ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_ldxwbe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_stble ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_stbbe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_jeqile ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_jeqrle ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_jeqibe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_jeqrbe ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_callle ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_ja ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 static const CGEN_IFMT ifmt_exit ATTRIBUTE_UNUSED = {
-  8, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
 };
 
 #undef F
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 25816efb56..299c23db13 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -660,6 +660,7 @@ disassemble_init_for_target (struct disassemble_info * info)
 #endif
 #ifdef ARCH_bpf
     case bfd_arch_bpf:
+      info->endian_code = BFD_ENDIAN_LITTLE;
       if (!info->private_data)
 	{
 	  info->private_data = cgen_bitset_create (ISA_EBPFMAX);
-- 
2.25.0.2.g232378479e


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open
  2020-05-29 17:08 ` [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open Jose E. Marchesi
@ 2020-06-01  7:19   ` Alan Modra
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2020-06-01  7:19 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: binutils

On Fri, May 29, 2020 at 07:08:18PM +0200, Jose E. Marchesi via Binutils wrote:
> include/ChangeLog:
> 
> 2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>
> 
> 	* opcode/cgen.h (enum cgen_cpu_open_arg): New value
> 	CGEN_CPU_OPEN_INSN_ENDIAN.
> 
> opcodes/ChangeLog:
> 
> 2020-05-29  Jose E. Marchesi  <jemarch@gnu.org>
> 
> 	* cgen-dis.in (cpu_desc_list): New field `insn_endian'.
> 	(print_insn_): Handle instruction endian.
> 	* bpf-dis.c: Regenerate.
> 	* bpf-desc.c: Regenerate.
> 	* epiphany-dis.c: Likewise.
> 	* epiphany-desc.c: Likewise.
> 	* fr30-dis.c: Likewise.
> 	* fr30-desc.c: Likewise.
> 	* frv-dis.c: Likewise.
> 	* frv-desc.c: Likewise.
> 	* ip2k-dis.c: Likewise.
> 	* ip2k-desc.c: Likewise.
> 	* iq2000-dis.c: Likewise.
> 	* iq2000-desc.c: Likewise.
> 	* lm32-dis.c: Likewise.
> 	* lm32-desc.c: Likewise.
> 	* m32c-dis.c: Likewise.
> 	* m32c-desc.c: Likewise.
> 	* m32r-dis.c: Likewise.
> 	* m32r-desc.c: Likewise.
> 	* mep-dis.c: Likewise.
> 	* mep-desc.c: Likewise.
> 	* mt-dis.c: Likewise.
> 	* mt-desc.c: Likewise.
> 	* or1k-dis.c: Likewise.
> 	* or1k-desc.c: Likewise.
> 	* xc16x-dis.c: Likewise.
> 	* xc16x-desc.c: Likewise.
> 	* xstormy16-dis.c: Likewise.
> 	* xstormy16-desc.c: Likewise.
> 
> binutils/ChangeLog:
> 
> 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
> 
> 	* objdump.c (disassemble_data): Set disasm_info.endian_code to
> 	disasm_info.endian after the later is initialized to the
> 	endianness reported by BFD.

OK, except s/later/latter/ above, and..

> @@ -2269,10 +2271,18 @@ epiphany_cgen_cpu_close (CGEN_CPU_DESC cd)
>  	  regfree (CGEN_INSN_RX (insns));
>      }
>  
> -  free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
> -  free ((CGEN_INSN *) cd->insn_table.init_entries);
> -  free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
> -  free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
> +  if (cd->macro_insn_table.init_entries)
> +    free ((CGEN_INSN *) cd->macro_insn_table.init_entries);
> +
> +  if (cd->insn_table.init_entries)
> +    free ((CGEN_INSN *) cd->insn_table.init_entries);
> +
> +  if (cd->hw_table.entries)
> +    free ((CGEN_HW_ENTRY *) cd->hw_table.entries);
> +
> +  if (cd->operand_table.entries)
> +    free ((CGEN_HW_ENTRY *) cd->operand_table.entries);
> +
>    free (cd);
>  }
>  

Please ensure your copy of cgen is up to date before regenerating.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports
  2020-05-29 17:08 ` [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports Jose E. Marchesi
@ 2020-06-01  7:31   ` Alan Modra
  2020-06-02 12:47     ` Jose E. Marchesi
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Modra @ 2020-06-01  7:31 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: binutils

On Fri, May 29, 2020 at 07:08:19PM +0200, Jose E. Marchesi via Binutils wrote:
> @@ -906,13 +907,15 @@ gas_cgen_md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
>  	  {
>  	    CGEN_INSN_INT insn_value =
>  	      cgen_get_insn_value (cd, (unsigned char *) where,
> -				   CGEN_INSN_BITSIZE (insn));
> +				   CGEN_INSN_BITSIZE (insn),
> +                                   cd->endian);
>  
>  	    /* ??? 0 is passed for `pc'.  */
>  	    errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
>  						   &insn_value, (bfd_vma) 0);
>  	    cgen_put_insn_value (cd, (unsigned char *) where,
> -				 CGEN_INSN_BITSIZE (insn), insn_value);
> +				 CGEN_INSN_BITSIZE (insn), insn_value,
> +                                 cd->endian);
>  	  }
>  #else
>  	  /* ??? 0 is passed for `pc'.  */

The above looks to be a typo.  Shouldn't you be using instruction
endianness here when modifying instruction operand fields?  The same
question applies for tc-bpf.c and tc-mep changes.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/3] cpu, gas, opcodes: remove no longer needed workaround from the BPF port
  2020-05-29 17:08 ` [PATCH 3/3] cpu, gas, opcodes: remove no longer needed workaround from the BPF port Jose E. Marchesi
@ 2020-06-01  7:34   ` Alan Modra
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2020-06-01  7:34 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: binutils

On Fri, May 29, 2020 at 07:08:20PM +0200, Jose E. Marchesi via Binutils wrote:
> cpu/ChangeLog:
> 
> 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
> 
> 	* bpf.cpu (define-bpf-isa): Set base-insn-bitsize to 64.
> 	* bpf.opc (bpf_print_insn): Do not set endian_code here.
> 
> gas/ChangeLog:
> 
> 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
> 
> 	* config/tc-bpf.c (md_begin): Pass CGEN_CPU_OPEN_INSN_ENDIAN to
> 	bpf_cgen_cpu_open.
> 	(md_assemble): Remove no longer needed hack.
> 
> opcodes/ChangeLog:
> 
> 2020-05-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
> 
> 	* disassemble.c (disassemble_init_for_target): Set endian_code for
> 	bpf targets.
> 	* bpf-desc.c: Regenerate.
> 	* bpf-opc.c: Likewise.
> 	* bpf-dis.c: Likewise.

You can self-approve this one.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports
  2020-06-01  7:31   ` Alan Modra
@ 2020-06-02 12:47     ` Jose E. Marchesi
  2020-06-02 13:29       ` Jose E. Marchesi
  0 siblings, 1 reply; 9+ messages in thread
From: Jose E. Marchesi @ 2020-06-02 12:47 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils


Hi Alan.
Thanks for the review.

    On Fri, May 29, 2020 at 07:08:19PM +0200, Jose E. Marchesi via Binutils wrote:
    > @@ -906,13 +907,15 @@ gas_cgen_md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
    >  	  {
    >  	    CGEN_INSN_INT insn_value =
    >  	      cgen_get_insn_value (cd, (unsigned char *) where,
    > -				   CGEN_INSN_BITSIZE (insn));
    > +				   CGEN_INSN_BITSIZE (insn),
    > +                                   cd->endian);
    >  
    >  	    /* ??? 0 is passed for `pc'.  */
    >  	    errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
    >  						   &insn_value, (bfd_vma) 0);
    >  	    cgen_put_insn_value (cd, (unsigned char *) where,
    > -				 CGEN_INSN_BITSIZE (insn), insn_value);
    > +				 CGEN_INSN_BITSIZE (insn), insn_value,
    > +                                 cd->endian);
    >  	  }
    >  #else
    >  	  /* ??? 0 is passed for `pc'.  */
    
    The above looks to be a typo.  Shouldn't you be using instruction
    endianness here when modifying instruction operand fields?  The same
    question applies for tc-bpf.c and tc-mep changes.

Hm, that's actually the main point of the patch: for the CGEN-based
ports to being able to use a different endianness for constant opcode
fields than the one used to encode the contents of operand fields.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports
  2020-06-02 12:47     ` Jose E. Marchesi
@ 2020-06-02 13:29       ` Jose E. Marchesi
  0 siblings, 0 replies; 9+ messages in thread
From: Jose E. Marchesi @ 2020-06-02 13:29 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils


        >  	  {
        >  	    CGEN_INSN_INT insn_value =
        >  	      cgen_get_insn_value (cd, (unsigned char *) where,
        > -				   CGEN_INSN_BITSIZE (insn));
        > +				   CGEN_INSN_BITSIZE (insn),
        > +                                   cd->endian);
        >  
        >  	    /* ??? 0 is passed for `pc'.  */
        >  	    errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
        >  						   &insn_value, (bfd_vma) 0);
        >  	    cgen_put_insn_value (cd, (unsigned char *) where,
        > -				 CGEN_INSN_BITSIZE (insn), insn_value);
        > +				 CGEN_INSN_BITSIZE (insn), insn_value,
        > +                                 cd->endian);
        >  	  }
        >  #else
        >  	  /* ??? 0 is passed for `pc'.  */
        
        The above looks to be a typo.  Shouldn't you be using instruction
        endianness here when modifying instruction operand fields?  The same
        question applies for tc-bpf.c and tc-mep changes.
    
    Hm, that's actually the main point of the patch: for the CGEN-based
    ports to being able to use a different endianness for constant opcode
    fields than the one used to encode the contents of operand fields.

Argh please scratch that, you are right.  It was a typo, in both
gas/cgen.c and gas/config/gc-mep.c.  It didn't break anything due to the
fact endian == insn_endian in all the impacted targets, but an error
nevertheless.  Fixing it.

On the other hand this doesn't apply to the BPF port: the
cgen_put_insn_value in gas/config/tc-bpf.c should definitely use endian
and not insn_endian.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-06-02 13:29 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-29 17:08 [PATCH 0/3] Improve insn endianness support in CGEN ports Jose E. Marchesi
2020-05-29 17:08 ` [PATCH 1/3] opcodes: support insn endianness in cgen_cpu_open Jose E. Marchesi
2020-06-01  7:19   ` Alan Modra
2020-05-29 17:08 ` [PATCH 2/3] opcodes: discriminate endianness and insn-endianness in CGEN ports Jose E. Marchesi
2020-06-01  7:31   ` Alan Modra
2020-06-02 12:47     ` Jose E. Marchesi
2020-06-02 13:29       ` Jose E. Marchesi
2020-05-29 17:08 ` [PATCH 3/3] cpu, gas, opcodes: remove no longer needed workaround from the BPF port Jose E. Marchesi
2020-06-01  7:34   ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).