This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Targetting S12Z


I think the S12Z target has reached the stage where it could be considered for
committing.  The status is as follows:

* The assembler and disassembler are complete, and have 291 tests.  I consider it to
  be fairly robust.  Probably however error reporting and recovery could be improved.

* The linker works - that is to say it does everthing I wanted it to.  However a rather
  large number of tests (37 to be precise) fail.   To me this is odd, because I haven't
  changed anything in the linker.  Also when I look in detail at these failing tests, 
  either a) I can't understand what they are trying to do; or b) I can undestand what
  they are doing, but can't understand why anyone would consider the tested behaviour
  to be desireable.  If someone can enlighten me on any of these that would be great.
  Otherwise, I suggest disabling those tests for this architecture.

* Similarly, there are few objdump tests which are failing for unknown reasons.  Again,
  the tested for behaviour seems odd IMO.

* There are no relaxes (yet).  Various opportunities for relaxation exist and would
  make the linked code somewhat smaller.

* The code follows the GCS at least to the extent that existing binutils code does.

If anyone has both the time and skills to review the code and provide feedback for 
the attached patch, that would be great.

J'



On Mon, Jan 08, 2018 at 09:14:57AM +0000, Nick Clifton wrote:
     
     We are open to supporting new (or even old) architectures, but there are a few
     caveats ...
     
       * You would need to have an FSF Copyright Assignment for the Binutils
         in place before we could accept your contribution.  (I can provide
         you with the necessary application form if you wish).
     
       * The code you submit should follow the GNU Coding Standards.
     
       * Ideally the port should include both the assembler *and* the linker.
         Being able to assemble object files but not link them is frustrating
         for users.
     
       * The port should include some new tests in the assembler testsuite, to
         make sure that assembling and disassembling is working correctly.  If
         you are including a port of the linker as well, then some new linker
         tests would also be appropriate.
     
       * You should consider whether you are willing to become a maintainer for
         the port.  A port without a maintainer is likely to bit-rot away over
         time, whereas a port with an active maintainer will continue to grow
         and blossom.  (OK, maybe I got a little bit too prosaic there, but I
         hope that you take my meaning).
     
     Cheers
       Nick
     
     PS.  Are details of the S12Z architecture, especially the ISA and ABI, available
       publicly ?  If so, please could you point me at them ?
     




-- 
Avoid eavesdropping.  Send strong encrypted email.
PGP Public key ID: 1024D/2DE827B3 
fingerprint = 8797 A26D 0854 2EAB 0285  A290 8A67 719C 2DE8 27B3
See http://sks-keyservers.net or any PGP keyserver for public key.

From 23cc51c0ed3877027eadb495b178c8de0032a409 Mon Sep 17 00:00:00 2001
From: John Darrington <john@darrington.wattle.id.au>
Date: Thu, 4 Jan 2018 12:27:12 +0100
Subject: [PATCH] Add target S12Z

---
 bfd/Makefile.am                                 |    4 +
 bfd/Makefile.in                                 |    6 +
 bfd/archures.c                                  |    4 +
 bfd/bfd-in.h                                    |    2 +
 bfd/bfd-in2.h                                   |    9 +
 bfd/config.bfd                                  |    4 +
 bfd/configure                                   |    1 +
 bfd/configure.ac                                |    1 +
 bfd/cpu-s12z.c                                  |   41 +
 bfd/elf32-s12z.c                                |  331 ++
 bfd/libbfd.c                                    |   21 +
 bfd/libbfd.h                                    |    1 +
 bfd/reloc.c                                     |   17 +
 bfd/targets.c                                   |    3 +
 binutils/readelf.c                              |    7 +
 binutils/testsuite/lib/binutils-common.exp      |    2 +-
 gas/Makefile.am                                 |    2 +
 gas/Makefile.in                                 |   17 +
 gas/NEWS                                        |    2 +
 gas/config/tc-s12z.c                            | 3840 +++++++++++++++++++++++
 gas/config/tc-s12z.h                            |  105 +
 gas/configure.tgt                               |    3 +
 gas/doc/Makefile.am                             |    1 +
 gas/doc/Makefile.in                             |    1 +
 gas/doc/all.texi                                |    1 +
 gas/doc/as.texinfo                              |    7 +
 gas/doc/c-s12z.texi                             |  212 ++
 gas/testsuite/gas/s12z/abs.d                    |   19 +
 gas/testsuite/gas/s12z/abs.s                    |    8 +
 gas/testsuite/gas/s12z/adc-imm.d                |   21 +
 gas/testsuite/gas/s12z/adc-imm.s                |    8 +
 gas/testsuite/gas/s12z/adc-opr.d                |   21 +
 gas/testsuite/gas/s12z/adc-opr.s                |    9 +
 gas/testsuite/gas/s12z/add-imm.d                |   21 +
 gas/testsuite/gas/s12z/add-imm.s                |    8 +
 gas/testsuite/gas/s12z/add-opr.d                |   21 +
 gas/testsuite/gas/s12z/add-opr.s                |    9 +
 gas/testsuite/gas/s12z/and-imm.d                |   21 +
 gas/testsuite/gas/s12z/and-imm.s                |    8 +
 gas/testsuite/gas/s12z/and-opr.d                |   22 +
 gas/testsuite/gas/s12z/and-opr.s                |    9 +
 gas/testsuite/gas/s12z/and-or-cc.d              |   13 +
 gas/testsuite/gas/s12z/and-or-cc.s              |    2 +
 gas/testsuite/gas/s12z/bfext-special.d          |   13 +
 gas/testsuite/gas/s12z/bfext-special.s          |    2 +
 gas/testsuite/gas/s12z/bfext.d                  |   47 +
 gas/testsuite/gas/s12z/bfext.s                  |   23 +
 gas/testsuite/gas/s12z/bit-manip.d              |   26 +
 gas/testsuite/gas/s12z/bit-manip.s              |   16 +
 gas/testsuite/gas/s12z/bit.d                    |   33 +
 gas/testsuite/gas/s12z/bit.s                    |   17 +
 gas/testsuite/gas/s12z/bra-expression-defined.d |   23 +
 gas/testsuite/gas/s12z/bra-expression-defined.s |   11 +
 gas/testsuite/gas/s12z/bra-expression-undef.d   |   24 +
 gas/testsuite/gas/s12z/bra-expression-undef.s   |    9 +
 gas/testsuite/gas/s12z/bra.d                    |   34 +
 gas/testsuite/gas/s12z/bra.s                    |   20 +
 gas/testsuite/gas/s12z/brclr-symbols.d          |   32 +
 gas/testsuite/gas/s12z/brclr-symbols.s          |    9 +
 gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d  |   23 +
 gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s  |    7 +
 gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d  |   21 +
 gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s  |    5 +
 gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d  |   24 +
 gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s  |   12 +
 gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d  |   19 +
 gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s  |    6 +
 gas/testsuite/gas/s12z/clb.d                    |   19 +
 gas/testsuite/gas/s12z/clb.s                    |    8 +
 gas/testsuite/gas/s12z/clr-opr.d                |   15 +
 gas/testsuite/gas/s12z/clr-opr.s                |    5 +
 gas/testsuite/gas/s12z/clr.d                    |   21 +
 gas/testsuite/gas/s12z/clr.s                    |   10 +
 gas/testsuite/gas/s12z/cmp-imm.d                |   23 +
 gas/testsuite/gas/s12z/cmp-imm.s                |   12 +
 gas/testsuite/gas/s12z/cmp-opr-inc.d            |   21 +
 gas/testsuite/gas/s12z/cmp-opr-inc.s            |   11 +
 gas/testsuite/gas/s12z/cmp-opr-rdirect.d        |   19 +
 gas/testsuite/gas/s12z/cmp-opr-rdirect.s        |    9 +
 gas/testsuite/gas/s12z/cmp-opr-reg.d            |   19 +
 gas/testsuite/gas/s12z/cmp-opr-reg.s            |    9 +
 gas/testsuite/gas/s12z/cmp-opr-rindirect.d      |   19 +
 gas/testsuite/gas/s12z/cmp-opr-rindirect.s      |    9 +
 gas/testsuite/gas/s12z/cmp-opr-sxe4.d           |   21 +
 gas/testsuite/gas/s12z/cmp-opr-sxe4.s           |   10 +
 gas/testsuite/gas/s12z/cmp-opr-xys.d            |   19 +
 gas/testsuite/gas/s12z/cmp-opr-xys.s            |    9 +
 gas/testsuite/gas/s12z/cmp-s-imm.d              |   27 +
 gas/testsuite/gas/s12z/cmp-s-imm.s              |   10 +
 gas/testsuite/gas/s12z/cmp-s-opr.d              |   25 +
 gas/testsuite/gas/s12z/cmp-s-opr.s              |   10 +
 gas/testsuite/gas/s12z/cmp-xy.d                 |   12 +
 gas/testsuite/gas/s12z/cmp-xy.s                 |    1 +
 gas/testsuite/gas/s12z/com-opr.d                |   15 +
 gas/testsuite/gas/s12z/com-opr.s                |    3 +
 gas/testsuite/gas/s12z/complex-shifts.d         |   18 +
 gas/testsuite/gas/s12z/complex-shifts.s         |    4 +
 gas/testsuite/gas/s12z/db-tb-cc-opr.d           |   30 +
 gas/testsuite/gas/s12z/db-tb-cc-opr.s           |   11 +
 gas/testsuite/gas/s12z/db-tb-cc-reg.d           |   31 +
 gas/testsuite/gas/s12z/db-tb-cc-reg.s           |   21 +
 gas/testsuite/gas/s12z/dbCC.d                   |   27 +
 gas/testsuite/gas/s12z/dbCC.s                   |    7 +
 gas/testsuite/gas/s12z/dec-opr.d                |   15 +
 gas/testsuite/gas/s12z/dec-opr.s                |    3 +
 gas/testsuite/gas/s12z/dec.d                    |   19 +
 gas/testsuite/gas/s12z/dec.s                    |    8 +
 gas/testsuite/gas/s12z/div.d                    |   23 +
 gas/testsuite/gas/s12z/div.s                    |    8 +
 gas/testsuite/gas/s12z/eor.d                    |   33 +
 gas/testsuite/gas/s12z/eor.s                    |   17 +
 gas/testsuite/gas/s12z/exg.d                    |   29 +
 gas/testsuite/gas/s12z/exg.s                    |   18 +
 gas/testsuite/gas/s12z/ext24-ld-xy.d            |   12 +
 gas/testsuite/gas/s12z/ext24-ld-xy.s            |    2 +
 gas/testsuite/gas/s12z/inc-opr.d                |   15 +
 gas/testsuite/gas/s12z/inc-opr.s                |    3 +
 gas/testsuite/gas/s12z/inc.d                    |   19 +
 gas/testsuite/gas/s12z/inc.s                    |    8 +
 gas/testsuite/gas/s12z/inh.d                    |   15 +
 gas/testsuite/gas/s12z/inh.s                    |    5 +
 gas/testsuite/gas/s12z/jmp.d                    |   33 +
 gas/testsuite/gas/s12z/jmp.s                    |   20 +
 gas/testsuite/gas/s12z/jsr.d                    |   33 +
 gas/testsuite/gas/s12z/jsr.s                    |   20 +
 gas/testsuite/gas/s12z/ld-imm-page2.d           |   15 +
 gas/testsuite/gas/s12z/ld-imm-page2.s           |    2 +
 gas/testsuite/gas/s12z/ld-imm.d                 |   25 +
 gas/testsuite/gas/s12z/ld-imm.s                 |   16 +
 gas/testsuite/gas/s12z/ld-immu18.d              |   28 +
 gas/testsuite/gas/s12z/ld-immu18.s              |   10 +
 gas/testsuite/gas/s12z/ld-large-direct.d        |   21 +
 gas/testsuite/gas/s12z/ld-large-direct.s        |   11 +
 gas/testsuite/gas/s12z/ld-opr.d                 |   22 +
 gas/testsuite/gas/s12z/ld-opr.s                 |   10 +
 gas/testsuite/gas/s12z/ld-s-opr.d               |   16 +
 gas/testsuite/gas/s12z/ld-s-opr.s               |    4 +
 gas/testsuite/gas/s12z/ld-small-direct.d        |   31 +
 gas/testsuite/gas/s12z/ld-small-direct.s        |   11 +
 gas/testsuite/gas/s12z/lea-immu18.d             |   14 +
 gas/testsuite/gas/s12z/lea-immu18.s             |    3 +
 gas/testsuite/gas/s12z/lea.d                    |   18 +
 gas/testsuite/gas/s12z/lea.s                    |    8 +
 gas/testsuite/gas/s12z/mac.d                    |   23 +
 gas/testsuite/gas/s12z/mac.s                    |    8 +
 gas/testsuite/gas/s12z/min-max.d                |   48 +
 gas/testsuite/gas/s12z/min-max.s                |   32 +
 gas/testsuite/gas/s12z/mod.d                    |   23 +
 gas/testsuite/gas/s12z/mod.s                    |    8 +
 gas/testsuite/gas/s12z/mov.d                    |   26 +
 gas/testsuite/gas/s12z/mov.s                    |    8 +
 gas/testsuite/gas/s12z/mul-imm.d                |   19 +
 gas/testsuite/gas/s12z/mul-imm.s                |    6 +
 gas/testsuite/gas/s12z/mul-opr-opr.d            |   19 +
 gas/testsuite/gas/s12z/mul-opr-opr.s            |    6 +
 gas/testsuite/gas/s12z/mul-opr.d                |   17 +
 gas/testsuite/gas/s12z/mul-opr.s                |    6 +
 gas/testsuite/gas/s12z/mul-reg.d                |   27 +
 gas/testsuite/gas/s12z/mul-reg.s                |   16 +
 gas/testsuite/gas/s12z/mul.d                    |   19 +
 gas/testsuite/gas/s12z/mul.s                    |    6 +
 gas/testsuite/gas/s12z/neg-opr.d                |   34 +
 gas/testsuite/gas/s12z/neg-opr.s                |   21 +
 gas/testsuite/gas/s12z/not-so-simple-shifts.d   |   17 +
 gas/testsuite/gas/s12z/not-so-simple-shifts.s   |    4 +
 gas/testsuite/gas/s12z/opr-18u.d                |   26 +
 gas/testsuite/gas/s12z/opr-18u.s                |   15 +
 gas/testsuite/gas/s12z/opr-expr.d               |   13 +
 gas/testsuite/gas/s12z/opr-expr.s               |    5 +
 gas/testsuite/gas/s12z/opr-ext-18.d             |   13 +
 gas/testsuite/gas/s12z/opr-ext-18.s             |    5 +
 gas/testsuite/gas/s12z/opr-idx-24-reg.d         |   13 +
 gas/testsuite/gas/s12z/opr-idx-24-reg.s         |    2 +
 gas/testsuite/gas/s12z/opr-idx3-reg.d           |   17 +
 gas/testsuite/gas/s12z/opr-idx3-reg.s           |    3 +
 gas/testsuite/gas/s12z/opr-idx3-xysp-24.d       |   15 +
 gas/testsuite/gas/s12z/opr-idx3-xysp-24.s       |    3 +
 gas/testsuite/gas/s12z/opr-indirect-expr.d      |   14 +
 gas/testsuite/gas/s12z/opr-indirect-expr.s      |    1 +
 gas/testsuite/gas/s12z/opr-symbol.d             |  170 +
 gas/testsuite/gas/s12z/opr-symbol.s             |  109 +
 gas/testsuite/gas/s12z/or-imm.d                 |   21 +
 gas/testsuite/gas/s12z/or-imm.s                 |    8 +
 gas/testsuite/gas/s12z/or-opr.d                 |   21 +
 gas/testsuite/gas/s12z/or-opr.s                 |    8 +
 gas/testsuite/gas/s12z/p2-mul.d                 |   17 +
 gas/testsuite/gas/s12z/p2-mul.s                 |    7 +
 gas/testsuite/gas/s12z/page2-inh.d              |   15 +
 gas/testsuite/gas/s12z/page2-inh.s              |    5 +
 gas/testsuite/gas/s12z/psh-pul.d                |   21 +
 gas/testsuite/gas/s12z/psh-pul.s                |    8 +
 gas/testsuite/gas/s12z/qmul.d                   |   23 +
 gas/testsuite/gas/s12z/qmul.s                   |    8 +
 gas/testsuite/gas/s12z/rotate.d                 |   22 +
 gas/testsuite/gas/s12z/rotate.s                 |   10 +
 gas/testsuite/gas/s12z/s12z.exp                 |  132 +
 gas/testsuite/gas/s12z/sat.d                    |   19 +
 gas/testsuite/gas/s12z/sat.s                    |    8 +
 gas/testsuite/gas/s12z/sbc-imm.d                |   21 +
 gas/testsuite/gas/s12z/sbc-imm.s                |    8 +
 gas/testsuite/gas/s12z/sbc-opr.d                |   23 +
 gas/testsuite/gas/s12z/sbc-opr.s                |    9 +
 gas/testsuite/gas/s12z/shift.d                  |   22 +
 gas/testsuite/gas/s12z/shift.s                  |   11 +
 gas/testsuite/gas/s12z/simple-shift.d           |   18 +
 gas/testsuite/gas/s12z/simple-shift.s           |    9 +
 gas/testsuite/gas/s12z/single-ops.d             |   15 +
 gas/testsuite/gas/s12z/single-ops.s             |    4 +
 gas/testsuite/gas/s12z/specd6.d                 |   14 +
 gas/testsuite/gas/s12z/specd6.s                 |    4 +
 gas/testsuite/gas/s12z/st-large-direct.d        |   21 +
 gas/testsuite/gas/s12z/st-large-direct.s        |   11 +
 gas/testsuite/gas/s12z/st-opr.d                 |   22 +
 gas/testsuite/gas/s12z/st-opr.s                 |   10 +
 gas/testsuite/gas/s12z/st-s-opr.d               |   16 +
 gas/testsuite/gas/s12z/st-s-opr.s               |    4 +
 gas/testsuite/gas/s12z/st-small-direct.d        |   34 +
 gas/testsuite/gas/s12z/st-small-direct.s        |   12 +
 gas/testsuite/gas/s12z/st-xy.d                  |   12 +
 gas/testsuite/gas/s12z/st-xy.s                  |    3 +
 gas/testsuite/gas/s12z/sub-imm.d                |   21 +
 gas/testsuite/gas/s12z/sub-imm.s                |    8 +
 gas/testsuite/gas/s12z/sub-opr.d                |   22 +
 gas/testsuite/gas/s12z/sub-opr.s                |    9 +
 gas/testsuite/gas/s12z/tfr.d                    |   20 +
 gas/testsuite/gas/s12z/tfr.s                    |    9 +
 gas/testsuite/gas/s12z/trap.d                   |  105 +
 gas/testsuite/gas/s12z/trap.s                   |   96 +
 include/elf/s12z.h                              |   36 +
 ld/Makefile.am                                  |    5 +
 ld/Makefile.in                                  |    6 +
 ld/configure.tgt                                |    2 +
 ld/emulparams/m9s12zelf.sh                      |   18 +
 ld/scripttempl/elfm9s12z.sc                     |  444 +++
 ld/testsuite/ld-discard/static.d                |    2 +-
 ld/testsuite/ld-elf/endsym.d                    |    2 +-
 ld/testsuite/ld-elf/merge.d                     |    2 +-
 ld/testsuite/ld-elf/pr14926.d                   |    2 +-
 ld/testsuite/ld-elf/sec64k.exp                  |    1 +
 ld/testsuite/ld-s12z/opr-linking.d              |   20 +
 ld/testsuite/ld-s12z/opr-linking.s              |    7 +
 ld/testsuite/ld-s12z/relative-linking.d         |   14 +
 ld/testsuite/ld-s12z/relative-linking.s         |    5 +
 ld/testsuite/ld-s12z/z12s.exp                   |   33 +
 opcodes/Makefile.am                             |    1 +
 opcodes/Makefile.in                             |    2 +
 opcodes/configure                               |    1 +
 opcodes/configure.ac                            |    1 +
 opcodes/disassemble.c                           |    5 +
 opcodes/disassemble.h                           |    1 +
 opcodes/s12z-dis.c                              | 2672 ++++++++++++++++
 opcodes/s12z.h                                  |   71 +
 252 files changed, 11595 insertions(+), 5 deletions(-)
 create mode 100644 bfd/cpu-s12z.c
 create mode 100644 bfd/elf32-s12z.c
 create mode 100644 gas/config/tc-s12z.c
 create mode 100644 gas/config/tc-s12z.h
 create mode 100644 gas/doc/c-s12z.texi
 create mode 100644 gas/testsuite/gas/s12z/abs.d
 create mode 100644 gas/testsuite/gas/s12z/abs.s
 create mode 100644 gas/testsuite/gas/s12z/adc-imm.d
 create mode 100644 gas/testsuite/gas/s12z/adc-imm.s
 create mode 100644 gas/testsuite/gas/s12z/adc-opr.d
 create mode 100644 gas/testsuite/gas/s12z/adc-opr.s
 create mode 100644 gas/testsuite/gas/s12z/add-imm.d
 create mode 100644 gas/testsuite/gas/s12z/add-imm.s
 create mode 100644 gas/testsuite/gas/s12z/add-opr.d
 create mode 100644 gas/testsuite/gas/s12z/add-opr.s
 create mode 100644 gas/testsuite/gas/s12z/and-imm.d
 create mode 100644 gas/testsuite/gas/s12z/and-imm.s
 create mode 100644 gas/testsuite/gas/s12z/and-opr.d
 create mode 100644 gas/testsuite/gas/s12z/and-opr.s
 create mode 100644 gas/testsuite/gas/s12z/and-or-cc.d
 create mode 100644 gas/testsuite/gas/s12z/and-or-cc.s
 create mode 100644 gas/testsuite/gas/s12z/bfext-special.d
 create mode 100644 gas/testsuite/gas/s12z/bfext-special.s
 create mode 100644 gas/testsuite/gas/s12z/bfext.d
 create mode 100644 gas/testsuite/gas/s12z/bfext.s
 create mode 100644 gas/testsuite/gas/s12z/bit-manip.d
 create mode 100644 gas/testsuite/gas/s12z/bit-manip.s
 create mode 100644 gas/testsuite/gas/s12z/bit.d
 create mode 100644 gas/testsuite/gas/s12z/bit.s
 create mode 100644 gas/testsuite/gas/s12z/bra-expression-defined.d
 create mode 100644 gas/testsuite/gas/s12z/bra-expression-defined.s
 create mode 100644 gas/testsuite/gas/s12z/bra-expression-undef.d
 create mode 100644 gas/testsuite/gas/s12z/bra-expression-undef.s
 create mode 100644 gas/testsuite/gas/s12z/bra.d
 create mode 100644 gas/testsuite/gas/s12z/bra.s
 create mode 100644 gas/testsuite/gas/s12z/brclr-symbols.d
 create mode 100644 gas/testsuite/gas/s12z/brclr-symbols.s
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d
 create mode 100644 gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s
 create mode 100644 gas/testsuite/gas/s12z/clb.d
 create mode 100644 gas/testsuite/gas/s12z/clb.s
 create mode 100644 gas/testsuite/gas/s12z/clr-opr.d
 create mode 100644 gas/testsuite/gas/s12z/clr-opr.s
 create mode 100644 gas/testsuite/gas/s12z/clr.d
 create mode 100644 gas/testsuite/gas/s12z/clr.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-imm.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-imm.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-inc.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-inc.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-rdirect.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-rdirect.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-reg.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-reg.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-rindirect.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-rindirect.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-sxe4.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-sxe4.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-xys.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-opr-xys.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-s-imm.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-s-imm.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-s-opr.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-s-opr.s
 create mode 100644 gas/testsuite/gas/s12z/cmp-xy.d
 create mode 100644 gas/testsuite/gas/s12z/cmp-xy.s
 create mode 100644 gas/testsuite/gas/s12z/com-opr.d
 create mode 100644 gas/testsuite/gas/s12z/com-opr.s
 create mode 100644 gas/testsuite/gas/s12z/complex-shifts.d
 create mode 100644 gas/testsuite/gas/s12z/complex-shifts.s
 create mode 100644 gas/testsuite/gas/s12z/db-tb-cc-opr.d
 create mode 100644 gas/testsuite/gas/s12z/db-tb-cc-opr.s
 create mode 100644 gas/testsuite/gas/s12z/db-tb-cc-reg.d
 create mode 100644 gas/testsuite/gas/s12z/db-tb-cc-reg.s
 create mode 100644 gas/testsuite/gas/s12z/dbCC.d
 create mode 100644 gas/testsuite/gas/s12z/dbCC.s
 create mode 100644 gas/testsuite/gas/s12z/dec-opr.d
 create mode 100644 gas/testsuite/gas/s12z/dec-opr.s
 create mode 100644 gas/testsuite/gas/s12z/dec.d
 create mode 100644 gas/testsuite/gas/s12z/dec.s
 create mode 100644 gas/testsuite/gas/s12z/div.d
 create mode 100644 gas/testsuite/gas/s12z/div.s
 create mode 100644 gas/testsuite/gas/s12z/eor.d
 create mode 100644 gas/testsuite/gas/s12z/eor.s
 create mode 100644 gas/testsuite/gas/s12z/exg.d
 create mode 100644 gas/testsuite/gas/s12z/exg.s
 create mode 100644 gas/testsuite/gas/s12z/ext24-ld-xy.d
 create mode 100644 gas/testsuite/gas/s12z/ext24-ld-xy.s
 create mode 100644 gas/testsuite/gas/s12z/inc-opr.d
 create mode 100644 gas/testsuite/gas/s12z/inc-opr.s
 create mode 100644 gas/testsuite/gas/s12z/inc.d
 create mode 100644 gas/testsuite/gas/s12z/inc.s
 create mode 100644 gas/testsuite/gas/s12z/inh.d
 create mode 100644 gas/testsuite/gas/s12z/inh.s
 create mode 100644 gas/testsuite/gas/s12z/jmp.d
 create mode 100644 gas/testsuite/gas/s12z/jmp.s
 create mode 100644 gas/testsuite/gas/s12z/jsr.d
 create mode 100644 gas/testsuite/gas/s12z/jsr.s
 create mode 100644 gas/testsuite/gas/s12z/ld-imm-page2.d
 create mode 100644 gas/testsuite/gas/s12z/ld-imm-page2.s
 create mode 100644 gas/testsuite/gas/s12z/ld-imm.d
 create mode 100644 gas/testsuite/gas/s12z/ld-imm.s
 create mode 100644 gas/testsuite/gas/s12z/ld-immu18.d
 create mode 100644 gas/testsuite/gas/s12z/ld-immu18.s
 create mode 100644 gas/testsuite/gas/s12z/ld-large-direct.d
 create mode 100644 gas/testsuite/gas/s12z/ld-large-direct.s
 create mode 100644 gas/testsuite/gas/s12z/ld-opr.d
 create mode 100644 gas/testsuite/gas/s12z/ld-opr.s
 create mode 100644 gas/testsuite/gas/s12z/ld-s-opr.d
 create mode 100644 gas/testsuite/gas/s12z/ld-s-opr.s
 create mode 100644 gas/testsuite/gas/s12z/ld-small-direct.d
 create mode 100644 gas/testsuite/gas/s12z/ld-small-direct.s
 create mode 100644 gas/testsuite/gas/s12z/lea-immu18.d
 create mode 100644 gas/testsuite/gas/s12z/lea-immu18.s
 create mode 100644 gas/testsuite/gas/s12z/lea.d
 create mode 100644 gas/testsuite/gas/s12z/lea.s
 create mode 100644 gas/testsuite/gas/s12z/mac.d
 create mode 100644 gas/testsuite/gas/s12z/mac.s
 create mode 100644 gas/testsuite/gas/s12z/min-max.d
 create mode 100644 gas/testsuite/gas/s12z/min-max.s
 create mode 100644 gas/testsuite/gas/s12z/mod.d
 create mode 100644 gas/testsuite/gas/s12z/mod.s
 create mode 100644 gas/testsuite/gas/s12z/mov.d
 create mode 100644 gas/testsuite/gas/s12z/mov.s
 create mode 100644 gas/testsuite/gas/s12z/mul-imm.d
 create mode 100644 gas/testsuite/gas/s12z/mul-imm.s
 create mode 100644 gas/testsuite/gas/s12z/mul-opr-opr.d
 create mode 100644 gas/testsuite/gas/s12z/mul-opr-opr.s
 create mode 100644 gas/testsuite/gas/s12z/mul-opr.d
 create mode 100644 gas/testsuite/gas/s12z/mul-opr.s
 create mode 100644 gas/testsuite/gas/s12z/mul-reg.d
 create mode 100644 gas/testsuite/gas/s12z/mul-reg.s
 create mode 100644 gas/testsuite/gas/s12z/mul.d
 create mode 100644 gas/testsuite/gas/s12z/mul.s
 create mode 100644 gas/testsuite/gas/s12z/neg-opr.d
 create mode 100644 gas/testsuite/gas/s12z/neg-opr.s
 create mode 100644 gas/testsuite/gas/s12z/not-so-simple-shifts.d
 create mode 100644 gas/testsuite/gas/s12z/not-so-simple-shifts.s
 create mode 100644 gas/testsuite/gas/s12z/opr-18u.d
 create mode 100644 gas/testsuite/gas/s12z/opr-18u.s
 create mode 100644 gas/testsuite/gas/s12z/opr-expr.d
 create mode 100644 gas/testsuite/gas/s12z/opr-expr.s
 create mode 100644 gas/testsuite/gas/s12z/opr-ext-18.d
 create mode 100644 gas/testsuite/gas/s12z/opr-ext-18.s
 create mode 100644 gas/testsuite/gas/s12z/opr-idx-24-reg.d
 create mode 100644 gas/testsuite/gas/s12z/opr-idx-24-reg.s
 create mode 100644 gas/testsuite/gas/s12z/opr-idx3-reg.d
 create mode 100644 gas/testsuite/gas/s12z/opr-idx3-reg.s
 create mode 100644 gas/testsuite/gas/s12z/opr-idx3-xysp-24.d
 create mode 100644 gas/testsuite/gas/s12z/opr-idx3-xysp-24.s
 create mode 100644 gas/testsuite/gas/s12z/opr-indirect-expr.d
 create mode 100644 gas/testsuite/gas/s12z/opr-indirect-expr.s
 create mode 100644 gas/testsuite/gas/s12z/opr-symbol.d
 create mode 100644 gas/testsuite/gas/s12z/opr-symbol.s
 create mode 100644 gas/testsuite/gas/s12z/or-imm.d
 create mode 100644 gas/testsuite/gas/s12z/or-imm.s
 create mode 100644 gas/testsuite/gas/s12z/or-opr.d
 create mode 100644 gas/testsuite/gas/s12z/or-opr.s
 create mode 100644 gas/testsuite/gas/s12z/p2-mul.d
 create mode 100644 gas/testsuite/gas/s12z/p2-mul.s
 create mode 100644 gas/testsuite/gas/s12z/page2-inh.d
 create mode 100644 gas/testsuite/gas/s12z/page2-inh.s
 create mode 100644 gas/testsuite/gas/s12z/psh-pul.d
 create mode 100644 gas/testsuite/gas/s12z/psh-pul.s
 create mode 100644 gas/testsuite/gas/s12z/qmul.d
 create mode 100644 gas/testsuite/gas/s12z/qmul.s
 create mode 100644 gas/testsuite/gas/s12z/rotate.d
 create mode 100644 gas/testsuite/gas/s12z/rotate.s
 create mode 100644 gas/testsuite/gas/s12z/s12z.exp
 create mode 100644 gas/testsuite/gas/s12z/sat.d
 create mode 100644 gas/testsuite/gas/s12z/sat.s
 create mode 100644 gas/testsuite/gas/s12z/sbc-imm.d
 create mode 100644 gas/testsuite/gas/s12z/sbc-imm.s
 create mode 100644 gas/testsuite/gas/s12z/sbc-opr.d
 create mode 100644 gas/testsuite/gas/s12z/sbc-opr.s
 create mode 100644 gas/testsuite/gas/s12z/shift.d
 create mode 100644 gas/testsuite/gas/s12z/shift.s
 create mode 100644 gas/testsuite/gas/s12z/simple-shift.d
 create mode 100644 gas/testsuite/gas/s12z/simple-shift.s
 create mode 100644 gas/testsuite/gas/s12z/single-ops.d
 create mode 100644 gas/testsuite/gas/s12z/single-ops.s
 create mode 100644 gas/testsuite/gas/s12z/specd6.d
 create mode 100644 gas/testsuite/gas/s12z/specd6.s
 create mode 100644 gas/testsuite/gas/s12z/st-large-direct.d
 create mode 100644 gas/testsuite/gas/s12z/st-large-direct.s
 create mode 100644 gas/testsuite/gas/s12z/st-opr.d
 create mode 100644 gas/testsuite/gas/s12z/st-opr.s
 create mode 100644 gas/testsuite/gas/s12z/st-s-opr.d
 create mode 100644 gas/testsuite/gas/s12z/st-s-opr.s
 create mode 100644 gas/testsuite/gas/s12z/st-small-direct.d
 create mode 100644 gas/testsuite/gas/s12z/st-small-direct.s
 create mode 100644 gas/testsuite/gas/s12z/st-xy.d
 create mode 100644 gas/testsuite/gas/s12z/st-xy.s
 create mode 100644 gas/testsuite/gas/s12z/sub-imm.d
 create mode 100644 gas/testsuite/gas/s12z/sub-imm.s
 create mode 100644 gas/testsuite/gas/s12z/sub-opr.d
 create mode 100644 gas/testsuite/gas/s12z/sub-opr.s
 create mode 100644 gas/testsuite/gas/s12z/tfr.d
 create mode 100644 gas/testsuite/gas/s12z/tfr.s
 create mode 100644 gas/testsuite/gas/s12z/trap.d
 create mode 100644 gas/testsuite/gas/s12z/trap.s
 create mode 100644 include/elf/s12z.h
 create mode 100644 ld/emulparams/m9s12zelf.sh
 create mode 100644 ld/scripttempl/elfm9s12z.sc
 create mode 100644 ld/testsuite/ld-s12z/opr-linking.d
 create mode 100644 ld/testsuite/ld-s12z/opr-linking.s
 create mode 100644 ld/testsuite/ld-s12z/relative-linking.d
 create mode 100644 ld/testsuite/ld-s12z/relative-linking.s
 create mode 100644 ld/testsuite/ld-s12z/z12s.exp
 create mode 100644 opcodes/s12z-dis.c
 create mode 100644 opcodes/s12z.h

diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 8500a4fa74..8374bbda20 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -123,6 +123,7 @@ ALL_MACHINES = \
 	cpu-m68hc11.lo \
 	cpu-m68hc12.lo \
 	cpu-m9s12x.lo \
+	cpu-s12z.lo \
 	cpu-m9s12xg.lo \
 	cpu-m68k.lo \
 	cpu-mcore.lo \
@@ -207,6 +208,7 @@ ALL_MACHINES_CFILES = \
 	cpu-m68hc11.c \
 	cpu-m68hc12.c \
 	cpu-m9s12x.c \
+	cpu-s12z.c \
 	cpu-m9s12xg.c \
 	cpu-m68k.c \
 	cpu-mcore.c \
@@ -322,6 +324,7 @@ BFD32_BACKENDS = \
 	elf32-m68hc12.lo \
 	elf32-m68hc1x.lo \
 	elf32-m68k.lo \
+	elf32-s12z.lo \
 	elf32-mcore.lo \
 	elf32-mep.lo \
 	elf32-metag.lo \
@@ -458,6 +461,7 @@ BFD32_BACKENDS_CFILES = \
 	elf32-m68hc12.c \
 	elf32-m68hc1x.c \
 	elf32-m68k.c \
+	elf32-s12z.c \
 	elf32-mcore.c \
 	elf32-mep.c \
 	elf32-metag.c \
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index ccd9ce1201..88b6b8ebd5 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -456,6 +456,7 @@ ALL_MACHINES = \
 	cpu-m68hc11.lo \
 	cpu-m68hc12.lo \
 	cpu-m9s12x.lo \
+	cpu-s12z.lo \
 	cpu-m9s12xg.lo \
 	cpu-m68k.lo \
 	cpu-mcore.lo \
@@ -540,6 +541,7 @@ ALL_MACHINES_CFILES = \
 	cpu-m68hc11.c \
 	cpu-m68hc12.c \
 	cpu-m9s12x.c \
+	cpu-s12z.c \
 	cpu-m9s12xg.c \
 	cpu-m68k.c \
 	cpu-mcore.c \
@@ -656,6 +658,7 @@ BFD32_BACKENDS = \
 	elf32-m68hc12.lo \
 	elf32-m68hc1x.lo \
 	elf32-m68k.lo \
+	elf32-s12z.lo \
 	elf32-mcore.lo \
 	elf32-mep.lo \
 	elf32-metag.lo \
@@ -792,6 +795,7 @@ BFD32_BACKENDS_CFILES = \
 	elf32-m68hc12.c \
 	elf32-m68hc1x.c \
 	elf32-m68k.c \
+	elf32-s12z.c \
 	elf32-mcore.c \
 	elf32-mep.c \
 	elf32-metag.c \
@@ -1253,6 +1257,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m68k.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m9s12x.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m9s12xg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-s12z.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-mcore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-mep.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-metag.Plo@am__quote@
@@ -1344,6 +1349,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc12.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc1x.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68k.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-s12z.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mcore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mep.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-metag.Plo@am__quote@
diff --git a/bfd/archures.c b/bfd/archures.c
index 4c20664257..3af7ddd19a 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -281,6 +281,8 @@ DESCRIPTION
 .#define bfd_mach_m6812s	2
 .  bfd_arch_m9s12x,    {* Freescale S12X.  *}
 .  bfd_arch_m9s12xg,   {* Freescale XGATE.  *}
+.  bfd_arch_s12z,    {* Freescale S12Z.  *}
+.#define bfd_mach_s12z_default 0
 .  bfd_arch_z8k,       {* Zilog Z8000.  *}
 .#define bfd_mach_z8001		1
 .#define bfd_mach_z8002		2
@@ -590,6 +592,7 @@ extern const bfd_arch_info_type bfd_m68hc11_arch;
 extern const bfd_arch_info_type bfd_m68hc12_arch;
 extern const bfd_arch_info_type bfd_m9s12x_arch;
 extern const bfd_arch_info_type bfd_m9s12xg_arch;
+extern const bfd_arch_info_type bfd_s12z_arch;
 extern const bfd_arch_info_type bfd_m68k_arch;
 extern const bfd_arch_info_type bfd_mcore_arch;
 extern const bfd_arch_info_type bfd_mep_arch;
@@ -679,6 +682,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
     &bfd_m68hc12_arch,
     &bfd_m9s12x_arch,
     &bfd_m9s12xg_arch,
+    &bfd_s12z_arch,
     &bfd_m68k_arch,
     &bfd_mcore_arch,
     &bfd_mep_arch,
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 50a8b52e96..481587e458 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -581,6 +581,8 @@ void bfd_putb64 (bfd_uint64_t, void *);
 void bfd_putl64 (bfd_uint64_t, void *);
 void bfd_putb32 (bfd_vma, void *);
 void bfd_putl32 (bfd_vma, void *);
+void bfd_putb24 (bfd_vma, void *);
+void bfd_putl24 (bfd_vma, void *);
 void bfd_putb16 (bfd_vma, void *);
 void bfd_putl16 (bfd_vma, void *);
 
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 48226860c7..a7833b66db 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -588,6 +588,8 @@ void bfd_putb64 (bfd_uint64_t, void *);
 void bfd_putl64 (bfd_uint64_t, void *);
 void bfd_putb32 (bfd_vma, void *);
 void bfd_putl32 (bfd_vma, void *);
+void bfd_putb24 (bfd_vma, void *);
+void bfd_putl24 (bfd_vma, void *);
 void bfd_putb16 (bfd_vma, void *);
 void bfd_putl16 (bfd_vma, void *);
 
@@ -2151,6 +2153,8 @@ enum bfd_architecture
 #define bfd_mach_m6812s        2
   bfd_arch_m9s12x,    /* Freescale S12X.  */
   bfd_arch_m9s12xg,   /* Freescale XGATE.  */
+  bfd_arch_s12z,    /* Freescale S12Z.  */
+#define bfd_mach_s12z_default 0
   bfd_arch_z8k,       /* Zilog Z8000.  */
 #define bfd_mach_z8001         1
 #define bfd_mach_z8002         2
@@ -5255,6 +5259,11 @@ This is the 8 bit high part of an absolute address and immediately follows
 a matching LO8XG part.  */
   BFD_RELOC_M68HC12_HI8XG,
 
+/* Freescale S12Z reloc.
+This is a 15 bit relative address.  If the most significant bits are all zero
+then it may be truncated to 8 bits.  */
+  BFD_RELOC_S12Z_15_PCREL,
+
 /* NS CR16C Relocations.  */
   BFD_RELOC_16C_NUM08,
   BFD_RELOC_16C_NUM08_C,
diff --git a/bfd/config.bfd b/bfd/config.bfd
index bbd4194153..0db8ed4562 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -179,6 +179,7 @@ lm32)	         targ_archs=bfd_lm32_arch ;;
 m6811*|m68hc11*) targ_archs="bfd_m68hc11_arch bfd_m68hc12_arch bfd_m9s12x_arch bfd_m9s12xg_arch" ;;
 m6812*|m68hc12*) targ_archs="bfd_m68hc12_arch bfd_m68hc11_arch bfd_m9s12x_arch bfd_m9s12xg_arch" ;;
 m68*)		 targ_archs=bfd_m68k_arch ;;
+s12z*)         targ_archs=bfd_s12z_arch ;;
 microblaze*)	 targ_archs=bfd_microblaze_arch ;;
 mips*)		 targ_archs=bfd_mips_arch ;;
 nds32*)		 targ_archs=bfd_nds32_arch ;;
@@ -814,6 +815,9 @@ case "${targ}" in
     targ_defvec=m68k_elf32_vec
     ;;
 
+  s12z-*-*)
+    targ_defvec=s12z_elf32_vec
+    ;;
   mcore-*-elf)
     targ_defvec=mcore_elf32_be_vec
     targ_selvecs="mcore_elf32_be_vec mcore_elf32_le_vec"
diff --git a/bfd/configure b/bfd/configure
index 5aca725edc..ff86c0a36b 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -14432,6 +14432,7 @@ do
     m68hc11_elf32_vec)		 tb="$tb elf32-m68hc11.lo elf32-m68hc1x.lo elf32.lo $elf" ;;
     m68hc12_elf32_vec)		 tb="$tb elf32-m68hc12.lo elf32-m68hc1x.lo elf32.lo $elf" ;;
     m68k_elf32_vec)		 tb="$tb elf32-m68k.lo elf32.lo $elf" ;;
+    s12z_elf32_vec)		 tb="$tb elf32-s12z.lo elf32.lo $elf" ;;
     mach_o_be_vec)		 tb="$tb mach-o.lo dwarf2.lo" ;;
     mach_o_le_vec)		 tb="$tb mach-o.lo dwarf2.lo" ;;
     mach_o_fat_vec)		 tb="$tb mach-o.lo dwarf2.lo" ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 3cef5f9a9e..44eea05cef 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -509,6 +509,7 @@ do
     m68hc11_elf32_vec)		 tb="$tb elf32-m68hc11.lo elf32-m68hc1x.lo elf32.lo $elf" ;;
     m68hc12_elf32_vec)		 tb="$tb elf32-m68hc12.lo elf32-m68hc1x.lo elf32.lo $elf" ;;
     m68k_elf32_vec)		 tb="$tb elf32-m68k.lo elf32.lo $elf" ;;
+    s12z_elf32_vec)		 tb="$tb elf32-s12z.lo elf32.lo $elf" ;;
     mach_o_be_vec)		 tb="$tb mach-o.lo dwarf2.lo" ;;
     mach_o_le_vec)		 tb="$tb mach-o.lo dwarf2.lo" ;;
     mach_o_fat_vec)		 tb="$tb mach-o.lo dwarf2.lo" ;;
diff --git a/bfd/cpu-s12z.c b/bfd/cpu-s12z.c
new file mode 100644
index 0000000000..07bcb49a69
--- /dev/null
+++ b/bfd/cpu-s12z.c
@@ -0,0 +1,41 @@
+/* BFD support for the Freescale 9S12Z processor
+   Copyright (C) 2008-2018 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_s12z_arch =
+{
+    16,	/* 16 bits in a word.  */
+    24,	/* 24 bits in an address.  */
+    8,	/* 8 bits in a byte.  */
+    bfd_arch_s12z,
+    0,
+    "s12z",
+    "s12z",
+    4, /* Section alignment power.  */
+    TRUE,
+    bfd_default_compatible,
+    bfd_default_scan,
+    bfd_arch_default_fill,
+    0,
+};
+
diff --git a/bfd/elf32-s12z.c b/bfd/elf32-s12z.c
new file mode 100644
index 0000000000..123b2d604e
--- /dev/null
+++ b/bfd/elf32-s12z.c
@@ -0,0 +1,331 @@
+/* Freescale S12Z-specific support for 32-bit ELF
+   Copyright (C) 1999-2018 Free Software Foundation, Inc.
+   (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+#include "elf/s12z.h"
+
+/* Relocation functions.  */
+static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
+  (bfd *, bfd_reloc_code_real_type);
+static bfd_boolean s12z_info_to_howto_rel
+  (bfd *, arelent *, Elf_Internal_Rela *);
+
+static bfd_reloc_status_type
+shift_addend_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol,
+		  void *data, asection *input_section, bfd *output, char **msg)
+{
+  /* This is a really peculiar reloc, which is done for compatibility
+     with the Freescale toolchain.
+
+     That toolchain appears to (ab)use the lowest 15 bits of the addend for
+     the purpose of holding flags.  The purpose of these flags are unknown.
+     So in this function, when writing the bfd we left shift the addend by
+     15, and when reading we right shift it by 15 (discarding the lower bits).
+
+     This allows the linker to work with object files generated by Freescale,
+     as well as by Gas.
+  */
+
+  if (abfd->is_linker_input)
+    reloc_entry->addend >>= 15;
+  else
+    reloc_entry->addend <<= 15;
+
+  return bfd_reloc_continue;
+}
+
+
+#define USE_REL	0
+
+static reloc_howto_type elf_s12z_howto_table[] = {
+  /* This reloc does nothing.  */
+  HOWTO (R_S12Z_NONE,	/* type */
+	 0,			/* rightshift */
+	 3,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_S12Z_NONE",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* A 24 bit absolute relocation emitted by the OPR mode operands  */
+  HOWTO (R_S12Z_OPR,        /* type */
+	 0,			/* rightshift */
+	 5,			/* size (0 = byte, 1 = short, 2 = long) */
+	 24,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 shift_addend_reloc,
+	 "R_S12Z_OPR",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x00ffffff,            /* src_mask */
+	 0x00ffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* The purpose of this reloc is not known */
+  HOWTO (R_S12Z_UKNWN_2,	/* type */
+	 0,			/* rightshift */
+	 3,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_S12Z_UKNWN_2",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* A 15 bit PC-rel relocation */
+  HOWTO (R_S12Z_PCREL_7_15,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 15,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 shift_addend_reloc,
+	 "R_S12Z_PCREL_7_15",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x00,                  /* src_mask */
+	 0x007fff,		/* dst_mask */
+	 TRUE),		/* pcrel_offset */
+
+  /* A 24 bit absolute relocation emitted by EXT24 mode operands */
+  HOWTO (R_S12Z_EXT24,        /* type */
+	 0,			/* rightshift */
+	 5,			/* size (0 = byte, 1 = short, 2 = long) */
+	 24,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_S12Z_EXT24",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0x00ffffff,            /* src_mask */
+	 0x00ffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* The purpose of this reloc is not known */
+  HOWTO (R_S12Z_UKNWN_3,	/* type */
+	 0,			/* rightshift */
+	 3,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont,/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_S12Z_UKNWN_3",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* A 32 bit absolute relocation  */
+  HOWTO (R_S12Z_EXT32,        /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_S12Z_EXT32",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0xffffffff,            /* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+};
+
+/* Map BFD reloc types to S12Z ELF reloc types.  */
+
+struct s12z_reloc_map
+{
+  bfd_reloc_code_real_type bfd_reloc_val;
+  unsigned char elf_reloc_val;
+};
+
+static const struct s12z_reloc_map s12z_reloc_map[] =
+{
+  /* bfd reloc val */ /* elf reloc val */
+  {BFD_RELOC_NONE, R_S12Z_NONE},
+  {BFD_RELOC_32, R_S12Z_EXT32},
+  {BFD_RELOC_24, R_S12Z_EXT24},
+  {BFD_RELOC_16_PCREL, R_S12Z_PCREL_7_15}
+};
+
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				 bfd_reloc_code_real_type code)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (s12z_reloc_map) / sizeof (struct s12z_reloc_map);
+       i++)
+    {
+      if (s12z_reloc_map[i].bfd_reloc_val == code)
+	{
+	  return &elf_s12z_howto_table[s12z_reloc_map[i].elf_reloc_val];
+	}
+    }
+
+  printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code);
+
+  return NULL;
+}
+
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				 const char *r_name)
+{
+  unsigned int i;
+
+  printf ("%s:%d Looking up %s\n", __FILE__, __LINE__, r_name);
+
+  for (i = 0;
+       i < (sizeof (elf_s12z_howto_table)
+	    / sizeof (elf_s12z_howto_table[0]));
+       i++)
+    if (elf_s12z_howto_table[i].name != NULL
+	&& strcasecmp (elf_s12z_howto_table[i].name, r_name) == 0)
+      return &elf_s12z_howto_table[i];
+
+  return NULL;
+}
+
+/* Set the howto pointer for an S12Z ELF reloc.  */
+
+static bfd_boolean
+s12z_info_to_howto_rel (bfd *abfd,
+			  arelent *cache_ptr, Elf_Internal_Rela *dst)
+{
+  unsigned int  r_type = ELF32_R_TYPE (dst->r_info);
+
+  if (r_type >= (unsigned int) R_S12Z_max)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+			  abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  cache_ptr->howto = &elf_s12z_howto_table[r_type];
+  return TRUE;
+}
+
+
+/* Far trampoline generation.  */
+
+/* Build a S12Z trampoline stub.  */
+static bfd_boolean
+s12z_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
+{
+  printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
+  struct elf32_s12z_stub_hash_entry *stub_entry;
+  struct bfd_link_info *info;
+  struct s12z_elf_link_hash_table *htab;
+  asection *stub_sec;
+  bfd *stub_bfd;
+  bfd_byte *loc;
+  bfd_vma sym_value, phys_page, phys_addr;
+
+  /* Massage our args to the form they really have.  */
+  stub_entry = (struct elf32_s12z_stub_hash_entry *) gen_entry;
+  info = (struct bfd_link_info *) in_arg;
+
+  //  htab = s12z_elf_hash_table (info);
+
+
+  return TRUE;
+}
+
+/* As above, but don't actually build the stub.  Just bump offset so
+   we know stub section sizes.  */
+
+static bfd_boolean
+s12z_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
+			   void *in_arg ATTRIBUTE_UNUSED)
+{
+  printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
+  return TRUE;
+}
+
+/* Create a S12Z ELF linker hash table.  */
+
+static struct bfd_link_hash_table *
+s12z_elf_bfd_link_hash_table_create (bfd *abfd)
+{
+  printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
+  return NULL;
+}
+
+static bfd_boolean
+s12z_elf_set_mach_from_flags (bfd *abfd)
+{
+  flagword flags = elf_elfheader (abfd)->e_flags;
+  bfd_default_set_arch_mach (abfd, bfd_arch_s12z, 0); // bfd_mach_s12z);
+
+  return TRUE;
+}
+
+
+#define ELF_ARCH		bfd_arch_s12z
+#define ELF_TARGET_ID		0
+#define ELF_MACHINE_CODE	EM_S12Z
+#define ELF_MAXPAGESIZE		0x1000
+
+#define TARGET_BIG_SYM		s12z_elf32_vec
+#define TARGET_BIG_NAME		"elf32-s12z"
+
+#define elf_info_to_howto	0
+#define elf_info_to_howto_rel	s12z_info_to_howto_rel
+//#define elf_backend_check_relocs     elf32_s12z_check_relocs
+//#define elf_backend_relocate_section elf32_s12z_relocate_section
+#define elf_backend_object_p		s12z_elf_set_mach_from_flags
+#define elf_backend_final_write_processing	0
+#define elf_backend_can_gc_sections		1
+/* #define elf_backend_post_process_headers     elf32_s12z_post_process_headers */
+/* #define elf_backend_add_symbol_hook  elf32_s12z_add_symbol_hook */
+/* #define elf_backend_merge_symbol_attribute elf32_s12z_merge_symbol_attribute */
+
+/* #define bfd_elf32_bfd_link_hash_table_create \ */
+/* 				s12z_elf_bfd_link_hash_table_create */
+/* #define bfd_elf32_bfd_merge_private_bfd_data \ */
+/* 					_bfd_s12z_elf_merge_private_bfd_data */
+/* #define bfd_elf32_bfd_set_private_flags	_bfd_s12z_elf_set_private_flags */
+/* #define bfd_elf32_bfd_print_private_bfd_data \ */
+/* 					_bfd_s12z_elf_print_private_bfd_data */
+
+#include "elf32-target.h"
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index c581238515..971be4f3de 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -613,6 +613,27 @@ bfd_putl16 (bfd_vma data, void *p)
   addr[1] = (data >> 8) & 0xff;
 }
 
+
+void
+bfd_putb24 (bfd_vma data, void *p)
+{
+  bfd_byte *addr = (bfd_byte *) p;
+  addr[0] = (data >> 16) & 0xff;
+  addr[1] = (data >> 8) & 0xff;
+  addr[2] = data & 0xff;
+}
+
+
+void
+bfd_putl24 (bfd_vma data, void *p)
+{
+  bfd_byte *addr = (bfd_byte *) p;
+  addr[0] = data & 0xff;
+  addr[1] = (data >> 8) & 0xff;
+  addr[2] = (data >> 16) & 0xff;
+}
+
+
 bfd_vma
 bfd_getb32 (const void *p)
 {
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 66c2a5abc0..df683e6311 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -2466,6 +2466,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_M68HC12_10_PCREL",
   "BFD_RELOC_M68HC12_LO8XG",
   "BFD_RELOC_M68HC12_HI8XG",
+  "BFD_RELOC_S12Z_15_PCREL",
   "BFD_RELOC_16C_NUM08",
   "BFD_RELOC_16C_NUM08_C",
   "BFD_RELOC_16C_NUM16",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index f7e34a993a..411f998f54 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -431,6 +431,7 @@ bfd_get_reloc_size (reloc_howto_type *howto)
 {
   switch (howto->size)
     {
+    case 5: return 3;
     case 0: return 1;
     case 1: return 2;
     case 2: return 4;
@@ -917,6 +918,16 @@ space consuming.  For each target:
 
   switch (howto->size)
     {
+    case 5:
+      {
+	long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
+	x >>= 8;
+	DOIT (x);
+	bfd_put_16 (abfd, (bfd_vma) (x >> 8), (bfd_byte *) data + octets);
+	bfd_put_8 (abfd, (x & 0xFF), (unsigned char *) data + 2 + octets);
+      }
+      break;
+
     case 0:
       {
 	char x = bfd_get_8 (abfd, (char *) data + octets);
@@ -5949,6 +5960,12 @@ ENUMDOC
   This is the 8 bit high part of an absolute address and immediately follows
   a matching LO8XG part.
 ENUM
+  BFD_RELOC_S12Z_15_PCREL
+ENUMDOC
+  Freescale S12Z reloc.
+  This is a 15 bit relative address.  If the most significant bits are all zero
+  then it may be truncated to 8 bits.
+ENUM
   BFD_RELOC_16C_NUM08
 ENUMX
   BFD_RELOC_16C_NUM08_C
diff --git a/bfd/targets.c b/bfd/targets.c
index 230048a2a7..e08534d672 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -684,6 +684,7 @@ extern const bfd_target m32r_elf32_linux_le_vec;
 extern const bfd_target m68hc11_elf32_vec;
 extern const bfd_target m68hc12_elf32_vec;
 extern const bfd_target m68k_elf32_vec;
+extern const bfd_target s12z_elf32_vec;
 extern const bfd_target mach_o_be_vec;
 extern const bfd_target mach_o_le_vec;
 extern const bfd_target mach_o_fat_vec;
@@ -1044,6 +1045,8 @@ static const bfd_target * const _bfd_target_vector[] =
 
 	&m68k_elf32_vec,
 
+	&s12z_elf32_vec,
+
 	&mach_o_be_vec,
 	&mach_o_le_vec,
 	&mach_o_fat_vec,
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 6a9c51d4bb..6a9319f5db 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -119,6 +119,7 @@
 #include "elf/m32r.h"
 #include "elf/m68k.h"
 #include "elf/m68hc11.h"
+#include "elf/s12z.h"
 #include "elf/mcore.h"
 #include "elf/mep.h"
 #include "elf/metag.h"
@@ -1274,6 +1275,10 @@ dump_relocations (Filedata *          filedata,
 	  rtype = elf_m68hc11_reloc_type (type);
 	  break;
 
+	case EM_S12Z:
+	  rtype = elf_s12z_reloc_type (type);
+	  break;
+
 	case EM_68K:
 	  rtype = elf_m68k_reloc_type (type);
 	  break;
@@ -12309,6 +12314,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_68HC11:
     case EM_68HC12:
       return reloc_type == 6; /* R_M68HC11_32.  */
+    case EM_S12Z:
+      return reloc_type == 6; /* R_S12Z_EXT32.  */
     case EM_MCORE:
       return reloc_type == 1; /* R_MCORE_ADDR32.  */
     case EM_CYGNUS_MEP:
diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
index e6d9f40f16..da77fbf691 100644
--- a/binutils/testsuite/lib/binutils-common.exp
+++ b/binutils/testsuite/lib/binutils-common.exp
@@ -23,7 +23,7 @@ proc is_elf_format {} {
     # config.sub for these targets curiously transforms a target doublet
     # ending in -elf to -none.  eg. m68hc12-elf to m68hc12-unknown-none
     # They are always elf.
-    if { [istarget m68hc1*-*] || [istarget xgate-*] } {
+    if { [istarget m68hc1*-*] || [istarget s12z*-*] || [istarget xgate-*] } {
 	return 1;
     }
 
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 952377093d..ff46b0dfef 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -156,6 +156,7 @@ TARGET_CPU_CFILES = \
 	config/tc-m32r.c \
 	config/tc-m68hc11.c \
 	config/tc-m68k.c \
+	config/tc-s12z.c \
 	config/tc-mcore.c \
 	config/tc-mep.c \
 	config/tc-metag.c \
@@ -229,6 +230,7 @@ TARGET_CPU_HFILES = \
 	config/tc-m32r.h \
 	config/tc-m68hc11.h \
 	config/tc-m68k.h \
+	config/tc-s12z.h \
 	config/tc-mcore.h \
 	config/tc-mep.h \
 	config/tc-metag.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 4feabb3432..c127d3606f 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -452,6 +452,7 @@ TARGET_CPU_CFILES = \
 	config/tc-m32r.c \
 	config/tc-m68hc11.c \
 	config/tc-m68k.c \
+	config/tc-s12z.c \
 	config/tc-mcore.c \
 	config/tc-mep.c \
 	config/tc-metag.c \
@@ -525,6 +526,7 @@ TARGET_CPU_HFILES = \
 	config/tc-m32r.h \
 	config/tc-m68hc11.h \
 	config/tc-m68k.h \
+	config/tc-s12z.h \
 	config/tc-mcore.h \
 	config/tc-mep.h \
 	config/tc-metag.h \
@@ -872,6 +874,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m32r.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m68hc11.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m68k.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-s12z.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-mcore.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-mep.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-metag.Po@am__quote@
@@ -1318,6 +1321,20 @@ tc-m68k.obj: config/tc-m68k.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-m68k.obj `if test -f 'config/tc-m68k.c'; then $(CYGPATH_W) 'config/tc-m68k.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-m68k.c'; fi`
 
+tc-s12z.o: config/tc-s12z.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-s12z.o -MD -MP -MF $(DEPDIR)/tc-s12z.Tpo -c -o tc-s12z.o `test -f 'config/tc-s12z.c' || echo '$(srcdir)/'`config/tc-s12z.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/tc-s12z.Tpo $(DEPDIR)/tc-s12z.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='config/tc-s12z.c' object='tc-s12z.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-s12z.o `test -f 'config/tc-s12z.c' || echo '$(srcdir)/'`config/tc-s12z.c
+
+tc-s12z.obj: config/tc-s12z.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-s12z.obj -MD -MP -MF $(DEPDIR)/tc-s12z.Tpo -c -o tc-s12z.obj `if test -f 'config/tc-s12z.c'; then $(CYGPATH_W) 'config/tc-s12z.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-s12z.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/tc-s12z.Tpo $(DEPDIR)/tc-s12z.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='config/tc-s12z.c' object='tc-s12z.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-s12z.obj `if test -f 'config/tc-s12z.c'; then $(CYGPATH_W) 'config/tc-s12z.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-s12z.c'; fi`
+
 tc-mcore.o: config/tc-mcore.c
 @am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-mcore.o -MD -MP -MF $(DEPDIR)/tc-mcore.Tpo -c -o tc-mcore.o `test -f 'config/tc-mcore.c' || echo '$(srcdir)/'`config/tc-mcore.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/tc-mcore.Tpo $(DEPDIR)/tc-mcore.Po
diff --git a/gas/NEWS b/gas/NEWS
index ec1ba78a66..a05b703d9c 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for the Freescale S12Z architecture.
+
 * Add --generate-missing-build-notes=[yes|no] option to create (or not) GNU
   Build Attribute notes if none are present in the input sources.  Add a
   --enable-generate-build-notes=[yes|no] configure time option to set the
diff --git a/gas/config/tc-s12z.c b/gas/config/tc-s12z.c
new file mode 100644
index 0000000000..e024e7298b
--- /dev/null
+++ b/gas/config/tc-s12z.c
@@ -0,0 +1,3840 @@
+/* tc-s12z.c -- Assembler code for the Freescale S12Z
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "as.h"
+#include "safe-ctype.h"
+#include "subsegs.h"
+#include "dwarf2dbg.h"
+#include "opcodes/s12z.h"
+#include <stdint.h>
+#include <limits.h>
+#include <stdbool.h>
+
+const char comment_chars[] = ";";
+
+const char line_comment_chars[] = "#*";
+const char line_separator_chars[] = "";
+
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "dD";
+
+static char *fail_line_pointer;
+
+
+/* Options and initialization.  */
+
+const char *md_shortopts = "Sm:";
+
+struct option md_longopts[] =
+  {
+  };
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+
+relax_typeS md_relax_table[] =
+  {
+
+  };
+
+/* This table describes all the machine specific pseudo-ops the assembler
+   has to support.  The fields are:
+   pseudo-op name without dot
+   function to call to execute this pseudo-op
+   Integer arg to pass to the function.  */
+const pseudo_typeS md_pseudo_table[] =
+  {
+    {0, 0, 0}
+  };
+
+
+/* Get the target cpu for the assembler.  */
+const char *
+s12z_arch_format (void)
+{
+  return "elf32-s12z";
+}
+
+enum bfd_architecture
+s12z_arch (void)
+{
+  return bfd_arch_s12z;
+}
+
+int
+s12z_mach (void)
+{
+  return 0;
+}
+
+/* Listing header selected according to cpu.  */
+const char *
+s12z_listing_header (void)
+{
+  return "S12Z GAS ";
+}
+
+void
+md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
+{
+}
+
+void
+s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED)
+{
+}
+
+int
+md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+symbolS *
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+const char *
+md_atof (int type, char *litP, int *sizeP)
+{
+  return ieee_md_atof (type, litP, sizeP, TRUE);
+}
+
+valueT
+md_section_align (asection *seg, valueT addr)
+{
+  int align = bfd_get_section_alignment (stdoutput, seg);
+  return ((addr + (1 << align) - 1) & -(1 << align));
+}
+
+void
+md_begin (void)
+{
+}
+
+void
+s12z_init_after_args (void)
+{
+}
+
+/* Builtin help.  */
+
+
+static char *
+skip_whites (char *p)
+{
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  return p;
+}
+
+
+
+/* Start a new insn that contains at least 'size' bytes.  Record the
+   line information of that insn in the dwarf2 debug sections.  */
+static char *
+s12z_new_insn (int size)
+{
+  char *f = frag_more (size);
+
+  dwarf2_emit_insn (size);
+
+  return f;
+}
+
+
+
+static int lex_reg_name (uint16_t which, int *reg);
+
+static int
+lex_constant (long *v)
+{
+  char *end = NULL;
+  char *p = input_line_pointer;
+
+  /* A constant may not have the same value as a register
+     eg: "d6" */
+  int dummy;
+  if (lex_reg_name (~0, &dummy))
+    {
+      input_line_pointer = p;
+      return 0;
+    }
+
+  errno = 0;
+  *v = strtol (p, &end, 0);
+  if (errno == 0 && end != p)
+    {
+      input_line_pointer = end;
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+lex_match (char x)
+{
+  char *p = input_line_pointer;
+  if (*p != x)
+    return 0;
+
+  input_line_pointer++;
+  return 1;
+}
+
+
+static int
+lex_expression (expressionS *exp)
+{
+  char *ilp = input_line_pointer;
+  int dummy;
+  exp->X_op = O_absent;
+
+  if (lex_match ('#'))
+    goto fail;
+
+  if (lex_reg_name (~0, &dummy))
+    goto fail;
+
+  expression (exp);
+  if (exp->X_op != O_absent)
+    return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+/* immediate operand */
+static int
+lex_imm (long *v)
+{
+  char *ilp = input_line_pointer;
+
+  if (*input_line_pointer != '#')
+    goto fail;
+
+  input_line_pointer++;
+  expressionS exp;
+  if (!lex_expression (&exp))
+    goto fail;
+
+  if (exp.X_op != O_constant)
+    goto fail;
+
+  *v = exp.X_add_number;
+  return 1;
+
+fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+/* Short mmediate operand */
+static int
+lex_imm_e4 (long *val)
+{
+  char *ilp = input_line_pointer;
+  if ((lex_imm (val)))
+    {
+      if ((*val == -1) || (*val > 0 && *val <= 15))
+	{
+	  return 1;
+	}
+    }
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+lex_match_string (const char *s)
+{
+  char *p = input_line_pointer;
+  while (p != 0 && *p != '\t' && *p != ' ' && *p != '\0')
+    {
+      p++;
+    }
+
+  size_t len = p - input_line_pointer;
+  if (len != strlen (s))
+    return 0;
+
+  if (0 == strncasecmp (s, input_line_pointer, len))
+    {
+      input_line_pointer = p;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Parse a register name.
+   WHICH is a ORwise combination of the registers which are accepted.
+   ~0 accepts all.
+   On success, REG will be filled with the index of the register which
+   was successfully scanned.
+*/
+static int
+lex_reg_name (uint16_t which, int *reg)
+{
+  char *p = input_line_pointer;
+  while (p != 0 &&
+	 ((*p >= 'a' && *p <='z') || (*p >= '0' && *p <= '9') || (*p >= 'A' && *p <='Z')))
+    {
+      p++;
+    }
+
+  int len = p - input_line_pointer;
+
+  if (len <= 0)
+    return 0;
+
+  int i;
+  for (i = 0; i < S12Z_N_REGISTERS; ++i)
+    {
+      gas_assert (registers[i].name);
+
+      if (0 == strncasecmp (registers[i].name, input_line_pointer, len))
+	{
+	  if ((0x1U << i) & which)
+	    {
+	      input_line_pointer = p;
+	      *reg = i;
+	      return 1;
+	    }
+	}
+    }
+
+  return 0;
+}
+
+static int
+lex_force_match (char x)
+{
+  char *p = input_line_pointer;
+  if (*p != x)
+    {
+      as_bad (_("Expecting '%c'"), x);
+      return 0;
+    }
+
+  input_line_pointer++;
+  return 1;
+}
+
+static int
+lex_opr (uint8_t *buffer, int *n_bytes, expressionS *exp)
+{
+  char *ilp = input_line_pointer;
+  uint8_t *xb = buffer;
+  int reg;
+  long imm;
+  exp->X_op = O_absent;
+  *n_bytes = 0;
+  *xb = 0;
+  if (lex_imm_e4 (&imm))
+    {
+      if (imm > 0)
+	*xb = imm;
+      else
+	*xb = 0;
+      *xb |= 0x70;
+      *n_bytes = 1;
+      return 1;
+    }
+  else if (lex_reg_name (REG_BIT_Dn, &reg))
+    {
+      *xb = reg;
+      *xb |= 0xb8;
+      *n_bytes = 1;
+      return 1;
+    }
+  else if (lex_match ('['))
+    {
+      if (lex_expression (exp))
+	{
+	  long c = exp->X_add_number;
+	  if (lex_match (','))
+	    {
+	      if (lex_reg_name (REG_BIT_XYSP, &reg))
+		{
+		  int i;
+		  if (c <= 255 && c >= -256)
+		    {
+		      *n_bytes = 2;
+		      *xb |= 0xc4;
+		    }
+		  else
+		    {
+		      *n_bytes = 4;
+		      *xb |= 0xc6;
+		    }
+		  *xb |= (reg - REG_X) << 4;
+
+		  if (c < 0)
+		    *xb |= 0x01;
+		  for (i = 1; i < *n_bytes ; ++i)
+		    {
+		      buffer[i] = c >> (8 * (*n_bytes - i - 1));
+		    }
+		}
+	      else
+		{
+		  as_bad (_("Bad operand for constant offset"));
+		  goto fail;
+		}
+	    }
+	  else
+	    {
+	      *xb = 0xfe;
+	      *n_bytes = 4;
+	      buffer[1] = c >> 16;
+	      buffer[2] = c >> 8;
+	      buffer[3] = c;
+	    }
+	}
+      else if (lex_reg_name (REG_BIT_Dn, &reg))
+	{
+	  if (!lex_force_match (','))
+	    goto fail;
+
+	  int reg2;
+	  if (lex_reg_name (REG_BIT_XY, &reg2))
+	    {
+	      *n_bytes = 1;
+	      *xb = reg;
+	      *xb |= (reg2 - REG_X) << 4;
+	      *xb |= 0xc8;
+	    }
+	  else
+	    {
+	      as_bad (_("Invalid operand for register offset"));
+	      goto fail;
+	    }
+	}
+      else
+	{
+	  goto fail;
+	}
+      if (!lex_force_match (']'))
+	goto fail;
+      return 1;
+    }
+  else if (lex_match ('('))
+    {
+      long c;
+      if (lex_constant (&c))
+	{
+	  if (!lex_force_match (','))
+	    goto fail;
+	  int reg2;
+	  if (lex_reg_name (REG_BIT_XYSP, &reg2))
+	    {
+	      if (reg2 != REG_P && c >= 0 && c <= 15)
+		{
+		  *n_bytes = 1;
+		  *xb = 0x40;
+		  *xb |= (reg2 - REG_X) << 4;
+		  *xb |= c;
+		}
+	      else if (c >= -256 && c <= 255)
+		{
+		  *n_bytes = 2;
+		  *xb = 0xc0;
+		  *xb |= (reg2 - REG_X) << 4;
+		  if (c < 0)
+		    *xb |= 0x01;
+		  buffer[1] = c;
+		}
+	      else
+		{
+		  *n_bytes = 4;
+		  *xb = 0xc2;
+		  *xb |= (reg2 - REG_X) << 4;
+		  buffer[1] = c >> 16;
+		  buffer[2] = c >> 8;
+		  buffer[3] = c;
+		}
+	    }
+	  else if (lex_reg_name (REG_BIT_Dn, &reg2))
+	    {
+	      if (c >= -1 * (long) (0x1u << 17)
+		  &&
+		  c < (long) (0x1u << 17) - 1)
+		{
+		  *n_bytes = 3;
+		  *xb = 0x80;
+		  *xb |= reg2;
+		  *xb |= ((c >> 16) & 0x03) << 4;
+		  buffer[1] = c >> 8;
+		  buffer[2] = c;
+		}
+	      else
+		{
+		  *n_bytes = 4;
+		  *xb = 0xe8;
+		  *xb |= reg2;
+		  buffer[1] = c >> 16;
+		  buffer[2] = c >> 8;
+		  buffer[3] = c;
+		}
+	    }
+	  else
+	    {
+	      as_bad (_("Bad operand for constant offset"));
+	      goto fail;
+	    }
+	}
+      else if (lex_reg_name (REG_BIT_Dn, &reg))
+	{
+	  if (lex_match (','))
+	    {
+	      int reg2;
+	      if (lex_reg_name (REG_BIT_XYS, &reg2))
+		{
+		  *n_bytes = 1;
+		  *xb = 0x88;
+		  *xb |= (reg2 - REG_X) << 4;
+		  *xb |= reg;
+		}
+	      else
+		{
+		  as_bad (_("Invalid operand for register offset"));
+		  goto fail;
+		}
+	    }
+	  else
+	    {
+	      goto fail;
+	    }
+	}
+      else if (lex_reg_name (REG_BIT_XYS, &reg))
+	{
+	  if (lex_match ('-'))
+	    {
+	      if (reg == REG_S)
+		{
+		  as_bad (_("Invalid register for postdecrement operation"));
+		  goto fail;
+		}
+	      *n_bytes = 1;
+	      if (reg == REG_X)
+		*xb = 0xc7;
+	      else if (reg == REG_Y)
+		*xb = 0xd7;
+	    }
+	  else if (lex_match ('+'))
+	    {
+	      *n_bytes = 1;
+	      if (reg == REG_X)
+		*xb = 0xe7;
+	      else if (reg == REG_Y)
+		*xb = 0xf7;
+	      else if (reg == REG_S)
+		*xb = 0xff;
+	    }
+	  else
+	    {
+	      goto fail;
+	    }
+	}
+      else if (lex_match ('+'))
+	{
+	  if (lex_reg_name (REG_BIT_XY, &reg))
+	    {
+	      *n_bytes = 1;
+	      if (reg == REG_X)
+		*xb = 0xe3;
+	      else if (reg == REG_Y)
+		*xb = 0xf3;
+	    }
+	  else
+	    {
+	      as_bad (_("Invalid register for preincrement operation"));
+	      goto fail;
+	    }
+	}
+      else if (lex_match ('-'))
+	{
+	  if (lex_reg_name (REG_BIT_XYS, &reg))
+	    {
+	      *n_bytes = 1;
+	      if (reg == REG_X)
+		*xb = 0xc3;
+	      else if (reg == REG_Y)
+		*xb = 0xd3;
+	      else if (reg == REG_S)
+		*xb = 0xfb;
+	    }
+	  else
+	    {
+	      as_bad (_("Invalid register for predecrement operation"));
+	      goto fail;
+	    }
+	}
+      else
+	{
+	  goto fail;
+	}
+
+      if (! lex_match (')'))
+	goto fail;
+      return 1;
+    }
+  else if (lex_expression (exp))
+    {
+      *xb = 0xfa;
+      *n_bytes = 4;
+      buffer[1] = 0;
+      buffer[2] = 0;
+      buffer[3] = 0;
+      if (exp->X_op == O_constant)
+	{
+	  if (exp->X_add_number < (0x1U << 14))
+	    {
+	      *xb = 0x00;
+	      *n_bytes = 2;
+	      *xb |= exp->X_add_number >> 8;
+	      buffer[1] = exp->X_add_number;
+	    }
+	  else if (exp->X_add_number < (0x1U << 19))
+	    {
+	      *xb = 0xf8;
+	      if (exp->X_add_number & (0x1U << 17))
+		*xb |= 0x04;
+	      if (exp->X_add_number & (0x1U << 16))
+		*xb |= 0x01;
+	      *n_bytes = 3;
+	      buffer[1] = exp->X_add_number >> 8;
+	      buffer[2] = exp->X_add_number;
+	    }
+	  else
+	    {
+	      *xb = 0xfa;
+	      *n_bytes = 4;
+	      buffer[1] = exp->X_add_number >> 16;
+	      buffer[2] = exp->X_add_number >> 8;
+	      buffer[3] = exp->X_add_number;
+	    }
+	}
+      return 1;
+    }
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+lex_offset (long *val)
+{
+  char *end = NULL;
+  char *p = input_line_pointer;
+
+  if (*p++ != '*')
+    return 0;
+
+  if (*p != '+' && *p != '-')
+    return 0;
+
+  bool negative =  (*p == '-');
+  p++;
+
+  errno = 0;
+  *val = strtol (p, &end, 0);
+  if (errno == 0)
+    {
+      if (negative)
+	*val *= -1;
+      input_line_pointer = end;
+      return 1;
+    }
+
+  return 0;
+}
+
+
+
+struct instruction;
+
+typedef int (*parse_operand_func) (const struct instruction *);
+
+struct instruction
+{
+  const char *name;
+
+  /* The "page" to which the instruction belongs.
+     This is also only a hint.  Some instructions might have modes in both
+     pages... */
+  char page;
+
+  /* This is a hint - and only a hint - about the opcode of the instruction.
+     The parse_operand_func is free to ignore it.
+  */
+  uint8_t opc;
+
+  parse_operand_func parse_operands;
+
+  /* Some instructions can be encoded with a different opcode */
+  uint8_t alt_opc;
+};
+
+static int
+no_operands (const struct instruction *insn)
+{
+  if (*input_line_pointer != '\0')
+    {
+      as_bad (_("Garbage at end of instruction"));
+      return 0;
+    }
+
+  char *f = s12z_new_insn (insn->page);
+  if (insn->page == 2)
+    number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+  number_to_chars_bigendian (f++, insn->opc, 1);
+
+  return 1;
+}
+
+/* Emit the code for an OPR address mode operand */
+static char *
+emit_opr (char *f, const uint8_t *buffer, int n_bytes, expressionS *exp)
+{
+  int i;
+  number_to_chars_bigendian (f++, buffer[0], 1);
+  if (exp->X_op != O_absent && exp->X_op != O_constant)
+    {
+      fix_new_exp (frag_now,
+		   f - frag_now->fr_literal,
+		   3,
+		   exp,
+		   FALSE,
+		   BFD_RELOC_24);
+    }
+  for (i = 1; i < n_bytes; ++i)
+    number_to_chars_bigendian (f++,  buffer[i], 1);
+
+  return f;
+}
+
+/* Emit the code for a 24 bit direct address operand */
+static char *
+emit_ext24 (char *f, long v)
+{
+  number_to_chars_bigendian (f, v, 3);
+
+  return f + 3;
+}
+
+static int
+opr (const struct instruction *insn)
+{
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (lex_opr (buffer, &n_bytes, &exp))
+    {
+      /* Large constant direct values are more efficiently encoded as ext24 mode.
+	 Otherwise a decision has to be deferred to a relax. */
+      if (exp.X_op == O_constant
+	  && buffer[0] == 0xFA
+	  && insn->alt_opc != 0)
+	{
+	  char *f = s12z_new_insn (4);
+
+	  /* I don't think there are any instances of page 2 opcodes in this case */
+	  gas_assert (insn->page == 1);
+
+	  number_to_chars_bigendian (f++, insn->alt_opc, 1);
+
+	  emit_ext24 (f, exp.X_add_number);
+	}
+      else
+	{
+	  char *f = s12z_new_insn (n_bytes + 1);
+	  number_to_chars_bigendian (f++, insn->opc, 1);
+
+	  emit_opr (f, buffer, n_bytes, &exp);
+	}
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Parse a 15 bit offset, as an expression.
+   LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
+   */
+static int
+lex_15_bit_offset (bool *long_displacement, expressionS *exp)
+{
+  char *ilp = input_line_pointer;
+
+  long val;
+  if (lex_offset (&val))
+    {
+      exp->X_op = O_absent;
+      exp->X_add_number = val;
+    }
+  else if (lex_expression (exp))
+    {
+      if (exp->X_op == O_constant)
+	{
+	  val = exp->X_add_number;
+	}
+      else
+	{
+	  /* If a symbol was parsed we don't know the displacement.
+	     We have to assume it is long, and relax it later if possible. */
+	  *long_displacement = true;
+	  return 1;
+	}
+    }
+  else
+    {
+      exp->X_op = O_absent;
+      goto fail;
+    }
+
+  if (val > 0x3FFF || val < -0x4000)
+    {
+      as_fatal (_("Offset is outside of 15 bit range"));
+      return 0;
+    }
+
+  *long_displacement = (val > 63 || val < -64);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static void
+emit_15_bit_offset (char *f, int where, expressionS *exp)
+{
+  gas_assert (exp);
+  if (exp->X_op != O_absent && exp->X_op != O_constant)
+    {
+      exp->X_add_number += where;
+      fixS *fix = fix_new_exp (frag_now,
+		   f - frag_now->fr_literal,
+		   2,
+		   exp,
+		   TRUE,
+		   BFD_RELOC_16_PCREL);
+      fix->fx_addnumber = where - 2;
+    }
+  else
+    {
+      long val = exp->X_add_number;
+      bool long_displacement = (val > 63 || val < -64);
+      if (long_displacement)
+	val |= 0x8000;
+      else
+	val &= 0x7F;
+
+      number_to_chars_bigendian (f++, val, long_displacement ? 2 : 1);
+    }
+}
+
+static int
+rel (const struct instruction *insn)
+{
+  bool long_displacement;
+
+  expressionS exp;
+  if (! lex_15_bit_offset (&long_displacement, &exp))
+    return 0;
+
+  char *f = s12z_new_insn (long_displacement ? 3 : 2);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  emit_15_bit_offset (f, 3, &exp);
+  return 1;
+}
+
+static int
+reg_inh (const struct instruction *insn)
+{
+  int reg;
+  if (lex_reg_name (REG_BIT_Dn, &reg))
+    {
+      char *f = s12z_new_insn (insn->page);
+      if (insn->page == 2)
+	number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+      number_to_chars_bigendian (f++, insn->opc + reg, 1);
+      return 1;
+    }
+
+  return 0;
+}
+
+
+/* Special case for CLR X and CLR Y */
+static int
+clr_xy (const struct instruction *insn ATTRIBUTE_UNUSED)
+{
+  int reg;
+  if (lex_reg_name (REG_BIT_XY, &reg))
+    {
+      char *f = s12z_new_insn (1);
+      number_to_chars_bigendian (f, 0x9a + reg - REG_X, 1);
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Some instructions have a suffix like ".l", ".b", ".w" etc
+   which indicates the size of the operands. */
+static int
+size_from_suffix  (const struct instruction *insn, int idx)
+{
+  const char *dot = strchr (insn->name, '.');
+
+  if (dot == NULL)
+    return -3;
+
+  int size = -2;
+  switch (dot[1 + idx])
+    {
+    case 'b':
+      size = 1;
+      break;
+    case 'w':
+      size = 2;
+      break;
+    case 'p':
+      size = 3;
+      break;
+    case 'l':
+      size = 4;
+      break;
+    default:
+      as_fatal (_("Bad size"));
+    };
+
+  return size;
+}
+
+static int
+mul_reg_reg_reg (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int Dd;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dj;
+  if (!lex_reg_name (REG_BIT_Dn, &Dj))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dk;
+  if (!lex_reg_name (REG_BIT_Dn, &Dk))
+    goto fail;
+
+  char *f = s12z_new_insn (insn->page + 1);
+  if (insn->page == 2)
+    number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+  number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+  const char *dot = strchrnul (insn->name, '.');
+  uint8_t mb ;
+  switch (dot[-1])
+    {
+    case 's':
+      mb = 0x80;
+      break;
+    case 'u':
+      mb = 0x00;
+      break;
+    default:
+      as_fatal (_("BAD MUL"));
+      break;
+    }
+
+  mb |= Dj << 3;
+  mb |= Dk;
+
+  number_to_chars_bigendian (f++, mb, 1);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+mul_reg_reg_imm (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int Dd;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dj;
+  if (!lex_reg_name (REG_BIT_Dn, &Dj))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long imm;
+  if (!lex_imm (&imm))
+    goto fail;
+
+
+  int size = size_from_suffix (insn, 0);
+
+  char *f = s12z_new_insn (insn->page + 1 + size);
+  if (insn->page == 2)
+    number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+  number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+  uint8_t mb = 0x44;
+  const char *dot = strchrnul (insn->name, '.');
+  switch (dot[-1])
+    {
+    case 's':
+      mb |= 0x80;
+      break;
+    case 'u':
+      mb |= 0x00;
+      break;
+    default:
+      as_fatal (_("BAD MUL"));
+      break;
+    }
+
+  mb |= Dj << 3;
+  mb |= size  - 1;
+
+  number_to_chars_bigendian (f++, mb, 1);
+  number_to_chars_bigendian (f++, imm, size);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+mul_reg_reg_opr (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int Dd;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dj;
+  if (!lex_reg_name (REG_BIT_Dn, &Dj))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  int size = size_from_suffix (insn, 0);
+
+  char *f = s12z_new_insn (insn->page + 1 + n_bytes);
+  if (insn->page == 2)
+    number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+  number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+  uint8_t mb = 0x40;
+  const char *dot = strchrnul (insn->name, '.');
+  switch (dot[-1])
+    {
+    case 's':
+      mb |= 0x80;
+      break;
+    case 'u':
+      mb |= 0x00;
+      break;
+    default:
+      as_fatal (_("BAD MUL"));
+      break;
+    }
+
+  mb |= Dj << 3;
+  mb |= size  - 1;
+
+  number_to_chars_bigendian (f++, mb, 1);
+
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+mul_reg_opr_opr (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int Dd;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer1[4];
+  int n_bytes1;
+  expressionS exp1;
+  if (!lex_opr (buffer1, &n_bytes1, &exp1))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer2[4];
+  int n_bytes2;
+  expressionS exp2;
+  if (!lex_opr (buffer2, &n_bytes2, &exp2))
+    goto fail;
+
+  int size1 = size_from_suffix (insn, 0);
+  int size2 = size_from_suffix (insn, 1);
+
+  char *f = s12z_new_insn (insn->page + 1 + n_bytes1 + n_bytes2);
+  if (insn->page == 2)
+    number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+  number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+  uint8_t mb = 0x42;
+  const char *dot = strchrnul (insn->name, '.');
+  switch (dot[-1])
+    {
+    case 's':
+      mb |= 0x80;
+      break;
+    case 'u':
+      mb |= 0x00;
+      break;
+    default:
+      as_fatal (_("BAD MUL"));
+      break;
+    }
+
+  mb |= (size1  - 1) << 4;
+  mb |= (size2  - 1) << 2;
+  number_to_chars_bigendian (f++, mb, 1);
+
+  f = emit_opr (f, buffer1, n_bytes1, &exp1);
+  f = emit_opr (f, buffer2, n_bytes2, &exp2);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+#define REG_BIT_GRP0				\
+  ((0x1U << REG_D2) |				\
+   (0x1U << REG_D3) |				\
+   (0x1U << REG_CCH) |				\
+   (0x1U << REG_CCL) |				\
+   (0x1U << REG_D0) |				\
+   (0x1U << REG_D1))
+
+#define REG_BIT_GRP1				\
+  ((0x1U << REG_D4) |				\
+   (0x1U << REG_D5) |				\
+   (0x1U << REG_D6) |				\
+   (0x1U << REG_D7) |				\
+   (0x1U << REG_X) |				\
+   (0x1U << REG_Y))
+
+static const uint8_t reg_map [] =
+  {
+    0x02,  // D2
+    0x01,  // D3
+    0x20,
+    0x10,  // D5
+    0x08,  // D0
+    0x04,  // D1
+    0x08,  // D6
+    0x04,  // D7
+    0x02,
+    0x01,  // Y
+    0x00,
+    0x00,
+    0x20,   // CCH
+    0x10,   // CCL
+    0x00
+  };
+
+static  int
+lex_reg_list (uint16_t grp, uint16_t *reg_bits)
+{
+  if (lex_match (','))
+    {
+      int reg;
+      if (!lex_reg_name (grp, &reg))
+	return 0;
+      *reg_bits |= 0x1u << reg;
+      lex_reg_list (grp, reg_bits);
+    }
+
+  /* Empty list */
+  return 1;
+}
+
+static int
+psh_pull (const struct instruction *insn)
+{
+  uint8_t pb =
+    (0 == strcmp ("pul", insn->name)) ? 0x80: 0x00;
+
+  if (lex_match_string ("all16b"))
+    {
+      pb |= 0x40;
+    }
+  else if (lex_match_string ("all"))
+    {
+      /* Nothing to do */
+    }
+  else
+    {
+      int reg1;
+      if (!lex_reg_name (REG_BIT_GRP1 | REG_BIT_GRP0, &reg1))
+	goto fail;
+      uint16_t admitted_group = 0;
+
+      if ((0x1U << reg1) & REG_BIT_GRP1)
+	admitted_group = REG_BIT_GRP1;
+      else if ((0x1U << reg1) & REG_BIT_GRP0)
+	admitted_group = REG_BIT_GRP0;
+
+      uint16_t reg_bits = 0x1 << reg1;
+      if (!lex_reg_list (admitted_group, &reg_bits))
+	goto fail;
+
+      if (reg_bits & REG_BIT_GRP1)
+	pb |= 0x40;
+
+      int i;
+      for (i = 0; i < 16; ++i)
+	{
+	  if (reg_bits & (0x1u << i))
+	    pb |= reg_map[i];
+	}
+    }
+
+  char *f = s12z_new_insn (2);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, pb, 1);
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  return 0;
+}
+
+
+static int
+tfr (const struct instruction *insn)
+{
+  int reg1;
+  if (!lex_reg_name (~0, &reg1))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int reg2;
+  if (!lex_reg_name (~0, &reg2))
+    goto fail;
+
+  if ((0 == strcasecmp ("sex", insn->name))
+      || (0 == strcasecmp ("zex", insn->name)))
+    {
+      if (registers[reg1].bytes >= registers[reg2].bytes)
+	{
+	  as_bad (_("Source register for %s must be smaller that the destination register"),
+		  insn->name);
+	  goto fail;
+	}
+    }
+
+  char *f = s12z_new_insn (1 + insn->page);
+  if (insn->page == 2)
+    number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, reg1 << 4 | reg2, 1);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  return 0;
+}
+
+static int
+imm8 (const struct instruction *insn)
+{
+  long imm;
+  if (! lex_imm (&imm))
+    return 0;
+  if (imm > 127 || imm < -128)
+    {
+      as_bad (_("Immediate value %ld is out of range for instruction %s"),
+	      imm, insn->name);
+    }
+
+  char *f = s12z_new_insn (2);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, imm, 1);
+
+  return 1;
+}
+
+static int
+reg_imm (const struct instruction *insn, int allowed_reg)
+{
+  char *ilp = input_line_pointer;
+  int reg;
+  if (lex_reg_name (allowed_reg, &reg))
+    {
+      if (!lex_force_match (','))
+	goto fail;
+      long imm;
+      if (! lex_imm (&imm))
+	goto fail;
+
+      short size = registers[reg].bytes;
+      char *f = s12z_new_insn (insn->page + size);
+      if (insn->page == 2)
+	number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+      number_to_chars_bigendian (f++, insn->opc + reg, 1);
+      number_to_chars_bigendian (f++, imm, size);
+      return 1;
+    }
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+regd_imm (const struct instruction *insn)
+{
+  return reg_imm (insn, REG_BIT_Dn);
+}
+
+static int
+regdxy_imm (const struct instruction *insn)
+{
+  return reg_imm (insn, REG_BIT_Dn | REG_BIT_XY);
+}
+
+
+static int
+regs_imm (const struct instruction *insn)
+{
+  return reg_imm (insn, 0x1U << REG_S);
+}
+
+static int
+trap_imm (const struct instruction *insn ATTRIBUTE_UNUSED)
+{
+  long imm = -1;
+  if (! lex_imm (&imm))
+    goto fail;
+
+  if (imm < 0x92 || imm > 0xFF ||
+      (imm >= 0xA0 && imm <= 0xA7) ||
+      (imm >= 0xB0 && imm <= 0xB7))
+    {
+      as_bad (_("trap value %ld is not valid"), imm);
+      return 0;
+    }
+  else
+    {
+      char *f = s12z_new_insn (2);
+      number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+      number_to_chars_bigendian (f++, imm & 0xFF, 1);
+      return 1;
+    }
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  return 0;
+}
+
+
+
+/* Special one byte instruction CMP X, Y */
+static int
+regx_regy (const struct instruction *insn)
+{
+  int reg;
+  if (lex_reg_name (0x1U << REG_X, &reg))
+    {
+      if (lex_force_match (','))
+	{
+	  if (lex_reg_name (0x1U << REG_Y, &reg))
+	    {
+	      char *f = s12z_new_insn (1);
+	      number_to_chars_bigendian (f, insn->opc, 1);
+	      return 1;
+	    }
+	}
+    }
+  return 0;
+}
+
+/* Special one byte instruction SUB D6, X, Y */
+static int
+regd6_regx_regy (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+  int reg;
+  if (!lex_reg_name (0x1U << REG_D6, &reg))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  if (!lex_reg_name (0x1U << REG_X, &reg))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  if (!lex_reg_name (0x1U << REG_Y, &reg))
+    goto fail;
+
+  char *f = s12z_new_insn (1);
+  number_to_chars_bigendian (f, insn->opc, 1);
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+/* Special one byte instruction SUB D6, Y, X */
+static int
+regd6_regy_regx (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+  int reg;
+  if (!lex_reg_name (0x1U << REG_D6, &reg))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  if (!lex_reg_name (0x1U << REG_Y, &reg))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  if (!lex_reg_name (0x1U << REG_X, &reg))
+    goto fail;
+
+  char *f = s12z_new_insn (1);
+  number_to_chars_bigendian (f, insn->opc, 1);
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+reg_opr (const struct instruction *insn, int allowed_regs)
+{
+  char *ilp = input_line_pointer;
+  int reg;
+  if (lex_reg_name (allowed_regs, &reg))
+    {
+      if (!lex_force_match (','))
+	goto fail;
+
+      uint8_t buffer[4];
+      int n_bytes;
+      expressionS exp;
+      if (lex_opr (buffer, &n_bytes, &exp))
+	{
+	  /* Large constant direct values are more efficiently encoded as ext24 mode.
+	     Otherwise a decision has to be deferred to a relax. */
+	  if (exp.X_op == O_constant
+	      && buffer[0] == 0xFA
+	      && insn->alt_opc != 0)
+	    {
+	      char *f = s12z_new_insn (4);
+
+	      /* I don't think there are any instances of page 2 opcodes in this case */
+	      gas_assert (insn->page == 1);
+
+	      number_to_chars_bigendian (f++, insn->alt_opc + reg, 1);
+
+	      emit_ext24 (f, exp.X_add_number);
+	    }
+	  else
+	    {
+	      char *f = s12z_new_insn (n_bytes + insn->page);
+
+	      if (insn->page == 2)
+		number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+	      number_to_chars_bigendian (f++, insn->opc + reg, 1);
+
+	      emit_opr (f, buffer, n_bytes, &exp);
+	    }
+
+	  return 1;
+	}
+    }
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+regdxy_opr (const struct instruction *insn)
+{
+  return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY);
+}
+
+static int
+regd_opr (const struct instruction *insn)
+{
+  return reg_opr (insn, REG_BIT_Dn);
+}
+
+
+static int
+regs_opr (const struct instruction *insn)
+{
+  return reg_opr (insn, 0x1U << REG_S);
+}
+
+static int
+imm_opr  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+  long imm;
+  if (!lex_imm (&imm))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  int size = size_from_suffix (insn, 0);
+  char *f = s12z_new_insn (1 + n_bytes + size);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+
+  int i;
+  for (i = 0; i < size; ++i)
+    number_to_chars_bigendian (f++, imm >> (CHAR_BIT * (size - i - 1)), 1);
+
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+opr_opr  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer1[4];
+  int n_bytes1;
+  expressionS exp1;
+  if (!lex_opr (buffer1, &n_bytes1, &exp1))
+    goto fail;
+
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer2[4];
+  int n_bytes2;
+  expressionS exp2;
+  if (!lex_opr (buffer2, &n_bytes2, &exp2))
+    goto fail;
+
+  char *f = s12z_new_insn (1 + n_bytes1 + n_bytes2);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+
+  f = emit_opr (f, buffer1, n_bytes1, &exp1);
+  f = emit_opr (f, buffer2, n_bytes2, &exp2);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+reg67sxy_opr  (const struct instruction *insn)
+{
+  int reg;
+  if (!lex_reg_name (REG_BIT_XYS | (0x1U << REG_D6) | (0x1U << REG_D7), &reg))
+    return 0;
+
+  if (!lex_match (','))
+    return 0;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    return 0;
+
+  char *f = s12z_new_insn (1 + n_bytes);
+  number_to_chars_bigendian (f++, insn->opc + reg - REG_D6, 1);
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+}
+
+static int
+rotate  (const struct instruction *insn, short dir)
+{
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (lex_opr (buffer, &n_bytes, &exp))
+    {
+      char *f = s12z_new_insn (n_bytes + 2);
+      number_to_chars_bigendian (f++, insn->opc, 1);
+      int size = size_from_suffix (insn, 0);
+      if (size < 0)
+	size = 1;
+      uint8_t sb = 0x24;
+      sb |= size - 1;
+      if (dir)
+	sb |= 0x40;
+      number_to_chars_bigendian (f++, sb, 1);
+      emit_opr (f, buffer, n_bytes, &exp);
+
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+rol  (const struct instruction *insn)
+{
+  return rotate (insn, 1);
+}
+
+static int
+ror  (const struct instruction *insn)
+{
+  return rotate (insn, 0);
+}
+
+
+/* Shift instruction with a register operand and an immediate #1 or #2
+   left = 1; right = 0;
+   logical = 0; arithmetic = 1;
+*/
+static int
+lex_shift_reg_imm1  (const struct instruction *insn, short type, short dir)
+{
+  /*
+    This function is highly unusual and a bit wierd!
+    It first matches the input against a register {d0, d1, ... d7} followed by an immediate
+    {#1, #2}.
+    Then, it rewinds the input and parses it again as a OPR.
+  */
+  char *ilp = input_line_pointer;
+
+  int Dd;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    {
+      goto fail;
+    }
+
+  if (!lex_match (','))
+    goto fail;
+
+  long imm = -1;
+  if (!lex_imm (&imm))
+    goto fail;
+
+  if (imm != 1 && imm != 2)
+    goto fail;
+  input_line_pointer = ilp;
+
+  /* Now parse the first operand again */
+
+  uint8_t buffer[4];
+  int n_bytes;
+
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  gas_assert (n_bytes == 1);
+
+  uint8_t sb = 0x34;
+  sb |= dir << 6;
+  sb |= type << 7;
+  if (imm == 2)
+    sb |= 0x08;
+
+  char *f = s12z_new_insn (3);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, sb, 1);
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+/* Shift instruction with a register operand.
+   left = 1; right = 0;
+   logical = 0; arithmetic = 1; */
+static int
+lex_shift_reg  (const struct instruction *insn, short type, short dir)
+{
+  int Dd, Ds, Dn;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    {
+      goto fail;
+    }
+
+  if (!lex_match (','))
+    goto fail;
+
+  if (!lex_reg_name (REG_BIT_Dn, &Ds))
+    {
+      goto fail;
+    }
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t sb = 0x10;
+  sb |= Ds;
+  sb |= dir << 6;
+  sb |= type << 7;
+  long imm;
+  if (lex_reg_name (REG_BIT_Dn, &Dn))
+    {
+      char *f = s12z_new_insn (3);
+      number_to_chars_bigendian (f++, insn->opc | Dd, 1);
+      number_to_chars_bigendian (f++, sb, 1);
+      uint8_t xb = 0xb8;
+      xb |= Dn;
+      number_to_chars_bigendian (f++, xb, 1);
+
+      return 1;
+    }
+  else if (lex_imm (&imm))
+    {
+      if (imm < 0 || imm > 31)
+	{
+	  as_bad (_("Shift value should be in the range [0,31]"));
+	  goto fail;
+	}
+
+      int n_bytes = 3;
+      if (imm == 1 || imm == 2)
+	{
+	  n_bytes = 2;
+	  sb &= ~0x10;
+	}
+      else
+	{
+	  sb |= (imm & 0x01) << 3;
+	}
+
+      char *f = s12z_new_insn (n_bytes);
+      number_to_chars_bigendian (f++, insn->opc | Dd, 1);
+      number_to_chars_bigendian (f++, sb, 1);
+      if (n_bytes > 2)
+	{
+	  uint8_t xb = 0x70;
+	  xb |= imm >> 1;
+	  number_to_chars_bigendian (f++, xb, 1);
+	}
+
+      return 1;
+    }
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  return 0;
+}
+
+static void
+impute_shift_dir_and_type (const struct instruction *insn, short *type, short *dir)
+{
+  *dir = -1;
+  *type = -1;
+  switch (insn->name[0])
+    {
+    case 'l':
+      *type = 0;
+      break;
+    case 'a':
+      *type = 1;
+      break;
+    default:
+      as_fatal (_("Bad shift mode"));
+      break;
+    }
+
+  switch (insn->name[2])
+    {
+    case 'l':
+      *dir = 1;
+      break;
+    case 'r':
+      *dir = 0;
+      break;
+    default:
+      as_fatal (_("Bad shift *direction"));
+      break;
+    }
+}
+
+/* Shift instruction with a OPR operand */
+static int
+shift_two_operand  (const struct instruction *insn)
+{
+  uint8_t sb = 0x34;
+  char *ilp = input_line_pointer;
+
+  short dir = -1;
+  short type = -1;
+  impute_shift_dir_and_type (insn, &type, &dir);
+  sb |= dir << 6;
+  sb |= type << 7;
+
+  int size = size_from_suffix (insn, 0);
+  sb |= size - 1;
+
+  uint8_t buffer[4];
+  int n_opr_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_opr_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long imm = -1;
+  if (!lex_imm (&imm))
+    goto fail;
+
+  if (imm != 1 && imm != 2)
+    goto fail;
+
+  if (imm == 2)
+    sb |= 0x08;
+
+  char *f = s12z_new_insn (2 + n_opr_bytes);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, sb, 1);
+  emit_opr (f, buffer, n_opr_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+/* Shift instruction with a OPR operand */
+static int
+shift_opr_imm  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  short dir = -1;
+  short type = -1;
+  impute_shift_dir_and_type (insn, &type, &dir);
+
+  int Dd = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int n_bytes = 2;
+
+  uint8_t buffer1[4];
+  int n_opr_bytes1;
+
+  expressionS exp1;
+  if (!lex_opr (buffer1, &n_opr_bytes1, &exp1))
+    goto fail;
+
+  n_bytes += n_opr_bytes1;
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer2[4];
+  int n_opr_bytes2 = 0;
+  expressionS exp2;
+  long imm;
+  bool immediate = false;
+  if (lex_imm (&imm))
+    {
+      immediate = true;
+    }
+  else if (!lex_opr (buffer2, &n_opr_bytes2, &exp2))
+    goto fail;
+
+  uint8_t sb = 0x20;
+
+  int size = size_from_suffix (insn, 0);
+
+  if (size != -1)
+    sb |= size - 1;
+
+  sb |= dir << 6;
+  sb |= type << 7;
+
+  if (immediate)
+    {
+      if (imm == 2 || imm == 1)
+	{
+	  if (imm == 2)
+	    sb |= 0x08;
+	}
+      else
+	{
+	  n_bytes++;
+	  sb |= 0x10;
+	  if (imm % 2)
+	    sb |= 0x08;
+	}
+    }
+  else
+    {
+      n_bytes += n_opr_bytes2;
+      sb |= 0x10;
+    }
+
+  char *f = s12z_new_insn (n_bytes);
+  number_to_chars_bigendian (f++, insn->opc | Dd, 1);
+  number_to_chars_bigendian (f++, sb, 1);
+  f = emit_opr (f, buffer1, n_opr_bytes1, &exp1);
+  if (immediate)
+    {
+      if (imm != 1 && imm != 2)
+	{
+	  number_to_chars_bigendian (f++, 0x70 | (imm >> 1), 1);
+	}
+    }
+  else
+    {
+      f = emit_opr (f, buffer2, n_opr_bytes2, &exp2);
+    }
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+/* Shift instruction with a register operand */
+static int
+shift_reg  (const struct instruction *insn)
+{
+  short dir = -1;
+  short type = -1;
+  impute_shift_dir_and_type (insn, &type, &dir);
+
+  if (lex_shift_reg_imm1 (insn, type, dir))
+    return 1;
+
+  return lex_shift_reg (insn, type, dir);
+}
+
+static int
+bm_regd_imm  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+  int Di = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Di))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long imm;
+  if (!lex_imm (&imm))
+    goto fail;
+
+
+  uint8_t bm = imm << 3;
+  bm |= Di;
+
+  char *f = s12z_new_insn (2);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+bm_opr_reg  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer[4];
+  int n_opr_bytes;
+
+  expressionS exp;
+  if (!lex_opr (buffer, &n_opr_bytes,  &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dn = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dn))
+    goto fail;
+
+  uint8_t bm = Dn << 4;
+  int size = size_from_suffix (insn, 0);
+  bm |= (size - 1) << 2;
+  bm |= 0x81;
+
+  char *f = s12z_new_insn (2 + n_opr_bytes);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+
+  emit_opr (f, buffer, n_opr_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+bm_opr_imm  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer[4];
+  int n_opr_bytes;
+
+  expressionS exp;
+  if (!lex_opr (buffer, &n_opr_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+
+  long imm;
+  if (!lex_imm (&imm))
+    goto fail;
+
+  int size = size_from_suffix (insn, 0);
+
+  if (imm < 0 || imm >= size * 8)
+    {
+      as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm);
+      goto fail;
+    }
+
+  uint8_t bm = 0x80;
+  if (size == 2)
+    bm |= 0x02;
+  else if (size == 4)
+    bm |= 0x08;
+  bm |= (imm & 0x07) << 4;
+  bm |= (imm >> 3);
+
+
+  char *f = s12z_new_insn (2 + n_opr_bytes);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+  emit_opr (f, buffer, n_opr_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+bm_regd_reg  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+  int Di = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Di))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dn = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dn))
+    goto fail;
+
+  uint8_t bm = Dn << 4;
+  bm |= 0x81;
+
+  uint8_t xb = Di | 0xb8;
+
+  char *f = s12z_new_insn (3);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+  number_to_chars_bigendian (f++, xb, 1);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+
+
+
+static int
+bf_reg_opr_imm  (const struct instruction *insn, short ie)
+{
+  char *ilp = input_line_pointer;
+  int Dd = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t buffer[4];
+  int n_bytes;
+
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long width;
+  if (!lex_imm (&width))
+    goto fail;
+
+  if (width < 0 || width > 31)
+    {
+      as_bad (_("Invalid width value for %s"), insn->name);
+      goto fail;
+    }
+
+  if (!lex_match (':'))
+    goto fail;
+
+  long offset;
+  if (!lex_constant (&offset))
+    goto fail;
+
+  if (offset < 0 || offset > 31)
+    {
+      as_bad (_("Invalid offset value for %s"), insn->name);
+      goto fail;
+    }
+
+  uint8_t i1 = width << 5;
+  i1 |= offset;
+
+  int size = size_from_suffix (insn, 0);
+  uint8_t bb = ie ? 0x80 : 0x00;
+  bb |= 0x60;
+  bb |= (size - 1) << 2;
+  bb |= width >> 3;
+
+  char *f = s12z_new_insn (4 + n_bytes);
+  number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+  number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+  number_to_chars_bigendian (f++, bb, 1);
+  number_to_chars_bigendian (f++, i1, 1);
+
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+bf_opr_reg_imm  (const struct instruction *insn, short ie)
+{
+  char *ilp = input_line_pointer;
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Ds = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Ds))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long width;
+  if (!lex_imm (&width))
+    goto fail;
+
+  if (width < 0 || width > 31)
+    {
+      as_bad (_("Invalid width value for %s"), insn->name);
+      goto fail;
+    }
+
+  if (!lex_match (':'))
+    goto fail;
+
+  long offset;
+  if (!lex_constant (&offset))
+    goto fail;
+
+  if (offset < 0 || offset > 31)
+    {
+      as_bad (_("Invalid offset value for %s"), insn->name);
+      goto fail;
+    }
+
+  uint8_t i1 = width << 5;
+  i1 |= offset;
+
+  int size = size_from_suffix (insn, 0);
+  uint8_t bb = ie ? 0x80 : 0x00;
+  bb |= 0x70;
+  bb |= (size - 1) << 2;
+  bb |= width >> 3;
+
+  char *f = s12z_new_insn (4 + n_bytes);
+  number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+  number_to_chars_bigendian (f++, 0x08 | Ds, 1);
+  number_to_chars_bigendian (f++, bb, 1);
+  number_to_chars_bigendian (f++, i1, 1);
+
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+
+static int
+bf_reg_reg_imm  (const struct instruction *insn, short ie)
+{
+  char *ilp = input_line_pointer;
+  int Dd = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Ds = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Ds))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long width;
+  if (!lex_imm (&width))
+    goto fail;
+
+  if (width < 0 || width > 31)
+    {
+      as_bad (_("Invalid width value for %s"), insn->name);
+      goto fail;
+    }
+
+  if (!lex_match (':'))
+    goto fail;
+
+  long offset;
+  if (!lex_constant (&offset))
+    goto fail;
+
+  if (offset < 0 || offset > 31)
+    {
+      as_bad (_("Invalid offset value for %s"), insn->name);
+      goto fail;
+    }
+
+  uint8_t bb = ie ? 0x80 : 0x00;
+  bb |= 0x20;
+  bb |= Ds << 2;
+  bb |= width >> 3;
+
+  uint8_t i1 = width << 5;
+  i1 |= offset;
+
+  char *f = s12z_new_insn (4);
+  number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+  number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+  number_to_chars_bigendian (f++, bb, 1);
+  number_to_chars_bigendian (f++, i1, 1);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+bf_reg_reg_reg  (const struct instruction *insn ATTRIBUTE_UNUSED, short ie)
+{
+  char *ilp = input_line_pointer;
+  int Dd = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Ds = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Ds))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dp = 0;
+  if (!lex_reg_name  ((0x01u << REG_D2) |
+		      (0x01u << REG_D3) |
+		      (0x01u << REG_D4) |
+		      (0x01u << REG_D5),
+		      &Dp))
+    goto fail;
+
+  uint8_t bb = ie ? 0x80 : 0x00;
+  bb |= Ds << 2;
+  bb |= Dp;
+
+  char *f = s12z_new_insn (3);
+  number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+  number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+  number_to_chars_bigendian (f++, bb , 1);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+bf_opr_reg_reg  (const struct instruction *insn, short ie)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+
+  int Ds = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Ds))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+
+  int Dp = 0;
+  if (!lex_reg_name  ((0x01u << REG_D2) |
+		      (0x01u << REG_D3) |
+		      (0x01u << REG_D4) |
+		      (0x01u << REG_D5),
+		      &Dp))
+    goto fail;
+
+  int size = size_from_suffix (insn, 0);
+  uint8_t bb = ie ? 0x80 : 0x00;
+  bb |= 0x50;
+  bb |= Dp;
+  bb |= (size - 1) << 2;
+
+  char *f = s12z_new_insn (3 + n_bytes);
+  number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+  number_to_chars_bigendian (f++, 0x08 | Ds, 1);
+  number_to_chars_bigendian (f++, bb , 1);
+
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+bf_reg_opr_reg  (const struct instruction *insn, short ie)
+{
+  char *ilp = input_line_pointer;
+  int Dd = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dd))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dp = 0;
+  if (!lex_reg_name  ((0x01u << REG_D2) |
+		      (0x01u << REG_D3) |
+		      (0x01u << REG_D4) |
+		      (0x01u << REG_D5),
+		      &Dp))
+    goto fail;
+
+  int size = size_from_suffix (insn, 0);
+  uint8_t bb = ie ? 0x80 : 0x00;
+  bb |= 0x40;
+  bb |= Dp;
+  bb |= (size - 1) << 2;
+
+  char *f = s12z_new_insn (3 + n_bytes);
+  number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+  number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+  number_to_chars_bigendian (f++, bb , 1);
+
+  emit_opr (f, buffer, n_bytes, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+
+static int
+bfe_reg_reg_reg  (const struct instruction *insn)
+{
+  return bf_reg_reg_reg (insn, 0);
+}
+
+static int
+bfi_reg_reg_reg  (const struct instruction *insn)
+{
+  return bf_reg_reg_reg (insn, 1);
+}
+
+static int
+bfe_reg_reg_imm  (const struct instruction *insn)
+{
+  return bf_reg_reg_imm (insn, 0);
+}
+
+static int
+bfi_reg_reg_imm  (const struct instruction *insn)
+{
+  return bf_reg_reg_imm (insn, 1);
+}
+
+
+static int
+bfe_reg_opr_reg  (const struct instruction *insn)
+{
+  return bf_reg_opr_reg (insn, 0);
+}
+
+static int
+bfi_reg_opr_reg  (const struct instruction *insn)
+{
+  return bf_reg_opr_reg (insn, 1);
+}
+
+
+static int
+bfe_opr_reg_reg  (const struct instruction *insn)
+{
+  return bf_opr_reg_reg (insn, 0);
+}
+
+static int
+bfi_opr_reg_reg  (const struct instruction *insn)
+{
+  return bf_opr_reg_reg (insn, 1);
+}
+
+static int
+bfe_reg_opr_imm  (const struct instruction *insn)
+{
+  return bf_reg_opr_imm (insn, 0);
+}
+
+static int
+bfi_reg_opr_imm  (const struct instruction *insn)
+{
+  return bf_reg_opr_imm (insn, 1);
+}
+
+static int
+bfe_opr_reg_imm  (const struct instruction *insn)
+{
+  return bf_opr_reg_imm (insn, 0);
+}
+
+static int
+bfi_opr_reg_imm  (const struct instruction *insn)
+{
+  return bf_opr_reg_imm (insn, 1);
+}
+
+
+
+
+static int
+tb_reg_rel  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int reg;
+  if (!lex_reg_name (REG_BIT_Dn | REG_BIT_XY, &reg))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  bool long_displacement;
+  expressionS exp;
+  if (! lex_15_bit_offset (&long_displacement, &exp))
+    goto fail;
+
+  uint8_t lb = 0x00;
+  if (reg == REG_X || reg == REG_Y)
+    {
+      lb |= 0x08;
+    }
+  else
+    {
+      lb |= reg;
+    }
+  if (reg == REG_Y)
+    lb |= 0x01;
+
+  if (0 == strncmp (insn->name + 2, "ne", 2))
+    lb |= 0x00 << 4;
+  else if (0 == strncmp (insn->name + 2, "eq", 2))
+    lb |= 0x01 << 4;
+  else if (0 == strncmp (insn->name + 2, "pl", 2))
+    lb |= 0x02 << 4;
+  else if (0 == strncmp (insn->name + 2, "mi", 2))
+    lb |= 0x03 << 4;
+  else if (0 == strncmp (insn->name + 2, "gt", 2))
+    lb |= 0x04 << 4;
+  else if (0 == strncmp (insn->name + 2, "le", 2))
+    lb |= 0x05 << 4;
+
+  switch (insn->name[0])
+    {
+    case 'd':
+      lb |= 0x80;
+      break;
+    case 't':
+      break;
+    default:
+      gas_assert (0);
+      break;
+    };
+
+  char *f = s12z_new_insn (long_displacement ? 4 : 3);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, lb, 1);
+
+  emit_15_bit_offset (f, 4, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+tb_opr_rel  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  bool long_displacement;
+  expressionS exp2;
+  if (! lex_15_bit_offset (&long_displacement, &exp2))
+    goto fail;
+
+  uint8_t lb = 0x0C;
+
+  if (0 == strncmp (insn->name + 2, "ne", 2))
+    lb |= 0x00 << 4;
+  else if (0 == strncmp (insn->name + 2, "eq", 2))
+    lb |= 0x01 << 4;
+  else if (0 == strncmp (insn->name + 2, "pl", 2))
+    lb |= 0x02 << 4;
+  else if (0 == strncmp (insn->name + 2, "mi", 2))
+    lb |= 0x03 << 4;
+  else if (0 == strncmp (insn->name + 2, "gt", 2))
+    lb |= 0x04 << 4;
+  else if (0 == strncmp (insn->name + 2, "le", 2))
+    lb |= 0x05 << 4;
+
+  switch (insn->name[0])
+    {
+    case 'd':
+      lb |= 0x80;
+      break;
+    case 't':
+      break;
+    default:
+      gas_assert (0);
+      break;
+    };
+
+  int size = size_from_suffix (insn, 0);
+
+  lb |= size -1;
+
+  char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, lb, 1);
+  f = emit_opr (f, buffer, n_bytes, &exp);
+
+  emit_15_bit_offset (f, n_bytes + 4, &exp2);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+
+
+static int
+test_br_reg_reg_rel  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int Di = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Di))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+
+  int Dn = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dn))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+
+  bool long_displacement;
+  expressionS exp;
+  if (! lex_15_bit_offset (&long_displacement, &exp))
+    goto fail;
+
+  uint8_t bm = 0x81;
+  uint8_t xb = 0xb8;
+
+  bm |= Dn << 4;
+  xb |= Di;
+
+  char *f = s12z_new_insn (long_displacement ? 5 : 4);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+  number_to_chars_bigendian (f++, xb, 1);
+
+  emit_15_bit_offset (f, 5, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+static int
+test_br_opr_reg_rel  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes,  &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  int Dn = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Dn))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  uint8_t bm = 0x81;
+  bm |= Dn << 4;
+  int size = size_from_suffix (insn, 0);
+  bm |= (size -1) << 2;
+
+  bool long_displacement;
+
+  expressionS exp2;
+  if (! lex_15_bit_offset (&long_displacement, &exp2))
+    goto fail;
+
+  int n = n_bytes + (long_displacement ? 4 : 3);
+  char *f = s12z_new_insn (n);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+  f = emit_opr (f, buffer, n_bytes, &exp);
+
+  emit_15_bit_offset (f, n, &exp2);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+test_br_opr_imm_rel  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  uint8_t buffer[4];
+  int n_bytes;
+  expressionS exp;
+  if (!lex_opr (buffer, &n_bytes, &exp))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long imm;
+  if (!lex_imm (&imm))
+    goto fail;
+
+  if (imm < 0 || imm > 31)
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  bool long_displacement;
+  expressionS exp2;
+  if (! lex_15_bit_offset (&long_displacement, &exp2))
+    goto fail;
+
+  int size = size_from_suffix (insn, 0);
+
+  uint8_t bm = 0x80;
+  bm |= (imm & 0x07) << 4;
+  bm |= (imm >> 3) & 0x03;
+  if (size == 4)
+    bm |=  0x08;
+  else if  (size == 2)
+    bm |= 0x02;
+
+  char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+  f = emit_opr (f, buffer, n_bytes, &exp);
+
+  emit_15_bit_offset (f, n_bytes + 4,  &exp2);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+static int
+test_br_reg_imm_rel  (const struct instruction *insn)
+{
+  char *ilp = input_line_pointer;
+
+  int Di = 0;
+  if (!lex_reg_name (REG_BIT_Dn, &Di))
+    goto fail;
+
+  if (!lex_match (','))
+    goto fail;
+
+  long imm;
+  if (!lex_imm (&imm))
+    goto fail;
+
+  if (imm < 0 || imm > 31)
+    goto fail;
+
+
+  if (!lex_match (','))
+    goto fail;
+
+  bool long_displacement;
+  expressionS exp;
+  if (! lex_15_bit_offset (&long_displacement, &exp))
+    goto fail;
+
+  uint8_t bm = Di;
+  bm |= imm << 3;
+
+  char *f = s12z_new_insn (long_displacement ? 4 : 3);
+  number_to_chars_bigendian (f++, insn->opc, 1);
+  number_to_chars_bigendian (f++, bm, 1);
+
+  emit_15_bit_offset (f, 4, &exp);
+
+  return 1;
+
+ fail:
+  fail_line_pointer = input_line_pointer;
+  input_line_pointer = ilp;
+  return 0;
+}
+
+
+
+
+static const struct instruction opcodes[] = {
+  {"bgnd", 1,  0x00,  no_operands, 0},
+  {"nop", 1,   0x01,  no_operands, 0},
+
+  {"brclr", 1, 0x02,  test_br_reg_reg_rel, 0},
+  {"brset", 1, 0x03,  test_br_reg_reg_rel, 0},
+
+  {"brclr", 1, 0x02,  test_br_reg_imm_rel, 0},
+  {"brset", 1, 0x03,  test_br_reg_imm_rel, 0},
+
+  {"brclr.b", 1, 0x02, test_br_opr_reg_rel, 0},
+  {"brclr.w", 1, 0x02, test_br_opr_reg_rel, 0},
+  {"brclr.l", 1, 0x02, test_br_opr_reg_rel, 0},
+
+  {"brset.b", 1, 0x03, test_br_opr_reg_rel, 0},
+  {"brset.w", 1, 0x03, test_br_opr_reg_rel, 0},
+  {"brset.l", 1, 0x03, test_br_opr_reg_rel, 0},
+
+  {"brclr.b", 1, 0x02, test_br_opr_imm_rel, 0},
+  {"brclr.w", 1, 0x02, test_br_opr_imm_rel, 0},
+  {"brclr.l", 1, 0x02, test_br_opr_imm_rel, 0},
+
+  {"brset.b", 1, 0x03, test_br_opr_imm_rel, 0},
+  {"brset.w", 1, 0x03, test_br_opr_imm_rel, 0},
+  {"brset.l", 1, 0x03, test_br_opr_imm_rel, 0},
+
+  {"psh", 1,   0x04,  psh_pull, 0},
+  {"pul", 1,   0x04,  psh_pull, 0},
+
+  {"rts", 1,   0x05,  no_operands, 0},
+  {"lea", 1,   0x06,  reg67sxy_opr, 0},
+
+  {"dbne", 1,  0x0b,  tb_reg_rel, 0},
+  {"dbeq", 1,  0x0b,  tb_reg_rel, 0},
+  {"dbpl", 1,  0x0b,  tb_reg_rel, 0},
+  {"dbmi", 1,  0x0b,  tb_reg_rel, 0},
+  {"dbgt", 1,  0x0b,  tb_reg_rel, 0},
+  {"dble", 1,  0x0b,  tb_reg_rel, 0},
+
+  {"dbne.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbeq.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbpl.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbmi.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbgt.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"dble.b", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"dbne.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbeq.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbpl.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbmi.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbgt.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"dble.w", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"dbne.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbeq.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbpl.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbmi.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbgt.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"dble.p", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"dbne.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbeq.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbpl.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbmi.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"dbgt.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"dble.l", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"tbne", 1,  0x0b,  tb_reg_rel, 0},
+  {"tbeq", 1,  0x0b,  tb_reg_rel, 0},
+  {"tbpl", 1,  0x0b,  tb_reg_rel, 0},
+  {"tbmi", 1,  0x0b,  tb_reg_rel, 0},
+  {"tbgt", 1,  0x0b,  tb_reg_rel, 0},
+  {"tble", 1,  0x0b,  tb_reg_rel, 0},
+
+  {"tbne.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbeq.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbpl.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbmi.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbgt.b", 1,  0x0b,  tb_opr_rel, 0},
+  {"tble.b", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"tbne.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbeq.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbpl.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbmi.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbgt.w", 1,  0x0b,  tb_opr_rel, 0},
+  {"tble.w", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"tbne.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbeq.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbpl.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbmi.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbgt.p", 1,  0x0b,  tb_opr_rel, 0},
+  {"tble.p", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"tbne.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbeq.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbpl.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbmi.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"tbgt.l", 1,  0x0b,  tb_opr_rel, 0},
+  {"tble.l", 1,  0x0b,  tb_opr_rel, 0},
+
+  {"mov.b", 1, 0x0c,  imm_opr, 0},
+  {"mov.w", 1, 0x0d,  imm_opr, 0},
+  {"mov.p", 1, 0x0e,  imm_opr, 0},
+  {"mov.l", 1, 0x0f,  imm_opr, 0},
+
+  {"rol",   1, 0x10,  rol, 0},
+  {"rol.b", 1, 0x10,  rol, 0},
+  {"rol.w", 1, 0x10,  rol, 0},
+  {"rol.p", 1, 0x10,  rol, 0},
+  {"rol.l", 1, 0x10,  rol, 0},
+
+  {"ror",   1, 0x10,  ror, 0},
+  {"ror.b", 1, 0x10,  ror, 0},
+  {"ror.w", 1, 0x10,  ror, 0},
+  {"ror.p", 1, 0x10,  ror, 0},
+  {"ror.l", 1, 0x10,  ror, 0},
+
+  {"lsl", 1,   0x10,  shift_reg, 0},
+  {"lsr", 1,   0x10,  shift_reg, 0},
+  {"asl", 1,   0x10,  shift_reg, 0},
+  {"asr", 1,   0x10,  shift_reg, 0},
+
+  {"lsl.b", 1, 0x10,  shift_two_operand, 0},
+  {"lsl.w", 1, 0x10,  shift_two_operand, 0},
+  {"lsl.p", 1, 0x10,  shift_two_operand, 0},
+  {"lsl.l", 1, 0x10,  shift_two_operand, 0},
+  {"asl.b", 1, 0x10,  shift_two_operand, 0},
+  {"asl.w", 1, 0x10,  shift_two_operand, 0},
+  {"asl.p", 1, 0x10,  shift_two_operand, 0},
+  {"asl.l", 1, 0x10,  shift_two_operand, 0},
+
+  {"lsr.b", 1, 0x10,  shift_two_operand, 0},
+  {"lsr.w", 1, 0x10,  shift_two_operand, 0},
+  {"lsr.p", 1, 0x10,  shift_two_operand, 0},
+  {"lsr.l", 1, 0x10,  shift_two_operand, 0},
+  {"asr.b", 1, 0x10,  shift_two_operand, 0},
+  {"asr.w", 1, 0x10,  shift_two_operand, 0},
+  {"asr.p", 1, 0x10,  shift_two_operand, 0},
+  {"asr.l", 1, 0x10,  shift_two_operand, 0},
+
+  {"lsl.b", 1, 0x10,  shift_opr_imm, 0},
+  {"lsl.w", 1, 0x10,  shift_opr_imm, 0},
+  {"lsl.p", 1, 0x10,  shift_opr_imm, 0},
+  {"lsl.l", 1, 0x10,  shift_opr_imm, 0},
+  {"asl.b", 1, 0x10,  shift_opr_imm, 0},
+  {"asl.w", 1, 0x10,  shift_opr_imm, 0},
+  {"asl.p", 1, 0x10,  shift_opr_imm, 0},
+  {"asl.l", 1, 0x10,  shift_opr_imm, 0},
+
+  {"lsr.b", 1, 0x10,  shift_opr_imm, 0},
+  {"lsr.w", 1, 0x10,  shift_opr_imm, 0},
+  {"lsr.p", 1, 0x10,  shift_opr_imm, 0},
+  {"lsr.l", 1, 0x10,  shift_opr_imm, 0},
+  {"asr.b", 1, 0x10,  shift_opr_imm, 0},
+  {"asr.w", 1, 0x10,  shift_opr_imm, 0},
+  {"asr.p", 1, 0x10,  shift_opr_imm, 0},
+  {"asr.l", 1, 0x10,  shift_opr_imm, 0},
+
+  {"mov.b", 1, 0x1c,  opr_opr, 0},
+  {"mov.w", 1, 0x1d,  opr_opr, 0},
+  {"mov.p", 1, 0x1e,  opr_opr, 0},
+  {"mov.l", 1, 0x1f,  opr_opr, 0},
+
+  {"bra", 1,   0x20,  rel, 0},
+  {"bsr", 1,   0x21,  rel, 0},
+  {"bhi", 1,   0x22,  rel, 0},
+  {"bls", 1,   0x23,  rel, 0},
+  {"bcc", 1,   0x24,  rel, 0},
+  {"bcs", 1,   0x25,  rel, 0},
+  {"bne", 1,   0x26,  rel, 0},
+  {"beq", 1,   0x27,  rel, 0},
+  {"bvc", 1,   0x28,  rel, 0},
+  {"bvs", 1,   0x29,  rel, 0},
+  {"bpl", 1,   0x2a,  rel, 0},
+  {"bmi", 1,   0x2b,  rel, 0},
+  {"bge", 1,   0x2c,  rel, 0},
+  {"blt", 1,   0x2d,  rel, 0},
+  {"bgt", 1,   0x2e,  rel, 0},
+  {"ble", 1,   0x2f,  rel, 0},
+
+  {"inc", 1,   0x30,  reg_inh, 0},
+  {"clr", 1,   0x38,  reg_inh, 0},
+  {"dec", 1,   0x40,  reg_inh, 0},
+
+  {"muls", 1,  0x48,  mul_reg_reg_reg, 0},
+  {"mulu", 1,  0x48,  mul_reg_reg_reg, 0},
+
+  {"muls.b", 1,  0x48,  mul_reg_reg_opr, 0},
+  {"muls.w", 1,  0x48,  mul_reg_reg_opr, 0},
+  {"muls.l", 1,  0x48,  mul_reg_reg_opr, 0},
+
+  {"mulu.b", 1,  0x48,  mul_reg_reg_opr, 0},
+  {"mulu.w", 1,  0x48,  mul_reg_reg_opr, 0},
+  {"mulu.l", 1,  0x48,  mul_reg_reg_opr, 0},
+
+  {"muls.b", 1,  0x48,  mul_reg_reg_imm, 0},
+  {"muls.w", 1,  0x48,  mul_reg_reg_imm, 0},
+  {"muls.l", 1,  0x48,  mul_reg_reg_imm, 0},
+
+  {"mulu.b", 1,  0x48,  mul_reg_reg_imm, 0},
+  {"mulu.w", 1,  0x48,  mul_reg_reg_imm, 0},
+  {"mulu.l", 1,  0x48,  mul_reg_reg_imm, 0},
+
+  {"muls.bb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.bw", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.bp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.bl", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"muls.wb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.ww", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.wp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.wl", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"muls.pb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.pw", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.pp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.pl", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"muls.lb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.lw", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.lp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"muls.ll", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"mulu.bb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.bw", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.bp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.bl", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"mulu.wb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.ww", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.wp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.wl", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"mulu.pb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.pw", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.pp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.pl", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"mulu.lb", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.lw", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.lp", 1,  0x48,  mul_reg_opr_opr, 0},
+  {"mulu.ll", 1,  0x48,  mul_reg_opr_opr, 0},
+
+  {"add", 1,   0x50,  regd_imm, 0},
+  {"and", 1,   0x58,  regd_imm, 0},
+
+  {"add", 1,   0x60,  regd_opr, 0},
+  {"and", 1,   0x68,  regd_opr, 0},
+
+  {"sub", 1,   0x70,  regd_imm, 0},
+  {"or", 1,    0x78,  regd_imm, 0},
+
+  {"sub", 1,   0x80,  regd_opr, 0},
+  {"or",  1,    0x88,  regd_opr, 0},
+
+  {"ld",  1,    0x90,  regdxy_imm, 0},
+
+  {"clr", 1,   0x9a,  clr_xy, 0},
+  {"tfr", 1,   0x9e,  tfr, 0},
+  {"zex", 1,   0x9e,  tfr, 0},
+
+  {"ld",  1,   0xa0,  regdxy_opr, 0xb0},
+
+  {"jmp", 1,   0xaa,  opr, 0xba},
+  {"jsr", 1,   0xab,  opr, 0xbb},
+
+  {"exg", 1,   0xae,  tfr, 0},
+  {"sex", 1,   0xae,  tfr, 0},
+
+  {"st", 1,    0xc0,  regdxy_opr, 0xd0},
+
+  {"andcc", 1, 0xce,  imm8, 0},
+  {"orcc", 1,  0xde,  imm8, 0},
+
+  {"inc.b", 1, 0x9c,  opr, 0},
+  {"inc.w", 1, 0x9d,  opr, 0},
+  {"inc.l", 1, 0x9f,  opr, 0},
+
+  {"dec.b", 1, 0xac,  opr, 0},
+  {"dec.w", 1, 0xad,  opr, 0},
+  {"dec.l", 1, 0xaf,  opr, 0},
+
+  {"clr.b", 1, 0xbc,  opr, 0},
+  {"clr.w", 1, 0xbd,  opr, 0},
+  {"clr.p", 1, 0xbe,  opr, 0},
+  {"clr.l", 1, 0xbf,  opr, 0},
+
+  {"com.b", 1, 0xcc,  opr, 0},
+  {"com.w", 1, 0xcd,  opr, 0},
+  {"com.l", 1, 0xcf,  opr, 0},
+
+  {"neg.b", 1, 0xdc,  opr, 0},
+  {"neg.w", 1, 0xdd,  opr, 0},
+  {"neg.l", 1, 0xdf,  opr, 0},
+
+  {"bclr",  1, 0xec, bm_regd_imm, 0},
+  {"bset",  1, 0xed, bm_regd_imm, 0},
+  {"btgl",  1, 0xee, bm_regd_imm, 0},
+
+  {"bclr",  1, 0xec, bm_regd_reg, 0},
+  {"bset",  1, 0xed, bm_regd_reg, 0},
+  {"btgl",  1, 0xee, bm_regd_reg, 0},
+
+  {"bclr.b",  1, 0xec, bm_opr_imm, 0},
+  {"bclr.w",  1, 0xec, bm_opr_imm, 0},
+  {"bclr.l",  1, 0xec, bm_opr_imm, 0},
+
+  {"bset.b",  1, 0xed, bm_opr_imm, 0},
+  {"bset.w",  1, 0xed, bm_opr_imm, 0},
+  {"bset.l",  1, 0xed, bm_opr_imm, 0},
+
+  {"btgl.b",  1, 0xee, bm_opr_imm, 0},
+  {"btgl.w",  1, 0xee, bm_opr_imm, 0},
+  {"btgl.l",  1, 0xee, bm_opr_imm, 0},
+
+  {"bclr.b",  1, 0xec, bm_opr_reg, 0},
+  {"bclr.w",  1, 0xec, bm_opr_reg, 0},
+  {"bclr.l",  1, 0xec, bm_opr_reg, 0},
+
+  {"bset.b",  1, 0xed, bm_opr_reg, 0},
+  {"bset.w",  1, 0xed, bm_opr_reg, 0},
+  {"bset.l",  1, 0xed, bm_opr_reg, 0},
+
+  {"btgl.b",  1, 0xee, bm_opr_reg, 0},
+  {"btgl.w",  1, 0xee, bm_opr_reg, 0},
+  {"btgl.l",  1, 0xee, bm_opr_reg, 0},
+
+  {"cmp", 1,   0xe0,  regdxy_imm, 0},
+  {"cmp", 1,   0xf0,  regdxy_opr, 0},
+
+  {"cmp", 1,   0xfc,  regx_regy, 0},
+  {"sub", 1,   0xfd,  regd6_regx_regy, 0},
+  {"sub", 1,   0xfe,  regd6_regy_regx, 0},
+
+  {"swi", 1,   0xff,  no_operands, 0},
+
+  /* Page 2 */
+
+  /* The -10 below is a kludge.  The opcode is in fact 0x00 */
+  {"ld",    2,  -10,  regs_opr, 0},
+
+  /* The -9 below is a kludge.  The opcode is in fact 0x01 */
+  {"st",    2,  -9,  regs_opr, 0},
+
+  /* The -8 below is a kludge.  The opcode is in fact 0x02 */
+  {"cmp",    2,  -8,  regs_opr, 0},
+
+  /* The -7 below is a kludge.  The opcode is in fact 0x03 */
+  {"ld",    2,  -7,  regs_imm, 0},
+
+  /* The -6 below is a kludge.  The opcode is in fact 0x04 */
+  {"cmp",    2,  -6,  regs_imm, 0},
+
+  {"bfext",   2,  0x08,  bfe_reg_reg_reg, 0},
+  {"bfext",   2,  0x08,  bfe_reg_reg_imm, 0},
+  {"bfext.b", 2,  0x08,  bfe_reg_opr_reg, 0},
+  {"bfext.w", 2,  0x08,  bfe_reg_opr_reg, 0},
+  {"bfext.p", 2,  0x08,  bfe_reg_opr_reg, 0},
+  {"bfext.l", 2,  0x08,  bfe_reg_opr_reg, 0},
+  {"bfext.b", 2,  0x08,  bfe_opr_reg_reg, 0},
+  {"bfext.w", 2,  0x08,  bfe_opr_reg_reg, 0},
+  {"bfext.p", 2,  0x08,  bfe_opr_reg_reg, 0},
+  {"bfext.l", 2,  0x08,  bfe_opr_reg_reg, 0},
+  {"bfext.b", 2,  0x08,  bfe_reg_opr_imm, 0},
+  {"bfext.w", 2,  0x08,  bfe_reg_opr_imm, 0},
+  {"bfext.p", 2,  0x08,  bfe_reg_opr_imm, 0},
+  {"bfext.l", 2,  0x08,  bfe_reg_opr_imm, 0},
+  {"bfext.b", 2,  0x08,  bfe_opr_reg_imm, 0},
+  {"bfext.w", 2,  0x08,  bfe_opr_reg_imm, 0},
+  {"bfext.p", 2,  0x08,  bfe_opr_reg_imm, 0},
+  {"bfext.l", 2,  0x08,  bfe_opr_reg_imm, 0},
+
+
+  {"bfins",   2,  0x08,  bfi_reg_reg_reg, 0},
+  {"bfins",   2,  0x08,  bfi_reg_reg_imm, 0},
+  {"bfins.b", 2,  0x08,  bfi_reg_opr_reg, 0},
+  {"bfins.w", 2,  0x08,  bfi_reg_opr_reg, 0},
+  {"bfins.p", 2,  0x08,  bfi_reg_opr_reg, 0},
+  {"bfins.l", 2,  0x08,  bfi_reg_opr_reg, 0},
+  {"bfins.b", 2,  0x08,  bfi_opr_reg_reg, 0},
+  {"bfins.w", 2,  0x08,  bfi_opr_reg_reg, 0},
+  {"bfins.p", 2,  0x08,  bfi_opr_reg_reg, 0},
+  {"bfins.l", 2,  0x08,  bfi_opr_reg_reg, 0},
+  {"bfins.b", 2,  0x08,  bfi_reg_opr_imm, 0},
+  {"bfins.w", 2,  0x08,  bfi_reg_opr_imm, 0},
+  {"bfins.p", 2,  0x08,  bfi_reg_opr_imm, 0},
+  {"bfins.l", 2,  0x08,  bfi_reg_opr_imm, 0},
+  {"bfins.b", 2,  0x08,  bfi_opr_reg_imm, 0},
+  {"bfins.w", 2,  0x08,  bfi_opr_reg_imm, 0},
+  {"bfins.p", 2,  0x08,  bfi_opr_reg_imm, 0},
+  {"bfins.l", 2,  0x08,  bfi_opr_reg_imm, 0},
+
+
+  {"minu",  2,  0x10,  regd_opr, 0},
+  {"maxu",  2,  0x18,  regd_opr, 0},
+  {"mins",  2,  0x20,  regd_opr, 0},
+  {"maxs",  2,  0x28,  regd_opr, 0},
+
+  {"clb",   2,  0x91,  tfr, 0},
+
+  {"trap",  2,  0x00, trap_imm, 0},
+  {"abs",   2,  0x40, reg_inh, 0},
+  {"sat",   2,  0xa0, reg_inh, 0},
+
+  {"rti",   2,  0x90, no_operands, 0},
+  {"stop",  2,  0x05, no_operands, 0},
+  {"wai",   2,  0x06, no_operands, 0},
+  {"sys",   2,  0x07, no_operands, 0},
+
+  {"bit",   2,   0x58,  regd_imm, 0},
+  {"bit",   2,   0x68,  regd_opr, 0},
+
+  {"adc",   2,   0x50,  regd_imm, 0},
+  {"adc",   2,   0x60,  regd_opr, 0},
+
+  {"sbc",   2,   0x70,  regd_imm, 0},
+  {"eor",   2,   0x78,  regd_imm, 0},
+
+  {"sbc",   2,   0x80,  regd_opr, 0},
+  {"eor",   2,   0x88,  regd_opr, 0},
+
+  {"divs",   2,  0x30,  mul_reg_reg_reg, 0},
+  {"divu",   2,  0x30,  mul_reg_reg_reg, 0},
+
+  {"divs.b", 2,  0x30,  mul_reg_reg_opr, 0},
+  {"divs.w", 2,  0x30,  mul_reg_reg_opr, 0},
+  {"divs.l", 2,  0x30,  mul_reg_reg_opr, 0},
+
+  {"divu.b", 2,  0x30,  mul_reg_reg_opr, 0},
+  {"divu.w", 2,  0x30,  mul_reg_reg_opr, 0},
+  {"divu.l", 2,  0x30,  mul_reg_reg_opr, 0},
+
+  {"divs.b", 2,  0x30,  mul_reg_reg_imm, 0},
+  {"divs.w", 2,  0x30,  mul_reg_reg_imm, 0},
+  {"divs.l", 2,  0x30,  mul_reg_reg_imm, 0},
+
+  {"divu.b", 2,  0x30,  mul_reg_reg_imm, 0},
+  {"divu.w", 2,  0x30,  mul_reg_reg_imm, 0},
+  {"divu.l", 2,  0x30,  mul_reg_reg_imm, 0},
+
+  {"divs.bb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.bw", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.bp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.bl", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divs.wb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.ww", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.wp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.wl", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divs.pb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.pw", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.pp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.pl", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divs.lb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.lw", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.lp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divs.ll", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divu.bb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.bw", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.bp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.bl", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divu.wb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.ww", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.wp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.wl", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divu.pb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.pw", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.pp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.pl", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  {"divu.lb", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.lw", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.lp", 2,  0x30,  mul_reg_opr_opr, 0},
+  {"divu.ll", 2,  0x30,  mul_reg_opr_opr, 0},
+
+  //
+
+  {"qmuls",   2,  0xb0,  mul_reg_reg_reg, 0},
+  {"qmulu",   2,  0xb0,  mul_reg_reg_reg, 0},
+
+  {"qmuls.b", 2,  0xb0,  mul_reg_reg_opr, 0},
+  {"qmuls.w", 2,  0xb0,  mul_reg_reg_opr, 0},
+  {"qmuls.l", 2,  0xb0,  mul_reg_reg_opr, 0},
+
+  {"qmulu.b", 2,  0xb0,  mul_reg_reg_opr, 0},
+  {"qmulu.w", 2,  0xb0,  mul_reg_reg_opr, 0},
+  {"qmulu.l", 2,  0xb0,  mul_reg_reg_opr, 0},
+
+  {"qmuls.b", 2,  0xb0,  mul_reg_reg_imm, 0},
+  {"qmuls.w", 2,  0xb0,  mul_reg_reg_imm, 0},
+  {"qmuls.l", 2,  0xb0,  mul_reg_reg_imm, 0},
+
+  {"qmulu.b", 2,  0xb0,  mul_reg_reg_imm, 0},
+  {"qmulu.w", 2,  0xb0,  mul_reg_reg_imm, 0},
+  {"qmulu.l", 2,  0xb0,  mul_reg_reg_imm, 0},
+
+  {"qmuls.bb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.bw", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.bp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.bl", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmuls.wb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.ww", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.wp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.wl", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmuls.pb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.pw", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.pp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.pl", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmuls.lb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.lw", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.lp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmuls.ll", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmulu.bb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.bw", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.bp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.bl", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmulu.wb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.ww", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.wp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.wl", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmulu.pb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.pw", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.pp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.pl", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+  {"qmulu.lb", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.lw", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.lp", 2,  0xb0,  mul_reg_opr_opr, 0},
+  {"qmulu.ll", 2,  0xb0,  mul_reg_opr_opr, 0},
+
+
+  //
+
+  {"macs",   2,  0x48,  mul_reg_reg_reg, 0},
+  {"macu",   2,  0x48,  mul_reg_reg_reg, 0},
+
+  {"macs.b", 2,  0x48,  mul_reg_reg_opr, 0},
+  {"macs.w", 2,  0x48,  mul_reg_reg_opr, 0},
+  {"macs.l", 2,  0x48,  mul_reg_reg_opr, 0},
+
+  {"macu.b", 2,  0x48,  mul_reg_reg_opr, 0},
+  {"macu.w", 2,  0x48,  mul_reg_reg_opr, 0},
+  {"macu.l", 2,  0x48,  mul_reg_reg_opr, 0},
+
+  {"macs.b", 2,  0x48,  mul_reg_reg_imm, 0},
+  {"macs.w", 2,  0x48,  mul_reg_reg_imm, 0},
+  {"macs.l", 2,  0x48,  mul_reg_reg_imm, 0},
+
+  {"macu.b", 2,  0x48,  mul_reg_reg_imm, 0},
+  {"macu.w", 2,  0x48,  mul_reg_reg_imm, 0},
+  {"macu.l", 2,  0x48,  mul_reg_reg_imm, 0},
+
+  {"macs.bb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.bw", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.bp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.bl", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macs.wb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.ww", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.wp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.wl", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macs.pb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.pw", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.pp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.pl", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macs.lb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.lw", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.lp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macs.ll", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macu.bb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.bw", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.bp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.bl", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macu.wb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.ww", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.wp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.wl", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macu.pb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.pw", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.pp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.pl", 2,  0x48,  mul_reg_opr_opr, 0},
+
+  {"macu.lb", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.lw", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.lp", 2,  0x48,  mul_reg_opr_opr, 0},
+  {"macu.ll", 2,  0x48,  mul_reg_opr_opr, 0},
+
+
+  //
+
+  {"mods",   2,  0x38,  mul_reg_reg_reg, 0},
+  {"modu",   2,  0x38,  mul_reg_reg_reg, 0},
+
+  {"mods.b", 2,  0x38,  mul_reg_reg_opr, 0},
+  {"mods.w", 2,  0x38,  mul_reg_reg_opr, 0},
+  {"mods.l", 2,  0x38,  mul_reg_reg_opr, 0},
+
+  {"modu.b", 2,  0x38,  mul_reg_reg_opr, 0},
+  {"modu.w", 2,  0x38,  mul_reg_reg_opr, 0},
+  {"modu.l", 2,  0x38,  mul_reg_reg_opr, 0},
+
+  {"mods.b", 2,  0x38,  mul_reg_reg_imm, 0},
+  {"mods.w", 2,  0x38,  mul_reg_reg_imm, 0},
+  {"mods.l", 2,  0x38,  mul_reg_reg_imm, 0},
+
+  {"modu.b", 2,  0x38,  mul_reg_reg_imm, 0},
+  {"modu.w", 2,  0x38,  mul_reg_reg_imm, 0},
+  {"modu.l", 2,  0x38,  mul_reg_reg_imm, 0},
+
+  {"mods.bb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.bw", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.bp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.bl", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"mods.wb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.ww", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.wp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.wl", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"mods.pb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.pw", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.pp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.pl", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"mods.lb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.lw", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.lp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"mods.ll", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"modu.bb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.bw", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.bp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.bl", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"modu.wb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.ww", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.wp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.wl", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"modu.pb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.pw", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.pp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.pl", 2,  0x38,  mul_reg_opr_opr, 0},
+
+  {"modu.lb", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.lw", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.lp", 2,  0x38,  mul_reg_opr_opr, 0},
+  {"modu.ll", 2,  0x38,  mul_reg_opr_opr, 0}
+};
+
+
+/* Gas line assembler entry point.  */
+
+/* This is the main entry point for the machine-dependent assembler.  str
+   points to a machine-dependent instruction.  This function is supposed to
+   emit the frags/bytes it assembles to.  */
+void
+md_assemble (char *str)
+{
+  char *op_start;
+  char *op_end;
+  char name[20];
+  size_t nlen = 0;
+
+  fail_line_pointer = NULL;
+
+  /* Find the opcode end and get the opcode in 'name'.  The opcode is forced
+     lower case (the opcode table only has lower case op-codes).  */
+  for (op_start = op_end = str;
+       *op_end && !is_end_of_line[(int)*op_end] && *op_end != ' ';
+       op_end++)
+    {
+      name[nlen] = TOLOWER (op_start[nlen]);
+      nlen++;
+      gas_assert (nlen < sizeof (name) - 1);
+    }
+  name[nlen] = 0;
+
+  if (nlen == 0)
+    {
+      as_bad (_("No instruction or missing opcode."));
+      return;
+    }
+
+  input_line_pointer = skip_whites (op_end);
+
+  size_t i;
+  for (i = 0; i < sizeof (opcodes) / sizeof (opcodes[0]); ++i)
+    {
+      const struct instruction *opc = opcodes + i;
+      if (0 == strcmp (name, opc->name))
+	{
+	  if (opc->parse_operands (opc))
+	    return;
+	  continue;
+	}
+    }
+
+  as_bad (_("Invalid instruction: \"%s\""), str);
+  as_bad (_("First invalid token: \"%s\""), fail_line_pointer);
+  while (*input_line_pointer++)
+    ;
+}
+
+
+
+
+
+/* Relocation, relaxation and frag conversions.  */
+
+/* PC-relative offsets are relative to the start of the
+   next instruction.  That is, the address of the offset, plus its
+   size, since the offset is always the last part of the insn.  */
+long
+md_pcrel_from (fixS *fixP)
+{
+  long ret = fixP->fx_size + fixP->fx_frag->fr_address;
+  if (fixP->fx_addsy && S_IS_DEFINED (fixP->fx_addsy))
+    ret += fixP->fx_where;
+
+  return ret;
+}
+
+
+/* We need a port-specific relaxation function to cope with sym2 - sym1
+   relative expressions with both symbols in the same segment (but not
+   necessarily in the same frag as this insn), for example:
+   ldab sym2-(sym1-2),pc
+   sym1:
+   The offset can be 5, 9 or 16 bits long.  */
+
+long
+s12z_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP ATTRIBUTE_UNUSED,
+		   long stretch ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+void
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED,
+                 fragS *fragP ATTRIBUTE_UNUSED)
+{
+}
+
+/* On an ELF system, we can't relax a weak symbol.  The weak symbol
+   can be overridden at final link time by a non weak symbol.  We can
+   relax externally visible symbol because there is no shared library
+   and such symbol can't be overridden (unless they are weak).  */
+
+/* Force truly undefined symbols to their maximum size, and generally set up
+   the frag list to be relaxed.  */
+int
+md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, asection *segment ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+
+/* If while processing a fixup, a reloc really needs to be created
+   then it is done here.  */
+arelent *
+tc_gen_reloc (asection *section, fixS *fixp)
+{
+  arelent *reloc = XNEW (arelent);
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
+  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+  if (reloc->howto == (reloc_howto_type *) NULL)
+    {
+      as_bad_where (fixp->fx_file, fixp->fx_line,
+		    _("Relocation %d is not supported by object file format."),
+		    (int) fixp->fx_r_type);
+      return NULL;
+    }
+
+  if (0 == (section->flags & SEC_CODE))
+    reloc->addend = fixp->fx_offset;
+  else
+    reloc->addend = fixp->fx_addnumber;
+
+  return reloc;
+}
+
+/* See whether we need to force a relocation into the output file.  */
+int
+tc_s12z_force_relocation (fixS *fixP)
+{
+  return generic_force_reloc (fixP);
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+   to the beginning of the section instead of the symbol.  Basically
+   we need to make sure that the linker relaxation is done
+   correctly, so in some cases we force the original symbol to be
+   used.  */
+int
+tc_s12z_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+void
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
+{
+  long value = *valP;
+
+  if (fixP->fx_addsy == (symbolS *) NULL)
+    fixP->fx_done = 1;
+
+  /* We don't actually support subtracting a symbol.  */
+  if (fixP->fx_subsy != (symbolS *) NULL)
+    as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));
+
+  /*
+    Patch the instruction with the resolved operand.  Elf relocation
+    info will also be generated to take care of linker/loader fixups.
+  */
+  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_8:
+      ((bfd_byte *) where)[0] = (bfd_byte) value;
+      break;
+    case BFD_RELOC_24:
+      bfd_putb24 ((bfd_vma) value, (unsigned char *) where);
+      break;
+    case BFD_RELOC_32:
+      bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
+      break;
+    case BFD_RELOC_16_PCREL:
+      if (value < -0x8000 || value > 0x7FFF)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      _("Value out of 16-bit range."));
+
+      bfd_putb16 ((bfd_vma) value | 0x8000, (unsigned char *) where);
+      break;
+
+    default:
+      as_fatal (_("Line %d: unknown relocation type: 0x%x."),
+		fixP->fx_line, fixP->fx_r_type);
+    }
+}
+
+/* Set the ELF specific flags.  */
+void
+s12z_elf_final_processing (void)
+{
+}
diff --git a/gas/config/tc-s12z.h b/gas/config/tc-s12z.h
new file mode 100644
index 0000000000..9d6b571b45
--- /dev/null
+++ b/gas/config/tc-s12z.h
@@ -0,0 +1,105 @@
+/* tc-s12z.h -- Header file for tc-s12z.c.
+   Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+struct fix;
+
+/* Define TC_M68K so that we can use the MRI mode.  */
+#define TC_M68K
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* Motorola assembler specs does not require '.' before pseudo-ops.  */
+#define NO_PSEUDO_DOT 1
+
+/* The target BFD architecture.  */
+#define TARGET_ARCH (s12z_arch ())
+extern enum bfd_architecture s12z_arch (void);
+
+#define TARGET_MACH (s12z_mach ())
+extern int s12z_mach (void);
+
+#define TARGET_FORMAT (s12z_arch_format ())
+extern const char *s12z_arch_format (void);
+
+#define LISTING_WORD_SIZE 1	/* A word is 1 bytes */
+#define LISTING_LHS_WIDTH 4	/* One word on the first line */
+#define LISTING_LHS_WIDTH_SECOND 4	/* One word on the second line */
+#define LISTING_LHS_CONT_LINES 4	/* And 4 lines max */
+#define LISTING_HEADER s12z_listing_header ()
+extern const char *s12z_listing_header (void);
+
+/* Permit temporary numeric labels.  */
+#define LOCAL_LABELS_FB 1
+
+#define tc_init_after_args s12z_init_after_args
+extern void s12z_init_after_args (void);
+
+#define md_parse_long_option s12z_parse_long_option
+extern int s12z_parse_long_option (char *);
+
+#define DWARF2_LINE_MIN_INSN_LENGTH 1
+
+/* Use 32-bit address to represent a symbol address so that we can
+   represent them with their page number.  */
+#define DWARF2_ADDR_SIZE(bfd) 4
+
+/* We don't need to handle .word strangely.  */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars           number_to_chars_bigendian
+
+/* Relax table to translate short relative branches (-128..127) into
+   absolute branches.  */
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+extern struct relax_type md_relax_table[];
+
+/* GAS only handles relaxations for pc-relative data targeting addresses
+   in the same segment, so we have to handle the rest on our own.  */
+#define md_relax_frag(SEG, FRAGP, STRETCH)		\
+ ((FRAGP)->fr_symbol != NULL				\
+  && S_GET_SEGMENT ((FRAGP)->fr_symbol) == (SEG)	\
+  ? relax_frag (SEG, FRAGP, STRETCH)			\
+  : s12z_relax_frag (SEG, FRAGP, STRETCH))
+extern long s12z_relax_frag (segT, fragS*, long);
+
+#define TC_HANDLES_FX_DONE
+
+#define DIFF_EXPR_OK		/* .-foo gets turned into PC relative relocs */
+
+/* Values passed to md_apply_fix don't include the symbol value.  */
+#define MD_APPLY_SYM_VALUE(FIX) 0
+
+/* No shared lib support, so we don't need to ensure externally
+   visible symbols can be overridden.  */
+#define EXTERN_FORCE_RELOC 0
+
+#define TC_FORCE_RELOCATION(fix) tc_s12z_force_relocation (fix)
+extern int tc_s12z_force_relocation (struct fix *);
+
+#define tc_fix_adjustable(X) tc_s12z_fix_adjustable(X)
+extern int tc_s12z_fix_adjustable (struct fix *);
+
+#define md_operand(x)
+
+#define elf_tc_final_processing	s12z_elf_final_processing
+extern void s12z_elf_final_processing (void);
+
+#define tc_print_statistics(FILE) s12z_print_statistics (FILE)
+extern void s12z_print_statistics (FILE *);
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 67edc1d197..3d0415c1aa 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -75,6 +75,7 @@ case ${cpu} in
   m680[012346]0)	cpu_type=m68k ;;
   m6811|m6812|m68hc12)	cpu_type=m68hc11 ;;
   m683??)		cpu_type=m68k ;;
+  s12z)               cpu_type=s12z ;;
   mep)			cpu_type=mep endian=little ;;
   microblazeel*)	cpu_type=microblaze endian=little;;
   microblaze*)		cpu_type=microblaze endian=big;;
@@ -285,6 +286,8 @@ case ${generic_target} in
   m68k-*-gnu*)				fmt=elf ;;
   m68k-*-netbsdelf*)			fmt=elf em=nbsd ;;
 
+  s12z-*-*)				fmt=elf ;;
+
   mep-*-elf)				fmt=elf ;;
 
   metag-*-elf)				fmt=elf ;;
diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am
index 80893581e1..c9c3405272 100644
--- a/gas/doc/Makefile.am
+++ b/gas/doc/Makefile.am
@@ -65,6 +65,7 @@ CPU_DOCS = \
 	c-m32r.texi \
 	c-m68hc11.texi \
 	c-m68k.texi \
+	c-s12z.texi \
 	c-metag.texi \
 	c-microblaze.texi \
 	c-mips.texi \
diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in
index 643df6175d..a126e2f159 100644
--- a/gas/doc/Makefile.in
+++ b/gas/doc/Makefile.in
@@ -340,6 +340,7 @@ CPU_DOCS = \
 	c-m32r.texi \
 	c-m68hc11.texi \
 	c-m68k.texi \
+	c-s12z.texi \
 	c-metag.texi \
 	c-microblaze.texi \
 	c-mips.texi \
diff --git a/gas/doc/all.texi b/gas/doc/all.texi
index 47d55df4f6..2b8af69027 100644
--- a/gas/doc/all.texi
+++ b/gas/doc/all.texi
@@ -46,6 +46,7 @@
 @set M32R
 @set xc16x
 @set M68HC11
+@set S12Z
 @set M680X0
 @set MCORE
 @set METAG
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 35616c8b55..b6b16b7b29 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -7565,6 +7565,9 @@ subject, see the hardware manufacturer's manual.
 @ifset M68HC11
 * M68HC11-Dependent::           M68HC11 and 68HC12 Dependent Features
 @end ifset
+@ifset S12Z
+* S12Z-Dependent::            S12Z Dependent Features
+@end ifset
 @ifset METAG
 * Meta-Dependent ::             Meta Dependent Features
 @end ifset
@@ -7776,6 +7779,10 @@ family.
 @include c-m68hc11.texi
 @end ifset
 
+@ifset S12Z
+@include c-s12z.texi
+@end ifset
+
 @ifset METAG
 @include c-metag.texi
 @end ifset
diff --git a/gas/doc/c-s12z.texi b/gas/doc/c-s12z.texi
new file mode 100644
index 0000000000..9c8a97f3cc
--- /dev/null
+++ b/gas/doc/c-s12z.texi
@@ -0,0 +1,212 @@
+@c Copyright (C) 2018 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node S12Z-Dependent
+@chapter S12Z Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter S12Z Dependent Features
+@end ifclear
+
+The Freescale S12Z version of @code{@value{AS}} has a few machine
+dependent features.
+
+@cindex S12Z support
+@menu
+* S12Z-Opts::                   S12Z Options
+* S12Z-Syntax::                 Syntax
+* S12Z-Directives::             Assembler Directives
+* S12Z-opcodes::                Opcodes
+@end menu
+
+@node S12Z-Opts
+@section S12Z Options
+
+@cindex options, S12Z
+@cindex S12Z options
+
+@node S12Z-Syntax
+@section Syntax
+
+@cindex S12Z syntax
+@cindex syntax, S12Z
+
+In the S12Z syntax, the instruction name comes first and it may
+be followed by one or by several operands.
+In most cases the maximum number of operands is three.
+Some instructions accept and (in certain situations require) a suffix
+indicating the size of the operand.
+The suffix is separated from the instruction name by a period (@samp{.})
+and may be one of @samp{b}, @samp{w}, @samp{p} or @samp{l} indicating
+`byte' (a single byte), `word' (2 bytes), `pointer' (3 bytes) or `long' (4 bytes)
+respectively.
+Operands are separated by a comma (@samp{,}).
+A comma however does not act as a separator if it appears within parentheses
+(@samp{()}) or within square brackets (@samp{[]}).
+@code{@value{AS}} will complain if too many, too few or inappropriate operands
+are specified for a given instruction.
+The MRI mode is not supported for this architecture.
+Example:
+
+@smallexample
+	bset.b  0xA98, #5
+	mov.b   #6, 0x2409
+	ld      d0, #4
+	mov.l   (d0, x), 0x2409
+	inc     d0
+	cmp     d0, #12
+	blt     *-4
+	lea     x, 0x2409
+	st      y,  (1, x)
+@end smallexample
+
+@cindex line comment character, S12Z
+@cindex S12Z line comment character
+The presence of a @samp{;} character anywhere
+on a line indicates the start of a comment that extends to the end of
+that line.
+
+A @samp{*} or a @samp{#} character at the start of a line also
+introduces a line comment, but these characters do not work elsewhere
+on the line.  If the first character of the line is a @samp{#} then as
+well as starting a comment, the line could also be logical line number
+directive (@pxref{Comments}) or a preprocessor control command
+(@pxref{Preprocessing}).
+
+@cindex line separator, S12Z
+@cindex statement separator, S12Z
+@cindex S12Z line separator
+The S12Z assembler does not currently support a line separator
+character.
+
+@cindex S12Z addressing modes
+@cindex addressing modes, S12Z
+The following addressing modes are understood for the S12Z.
+@table @dfn
+@item Immediate
+@samp{#@var{number}}
+
+@item Immediate Bit Field
+@samp{#@var{width}:@var{offset}}
+
+Bit field instructions in the immediate mode require the width and offset to
+be specified.
+The @var{width} pararmeter specifies the number of bits in the field.
+It should be a number in the range [1,32].
+@var{Offset} determines the position within the field where the operation
+should start.
+It should be a number in the range [0,31].
+
+@item Relative
+@samp{*@var{symbol}}, or @samp{*[+-]@var{digits}}
+
+Program counter relative addresses have a width of 15 bits.
+Thus, they must be within the range [-32768, 32767].
+
+@item Register
+@samp{@var{reg}}
+
+Some instructions accept a register as an operand.
+In general, @var{reg} may be a data register (@samp{D0}, @samp{D1} @dots{}
+@samp{D7}), the @var{X} register or the @var{Y} register.
+
+A few instructions accept as an argument the stack pointer
+register (@samp{S}), and/or the program counter (@samp{P}).
+
+Some very special instructions accept arguments which refer to the
+condition code register.  For these arguments the  syntax is
+@samp{CCR}, @samp{CCH} or @samp{CCL} which refer to the complete condition code register, the condition code register high byte and the condition code register low byte respectively.
+
+@item Absolute Direct
+@samp{@var{symbol}}, or @samp{@var{digits}}
+
+@item Absolute Indirect
+@samp{[@var{symbol}}, or @samp{@var{digits}]}
+
+
+@item Constant Offset Indexed
+@samp{(@var{number},@var{reg})}
+
+@var{Reg} may be either @samp{X}, @samp{Y}, @samp{S} or
+@samp{P} or one of the data registers @samp{D0}, @samp{D1} @dots{}
+@samp{D7}.
+If any of the registers @samp{D2} @dots{} @samp{D5} are specified, then the
+register value is treated as a signed value.
+Otherwise it is treated as unsigned.
+@var{Number} may be any integer in the range [-8388608,8388607].
+
+@item Offset Indexed Indirect
+@samp{[@var{number},@var{reg}]}
+
+@var{Reg} may be either @samp{X}, @samp{Y}, @samp{S} or
+@samp{P}.
+@var{Number} may be any integer in the range [-8388608,8388607].
+
+@item Auto Pre-Increment/Pre-Decrement/Post-Increment/Post-Decrement
+@samp{-@var{reg}},
+@samp{+@var{reg}},
+@samp{@var{reg}-} or
+@samp{@var{reg}+}
+
+This addressing mode is typically used to access a value at an address,
+and simultaneously to increment/decrement the register pointing to that
+address.
+Thus @var{reg} may be any of the 24 bit registers @samp{X}, @samp{Y}, or
+@samp{S}.
+Pre-increment and post-decrement are not available for
+register @samp{S} (only post-increment and pre-decrement are available).
+
+@item Register Offset Direct
+@samp{(@var{data-reg},@var{reg})}
+
+@var{Reg} can be either @samp{X}, @samp{Y}, or @samp{S}.
+@var{Data-reg}
+must be one of the data registers @samp{D0}, @samp{D1} @dots{} @samp{D7}.
+If any of the registers @samp{D2} @dots{} @samp{D5} are specified, then
+the register value is treated as a signed value.
+Otherwise it is treated as unsigned.
+
+@item Register Offset Indirect
+@samp{[@var{data-reg},@var{reg}]}
+
+@var{Reg} can be either @samp{X} or @samp{Y}.
+@var{Data-reg}
+must be one of the data registers @samp{D0}, @samp{D1} @dots{} @samp{D7}.
+If any of the registers @samp{D2} @dots{} @samp{D5} are specified, then
+the register value is treated as a signed value.
+Otherwise it is treated as unsigned.
+
+
+@end table
+
+For example:
+
+@smallexample
+	trap    #197
+	bra     *+49
+	bra     .L0
+	jmp     0xFE0034
+	jmp     [0xFD0012]
+	inc.b   (4,x)
+	dec.w   [4,y]
+	clr.p   (-s)
+	neg.l   (d0, s)
+	com.b   [d1, x]
+	jsr     (45, d0)
+	psh     cch
+@end smallexample
+
+@node S12Z-Directives
+@section Assembler Directives
+
+@cindex assembler directives, S12Z
+
+@node S12Z-opcodes
+@section Opcodes
+
+@cindex S12Z opcodes
+@cindex opcodes, S12Z
+@cindex instruction set, S12Z
diff --git a/gas/testsuite/gas/s12z/abs.d b/gas/testsuite/gas/s12z/abs.d
new file mode 100644
index 0000000000..b41238f065
--- /dev/null
+++ b/gas/testsuite/gas/s12z/abs.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  abs.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 40       	abs d2
+   2:	1b 41       	abs d3
+   4:	1b 42       	abs d4
+   6:	1b 43       	abs d5
+   8:	1b 44       	abs d0
+   a:	1b 45       	abs d1
+   c:	1b 46       	abs d6
+   e:	1b 47       	abs d7
diff --git a/gas/testsuite/gas/s12z/abs.s b/gas/testsuite/gas/s12z/abs.s
new file mode 100644
index 0000000000..718a2eb2a4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/abs.s
@@ -0,0 +1,8 @@
+	abs d2
+	abs d3
+	abs d4
+	abs d5
+	abs d0
+	abs d1
+	abs d6
+	abs d7
diff --git a/gas/testsuite/gas/s12z/adc-imm.d b/gas/testsuite/gas/s12z/adc-imm.d
new file mode 100644
index 0000000000..b13d136ee0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  adc-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 50 12 34 	adc d2, #4660
+   4:	1b 51 12 34 	adc d3, #4660
+   8:	1b 52 12 34 	adc d4, #4660
+   c:	1b 53 12 34 	adc d5, #4660
+  10:	1b 54 12    	adc d0, #18
+  13:	1b 55 34    	adc d1, #52
+  16:	1b 56 00 56 	adc d6, #5666970
+  1a:	78 9a 
+  1c:	1b 57 00 98 	adc d7, #9991764
+  20:	76 54 
diff --git a/gas/testsuite/gas/s12z/adc-imm.s b/gas/testsuite/gas/s12z/adc-imm.s
new file mode 100644
index 0000000000..cddf980cf2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-imm.s
@@ -0,0 +1,8 @@
+	adc d2, #0x1234
+	adc d3, #0x1234
+	adc d4, #0x1234
+	adc d5, #0x1234
+	adc d0, #0x12
+	adc d1, #0x34
+	adc d6, #0x56789A
+	adc d7, #0x987654
diff --git a/gas/testsuite/gas/s12z/adc-opr.d b/gas/testsuite/gas/s12z/adc-opr.d
new file mode 100644
index 0000000000..d2023a24b0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-opr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  adc-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 64 c5 21 	adc d0, \[-223,x\]
+   4:	1b 65 e2 ff 	adc d1, \(-2000,s\)
+   8:	f8 30 
+   a:	1b 60 c7    	adc d2, \(x-\)
+   d:	1b 61 f3    	adc d3, \(\+y\)
+  10:	1b 62 bb    	adc d4, d5
+  13:	1b 63 3e ce 	adc d5, 16078
+  17:	1b 66 fe 01 	adc d6, \[73056\]
+  1b:	1d 60 
+  1d:	1b 67 8a    	adc d7, \(d4,x\)
diff --git a/gas/testsuite/gas/s12z/adc-opr.s b/gas/testsuite/gas/s12z/adc-opr.s
new file mode 100644
index 0000000000..b16befc520
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-opr.s
@@ -0,0 +1,9 @@
+	adc d0, [-223,x]
+	adc d1, (-2000, s)
+	adc d2, (x-)
+	adc d3, (+y)
+	adc d4,  d5
+	adc d5,  16078
+	adc d6,  [73056]
+	adc d7,  (d4,x)
+
diff --git a/gas/testsuite/gas/s12z/add-imm.d b/gas/testsuite/gas/s12z/add-imm.d
new file mode 100644
index 0000000000..6125da479f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  add-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+   0:	50 12 34    	add d2, #4660
+   3:	51 12 34    	add d3, #4660
+   6:	52 12 34    	add d4, #4660
+   9:	53 12 34    	add d5, #4660
+   c:	54 12       	add d0, #18
+   e:	55 34       	add d1, #52
+  10:	56 00 56 78 	add d6, #5666970
+  14:	9a 
+  15:	57 00 98 76 	add d7, #9991764
+  19:	54 
diff --git a/gas/testsuite/gas/s12z/add-imm.s b/gas/testsuite/gas/s12z/add-imm.s
new file mode 100644
index 0000000000..5986c8e7bc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-imm.s
@@ -0,0 +1,8 @@
+start:	add d2, #0x1234
+	add d3, #0x1234
+	add d4, #0x1234
+	add d5, #0x1234
+	add d0, #0x12
+	add d1, #0x34
+	add d6, #0x56789A
+	add d7, #0x987654
diff --git a/gas/testsuite/gas/s12z/add-opr.d b/gas/testsuite/gas/s12z/add-opr.d
new file mode 100644
index 0000000000..0528312d34
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-opr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  add-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	64 c5 21    	add d0, \[-223,x\]
+   3:	65 e2 00 75 	add d1, \(30000,s\)
+   7:	30 
+   8:	60 c7       	add d2, \(x-\)
+   a:	61 f3       	add d3, \(\+y\)
+   c:	62 bf       	add d4, d7
+   e:	63 17 be    	add d5, 6078
+  11:	66 fe 01 1d 	add d6, \[73056\]
+  15:	60 
+  16:	67 8a       	add d7, \(d4,x\)
diff --git a/gas/testsuite/gas/s12z/add-opr.s b/gas/testsuite/gas/s12z/add-opr.s
new file mode 100644
index 0000000000..d86a4aa51f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-opr.s
@@ -0,0 +1,9 @@
+	add d0, [-223,x]
+	add d1, (30000, s)
+	add d2, (x-)
+	add d3, (+y)
+	add d4,  d7
+	add d5,  6078
+	add d6,  [73056]
+	add d7,  (d4,x)
+
diff --git a/gas/testsuite/gas/s12z/and-imm.d b/gas/testsuite/gas/s12z/and-imm.d
new file mode 100644
index 0000000000..fea351d534
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  and-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+   0:	58 12 34    	and d2, #4660
+   3:	59 12 34    	and d3, #4660
+   6:	5a 12 34    	and d4, #4660
+   9:	5b 12 34    	and d5, #4660
+   c:	5c 12       	and d0, #18
+   e:	5d 34       	and d1, #52
+  10:	5e 56 78 9a 	and d6, #1450744508
+  14:	bc 
+  15:	5f 98 76 54 	and d7, #-1737075662
+  19:	32 
diff --git a/gas/testsuite/gas/s12z/and-imm.s b/gas/testsuite/gas/s12z/and-imm.s
new file mode 100644
index 0000000000..fcd947a3e2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-imm.s
@@ -0,0 +1,8 @@
+start:	and d2, #0x1234
+	and d3, #0x1234
+	and d4, #0x1234
+	and d5, #0x1234
+	and d0, #0x12
+	and d1, #0x34
+	and d6, #0x56789ABC
+	and d7, #-1737075662
diff --git a/gas/testsuite/gas/s12z/and-opr.d b/gas/testsuite/gas/s12z/and-opr.d
new file mode 100644
index 0000000000..b9cc366fe5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:    
+#source:  and-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	6c c4 17    	and d0, \[23,x\]
+   3:	6d d2 ff 8a 	and d1, \(-30000,y\)
+   7:	d0 
+   8:	68 c7       	and d2, \(x-\)
+   a:	69 f3       	and d3, \(\+y\)
+   c:	6a bb       	and d4, d5
+   e:	6b fa 23 ca 	and d5, 2345678
+  12:	ce 
+  13:	6e fe 01 e2 	and d6, \[123456\]
+  17:	40 
+  18:	6f ac       	and d7, \(d0,s\)
diff --git a/gas/testsuite/gas/s12z/and-opr.s b/gas/testsuite/gas/s12z/and-opr.s
new file mode 100644
index 0000000000..6569ebede3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-opr.s
@@ -0,0 +1,9 @@
+	and d0, [23,x]
+	and d1, (-30000, y)
+	and d2, (x-)
+	and d3, (+y)
+	and d4,  d5
+	and d5,  2345678
+	and d6,  [123456]
+	and d7,  (d0,s)
+
diff --git a/gas/testsuite/gas/s12z/and-or-cc.d b/gas/testsuite/gas/s12z/and-or-cc.d
new file mode 100644
index 0000000000..38117e9229
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-or-cc.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:    
+#source:  and-or-cc.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <xx>:
+   0:	ce 7b       	andcc #123
+   2:	de 20       	orcc #32
diff --git a/gas/testsuite/gas/s12z/and-or-cc.s b/gas/testsuite/gas/s12z/and-or-cc.s
new file mode 100644
index 0000000000..afa4a1eb20
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-or-cc.s
@@ -0,0 +1,2 @@
+xx:	andcc #123
+	orcc #32
diff --git a/gas/testsuite/gas/s12z/bfext-special.d b/gas/testsuite/gas/s12z/bfext-special.d
new file mode 100644
index 0000000000..380e627543
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext-special.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:    
+#source:  bfext-special.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 0f 75 a3 	bfext.w \(45,d1\), d7, #13:3
+   4:	85 00 2d 
diff --git a/gas/testsuite/gas/s12z/bfext-special.s b/gas/testsuite/gas/s12z/bfext-special.s
new file mode 100644
index 0000000000..1810c9afa1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext-special.s
@@ -0,0 +1,2 @@
+	  bfext.w (45,d1), d7, #13:3
+
diff --git a/gas/testsuite/gas/s12z/bfext.d b/gas/testsuite/gas/s12z/bfext.d
new file mode 100644
index 0000000000..84f439a227
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext.d
@@ -0,0 +1,47 @@
+#objdump: -d
+#name:    
+#source:  bfext.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 0c 14    	bfext d0, d1, d2
+   3:	1b 0d 21 17 	bfext d1, d2, #8:23
+   7:	1b 08 41 e3 	bfext.b d2, \(\+x\), d3
+   b:	1b 09 46 c4 	bfext.w d3, \[123,x\], d4
+   f:	7b 
+  10:	1b 0a 4b ac 	bfext.p d4, \(d0,s\), d5
+  14:	1b 0b 4c 84 	bfext.l d5, \(45,d0\), d2
+  18:	00 2d 
+  1a:	1b 0e 51 84 	bfext.b \(45,d0\), d6, d3
+  1e:	00 2d 
+  20:	1b 0f 54 c4 	bfext.w \[45,x\], d7, d2
+  24:	2d 
+  25:	1b 0c 61 a2 	bfext.b d0, \(45,d1\), #13:2
+  29:	85 00 2d 
+  2c:	1b 0f 75 a3 	bfext.w \(45,d1\), d7, #13:3
+  30:	85 00 2d 
+  33:	1b 0f 58 c6 	bfext.p \[451,x\], d7, d2
+  37:	00 01 c3 
+  3a:	1b 0c 94    	bfins d0, d1, d2
+  3d:	1b 0d a1 17 	bfins d1, d2, #8:23
+  41:	1b 08 c1 e3 	bfins.b d2, \(\+x\), d3
+  45:	1b 09 c6 c4 	bfins.w d3, \[123,x\], d4
+  49:	7b 
+  4a:	1b 0a cb ac 	bfins.p d4, \(d0,s\), d5
+  4e:	1b 0b cc 84 	bfins.l d5, \(45,d0\), d2
+  52:	00 2d 
+  54:	1b 0e d1 84 	bfins.b \(45,d0\), d6, d3
+  58:	00 2d 
+  5a:	1b 0f d4 c4 	bfins.w \[45,x\], d7, d2
+  5e:	2d 
+  5f:	1b 0c e1 a2 	bfins.b d0, \(45,d1\), #13:2
+  63:	85 00 2d 
+  66:	1b 0f f5 a3 	bfins.w \(45,d1\), d7, #13:3
+  6a:	85 00 2d 
+  6d:	1b 0f d8 c6 	bfins.p \[451,x\], d7, d2
+  71:	00 01 c3 
diff --git a/gas/testsuite/gas/s12z/bfext.s b/gas/testsuite/gas/s12z/bfext.s
new file mode 100644
index 0000000000..66cb5b6668
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext.s
@@ -0,0 +1,23 @@
+	bfext   d0, d1,       d2
+	bfext   d1, d2,    #8:23
+	bfext.b d2, (+x),     d3
+	bfext.w d3, [123,x],  d4
+	bfext.p d4, (d0, s),  d5
+	bfext.l d5, (45,d0),  d2
+	bfext.b (45,d0),  d6, d3
+	bfext.w [45,x],   d7, d2
+	bfext.b d0, (45,d1), #13:2
+	bfext.w (45,d1), d7, #13:3
+	bfext.p [451,x],   d7, d2
+
+	bfins   d0, d1,       d2
+	bfins   d1, d2,    #8:23
+	bfins.b d2, (+x),     d3
+	bfins.w d3, [123,x],  d4
+	bfins.p d4, (d0, s),  d5
+	bfins.l d5, (45,d0),  d2
+	bfins.b (45,d0),  d6, d3
+	bfins.w [45,x],   d7, d2
+	bfins.b d0, (45,d1), #13:2
+	bfins.w (45,d1), d7, #13:3
+	bfins.p [451,x],   d7, d2
diff --git a/gas/testsuite/gas/s12z/bit-manip.d b/gas/testsuite/gas/s12z/bit-manip.d
new file mode 100644
index 0000000000..6a0c7ee724
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit-manip.d
@@ -0,0 +1,26 @@
+#objdump: -d
+#name:    
+#source:  bit-manip.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	ec 1c       	bclr d0, #3
+   2:	ed 25       	bset d1, #4
+   4:	ee 28       	btgl d2, #5
+   6:	ec b1 b9    	bclr d3, d5
+   9:	ed e1 ba    	bset d4, d6
+   c:	ee f1 bb    	btgl d5, d7
+   f:	ec a0 c0 22 	bclr.b \(34,x\), #2
+  13:	ec c3 ff    	bclr.w \(s\+\), #12
+  16:	ec fd e0 38 	bclr.l \(56,s\), d7
+  1a:	ed d0 c4 22 	bset.b \[34,x\], #5
+  1e:	ed db fb    	bset.l \(-s\), #29
+  21:	ed f5 c0 9c 	bset.w \(156,x\), d7
+  25:	ee d0 c4 22 	btgl.b \[34,x\], #5
+  29:	ee f3 fb    	btgl.w \(-s\), #15
+  2c:	ee fd f0 0f 	btgl.l \(15,p\), d7
diff --git a/gas/testsuite/gas/s12z/bit-manip.s b/gas/testsuite/gas/s12z/bit-manip.s
new file mode 100644
index 0000000000..cebb478624
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit-manip.s
@@ -0,0 +1,16 @@
+	bclr    d0, #3
+	bset    d1, #4
+	btgl    d2, #5
+	bclr    d3, d5
+	bset    d4, d6
+	btgl    d5, d7
+	bclr.b  (34,x), #2
+	bclr.w  (s+), #12
+	bclr.l  (56,s), d7
+	bset.b  [34,x], #5
+	bset.l  (-s), #29
+	bset.w  (156,x), d7
+	btgl.b  [34,x], #5
+	btgl.w  (-s), #15
+	btgl.l  (15,p), d7
+
diff --git a/gas/testsuite/gas/s12z/bit.d b/gas/testsuite/gas/s12z/bit.d
new file mode 100644
index 0000000000..68dd30ca3d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name:    
+#source:  bit.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 58 fc 84 	bit d2, #-892
+   4:	1b 59 ef 32 	bit d3, #-4302
+   8:	1b 5f 00 01 	bit d7, #123456
+   c:	e2 40 
+   e:	1b 5b 04 d2 	bit d5, #1234
+  12:	1b 5c 7b    	bit d0, #123
+  15:	1b 5d 22    	bit d1, #34
+  18:	1b 5e ff ff 	bit d6, #-56789
+  1c:	22 2b 
+  1e:	1b 5a 22 3d 	bit d4, #8765
+  22:	1b 6c d5 21 	bit d0, \[-223,y\]
+  26:	1b 6d f2 00 	bit d1, \(34000,p\)
+  2a:	84 d0 
+  2c:	1b 68 fb    	bit d2, \(-s\)
+  2f:	1b 59 00 04 	bit d3, #4
+  33:	1b 6a bc    	bit d4, d0
+  36:	1b 6b f9 4c 	bit d5, 85178
+  3a:	ba 
+  3b:	1b 6e fe 00 	bit d6, \[15256\]
+  3f:	3b 98 
+  41:	1b 6f 8b    	bit d7, \(d5,x\)
+  44:	1b 69 f3    	bit d3, \(\+y\)
diff --git a/gas/testsuite/gas/s12z/bit.s b/gas/testsuite/gas/s12z/bit.s
new file mode 100644
index 0000000000..539b593f9f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit.s
@@ -0,0 +1,17 @@
+	bit d2, #-892
+	bit d3, #-4302
+	bit d7, #123456
+	bit d5, #1234
+	bit d0, #123
+	bit d1, #34
+	bit d6, #-56789
+	bit d4, #8765
+	bit d0, [-223,y]
+	bit d1, (34000, p)
+	bit d2, (-s)
+	bit d3, #4
+	bit d4, d0
+	bit d5, 85178
+	bit d6, [15256]
+	bit d7, (d5, x)
+	bit d3, (+y)
diff --git a/gas/testsuite/gas/s12z/bra-expression-defined.d b/gas/testsuite/gas/s12z/bra-expression-defined.d
new file mode 100644
index 0000000000..700f7cdd16
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-defined.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    pc_relative expressions defined at assembly time
+#source:  bra-expression-defined.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <loop-0x11>:
+   0:	01          	nop
+   1:	01          	nop
+   2:	20 80 19    	bra \*\+25
+   5:	01          	nop
+   6:	02 c0 bc 80 	brclr.b d0, #4, \*\+31
+   a:	1f 
+   b:	01          	nop
+   c:	0b 06 80 23 	tbne d6, \*\+35
+  10:	01          	nop
+
+00000011 <loop>:
+  11:	01          	nop
diff --git a/gas/testsuite/gas/s12z/bra-expression-defined.s b/gas/testsuite/gas/s12z/bra-expression-defined.s
new file mode 100644
index 0000000000..2a1baeb4d5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-defined.s
@@ -0,0 +1,11 @@
+
+	nop
+	nop
+	bra loop+10
+	nop
+	brclr.b d0, #4, loop+20
+	nop
+	tbne d6,  loop+30
+	nop
+loop:
+	nop
diff --git a/gas/testsuite/gas/s12z/bra-expression-undef.d b/gas/testsuite/gas/s12z/bra-expression-undef.d
new file mode 100644
index 0000000000..ddd7dcb9ee
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-undef.d
@@ -0,0 +1,24 @@
+#objdump: -dr
+#name:    pc_relative expressions without a definition
+#source:  bra-expression-undef.s
+
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	01          	nop
+   1:	01          	nop
+   2:	20 80 0b    	bra \*\+11
+			3: R_S12Z_PCREL_7_15	loop\+0x8000
+   5:	01          	nop
+   6:	02 c0 bc 80 	brclr.b d0, #4, \*\+23
+   a:	17 
+			9: R_S12Z_PCREL_7_15	loop\+0x18000
+   b:	01          	nop
+   c:	0b 06 80 20 	tbne d6, \*\+32
+			e: R_S12Z_PCREL_7_15	loop\+0x10000
+  10:	01          	nop
diff --git a/gas/testsuite/gas/s12z/bra-expression-undef.s b/gas/testsuite/gas/s12z/bra-expression-undef.s
new file mode 100644
index 0000000000..1d5a81ea06
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-undef.s
@@ -0,0 +1,9 @@
+
+	nop
+	nop
+	bra loop+10
+	nop
+	brclr.b d0, #4, loop+20
+	nop
+	tbne d6,  loop+30
+	nop
diff --git a/gas/testsuite/gas/s12z/bra.d b/gas/testsuite/gas/s12z/bra.d
new file mode 100644
index 0000000000..7a6cc1cb19
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra.d
@@ -0,0 +1,34 @@
+#objdump: -d
+#name:    
+#source:  bra.s
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	20 80 0f    	bra L4
+
+00000003 <L2>:
+   3:	21 ff fd    	bsr L1
+   6:	22 ff fa    	bhi L1
+
+00000009 <L3>:
+   9:	23 80 00    	bls L3
+   c:	24 ff f4    	bcc L1
+
+0000000f <L4>:
+   f:	25 ff f4    	bcs L2
+  12:	26 ff f7    	bne L3
+  15:	27 ff fa    	beq L4
+  18:	28 ff f7    	bvc L4
+  1b:	29 ff e8    	bvs L2
+  1e:	2a ff e2    	bpl L1
+  21:	2b ff e2    	bmi L2
+  24:	2c ff dc    	bge L1
+  27:	2d ff e8    	blt L4
+  2a:	2e ff df    	bgt L3
+  2d:	2f ff d3    	ble L1
+  30:	20 02       	bra \*\+2
+  32:	20 7c       	bra \*-4
diff --git a/gas/testsuite/gas/s12z/bra.s b/gas/testsuite/gas/s12z/bra.s
new file mode 100644
index 0000000000..a2528b39df
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra.s
@@ -0,0 +1,20 @@
+L1:	bra L4
+L2:	bsr L1
+	bhi L1
+L3:	bls L3
+	bcc L1
+L4:	bcs L2
+	bne L3
+	beq L4
+	bvc L4
+	bvs L2
+	bpl L1
+	bmi L2
+	bge L1
+	blt L4
+	bgt L3
+	ble L1
+
+	bra *+2
+	bra *-4
+	
diff --git a/gas/testsuite/gas/s12z/brclr-symbols.d b/gas/testsuite/gas/s12z/brclr-symbols.d
new file mode 100644
index 0000000000..59de1c0e57
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brclr-symbols.d
@@ -0,0 +1,32 @@
+#objdump: -dt
+#name:    
+#source:  brclr-symbols.s
+
+
+dump.o:     file format elf32-s12z
+
+SYMBOL TABLE:
+00000000 l    d  .text	00000000 .text
+00000000 l    d  .data	00000000 .data
+00000000 l    d  .bss	00000000 .bss
+00000001 l       .text	00000000 foo
+
+
+
+Disassembly of section .text:
+
+00000000 <foo-0x1>:
+   0:	01          	nop
+
+00000001 <foo>:
+   1:	01          	nop
+   2:	01          	nop
+   3:	02 0c ff fe 	brclr d0, #1, foo
+   7:	03 81 bd ff 	brset d1, d2, foo
+   b:	fa 
+   c:	02 a0 e7 ff 	brclr.b \(x\+\), #2, foo
+  10:	f5 
+  11:	03 c1 84 00 	brset.b \(23,d0\), d0, foo
+  15:	17 ff f0 
+  18:	02 a0 03 86 	brclr.b 902, #2, foo
+  1c:	ff e9 
\ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/brclr-symbols.s b/gas/testsuite/gas/s12z/brclr-symbols.s
new file mode 100644
index 0000000000..fa212fe2f7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brclr-symbols.s
@@ -0,0 +1,9 @@
+        nop
+foo:
+	nop
+	nop
+        brclr  d0, #1, foo
+        brset  d1, d2, foo
+        brclr.b (x+), #2, foo
+        brset.b (23,d0), d0, foo
+	brclr.b  902, #2, foo
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d
new file mode 100644
index 0000000000..588e606580
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  brset-clr-opr-imm-rel.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	03 c0 e4 2d 	brset.b \[45,s\], #4, \*\+3
+   4:	03 
+   5:	03 e3 e6 00 	brset.w \[345,s\], #14, \*\+32
+   9:	01 59 20 
+   c:	03 99 e2 00 	brset.l \(345,s\), #9, \*\+309
+  10:	01 59 81 35 
+  14:	02 c0 e6 00 	brclr.b \[345,s\], #4, \*\+3
+  18:	01 59 03 
+  1b:	02 f3 e6 00 	brclr.w \[345,s\], #15, \*\+3087
+  1f:	01 59 8c 0f 
+  23:	02 fb e6 00 	brclr.l \[345,s\], #31, \*\+3
+  27:	01 59 03 
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s
new file mode 100644
index 0000000000..1bb8da9854
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s
@@ -0,0 +1,7 @@
+	brset.b [45,s], #4, *+3
+	brset.w [345,s], #14, *+32
+	brset.l (345,s), #9, *+309
+	brclr.b [345,s], #4, *+3
+	brclr.w [345,s], #15, *+3087
+	brclr.l [345,s], #31, *+3
+
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d
new file mode 100644
index 0000000000..1a87e786a7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  brset-clr-opr-reg-rel.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1-0x6>:
+   0:	02 85 d0 22 	brclr.w \(34,y\), d2, \*\+3034
+   4:	8b da 
+
+00000006 <L1>:
+   6:	03 c1 d3 81 	brset.b \(-y\), d0, \*\+434
+   a:	b2 
+   b:	03 9d e3 88 	brset.l \(\+x\), d3, \*\+2134
+   f:	56 
+  10:	02 ad c4 22 	brclr.l \[34,x\], d4, L1
+  14:	ff f6 
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s
new file mode 100644
index 0000000000..76c3bb51b3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s
@@ -0,0 +1,5 @@
+	brclr.w (34,y), d2, *+3034
+L1:	brset.b (-y),   d0, *+434
+	brset.l (+x),   d3, *+2134
+	brclr.l [34,x], d4, L1
+
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d
new file mode 100644
index 0000000000..ddcc61dc98
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d
@@ -0,0 +1,24 @@
+#objdump: -d
+#name:    
+#source:  brset-clr-reg-imm-rel.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	03 10 05    	brset d2, #2, \*\+5
+   3:	03 19 17    	brset d3, #3, \*\+23
+   6:	03 11 71    	brset d3, #2, \*-15
+   9:	03 40 43    	brset d2, #8, \*-61
+   c:	03 40 fd 01 	brset d2, #8, \*-767
+  10:	03 6e fd 01 	brset d6, #13, \*-767
+
+00000014 <L2>:
+  14:	02 10 05    	brclr d2, #2, \*\+5
+  17:	02 19 17    	brclr d3, #3, \*\+23
+  1a:	02 11 fc c0 	brclr d3, #2, \*-832
+  1e:	02 40 43    	brclr d2, #8, \*-61
+  21:	02 40 fd 01 	brclr d2, #8, \*-767
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s
new file mode 100644
index 0000000000..3aca6219ec
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s
@@ -0,0 +1,12 @@
+L1:	brset   d2, #2, *+5
+	brset   d3, #3, *+23
+	brset   d3, #2, *-15
+	brset   d2, #8, *-61
+	brset   d2, #8, *-767
+	brset   d6, #13, *-767
+L2:	brclr   d2, #2, *+5
+	brclr   d3, #3, *+23
+	brclr   d3, #2, *-832
+	brclr   d2, #8, *-61
+	brclr   d2, #8, *-767
+
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d
new file mode 100644
index 0000000000..1cad90684e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  brset-clr-reg-reg-rel.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	03 e1 bb 2d 	brset d5, d6, \*\+45
+   4:	02 d1 b8 6f 	brclr d2, d1, \*-17
+   8:	03 91 be ff 	brset d6, d3, \*-90
+   c:	a6 
+   d:	02 f1 bc ff 	brclr d0, d7, \*-90
+  11:	a6 
+  12:	02 81 bd ff 	brclr d1, d2, \*-190
+  16:	42 
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s
new file mode 100644
index 0000000000..c78ec97902
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s
@@ -0,0 +1,6 @@
+	brset   d5, d6, *+45
+	brclr   d2, d1, *-17
+	brset   d6, d3, *-90
+	brclr   d0, d7, *-90
+	brclr   d1, d2, *-190
+
diff --git a/gas/testsuite/gas/s12z/clb.d b/gas/testsuite/gas/s12z/clb.d
new file mode 100644
index 0000000000..fd142dc2b1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clb.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  clb.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 91 47    	clb d0, d7
+   3:	1b 91 56    	clb d1, d6
+   6:	1b 91 03    	clb d2, d5
+   9:	1b 91 12    	clb d3, d4
+   c:	1b 91 21    	clb d4, d3
+   f:	1b 91 30    	clb d5, d2
+  12:	1b 91 65    	clb d6, d1
+  15:	1b 91 74    	clb d7, d0
diff --git a/gas/testsuite/gas/s12z/clb.s b/gas/testsuite/gas/s12z/clb.s
new file mode 100644
index 0000000000..877bbce116
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clb.s
@@ -0,0 +1,8 @@
+	clb d0, d7
+	clb d1, d6
+	clb d2, d5
+	clb d3, d4
+	clb d4, d3
+	clb d5, d2
+	clb d6, d1
+	clb d7, d0
diff --git a/gas/testsuite/gas/s12z/clr-opr.d b/gas/testsuite/gas/s12z/clr-opr.d
new file mode 100644
index 0000000000..7c05ebb998
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  clr-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	bc ff       	clr.b \(s\+\)
+   2:	bd c0 2d    	clr.w \(45,x\)
+   5:	be f9 e2 32 	clr.p 123442
+   9:	bf d4 03    	clr.l \[3,y\]
diff --git a/gas/testsuite/gas/s12z/clr-opr.s b/gas/testsuite/gas/s12z/clr-opr.s
new file mode 100644
index 0000000000..ecfa266797
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr-opr.s
@@ -0,0 +1,5 @@
+	clr.b (s+)
+	clr.w (45,x)
+	clr.p 123442
+	clr.l [3,y]
+
diff --git a/gas/testsuite/gas/s12z/clr.d b/gas/testsuite/gas/s12z/clr.d
new file mode 100644
index 0000000000..1e902d6678
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  clr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	38          	clr d2
+   1:	39          	clr d3
+   2:	3a          	clr d4
+   3:	3b          	clr d5
+   4:	3c          	clr d0
+   5:	3d          	clr d1
+   6:	3e          	clr d6
+   7:	3f          	clr d7
+   8:	9a          	clr x
+   9:	9b          	clr y
diff --git a/gas/testsuite/gas/s12z/clr.s b/gas/testsuite/gas/s12z/clr.s
new file mode 100644
index 0000000000..1f0b57fae8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr.s
@@ -0,0 +1,10 @@
+L1:	clr d2
+	clr d3
+	clr d4
+	clr d5
+	clr d0
+	clr d1
+	clr d6
+	clr d7
+	clr x
+	clr y
diff --git a/gas/testsuite/gas/s12z/cmp-imm.d b/gas/testsuite/gas/s12z/cmp-imm.d
new file mode 100644
index 0000000000..d756b00db9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-imm.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  cmp-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <here>:
+   0:	e4 12       	cmp d0, #18
+   2:	e5 34       	cmp d1, #52
+   4:	e0 34 56    	cmp d2, #13398
+   7:	e1 34 56    	cmp d3, #13398
+   a:	e2 34 56    	cmp d4, #13398
+   d:	e3 34 56    	cmp d5, #13398
+  10:	e6 00 34 56 	cmp d6, #3430008
+  14:	78 
+  15:	e7 00 34 56 	cmp d7, #3430008
+  19:	78 
+  1a:	e8 aa bb cc 	cmp x, #-5588020
+  1e:	e9 dd ee ff 	cmp y, #-2232577
diff --git a/gas/testsuite/gas/s12z/cmp-imm.s b/gas/testsuite/gas/s12z/cmp-imm.s
new file mode 100644
index 0000000000..89b41b585d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-imm.s
@@ -0,0 +1,12 @@
+here:	cmp d0, #0x12
+	cmp d1, #0x34
+	cmp d2, #0x3456
+	cmp d3, #0x3456
+	cmp d4, #0x3456
+	cmp d5, #0x3456
+	cmp d6, #0x345678
+	cmp d7, #0x345678
+
+	cmp x, #-5588020
+	cmp y, #-2232577
+
diff --git a/gas/testsuite/gas/s12z/cmp-opr-inc.d b/gas/testsuite/gas/s12z/cmp-opr-inc.d
new file mode 100644
index 0000000000..bda08de399
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-inc.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  cmp-opr-inc.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	f0 e3       	cmp d2, \(\+x\)
+   2:	f1 f3       	cmp d3, \(\+y\)
+   4:	f2 c3       	cmp d4, \(-x\)
+   6:	f3 d3       	cmp d5, \(-y\)
+   8:	f4 fb       	cmp d0, \(-s\)
+   a:	f6 ff       	cmp d6, \(s\+\)
+   c:	f8 d7       	cmp x, \(y-\)
+   e:	f8 c7       	cmp x, \(x-\)
+  10:	f9 f7       	cmp y, \(y\+\)
+  12:	f9 e7       	cmp y, \(x\+\)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-inc.s b/gas/testsuite/gas/s12z/cmp-opr-inc.s
new file mode 100644
index 0000000000..48b1d48f09
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-inc.s
@@ -0,0 +1,11 @@
+;; Pre/Post increment/decrement xys
+	cmp d2, (+x)
+	cmp d3, (+y)
+	cmp d4, (-x)
+	cmp d5, (-y)
+	cmp d0, (-s)
+	cmp d6, (s+)
+	cmp x,  (y-)
+	cmp x,  (x-)
+	cmp y,  (y+)
+	cmp y,  (x+)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rdirect.d b/gas/testsuite/gas/s12z/cmp-opr-rdirect.d
new file mode 100644
index 0000000000..879ed98c84
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rdirect.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  cmp-opr-rdirect.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	f0 ad       	cmp d2, \(d1,s\)
+   2:	f1 88       	cmp d3, \(d2,x\)
+   4:	f2 89       	cmp d4, \(d3,x\)
+   6:	f3 99       	cmp d5, \(d3,y\)
+   8:	f4 8a       	cmp d0, \(d4,x\)
+   a:	f5 8b       	cmp d1, \(d5,x\)
+   c:	f6 8e       	cmp d6, \(d6,x\)
+   e:	f7 8f       	cmp d7, \(d7,x\)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rdirect.s b/gas/testsuite/gas/s12z/cmp-opr-rdirect.s
new file mode 100644
index 0000000000..ff5dcbcbe2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rdirect.s
@@ -0,0 +1,9 @@
+;;; Direct register offset
+	cmp d2, (d1,s)
+	cmp d3, (d2,x)
+	cmp d4, (d3,x)
+	cmp d5, (d3,y)
+	cmp d0, (d4,x)
+	cmp d1, (d5,x)
+	cmp d6, (d6,x)
+	cmp d7, (d7,x)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-reg.d b/gas/testsuite/gas/s12z/cmp-opr-reg.d
new file mode 100644
index 0000000000..cff87d31bb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-reg.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  cmp-opr-reg.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	f0 b8       	cmp d2, d2
+   2:	f1 b9       	cmp d3, d3
+   4:	f2 ba       	cmp d4, d4
+   6:	f3 bb       	cmp d5, d5
+   8:	f4 bc       	cmp d0, d0
+   a:	f5 bd       	cmp d1, d1
+   c:	f6 be       	cmp d6, d6
+   e:	f7 bf       	cmp d7, d7
diff --git a/gas/testsuite/gas/s12z/cmp-opr-reg.s b/gas/testsuite/gas/s12z/cmp-opr-reg.s
new file mode 100644
index 0000000000..75bb440b20
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-reg.s
@@ -0,0 +1,9 @@
+;; Register as operand
+	cmp d2, d2
+	cmp d3, d3
+	cmp d4, d4
+	cmp d5, d5
+	cmp d0, d0
+	cmp d1, d1
+	cmp d6, d6
+	cmp d7, d7
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rindirect.d b/gas/testsuite/gas/s12z/cmp-opr-rindirect.d
new file mode 100644
index 0000000000..7c1108fa70
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rindirect.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  cmp-opr-rindirect.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	f0 dd       	cmp d2, \[d1,y\]
+   2:	f1 dd       	cmp d3, \[d1,y\]
+   4:	f2 dc       	cmp d4, \[d0,y\]
+   6:	f3 dc       	cmp d5, \[d0,y\]
+   8:	f4 ce       	cmp d0, \[d6,x\]
+   a:	f5 ce       	cmp d1, \[d6,x\]
+   c:	f6 ce       	cmp d6, \[d6,x\]
+   e:	f7 cf       	cmp d7, \[d7,x\]
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rindirect.s b/gas/testsuite/gas/s12z/cmp-opr-rindirect.s
new file mode 100644
index 0000000000..27ac5fbaaf
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rindirect.s
@@ -0,0 +1,9 @@
+;;; Indirect register offset
+	cmp d2, [d1,y]
+	cmp d3, [d1,y]
+	cmp d4, [d0,y]
+	cmp d5, [d0,y]
+	cmp d0, [d6,x]
+	cmp d1, [d6,x]
+	cmp d6, [d6,x]
+	cmp d7, [d7,x]
diff --git a/gas/testsuite/gas/s12z/cmp-opr-sxe4.d b/gas/testsuite/gas/s12z/cmp-opr-sxe4.d
new file mode 100644
index 0000000000..5eac2fdcd9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-sxe4.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  cmp-opr-sxe4.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	e0 ff ff    	cmp d2, #-1
+   3:	e1 00 01    	cmp d3, #1
+   6:	e2 00 02    	cmp d4, #2
+   9:	e3 00 03    	cmp d5, #3
+   c:	e4 0e       	cmp d0, #14
+   e:	e5 0f       	cmp d1, #15
+  10:	e6 00 00 00 	cmp d6, #4
+  14:	04 
+  15:	e7 00 00 00 	cmp d7, #10
+  19:	0a 
diff --git a/gas/testsuite/gas/s12z/cmp-opr-sxe4.s b/gas/testsuite/gas/s12z/cmp-opr-sxe4.s
new file mode 100644
index 0000000000..7b3d113efb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-sxe4.s
@@ -0,0 +1,10 @@
+;; Short immediate forms
+	cmp d2, #-1
+	cmp d3, #1
+	cmp d4, #2
+	cmp d5, #3
+	cmp d0, #14
+	cmp d1, #15
+	cmp d6, #4
+	cmp d7, #10
+
diff --git a/gas/testsuite/gas/s12z/cmp-opr-xys.d b/gas/testsuite/gas/s12z/cmp-opr-xys.d
new file mode 100644
index 0000000000..87d065fb1b
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-xys.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  cmp-opr-xys.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	f0 61       	cmp d2, \(1,s\)
+   2:	f1 42       	cmp d3, \(2,x\)
+   4:	f2 43       	cmp d4, \(3,x\)
+   6:	f3 53       	cmp d5, \(3,y\)
+   8:	f4 44       	cmp d0, \(4,x\)
+   a:	f5 45       	cmp d1, \(5,x\)
+   c:	f6 46       	cmp d6, \(6,x\)
+   e:	f7 47       	cmp d7, \(7,x\)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-xys.s b/gas/testsuite/gas/s12z/cmp-opr-xys.s
new file mode 100644
index 0000000000..929bb081cf
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-xys.s
@@ -0,0 +1,9 @@
+;; Constant offset from xys
+	cmp d2, (1,s)
+	cmp d3, (2,x)
+	cmp d4, (3,x)
+	cmp d5, (3,y)
+	cmp d0, (4,x)
+	cmp d1, (5,x)
+	cmp d6, (6,x)
+	cmp d7, (7,x)
diff --git a/gas/testsuite/gas/s12z/cmp-s-imm.d b/gas/testsuite/gas/s12z/cmp-s-imm.d
new file mode 100644
index 0000000000..d4e7efb271
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-imm.d
@@ -0,0 +1,27 @@
+#objdump: -d
+#name:    
+#source:  cmp-s-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 04 00 00 	cmp s, #0
+   4:	00 
+   5:	1b 02 71    	cmp s, #1
+   8:	1b 02 70    	cmp s, #-1
+   b:	1b 04 00 00 	cmp s, #255
+   f:	ff 
+  10:	1b 04 ff ff 	cmp s, #-256
+  14:	00 
+  15:	1b 04 00 7f 	cmp s, #32767
+  19:	ff 
+  1a:	1b 04 ff 80 	cmp s, #-32768
+  1e:	00 
+  1f:	1b 04 07 ff 	cmp s, #524287
+  23:	ff 
+  24:	1b 04 f8 00 	cmp s, #-524288
+  28:	00 
diff --git a/gas/testsuite/gas/s12z/cmp-s-imm.s b/gas/testsuite/gas/s12z/cmp-s-imm.s
new file mode 100644
index 0000000000..e873d82cf6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-imm.s
@@ -0,0 +1,10 @@
+	cmp s, #0
+	cmp s, #1
+	cmp s, #-1
+	cmp s, #255
+	cmp s, #-256
+	cmp s, #32767
+	cmp s, #-32768
+	cmp s, #524287
+	cmp s, #-524288
+
diff --git a/gas/testsuite/gas/s12z/cmp-s-opr.d b/gas/testsuite/gas/s12z/cmp-s-opr.d
new file mode 100644
index 0000000000..77d2ac7bd6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-opr.d
@@ -0,0 +1,25 @@
+#objdump: -d
+#name:    
+#source:  cmp-s-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 02 e0 43 	cmp s, \(67,s\)
+   4:	1b 02 e3    	cmp s, \(\+x\)
+   7:	1b 02 8c    	cmp s, \(d0,x\)
+   a:	1b 02 dd    	cmp s, \[d1,y\]
+   d:	1b 02 f2 00 	cmp s, \(2134,p\)
+  11:	08 56 
+  13:	1b 02 f6 00 	cmp s, \[2134,p\]
+  17:	08 56 
+  19:	1b 02 fa 0f 	cmp s, 987654
+  1d:	12 06 
+  1f:	1b 02 e6 08 	cmp s, \[565543,s\]
+  23:	a1 27 
+  25:	1b 02 80 04 	cmp s, \(1233,d2\)
+  29:	d1 
diff --git a/gas/testsuite/gas/s12z/cmp-s-opr.s b/gas/testsuite/gas/s12z/cmp-s-opr.s
new file mode 100644
index 0000000000..5deb45aa6e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-opr.s
@@ -0,0 +1,10 @@
+	cmp s, (67,s)
+	cmp s, (+x)
+	cmp s, (d0,x)
+	cmp s, [d1,y]
+	cmp s, (2134,p)
+	cmp s, [2134,p]
+	cmp s, 987654
+	cmp s, [565543,s]
+	cmp s, (1233, d2)
+
diff --git a/gas/testsuite/gas/s12z/cmp-xy.d b/gas/testsuite/gas/s12z/cmp-xy.d
new file mode 100644
index 0000000000..9fef4e13cb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-xy.d
@@ -0,0 +1,12 @@
+#objdump: -d
+#name:    
+#source:  cmp-xy.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	fc          	cmp x, y
diff --git a/gas/testsuite/gas/s12z/cmp-xy.s b/gas/testsuite/gas/s12z/cmp-xy.s
new file mode 100644
index 0000000000..dcfd47c9db
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-xy.s
@@ -0,0 +1 @@
+	cmp x, y
diff --git a/gas/testsuite/gas/s12z/com-opr.d b/gas/testsuite/gas/s12z/com-opr.d
new file mode 100644
index 0000000000..ce51785f1e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/com-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  com-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	cc df       	com.b \[d7,y\]
+   2:	cd fe 00 1f 	com.w \[8134\]
+   6:	c6 
+   7:	cf ae       	com.l \(d6,s\)
diff --git a/gas/testsuite/gas/s12z/com-opr.s b/gas/testsuite/gas/s12z/com-opr.s
new file mode 100644
index 0000000000..5eb2760ff6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/com-opr.s
@@ -0,0 +1,3 @@
+	com.b  [d7, y]
+	com.w  [8134]
+	com.l  (d6, s)
diff --git a/gas/testsuite/gas/s12z/complex-shifts.d b/gas/testsuite/gas/s12z/complex-shifts.d
new file mode 100644
index 0000000000..e17fe90a33
--- /dev/null
+++ b/gas/testsuite/gas/s12z/complex-shifts.d
@@ -0,0 +1,18 @@
+#objdump: -d
+#name:    
+#source:  complex-shifts.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	14 73 e3 e6 	lsl.l d0, \(\+x\), \[345,s\]
+   4:	00 01 59 
+   7:	13 32 8e fb 	lsr.p d5, \(d6,x\), \(-s\)
+   b:	17 f1 f4 2d 	asl.w d7, \[45,p\], \(278,y\)
+   f:	d2 00 01 16 
+  13:	12 b0 84 00 	asr.b d4, \(145,d0\), \(d0,s\)
+  17:	91 ac 
diff --git a/gas/testsuite/gas/s12z/complex-shifts.s b/gas/testsuite/gas/s12z/complex-shifts.s
new file mode 100644
index 0000000000..118296ed69
--- /dev/null
+++ b/gas/testsuite/gas/s12z/complex-shifts.s
@@ -0,0 +1,4 @@
+	lsl.l d0, (+x), [345, s]
+	lsr.p d5, (d6,x), (-s)
+	asl.w d7, [45,p], (278, y)
+	asr.b d4, (145,d0), (d0,s)
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-opr.d b/gas/testsuite/gas/s12z/db-tb-cc-opr.d
new file mode 100644
index 0000000000..ee556e25d0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-opr.d
@@ -0,0 +1,30 @@
+#objdump: -d
+#name:    
+#source:  db-tb-cc-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	0b dc 82 00 	dble.b \(3,d4\), \*\+1
+   4:	03 01 
+   6:	0b cd 83 00 	dbgt.w \(23,d5\), \*\+18
+   a:	17 12 
+   c:	0b de 84 00 	dble.p \(2,d0\), \*-19
+  10:	02 6d 
+  12:	0b bf fb ff 	dbmi.l \(-s\), \*-137
+  16:	77 
+  17:	0b 3c e4 22 	tbmi.b \[34,s\], \*\+43
+  1b:	2b 
+  1c:	0b 4d ff 5f 	tbgt.w \(s\+\), \*-33
+  20:	0b 1e c4 ea 	tbeq.p \[234,x\], \*-134
+  24:	ff 7a 
+  26:	0b 5f f0 22 	tble.l \(34,p\), \*\+331
+  2a:	81 4b 
+  2c:	0b 0c 5e 81 	tbne.b \(14,y\), \*\+431
+  30:	af 
+  31:	0b 2e 4e 80 	tbpl.p \(14,x\), \*\+231
+  35:	e7 
\ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-opr.s b/gas/testsuite/gas/s12z/db-tb-cc-opr.s
new file mode 100644
index 0000000000..a79cbdee9b
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-opr.s
@@ -0,0 +1,11 @@
+	dble.b (3,d4), *+1
+	dbgt.w (23,d5), *+18
+	dble.p (2,d0),  *-19
+	dbmi.l (-s),    *-137
+	tbmi.b [34,s],  *+43
+	tbgt.w (s+),    *-33
+	tbeq.p [234,x], *-134
+	tble.l (34, p), *+331
+	tbne.b (14, y), *+431
+	tbpl.p (14, x), *+231
+
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-reg.d b/gas/testsuite/gas/s12z/db-tb-cc-reg.d
new file mode 100644
index 0000000000..54ea832a2d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-reg.d
@@ -0,0 +1,31 @@
+#objdump: -d
+#name:    
+#source:  db-tb-cc-reg.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	0b 84 0c    	dbne d0, \*\+12
+   3:	0b 95 0d    	dbeq d1, \*\+13
+   6:	0b a8 72    	dbpl x, \*-14
+   9:	0b b9 0f    	dbmi y, \*\+15
+   c:	0b c1 80 7b 	dbgt d3, \*\+123
+  10:	0b d7 fb 1f 	dble d7, \*-1249
+  14:	0b 04 16    	tbne d0, \*\+22
+  17:	0b 15 17    	tbeq d1, \*\+23
+  1a:	0b 28 18    	tbpl x, \*\+24
+  1d:	0b 39 19    	tbmi y, \*\+25
+  20:	0b 41 80 df 	tbgt d3, \*\+223
+  24:	0b 57 88 c9 	tble d7, \*\+2249
+  28:	0b 39 28    	tbmi y, \*\+40
+  2b:	0b 84 ff 75 	dbne d0, \*-139
+  2f:	0b a5 04    	dbpl d1, \*\+4
+  32:	0b c2 ff 76 	dbgt d4, \*-138
+  36:	0b 90 29    	dbeq d2, \*\+41
+  39:	0b 06 04    	tbne d6, \*\+4
+  3c:	0b 27 ff 78 	tbpl d7, \*-136
+  40:	0b 18 28    	tbeq x, \*\+40
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-reg.s b/gas/testsuite/gas/s12z/db-tb-cc-reg.s
new file mode 100644
index 0000000000..524f4d00f7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-reg.s
@@ -0,0 +1,21 @@
+        dbne   d0,   *+12
+        dbeq   d1,   *+13
+        dbpl   x,    *-14
+        dbmi   y,    *+15
+        dbgt   d3,   *+123
+        dble   d7,   *-1249
+        tbne   d0,   *+22
+        tbeq   d1,   *+23
+        tbpl   x,    *+24
+        tbmi   y,    *+25
+        tbgt   d3,   *+223
+        tble   d7,   *+2249
+	tbmi   y,    *+40
+	dbne   d0,   *-139
+	dbpl   d1,   *+4
+	dbgt   d4,   *-138
+	dbeq   d2,   *+41
+	tbne   d6,   *+4
+	tbpl   d7,   *-136
+	tbeq   x,    *+40
+
diff --git a/gas/testsuite/gas/s12z/dbCC.d b/gas/testsuite/gas/s12z/dbCC.d
new file mode 100644
index 0000000000..87dd7fcaba
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dbCC.d
@@ -0,0 +1,27 @@
+#objdump: -dt
+#name:    
+#source:  dbCC.s
+
+
+dump.o:     file format elf32-s12z
+
+SYMBOL TABLE:
+00000000 l    d  .text	00000000 .text
+00000000 l    d  .data	00000000 .data
+00000000 l    d  .bss	00000000 .bss
+00000001 l       .text	00000000 foo
+
+
+
+Disassembly of section .text:
+
+00000000 <foo-0x1>:
+   0:	01          	nop
+
+00000001 <foo>:
+   1:	01          	nop
+   2:	0b 84 ff ff 	dbne d0, foo
+   6:	0b 88 ff fb 	dbne x, foo
+   a:	0b 89 ff f7 	dbne y, foo
+   e:	0b 8c f3 ff 	dbne.b \(\+y\), foo
+  12:	f3 
diff --git a/gas/testsuite/gas/s12z/dbCC.s b/gas/testsuite/gas/s12z/dbCC.s
new file mode 100644
index 0000000000..3a637e7b85
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dbCC.s
@@ -0,0 +1,7 @@
+        nop
+foo:
+	nop
+        dbne  d0,    foo
+        dbne  x,     foo
+        dbne  y,     foo
+        dbne.b (+y), foo
diff --git a/gas/testsuite/gas/s12z/dec-opr.d b/gas/testsuite/gas/s12z/dec-opr.d
new file mode 100644
index 0000000000..4f490883c1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  dec-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	ac ca       	dec.b \[d4,x\]
+   2:	ad fe 00 00 	dec.w \[134\]
+   6:	86 
+   7:	af ad       	dec.l \(d1,s\)
diff --git a/gas/testsuite/gas/s12z/dec-opr.s b/gas/testsuite/gas/s12z/dec-opr.s
new file mode 100644
index 0000000000..2f54a4c452
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec-opr.s
@@ -0,0 +1,3 @@
+	dec.b  [d4, x]
+	dec.w  [134]
+	dec.l  (d1, s)
diff --git a/gas/testsuite/gas/s12z/dec.d b/gas/testsuite/gas/s12z/dec.d
new file mode 100644
index 0000000000..74a2c3e603
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  dec.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	40          	dec d2
+   1:	41          	dec d3
+   2:	42          	dec d4
+   3:	43          	dec d5
+   4:	44          	dec d0
+   5:	45          	dec d1
+   6:	46          	dec d6
+   7:	47          	dec d7
diff --git a/gas/testsuite/gas/s12z/dec.s b/gas/testsuite/gas/s12z/dec.s
new file mode 100644
index 0000000000..1280bf4753
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec.s
@@ -0,0 +1,8 @@
+L1:	dec d2
+	dec d3
+	dec d4
+	dec d5
+	dec d0
+	dec d1
+	dec d6
+	dec d7
diff --git a/gas/testsuite/gas/s12z/div.d b/gas/testsuite/gas/s12z/div.d
new file mode 100644
index 0000000000..3569519e5a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/div.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  div.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 34 ec 62 	divs.b d0, d1, #98
+   4:	1b 35 c0 b9 	divs.b d1, d2, d3
+   8:	1b 30 c9 ba 	divs.w d2, d3, d4
+   c:	1b 31 ff 00 	divs.l d3, d7, #9842
+  10:	00 26 72 
+  13:	1b 32 68 e0 	divu.b d4, d1, \(32,s\)
+  17:	20 
+  18:	1b 33 49 c4 	divu.w d5, d3, \[34,x\]
+  1c:	22 
+  1d:	1b 36 7b ff 	divu.l d6, d7, \(s\+\)
+  21:	1b 37 7a d4 	divu.lp d7, \[12,y\], \(7,d1\)
+  25:	0c 85 00 07 
diff --git a/gas/testsuite/gas/s12z/div.s b/gas/testsuite/gas/s12z/div.s
new file mode 100644
index 0000000000..edd79903cd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/div.s
@@ -0,0 +1,8 @@
+	divs.b  d0, d1, #98
+	divs.b  d1, d2, d3
+	divs.w  d2, d3, d4
+	divs.l  d3, d7, #9842
+	divu.b  d4, d1, (32,s)
+	divu.w  d5, d3, [34,x]
+	divu.l  d6, d7, (s+)
+	divu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/eor.d b/gas/testsuite/gas/s12z/eor.d
new file mode 100644
index 0000000000..f829a52082
--- /dev/null
+++ b/gas/testsuite/gas/s12z/eor.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name:    
+#source:  eor.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 78 fc 84 	eor d2, #-892
+   4:	1b 79 ef 32 	eor d3, #-4302
+   8:	1b 7f 00 01 	eor d7, #123456
+   c:	e2 40 
+   e:	1b 7b 04 d2 	eor d5, #1234
+  12:	1b 7c 7b    	eor d0, #123
+  15:	1b 7d 22    	eor d1, #34
+  18:	1b 7e ff ff 	eor d6, #-56789
+  1c:	22 2b 
+  1e:	1b 7a 22 3d 	eor d4, #8765
+  22:	1b 8c d5 21 	eor d0, \[-223,y\]
+  26:	1b 8d f2 00 	eor d1, \(34000,p\)
+  2a:	84 d0 
+  2c:	1b 88 fb    	eor d2, \(-s\)
+  2f:	1b 79 00 04 	eor d3, #4
+  33:	1b 8a bc    	eor d4, d0
+  36:	1b 8b f9 4c 	eor d5, 85178
+  3a:	ba 
+  3b:	1b 8e fe 00 	eor d6, \[15256\]
+  3f:	3b 98 
+  41:	1b 8f 8b    	eor d7, \(d5,x\)
+  44:	1b 89 f7    	eor d3, \(y\+\)
diff --git a/gas/testsuite/gas/s12z/eor.s b/gas/testsuite/gas/s12z/eor.s
new file mode 100644
index 0000000000..cc4985add4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/eor.s
@@ -0,0 +1,17 @@
+	eor d2, #-892
+	eor d3, #-4302
+	eor d7, #123456
+	eor d5, #1234
+	eor d0, #123
+	eor d1, #34
+	eor d6, #-56789
+	eor d4, #8765
+	eor d0, [-223,y]
+	eor d1, (34000, p)
+	eor d2, (-s)
+	eor d3, #4
+	eor d4, d0
+	eor d5, 85178
+	eor d6, [15256]
+	eor d7, (d5, x)
+	eor d3, (y+)
diff --git a/gas/testsuite/gas/s12z/exg.d b/gas/testsuite/gas/s12z/exg.d
new file mode 100644
index 0000000000..58e4ae7c80
--- /dev/null
+++ b/gas/testsuite/gas/s12z/exg.d
@@ -0,0 +1,29 @@
+#objdump: -d
+#name:    
+#source:  exg.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	ae 45       	exg d0, d1
+   2:	ae 55       	exg d1, d1
+   4:	ae 05       	exg d2, d1
+   6:	ae 15       	exg d3, d1
+   8:	ae 25       	exg d4, d1
+   a:	ae 35       	exg d5, d1
+   c:	ae 65       	exg d6, d1
+   e:	ae 75       	exg d7, d1
+  10:	ae 85       	exg x, d1
+  12:	ae 95       	exg y, d1
+  14:	ae c5       	exg cch, d1
+  16:	ae d5       	exg ccl, d1
+  18:	ae e5       	exg ccw, d1
+  1a:	ae 68       	exg d6, x
+  1c:	ae 79       	exg d7, y
+  1e:	ae 8e       	exg x, ccw
+  20:	ae 97       	sex y, d7
+  22:	ae cd       	exg cch, ccl
diff --git a/gas/testsuite/gas/s12z/exg.s b/gas/testsuite/gas/s12z/exg.s
new file mode 100644
index 0000000000..55ce30139c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/exg.s
@@ -0,0 +1,18 @@
+	exg d0, d1
+	exg d1, d1
+	exg d2, d1
+	exg d3, d1
+	exg d4, d1
+	exg d5, d1
+	exg d6, d1
+	exg d7, d1
+	exg x, d1
+	exg y, d1
+	exg cch, d1
+	exg ccl, d1
+	exg ccw, d1
+	exg d6, x
+	exg d7, y
+	exg x, ccw
+	sex y, d7
+	exg cch, ccl
diff --git a/gas/testsuite/gas/s12z/ext24-ld-xy.d b/gas/testsuite/gas/s12z/ext24-ld-xy.d
new file mode 100644
index 0000000000..a3f075f0be
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ext24-ld-xy.d
@@ -0,0 +1,12 @@
+#objdump: -d
+#name:    
+#source:  ext24-ld-xy.s
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	b8 74 cb b1 	ld x, 7654321
+   4:	b9 63 d7 6a 	ld y, 6543210
diff --git a/gas/testsuite/gas/s12z/ext24-ld-xy.s b/gas/testsuite/gas/s12z/ext24-ld-xy.s
new file mode 100644
index 0000000000..2b262f06df
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ext24-ld-xy.s
@@ -0,0 +1,2 @@
+	.long 0xB874CBB1               ;; LD        X,7654321
+	.long 0xB963D76A               ;; LD        Y,6543210
diff --git a/gas/testsuite/gas/s12z/inc-opr.d b/gas/testsuite/gas/s12z/inc-opr.d
new file mode 100644
index 0000000000..d013d6ac6f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  inc-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	9c 88       	inc.b \(d2,x\)
+   2:	9d fe 00 04 	inc.w \[1234\]
+   6:	d2 
+   7:	9f 88       	inc.l \(d2,x\)
diff --git a/gas/testsuite/gas/s12z/inc-opr.s b/gas/testsuite/gas/s12z/inc-opr.s
new file mode 100644
index 0000000000..18760826f3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc-opr.s
@@ -0,0 +1,3 @@
+	inc.b  (d2, x)
+	inc.w  [1234]
+	inc.l  (d2, x)
diff --git a/gas/testsuite/gas/s12z/inc.d b/gas/testsuite/gas/s12z/inc.d
new file mode 100644
index 0000000000..51b912b9ce
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  inc.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	30          	inc d2
+   1:	31          	inc d3
+   2:	32          	inc d4
+   3:	33          	inc d5
+   4:	34          	inc d0
+   5:	35          	inc d1
+   6:	36          	inc d6
+   7:	37          	inc d7
diff --git a/gas/testsuite/gas/s12z/inc.s b/gas/testsuite/gas/s12z/inc.s
new file mode 100644
index 0000000000..89e0b97162
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc.s
@@ -0,0 +1,8 @@
+L1:	inc d2
+	inc d3
+	inc d4
+	inc d5
+	inc d0
+	inc d1
+	inc d6
+	inc d7
diff --git a/gas/testsuite/gas/s12z/inh.d b/gas/testsuite/gas/s12z/inh.d
new file mode 100644
index 0000000000..4f437f1bca
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inh.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  inh.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	ff          	swi
+   1:	05          	rts
+   2:	00          	bgnd
+   3:	01          	nop
diff --git a/gas/testsuite/gas/s12z/inh.s b/gas/testsuite/gas/s12z/inh.s
new file mode 100644
index 0000000000..22b2858325
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inh.s
@@ -0,0 +1,5 @@
+	swi
+	rts
+	bgnd
+	nop
+
diff --git a/gas/testsuite/gas/s12z/jmp.d b/gas/testsuite/gas/s12z/jmp.d
new file mode 100644
index 0000000000..12ff350b47
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jmp.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name:    JMP instruction
+#source:  jmp.s
+
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	aa bb       	jmp d5
+   2:	aa 4c       	jmp \(12,x\)
+   4:	aa f3       	jmp \(\+y\)
+   6:	aa d3       	jmp \(-y\)
+   8:	aa f7       	jmp \(y\+\)
+   a:	aa d7       	jmp \(y-\)
+   c:	aa e3       	jmp \(\+x\)
+   e:	aa c3       	jmp \(-x\)
+  10:	aa e7       	jmp \(x\+\)
+  12:	aa c7       	jmp \(x-\)
+  14:	aa fb       	jmp \(-s\)
+  16:	aa ff       	jmp \(s\+\)
+  18:	aa ab       	jmp \(d5,s\)
+  1a:	aa 87 00 5a 	jmp \(90,d7\)
+  1e:	aa f0 5a    	jmp \(90,p\)
+  21:	aa d4 2d    	jmp \[45,y\]
+  24:	aa 00 10    	jmp 16
+  27:	aa 37 f1    	jmp 14321
+  2a:	aa f9 be 91 	jmp 114321
+  2e:	aa fe 06 98 	jmp \[432134\]
+  32:	06 
diff --git a/gas/testsuite/gas/s12z/jmp.s b/gas/testsuite/gas/s12z/jmp.s
new file mode 100644
index 0000000000..fa4321d649
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jmp.s
@@ -0,0 +1,20 @@
+ 	jmp d5
+	jmp (12, x)
+	jmp (+y)
+	jmp (-y)
+	jmp (y+)
+	jmp (y-)
+	jmp (+x)
+	jmp (-x)
+	jmp (x+)
+	jmp (x-)
+	jmp (-s)
+	jmp (s+)
+ 	jmp (d5,s)
+ 	jmp (90,d7)
+ 	jmp (90,p)
+	jmp [45,y]
+	jmp 16
+	jmp 14321
+	jmp 114321
+	jmp [432134]
diff --git a/gas/testsuite/gas/s12z/jsr.d b/gas/testsuite/gas/s12z/jsr.d
new file mode 100644
index 0000000000..8508a0a740
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jsr.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name:    JSR instruction
+#source:  jsr.s
+
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	ab b8       	jsr d2
+   2:	ab 52       	jsr \(2,y\)
+   4:	ab f3       	jsr \(\+y\)
+   6:	ab d3       	jsr \(-y\)
+   8:	ab f7       	jsr \(y\+\)
+   a:	ab d7       	jsr \(y-\)
+   c:	ab e3       	jsr \(\+x\)
+   e:	ab c3       	jsr \(-x\)
+  10:	ab e7       	jsr \(x\+\)
+  12:	ab c7       	jsr \(x-\)
+  14:	ab fb       	jsr \(-s\)
+  16:	ab ff       	jsr \(s\+\)
+  18:	ab 89       	jsr \(d3,x\)
+  1a:	ab 86 00 1e 	jsr \(30,d6\)
+  1e:	ab f0 5d    	jsr \(93,p\)
+  21:	ab d4 2d    	jsr \[45,y\]
+  24:	ab 00 0c    	jsr 12
+  27:	ab 0f b5    	jsr 4021
+  2a:	ab f9 be 91 	jsr 114321
+  2e:	ab fe 07 82 	jsr \[492134\]
+  32:	66 
diff --git a/gas/testsuite/gas/s12z/jsr.s b/gas/testsuite/gas/s12z/jsr.s
new file mode 100644
index 0000000000..80f0ff1422
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jsr.s
@@ -0,0 +1,20 @@
+ 	jsr d2
+	jsr (2, y)
+	jsr (+y)
+	jsr (-y)
+	jsr (y+)
+	jsr (y-)
+	jsr (+x)
+	jsr (-x)
+	jsr (x+)
+	jsr (x-)
+	jsr (-s)
+	jsr (s+)
+ 	jsr (d3,x)
+ 	jsr (30,d6)
+ 	jsr (93,p)
+	jsr [45,y]
+	jsr 12
+	jsr 4021
+	jsr 114321
+	jsr [492134]
diff --git a/gas/testsuite/gas/s12z/ld-imm-page2.d b/gas/testsuite/gas/s12z/ld-imm-page2.d
new file mode 100644
index 0000000000..3f1744f833
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm-page2.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  ld-imm-page2.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 03 aa bb 	ld s, #-5588020
+   4:	cc 
+   5:	1b 03 00 30 	ld s, #12309
+   9:	15 
diff --git a/gas/testsuite/gas/s12z/ld-imm-page2.s b/gas/testsuite/gas/s12z/ld-imm-page2.s
new file mode 100644
index 0000000000..09c735c893
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm-page2.s
@@ -0,0 +1,2 @@
+	ld s, #-5588020
+	ld s, #12309
diff --git a/gas/testsuite/gas/s12z/ld-imm.d b/gas/testsuite/gas/s12z/ld-imm.d
new file mode 100644
index 0000000000..b0e4fcbe3f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm.d
@@ -0,0 +1,25 @@
+#objdump: -d
+#name:    
+#source:  ld-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <here>:
+   0:	90 01 23    	ld d2, #291
+   3:	91 01 23    	ld d3, #291
+   6:	92 01 23    	ld d4, #291
+   9:	93 01 23    	ld d5, #291
+   c:	94 56       	ld d0, #86
+   e:	95 78       	ld d1, #120
+  10:	96 12 34 56 	ld d6, #305419896
+  14:	78 
+  15:	97 12 34 56 	ld d7, #305419896
+  19:	78 
+  1a:	98 ab cd ef 	ld x, #-5517841
+  1e:	99 fe dc ba 	ld y, #-74566
+  22:	98 00 cd ef 	ld x, #52719
+  26:	99 00 dc ba 	ld y, #56506
diff --git a/gas/testsuite/gas/s12z/ld-imm.s b/gas/testsuite/gas/s12z/ld-imm.s
new file mode 100644
index 0000000000..569123de20
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm.s
@@ -0,0 +1,16 @@
+here:	ld d2, #0x0123
+	ld d3, #0x0123
+	ld d4, #0x0123
+	ld d5, #0x0123
+	ld d0, #0x56
+	ld d1, #0x78
+	ld d6, #0x12345678
+	ld d7, #0x12345678
+
+	ld x, #-5517841
+	ld y, #-74566
+
+
+	;; The following two can be encoded using {CDEF}{AB}
+	ld x, #0xcdef
+	ld y, #0xdcba
diff --git a/gas/testsuite/gas/s12z/ld-immu18.d b/gas/testsuite/gas/s12z/ld-immu18.d
new file mode 100644
index 0000000000..ba071dfbdf
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-immu18.d
@@ -0,0 +1,28 @@
+#objdump: -d
+#name:    
+#source:  ld-immu18.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	00          	bgnd
+   1:	ca ff ee    	ld x, #65518
+   4:	00          	bgnd
+   5:	cb df e4    	ld y, #57316
+   8:	00          	bgnd
+   9:	da f0 ea    	ld x, #127210
+   c:	00          	bgnd
+   d:	db 7f 6e    	ld y, #98158
+  10:	00          	bgnd
+  11:	ea 6f ea    	ld x, #159722
+  14:	00          	bgnd
+  15:	eb 7f 9e    	ld y, #163742
+  18:	00          	bgnd
+  19:	fa 1f ca    	ld x, #204746
+  1c:	00          	bgnd
+  1d:	fb 7f 0e    	ld y, #229134
+  20:	01          	nop
diff --git a/gas/testsuite/gas/s12z/ld-immu18.s b/gas/testsuite/gas/s12z/ld-immu18.s
new file mode 100644
index 0000000000..563765e8bd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-immu18.s
@@ -0,0 +1,10 @@
+	.long 0xCAFFEE
+	.long 0xCBDFE4
+	.long 0xDAF0EA
+	.long 0xDB7F6E
+	.long 0xEA6FEA
+	.long 0xEB7F9E
+	.long 0xFA1FCA
+	.long 0xFB7F0E
+	nop
+
diff --git a/gas/testsuite/gas/s12z/ld-large-direct.d b/gas/testsuite/gas/s12z/ld-large-direct.d
new file mode 100644
index 0000000000..c17f1c96af
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-large-direct.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    LD reg - conldant optimised to EXT24
+#source:  ld-large-direct.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	b0 12 34 56 	ld d2, 1193046
+   4:	b1 c0 ff ee 	ld d3, 12648430
+   8:	b2 80 00 02 	ld d4, 8388610
+   c:	b4 80 00 03 	ld d0, 8388611
+  10:	b5 80 00 03 	ld d1, 8388611
+  14:	b3 80 00 04 	ld d5, 8388612
+  18:	b6 80 00 06 	ld d6, 8388614
+  1c:	b7 80 00 07 	ld d7, 8388615
+  20:	b8 80 00 08 	ld x, 8388616
+  24:	b9 80 00 09 	ld y, 8388617
diff --git a/gas/testsuite/gas/s12z/ld-large-direct.s b/gas/testsuite/gas/s12z/ld-large-direct.s
new file mode 100644
index 0000000000..4c53f2ade7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-large-direct.s
@@ -0,0 +1,11 @@
+	ld d2, 0x123456
+	ld d3, 0xc0ffee
+	ld d4, 0x800002
+	ld d0, 0x800003
+	ld d1, 0x800003
+	ld d5, 0x800004
+	ld d6, 0x800006
+	ld d7, 0x800007
+	ld x,  0x800008
+	ld y,  0x800009
+
diff --git a/gas/testsuite/gas/s12z/ld-opr.d b/gas/testsuite/gas/s12z/ld-opr.d
new file mode 100644
index 0000000000..c0a8ec2d89
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:    
+#source:  ld-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	a4 dc       	ld d0, \[d0,y\]
+   2:	a5 cd       	ld d1, \[d1,x\]
+   4:	a0 cd       	ld d2, \[d1,x\]
+   6:	a1 80 04 d2 	ld d3, \(1234,d2\)
+   a:	a2 e2 ff fb 	ld d4, \(-1234,s\)
+   e:	2e 
+   f:	a3 bf       	ld d5, d7
+  11:	a6 88       	ld d6, \(d2,x\)
+  13:	a7 d9       	ld d7, \[d3,y\]
+  15:	a8 ac       	ld x, \(d0,s\)
+  17:	a9 cd       	ld y, \[d1,x\]
diff --git a/gas/testsuite/gas/s12z/ld-opr.s b/gas/testsuite/gas/s12z/ld-opr.s
new file mode 100644
index 0000000000..ee452e9c13
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-opr.s
@@ -0,0 +1,10 @@
+	ld d0, [d0,y]
+	ld d1, [d1,x]
+	ld d2, [d1, x]
+	ld d3, (1234,d2)
+	ld d4, (-1234,s)
+	ld d5, d7
+	ld d6, (d2, x)
+	ld d7, [d3, y]
+	ld x,  (d0, s)
+	ld y,  [d1, x]
diff --git a/gas/testsuite/gas/s12z/ld-s-opr.d b/gas/testsuite/gas/s12z/ld-s-opr.d
new file mode 100644
index 0000000000..085ebfbd3e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-s-opr.d
@@ -0,0 +1,16 @@
+#objdump: -d
+#name:    
+#source:  ld-s-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 00 df    	ld s, \[d7,y\]
+   3:	1b 00 fe 00 	ld s, \[8134\]
+   7:	1f c6 
+   9:	1b 00 ae    	ld s, \(d6,s\)
+   c:	1b 00 fb    	ld s, \(-s\)
diff --git a/gas/testsuite/gas/s12z/ld-s-opr.s b/gas/testsuite/gas/s12z/ld-s-opr.s
new file mode 100644
index 0000000000..41ee23e095
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-s-opr.s
@@ -0,0 +1,4 @@
+	ld s,  [d7, y]
+	ld s,  [8134]
+	ld s,  (d6, s)
+	ld s,  (-s)
diff --git a/gas/testsuite/gas/s12z/ld-small-direct.d b/gas/testsuite/gas/s12z/ld-small-direct.d
new file mode 100644
index 0000000000..e6cffd29c8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-small-direct.d
@@ -0,0 +1,31 @@
+#objdump: -d
+#name:    LD reg - small constants left in OPR mode
+#source:  ld-small-direct.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	a0 fa 00 00 	ld d2, L1
+   4:	00 
+   5:	a1 fa 00 00 	ld d3, 25
+   9:	19 
+   a:	a2 fa 00 00 	ld d4, L1
+   e:	00 
+
+0000000f <L3>:
+   f:	a4 fa 00 00 	ld d0, 25
+  13:	19 
+  14:	a5 fa 00 00 	ld d1, L3
+  18:	0f 
+  19:	a3 fa 00 00 	ld d5, L1
+  1d:	00 
+  1e:	a6 fa 00 00 	ld d6, L3
+  22:	0f 
+  23:	a7 fa 00 00 	ld d7, 25
+  27:	19 
+  28:	a8 30 39    	ld x, 12345
+  2b:	a9 26 94    	ld y, 9876
diff --git a/gas/testsuite/gas/s12z/ld-small-direct.s b/gas/testsuite/gas/s12z/ld-small-direct.s
new file mode 100644
index 0000000000..5d9ea6d433
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-small-direct.s
@@ -0,0 +1,11 @@
+L1:	ld d2, L1
+	ld d3, .L2
+	ld d4, L1
+L3:     ld d0, .L2
+	ld d1, L3
+.L2:	ld d5, L1
+	ld d6, L3
+	ld d7, .L2
+	ld x,  12345
+	ld y,  9876
+
diff --git a/gas/testsuite/gas/s12z/lea-immu18.d b/gas/testsuite/gas/s12z/lea-immu18.d
new file mode 100644
index 0000000000..3088b41ab9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea-immu18.d
@@ -0,0 +1,14 @@
+#objdump: -d
+#name:    
+#source:  lea-immu18.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	18 55       	lea x, \(85,x\)
+   2:	19 aa       	lea y, \(-86,y\)
+   4:	1a 12       	lea s, \(18,s\)
diff --git a/gas/testsuite/gas/s12z/lea-immu18.s b/gas/testsuite/gas/s12z/lea-immu18.s
new file mode 100644
index 0000000000..b003922fa9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea-immu18.s
@@ -0,0 +1,3 @@
+	.short 0x1855
+	.short 0x19AA
+	.short 0x1A12
diff --git a/gas/testsuite/gas/s12z/lea.d b/gas/testsuite/gas/s12z/lea.d
new file mode 100644
index 0000000000..30722a500d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea.d
@@ -0,0 +1,18 @@
+#objdump: -d
+#name:    
+#source:  lea.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	0a 44       	lea s, \(4,x\)
+   2:	06 c0 7b    	lea d6, \(123,x\)
+   5:	07 d1 16    	lea d7, \(-234,y\)
+   8:	08 c1 ea    	lea x, \(-22,x\)
+   b:	09 d0 16    	lea y, \(22,y\)
+   e:	0a e0 16    	lea s, \(22,s\)
+  11:	09 c1 d3    	lea y, \(-45,x\)
diff --git a/gas/testsuite/gas/s12z/lea.s b/gas/testsuite/gas/s12z/lea.s
new file mode 100644
index 0000000000..2d75a939af
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea.s
@@ -0,0 +1,8 @@
+	lea s, (4,x)
+	lea d6, (123,x)
+	lea d7, (-234,y)
+	lea x, (-22,x)
+	lea y, (22,y)
+	lea s, (22,s)
+	lea y, (-45,x)
+
diff --git a/gas/testsuite/gas/s12z/mac.d b/gas/testsuite/gas/s12z/mac.d
new file mode 100644
index 0000000000..d2758b6e1f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mac.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  mac.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 4c ec 62 	macs.b d0, d1, #98
+   4:	1b 4d c0 b9 	macs.b d1, d2, d3
+   8:	1b 48 c9 ba 	macs.w d2, d3, d4
+   c:	1b 49 ff 00 	macs.l d3, d7, #9842
+  10:	00 26 72 
+  13:	1b 4a 68 e0 	macu.b d4, d1, \(32,s\)
+  17:	20 
+  18:	1b 4b 49 c4 	macu.w d5, d3, \[34,x\]
+  1c:	22 
+  1d:	1b 4e 7b ff 	macu.l d6, d7, \(s\+\)
+  21:	1b 4f 7a d4 	macu.lp d7, \[12,y\], \(7,d1\)
+  25:	0c 85 00 07 
diff --git a/gas/testsuite/gas/s12z/mac.s b/gas/testsuite/gas/s12z/mac.s
new file mode 100644
index 0000000000..8914524198
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mac.s
@@ -0,0 +1,8 @@
+	macs.b  d0, d1, #98
+	macs.b  d1, d2, d3
+	macs.w  d2, d3, d4
+	macs.l  d3, d7, #9842
+	macu.b  d4, d1, (32,s)
+	macu.w  d5, d3, [34,x]
+	macu.l  d6, d7, (s+)
+	macu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/min-max.d b/gas/testsuite/gas/s12z/min-max.d
new file mode 100644
index 0000000000..f01684a68d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/min-max.d
@@ -0,0 +1,48 @@
+#objdump: -d
+#name:    
+#source:  min-max.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 2c fe 01 	maxs d0, \[123456\]
+   4:	e2 40 
+   6:	1b 2d c4 04 	maxs d1, \[4,x\]
+   a:	1b 28 b8    	maxs d2, d2
+   d:	1b 29 dc    	maxs d3, \[d0,y\]
+  10:	1b 2a e4 0c 	maxs d4, \[12,s\]
+  14:	1b 2b 63    	maxs d5, \(3,s\)
+  17:	1b 2e e1 85 	maxs d6, \(-123,s\)
+  1b:	1b 2f f2 01 	maxs d7, \(123987,p\)
+  1f:	e4 53 
+  21:	1b 24 c7    	mins d0, \(x-\)
+  24:	1b 25 d7    	mins d1, \(y-\)
+  27:	1b 20 e7    	mins d2, \(x\+\)
+  2a:	1b 21 f7    	mins d3, \(y\+\)
+  2d:	1b 22 ff    	mins d4, \(s\+\)
+  30:	1b 23 e3    	mins d5, \(\+x\)
+  33:	1b 26 f3    	mins d6, \(\+y\)
+  36:	1b 27 c3    	mins d7, \(-x\)
+  39:	1b 1c d3    	maxu d0, \(-y\)
+  3c:	1b 1d fb    	maxu d1, \(-s\)
+  3f:	1b 18 8b    	maxu d2, \(d5,x\)
+  42:	1b 19 9e    	maxu d3, \(d6,y\)
+  45:	1b 1a af    	maxu d4, \(d7,s\)
+  48:	1b 1b e2 ff 	maxu d5, \(-1023,s\)
+  4c:	fc 01 
+  4e:	1b 1e f6 00 	maxu d6, \[1087,p\]
+  52:	04 3f 
+  54:	1b 1f d3    	maxu d7, \(-y\)
+  57:	1b 14 c3    	minu d0, \(-x\)
+  5a:	1b 15 ff    	minu d1, \(s\+\)
+  5d:	1b 10 8d    	minu d2, \(d1,x\)
+  60:	1b 11 98    	minu d3, \(d2,y\)
+  63:	1b 12 a9    	minu d4, \(d3,s\)
+  66:	1b 13 e1 85 	minu d5, \(-123,s\)
+  6a:	1b 16 f6 01 	minu d6, \[123987,p\]
+  6e:	e4 53 
+  70:	1b 17 d7    	minu d7, \(y-\)
diff --git a/gas/testsuite/gas/s12z/min-max.s b/gas/testsuite/gas/s12z/min-max.s
new file mode 100644
index 0000000000..1b6b9d7001
--- /dev/null
+++ b/gas/testsuite/gas/s12z/min-max.s
@@ -0,0 +1,32 @@
+        maxs d0, [123456]
+        maxs d1, [4,x]
+        maxs d2, d2
+        maxs d3, [d0, y]
+        maxs d4, [12,s]
+        maxs d5, (3,s)
+        maxs d6, (-123,s)
+        maxs d7, (123987, p)
+        mins d0, (x-)
+        mins d1, (y-)
+        mins d2, (x+)
+        mins d3, (y+)
+        mins d4, (s+)
+        mins d5, (+x)
+        mins d6, (+y)
+        mins d7, (-x)
+        maxu d0, (-y)
+        maxu d1, (-s)
+        maxu d2, (d5, x)
+        maxu d3, (d6, y)
+        maxu d4, (d7, s)
+        maxu d5, (-1023,s)
+        maxu d6, [1087, p]
+        maxu d7, (-y)
+        minu d0, (-x)
+        minu d1, (s+)
+        minu d2, (d1, x)
+        minu d3, (d2, y)
+        minu d4, (d3, s)
+        minu d5, (-123,s)
+        minu d6, [123987, p]
+        minu d7, (y-)
diff --git a/gas/testsuite/gas/s12z/mod.d b/gas/testsuite/gas/s12z/mod.d
new file mode 100644
index 0000000000..34c67dd07a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mod.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  mod.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 3c ec 62 	mods.b d0, d1, #98
+   4:	1b 3d c0 b9 	mods.b d1, d2, d3
+   8:	1b 38 c9 ba 	mods.w d2, d3, d4
+   c:	1b 39 ff 00 	mods.l d3, d7, #9842
+  10:	00 26 72 
+  13:	1b 3a 68 e0 	modu.b d4, d1, \(32,s\)
+  17:	20 
+  18:	1b 3b 49 c4 	modu.w d5, d3, \[34,x\]
+  1c:	22 
+  1d:	1b 3e 7b ff 	modu.l d6, d7, \(s\+\)
+  21:	1b 3f 7a d4 	modu.lp d7, \[12,y\], \(7,d1\)
+  25:	0c 85 00 07 
diff --git a/gas/testsuite/gas/s12z/mod.s b/gas/testsuite/gas/s12z/mod.s
new file mode 100644
index 0000000000..c94994a9ac
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mod.s
@@ -0,0 +1,8 @@
+	mods.b  d0, d1, #98
+	mods.b  d1, d2, d3
+	mods.w  d2, d3, d4
+	mods.l  d3, d7, #9842
+	modu.b  d4, d1, (32,s)
+	modu.w  d5, d3, [34,x]
+	modu.l  d6, d7, (s+)
+	modu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/mov.d b/gas/testsuite/gas/s12z/mov.d
new file mode 100644
index 0000000000..e9f4086394
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mov.d
@@ -0,0 +1,26 @@
+#objdump: -d
+#name:    
+#source:  mov.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	0c 7b e3    	mov.b #123, \(\+x\)
+   3:	0d 11 70 80 	mov.w #4464, \(45,d2\)
+   7:	00 2d 
+   9:	0e 12 34 56 	mov.p #1193046, \[34,s\]
+   d:	e4 22 
+   f:	0f 12 34 56 	mov.l #305419896, \(2234,d7\)
+  13:	78 87 08 ba 
+  17:	1c 84 00 01 	mov.b \(1,d0\), \(2,d1\)
+  1b:	85 00 02 
+  1e:	1d 82 00 01 	mov.w \(1,d4\), \(-s\)
+  22:	fb 
+  23:	1e 83 00 03 	mov.p \(3,d5\), \(-x\)
+  27:	c3 
+  28:	1f 87 00 26 	mov.l \(38,d7\), \(\+x\)
+  2c:	e3 
diff --git a/gas/testsuite/gas/s12z/mov.s b/gas/testsuite/gas/s12z/mov.s
new file mode 100644
index 0000000000..35af91963e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mov.s
@@ -0,0 +1,8 @@
+	mov.b #123, (+x)
+	mov.w #4464, (45,d2)
+	mov.p #0x123456, [34,s]
+	mov.l #0x12345678, (2234, d7)
+	mov.b (1,d0), (2,d1)
+	mov.w (1,d4), (-s)
+	mov.p (3,d5), (-x)
+	mov.l (38,d7), (+x)
diff --git a/gas/testsuite/gas/s12z/mul-imm.d b/gas/testsuite/gas/s12z/mul-imm.d
new file mode 100644
index 0000000000..fdc4e10dd5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-imm.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  mul-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	4c ec 85    	muls.b d0, d1, #-123
+   3:	4d ed cf c7 	muls.w d1, d1, #-12345
+   7:	48 ef ff ed 	muls.l d2, d1, #-1234567
+   b:	29 79 
+   d:	4c 6c 7b    	mulu.b d0, d1, #123
+  10:	4d 6d 30 39 	mulu.w d1, d1, #12345
+  14:	48 6f 00 12 	mulu.l d2, d1, #1234567
+  18:	d6 87 
diff --git a/gas/testsuite/gas/s12z/mul-imm.s b/gas/testsuite/gas/s12z/mul-imm.s
new file mode 100644
index 0000000000..d0479346a4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-imm.s
@@ -0,0 +1,6 @@
+	muls.b d0, d1, #-123
+	muls.w d1, d1, #-12345
+	muls.l d2, d1, #-1234567
+	mulu.b d0, d1, #123
+	mulu.w d1, d1, #12345
+	mulu.l d2, d1, #1234567
diff --git a/gas/testsuite/gas/s12z/mul-opr-opr.d b/gas/testsuite/gas/s12z/mul-opr-opr.d
new file mode 100644
index 0000000000..15bb7a915e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr-opr.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  mul-opr-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	4c c2 ff fb 	muls.bb d0, \(s\+\), \(-s\)
+   4:	4d 46 e0 2d 	mulu.bw d1, \(45,s\), \(d0,s\)
+   8:	ac 
+   9:	48 ca e5 d3 	muls.bp d2, \[-45,s\], \[1239\]
+   d:	fe 00 04 d7 
+  11:	49 4e c5 6f 	mulu.bl d3, \[-145,x\], \(\+x\)
+  15:	e3 
+  16:	4c d2 e7 d3 	muls.wb d0, \(x\+\), \(-y\)
diff --git a/gas/testsuite/gas/s12z/mul-opr-opr.s b/gas/testsuite/gas/s12z/mul-opr-opr.s
new file mode 100644
index 0000000000..a25372558c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr-opr.s
@@ -0,0 +1,6 @@
+	muls.bb d0, (s+), (-s)
+	mulu.bw d1, (45, s), (d0, s)
+	muls.bp d2, [-45, s], [1239]
+	mulu.bl d3, [-145, x], (+x)
+	muls.wb d0, (x+), (-y)
+
diff --git a/gas/testsuite/gas/s12z/mul-opr.d b/gas/testsuite/gas/s12z/mul-opr.d
new file mode 100644
index 0000000000..875ba7268e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:    
+#source:  mul-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	4c e8 70    	muls.b d0, d1, #-1
+   3:	49 f9 fb    	muls.w d3, d7, \(-s\)
+   6:	49 fb e3    	muls.l d3, d7, \(\+x\)
+   9:	4a 68 e0 20 	mulu.b d4, d1, \(32,s\)
+   d:	4b 49 c4 22 	mulu.w d5, d3, \[34,x\]
+  11:	4e 7b ff    	mulu.l d6, d7, \(s\+\)
diff --git a/gas/testsuite/gas/s12z/mul-opr.s b/gas/testsuite/gas/s12z/mul-opr.s
new file mode 100644
index 0000000000..22e97fb459
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr.s
@@ -0,0 +1,6 @@
+	muls.b d0, d1, #-1
+	muls.w d3, d7, (-s)
+	muls.l d3, d7, (+x)
+	mulu.b d4, d1, (32,s)
+	mulu.w d5, d3, [34,x]
+	mulu.l d6, d7, (s+)
diff --git a/gas/testsuite/gas/s12z/mul-reg.d b/gas/testsuite/gas/s12z/mul-reg.d
new file mode 100644
index 0000000000..3f4c84b689
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-reg.d
@@ -0,0 +1,27 @@
+#objdump: -d
+#name:    
+#source:  mul-reg.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	4c a8       	muls d0, d1, d2
+   2:	4d 81       	muls d1, d2, d3
+   4:	48 8a       	muls d2, d3, d4
+   6:	49 93       	muls d3, d4, d5
+   8:	4a 9e       	muls d4, d5, d6
+   a:	4b b7       	muls d5, d6, d7
+   c:	4e bc       	muls d6, d7, d0
+   e:	4f a5       	muls d7, d0, d1
+  10:	4c 28       	mulu d0, d1, d2
+  12:	4d 01       	mulu d1, d2, d3
+  14:	48 0a       	mulu d2, d3, d4
+  16:	49 13       	mulu d3, d4, d5
+  18:	4a 1e       	mulu d4, d5, d6
+  1a:	4b 37       	mulu d5, d6, d7
+  1c:	4e 3c       	mulu d6, d7, d0
+  1e:	4f 25       	mulu d7, d0, d1
diff --git a/gas/testsuite/gas/s12z/mul-reg.s b/gas/testsuite/gas/s12z/mul-reg.s
new file mode 100644
index 0000000000..9cb9ac9f06
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-reg.s
@@ -0,0 +1,16 @@
+	muls d0, d1, d2
+	muls d1, d2, d3
+	muls d2, d3, d4
+	muls d3, d4, d5
+	muls d4, d5, d6
+	muls d5, d6, d7
+	muls d6, d7, d0
+	muls d7, d0, d1
+	mulu d0, d1, d2
+	mulu d1, d2, d3
+	mulu d2, d3, d4
+	mulu d3, d4, d5
+	mulu d4, d5, d6
+	mulu d5, d6, d7
+	mulu d6, d7, d0
+	mulu d7, d0, d1
diff --git a/gas/testsuite/gas/s12z/mul.d b/gas/testsuite/gas/s12z/mul.d
new file mode 100644
index 0000000000..e028b8558c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  mul.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	4c ec 62    	muls.b d0, d1, #98
+   3:	49 ff 00 00 	muls.l d3, d7, #9842
+   7:	26 72 
+   9:	4a 68 e0 20 	mulu.b d4, d1, \(32,s\)
+   d:	4b 49 c4 22 	mulu.w d5, d3, \[34,x\]
+  11:	4e 7b ff    	mulu.l d6, d7, \(s\+\)
+  14:	4f 7a d4 0c 	mulu.lp d7, \[12,y\], \(7,d1\)
+  18:	85 00 07 
diff --git a/gas/testsuite/gas/s12z/mul.s b/gas/testsuite/gas/s12z/mul.s
new file mode 100644
index 0000000000..1626ee410f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul.s
@@ -0,0 +1,6 @@
+	muls.b d0, d1, #98
+	muls.l d3, d7, #9842
+	mulu.b d4, d1, (32,s)
+	mulu.w d5, d3, [34,x]
+	mulu.l d6, d7, (s+)
+	mulu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/neg-opr.d b/gas/testsuite/gas/s12z/neg-opr.d
new file mode 100644
index 0000000000..7d4116dc7c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/neg-opr.d
@@ -0,0 +1,34 @@
+#objdump: -d
+#name:    
+#source:  neg-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	df fe 12 34 	neg.l \[1193046\]
+   4:	56 
+   5:	dc c4 04    	neg.b \[4,x\]
+   8:	dd b8       	neg.w d2
+   a:	dc dc       	neg.b \[d0,y\]
+   c:	dc e4 0c    	neg.b \[12,s\]
+   f:	dc 63       	neg.b \(3,s\)
+  11:	dc e1 85    	neg.b \(-123,s\)
+  14:	df f2 12 3a 	neg.l \(1194684,p\)
+  18:	bc 
+  19:	dd c7       	neg.w \(x-\)
+  1b:	dd d7       	neg.w \(y-\)
+  1d:	dc e7       	neg.b \(x\+\)
+  1f:	dc f7       	neg.b \(y\+\)
+  21:	dc ff       	neg.b \(s\+\)
+  23:	df e3       	neg.l \(\+x\)
+  25:	dd f3       	neg.w \(\+y\)
+  27:	df c3       	neg.l \(-x\)
+  29:	dd d3       	neg.w \(-y\)
+  2b:	dc fb       	neg.b \(-s\)
+  2d:	df 8d       	neg.l \(d1,x\)
+  2f:	df 98       	neg.l \(d2,y\)
+  31:	df a9       	neg.l \(d3,s\)
diff --git a/gas/testsuite/gas/s12z/neg-opr.s b/gas/testsuite/gas/s12z/neg-opr.s
new file mode 100644
index 0000000000..6e36326d3d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/neg-opr.s
@@ -0,0 +1,21 @@
+        neg.l [0x123456]
+        neg.b [4,x]
+        neg.w d2
+        neg.b [d0, y]
+        neg.b [12,s]
+        neg.b (3,s)
+        neg.b (-123,s)
+        neg.l (0x123abc,p)
+        neg.w (x-)
+        neg.w (y-)
+        neg.b (x+)
+        neg.b (y+)
+        neg.b (s+)
+        neg.l (+x)
+        neg.w (+y)
+        neg.l (-x)
+        neg.w (-y)
+        neg.b (-s)
+        neg.l (d1, x)
+        neg.l (d2, y)
+        neg.l (d3, s)
diff --git a/gas/testsuite/gas/s12z/not-so-simple-shifts.d b/gas/testsuite/gas/s12z/not-so-simple-shifts.d
new file mode 100644
index 0000000000..f9b4e11a10
--- /dev/null
+++ b/gas/testsuite/gas/s12z/not-so-simple-shifts.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:    
+#source:  not-so-simple-shifts.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	14 7b e3 71 	lsl.l d0, \(\+x\), #3
+   4:	13 2a 8e    	lsr.p d5, \(d6,x\), #2
+   7:	17 f9 f4 2d 	asl.w d7, \[45,p\], #13
+   b:	76 
+   c:	12 b8 84 00 	asr.b d4, \(145,d0\), #3
+  10:	91 71 
diff --git a/gas/testsuite/gas/s12z/not-so-simple-shifts.s b/gas/testsuite/gas/s12z/not-so-simple-shifts.s
new file mode 100644
index 0000000000..fe546e10f1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/not-so-simple-shifts.s
@@ -0,0 +1,4 @@
+	lsl.l d0, (+x), #3
+	lsr.p d5, (d6,x), #2
+	asl.w d7, [45,p], #13
+	asr.b d4, (145,d0), #3
diff --git a/gas/testsuite/gas/s12z/opr-18u.d b/gas/testsuite/gas/s12z/opr-18u.d
new file mode 100644
index 0000000000..d3a75cd335
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-18u.d
@@ -0,0 +1,26 @@
+#objdump: -d
+#name:    
+#source:  opr-18u.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	87 84 00 2d 	sub d7, \(45,d0\)
+   4:	87 85 00 2d 	sub d7, \(45,d1\)
+   8:	87 80 00 2d 	sub d7, \(45,d2\)
+   c:	87 81 00 2d 	sub d7, \(45,d3\)
+  10:	87 82 00 2d 	sub d7, \(45,d4\)
+  14:	87 83 00 2d 	sub d7, \(45,d5\)
+  18:	87 83 00 2d 	sub d7, \(45,d5\)
+  1c:	87 86 00 2d 	sub d7, \(45,d6\)
+  20:	87 87 00 2d 	sub d7, \(45,d7\)
+  24:	87 ef 03 ff 	sub d7, \(262143,d7\)
+  28:	ff 
+  29:	87 ef 04 00 	sub d7, \(262144,d7\)
+  2d:	00 
+  2e:	87 ef 04 00 	sub d7, \(262145,d7\)
+  32:	01 
diff --git a/gas/testsuite/gas/s12z/opr-18u.s b/gas/testsuite/gas/s12z/opr-18u.s
new file mode 100644
index 0000000000..79f95f13fc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-18u.s
@@ -0,0 +1,15 @@
+	sub d7, (45,D0)
+	sub d7, (45,D1)
+	sub d7, (45,D2)
+	sub d7, (45,D3)
+	sub d7, (45,D4)
+	sub d7, (45,D5)
+	sub d7, (45,D5)
+	sub d7, (45,D6)
+	sub d7, (45,D7)
+
+	sub d7, (262143,D7)
+	sub d7, (262144,D7)
+	sub d7, (262145,D7)
+
+
diff --git a/gas/testsuite/gas/s12z/opr-expr.d b/gas/testsuite/gas/s12z/opr-expr.d
new file mode 100644
index 0000000000..e02a78e56f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-expr.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:    Expressions in OPR direct submode
+#source:  opr-expr.s
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	01          	nop
+   1:	01          	nop
+   2:	bc 12 39    	clr.b 4665
diff --git a/gas/testsuite/gas/s12z/opr-expr.s b/gas/testsuite/gas/s12z/opr-expr.s
new file mode 100644
index 0000000000..d52ac38213
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-expr.s
@@ -0,0 +1,5 @@
+	equiv FOO, 0x1230
+
+	nop
+	nop
+	clr.b FOO+9
diff --git a/gas/testsuite/gas/s12z/opr-ext-18.d b/gas/testsuite/gas/s12z/opr-ext-18.d
new file mode 100644
index 0000000000..481ce9f5aa
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-ext-18.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:    
+#source:  opr-ext-18.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	85 fc ab cd 	sub d1, 175053
+   4:	84 f9 fe ed 	sub d0, 130797
\ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/opr-ext-18.s b/gas/testsuite/gas/s12z/opr-ext-18.s
new file mode 100644
index 0000000000..e0fdc3e24f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-ext-18.s
@@ -0,0 +1,5 @@
+;;; Test the 18 bit OPR mode
+;;; This should encode to four bytes only
+	sub d1, 0x2abcd
+	sub d0, 0x1feed
+
diff --git a/gas/testsuite/gas/s12z/opr-idx-24-reg.d b/gas/testsuite/gas/s12z/opr-idx-24-reg.d
new file mode 100644
index 0000000000..2ee64f5d22
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx-24-reg.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:    
+#source:  opr-idx-24-reg.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	bc e8 02 ab 	clr.b \(175053,d2\)
+   4:	cd 
diff --git a/gas/testsuite/gas/s12z/opr-idx-24-reg.s b/gas/testsuite/gas/s12z/opr-idx-24-reg.s
new file mode 100644
index 0000000000..e25468c4f0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx-24-reg.s
@@ -0,0 +1,2 @@
+	clr.b (175053, d2)
+
diff --git a/gas/testsuite/gas/s12z/opr-idx3-reg.d b/gas/testsuite/gas/s12z/opr-idx3-reg.d
new file mode 100644
index 0000000000..9b66f06fd7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-reg.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:    
+#source:  opr-idx3-reg.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	a9 c6 11 22 	ld y, \[1122867,x\]
+   4:	33 
+   5:	df fe 11 77 	neg.l \[1144678\]
+   9:	66 
+   a:	0c 9a fa 11 	mov.b #-102, 1162188
+   e:	bb cc 
diff --git a/gas/testsuite/gas/s12z/opr-idx3-reg.s b/gas/testsuite/gas/s12z/opr-idx3-reg.s
new file mode 100644
index 0000000000..b4d95ac39f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-reg.s
@@ -0,0 +1,3 @@
+L1: ld y, [0x112233, x]
+    neg.l [0x117766]
+    mov.b #-102, 0x11bbcc
diff --git a/gas/testsuite/gas/s12z/opr-idx3-xysp-24.d b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.d
new file mode 100644
index 0000000000..28fafbc42c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  opr-idx3-xysp-24.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	a6 c2 99 aa 	ld d6, \(-6706501,x\)
+   4:	bb 
+   5:	a7 d2 0a d3 	ld d7, \(709501,y\)
+   9:	7d 
diff --git a/gas/testsuite/gas/s12z/opr-idx3-xysp-24.s b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.s
new file mode 100644
index 0000000000..384a4cfc76
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.s
@@ -0,0 +1,3 @@
+	ld d6, (-6706501,x)
+	ld d7, (709501,y)
+	
diff --git a/gas/testsuite/gas/s12z/opr-indirect-expr.d b/gas/testsuite/gas/s12z/opr-indirect-expr.d
new file mode 100644
index 0000000000..95d51b34f0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-indirect-expr.d
@@ -0,0 +1,14 @@
+#objdump: -dr
+#name:    Expressions in OPR indirect mode
+#source:  opr-indirect-expr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	a7 fe 00 00 	ld d7, \[1\]
+   4:	01 
+			2: R_S12Z_EXT24	FOO
diff --git a/gas/testsuite/gas/s12z/opr-indirect-expr.s b/gas/testsuite/gas/s12z/opr-indirect-expr.s
new file mode 100644
index 0000000000..ee1fb12002
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-indirect-expr.s
@@ -0,0 +1 @@
+ ld d7, [FOO+1]
diff --git a/gas/testsuite/gas/s12z/opr-symbol.d b/gas/testsuite/gas/s12z/opr-symbol.d
new file mode 100644
index 0000000000..97e5b4fc32
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-symbol.d
@@ -0,0 +1,170 @@
+#objdump: -dt
+#name:    OPR addressing mode: symbols in its direct submode
+#source:  opr-symbol.s
+
+dump.o:     file format elf32-s12z
+
+SYMBOL TABLE:
+00000000 l    d  .text	00000000 .text
+00000000 l    d  .data	00000000 .data
+00000000 l    d  .bss	00000000 .bss
+00123456 l       \*ABS\*	00000000 sym1
+00abcdef l       \*ABS\*	00000000 sym2
+
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	0c 17 fa 12 	mov.b #23, sym1
+   4:	34 56 
+   6:	0d 00 17 fa 	mov.w #23, sym1
+   a:	12 34 56 
+   d:	0e 00 00 17 	mov.p #23, sym1
+  11:	fa 12 34 56 
+  15:	0f 00 00 00 	mov.l #23, sym1
+  19:	17 fa 12 34 
+  1d:	56 
+  1e:	1c fa 12 34 	mov.b sym1, sym2
+  22:	56 fa ab cd 
+  26:	ef 
+  27:	1d fa 12 34 	mov.w sym1, sym2
+  2b:	56 fa ab cd 
+  2f:	ef 
+  30:	1e fa 12 34 	mov.p sym1, sym2
+  34:	56 fa ab cd 
+  38:	ef 
+  39:	1f fa 12 34 	mov.l sym1, sym2
+  3d:	56 fa ab cd 
+  41:	ef 
+  42:	65 fa 12 34 	add d1, sym1
+  46:	56 
+  47:	68 fa 12 34 	and d2, sym1
+  4b:	56 
+  4c:	81 fa 12 34 	sub d3, sym1
+  50:	56 
+  51:	8a fa 12 34 	or d4, sym1
+  55:	56 
+  56:	9c fa 12 34 	inc.b sym1
+  5a:	56 
+  5b:	9d fa 12 34 	inc.w sym1
+  5f:	56 
+  60:	9f fa 12 34 	inc.l sym1
+  64:	56 
+  65:	b2 12 34 56 	ld d4, sym1
+  69:	ba ab cd ef 	jmp sym2
+  6d:	bb 12 34 56 	jsr sym1
+  71:	ac fa 12 34 	dec.b sym1
+  75:	56 
+  76:	ad fa 12 34 	dec.w sym1
+  7a:	56 
+  7b:	af fa 12 34 	dec.l sym1
+  7f:	56 
+  80:	bc fa 12 34 	clr.b sym1
+  84:	56 
+  85:	bd fa 12 34 	clr.w sym1
+  89:	56 
+  8a:	bf fa 12 34 	clr.l sym1
+  8e:	56 
+  8f:	d3 12 34 56 	st d5, sym1
+  93:	cc fa 12 34 	com.b sym1
+  97:	56 
+  98:	cd fa 12 34 	com.w sym1
+  9c:	56 
+  9d:	cf fa 12 34 	com.l sym1
+  a1:	56 
+  a2:	dc fa 12 34 	neg.b sym1
+  a6:	56 
+  a7:	dd fa 12 34 	neg.w sym1
+  ab:	56 
+  ac:	df fa 12 34 	neg.l sym1
+  b0:	56 
+  b1:	f3 fa 12 34 	cmp d5, sym1
+  b5:	56 
+  b6:	1b 00 fa 12 	ld s, sym1
+  ba:	34 56 
+  bc:	1b 01 fa 12 	st s, sym1
+  c0:	34 56 
+  c2:	1b 02 fa 12 	cmp s, sym1
+  c6:	34 56 
+  c8:	1b 10 fa 12 	minu d2, sym1
+  cc:	34 56 
+  ce:	1b 18 fa 12 	maxu d2, sym1
+  d2:	34 56 
+  d4:	1b 20 fa 12 	mins d2, sym1
+  d8:	34 56 
+  da:	1b 28 fa 12 	maxs d2, sym1
+  de:	34 56 
+  e0:	1b 61 fa 12 	adc d3, sym1
+  e4:	34 56 
+  e6:	1b 69 fa 12 	bit d3, sym1
+  ea:	34 56 
+  ec:	1b 81 fa 12 	sbc d3, sym1
+  f0:	34 56 
+  f2:	1b 89 fa 12 	eor d3, sym1
+  f6:	34 56 
+  f8:	02 d1 fa 12 	brclr.b sym1, d1, \*\+3
+  fc:	34 56 03 
+  ff:	02 a2 fa 12 	brclr.w sym1, #2, \*\+4
+ 103:	34 56 04 
+ 106:	03 81 fa ab 	brset.b sym2, d2, \*\+5
+ 10a:	cd ef 05 
+ 10d:	03 b2 fa ab 	brset.w sym2, #3, \*\+6
+ 111:	cd ef 06 
+ 114:	4d 40 fa 12 	mulu.b d1, d2, sym1
+ 118:	34 56 
+ 11a:	4e 7e fa 12 	mulu.ll d6, sym1, sym2
+ 11e:	34 56 fa ab 
+ 122:	cd ef 
+ 124:	4d c0 fa 12 	muls.b d1, d2, sym1
+ 128:	34 56 
+ 12a:	4e fe fa 12 	muls.ll d6, sym1, sym2
+ 12e:	34 56 fa ab 
+ 132:	cd ef 
+ 134:	1b b5 c0 fa 	qmuls.b d1, d2, sym1
+ 138:	12 34 56 
+ 13b:	1b b6 fe fa 	qmuls.ll d6, sym1, sym2
+ 13f:	12 34 56 fa 
+ 143:	ab cd ef 
+ 146:	1b 35 40 fa 	divu.b d1, d2, sym1
+ 14a:	12 34 56 
+ 14d:	1b 36 7e fa 	divu.ll d6, sym1, sym2
+ 151:	12 34 56 fa 
+ 155:	ab cd ef 
+ 158:	1b 35 c0 fa 	divs.b d1, d2, sym1
+ 15c:	12 34 56 
+ 15f:	1b 36 fe fa 	divs.ll d6, sym1, sym2
+ 163:	12 34 56 fa 
+ 167:	ab cd ef 
+ 16a:	ec a0 fa 12 	bclr.b sym1, #2
+ 16e:	34 56 
+ 170:	ec 85 fa ab 	bclr.w sym2, d2
+ 174:	cd ef 
+ 176:	ed a0 fa 12 	bset.b sym1, #2
+ 17a:	34 56 
+ 17c:	ed 85 fa ab 	bset.w sym2, d2
+ 180:	cd ef 
+ 182:	ee a0 fa 12 	btgl.b sym1, #2
+ 186:	34 56 
+ 188:	ee 85 fa ab 	btgl.w sym2, d2
+ 18c:	cd ef 
+ 18e:	0b 0c fa 12 	tbne.b sym1, \*\+8
+ 192:	34 56 08 
+ 195:	0b ad fa ab 	dbpl.w sym2, \*\+9
+ 199:	cd ef 09 
+ 19c:	1b 08 c0 fa 	bfins.b d2, sym1, d2
+ 1a0:	12 34 56 
+ 1a3:	1b 08 d4 fa 	bfins.w sym1, d2, d2
+ 1a7:	12 34 56 
+ 1aa:	1b 08 e9 01 	bfins.p d2, sym1, #8\:1
+ 1ae:	fa 12 34 56 
+ 1b2:	1b 08 fd 01 	bfins.l sym1, d2, #8\:1
+ 1b6:	fa 12 34 56 
+ 1ba:	1b 08 40 fa 	bfext.b d2, sym1, d2
+ 1be:	12 34 56 
+ 1c1:	1b 08 54 fa 	bfext.w sym1, d2, d2
+ 1c5:	12 34 56 
+ 1c8:	1b 08 69 01 	bfext.p d2, sym1, #8\:1
+ 1cc:	fa 12 34 56 
+ 1d0:	1b 08 7c e2 	bfext.l sym1, d2, #7\:2
+ 1d4:	fa 12 34 56 
diff --git a/gas/testsuite/gas/s12z/opr-symbol.s b/gas/testsuite/gas/s12z/opr-symbol.s
new file mode 100644
index 0000000000..6ce2afb8e8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-symbol.s
@@ -0,0 +1,109 @@
+#sym1: set $123456
+
+#sym2: set $abcdef
+
+	.equiv sym1, 0x123456
+	.equiv sym2, 0xabcdef
+
+	mov.b #23, sym1
+	mov.w #23, sym1
+	mov.p #23, sym1
+	mov.l #23, sym1
+
+	mov.b sym1, sym2
+	mov.w sym1, sym2
+	mov.p sym1, sym2
+	mov.l sym1, sym2
+
+	add d1, sym1
+	and d2, sym1
+	sub d3, sym1
+	or  d4, sym1
+
+	inc.b  sym1
+	inc.w  sym1
+	inc.l  sym1
+
+	ld d4, sym1
+
+	jmp sym2
+	jsr sym1
+
+	dec.b  sym1
+	dec.w  sym1
+	dec.l  sym1
+
+	clr.b  sym1
+	clr.w  sym1
+	clr.l  sym1
+
+	st d5, sym1
+
+	com.b  sym1
+	com.w  sym1
+	com.l  sym1
+
+	neg.b  sym1
+	neg.w  sym1
+	neg.l  sym1
+
+	cmp d5, sym1
+
+	ld s, sym1
+	st s, sym1
+	cmp s, sym1
+
+	minu d2, sym1
+	maxu d2, sym1
+
+	mins d2, sym1
+	maxs d2, sym1
+
+	adc d3, sym1
+	bit d3, sym1
+	sbc d3, sym1
+	eor d3, sym1
+
+	brclr.b sym1, d1, *+3
+	brclr.w sym1, #2, *+4
+
+	brset.b sym2, d2, *+5
+	brset.w sym2, #3, *+6
+
+	mulu.b d1, d2, sym1
+	mulu.ll d6, sym1, sym2
+
+	muls.b d1, d2, sym1
+	muls.ll d6, sym1, sym2
+
+	qmuls.b d1, d2, sym1
+	qmuls.ll d6, sym1, sym2
+
+	divu.b d1, d2, sym1
+	divu.ll d6, sym1, sym2
+
+	divs.b d1, d2, sym1
+	divs.ll d6, sym1, sym2
+
+	bclr.b sym1, #2
+	bclr.w sym2, d2
+
+	bset.b sym1, #2
+	bset.w sym2, d2
+
+	btgl.b sym1, #2
+	btgl.w sym2, d2
+
+	tbne.b sym1, *+8
+	dbpl.w sym2, *+9
+
+	bfins.b d2, sym1, d2
+	bfins.w sym1, d2, d2
+	bfins.p d2, sym1, #8:1
+	bfins.l sym1, d2, #8:1
+
+	bfext.b d2, sym1, d2
+	bfext.w sym1, d2, d2
+	bfext.p d2, sym1, #8:1
+	bfext.l sym1, d2, #7:2
+
diff --git a/gas/testsuite/gas/s12z/or-imm.d b/gas/testsuite/gas/s12z/or-imm.d
new file mode 100644
index 0000000000..dbaa77ddf9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  or-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+   0:	78 12 34    	or d2, #4660
+   3:	79 12 34    	or d3, #4660
+   6:	7a fc 7a    	or d4, #-902
+   9:	7b 01 59    	or d5, #345
+   c:	7c 12       	or d0, #18
+   e:	7d 34       	or d1, #52
+  10:	7e 56 78 9a 	or d6, #1450744508
+  14:	bc 
+  15:	7f ff 43 9e 	or d7, #-12345678
+  19:	b2 
diff --git a/gas/testsuite/gas/s12z/or-imm.s b/gas/testsuite/gas/s12z/or-imm.s
new file mode 100644
index 0000000000..65585250a6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-imm.s
@@ -0,0 +1,8 @@
+start:	or d2, #0x1234
+	or d3, #0x1234
+	or d4, #-902
+	or d5, #345
+	or d0, #0x12
+	or d1, #0x34
+	or d6, #0x56789ABC
+	or d7, #-12345678
diff --git a/gas/testsuite/gas/s12z/or-opr.d b/gas/testsuite/gas/s12z/or-opr.d
new file mode 100644
index 0000000000..188bb654b8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-opr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  or-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	8c d5 21    	or d0, \[-223,y\]
+   3:	8d f2 00 84 	or d1, \(34000,p\)
+   7:	d0 
+   8:	88 c3       	or d2, \(-x\)
+   a:	89 f7       	or d3, \(y\+\)
+   c:	8a ba       	or d4, d4
+   e:	8b f8 77 d6 	or d5, 30678
+  12:	8e fe 01 64 	or d6, \[91256\]
+  16:	78 
+  17:	8f 9a       	or d7, \(d4,y\)
diff --git a/gas/testsuite/gas/s12z/or-opr.s b/gas/testsuite/gas/s12z/or-opr.s
new file mode 100644
index 0000000000..4dabcb6c62
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-opr.s
@@ -0,0 +1,8 @@
+	or d0, [-223,y]
+	or d1, (34000, p)
+	or d2, (-x)
+	or d3, (y+)
+	or d4,  d4
+	or d5,  30678
+	or d6,  [91256]
+	or d7,  (d4,y)
diff --git a/gas/testsuite/gas/s12z/p2-mul.d b/gas/testsuite/gas/s12z/p2-mul.d
new file mode 100644
index 0000000000..ce52171dde
--- /dev/null
+++ b/gas/testsuite/gas/s12z/p2-mul.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:    Multiply instructions from page2 in all reg-reg-reg mode
+#source:  p2-mul.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b b4 a9    	qmuls d0, d1, d3
+   3:	1b b2 1e    	qmulu d4, d5, d6
+   6:	1b 37 a5    	divs d7, d0, d1
+   9:	1b 30 0a    	divu d2, d3, d4
+   c:	1b 3b b7    	mods d5, d6, d7
+   f:	1b 3c 28    	modu d0, d1, d2
diff --git a/gas/testsuite/gas/s12z/p2-mul.s b/gas/testsuite/gas/s12z/p2-mul.s
new file mode 100644
index 0000000000..b9952e366b
--- /dev/null
+++ b/gas/testsuite/gas/s12z/p2-mul.s
@@ -0,0 +1,7 @@
+	qmuls d0, d1, d3
+	qmulu d4, d5, d6
+	divs  d7, d0, d1
+	divu  d2, d3, d4
+	mods  d5, d6, d7
+	modu  d0, d1, d2
+
diff --git a/gas/testsuite/gas/s12z/page2-inh.d b/gas/testsuite/gas/s12z/page2-inh.d
new file mode 100644
index 0000000000..0903fa7ac1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/page2-inh.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  page2-inh.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 90       	rti
+   2:	1b 07       	sys
+   4:	1b 05       	stop
+   6:	1b 06       	wai
diff --git a/gas/testsuite/gas/s12z/page2-inh.s b/gas/testsuite/gas/s12z/page2-inh.s
new file mode 100644
index 0000000000..0351ec61f1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/page2-inh.s
@@ -0,0 +1,5 @@
+	RTI
+	SYS
+	STOP
+	WAI
+
diff --git a/gas/testsuite/gas/s12z/psh-pul.d b/gas/testsuite/gas/s12z/psh-pul.d
new file mode 100644
index 0000000000..40113e7869
--- /dev/null
+++ b/gas/testsuite/gas/s12z/psh-pul.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  psh-pul.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <here>:
+   0:	04 00       	psh ALL
+   2:	04 40       	psh ALL16b
+   4:	04 3c       	psh cch, ccl, d0, d1
+   6:	04 43       	psh x, y
+
+00000008 <there>:
+   8:	04 80       	pul ALL
+   a:	04 c0       	pul ALL16b
+   c:	04 bc       	pul cch, ccl, d0, d1
+   e:	04 c3       	pul x, y
diff --git a/gas/testsuite/gas/s12z/psh-pul.s b/gas/testsuite/gas/s12z/psh-pul.s
new file mode 100644
index 0000000000..57a2d5930a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/psh-pul.s
@@ -0,0 +1,8 @@
+here:	psh all
+	psh all16b
+	psh cch, ccl, d1, d0
+	psh x, y
+there:	pul all
+	pul all16b
+	pul cch, ccl, d1, d0
+	pul x, y
diff --git a/gas/testsuite/gas/s12z/qmul.d b/gas/testsuite/gas/s12z/qmul.d
new file mode 100644
index 0000000000..6cd5af7fec
--- /dev/null
+++ b/gas/testsuite/gas/s12z/qmul.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  qmul.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b b4 ec 62 	qmuls.b d0, d1, #98
+   4:	1b b5 c0 b9 	qmuls.b d1, d2, d3
+   8:	1b b0 c9 ba 	qmuls.w d2, d3, d4
+   c:	1b b1 ff 00 	qmuls.l d3, d7, #9842
+  10:	00 26 72 
+  13:	1b b2 68 e0 	qmulu.b d4, d1, \(32,s\)
+  17:	20 
+  18:	1b b3 49 c4 	qmulu.w d5, d3, \[34,x\]
+  1c:	22 
+  1d:	1b b6 7b ff 	qmulu.l d6, d7, \(s\+\)
+  21:	1b b7 7a d4 	qmulu.lp d7, \[12,y\], \(7,d1\)
+  25:	0c 85 00 07 
diff --git a/gas/testsuite/gas/s12z/qmul.s b/gas/testsuite/gas/s12z/qmul.s
new file mode 100644
index 0000000000..6237d48ece
--- /dev/null
+++ b/gas/testsuite/gas/s12z/qmul.s
@@ -0,0 +1,8 @@
+	qmuls.b d0, d1, #98
+	qmuls.b d1, d2, d3
+	qmuls.w d2, d3, d4
+	qmuls.l d3, d7, #9842
+	qmulu.b d4, d1, (32,s)
+	qmulu.w d5, d3, [34,x]
+	qmulu.l d6, d7, (s+)
+	qmulu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/rotate.d b/gas/testsuite/gas/s12z/rotate.d
new file mode 100644
index 0000000000..a58eb9a637
--- /dev/null
+++ b/gas/testsuite/gas/s12z/rotate.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:    
+#source:  rotate.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	10 24 b8    	ror.b d2
+   3:	10 64 fb    	rol.b \(-s\)
+   6:	10 65 ff    	rol.w \(s\+\)
+   9:	10 66 d4 2d 	rol.p \[45,y\]
+   d:	10 67 87 00 	rol.l \(78,d7\)
+  11:	4e 
+  12:	10 24 bc    	ror.b d0
+  15:	10 24 c3    	ror.b \(-x\)
+  18:	10 25 f7    	ror.w \(y\+\)
+  1b:	10 26 f4 29 	ror.p \[41,p\]
+  1f:	10 27 8b    	ror.l \(d5,x\)
diff --git a/gas/testsuite/gas/s12z/rotate.s b/gas/testsuite/gas/s12z/rotate.s
new file mode 100644
index 0000000000..91e3f6d1a3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/rotate.s
@@ -0,0 +1,10 @@
+	ror   d2
+	rol.b (-s)
+	rol.w (s+)
+	rol.p [45,y]
+	rol.l (78, d7)
+	ror   d0
+	ror.b (-x)
+	ror.w (y+)
+	ror.p [41,p]
+	ror.l (d5, x)
diff --git a/gas/testsuite/gas/s12z/s12z.exp b/gas/testsuite/gas/s12z/s12z.exp
new file mode 100644
index 0000000000..acd50cf4d3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/s12z.exp
@@ -0,0 +1,132 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  
+
+#
+# Some s12z  tests
+#
+if { ![istarget "s12z*-*-*"] } then {
+    return
+}
+
+
+run_dump_test abs
+run_dump_test adc-imm
+run_dump_test adc-opr
+run_dump_test add-imm
+run_dump_test add-opr
+run_dump_test and-imm
+run_dump_test and-opr
+run_dump_test and-or-cc
+run_dump_test bfext-special
+run_dump_test bfext
+run_dump_test bit-manip
+run_dump_test bit
+run_dump_test bra
+run_dump_test brset-clr-opr-imm-rel
+run_dump_test brset-clr-opr-reg-rel
+run_dump_test brset-clr-reg-imm-rel
+run_dump_test brset-clr-reg-reg-rel
+run_dump_test clb
+run_dump_test clr-opr
+run_dump_test clr
+run_dump_test cmp-imm
+run_dump_test cmp-opr-inc
+run_dump_test cmp-opr-rdirect
+run_dump_test cmp-opr-reg
+run_dump_test cmp-opr-rindirect
+run_dump_test cmp-opr-sxe4
+run_dump_test cmp-opr-xys
+run_dump_test cmp-s-imm
+run_dump_test cmp-s-opr
+run_dump_test cmp-xy
+run_dump_test com-opr
+run_dump_test complex-shifts
+run_dump_test db-tb-cc-opr
+run_dump_test db-tb-cc-reg
+run_dump_test dec-opr
+run_dump_test dec
+run_dump_test div
+run_dump_test eor
+run_dump_test exg
+run_dump_test inc-opr
+run_dump_test inc
+run_dump_test inh
+run_dump_test jmp
+run_dump_test jsr
+run_dump_test ld-imm-page2
+run_dump_test ld-imm
+run_dump_test ld-opr
+run_dump_test ld-s-opr
+run_dump_test lea
+run_dump_test mac
+run_dump_test min-max
+run_dump_test mod
+run_dump_test mov
+run_dump_test p2-mul
+run_dump_test mul-imm
+run_dump_test mul-opr-opr
+run_dump_test mul-opr
+run_dump_test mul-reg
+run_dump_test mul
+run_dump_test neg-opr
+run_dump_test not-so-simple-shifts
+run_dump_test opr-18u
+run_dump_test opr-ext-18
+run_dump_test opr-idx-24-reg
+run_dump_test opr-idx3-reg
+run_dump_test opr-idx3-xysp-24
+run_dump_test or-imm
+run_dump_test or-opr
+run_dump_test page2-inh
+run_dump_test psh-pul
+run_dump_test qmul
+run_dump_test rotate
+run_dump_test sat
+run_dump_test sbc-imm
+run_dump_test sbc-opr
+run_dump_test shift
+run_dump_test simple-shift
+run_dump_test single-ops
+run_dump_test st-opr
+run_dump_test st-s-opr
+run_dump_test sub-imm
+run_dump_test sub-opr
+run_dump_test tfr
+run_dump_test trap
+run_dump_test specd6
+
+# Tests of the disassembler - these are hard to force the assembler to generate
+run_dump_test ld-immu18
+run_dump_test lea-immu18
+run_dump_test ext24-ld-xy
+run_dump_test st-xy
+
+# Symbol related tests
+run_dump_test opr-symbol
+run_dump_test brclr-symbols
+run_dump_test dbCC
+
+# Expression related tests
+run_dump_test opr-expr
+run_dump_test opr-indirect-expr
+run_dump_test bra-expression-defined
+run_dump_test bra-expression-undef
+
+# Tests related to optimisation
+run_dump_test ld-large-direct
+run_dump_test ld-small-direct
+run_dump_test st-large-direct
+run_dump_test st-small-direct
diff --git a/gas/testsuite/gas/s12z/sat.d b/gas/testsuite/gas/s12z/sat.d
new file mode 100644
index 0000000000..4cbac0ba97
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sat.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:    
+#source:  sat.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b a0       	sat d2
+   2:	1b a1       	sat d3
+   4:	1b a2       	sat d4
+   6:	1b a3       	sat d5
+   8:	1b a4       	sat d0
+   a:	1b a5       	sat d1
+   c:	1b a6       	sat d6
+   e:	1b a7       	sat d7
diff --git a/gas/testsuite/gas/s12z/sat.s b/gas/testsuite/gas/s12z/sat.s
new file mode 100644
index 0000000000..ba2ff8eed1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sat.s
@@ -0,0 +1,8 @@
+	sat d2
+	sat d3
+	sat d4
+	sat d5
+	sat d0
+	sat d1
+	sat d6
+	sat d7
diff --git a/gas/testsuite/gas/s12z/sbc-imm.d b/gas/testsuite/gas/s12z/sbc-imm.d
new file mode 100644
index 0000000000..1bca708ff1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  sbc-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 70 12 34 	sbc d2, #4660
+   4:	1b 71 12 34 	sbc d3, #4660
+   8:	1b 72 12 34 	sbc d4, #4660
+   c:	1b 73 12 34 	sbc d5, #4660
+  10:	1b 74 ef    	sbc d0, #-17
+  13:	1b 75 34    	sbc d1, #52
+  16:	1b 76 56 78 	sbc d6, #1450744508
+  1a:	9a bc 
+  1c:	1b 77 98 77 	sbc d7, #-1737025662
+  20:	17 82 
diff --git a/gas/testsuite/gas/s12z/sbc-imm.s b/gas/testsuite/gas/s12z/sbc-imm.s
new file mode 100644
index 0000000000..9879e33eb9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-imm.s
@@ -0,0 +1,8 @@
+	sbc d2, #0x1234
+	sbc d3, #0x1234
+	sbc d4, #0x1234
+	sbc d5, #0x1234
+	sbc d0, #-17
+	sbc d1, #0x34
+	sbc d6, #0x56789ABC
+	sbc d7, #-1737025662
diff --git a/gas/testsuite/gas/s12z/sbc-opr.d b/gas/testsuite/gas/s12z/sbc-opr.d
new file mode 100644
index 0000000000..bd5ed4982a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-opr.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:    
+#source:  sbc-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 84 d5 21 	sbc d0, \[-223,y\]
+   4:	1b 85 f2 00 	sbc d1, \(34000,p\)
+   8:	84 d0 
+   a:	1b 80 fb    	sbc d2, \(-s\)
+   d:	1b 71 00 22 	sbc d3, #34
+  11:	1b 82 bc    	sbc d4, d0
+  14:	1b 83 0a 76 	sbc d5, 2678
+  18:	1b 86 fe 00 	sbc d6, \[56\]
+  1c:	00 38 
+  1e:	1b 87 9b    	sbc d7, \(d5,y\)
+  21:	1b 81 85 00 	sbc d3, \(34,d1\)
+  25:	22 
diff --git a/gas/testsuite/gas/s12z/sbc-opr.s b/gas/testsuite/gas/s12z/sbc-opr.s
new file mode 100644
index 0000000000..3202174cf8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-opr.s
@@ -0,0 +1,9 @@
+	sbc d0, [-223,y]
+	sbc d1, (34000, p)
+	sbc d2, (-s)
+	sbc d3, #34
+	sbc d4, d0
+	sbc d5, 2678
+	sbc d6, [56]
+	sbc d7, (d5,y)
+	sbc d3, (34, d1)
diff --git a/gas/testsuite/gas/s12z/shift.d b/gas/testsuite/gas/s12z/shift.d
new file mode 100644
index 0000000000..41e061f998
--- /dev/null
+++ b/gas/testsuite/gas/s12z/shift.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:    
+#source:  shift.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	14 11 bb    	lsr d0, d3, d5
+   3:	15 9a 76    	asr d1, d4, #13
+   6:	15 84       	asr d1, d0, #1
+   8:	17 68 fb    	lsl.b d7, \(-s\), #2
+   b:	17 69 fb    	lsl.w d7, \(-s\), #2
+   e:	17 6b fb    	lsl.l d7, \(-s\), #2
+  11:	17 2a fb    	lsr.p d7, \(-s\), #2
+  14:	10 3d f3    	lsr.w \(\+y\), #2
+  17:	10 3e 8e    	lsr.p \(d6,x\), #2
+  1a:	10 f4 bf    	asl d7, #1
+  1d:	10 bc bd    	asr d1, #2
diff --git a/gas/testsuite/gas/s12z/shift.s b/gas/testsuite/gas/s12z/shift.s
new file mode 100644
index 0000000000..cb41f3c030
--- /dev/null
+++ b/gas/testsuite/gas/s12z/shift.s
@@ -0,0 +1,11 @@
+	lsr   d0, d3, d5
+	asr   d1, d4, #13
+	asr   d1, d0, #1
+	lsl.b d7, (-s), #2
+	lsl.w d7, (-s), #2
+	lsl.l d7, (-s), #2
+	lsr.p d7, (-s), #2
+	lsr.w (+y), #2
+	lsr.p (d6,x), #2
+	asl   d7, #1
+	asr   d1, #2
diff --git a/gas/testsuite/gas/s12z/simple-shift.d b/gas/testsuite/gas/s12z/simple-shift.d
new file mode 100644
index 0000000000..13af3bf9f0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/simple-shift.d
@@ -0,0 +1,18 @@
+#objdump: -d
+#name:    
+#source:  simple-shift.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	14 55 b8    	lsl d0, d1, d2
+   3:	11 12 bb    	lsr d3, d4, d5
+   6:	17 d4 bd    	asl d7, d0, d1
+   9:	10 91 ba    	asr d2, d3, d4
+   c:	16 d5 b8    	asl d6, d1, d2
+   f:	15 5a 76    	lsl d1, d4, #13
+  12:	13 46       	lsl d5, d6, #1
diff --git a/gas/testsuite/gas/s12z/simple-shift.s b/gas/testsuite/gas/s12z/simple-shift.s
new file mode 100644
index 0000000000..045e0718f7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/simple-shift.s
@@ -0,0 +1,9 @@
+        lsl d0, d1, d2
+        lsr d3, d4, d5
+        asl d7, d0, d1
+        asr d2, d3, d4
+	asl d6, d1, d2
+
+        lsl d1, d4, #13
+        lsl d5, d6, #1 ; this creates a short form
+
diff --git a/gas/testsuite/gas/s12z/single-ops.d b/gas/testsuite/gas/s12z/single-ops.d
new file mode 100644
index 0000000000..ca9b38a40f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/single-ops.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:    
+#source:  single-ops.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	01          	nop
+   1:	05          	rts
+   2:	00          	bgnd
+   3:	ff          	swi
diff --git a/gas/testsuite/gas/s12z/single-ops.s b/gas/testsuite/gas/s12z/single-ops.s
new file mode 100644
index 0000000000..ab6fe2ceb2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/single-ops.s
@@ -0,0 +1,4 @@
+	nop
+	rts
+	bgnd
+	swi
diff --git a/gas/testsuite/gas/s12z/specd6.d b/gas/testsuite/gas/s12z/specd6.d
new file mode 100644
index 0000000000..0c743cd9d9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/specd6.d
@@ -0,0 +1,14 @@
+#objdump: -d
+#name:    
+#source:  specd6.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	fc          	cmp x, y
+   1:	fd          	sub d6, x, y
+   2:	fe          	sub d6, y, x
diff --git a/gas/testsuite/gas/s12z/specd6.s b/gas/testsuite/gas/s12z/specd6.s
new file mode 100644
index 0000000000..92308b4dcd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/specd6.s
@@ -0,0 +1,4 @@
+        cmp x, y
+        sub d6, x, y
+        sub d6, y, x
+
diff --git a/gas/testsuite/gas/s12z/st-large-direct.d b/gas/testsuite/gas/s12z/st-large-direct.d
new file mode 100644
index 0000000000..03ca41e904
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-large-direct.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    ST reg - constant optimised to EXT24
+#source:  st-large-direct.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	d0 12 34 56 	st d2, 1193046
+   4:	d1 c0 ff ee 	st d3, 12648430
+   8:	d2 80 00 02 	st d4, 8388610
+   c:	d4 80 00 03 	st d0, 8388611
+  10:	d5 80 00 03 	st d1, 8388611
+  14:	d3 80 00 04 	st d5, 8388612
+  18:	d6 80 00 06 	st d6, 8388614
+  1c:	d7 80 00 07 	st d7, 8388615
+  20:	d8 80 00 08 	st x, 8388616
+  24:	d9 80 00 09 	st y, 8388617
diff --git a/gas/testsuite/gas/s12z/st-large-direct.s b/gas/testsuite/gas/s12z/st-large-direct.s
new file mode 100644
index 0000000000..74956d1417
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-large-direct.s
@@ -0,0 +1,11 @@
+	st d2, 0x123456
+	st d3, 0xc0ffee
+	st d4, 0x800002
+	st d0, 0x800003
+	st d1, 0x800003
+	st d5, 0x800004
+	st d6, 0x800006
+	st d7, 0x800007
+	st x,  0x800008
+	st y,  0x800009
+
diff --git a/gas/testsuite/gas/s12z/st-opr.d b/gas/testsuite/gas/s12z/st-opr.d
new file mode 100644
index 0000000000..d39bb62ab0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:    
+#source:  st-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	c4 d8       	st d0, \[d2,y\]
+   2:	c5 c9       	st d1, \[d3,x\]
+   4:	c0 ca       	st d2, \[d4,x\]
+   6:	c1 87 3b 82 	st d3, \(15234,d7\)
+   a:	c2 e1 16    	st d4, \(-234,s\)
+   d:	c3 bc       	st d5, d0
+   f:	c6 88       	st d6, \(d2,x\)
+  11:	c7 fe 00 04 	st d7, \[1234\]
+  15:	d2 
+  16:	c8 88       	st x, \(d2,x\)
+  18:	c9 db       	st y, \[d5,y\]
diff --git a/gas/testsuite/gas/s12z/st-opr.s b/gas/testsuite/gas/s12z/st-opr.s
new file mode 100644
index 0000000000..c5257a5b1a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-opr.s
@@ -0,0 +1,10 @@
+	st d0, [d2,y]
+	st d1, [d3,x]
+	st d2, [d4,x]
+	st d3, (15234,d7)
+	st d4, (-234,s)
+	st d5, d0
+	st d6, (d2, x)
+	st d7, [1234]
+	st x,  (d2, x)
+	st y,  [d5, y]
diff --git a/gas/testsuite/gas/s12z/st-s-opr.d b/gas/testsuite/gas/s12z/st-s-opr.d
new file mode 100644
index 0000000000..3748914a34
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-s-opr.d
@@ -0,0 +1,16 @@
+#objdump: -d
+#name:    
+#source:  st-s-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 01 aa    	st s, \(d4,s\)
+   3:	1b 01 fe 00 	st s, \[1340\]
+   7:	05 3c 
+   9:	1b 01 9b    	st s, \(d5,y\)
+   c:	1b 01 d3    	st s, \(-y\)
diff --git a/gas/testsuite/gas/s12z/st-s-opr.s b/gas/testsuite/gas/s12z/st-s-opr.s
new file mode 100644
index 0000000000..90cc5e8072
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-s-opr.s
@@ -0,0 +1,4 @@
+	st s,  (d4, s)
+	st s,  [1340]
+	st s,  (d5, y)
+	st s,  (-y)
diff --git a/gas/testsuite/gas/s12z/st-small-direct.d b/gas/testsuite/gas/s12z/st-small-direct.d
new file mode 100644
index 0000000000..df67d4adeb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-small-direct.d
@@ -0,0 +1,34 @@
+#objdump: -d
+#name:    ST reg - small constants left in OPR mode
+#source:  st-small-direct.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	c0 fa 00 00 	st d2, L1
+   4:	00 
+   5:	c1 fa 00 00 	st d3, L2
+   9:	1a 
+   a:	c2 fa 00 00 	st d4, L1
+   e:	00 
+
+0000000f <L3>:
+   f:	01          	nop
+  10:	c4 fa 00 00 	st d0, L2
+  14:	1a 
+  15:	c5 fa 00 00 	st d1, L3
+  19:	0f 
+
+0000001a <L2>:
+  1a:	c3 fa 00 00 	st d5, L1
+  1e:	00 
+  1f:	c6 fa 00 00 	st d6, L3
+  23:	0f 
+  24:	c7 fa 00 00 	st d7, L2
+  28:	1a 
+  29:	c8 30 39    	st x, 12345
+  2c:	c9 26 94    	st y, 9876
diff --git a/gas/testsuite/gas/s12z/st-small-direct.s b/gas/testsuite/gas/s12z/st-small-direct.s
new file mode 100644
index 0000000000..c0d736ddf7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-small-direct.s
@@ -0,0 +1,12 @@
+L1:	st d2, L1
+	st d3, L2
+	st d4, L1
+L3:	nop
+	st d0, L2
+	st d1, L3
+L2:	st d5, L1
+	st d6, L3
+	st d7, L2
+	st x,  12345
+	st y,  9876
+
diff --git a/gas/testsuite/gas/s12z/st-xy.d b/gas/testsuite/gas/s12z/st-xy.d
new file mode 100644
index 0000000000..335e77eee4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-xy.d
@@ -0,0 +1,12 @@
+#objdump: -d
+#name:    
+#source:  st-xy.s
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	d8 90 12 34 	st x, 9441844
+   4:	d9 80 12 34 	st y, 8393268
diff --git a/gas/testsuite/gas/s12z/st-xy.s b/gas/testsuite/gas/s12z/st-xy.s
new file mode 100644
index 0000000000..6e774657a1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-xy.s
@@ -0,0 +1,3 @@
+	.long 0xD8901234	;;  ST        X,9441844
+	.long 0xD9801234        ;;  ST        Y,8393268
+
diff --git a/gas/testsuite/gas/s12z/sub-imm.d b/gas/testsuite/gas/s12z/sub-imm.d
new file mode 100644
index 0000000000..7c1064ab6a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:    
+#source:  sub-imm.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+   0:	70 12 34    	sub d2, #4660
+   3:	71 12 34    	sub d3, #4660
+   6:	72 12 34    	sub d4, #4660
+   9:	73 12 34    	sub d5, #4660
+   c:	74 ef       	sub d0, #-17
+   e:	75 34       	sub d1, #52
+  10:	76 56 78 9a 	sub d6, #1450744508
+  14:	bc 
+  15:	77 98 77 17 	sub d7, #-1737025662
+  19:	82 
diff --git a/gas/testsuite/gas/s12z/sub-imm.s b/gas/testsuite/gas/s12z/sub-imm.s
new file mode 100644
index 0000000000..1b4f38c479
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-imm.s
@@ -0,0 +1,8 @@
+start:	sub d2, #0x1234
+	sub d3, #0x1234
+	sub d4, #0x1234
+	sub d5, #0x1234
+	sub d0, #-17
+	sub d1, #0x34
+	sub d6, #0x56789ABC
+	sub d7, #-1737025662
diff --git a/gas/testsuite/gas/s12z/sub-opr.d b/gas/testsuite/gas/s12z/sub-opr.d
new file mode 100644
index 0000000000..e98e26cb67
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:    
+#source:  sub-opr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	84 d5 21    	sub d0, \[-223,y\]
+   3:	85 f2 00 84 	sub d1, \(34000,p\)
+   7:	d0 
+   8:	80 fb       	sub d2, \(-s\)
+   a:	71 00 04    	sub d3, #4
+   d:	82 bc       	sub d4, d0
+   f:	83 f9 4e ae 	sub d5, 85678
+  13:	86 fe 00 4b 	sub d6, \[19256\]
+  17:	38 
+  18:	87 8a       	sub d7, \(d4,x\)
+  1a:	81 81 00 0b 	sub d3, \(11,d3\)
\ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/sub-opr.s b/gas/testsuite/gas/s12z/sub-opr.s
new file mode 100644
index 0000000000..f1f7b54121
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-opr.s
@@ -0,0 +1,9 @@
+	sub d0, [-223,y]
+	sub d1, (34000, p)
+	sub d2, (-s)
+	sub d3, #4
+	sub d4,  d0
+	sub d5,  85678
+	sub d6,  [19256]
+	sub d7,  (d4,x)
+	sub d3, (11, d3)
diff --git a/gas/testsuite/gas/s12z/tfr.d b/gas/testsuite/gas/s12z/tfr.d
new file mode 100644
index 0000000000..58c7642465
--- /dev/null
+++ b/gas/testsuite/gas/s12z/tfr.d
@@ -0,0 +1,20 @@
+#objdump: -d
+#name:    The TFR (incl ZEX) instruction
+#source:  tfr.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+   0:	9e 45       	tfr d0, d1
+   2:	9e 58       	tfr d1, x
+   4:	9e 0a       	tfr d2, s
+   6:	9e 0d       	tfr d2, ccl
+   8:	9e 6e       	tfr d6, ccw
+   a:	9e 29       	tfr d4, y
+   c:	9e 37       	tfr d5, d7
+   e:	9e 5e       	tfr d1, ccw
+  10:	9e 40       	tfr d0, d2
diff --git a/gas/testsuite/gas/s12z/tfr.s b/gas/testsuite/gas/s12z/tfr.s
new file mode 100644
index 0000000000..c61551ee6c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/tfr.s
@@ -0,0 +1,9 @@
+L1:	tfr d0,d1 
+	tfr d1, x
+	tfr d2, s
+	tfr d2, ccl
+	tfr d6, ccw
+	tfr d4, y
+	zex d5, d7
+	zex d1, ccw
+	zex d0, d2
diff --git a/gas/testsuite/gas/s12z/trap.d b/gas/testsuite/gas/s12z/trap.d
new file mode 100644
index 0000000000..bf6961346d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/trap.d
@@ -0,0 +1,105 @@
+#objdump: -d
+#name:    
+#source:  trap.s
+
+
+dump.o:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+   0:	1b 92       	trap #146
+   2:	1b 93       	trap #147
+   4:	1b 94       	trap #148
+   6:	1b 95       	trap #149
+   8:	1b 96       	trap #150
+   a:	1b 97       	trap #151
+   c:	1b 98       	trap #152
+   e:	1b 99       	trap #153
+  10:	1b 9a       	trap #154
+  12:	1b 9b       	trap #155
+  14:	1b 9c       	trap #156
+  16:	1b 9d       	trap #157
+  18:	1b 9e       	trap #158
+  1a:	1b 9f       	trap #159
+  1c:	1b a8       	trap #168
+  1e:	1b a9       	trap #169
+  20:	1b aa       	trap #170
+  22:	1b ab       	trap #171
+  24:	1b ac       	trap #172
+  26:	1b ad       	trap #173
+  28:	1b ae       	trap #174
+  2a:	1b af       	trap #175
+  2c:	1b b8       	trap #184
+  2e:	1b b9       	trap #185
+  30:	1b ba       	trap #186
+  32:	1b bb       	trap #187
+  34:	1b bc       	trap #188
+  36:	1b bd       	trap #189
+  38:	1b be       	trap #190
+  3a:	1b bf       	trap #191
+  3c:	1b c0       	trap #192
+  3e:	1b c1       	trap #193
+  40:	1b c2       	trap #194
+  42:	1b c3       	trap #195
+  44:	1b c4       	trap #196
+  46:	1b c5       	trap #197
+  48:	1b c6       	trap #198
+  4a:	1b c7       	trap #199
+  4c:	1b c8       	trap #200
+  4e:	1b c9       	trap #201
+  50:	1b ca       	trap #202
+  52:	1b cb       	trap #203
+  54:	1b cc       	trap #204
+  56:	1b cd       	trap #205
+  58:	1b ce       	trap #206
+  5a:	1b cf       	trap #207
+  5c:	1b d0       	trap #208
+  5e:	1b d1       	trap #209
+  60:	1b d2       	trap #210
+  62:	1b d3       	trap #211
+  64:	1b d4       	trap #212
+  66:	1b d5       	trap #213
+  68:	1b d6       	trap #214
+  6a:	1b d7       	trap #215
+  6c:	1b d8       	trap #216
+  6e:	1b d9       	trap #217
+  70:	1b da       	trap #218
+  72:	1b db       	trap #219
+  74:	1b dc       	trap #220
+  76:	1b dd       	trap #221
+  78:	1b de       	trap #222
+  7a:	1b df       	trap #223
+  7c:	1b e0       	trap #224
+  7e:	1b e1       	trap #225
+  80:	1b e2       	trap #226
+  82:	1b e3       	trap #227
+  84:	1b e4       	trap #228
+  86:	1b e5       	trap #229
+  88:	1b e6       	trap #230
+  8a:	1b e7       	trap #231
+  8c:	1b e8       	trap #232
+  8e:	1b e9       	trap #233
+  90:	1b ea       	trap #234
+  92:	1b eb       	trap #235
+  94:	1b ec       	trap #236
+  96:	1b ed       	trap #237
+  98:	1b ee       	trap #238
+  9a:	1b ef       	trap #239
+  9c:	1b f0       	trap #240
+  9e:	1b f1       	trap #241
+  a0:	1b f2       	trap #242
+  a2:	1b f3       	trap #243
+  a4:	1b f4       	trap #244
+  a6:	1b f5       	trap #245
+  a8:	1b f6       	trap #246
+  aa:	1b f7       	trap #247
+  ac:	1b f8       	trap #248
+  ae:	1b f9       	trap #249
+  b0:	1b fa       	trap #250
+  b2:	1b fb       	trap #251
+  b4:	1b fc       	trap #252
+  b6:	1b fd       	trap #253
+  b8:	1b fe       	trap #254
+  ba:	1b ff       	trap #255
diff --git a/gas/testsuite/gas/s12z/trap.s b/gas/testsuite/gas/s12z/trap.s
new file mode 100644
index 0000000000..7ea72bb6f8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/trap.s
@@ -0,0 +1,96 @@
+   trap #146
+   trap #147
+   trap #148
+   trap #149
+   trap #150
+   trap #151
+   trap #152
+   trap #153
+   trap #154
+   trap #155
+   trap #156
+   trap #157
+   trap #158
+   trap #159
+
+   trap #168
+   trap #169
+   trap #170
+   trap #171
+   trap #172
+   trap #173
+   trap #174
+   trap #175
+
+   trap #184
+   trap #185
+   trap #186
+   trap #187
+   trap #188
+   trap #189
+   trap #190
+   trap #191
+   trap #192
+   trap #193
+   trap #194
+   trap #195
+   trap #196
+   trap #197
+   trap #198
+   trap #199
+   trap #200
+   trap #201
+   trap #202
+   trap #203
+   trap #204
+   trap #205
+   trap #206
+   trap #207
+   trap #208
+   trap #209
+   trap #210
+   trap #211
+   trap #212
+   trap #213
+   trap #214
+   trap #215
+   trap #216
+   trap #217
+   trap #218
+   trap #219
+   trap #220
+   trap #221
+   trap #222
+   trap #223
+   trap #224
+   trap #225
+   trap #226
+   trap #227
+   trap #228
+   trap #229
+   trap #230
+   trap #231
+   trap #232
+   trap #233
+   trap #234
+   trap #235
+   trap #236
+   trap #237
+   trap #238
+   trap #239
+   trap #240
+   trap #241
+   trap #242
+   trap #243
+   trap #244
+   trap #245
+   trap #246
+   trap #247
+   trap #248
+   trap #249
+   trap #250
+   trap #251
+   trap #252
+   trap #253
+   trap #254
+   trap #255
diff --git a/include/elf/s12z.h b/include/elf/s12z.h
new file mode 100644
index 0000000000..72504ee9f4
--- /dev/null
+++ b/include/elf/s12z.h
@@ -0,0 +1,36 @@
+/* s12z ELF support for BFD.
+   Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _ELF_S12Z_H
+#define _ELF_S12Z_H
+
+#include "elf/reloc-macros.h"
+
+/* Relocation types.  */
+START_RELOC_NUMBERS (elf_s12z_reloc_type)
+  RELOC_NUMBER (R_S12Z_NONE, 0)
+  RELOC_NUMBER (R_S12Z_OPR, 1)
+  RELOC_NUMBER (R_S12Z_UKNWN_2, 2)
+  RELOC_NUMBER (R_S12Z_PCREL_7_15, 3)
+  RELOC_NUMBER (R_S12Z_EXT24, 4)
+  RELOC_NUMBER (R_S12Z_UKNWN_3, 5)
+  RELOC_NUMBER (R_S12Z_EXT32, 6)
+END_RELOC_NUMBERS (R_S12Z_max)
+
+#endif
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 8e4c8774d1..151e1e200a 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -324,6 +324,7 @@ ALL_EMULATION_SOURCES = \
 	em68hc12elfb.c \
 	em68kelf.c \
 	em68kelfnbsd.c \
+	em9s12zelf.c \
 	emcorepe.c \
 	emn10200.c \
 	emn10300.c \
@@ -1433,6 +1434,10 @@ em68kelfnbsd.c: $(srcdir)/emulparams/m68kelfnbsd.sh \
   $(ELF_DEPS) $(srcdir)/emultempl/m68kelf.em \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
+em9s12zelf.c: $(srcdir)/emulparams/m9s12zelf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/generic.em \
+  $(srcdir)/scripttempl/elfm9s12z.sc ${GEN_DEPENDS}
+
 emcorepe.c: $(srcdir)/emulparams/mcorepe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 
diff --git a/ld/Makefile.in b/ld/Makefile.in
index afd2a4bb88..5cfd4ab0fb 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -693,6 +693,7 @@ ALL_EMULATION_SOURCES = \
 	em68hc12elfb.c \
 	em68kelf.c \
 	em68kelfnbsd.c \
+	em9s12zelf.c \
 	emcorepe.c \
 	emn10200.c \
 	emn10300.c \
@@ -1305,6 +1306,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc12elfb.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelfnbsd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em9s12zelf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emcorepe.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@
@@ -2938,6 +2940,10 @@ em68kelfnbsd.c: $(srcdir)/emulparams/m68kelfnbsd.sh \
   $(ELF_DEPS) $(srcdir)/emultempl/m68kelf.em \
   $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
 
+em9s12zelf.c: $(srcdir)/emulparams/m9s12zelf.sh \
+  $(ELF_DEPS) $(srcdir)/emultempl/generic.em \
+  $(srcdir)/scripttempl/elfm9s12z.sc ${GEN_DEPENDS}
+
 emcorepe.c: $(srcdir)/emulparams/mcorepe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 4c4ab850f2..3386c3d928 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -402,6 +402,8 @@ m68hc12-*-*|m6812-*-*)	targ_emul=m68hc12elf
 			targ_extra_emuls="m68hc12elfb m68hc11elf m68hc11elfb" ;;
 m68*-*-netbsdelf*)	targ_emul=m68kelfnbsd ;;
 m68*-*-*)		targ_emul=m68kelf ;;
+s12z-*-*)		targ_emul=m9s12zelf
+			;;
 mcore-*-pe)		targ_emul=mcorepe ;
 			targ_extra_ofiles="deffilep.o pe-dll.o" ;;
 mcore-*-elf)		targ_emul=elf32mcore
diff --git a/ld/emulparams/m9s12zelf.sh b/ld/emulparams/m9s12zelf.sh
new file mode 100644
index 0000000000..7a819e8409
--- /dev/null
+++ b/ld/emulparams/m9s12zelf.sh
@@ -0,0 +1,18 @@
+MACHINE=
+SCRIPT_NAME=elfm9s12z
+OUTPUT_FORMAT="elf32-s12z"
+ROM_TOP=0xFFFFFF
+ROM_SIZE=0x20000
+RAM_START_ADDR=0x001000
+RAM_SIZE=8192
+EEPROM_START_ADDR=0x100000
+EEPROM_SIZE=2048
+TEXT_MEMORY=text
+DATA_MEMORY=data
+EEPROM_MEMORY=eeprom
+ARCH=s12z
+EMBEDDED=yes
+GENERIC_BOARD=no
+TEMPLATE_NAME=elf32
+NOP=0x00
+
diff --git a/ld/scripttempl/elfm9s12z.sc b/ld/scripttempl/elfm9s12z.sc
new file mode 100644
index 0000000000..c39d2708af
--- /dev/null
+++ b/ld/scripttempl/elfm9s12z.sc
@@ -0,0 +1,444 @@
+# Copyright (C) 2014-2018 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+# Unusual variables checked by this code:
+#	NOP - four byte opcode for no-op (defaults to 0)
+#	DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
+#	OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
+#		(e.g., .PARISC.global)
+#	OTHER_SECTIONS - at the end
+#	EXECUTABLE_SYMBOLS - symbols that must be defined for an
+#		executable (e.g., _DYNAMIC_LINK)
+#	TEXT_START_SYMBOLS - symbols that appear at the start of the
+#		.text section.
+#	DATA_START_SYMBOLS - symbols that appear at the start of the
+#		.data section.
+#	OTHER_BSS_SYMBOLS - symbols that appear at the start of the
+#		.bss section besides __bss_start.
+#	EMBEDDED - whether this is for an embedded system.
+#
+# When adding sections, do note that the names of some sections are used
+# when specifying the start address of the next.
+#
+test -z "$ENTRY" && ENTRY=_start
+test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
+test "$LD_FLAG" = "N" && DATA_ADDR=.
+
+CTOR=".ctors ${CONSTRUCTING-0} :
+  {
+    ${CONSTRUCTING+ PROVIDE (__CTOR_LIST__ = .); }
+    ${CONSTRUCTING+${CTOR_START}}
+    KEEP (*(.ctors))
+
+    ${CONSTRUCTING+${CTOR_END}}
+    ${CONSTRUCTING+ PROVIDE(__CTOR_END__ = .); }
+  } ${RELOCATING+ > ${TEXT_MEMORY}}"
+
+DTOR="  .dtors	${CONSTRUCTING-0} :
+  {
+    ${CONSTRUCTING+ PROVIDE(__DTOR_LIST__ = .); }
+    KEEP (*(.dtors))
+    ${CONSTRUCTING+ PROVIDE(__DTOR_END__ = .); }
+  } ${RELOCATING+ > ${TEXT_MEMORY}}"
+
+
+VECTORS="
+  /* If the 'vectors_addr' symbol is defined, it indicates the start address
+     of interrupt vectors.
+
+     In general, the vectors address is 0xfffe00.  This can be overriden
+     with the '-defsym vectors_addr=0xbfc000' ld option.  If you do this,
+     then your startup code should also set the IVBR register accordingly.
+  */
+
+  PROVIDE (_vectors_addr = DEFINED (vectors_addr) ? vectors_addr : 0xfffe00);
+  .vectors DEFINED (vectors_addr) ? vectors_addr : 0xfffe00 :
+  {
+    KEEP (*(.vectors))
+  }"
+
+#
+# We provide two emulations: a fixed on that defines some memory banks
+# and a configurable one that includes a user provided memory definition.
+#
+case $GENERIC_BOARD in
+  yes|1|YES)
+	MEMORY_DEF="
+/* Get memory banks definition from some user configuration file.
+   This file must be located in some linker directory (search path
+   with -L<dir>). See fixed memory banks emulation script.  */
+INCLUDE memory.x;
+"
+	;;
+  *)
+MEMORY_DEF="
+/* Fixed definition of the available memory banks.
+   See generic emulation script for a user defined configuration.  */
+MEMORY
+{
+  text  (rx)  : ORIGIN = $[$ROM_TOP - $ROM_SIZE + 1], LENGTH = ${ROM_SIZE} - 4
+  data        : ORIGIN = ${RAM_START_ADDR}, LENGTH = ${RAM_SIZE}
+  eeprom      : ORIGIN = ${EEPROM_START_ADDR}, LENGTH = ${EEPROM_SIZE}
+  rvec        : ORIGIN = 0xFFFFFC,  LENGTH = 4
+}
+
+/* Setup the stack on the top of the data memory bank.  */
+PROVIDE (_stack = ${RAM_START_ADDR} + ${RAM_SIZE} - 1);
+"
+	;;
+esac
+
+STARTUP_CODE="
+    /* Startup code.  */
+    KEEP (*(.install0))	/* Section should setup the stack pointer.  */
+    KEEP (*(.install1))	/* Place holder for applications.  */
+    KEEP (*(.install2))	/* Optional installation of data sections in RAM.  */
+    KEEP (*(.install3))	/* Place holder for applications.  */
+    KEEP (*(.install4))	/* Section that calls the main.  */
+"
+
+FINISH_CODE="
+    /* Finish code.  */
+    KEEP (*(.fini0))	/* Beginning of finish code (_exit symbol).  */
+    KEEP (*(.fini1))	/* Place holder for applications.  */
+    KEEP (*(.fini2))	/* C++ destructors.  */
+    KEEP (*(.fini3))	/* Place holder for applications.  */
+    KEEP (*(.fini4))	/* Runtime exit.  */
+"
+
+PRE_COMPUTE_DATA_SIZE="
+/* SCz: this does not work yet... This is supposed to force the loading
+   of _map_data.o (from libgcc.a) when the .data section is not empty.
+   By doing so, this should bring the code that copies the .data section
+   from ROM to RAM at init time.
+
+  ___pre_comp_data_size = SIZEOF(.data);
+  __install_data_sections = ___pre_comp_data_size > 0 ?
+		__map_data_sections : 0;
+*/
+"
+
+INSTALL_RELOC="
+  .install0 0 : { *(.install0) }
+  .install1 0 : { *(.install1) }
+  .install2 0 : { *(.install2) }
+  .install3 0 : { *(.install3) }
+  .install4 0 : { *(.install4) }
+"
+
+FINISH_RELOC="
+  .fini0 0 : { *(.fini0) }
+  .fini1 0 : { *(.fini1) }
+  .fini2 0 : { *(.fini2) }
+  .fini3 0 : { *(.fini3) }
+  .fini4 0 : { *(.fini4) }
+"
+
+BSS_DATA_RELOC="
+  .data1 0 : { *(.data1) }
+
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata   0 : { *(.sdata) }
+  .sbss    0 : { *(.sbss) }
+  .scommon 0 : { *(.scommon) }
+"
+
+SOFT_REGS_RELOC="
+  .softregs 0 : { *(.softregs) }
+"
+
+cat <<EOF
+/* Copyright (C) 2014-2018 Free Software Foundation, Inc.
+
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+${RELOCATING+/* Linker script for HCS12Z executable (PROM).  */}
+${RELOCATING-/* Linker script for HCS12Z object file (ld -r).  */}
+
+OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
+	      "${LITTLE_OUTPUT_FORMAT}")
+OUTPUT_ARCH(${OUTPUT_ARCH})
+${RELOCATING+ENTRY(${ENTRY})}
+
+${RELOCATING+${LIB_SEARCH_DIRS}}
+${RELOCATING+${EXECUTABLE_SYMBOLS}}
+${RELOCATING+${MEMORY_DEF}}
+
+PROVIDE (_start = $[$ROM_TOP - $ROM_SIZE + 1]);
+SECTIONS
+{
+  .hash        ${RELOCATING-0} : { *(.hash)		}
+  .dynsym      ${RELOCATING-0} : { *(.dynsym)		}
+  .dynstr      ${RELOCATING-0} : { *(.dynstr)		}
+  .gnu.version		${RELOCATING-0} : { *(.gnu.version) }
+  .gnu.version_d	${RELOCATING-0} : { *(.gnu.version_d) }
+  .gnu.version_r	${RELOCATING-0} : { *(.gnu.version_r) }
+
+  .rel.text    ${RELOCATING-0} :
+    {
+      *(.rel.text)
+      ${RELOCATING+*(.rel.text.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.t.*)}
+    }
+  .rela.text   ${RELOCATING-0} :
+    {
+      *(.rela.text)
+      ${RELOCATING+*(.rela.text.*)}
+      ${RELOCATING+*(.rela.gnu.linkonce.t.*)}
+    }
+  .rel.data    ${RELOCATING-0} :
+    {
+      *(.rel.data)
+      ${RELOCATING+*(.rel.data.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.d.*)}
+    }
+  .rela.data   ${RELOCATING-0} :
+    {
+      *(.rela.data)
+      ${RELOCATING+*(.rela.data.*)}
+      ${RELOCATING+*(.rela.gnu.linkonce.d.*)}
+    }
+  .rel.rodata  ${RELOCATING-0} :
+    {
+      *(.rel.rodata)
+      ${RELOCATING+*(.rel.rodata.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.r.*)}
+    }
+  .rela.rodata ${RELOCATING-0} :
+    {
+      *(.rela.rodata)
+      ${RELOCATING+*(.rela.rodata.*)}
+      ${RELOCATING+*(.rela.gnu.linkonce.r.*)}
+    }
+  .rel.sdata   ${RELOCATING-0} :
+    {
+      *(.rel.sdata)
+      ${RELOCATING+*(.rel.sdata.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.s.*)}
+    }
+  .rela.sdata   ${RELOCATING-0} :
+    {
+      *(.rela.sdata)
+      ${RELOCATING+*(.rela.sdata.*)}
+      ${RELOCATING+*(.rela.gnu.linkonce.s.*)}
+    }
+  .rel.sbss    ${RELOCATING-0} :
+    {
+      *(.rel.sbss)
+      ${RELOCATING+*(.rel.sbss.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.sb.*)}
+    }
+  .rela.sbss   ${RELOCATING-0} :
+    {
+      *(.rela.sbss)
+      ${RELOCATING+*(.rela.sbss.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.sb.*)}
+    }
+  .rel.bss     ${RELOCATING-0} :
+    {
+      *(.rel.bss)
+      ${RELOCATING+*(.rel.bss.*)}
+      ${RELOCATING+*(.rel.gnu.linkonce.b.*)}
+    }
+  .rela.bss    ${RELOCATING-0} :
+    {
+      *(.rela.bss)
+      ${RELOCATING+*(.rela.bss.*)}
+      ${RELOCATING+*(.rela.gnu.linkonce.b.*)}
+    }
+  .rel.stext		${RELOCATING-0} : { *(.rel.stest) }
+  .rela.stext		${RELOCATING-0} : { *(.rela.stest) }
+  .rel.etext		${RELOCATING-0} : { *(.rel.etest) }
+  .rela.etext		${RELOCATING-0} : { *(.rela.etest) }
+  .rel.sdata		${RELOCATING-0} : { *(.rel.sdata) }
+  .rela.sdata		${RELOCATING-0} : { *(.rela.sdata) }
+  .rel.edata		${RELOCATING-0} : { *(.rel.edata) }
+  .rela.edata		${RELOCATING-0} : { *(.rela.edata) }
+  .rel.eit_v		${RELOCATING-0} : { *(.rel.eit_v) }
+  .rela.eit_v		${RELOCATING-0} : { *(.rela.eit_v) }
+  .rel.ebss		${RELOCATING-0} : { *(.rel.ebss) }
+  .rela.ebss		${RELOCATING-0} : { *(.rela.ebss) }
+  .rel.srodata		${RELOCATING-0} : { *(.rel.srodata) }
+  .rela.srodata		${RELOCATING-0} : { *(.rela.srodata) }
+  .rel.erodata		${RELOCATING-0} : { *(.rel.erodata) }
+  .rela.erodata		${RELOCATING-0} : { *(.rela.erodata) }
+  .rel.got		${RELOCATING-0} : { *(.rel.got) }
+  .rela.got		${RELOCATING-0} : { *(.rela.got) }
+  .rel.ctors		${RELOCATING-0} : { *(.rel.ctors) }
+  .rela.ctors		${RELOCATING-0} : { *(.rela.ctors) }
+  .rel.dtors		${RELOCATING-0} : { *(.rel.dtors) }
+  .rela.dtors		${RELOCATING-0} : { *(.rela.dtors) }
+  .rel.init		${RELOCATING-0} : { *(.rel.init) }
+  .rela.init		${RELOCATING-0} : { *(.rela.init) }
+  .rel.fini		${RELOCATING-0} : { *(.rel.fini) }
+  .rela.fini		${RELOCATING-0} : { *(.rela.fini) }
+  .rel.plt		${RELOCATING-0} : { *(.rel.plt) }
+  .rela.plt		${RELOCATING-0} : { *(.rela.plt) }
+
+  /* Start of text section.  */
+  .stext ${RELOCATING-0} :
+  {
+    *(.stext)
+  } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+  .init	${RELOCATING-0} :
+  {
+    *(.init)
+  } ${RELOCATING+=${NOP-0}}
+
+  ${RELOCATING-${INSTALL_RELOC}}
+  ${RELOCATING-${FINISH_RELOC}}
+
+  .text ${RELOCATING-0}:
+  {
+    /* Put startup code at beginning so that _start keeps same address.  */
+    ${RELOCATING+${STARTUP_CODE}}
+
+    ${RELOCATING+*(.init)}
+    *(.text)
+    ${RELOCATING+*(.text.*)}
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    ${RELOCATING+*(.gnu.linkonce.t.*)}
+    ${RELOCATING+*(.tramp)}
+    ${RELOCATING+*(.tramp.*)}
+
+    ${RELOCATING+${FINISH_CODE}}
+
+    ${RELOCATING+_etext = .;}
+    ${RELOCATING+PROVIDE (etext = .);}
+    ${RELOCATING+. = ALIGN(2);}
+  } ${RELOCATING+ > ${TEXT_MEMORY} =${NOP}}
+  .rvec ${RELOCATING-0} :
+  {
+    ${RELOCATING+LONG(_start);}
+  } ${RELOCATING+ > rvec}
+  .eh_frame ${RELOCATING-0} :
+  {
+    KEEP (*(.eh_frame))
+  } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+  .gcc_except_table ${RELOCATING-0} :
+  {
+    *(.gcc_except_table)
+  } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+  .rodata  ${RELOCATING-0} :
+  {
+    *(.rodata)
+    ${RELOCATING+*(.rodata.*)}
+    ${RELOCATING+*(.gnu.linkonce.r*)}
+    ${RELOCATING+. = ALIGN(2);}
+  } ${RELOCATING+ > ${TEXT_MEMORY} =0xffffffff}
+
+  .rodata1 ${RELOCATING-0} :
+  {
+    *(.rodata1)
+    ${RELOCATING+. = ALIGN(2);}
+  } ${RELOCATING+ > ${TEXT_MEMORY} =0xffffffff}
+
+  /* Constructor and destructor tables are in ROM.  */
+  ${RELOCATING+${CTOR}}
+  ${RELOCATING+${DTOR}}
+
+  .jcr ${RELOCATING-0} :
+  {
+    KEEP (*(.jcr))
+  } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+  /* Start of the data section image in ROM.  */
+  ${RELOCATING+__data_image = .;}
+  ${RELOCATING+PROVIDE (__data_image = .);}
+
+  /* All read-only sections that normally go in PROM must be above.
+     We construct the DATA image section in PROM at end of all these
+     read-only sections.  The data image must be copied at init time.
+     Refer to GNU ld, Section 3.6.8.2 Output Section LMA.  */
+  .data  ${RELOCATING-0} : ${RELOCATING+AT (__data_image)}
+  {
+    ${RELOCATING+__data_section_start = .;}
+    ${RELOCATING+PROVIDE (__data_section_start = .);}
+
+    ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+*(.sdata)}
+    *(.data)
+    ${RELOCATING+*(.data.*)}
+    ${RELOCATING+*(.data1)}
+    ${RELOCATING+*(.gnu.linkonce.d.*)}
+    ${CONSTRUCTING+CONSTRUCTORS}
+
+    ${RELOCATING+_edata  =  .;}
+    ${RELOCATING+PROVIDE (edata = .);}
+    ${RELOCATING+. = ALIGN(2);}
+  } ${RELOCATING+ > ${DATA_MEMORY} =0xffffffff}
+
+  ${RELOCATING+__data_section_size = SIZEOF(.data);}
+  ${RELOCATING+PROVIDE (__data_section_size = SIZEOF(.data));}
+  ${RELOCATING+__data_image_end = __data_image + __data_section_size;}
+
+  ${RELOCATING+${PRE_COMPUTE_DATA_SIZE}}
+
+  /* .install ${RELOCATING-0}:
+  {
+    . = _data_image_end;
+  } ${RELOCATING+ > ${TEXT_MEMORY}} */
+
+  /* Relocation for some bss and data sections.  */
+  ${RELOCATING-${BSS_DATA_RELOC}}
+  ${RELOCATING-${SOFT_REGS_RELOC}}
+
+  .bss ${RELOCATING-0} :
+  {
+    ${RELOCATING+__bss_start = .;}
+    ${RELOCATING+*(.softregs)}
+    ${RELOCATING+*(.sbss)}
+    ${RELOCATING+*(.scommon)}
+
+    *(.dynbss)
+    *(.bss)
+    ${RELOCATING+*(.bss.*)}
+    ${RELOCATING+*(.gnu.linkonce.b.*)}
+    *(COMMON)
+    ${RELOCATING+PROVIDE (_end = .);}
+  } ${RELOCATING+ > ${DATA_MEMORY}}
+  ${RELOCATING+__bss_size = SIZEOF(.bss);}
+  ${RELOCATING+PROVIDE (__bss_size = SIZEOF(.bss));}
+
+  .eeprom ${RELOCATING-0} :
+  {
+    *(.eeprom)
+    *(.eeprom.*)
+  } ${RELOCATING+ > ${EEPROM_MEMORY}}
+
+  ${RELOCATING+${VECTORS}}
+
+  /* Stabs debugging sections.  */
+  .stab		 0 : { *(.stab) }
+  .stabstr	 0 : { *(.stabstr) }
+  .stab.excl	 0 : { *(.stab.excl) }
+  .stab.exclstr	 0 : { *(.stab.exclstr) }
+  .stab.index	 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+
+  .comment	 0 : { *(.comment) }
+
+  /* Treatment of DWARF debug section must be at end of the linker
+     script to avoid problems when there are undefined symbols. It's necessary
+     to avoid that the DWARF section is relocated before such undefined
+     symbols are found.  */
+EOF
+
+. $srcdir/scripttempl/DWARF.sc
+
+cat <<EOF
+}
+EOF
diff --git a/ld/testsuite/ld-discard/static.d b/ld/testsuite/ld-discard/static.d
index 7a299cc9c0..ebdbda840e 100644
--- a/ld/testsuite/ld-discard/static.d
+++ b/ld/testsuite/ld-discard/static.d
@@ -3,5 +3,5 @@
 #error: `(\.data\.exit|data)' referenced in section `\.text' of tmpdir/static.o: defined in discarded section `\.data\.exit' of tmpdir/static.o
 #objdump: -p
 #xfail: d30v-*-* dlx-*-* pj*-*-*
-#xfail: m68hc12-*-* m6812-*-*
+#xfail: m68hc12-*-* m6812-*-* 
 #pass
diff --git a/ld/testsuite/ld-elf/endsym.d b/ld/testsuite/ld-elf/endsym.d
index 86fda2114e..39667e37ce 100644
--- a/ld/testsuite/ld-elf/endsym.d
+++ b/ld/testsuite/ld-elf/endsym.d
@@ -2,7 +2,7 @@
 #source: endsym.s
 #ld: --sort-common
 #nm: -n
-#xfail: m68hc1*-* xgate-* cr16-*-* crx-*-* dlx-*-* nds32*-*-* visium-*-*
+#xfail: m68hc1*-* xgate-* cr16-*-* crx-*-* dlx-*-* nds32*-*-* visium-*-* s12z-*-*
 #xfail: pru-*-*
 
 #...
diff --git a/ld/testsuite/ld-elf/merge.d b/ld/testsuite/ld-elf/merge.d
index 2ac88ea89c..ebabae8d95 100644
--- a/ld/testsuite/ld-elf/merge.d
+++ b/ld/testsuite/ld-elf/merge.d
@@ -4,7 +4,7 @@
 #xfail: "bfin-*-*" "cr16-*-*" "cris*-*-*" "crx-*-*" "d10v-*-*" "d30v-*-*"
 #xfail: "dlx-*-*" "fr30-*-*" "frv-*-*" "hppa*64*-*-*" "h8300-*-*" "score-*-*"
 #xfail: "ip2k-*-*" "iq2000-*-*" "lm32-*-*"
-#xfail: "mcore-*-*" "mn102*-*-*" "ms1-*-*" "mep-*-*" "m68hc11-*-*" "nios2-*-*"
+#xfail: "mcore-*-*" "mn102*-*-*" "ms1-*-*" "mep-*-*" "m68hc11-*-*" "nios2-*-*" s12z-*-*
 #xfail: "or32-*-*" "pj-*-*" "tic6x-*-*" "vax-*-*" "xstormy16-*-*"
 #xfail: "xtensa*-*-*" "metag-*-*" "ft32-*-*" "pru-*-*"
 
diff --git a/ld/testsuite/ld-elf/pr14926.d b/ld/testsuite/ld-elf/pr14926.d
index 8fc8e6416c..4e0a8da4dd 100644
--- a/ld/testsuite/ld-elf/pr14926.d
+++ b/ld/testsuite/ld-elf/pr14926.d
@@ -1,6 +1,6 @@
 #ld: -Ttext=0x60
 #readelf: -S --wide
-#notarget: d10v-* m68hc1*-* msp*-* visium-* xgate-* xstormy*-* pru-*-*
+#notarget: d10v-* m68hc1*-* msp*-* visium-* xgate-* xstormy*-* pru-*-* s12z-*-*
 # the above targets use memory regions that don't allow 0x60 for .text
 
 #...
diff --git a/ld/testsuite/ld-elf/sec64k.exp b/ld/testsuite/ld-elf/sec64k.exp
index 2495cb85f5..b58139e9dd 100644
--- a/ld/testsuite/ld-elf/sec64k.exp
+++ b/ld/testsuite/ld-elf/sec64k.exp
@@ -40,6 +40,7 @@ if {[istarget "ft32-*-*"]
     || [istarget "h8300-*-*"]
     || [istarget "ip2k-*-*"]
     || [istarget "m68hc1*-*"]
+    || [istarget "s12z-*"]
     || [istarget "xgate-*"] } {
     return
 }
diff --git a/ld/testsuite/ld-s12z/opr-linking.d b/ld/testsuite/ld-s12z/opr-linking.d
new file mode 100644
index 0000000000..05d154bc12
--- /dev/null
+++ b/ld/testsuite/ld-s12z/opr-linking.d
@@ -0,0 +1,20 @@
+#source: opr-linking.s
+#ld: --no-relax --defsym here=0xfe0000 --defsym=foo=0xfe0050  --defsym=bar=0xfe0010 --defsym=wiz=0xfe0040
+#objdump: -d -r
+
+tmpdir/dump:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+
+00fe0000 .*:
+  fe0000:	01          	nop
+  fe0001:	01          	nop
+  fe0002:	01          	nop
+  fe0003:	01          	nop
+  fe0004:	1b 37 f6 fa 	divs\.lw d7, bar, wiz
+  fe0008:	fe 00 10 fa 
+  fe000c:	fe 00 40 
+  fe000f:	bc fa fe 00 	clr\.b foo
+  fe0013:	50 
diff --git a/ld/testsuite/ld-s12z/opr-linking.s b/ld/testsuite/ld-s12z/opr-linking.s
new file mode 100644
index 0000000000..aa7056640a
--- /dev/null
+++ b/ld/testsuite/ld-s12z/opr-linking.s
@@ -0,0 +1,7 @@
+here:
+	nop
+	nop
+	nop
+	nop
+	divs.lw d7, bar, wiz
+	clr.b foo
diff --git a/ld/testsuite/ld-s12z/relative-linking.d b/ld/testsuite/ld-s12z/relative-linking.d
new file mode 100644
index 0000000000..286fe5281a
--- /dev/null
+++ b/ld/testsuite/ld-s12z/relative-linking.d
@@ -0,0 +1,14 @@
+#source: relative-linking.s
+#ld: --no-relax --defsym here=0xfe0020 --defsym=foo=0xfe0008  --defsym=bar=0xfe0010 --defsym=wiz=0xfe0040
+#objdump: -d -r
+
+tmpdir/dump:     file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00fe0000 <here>:
+  fe0000:	20 80 08    	bra foo
+  fe0003:	02 b0 bc 80 	brclr.b d0, #3, bar
+  fe0007:	0d 
+  fe0008:	0b 85 80 38 	dbne d1, wiz
diff --git a/ld/testsuite/ld-s12z/relative-linking.s b/ld/testsuite/ld-s12z/relative-linking.s
new file mode 100644
index 0000000000..fa52edbc78
--- /dev/null
+++ b/ld/testsuite/ld-s12z/relative-linking.s
@@ -0,0 +1,5 @@
+
+here:
+	bra foo
+	brclr.b d0, #3, bar
+	dbne  d1, wiz
diff --git a/ld/testsuite/ld-s12z/z12s.exp b/ld/testsuite/ld-s12z/z12s.exp
new file mode 100644
index 0000000000..4c9baa4a7a
--- /dev/null
+++ b/ld/testsuite/ld-s12z/z12s.exp
@@ -0,0 +1,33 @@
+# Expect script for run_dump_test based ld-m68hc11 tests.
+#   Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# Test S12Z linker tests.  This tests the assembler as well as the linker.
+
+if { ![istarget s12z-*-*] } {
+    return
+}
+
+set rd_test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach shtest $rd_test_list {
+    # We need to strip the ".d", but can leave the dirname.
+    verbose [file rootname $shtest]
+    run_dump_test [file rootname $shtest]
+}
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index 0c7d09d759..98fd7f3f70 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -175,6 +175,7 @@ TARGET_LIBOPCODES_CFILES = \
 	m68hc11-opc.c \
 	m68k-dis.c \
 	m68k-opc.c \
+	s12z-dis.c \
 	mcore-dis.c \
 	mep-asm.c \
 	mep-desc.c \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index 0d85bd43fa..b55daea21b 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -477,6 +477,7 @@ TARGET_LIBOPCODES_CFILES = \
 	m68hc11-opc.c \
 	m68k-dis.c \
 	m68k-opc.c \
+	s12z-dis.c \
 	mcore-dis.c \
 	mep-asm.c \
 	mep-desc.c \
@@ -878,6 +879,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68hc11-opc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68k-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68k-opc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s12z-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcore-dis.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mep-asm.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mep-desc.Plo@am__quote@
diff --git a/opcodes/configure b/opcodes/configure
index c7a88054b3..c5f0c1000c 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12659,6 +12659,7 @@ if test x${all_targets} = xfalse ; then
 	bfd_m68hc12_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
 	bfd_m9s12x_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
 	bfd_m9s12xg_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
+	bfd_s12z_arch)	ta="$ta s12z-dis.lo m68hc11-opc.lo" ;;
 	bfd_m68k_arch)		ta="$ta m68k-dis.lo m68k-opc.lo" ;;
 	bfd_mcore_arch)		ta="$ta mcore-dis.lo" ;;
 	bfd_mep_arch)		ta="$ta mep-asm.lo mep-desc.lo mep-dis.lo mep-ibld.lo mep-opc.lo" using_cgen=yes ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index e42b661fcf..86a0ca01ff 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -283,6 +283,7 @@ if test x${all_targets} = xfalse ; then
 	bfd_m68hc12_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
 	bfd_m9s12x_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
 	bfd_m9s12xg_arch)	ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
+	bfd_s12z_arch)	ta="$ta s12z-dis.lo m68hc11-opc.lo" ;;
 	bfd_m68k_arch)		ta="$ta m68k-dis.lo m68k-opc.lo" ;;
 	bfd_mcore_arch)		ta="$ta mcore-dis.lo" ;;
 	bfd_mep_arch)		ta="$ta mep-asm.lo mep-desc.lo mep-dis.lo mep-ibld.lo mep-opc.lo" using_cgen=yes ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 100ccd3fac..c8fda59b6e 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -251,6 +251,11 @@ disassembler (enum bfd_architecture a,
       disassemble = print_insn_m9s12xg;
       break;
 #endif
+#if defined(ARCH_s12z)
+    case bfd_arch_s12z:
+      disassemble = print_insn_s12z;
+      break;
+#endif
 #ifdef ARCH_m68k
     case bfd_arch_m68k:
       disassemble = print_insn_m68k;
diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h
index 9d78b2193f..0457344612 100644
--- a/opcodes/disassemble.h
+++ b/opcodes/disassemble.h
@@ -61,6 +61,7 @@ extern int print_insn_m68hc11		(bfd_vma, disassemble_info *);
 extern int print_insn_m68hc12		(bfd_vma, disassemble_info *);
 extern int print_insn_m9s12x		(bfd_vma, disassemble_info *);
 extern int print_insn_m9s12xg		(bfd_vma, disassemble_info *);
+extern int print_insn_s12z		(bfd_vma, disassemble_info *);
 extern int print_insn_m68k		(bfd_vma, disassemble_info *);
 extern int print_insn_mcore		(bfd_vma, disassemble_info *);
 extern int print_insn_metag		(bfd_vma, disassemble_info *);
diff --git a/opcodes/s12z-dis.c b/opcodes/s12z-dis.c
new file mode 100644
index 0000000000..11f01a19b5
--- /dev/null
+++ b/opcodes/s12z-dis.c
@@ -0,0 +1,2672 @@
+/* s12z-dis.c -- Freescale S12Z disassembly
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU opcodes library.
+
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include "s12z.h"
+
+#include "bfd.h"
+#include "dis-asm.h"
+
+
+#include "disassemble.h"
+
+static int
+read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
+             struct disassemble_info* info)
+{
+  int status = (*info->read_memory_func) (memaddr, buffer, size, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+  return 0;
+}
+
+typedef int (* insn_bytes_f) (bfd_vma memaddr,
+			      struct disassemble_info* info);
+
+typedef void (*operands_f) (bfd_vma memaddr, struct disassemble_info* info);
+
+enum OPR_MODE
+  {
+    OPR_IMMe4,
+    OPR_REG,
+    OPR_OFXYS,
+    OPR_XY_PRE_INC,
+    OPR_XY_POST_INC,
+    OPR_XY_PRE_DEC,
+    OPR_XY_POST_DEC,
+    OPR_S_PRE_DEC,
+    OPR_S_POST_INC,
+    OPR_REG_DIRECT,
+    OPR_REG_INDIRECT,
+    OPR_IDX_DIRECT,
+    OPR_IDX_INDIRECT,
+    OPR_EXT1,
+    OPR_IDX2_REG,
+    OPR_IDX3_DIRECT,
+    OPR_IDX3_INDIRECT,
+
+    OPR_EXT18,
+    OPR_IDX3_DIRECT_REG,
+    OPR_EXT3_DIRECT,
+    OPR_EXT3_INDIRECT
+  };
+
+struct opr_pb
+{
+  uint8_t mask;
+  uint8_t value;
+  int n_operands;
+  enum OPR_MODE mode;
+};
+
+static const  struct opr_pb opr_pb[] = {
+  {0xF0, 0x70, 1, OPR_IMMe4},
+  {0xF8, 0xB8, 1, OPR_REG},
+  {0xC0, 0x40, 1, OPR_OFXYS},
+  {0xEF, 0xE3, 1, OPR_XY_PRE_INC},
+  {0xEF, 0xE7, 1, OPR_XY_POST_INC},
+  {0xEF, 0xC3, 1, OPR_XY_PRE_DEC},
+  {0xEF, 0xC7, 1, OPR_XY_POST_DEC},
+  {0xFF, 0xFB, 1, OPR_S_PRE_DEC},
+  {0xFF, 0xFF, 1, OPR_S_POST_INC},
+  {0xC8, 0x88, 1, OPR_REG_DIRECT},
+  {0xE8, 0xC8, 1, OPR_REG_INDIRECT},
+
+  {0xCE, 0xC0, 2, OPR_IDX_DIRECT},
+  {0xCE, 0xC4, 2, OPR_IDX_INDIRECT},
+  {0xC0, 0x00, 2, OPR_EXT1},
+
+  {0xC8, 0x80, 3, OPR_IDX2_REG},
+  {0xFA, 0xF8, 3, OPR_EXT18},
+
+  {0xCF, 0xC2, 4, OPR_IDX3_DIRECT},
+  {0xCF, 0xC6, 4, OPR_IDX3_INDIRECT},
+
+  {0xF8, 0xE8, 4, OPR_IDX3_DIRECT_REG},
+  {0xFF, 0xFA, 4, OPR_EXT3_DIRECT},
+  {0xFF, 0xFE, 4, OPR_EXT3_INDIRECT},
+};
+
+
+/* Return the number of bytes in a OPR operand, including the XB postbyte.
+   It does not include any preceeding opcodes. */
+static int
+opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte xb;
+  int status = read_memory (memaddr, &xb, 1, info);
+  if (status < 0)
+    return status;
+
+  size_t i;
+  for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
+    {
+      const struct opr_pb *pb = opr_pb + i;
+      if ((xb & pb->mask) == pb->value)
+	{
+	  return pb->n_operands;
+	}
+    }
+
+  return 1;
+}
+
+static int
+opr_n_bytes_p1 (bfd_vma memaddr, struct disassemble_info* info)
+{
+  return 1 + opr_n_bytes (memaddr, info);
+}
+
+static int
+opr_n_bytes2 (bfd_vma memaddr, struct disassemble_info* info)
+{
+  int s = opr_n_bytes (memaddr, info);
+  s += opr_n_bytes (memaddr + s, info);
+  return s + 1;
+}
+
+enum BB_MODE
+  {
+    BB_REG_REG_REG,
+    BB_REG_REG_IMM,
+    BB_REG_OPR_REG,
+    BB_OPR_REG_REG,
+    BB_REG_OPR_IMM,
+    BB_OPR_REG_IMM
+  };
+
+struct opr_bb
+{
+  uint8_t mask;
+  uint8_t value;
+  int n_operands;
+  bool opr;
+  enum BB_MODE mode;
+};
+
+static const struct opr_bb bb_modes[] =
+  {
+    {0x60, 0x00, 2, false, BB_REG_REG_REG},
+    {0x60, 0x20, 3, false, BB_REG_REG_IMM},
+    {0x70, 0x40, 2, true,  BB_REG_OPR_REG},
+    {0x70, 0x50, 2, true,  BB_OPR_REG_REG},
+    {0x70, 0x60, 3, true,  BB_REG_OPR_IMM},
+    {0x70, 0x70, 3, true,  BB_OPR_REG_IMM}
+  };
+
+static int
+bfextins_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte bb;
+  int status = read_memory (memaddr, &bb, 1, info);
+  if (status < 0)
+    return status;
+
+  size_t i;
+  const struct opr_bb *bbs = 0;
+  for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
+    {
+      bbs = bb_modes + i;
+      if ((bb & bbs->mask) == bbs->value)
+	{
+	  break;
+	}
+    }
+
+  int n = bbs->n_operands;
+  if (bbs->opr)
+    n += opr_n_bytes (memaddr + n - 1, info);
+
+  return n;
+}
+
+static int
+single (bfd_vma memaddr ATTRIBUTE_UNUSED,
+	struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+static int
+two (bfd_vma memaddr ATTRIBUTE_UNUSED,
+     struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  return 2;
+}
+
+static int
+three (bfd_vma memaddr ATTRIBUTE_UNUSED,
+       struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  return 3;
+}
+
+static int
+four (bfd_vma memaddr ATTRIBUTE_UNUSED,
+      struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  return 4;
+}
+
+static int
+five (bfd_vma memaddr ATTRIBUTE_UNUSED,
+      struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+  return 5;
+}
+
+static int
+pcrel_15bit (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr, &byte, 1, info);
+  if (status < 0)
+    return status;
+  return (byte & 0x80) ? 3 : 2;
+}
+
+
+
+
+static void
+operand_separator (struct disassemble_info *info)
+{
+  if ((info->flags & 0x2))
+    {
+      (*info->fprintf_func) (info->stream, ", ");
+    }
+  else
+    {
+      (*info->fprintf_func) (info->stream, " ");
+    }
+
+  info->flags |= 0x2;
+}
+
+
+
+static void
+imm1 (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "#%d", byte);
+}
+
+static void
+trap_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  imm1 (memaddr - 1, info);
+}
+
+
+const struct reg registers[S12Z_N_REGISTERS] =
+  {
+    {"d2", 2},
+    {"d3", 2},
+    {"d4", 2},
+    {"d5", 2},
+
+    {"d0", 1},
+    {"d1", 1},
+
+    {"d6", 4},
+    {"d7", 4},
+
+    {"x", 3},
+    {"y", 3},
+    {"s", 3},
+    {"p", 3},
+    {"cch", 1},
+    {"ccl", 1},
+    {"ccw", 2}
+  };
+
+static char *
+xys_from_postbyte (uint8_t postbyte)
+{
+  char *reg = "?";
+  switch ((postbyte & 0x30) >> 4)
+    {
+    case 0:
+      reg = "x";
+      break;
+    case 1:
+      reg = "y";
+      break;
+    case 2:
+      reg = "s";
+      break;
+    default:
+      reg = "?";
+      break;
+    }
+  return reg;
+}
+
+static char *
+xysp_from_postbyte (uint8_t postbyte)
+{
+  char *reg = "?";
+  switch ((postbyte & 0x30) >> 4)
+    {
+    case 0:
+      reg = "x";
+      break;
+    case 1:
+      reg = "y";
+      break;
+    case 2:
+      reg = "s";
+      break;
+    default:
+      reg = "p";
+      break;
+    }
+  return reg;
+}
+
+/* Render the symbol name whose value is ADDR or the adddress itself if there is
+   no symbol. */
+static void
+decode_possible_symbol (bfd_vma addr, struct disassemble_info *info)
+{
+  if (!info->symbol_at_address_func (addr, info))
+    {
+      (*info->fprintf_func) (info->stream, "%d", addr);
+    }
+  else
+    {
+      asymbol *sym = NULL;
+      int j;
+      for (j = 0; j < info->symtab_size; ++j)
+	{
+	  sym = info->symtab[j];
+	  if (bfd_asymbol_value (sym) == addr)
+	    {
+	      break;
+	    }
+	}
+      if (j < info->symtab_size)
+	(*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
+    }
+}
+
+static void ld_18bit_decode (bfd_vma memaddr, struct disassemble_info* info);
+
+static void
+ext24_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  uint8_t buffer[3];
+  int status = read_memory (memaddr, buffer, 3, info);
+  if (status < 0)
+    return;
+
+  int i;
+  uint32_t addr = 0;
+  for (i = 0; i < 3; ++i)
+    {
+      addr <<= 8;
+      addr |= buffer[i];
+    }
+
+  operand_separator (info);
+  decode_possible_symbol (addr, info);
+}
+
+
+static uint32_t
+decode_signed_value (bfd_vma memaddr, struct disassemble_info* info, short size)
+{
+  assert (size >0);
+  assert (size <= 4);
+  bfd_byte buffer[4];
+  if (0 > read_memory (memaddr, buffer, size, info))
+    {
+      return 0;
+    }
+
+  int i;
+  uint32_t value = 0;
+  for (i = 0; i < size; ++i)
+    {
+      value |= buffer[i] << (8 * (size - i - 1));
+    }
+
+  if (buffer[0] & 0x80)
+    {
+      /* Deal with negative values */
+      value -= 0x1UL << (size * 8);
+    }
+  return value;
+}
+
+
+static void
+opr_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte postbyte;
+  int status = read_memory (memaddr, &postbyte, 1, info);
+  if (status < 0)
+    return;
+
+  enum OPR_MODE mode = -1;
+  size_t i;
+  for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
+    {
+      const struct opr_pb *pb = opr_pb + i;
+      if ((postbyte & pb->mask) == pb->value)
+	{
+	  mode = pb->mode;
+	  break;
+	}
+    }
+
+  operand_separator (info);
+  switch (mode)
+    {
+    case OPR_IMMe4:
+      {
+	int n;
+	uint8_t x = (postbyte & 0x0F);
+	if (x == 0)
+	  n = -1;
+	else
+	  n = x;
+
+	(*info->fprintf_func) (info->stream, "#%d", n);
+	break;
+      }
+    case OPR_REG:
+      {
+	uint8_t x = (postbyte & 0x07);
+	(*info->fprintf_func) (info->stream, "%s", registers[x].name);
+	break;
+      }
+    case OPR_OFXYS:
+      {
+	const char *reg  = xys_from_postbyte (postbyte);
+	(*info->fprintf_func) (info->stream, "(%d,%s)", postbyte & 0x0F, reg);
+	break;
+      }
+    case OPR_REG_DIRECT:
+      {
+	(*info->fprintf_func) (info->stream, "(%s,%s)", registers[postbyte & 0x07].name,
+			       xys_from_postbyte (postbyte));
+	break;
+      }
+    case OPR_REG_INDIRECT:
+      {
+	(*info->fprintf_func) (info->stream, "[%s,%s]", registers[postbyte & 0x07].name,
+			       (postbyte & 0x10) ? "y": "x");
+	break;
+      }
+
+    case OPR_IDX_INDIRECT:
+      {
+	uint8_t x1;
+	read_memory (memaddr + 1, &x1, 1, info);
+	int idx = x1;
+
+	if (postbyte & 0x01)
+	  {
+	    /* Deal with negative values */
+	    idx -= 0x1UL << 8;
+	  }
+
+	(*info->fprintf_func) (info->stream, "[%d,%s]", idx,
+			       xysp_from_postbyte (postbyte));
+	break;
+      }
+
+    case OPR_IDX3_DIRECT:
+      {
+	uint8_t x[3];
+	read_memory (memaddr + 1, x, 3, info);
+	int idx = x[0] << 16 | x[1] << 8 | x[2];
+
+	if (x[0] & 0x80)
+	  {
+	    /* Deal with negative values */
+	    idx -= 0x1UL << 24;
+	  }
+
+	(*info->fprintf_func) (info->stream, "(%d,%s)", idx,
+			       xysp_from_postbyte (postbyte));
+	break;
+      }
+
+    case OPR_IDX3_DIRECT_REG:
+      {
+	uint8_t x[3];
+	read_memory (memaddr + 1, x, 3, info);
+	int idx = x[0] << 16 | x[1] << 8 | x[2];
+
+	if (x[0] & 0x80)
+	  {
+	    /* Deal with negative values */
+	    idx -= 0x1UL << 24;
+	  }
+
+	(*info->fprintf_func) (info->stream, "(%d,%s)", idx,
+			       registers[postbyte & 0x07].name);
+	break;
+      }
+
+    case OPR_IDX3_INDIRECT:
+      {
+	uint8_t x[3];
+	read_memory (memaddr + 1, x, 3, info);
+	int idx = x[0] << 16 | x[1] << 8 | x[2];
+
+	if (x[0] & 0x80)
+	  {
+	    /* Deal with negative values */
+	    idx -= 0x1UL << 24;
+	  }
+
+	(*info->fprintf_func) (info->stream, "[%d,%s]", idx,
+			       xysp_from_postbyte (postbyte));
+	break;
+      }
+
+    case OPR_IDX_DIRECT:
+      {
+	uint8_t x1;
+	read_memory (memaddr + 1, &x1, 1, info);
+	int idx = x1;
+
+	if (postbyte & 0x01)
+	  {
+	    /* Deal with negative values */
+	    idx -= 0x1UL << 8;
+	  }
+
+	(*info->fprintf_func) (info->stream, "(%d,%s)", idx,
+			       xysp_from_postbyte (postbyte));
+	break;
+      }
+
+    case OPR_IDX2_REG:
+      {
+	uint8_t x[2];
+	read_memory (memaddr + 1, x, 2, info);
+	uint32_t offset = x[1] | x[0] << 8 ;
+	offset |= (postbyte & 0x30) << 12;
+
+	(*info->fprintf_func) (info->stream, "(%d,%s)", offset,
+			       registers[postbyte & 0x07].name);
+	break;
+      }
+
+    case OPR_XY_PRE_INC:
+      {
+	(*info->fprintf_func) (info->stream, "(+%s)",
+			       (postbyte & 0x10) ? "y": "x");
+
+	break;
+      }
+    case OPR_XY_POST_INC:
+      {
+	(*info->fprintf_func) (info->stream, "(%s+)",
+			       (postbyte & 0x10) ? "y": "x");
+
+	break;
+      }
+    case OPR_XY_PRE_DEC:
+      {
+	(*info->fprintf_func) (info->stream, "(-%s)",
+			       (postbyte & 0x10) ? "y": "x");
+
+	break;
+      }
+    case OPR_XY_POST_DEC:
+      {
+	(*info->fprintf_func) (info->stream, "(%s-)",
+			       (postbyte & 0x10) ? "y": "x");
+
+	break;
+      }
+    case OPR_S_PRE_DEC:
+      {
+	(*info->fprintf_func) (info->stream, "(-s)");
+	break;
+      }
+    case OPR_S_POST_INC:
+      {
+	(*info->fprintf_func) (info->stream, "(s+)");
+	break;
+      }
+
+    case OPR_EXT18:
+      {
+	const size_t size = 2;
+	bfd_byte buffer[4];
+	status = read_memory (memaddr + 1, buffer, size, info);
+	if (status < 0)
+	  return;
+
+	uint32_t ext18 = 0;
+	for (i = 0; i < size; ++i)
+	  {
+	    ext18 <<= 8;
+	    ext18 |= buffer[i];
+	  }
+
+	ext18 |= (postbyte & 0x01) << 16;
+	ext18 |= (postbyte & 0x04) << 15;
+
+	decode_possible_symbol (ext18, info);
+	break;
+      }
+
+    case OPR_EXT1:
+      {
+	uint8_t x1 = 0;
+	read_memory (memaddr + 1, &x1, 1, info);
+	int16_t addr;
+	addr = x1;
+	addr |= (postbyte & 0x3f) << 8;
+
+	decode_possible_symbol (addr, info);
+	break;
+      }
+
+    case OPR_EXT3_DIRECT:
+      {
+	const size_t size = 3;
+	bfd_byte buffer[4];
+	status = read_memory (memaddr + 1, buffer, size, info);
+	if (status < 0)
+	  return;
+
+	uint32_t ext24 = 0;
+	for (i = 0; i < size; ++i)
+	  {
+	    ext24 |= buffer[i] << (8 * (size - i - 1));
+	  }
+
+	decode_possible_symbol (ext24, info);
+	break;
+      }
+
+    case OPR_EXT3_INDIRECT:
+      {
+	const size_t size = 3;
+	bfd_byte buffer[4];
+	status = read_memory (memaddr + 1, buffer, size, info);
+	if (status < 0)
+	  return;
+
+	uint32_t ext24 = 0;
+	for (i = 0; i < size; ++i)
+	  {
+	    ext24 |= buffer[i] << (8 * (size - i - 1));
+	  }
+
+	(*info->fprintf_func) (info->stream, "[%d]", ext24);
+
+	break;
+      }
+
+    default:
+      (*info->fprintf_func) (info->stream, "Unknown OPR mode #0x%x (%d)", postbyte, mode);
+    }
+}
+
+
+static void
+opr_decode2 (bfd_vma memaddr, struct disassemble_info* info)
+{
+  int n = opr_n_bytes (memaddr, info);
+  opr_decode (memaddr, info);
+  opr_decode (memaddr + n, info);
+}
+
+static void
+imm1234 (bfd_vma memaddr, struct disassemble_info* info, int base)
+{
+  bfd_byte opcode;
+  int status = read_memory (memaddr - 1, &opcode, 1, info);
+  if (status < 0)
+    return;
+
+  opcode -= base;
+
+  int size = registers[opcode & 0xF].bytes;
+
+  uint32_t imm = decode_signed_value (memaddr, info, size);
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "#%d", imm);
+}
+
+
+/* Special case of LD and CMP with register S and IMM operand */
+static void
+reg_s_imm (bfd_vma memaddr, struct disassemble_info* info)
+{
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "s");
+
+  uint32_t imm = decode_signed_value (memaddr, info, 3);
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "#%d", imm);
+}
+
+/* Special case of LD, CMP and ST with register S and OPR operand */
+static void
+reg_s_opr (bfd_vma memaddr, struct disassemble_info* info)
+{
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "s");
+
+  opr_decode (memaddr, info);
+}
+
+static void
+imm1234_8base (bfd_vma memaddr, struct disassemble_info* info)
+{
+  imm1234 (memaddr, info, 8);
+}
+
+static void
+imm1234_0base (bfd_vma memaddr, struct disassemble_info* info)
+{
+  imm1234 (memaddr, info, 0);
+}
+
+static void
+tfr (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s, %s",
+			 registers[byte >> 4].name,
+			 registers[byte & 0xF].name);
+}
+
+
+static void
+reg (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x07].name);
+}
+
+static void
+reg_xy (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s", (byte & 0x01) ? "y" : "x");
+}
+
+static void
+lea_reg_xys_opr (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  char *reg = NULL;
+  switch (byte & 0x03)
+    {
+    case 0x00:
+      reg = "x";
+      break;
+    case 0x01:
+      reg = "y";
+      break;
+    case 0x02:
+      reg = "s";
+      break;
+    }
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s", reg);
+  opr_decode (memaddr, info);
+}
+
+
+
+static void
+lea_reg_xys (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  char *reg = NULL;
+  switch (byte & 0x03)
+    {
+    case 0x00:
+      reg = "x";
+      break;
+    case 0x01:
+      reg = "y";
+      break;
+    case 0x02:
+      reg = "s";
+      break;
+    }
+
+  status = read_memory (memaddr, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  int8_t v = byte;
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s, (%d,%s)", reg, v, reg);
+}
+
+
+/* PC Relative offsets of size 15 or 7 bits */
+static void
+rel_15_7 (bfd_vma memaddr, struct disassemble_info* info, int offset)
+{
+  bfd_byte upper;
+  int status = read_memory (memaddr, &upper, 1, info);
+  if (status < 0)
+    return;
+
+  bool rel_size = (upper & 0x80);
+
+  int16_t addr = upper;
+  if (rel_size)
+    {
+      /* 15 bits.  Get the next byte */
+      bfd_byte lower;
+      status = read_memory (memaddr + 1, &lower, 1, info);
+      if (status < 0)
+	return;
+
+      addr <<= 8;
+      addr |= lower;
+      addr &= 0x7FFF;
+
+      bool negative = (addr & 0x4000);
+      addr &= 0x3FFF;
+      if (negative)
+	addr = addr - 0x4000;
+    }
+  else
+    {
+      /* 7 bits. */
+      bool negative = (addr & 0x40);
+      addr &= 0x3F;
+      if (negative)
+	addr = addr - 0x40;
+    }
+
+  operand_separator (info);
+  if (!info->symbol_at_address_func (addr + memaddr - offset, info))
+    {
+      (*info->fprintf_func) (info->stream, "*%+d", addr);
+    }
+  else
+    {
+      asymbol *sym = NULL;
+      int i;
+      for (i = 0; i < info->symtab_size; ++i)
+	{
+	  sym = info->symtab[i];
+	  if (bfd_asymbol_value (sym) == addr + memaddr - offset)
+	    {
+	      break;
+	    }
+	}
+      if (i < info->symtab_size)
+	(*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
+    }
+}
+
+
+/* PC Relative offsets of size 15 or 7 bits */
+static void
+decode_rel_15_7 (bfd_vma memaddr, struct disassemble_info* info)
+{
+  rel_15_7 (memaddr, info, 1);
+}
+
+struct opcode
+{
+  const char *mnemonic;
+  insn_bytes_f insn_bytes;
+  operands_f operands;
+  operands_f operands2;
+};
+
+static int shift_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
+static int mov_imm_opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
+static int loop_prim_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
+static void mov_imm_opr (bfd_vma memaddr, struct disassemble_info* info);
+static void bm_rel_decode (bfd_vma memaddr, struct disassemble_info* info);
+static int bm_rel_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
+static int mul_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
+static void mul_decode (bfd_vma memaddr, struct disassemble_info* info);
+static int bm_n_bytes (bfd_vma memaddr, struct disassemble_info* info);
+static void bm_decode (bfd_vma memaddr, struct disassemble_info* info);
+
+static void
+cmp_xy (bfd_vma memaddr ATTRIBUTE_UNUSED, struct disassemble_info* info)
+{
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "x, y");
+}
+
+static void
+sub_d6_x_y (bfd_vma memaddr ATTRIBUTE_UNUSED, struct disassemble_info* info)
+{
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "d6, x, y");
+}
+
+static void
+sub_d6_y_x (bfd_vma memaddr ATTRIBUTE_UNUSED, struct disassemble_info* info)
+{
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "d6, y, x");
+}
+
+static const char shift_size_table[] = {
+  'b', 'w', 'p', 'l'
+};
+
+static const struct opcode page2[] =
+  {
+    [0x00] = {"ld",  opr_n_bytes_p1, 0, reg_s_opr},
+    [0x01] = {"st",  opr_n_bytes_p1, 0, reg_s_opr},
+    [0x02] = {"cmp", opr_n_bytes_p1, 0, reg_s_opr},
+    [0x03] = {"ld",  four, 0, reg_s_imm},
+    [0x04] = {"cmp", four, 0, reg_s_imm},
+    [0x05] = {"stop", single, 0, 0},
+    [0x06] = {"wai",  single, 0, 0},
+    [0x07] = {"sys",  single, 0, 0},
+    [0x08] = {NULL,  bfextins_n_bytes, 0, 0},  /* BFEXT / BFINS */
+    [0x09] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x0a] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x0b] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x0c] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x0d] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x0e] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x0f] = {NULL,  bfextins_n_bytes, 0, 0},
+    [0x10] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x11] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x12] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x13] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x14] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x15] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x16] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x17] = {"minu", opr_n_bytes_p1, reg, opr_decode},
+    [0x18] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x19] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x1a] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x1b] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x1c] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x1d] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x1e] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x1f] = {"maxu", opr_n_bytes_p1, reg, opr_decode},
+    [0x20] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x21] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x22] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x23] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x24] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x25] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x26] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x27] = {"mins", opr_n_bytes_p1, reg, opr_decode},
+    [0x28] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x29] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x2a] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x2b] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x2c] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x2d] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x2e] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x2f] = {"maxs", opr_n_bytes_p1, reg, opr_decode},
+    [0x30] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x31] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x32] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x33] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x34] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x35] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x36] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x37] = {"div", mul_n_bytes, mul_decode, 0},
+    [0x38] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x39] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x3a] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x3b] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x3c] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x3d] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x3e] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x3f] = {"mod", mul_n_bytes, mul_decode, 0},
+    [0x40] = {"abs", single, reg, 0},
+    [0x41] = {"abs", single, reg, 0},
+    [0x42] = {"abs", single, reg, 0},
+    [0x43] = {"abs", single, reg, 0},
+    [0x44] = {"abs", single, reg, 0},
+    [0x45] = {"abs", single, reg, 0},
+    [0x46] = {"abs", single, reg, 0},
+    [0x47] = {"abs", single, reg, 0},
+    [0x48] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x49] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x4a] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x4b] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x4c] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x4d] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x4e] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x4f] = {"mac", mul_n_bytes, mul_decode, 0},
+    [0x50] = {"adc", three, reg, imm1234_0base},
+    [0x51] = {"adc", three, reg, imm1234_0base},
+    [0x52] = {"adc", three, reg, imm1234_0base},
+    [0x53] = {"adc", three, reg, imm1234_0base},
+    [0x54] = {"adc", two,   reg, imm1234_0base},
+    [0x55] = {"adc", two,   reg, imm1234_0base},
+    [0x56] = {"adc", five,  reg, imm1234_0base},
+    [0x57] = {"adc", five,  reg, imm1234_0base},
+    [0x58] = {"bit", three, reg, imm1234_8base},
+    [0x59] = {"bit", three, reg, imm1234_8base},
+    [0x5a] = {"bit", three, reg, imm1234_8base},
+    [0x5b] = {"bit", three, reg, imm1234_8base},
+    [0x5c] = {"bit", two,   reg, imm1234_8base},
+    [0x5d] = {"bit", two,   reg, imm1234_8base},
+    [0x5e] = {"bit", five,  reg, imm1234_8base},
+    [0x5f] = {"bit", five,  reg, imm1234_8base},
+    [0x60] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x61] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x62] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x63] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x64] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x65] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x66] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x67] = {"adc", opr_n_bytes_p1, reg, opr_decode},
+    [0x68] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x69] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x6a] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x6b] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x6c] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x6d] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x6e] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x6f] = {"bit", opr_n_bytes_p1, reg, opr_decode},
+    [0x70] = {"sbc", three, reg, imm1234_0base},
+    [0x71] = {"sbc", three, reg, imm1234_0base},
+    [0x72] = {"sbc", three, reg, imm1234_0base},
+    [0x73] = {"sbc", three, reg, imm1234_0base},
+    [0x74] = {"sbc", two,   reg, imm1234_0base},
+    [0x75] = {"sbc", two,   reg, imm1234_0base},
+    [0x76] = {"sbc", five,  reg, imm1234_0base},
+    [0x77] = {"sbc", five,  reg, imm1234_0base},
+    [0x78] = {"eor", three, reg, imm1234_8base},
+    [0x79] = {"eor", three, reg, imm1234_8base},
+    [0x7a] = {"eor", three, reg, imm1234_8base},
+    [0x7b] = {"eor", three, reg, imm1234_8base},
+    [0x7c] = {"eor", two,   reg, imm1234_8base},
+    [0x7d] = {"eor", two,   reg, imm1234_8base},
+    [0x7e] = {"eor", five,  reg, imm1234_8base},
+    [0x7f] = {"eor", five,  reg, imm1234_8base},
+    [0x80] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x81] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x82] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x83] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x84] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x85] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x86] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x87] = {"sbc", opr_n_bytes_p1, reg, opr_decode},
+    [0x88] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x89] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8a] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8b] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8c] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8d] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8e] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8f] = {"eor", opr_n_bytes_p1, reg,    opr_decode},
+    [0x90] = {"rti",  single, 0, 0},
+    [0x91] = {"clb",   two, tfr, 0},
+    [0x92] = {"trap",  single, trap_decode, 0},
+    [0x93] = {"trap",  single, trap_decode, 0},
+    [0x94] = {"trap",  single, trap_decode, 0},
+    [0x95] = {"trap",  single, trap_decode, 0},
+    [0x96] = {"trap",  single, trap_decode, 0},
+    [0x97] = {"trap",  single, trap_decode, 0},
+    [0x98] = {"trap",  single, trap_decode, 0},
+    [0x99] = {"trap",  single, trap_decode, 0},
+    [0x9a] = {"trap",  single, trap_decode, 0},
+    [0x9b] = {"trap",  single, trap_decode, 0},
+    [0x9c] = {"trap",  single, trap_decode, 0},
+    [0x9d] = {"trap",  single, trap_decode, 0},
+    [0x9e] = {"trap",  single, trap_decode, 0},
+    [0x9f] = {"trap",  single, trap_decode, 0},
+    [0xa0] = {"sat", single, reg, 0},
+    [0xa1] = {"sat", single, reg, 0},
+    [0xa2] = {"sat", single, reg, 0},
+    [0xa3] = {"sat", single, reg, 0},
+    [0xa4] = {"sat", single, reg, 0},
+    [0xa5] = {"sat", single, reg, 0},
+    [0xa6] = {"sat", single, reg, 0},
+    [0xa7] = {"sat", single, reg, 0},
+    [0xa8] = {"trap",  single, trap_decode, 0},
+    [0xa9] = {"trap",  single, trap_decode, 0},
+    [0xaa] = {"trap",  single, trap_decode, 0},
+    [0xab] = {"trap",  single, trap_decode, 0},
+    [0xac] = {"trap",  single, trap_decode, 0},
+    [0xad] = {"trap",  single, trap_decode, 0},
+    [0xae] = {"trap",  single, trap_decode, 0},
+    [0xaf] = {"trap",  single, trap_decode, 0},
+    [0xb0] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb1] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb2] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb3] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb4] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb5] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb6] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb7] = {"qmul", mul_n_bytes, mul_decode, 0},
+    [0xb8] = {"trap",  single, trap_decode, 0},
+    [0xb9] = {"trap",  single, trap_decode, 0},
+    [0xba] = {"trap",  single, trap_decode, 0},
+    [0xbb] = {"trap",  single, trap_decode, 0},
+    [0xbc] = {"trap",  single, trap_decode, 0},
+    [0xbd] = {"trap",  single, trap_decode, 0},
+    [0xbe] = {"trap",  single, trap_decode, 0},
+    [0xbf] = {"trap",  single, trap_decode, 0},
+    [0xc0] = {"trap",  single, trap_decode, 0},
+    [0xc1] = {"trap",  single, trap_decode, 0},
+    [0xc2] = {"trap",  single, trap_decode, 0},
+    [0xc3] = {"trap",  single, trap_decode, 0},
+    [0xc4] = {"trap",  single, trap_decode, 0},
+    [0xc5] = {"trap",  single, trap_decode, 0},
+    [0xc6] = {"trap",  single, trap_decode, 0},
+    [0xc7] = {"trap",  single, trap_decode, 0},
+    [0xc8] = {"trap",  single, trap_decode, 0},
+    [0xc9] = {"trap",  single, trap_decode, 0},
+    [0xca] = {"trap",  single, trap_decode, 0},
+    [0xcb] = {"trap",  single, trap_decode, 0},
+    [0xcc] = {"trap",  single, trap_decode, 0},
+    [0xcd] = {"trap",  single, trap_decode, 0},
+    [0xce] = {"trap",  single, trap_decode, 0},
+    [0xcf] = {"trap",  single, trap_decode, 0},
+    [0xd0] = {"trap",  single, trap_decode, 0},
+    [0xd1] = {"trap",  single, trap_decode, 0},
+    [0xd2] = {"trap",  single, trap_decode, 0},
+    [0xd3] = {"trap",  single, trap_decode, 0},
+    [0xd4] = {"trap",  single, trap_decode, 0},
+    [0xd5] = {"trap",  single, trap_decode, 0},
+    [0xd6] = {"trap",  single, trap_decode, 0},
+    [0xd7] = {"trap",  single, trap_decode, 0},
+    [0xd8] = {"trap",  single, trap_decode, 0},
+    [0xd9] = {"trap",  single, trap_decode, 0},
+    [0xda] = {"trap",  single, trap_decode, 0},
+    [0xdb] = {"trap",  single, trap_decode, 0},
+    [0xdc] = {"trap",  single, trap_decode, 0},
+    [0xdd] = {"trap",  single, trap_decode, 0},
+    [0xde] = {"trap",  single, trap_decode, 0},
+    [0xdf] = {"trap",  single, trap_decode, 0},
+    [0xe0] = {"trap",  single, trap_decode, 0},
+    [0xe1] = {"trap",  single, trap_decode, 0},
+    [0xe2] = {"trap",  single, trap_decode, 0},
+    [0xe3] = {"trap",  single, trap_decode, 0},
+    [0xe4] = {"trap",  single, trap_decode, 0},
+    [0xe5] = {"trap",  single, trap_decode, 0},
+    [0xe6] = {"trap",  single, trap_decode, 0},
+    [0xe7] = {"trap",  single, trap_decode, 0},
+    [0xe8] = {"trap",  single, trap_decode, 0},
+    [0xe9] = {"trap",  single, trap_decode, 0},
+    [0xea] = {"trap",  single, trap_decode, 0},
+    [0xeb] = {"trap",  single, trap_decode, 0},
+    [0xec] = {"trap",  single, trap_decode, 0},
+    [0xed] = {"trap",  single, trap_decode, 0},
+    [0xee] = {"trap",  single, trap_decode, 0},
+    [0xef] = {"trap",  single, trap_decode, 0},
+    [0xf0] = {"trap",  single, trap_decode, 0},
+    [0xf1] = {"trap",  single, trap_decode, 0},
+    [0xf2] = {"trap",  single, trap_decode, 0},
+    [0xf3] = {"trap",  single, trap_decode, 0},
+    [0xf4] = {"trap",  single, trap_decode, 0},
+    [0xf5] = {"trap",  single, trap_decode, 0},
+    [0xf6] = {"trap",  single, trap_decode, 0},
+    [0xf7] = {"trap",  single, trap_decode, 0},
+    [0xf8] = {"trap",  single, trap_decode, 0},
+    [0xf9] = {"trap",  single, trap_decode, 0},
+    [0xfa] = {"trap",  single, trap_decode, 0},
+    [0xfb] = {"trap",  single, trap_decode, 0},
+    [0xfc] = {"trap",  single, trap_decode, 0},
+    [0xfd] = {"trap",  single, trap_decode, 0},
+    [0xfe] = {"trap",  single, trap_decode, 0},
+    [0xff] = {"trap",  single, trap_decode, 0},
+  };
+
+static const struct opcode page1[] =
+  {
+    [0x00] = {"bgnd", single, 0, 0},
+    [0x01] = {"nop",  single, 0, 0},
+    [0x02] = {"brclr", bm_rel_n_bytes, bm_rel_decode, 0},
+    [0x03] = {"brset", bm_rel_n_bytes, bm_rel_decode, 0},
+    [0x04] = {NULL,   two,    0, 0}, /* psh/pul */
+    [0x05] = {"rts",  single, 0, 0},
+    [0x06] = {"lea", opr_n_bytes_p1, reg, opr_decode},
+    [0x07] = {"lea", opr_n_bytes_p1, reg, opr_decode},
+    [0x08] = {"lea", opr_n_bytes_p1, lea_reg_xys_opr, 0},
+    [0x09] = {"lea", opr_n_bytes_p1, lea_reg_xys_opr, 0},
+    [0x0a] = {"lea", opr_n_bytes_p1, lea_reg_xys_opr, 0},
+    [0x0b] = {NULL, loop_prim_n_bytes, 0, 0}, /* Loop primitives TBcc / DBcc */
+    [0x0c] = {"mov.b", mov_imm_opr_n_bytes, mov_imm_opr, 0},
+    [0x0d] = {"mov.w", mov_imm_opr_n_bytes, mov_imm_opr, 0},
+    [0x0e] = {"mov.p", mov_imm_opr_n_bytes, mov_imm_opr, 0},
+    [0x0f] = {"mov.l", mov_imm_opr_n_bytes, mov_imm_opr, 0},
+    [0x10] = {NULL,   shift_n_bytes, 0, 0},  /* lsr/lsl/asl/asr/rol/ror */
+    [0x11] = {NULL,   shift_n_bytes, 0, 0},
+    [0x12] = {NULL,   shift_n_bytes, 0, 0},
+    [0x13] = {NULL,   shift_n_bytes, 0, 0},
+    [0x14] = {NULL,   shift_n_bytes, 0, 0},
+    [0x15] = {NULL,   shift_n_bytes, 0, 0},
+    [0x16] = {NULL,   shift_n_bytes, 0, 0},
+    [0x17] = {NULL,   shift_n_bytes, 0, 0},
+    [0x18] = {"lea",  two, lea_reg_xys, NULL},
+    [0x19] = {"lea",  two, lea_reg_xys, NULL},
+    [0x1a] = {"lea",  two, lea_reg_xys, NULL},
+    /* 0x1b PG2 */
+    [0x1c] = {"mov.b", opr_n_bytes2, 0, opr_decode2},
+    [0x1d] = {"mov.w", opr_n_bytes2, 0, opr_decode2},
+    [0x1e] = {"mov.p", opr_n_bytes2, 0, opr_decode2},
+    [0x1f] = {"mov.l", opr_n_bytes2, 0, opr_decode2},
+    [0x20] = {"bra",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x21] = {"bsr",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x22] = {"bhi",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x23] = {"bls",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x24] = {"bcc",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x25] = {"bcs",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x26] = {"bne",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x27] = {"beq",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x28] = {"bvc",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x29] = {"bvs",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x2a] = {"bpl",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x2b] = {"bmi",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x2c] = {"bge",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x2d] = {"blt",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x2e] = {"bgt",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x2f] = {"ble",  pcrel_15bit, decode_rel_15_7, 0},
+    [0x30] = {"inc", single, reg, 0},
+    [0x31] = {"inc", single, reg, 0},
+    [0x32] = {"inc", single, reg, 0},
+    [0x33] = {"inc", single, reg, 0},
+    [0x34] = {"inc", single, reg, 0},
+    [0x35] = {"inc", single, reg, 0},
+    [0x36] = {"inc", single, reg, 0},
+    [0x37] = {"inc", single, reg, 0},
+    [0x38] = {"clr", single, reg, 0},
+    [0x39] = {"clr", single, reg, 0},
+    [0x3a] = {"clr", single, reg, 0},
+    [0x3b] = {"clr", single, reg, 0},
+    [0x3c] = {"clr", single, reg, 0},
+    [0x3d] = {"clr", single, reg, 0},
+    [0x3e] = {"clr", single, reg, 0},
+    [0x3f] = {"clr", single, reg, 0},
+    [0x40] = {"dec", single, reg, 0},
+    [0x41] = {"dec", single, reg, 0},
+    [0x42] = {"dec", single, reg, 0},
+    [0x43] = {"dec", single, reg, 0},
+    [0x44] = {"dec", single, reg, 0},
+    [0x45] = {"dec", single, reg, 0},
+    [0x46] = {"dec", single, reg, 0},
+    [0x47] = {"dec", single, reg, 0},
+    [0x48] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x49] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x4a] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x4b] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x4c] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x4d] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x4e] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x4f] = {"mul", mul_n_bytes, mul_decode, 0},
+    [0x50] = {"add", three, reg, imm1234_0base},
+    [0x51] = {"add", three, reg, imm1234_0base},
+    [0x52] = {"add", three, reg, imm1234_0base},
+    [0x53] = {"add", three, reg, imm1234_0base},
+    [0x54] = {"add", two,   reg, imm1234_0base},
+    [0x55] = {"add", two,   reg, imm1234_0base},
+    [0x56] = {"add", five,  reg, imm1234_0base},
+    [0x57] = {"add", five,  reg, imm1234_0base},
+    [0x58] = {"and", three, reg, imm1234_8base},
+    [0x59] = {"and", three, reg, imm1234_8base},
+    [0x5a] = {"and", three, reg, imm1234_8base},
+    [0x5b] = {"and", three, reg, imm1234_8base},
+    [0x5c] = {"and", two,   reg, imm1234_8base},
+    [0x5d] = {"and", two,   reg, imm1234_8base},
+    [0x5e] = {"and", five,  reg, imm1234_8base},
+    [0x5f] = {"and", five,  reg, imm1234_8base},
+    [0x60] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x61] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x62] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x63] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x64] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x65] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x66] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x67] = {"add", opr_n_bytes_p1, reg, opr_decode},
+    [0x68] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x69] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x6a] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x6b] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x6c] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x6d] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x6e] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x6f] = {"and", opr_n_bytes_p1, reg, opr_decode},
+    [0x70] = {"sub", three, reg, imm1234_0base},
+    [0x71] = {"sub", three, reg, imm1234_0base},
+    [0x72] = {"sub", three, reg, imm1234_0base},
+    [0x73] = {"sub", three, reg, imm1234_0base},
+    [0x74] = {"sub", two,   reg, imm1234_0base},
+    [0x75] = {"sub", two,   reg, imm1234_0base},
+    [0x76] = {"sub", five,  reg, imm1234_0base},
+    [0x77] = {"sub", five,  reg, imm1234_0base},
+    [0x78] = {"or", three, reg, imm1234_8base},
+    [0x79] = {"or", three, reg, imm1234_8base},
+    [0x7a] = {"or", three, reg, imm1234_8base},
+    [0x7b] = {"or", three, reg, imm1234_8base},
+    [0x7c] = {"or", two,   reg, imm1234_8base},
+    [0x7d] = {"or", two,   reg, imm1234_8base},
+    [0x7e] = {"or", five,  reg, imm1234_8base},
+    [0x7f] = {"or", five,  reg, imm1234_8base},
+    [0x80] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x81] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x82] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x83] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x84] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x85] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x86] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x87] = {"sub", opr_n_bytes_p1, reg,    opr_decode},
+    [0x88] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x89] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8a] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8b] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8c] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8d] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8e] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x8f] = {"or", opr_n_bytes_p1, reg,    opr_decode},
+    [0x90] = {"ld", three,  reg, imm1234_0base},
+    [0x91] = {"ld", three,  reg, imm1234_0base},
+    [0x92] = {"ld", three,  reg, imm1234_0base},
+    [0x93] = {"ld", three,  reg, imm1234_0base},
+    [0x94] = {"ld", two,    reg, imm1234_0base},
+    [0x95] = {"ld", two,    reg, imm1234_0base},
+    [0x96] = {"ld", five,   reg, imm1234_0base},
+    [0x97] = {"ld", five,   reg, imm1234_0base},
+    [0x98] = {"ld", four,   reg_xy, imm1234_0base},
+    [0x99] = {"ld", four,   reg_xy, imm1234_0base},
+    [0x9a] = {"clr", single, reg_xy, 0},
+    [0x9b] = {"clr", single, reg_xy, 0},
+    [0x9c] = {"inc.b", opr_n_bytes_p1, 0, opr_decode},
+    [0x9d] = {"inc.w", opr_n_bytes_p1, 0, opr_decode},
+    [0x9e] = {"tfr", two, tfr, NULL},
+    [0x9f] = {"inc.l", opr_n_bytes_p1, 0, opr_decode},
+    [0xa0] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa1] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa2] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa3] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa4] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa5] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa6] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa7] = {"ld", opr_n_bytes_p1, reg,    opr_decode},
+    [0xa8] = {"ld", opr_n_bytes_p1, reg_xy, opr_decode},
+    [0xa9] = {"ld", opr_n_bytes_p1, reg_xy, opr_decode},
+    [0xaa] = {"jmp", opr_n_bytes_p1, opr_decode, 0},
+    [0xab] = {"jsr", opr_n_bytes_p1, opr_decode, 0},
+    [0xac] = {"dec.b", opr_n_bytes_p1, 0, opr_decode},
+    [0xad] = {"dec.w", opr_n_bytes_p1, 0, opr_decode},
+    [0xae] = {NULL,   two, 0, 0},  /* EXG / SEX */
+    [0xaf] = {"dec.l", opr_n_bytes_p1, 0, opr_decode},
+    [0xb0] = {"ld", four,  reg, ext24_decode},
+    [0xb1] = {"ld", four,  reg, ext24_decode},
+    [0xb2] = {"ld", four,  reg, ext24_decode},
+    [0xb3] = {"ld", four,  reg, ext24_decode},
+    [0xb4] = {"ld", four,  reg, ext24_decode},
+    [0xb5] = {"ld", four,  reg, ext24_decode},
+    [0xb6] = {"ld", four,  reg, ext24_decode},
+    [0xb7] = {"ld", four,  reg, ext24_decode},
+    [0xb8] = {"ld", four,  reg_xy, ext24_decode},
+    [0xb9] = {"ld", four,  reg_xy, ext24_decode},
+    [0xba] = {"jmp", four, ext24_decode, 0},
+    [0xbb] = {"jsr", four, ext24_decode, 0},
+    [0xbc] = {"clr.b", opr_n_bytes_p1, 0, opr_decode},
+    [0xbd] = {"clr.w", opr_n_bytes_p1, 0, opr_decode},
+    [0xbe] = {"clr.p", opr_n_bytes_p1, 0, opr_decode},
+    [0xbf] = {"clr.l", opr_n_bytes_p1, 0, opr_decode},
+    [0xc0] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc1] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc2] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc3] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc4] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc5] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc6] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc7] = {"st", opr_n_bytes_p1, reg,    opr_decode},
+    [0xc8] = {"st", opr_n_bytes_p1, reg_xy, opr_decode},
+    [0xc9] = {"st", opr_n_bytes_p1, reg_xy, opr_decode},
+    [0xca] = {"ld", three, reg_xy, ld_18bit_decode},
+    [0xcb] = {"ld", three, reg_xy, ld_18bit_decode},
+    [0xcc] = {"com.b", opr_n_bytes_p1, NULL, opr_decode},
+    [0xcd] = {"com.w", opr_n_bytes_p1, NULL, opr_decode},
+    [0xce] = {"andcc", two, imm1, 0},
+    [0xcf] = {"com.l", opr_n_bytes_p1, NULL, opr_decode},
+    [0xd0] = {"st", four,  reg, ext24_decode},
+    [0xd1] = {"st", four,  reg, ext24_decode},
+    [0xd2] = {"st", four,  reg, ext24_decode},
+    [0xd3] = {"st", four,  reg, ext24_decode},
+    [0xd4] = {"st", four,  reg, ext24_decode},
+    [0xd5] = {"st", four,  reg, ext24_decode},
+    [0xd6] = {"st", four,  reg, ext24_decode},
+    [0xd7] = {"st", four,  reg, ext24_decode},
+    [0xd8] = {"st", four,  reg_xy, ext24_decode},
+    [0xd9] = {"st", four,  reg_xy, ext24_decode},
+    [0xda] = {"ld", three, reg_xy, ld_18bit_decode},
+    [0xdb] = {"ld", three, reg_xy, ld_18bit_decode},
+    [0xdc] = {"neg.b", opr_n_bytes_p1, NULL, opr_decode},
+    [0xdd] = {"neg.w", opr_n_bytes_p1, NULL, opr_decode},
+    [0xde] = {"orcc",  two,  imm1, 0},
+    [0xdf] = {"neg.l", opr_n_bytes_p1, NULL, opr_decode},
+    [0xe0] = {"cmp", three,  reg, imm1234_0base},
+    [0xe1] = {"cmp", three,  reg, imm1234_0base},
+    [0xe2] = {"cmp", three,  reg, imm1234_0base},
+    [0xe3] = {"cmp", three,  reg, imm1234_0base},
+    [0xe4] = {"cmp", two,    reg, imm1234_0base},
+    [0xe5] = {"cmp", two,    reg, imm1234_0base},
+    [0xe6] = {"cmp", five,   reg, imm1234_0base},
+    [0xe7] = {"cmp", five,   reg, imm1234_0base},
+    [0xe8] = {"cmp", four,   reg_xy, imm1234_0base},
+    [0xe9] = {"cmp", four,   reg_xy, imm1234_0base},
+    [0xea] = {"ld", three, reg_xy, ld_18bit_decode},
+    [0xeb] = {"ld", three, reg_xy, ld_18bit_decode},
+    [0xec] = {"bclr", bm_n_bytes, bm_decode, 0},
+    [0xed] = {"bset", bm_n_bytes, bm_decode, 0},
+    [0xee] = {"btgl", bm_n_bytes, bm_decode, 0},
+    [0xef] = {"!!invalid!!", NULL, NULL, NULL}, /* SPARE */
+    [0xf0] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf1] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf2] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf3] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf4] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf5] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf6] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf7] = {"cmp", opr_n_bytes_p1, reg,    opr_decode},
+    [0xf8] = {"cmp", opr_n_bytes_p1, reg_xy, opr_decode},
+    [0xf9] = {"cmp", opr_n_bytes_p1, reg_xy, opr_decode},
+    [0xfa] = {"ld",  three, reg_xy, ld_18bit_decode},
+    [0xfb] = {"ld",  three, reg_xy, ld_18bit_decode},
+    [0xfc] = {"cmp", single, cmp_xy, 0},
+    [0xfd] = {"sub", single, sub_d6_x_y, 0},
+    [0xfe] = {"sub", single, sub_d6_y_x, 0},
+    [0xff] = {"swi", single, 0, 0}
+  };
+
+
+static const char *oprregs1[] =
+  {
+    "d3", "d2", "d1", "d0", "ccl", "cch"
+  };
+
+static const char *oprregs2[] =
+  {
+    "y", "x", "d7", "d6", "d5", "d4"
+  };
+
+
+
+
+enum MUL_MODE
+  {
+    MUL_REG_REG,
+    MUL_REG_OPR,
+    MUL_REG_IMM,
+    MUL_OPR_OPR
+  };
+
+struct mb
+{
+  uint8_t mask;
+  uint8_t value;
+  enum MUL_MODE mode;
+};
+
+static const struct mb mul_table[] = {
+  {0x40, 0x00, MUL_REG_REG},
+
+  {0x47, 0x40, MUL_REG_OPR},
+  {0x47, 0x41, MUL_REG_OPR},
+  {0x47, 0x43, MUL_REG_OPR},
+
+  {0x47, 0x44, MUL_REG_IMM},
+  {0x47, 0x45, MUL_REG_IMM},
+  {0x47, 0x47, MUL_REG_IMM},
+
+  {0x43, 0x42, MUL_OPR_OPR},
+};
+
+static void
+mul_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  uint8_t mb;
+  int status = read_memory (memaddr, &mb, 1, info);
+  if (status < 0)
+    return;
+
+
+  uint8_t byte;
+  status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return;
+
+  (*info->fprintf_func) (info->stream, "%c", (mb & 0x80) ? 's' : 'u');
+
+  enum MUL_MODE mode = -1;
+  size_t i;
+  for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
+    {
+      const struct mb *mm = mul_table + i;
+      if ((mb & mm->mask) == mm->value)
+	{
+	  mode = mm->mode;
+	  break;
+	}
+    }
+
+  switch (mode)
+    {
+    case MUL_REG_REG:
+      break;
+    case MUL_OPR_OPR:
+      {
+	int size1 = (mb & 0x30) >> 4;
+	int size2 = (mb & 0x0c) >> 2;
+	(*info->fprintf_func) (info->stream, ".%c%c",
+			       shift_size_table [size1],
+			       shift_size_table [size2]);
+      }
+      break;
+    default:
+      {
+	int size = (mb & 0x3);
+	(*info->fprintf_func) (info->stream, ".%c", shift_size_table [size]);
+      }
+      break;
+    }
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x7].name);
+
+  switch (mode)
+    {
+    case MUL_REG_REG:
+    case MUL_REG_IMM:
+    case MUL_REG_OPR:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", registers[(mb & 0x38) >> 3].name);
+      break;
+    default:
+      break;
+    }
+
+  switch (mode)
+    {
+    case MUL_REG_IMM:
+      operand_separator (info);
+      int size = (mb & 0x3);
+      uint32_t imm = decode_signed_value (memaddr + 1, info, size + 1);
+      (*info->fprintf_func) (info->stream, "#%d", imm);
+      break;
+    case MUL_REG_REG:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", registers[mb & 0x07].name);
+      break;
+    case MUL_REG_OPR:
+      opr_decode (memaddr + 1, info);
+      break;
+    case MUL_OPR_OPR:
+      {
+	int first = opr_n_bytes (memaddr + 1, info);
+	opr_decode (memaddr + 1, info);
+	opr_decode (memaddr + first + 1, info);
+	break;
+      }
+    }
+}
+
+
+static int
+mul_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  int nx = 2;
+  uint8_t mb;
+  int status = read_memory (memaddr, &mb, 1, info);
+  if (status < 0)
+    return 0;
+
+  enum MUL_MODE mode = -1;
+  size_t i;
+  for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
+    {
+      const struct mb *mm = mul_table + i;
+      if ((mb & mm->mask) == mm->value)
+	{
+	  mode = mm->mode;
+	  break;
+	}
+    }
+
+  int size = (mb & 0x3) + 1;
+
+  switch (mode)
+    {
+    case MUL_REG_IMM:
+      nx += size;
+      break;
+    case MUL_REG_REG:
+      break;
+    case MUL_REG_OPR:
+      nx += opr_n_bytes (memaddr + 1, info);
+      break;
+    case MUL_OPR_OPR:
+      {
+	int first = opr_n_bytes (memaddr + nx - 1, info);
+	nx += first;
+	int second = opr_n_bytes (memaddr + nx - 1, info);
+	nx += second;
+      }
+      break;
+    }
+
+  return nx;
+}
+
+
+enum BM_MODE {
+  BM_REG_IMM,
+  BM_RESERVED0,
+  BM_OPR_B,
+  BM_OPR_W,
+  BM_OPR_L,
+  BM_OPR_REG,
+  BM_RESERVED1
+};
+
+struct bm
+{
+  uint8_t mask;
+  uint8_t value;
+  enum BM_MODE mode;
+};
+
+static const  struct bm bm_table[] = {
+  { 0xC6, 0x04,     BM_REG_IMM},
+  { 0x84, 0x00,     BM_REG_IMM},
+  { 0x06, 0x06,     BM_REG_IMM},
+  { 0xC6, 0x44,     BM_RESERVED0},
+  // 00
+  { 0x8F, 0x80,     BM_OPR_B},
+  { 0x8E, 0x82,     BM_OPR_W},
+  { 0x8C, 0x88,     BM_OPR_L},
+
+  { 0x83, 0x81,     BM_OPR_REG},
+  { 0x87, 0x84,     BM_RESERVED1},
+};
+
+static void
+bm_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  uint8_t bm;
+  int status = read_memory (memaddr, &bm, 1, info);
+  if (status < 0)
+    return;
+
+  size_t i;
+  enum BM_MODE mode = -1;
+  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
+    {
+      const struct bm *bme = bm_table + i;
+      if ((bm & bme->mask) == bme->value)
+	{
+	  mode = bme->mode;
+	  break;
+	}
+    }
+
+  switch (mode)
+    {
+    case BM_REG_IMM:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", registers[bm & 0x07].name);
+      break;
+    case BM_OPR_B:
+      (*info->fprintf_func) (info->stream, ".%c", 'b');
+      opr_decode (memaddr + 1, info);
+      break;
+    case BM_OPR_W:
+      (*info->fprintf_func) (info->stream, ".%c", 'w');
+      opr_decode (memaddr + 1, info);
+      break;
+    case BM_OPR_L:
+      (*info->fprintf_func) (info->stream, ".%c", 'l');
+      opr_decode (memaddr + 1, info);
+      break;
+    case BM_OPR_REG:
+      {
+	uint8_t xb;
+	read_memory (memaddr + 1, &xb, 1, info);
+	/* Don't emit a size suffix for register operands */
+	if ((xb & 0xF8) != 0xB8)
+	  (*info->fprintf_func) (info->stream, ".%c", shift_size_table[(bm & 0x0c) >> 2]);
+	opr_decode (memaddr + 1, info);
+      }
+      break;
+    case BM_RESERVED0:
+    case BM_RESERVED1:
+      assert (0);
+      break;
+    }
+
+  uint8_t imm = 0;
+  operand_separator (info);
+  switch (mode)
+    {
+    case BM_REG_IMM:
+      {
+	imm = (bm & 0xF8) >> 3;
+	(*info->fprintf_func) (info->stream, "#%d", imm);
+      }
+      break;
+    case BM_OPR_L:
+      imm |= (bm & 0x03) << 3;
+      /* fallthrough */
+    case BM_OPR_W:
+      imm |= (bm & 0x01) << 3;
+      /* fallthrough */
+    case BM_OPR_B:
+      imm |= (bm & 0x70) >> 4;
+      (*info->fprintf_func) (info->stream, "#%d", imm);
+      break;
+    case BM_OPR_REG:
+      (*info->fprintf_func) (info->stream, "%s", registers[(bm & 0x70) >> 4].name);
+      break;
+    case BM_RESERVED0:
+    case BM_RESERVED1:
+      assert (0);
+      break;
+    }
+}
+
+
+static void
+bm_rel_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  uint8_t bm;
+  int status = read_memory (memaddr, &bm, 1, info);
+  if (status < 0)
+    return;
+
+  size_t i;
+  enum BM_MODE mode = -1;
+  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
+    {
+      const struct bm *bme = bm_table + i;
+      if ((bm & bme->mask) == bme->value)
+	{
+	  mode = bme->mode;
+	  break;
+	}
+    }
+
+  switch (mode)
+    {
+    case BM_REG_IMM:
+      break;
+    case BM_OPR_B:
+      (*info->fprintf_func) (info->stream, ".%c", 'b');
+      break;
+    case BM_OPR_W:
+      (*info->fprintf_func) (info->stream, ".%c", 'w');
+      break;
+    case BM_OPR_L:
+      (*info->fprintf_func) (info->stream, ".%c", 'l');
+      break;
+    case BM_OPR_REG:
+      {
+	uint8_t xb;
+	read_memory (memaddr + 1, &xb, 1, info);
+	/* Don't emit a size suffix for register operands */
+	if ((xb & 0xF8) != 0xB8)
+	  (*info->fprintf_func) (info->stream, ".%c",
+				 shift_size_table[(bm & 0x0C) >> 2]);
+      }
+      break;
+    case BM_RESERVED0:
+    case BM_RESERVED1:
+      assert (0);
+      break;
+    }
+
+  int n = 1;
+  switch (mode)
+    {
+    case BM_REG_IMM:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", registers[bm & 0x07].name);
+      break;
+    case BM_OPR_B:
+    case BM_OPR_W:
+    case BM_OPR_L:
+      opr_decode (memaddr + 1, info);
+      n = 1 + opr_n_bytes (memaddr + 1, info);
+      break;
+    case BM_OPR_REG:
+      opr_decode (memaddr + 1, info);
+      break;
+    case BM_RESERVED0:
+    case BM_RESERVED1:
+      assert (0);
+      break;
+    }
+
+
+  int imm = 0;
+  operand_separator (info);
+  switch (mode)
+    {
+    case BM_OPR_L:
+      imm |= (bm & 0x02) << 3;
+      /* fall through */
+    case BM_OPR_W:
+      imm |= (bm & 0x01) << 3;
+      /* fall through */
+    case BM_OPR_B:
+      imm |= (bm & 0x70) >> 4;
+      (*info->fprintf_func) (info->stream, "#%d", imm);
+      break;
+    case BM_REG_IMM:
+      imm = (bm & 0xF8) >> 3;
+      (*info->fprintf_func) (info->stream, "#%d", imm);
+      break;
+    case BM_RESERVED0:
+    case BM_RESERVED1:
+      assert (0);
+      break;
+    case BM_OPR_REG:
+      (*info->fprintf_func) (info->stream, "%s", registers[(bm & 0x70) >> 4].name);
+      n += opr_n_bytes (memaddr + 1, info);
+      break;
+    }
+
+  rel_15_7 (memaddr + n, info, n + 1);
+}
+
+static int
+bm_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  uint8_t bm;
+  int status = read_memory (memaddr, &bm, 1, info);
+  if (status < 0)
+    return status;
+
+  size_t i;
+  enum BM_MODE mode = -1;
+  for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
+    {
+      const struct bm *bme = bm_table + i;
+      if ((bm & bme->mask) == bme->value)
+	{
+	  mode = bme->mode;
+	  break;
+	}
+    }
+
+  int n = 2;
+  switch (mode)
+    {
+    case BM_REG_IMM:
+      break;
+
+    case BM_OPR_B:
+    case BM_OPR_W:
+    case BM_OPR_L:
+      n += opr_n_bytes (memaddr + 1, info);
+      break;
+    case BM_OPR_REG:
+      n += opr_n_bytes (memaddr + 1, info);
+      break;
+    default:
+      break;
+  }
+
+  return n;
+}
+
+static int
+bm_rel_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  int n = 1 + bm_n_bytes (memaddr, info);
+
+  bfd_byte rb;
+  int status = read_memory (memaddr + n - 2, &rb, 1, info);
+  if (status != 0)
+    return status;
+
+  if (rb & 0x80)
+    n++;
+
+  return n;
+}
+
+
+
+
+
+/* shift direction */
+enum SB_DIR
+  {
+    SB_LEFT,
+    SB_RIGHT
+  };
+
+enum SB_TYPE
+  {
+    SB_ARITHMETIC,
+    SB_LOGICAL
+  };
+
+
+enum SB_MODE
+  {
+    SB_REG_REG_N_EFF,
+    SB_REG_REG_N,
+    SB_REG_OPR_EFF,
+    SB_ROT,
+    SB_REG_OPR_OPR,
+    SB_OPR_N
+  };
+
+struct sb
+{
+  uint8_t mask;
+  uint8_t value;
+  enum SB_MODE mode;
+};
+
+static const  struct sb sb_table[] = {
+  {0x30, 0x00,     SB_REG_REG_N_EFF},
+  {0x30, 0x10,     SB_REG_REG_N},
+  {0x34, 0x20,     SB_REG_OPR_EFF},
+  {0x34, 0x24,     SB_ROT},
+  {0x34, 0x30,     SB_REG_OPR_OPR},
+  {0x34, 0x34,     SB_OPR_N},
+};
+
+static int
+shift_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte sb;
+  int status = read_memory (memaddr++, &sb, 1, info);
+  if (status != 0)
+    return status;
+
+  size_t i;
+  enum SB_MODE mode = -1;
+  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
+    {
+      const struct sb *sbe = sb_table + i;
+      if ((sb & sbe->mask) == sbe->value)
+	mode = sbe->mode;
+    }
+
+  switch (mode)
+    {
+    case SB_REG_REG_N_EFF:
+      return 2;
+      break;
+    case SB_REG_OPR_EFF:
+    case SB_ROT:
+	return 2 + opr_n_bytes (memaddr, info);
+      break;
+    case SB_REG_OPR_OPR:
+      {
+	int opr1 = opr_n_bytes (memaddr, info);
+	int opr2 = 0;
+	if ((sb & 0x30) != 0x20)
+	  opr2 = opr_n_bytes (memaddr + opr1, info);
+	return 2 + opr1 + opr2;
+      }
+      break;
+    default:
+      return 3;
+    }
+
+  /* not reached */
+  return -1;
+}
+
+
+static int
+mov_imm_opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return status;
+
+  int size = byte - 0x0c + 1;
+
+  return size + opr_n_bytes (memaddr + size, info) + 1;
+}
+
+static void
+mov_imm_opr (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr - 1, &byte, 1, info);
+  if (status < 0)
+    return ;
+
+  int size = byte - 0x0c + 1;
+  uint32_t imm = decode_signed_value (memaddr, info, size);
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "#%d", imm);
+  opr_decode (memaddr + size, info);
+}
+
+
+
+static void
+ld_18bit_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+  size_t size = 3;
+  bfd_byte buffer[3];
+  int status = read_memory (memaddr, buffer + 1, 2, info);
+  if (status < 0)
+    return ;
+
+
+  status = read_memory (memaddr - 1, buffer, 1, info);
+  if (status < 0)
+    return ;
+
+  buffer[0] = (buffer[0] & 0x30) >> 4;
+
+  size_t i;
+  uint32_t imm = 0;
+  for (i = 0; i < size; ++i)
+    {
+      imm |= buffer[i] << (8 * (size - i - 1));
+    }
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "#%d", imm);
+}
+
+
+
+/* Loop Primitives */
+
+enum LP_MODE {
+  LP_REG,
+  LP_XY,
+  LP_OPR
+};
+
+struct lp
+{
+  uint8_t mask;
+  uint8_t value;
+  enum LP_MODE mode;
+};
+
+static const struct lp lp_mode[] = {
+  {0x08, 0x00, LP_REG},
+  {0x0C, 0x08, LP_XY},
+  {0x0C, 0x0C, LP_OPR},
+};
+
+
+static const char *lb_condition[] =
+  {
+    "ne", "eq", "pl", "mi", "gt", "le",
+    "??", "??"
+  };
+
+static int
+loop_prim_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+  int mx = 0;
+  uint8_t lb;
+  read_memory (memaddr + mx++, &lb, 1, info);
+
+  enum LP_MODE mode = -1;
+  size_t i;
+  for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
+    {
+      const struct lp *pb = lp_mode + i;
+      if ((lb & pb->mask) == pb->value)
+	{
+	  mode = pb->mode;
+	  break;
+	}
+    }
+
+  if (mode == LP_OPR)
+    {
+      mx += opr_n_bytes (memaddr + mx, info) ;
+    }
+
+  uint8_t rb;
+  read_memory (memaddr + mx++, &rb, 1, info);
+  if (rb & 0x80)
+    mx++;
+
+  return mx + 1;
+}
+
+
+
+
+static int
+print_insn_exg_sex (bfd_vma memaddr, struct disassemble_info* info)
+{
+  uint8_t eb;
+  int status = read_memory (memaddr, &eb, 1, info);
+  if (status < 0)
+    return -1;
+
+  const struct reg *first =  &registers[(eb & 0xf0) >> 4];
+  const struct reg *second = &registers[(eb & 0xf)];
+
+  if (first->bytes < second->bytes)
+    (*info->fprintf_func) (info->stream, "sex");
+  else
+    (*info->fprintf_func) (info->stream, "exg");
+
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s", first->name);
+  operand_separator (info);
+  (*info->fprintf_func) (info->stream, "%s", second->name);
+  return 0;
+}
+
+
+
+static int
+print_insn_loop_primitive (bfd_vma memaddr, struct disassemble_info* info)
+{
+  int offs = 1;
+  uint8_t lb;
+  int status = read_memory (memaddr, &lb, 1, info);
+
+  char mnemonic[7];
+  int x = 0;
+  mnemonic[x++] = (lb & 0x80) ? 'd' : 't';
+  mnemonic[x++] = 'b';
+  stpcpy (mnemonic + x, lb_condition [(lb & 0x70) >> 4]);
+  x += 2;
+
+  const char *reg  = NULL;
+  enum LP_MODE mode = -1;
+  size_t i;
+  for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
+    {
+      const struct lp *pb = lp_mode + i;
+      if ((lb & pb->mask) == pb->value)
+	{
+	  mode = pb->mode;
+	  break;
+	}
+    }
+
+  switch (mode)
+    {
+    case LP_REG:
+      reg = registers [lb & 0x07].name;
+      break;
+    case LP_XY:
+      reg = (lb & 0x1) ? "y" : "x";
+      break;
+    case LP_OPR:
+      mnemonic[x++] = '.';
+      mnemonic[x++] = shift_size_table [lb & 0x03];
+      offs += opr_n_bytes (memaddr + 1, info);
+      break;
+    }
+
+  mnemonic[x++] = '\0';
+
+  (*info->fprintf_func) (info->stream, "%s", mnemonic);
+
+  if (mode == LP_OPR)
+    opr_decode (memaddr + 1, info);
+  else
+    {
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", reg);
+    }
+
+  rel_15_7 (memaddr + offs, info, offs + 1);
+
+  return status;
+}
+
+
+static int
+print_insn_shift (bfd_vma memaddr, struct disassemble_info* info, uint8_t byte)
+{
+  size_t i;
+  uint8_t sb;
+  int status = read_memory (memaddr, &sb, 1, info);
+  if (status < 0)
+    return status;
+
+  enum SB_DIR  dir = (sb & 0x40) ? SB_LEFT : SB_RIGHT;
+  enum SB_TYPE type = (sb & 0x80) ? SB_ARITHMETIC : SB_LOGICAL;
+  enum SB_MODE mode = -1;
+  for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
+    {
+      const struct sb *sbe = sb_table + i;
+      if ((sb & sbe->mask) == sbe->value)
+	mode = sbe->mode;
+    }
+
+  char mnemonic[6];
+  int x = 0;
+  if (mode == SB_ROT)
+    {
+      mnemonic[x++] = 'r';
+      mnemonic[x++] = 'o';
+    }
+  else
+    {
+      mnemonic[x++] = (type == SB_LOGICAL) ? 'l' : 'a';
+      mnemonic[x++] = 's';
+    }
+
+  mnemonic[x++] = (dir == SB_LEFT) ? 'l' : 'r';
+
+  switch (mode)
+    {
+    case SB_REG_OPR_EFF:
+    case SB_ROT:
+    case SB_REG_OPR_OPR:
+      mnemonic[x++] = '.';
+      mnemonic[x++] = shift_size_table[sb & 0x03];
+      break;
+    case SB_OPR_N:
+      {
+	uint8_t xb;
+	read_memory (memaddr + 1, &xb, 1, info);
+	/* The size suffix is not printed if the OPR operand refers
+	   directly to a register, because the size is implied by the
+	   size of that register. */
+	if ((xb & 0xF8) != 0xB8)
+	  {
+	    mnemonic[x++] = '.';
+	    mnemonic[x++] = shift_size_table[sb & 0x03];
+	  }
+      }
+      break;
+    default:
+      break;
+    };
+
+  mnemonic[x++] = '\0';
+
+  (*info->fprintf_func) (info->stream, "%s", mnemonic);
+
+  /* Destination register */
+  switch (mode)
+    {
+    case SB_REG_REG_N_EFF:
+    case SB_REG_REG_N:
+    case SB_REG_OPR_EFF:
+    case SB_REG_OPR_OPR:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x7].name);
+      break;
+
+    case SB_ROT:
+      opr_decode (memaddr + 1, info);
+      break;
+
+    default:
+      break;
+    }
+
+  /* Source register */
+  switch (mode)
+    {
+    case SB_REG_REG_N_EFF:
+    case SB_REG_REG_N:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "%s", registers[sb & 0x7].name);
+      break;
+
+    case SB_REG_OPR_OPR:
+      opr_decode (memaddr + 1, info);
+      break;
+
+    default:
+      break;
+    }
+
+  /* 3rd arg */
+  switch (mode)
+    {
+    case SB_REG_OPR_EFF:
+    case SB_OPR_N:
+      opr_decode (memaddr + 1, info);
+      break;
+
+    case SB_REG_REG_N:
+      if (sb & 0x08)
+	{
+	  operand_separator (info);
+	  if (byte & 0x10)
+	    {
+	      uint8_t xb;
+	      read_memory (memaddr + 1, &xb, 1, info);
+	      int shift = ((sb & 0x08) >> 3) | ((xb & 0x0f) << 1);
+	      (*info->fprintf_func) (info->stream, "#%d", shift);
+	    }
+	  else
+	    {
+	      (*info->fprintf_func) (info->stream, "%s:%d", __FILE__, __LINE__);
+	    }
+	}
+      else
+	{
+	  opr_decode (memaddr + 1, info);
+	}
+      break;
+    case SB_REG_OPR_OPR:
+      {
+      uint8_t xb;
+      int n = opr_n_bytes (memaddr + 1, info);
+      read_memory (memaddr + 1 + n, &xb, 1, info);
+
+      if ((xb & 0xF0) == 0x70)
+	{
+	  int imm = xb & 0x0F;
+	  imm <<= 1;
+	  imm |= (sb & 0x08) >> 3;
+	  operand_separator (info);
+	  (*info->fprintf_func) (info->stream, "#%d", imm);
+	}
+      else
+	{
+	  opr_decode (memaddr + 1 + n, info);
+	}
+      }
+      break;
+    default:
+      break;
+    }
+
+  switch (mode)
+    {
+    case SB_REG_REG_N_EFF:
+    case SB_REG_OPR_EFF:
+    case SB_OPR_N:
+      operand_separator (info);
+      (*info->fprintf_func) (info->stream, "#%d",
+			     (sb & 0x08) ? 2 : 1);
+      break;
+
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+int
+print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
+{
+  bfd_byte byte;
+  int status = read_memory (memaddr++, &byte, 1, info);
+  if (status != 0)
+    return status;
+
+  const struct opcode *opc2 = NULL;
+  const struct opcode *opc = page1 + byte;
+  if (opc->mnemonic)
+    {
+      (*info->fprintf_func) (info->stream, "%s", opc->mnemonic);
+    }
+  else
+    {
+      /* The special cases ... */
+      switch (byte)
+	{
+	case PAGE2_PREBYTE:
+	  {
+	    bfd_byte byte2;
+	    read_memory (memaddr++, &byte2, 1, info);
+	    opc2 = page2 + byte2;
+	    if (opc2->mnemonic)
+	      {
+		(*info->fprintf_func) (info->stream, "%s", opc2->mnemonic);
+
+		if (opc2->operands)
+		  {
+		    opc2->operands (memaddr, info);
+		  }
+
+		if (opc2->operands2)
+		  {
+		    opc2->operands2 (memaddr, info);
+		  }
+	      }
+	    else if (byte2 >= 0x08 && byte2 <= 0x1F)
+	      {
+		bfd_byte bb;
+		read_memory (memaddr, &bb, 1, info);
+		if (bb & 0x80)
+		  (*info->fprintf_func) (info->stream, "bfins");
+		else
+		  (*info->fprintf_func) (info->stream, "bfext");
+
+		enum BB_MODE mode = -1;
+		size_t i;
+		const struct opr_bb *bbs = 0;
+		for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
+		  {
+		    bbs = bb_modes + i;
+		    if ((bb & bbs->mask) == bbs->value)
+		      {
+			mode = bbs->mode;
+			break;
+		      }
+		  }
+
+		switch (mode)
+		  {
+		  case BB_REG_OPR_REG:
+		  case BB_REG_OPR_IMM:
+		  case BB_OPR_REG_REG:
+		  case BB_OPR_REG_IMM:
+		    {
+		      int size = (bb >> 2) & 0x03;
+		      (*info->fprintf_func) (info->stream, ".%c",
+					     shift_size_table [size]);
+		    }
+		    break;
+		  default:
+		    break;
+		  }
+
+		int reg1 = byte2 & 0x07;
+		/* First operand */
+		switch (mode)
+		  {
+		  case BB_REG_REG_REG:
+		  case BB_REG_REG_IMM:
+		  case BB_REG_OPR_REG:
+		  case BB_REG_OPR_IMM:
+		    operand_separator (info);
+		    (*info->fprintf_func) (info->stream, "%s",
+					   registers[reg1].name);
+		    break;
+		  case BB_OPR_REG_REG:
+		    opr_decode (memaddr + 1, info);
+		    break;
+		  case BB_OPR_REG_IMM:
+		    opr_decode (memaddr + 2, info);
+		    break;
+		  }
+
+		/* Second operand */
+		switch (mode)
+		  {
+		  case BB_REG_REG_REG:
+		  case BB_REG_REG_IMM:
+		    {
+		      int reg_src = (bb >> 2) & 0x07;
+		      operand_separator (info);
+		      (*info->fprintf_func) (info->stream, "%s",
+					     registers[reg_src].name);
+		    }
+		    break;
+		  case BB_OPR_REG_REG:
+		  case BB_OPR_REG_IMM:
+		    {
+		      int reg_src = (byte2 & 0x07);
+		      operand_separator (info);
+		      (*info->fprintf_func) (info->stream, "%s",
+					     registers[reg_src].name);
+		    }
+		    break;
+		  case BB_REG_OPR_REG:
+		    opr_decode (memaddr + 1, info);
+		    break;
+		  case BB_REG_OPR_IMM:
+		    opr_decode (memaddr + 2, info);
+		    break;
+		  }
+
+		/* Third operand */
+		operand_separator (info);
+		switch (mode)
+		  {
+		  case BB_REG_REG_REG:
+		  case BB_OPR_REG_REG:
+		  case BB_REG_OPR_REG:
+		    {
+		      int reg_parm = bb & 0x03;
+		      (*info->fprintf_func) (info->stream, "%s",
+					     registers[reg_parm].name);
+		    }
+		    break;
+		  case BB_REG_REG_IMM:
+		  case BB_OPR_REG_IMM:
+		  case BB_REG_OPR_IMM:
+		    {
+		      bfd_byte i1;
+		      read_memory (memaddr + 1, &i1, 1, info);
+		      int offset = i1 & 0x1f;
+		      int width = bb & 0x03;
+		      width <<= 3;
+		      width |= i1 >> 5;
+		      (*info->fprintf_func) (info->stream, "#%d:%d", width,  offset);
+		    }
+		    break;
+		  }
+	      }
+	  }
+	  break;
+	case 0xae: /* EXG / SEX */
+	  status = print_insn_exg_sex (memaddr, info);
+	  break;
+	case 0x0b:  /* Loop Primitives TBcc and DBcc */
+	  status = print_insn_loop_primitive (memaddr, info);
+	  break;
+	case 0x10:  	    /* shift */
+	case 0x11:  	    /* shift */
+	case 0x12:  	    /* shift */
+	case 0x13:  	    /* shift */
+	case 0x14:  	    /* shift */
+	case 0x15:  	    /* shift */
+	case 0x16:  	    /* shift */
+	case 0x17:  	    /* shift */
+	  status = print_insn_shift (memaddr, info, byte);
+	  break;
+	case 0x04:  	    /* psh / pul */
+	  {
+	    read_memory (memaddr, &byte, 1, info);
+	    (*info->fprintf_func) (info->stream, (byte & 0x80) ? "pul" : "psh");
+	    int bit;
+	    if (byte & 0x40)
+	      {
+		if ((byte & 0x3F) == 0)
+		  {
+		    operand_separator (info);
+		    (*info->fprintf_func) (info->stream, "%s", "ALL16b");
+		  }
+		else
+		  for (bit = 5; bit >= 0; --bit)
+		    {
+		      if (byte & (0x1 << bit))
+			{
+			  operand_separator (info);
+			  (*info->fprintf_func) (info->stream, "%s", oprregs2[bit]);
+			}
+		    }
+	      }
+	    else
+	      {
+		if ((byte & 0x3F) == 0)
+		  {
+		    operand_separator (info);
+		    (*info->fprintf_func) (info->stream, "%s", "ALL");
+		  }
+		else
+		  for (bit = 5; bit >= 0; --bit)
+		    {
+		      if (byte & (0x1 << bit))
+			{
+			  operand_separator (info);
+			  (*info->fprintf_func) (info->stream, "%s", oprregs1[bit]);
+			}
+		    }
+	      }
+	  }
+	  break;
+	default:
+	  operand_separator (info);
+	  (*info->fprintf_func) (info->stream, "???");
+	  break;
+	}
+    }
+
+  if (opc2 == NULL)
+    {
+      if (opc->operands)
+	{
+	  opc->operands (memaddr, info);
+	}
+
+      if (opc->operands2)
+	{
+	  opc->operands2 (memaddr, info);
+	}
+    }
+
+  int n = 0;
+
+  /* Opcodes in page2 have an additional byte */
+  if (opc2)
+    n++;
+
+  if (opc2 && opc2->insn_bytes == 0)
+    return n;
+
+  if (!opc2 && opc->insn_bytes == 0)
+    return n;
+
+  if (opc2)
+    n += opc2->insn_bytes (memaddr, info);
+  else
+    n += opc->insn_bytes (memaddr, info);
+
+  return n;
+}
diff --git a/opcodes/s12z.h b/opcodes/s12z.h
new file mode 100644
index 0000000000..7e38ac5e1c
--- /dev/null
+++ b/opcodes/s12z.h
@@ -0,0 +1,71 @@
+#ifndef S12Z_H
+#define S12Z_H
+
+/* This byte is used to prefix instructions in "page 2" of the opcode
+   space */
+#define PAGE2_PREBYTE (0x1b)
+
+struct reg
+{
+  char      *name;   /* The canonical name of the register */
+  int       bytes;   /* its size, in bytes */
+};
+
+
+/* How many registers do we have.  Actually there are only 13,
+   because CCL and CCH are the low and high bytes of CCW.  But
+   for assemnbly / disassembly purposes they are considered
+   distinct registers. */
+#define S12Z_N_REGISTERS 15
+
+extern const struct reg registers[S12Z_N_REGISTERS];
+
+enum {
+    REG_D2 = 0,
+    REG_D3,
+    REG_D4,
+    REG_D5,
+    REG_D0,
+    REG_D1,
+    REG_D6,
+    REG_D7,
+    REG_X,
+    REG_Y,
+    REG_S,
+    REG_P,
+    REG_CCH,
+    REG_CCL,
+    REG_CCW
+  };
+
+/* Any of the registers d0, d1, ... d7 */
+#define REG_BIT_Dn \
+((0x1U << REG_D2) | \
+ (0x1U << REG_D3) | \
+ (0x1U << REG_D4) | \
+ (0x1U << REG_D5) | \
+ (0x1U << REG_D6) | \
+ (0x1U << REG_D7) | \
+ (0x1U << REG_D0) | \
+ (0x1U << REG_D1))
+
+/* Any of the registers x, y or z */
+#define REG_BIT_XYS \
+((0x1U << REG_X) | \
+ (0x1U << REG_Y) | \
+ (0x1U << REG_S))
+
+/* Any of the registers x, y, z or p */
+#define REG_BIT_XYSP \
+((0x1U << REG_X)  | \
+ (0x1U << REG_Y)  | \
+ (0x1U << REG_S)  | \
+ (0x1U << REG_P))
+
+/* The x register or the y register */
+#define REG_BIT_XY \
+((0x1U << REG_X) | \
+ (0x1U << REG_Y))
+
+
+#endif
-- 
2.11.0

Attachment: signature.asc
Description: Digital signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]