]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add support for the Freescale s12z processor.
authorJohn Darrington <john@darrington.wattle.id.au>
Fri, 18 May 2018 14:26:18 +0000 (15:26 +0100)
committerNick Clifton <nickc@redhat.com>
Fri, 18 May 2018 14:26:18 +0000 (15:26 +0100)
bfd * Makefile.am: Add s12z files.
* Makefile.in: Regenerate.
* archures.c: Add bfd_s12z_arch.
* bfd-in.h: Add exports of bfd_putb24 and bfd_putl24.
* bfd-in2.h: Regenerate.
* config.bfd: Add s12z target.
* configure.ac: Add s12z target.
* configure: Regenerate.
* cpu-s12z.c: New file.
* elf32-s12z.c: New file.
* libbfd.c (bfd_putb24): New function.
(bfd_putl24): New function.
* libbfd.h: Regenerate.
* reloc.c: Add s12z relocations.
(bfd_get_reloc_size): Handle size 5 relocs.
* targets.c: Add s12z_elf32_vec.

opcodes * Makefile.am: Add support for s12z architecture.
* configure.ac: Likewise.
* disassemble.c: Likewise.
* disassemble.h: Likewise.
* Makefile.in: Regenerate.
* configure: Regenerate.
* s12z-dis.c: New file.
* s12z.h: New file.

include * elf/s12z.h: New header.

ld * Makefile.am: Add support for s12z architecture.
* configure.tgt: Likewise.
* Makefile.in: Regenerate.
* emulparams/m9s12zelf.sh: New file.
* scripttempl/elfm9s12z.sc: New file.
* testsuite/ld-discard/static.d: Expect to fail for the s12z
target.
* testsuite/ld-elf/endsym.d: Likewise.
* testsuite/ld-elf/merge.d: Likewise.
* testsuite/ld-elf/pr14926.d: Skip for the s12z target.
* testsuite/ld-elf/sec64k.exp: Likewise.
* testsuite/ld-s12z: New directory.
* testsuite/ld-s12z/opr-linking.d: New file.
* testsuite/ld-s12z/opr-linking.s: New file.
* testsuite/ld-s12z/relative-linking.d: New file.
* testsuite/ld-s12z/relative-linking.s: New file.
* testsuite/ld-s12z/z12s.exp: New file.

gas * Makefile.am: Add support for s12z target.
* Makefile.in: Regenerate.
* NEWS: Mention the new support.
* config/tc-s12z.c: New file.
* config/tc-s12z.h: New file.
* configure.tgt: Add  s12z support.
* doc/Makefile.am: Likewise.
* doc/Makefile.in: Regenerate.
* doc/all.texi: Add s12z documentation.
* doc/as.textinfo: Likewise.
* doc/c-s12z.texi: New file.
* testsuite/gas/s12z: New directory.
* testsuite/gas/s12z/abs.d: New file.
* testsuite/gas/s12z/abs.s: New file.
* testsuite/gas/s12z/adc-imm.d: New file.
* testsuite/gas/s12z/adc-imm.s: New file.
* testsuite/gas/s12z/adc-opr.d: New file.
* testsuite/gas/s12z/adc-opr.s: New file.
* testsuite/gas/s12z/add-imm.d: New file.
* testsuite/gas/s12z/add-imm.s: New file.
* testsuite/gas/s12z/add-opr.d: New file.
* testsuite/gas/s12z/add-opr.s: New file.
* testsuite/gas/s12z/and-imm.d: New file.
* testsuite/gas/s12z/and-imm.s: New file.
* testsuite/gas/s12z/and-opr.d: New file.
* testsuite/gas/s12z/and-opr.s: New file.
* testsuite/gas/s12z/and-or-cc.d: New file.
* testsuite/gas/s12z/and-or-cc.s: New file.
* testsuite/gas/s12z/bfext-special.d: New file.
* testsuite/gas/s12z/bfext-special.s: New file.
* testsuite/gas/s12z/bfext.d: New file.
* testsuite/gas/s12z/bfext.s: New file.
* testsuite/gas/s12z/bit-manip.d: New file.
* testsuite/gas/s12z/bit-manip.s: New file.
* testsuite/gas/s12z/bit.d: New file.
* testsuite/gas/s12z/bit.s: New file.
* testsuite/gas/s12z/bra-expression-defined.d: New file.
* testsuite/gas/s12z/bra-expression-defined.s: New file.
* testsuite/gas/s12z/bra-expression-undef.d: New file.
* testsuite/gas/s12z/bra-expression-undef.s: New file.
* testsuite/gas/s12z/bra.d: New file.
* testsuite/gas/s12z/bra.s: New file.
* testsuite/gas/s12z/brclr-symbols.d: New file.
* testsuite/gas/s12z/brclr-symbols.s: New file.
* testsuite/gas/s12z/brset-clr-opr-imm-rel.d: New file.
* testsuite/gas/s12z/brset-clr-opr-imm-rel.s: New file.
* testsuite/gas/s12z/brset-clr-opr-reg-rel.d: New file.
* testsuite/gas/s12z/brset-clr-opr-reg-rel.s: New file.
* testsuite/gas/s12z/brset-clr-reg-imm-rel.d: New file.
* testsuite/gas/s12z/brset-clr-reg-imm-rel.s: New file.
* testsuite/gas/s12z/brset-clr-reg-reg-rel.d: New file.
* testsuite/gas/s12z/brset-clr-reg-reg-rel.s: New file.
* testsuite/gas/s12z/clb.d: New file.
* testsuite/gas/s12z/clb.s: New file.
* testsuite/gas/s12z/clr-opr.d: New file.
* testsuite/gas/s12z/clr-opr.s: New file.
* testsuite/gas/s12z/clr.d: New file.
* testsuite/gas/s12z/clr.s: New file.
* testsuite/gas/s12z/cmp-imm.d: New file.
* testsuite/gas/s12z/cmp-imm.s: New file.
* testsuite/gas/s12z/cmp-opr-inc.d: New file.
* testsuite/gas/s12z/cmp-opr-inc.s: New file.
* testsuite/gas/s12z/cmp-opr-rdirect.d: New file.
* testsuite/gas/s12z/cmp-opr-rdirect.s: New file.
* testsuite/gas/s12z/cmp-opr-reg.d: New file.
* testsuite/gas/s12z/cmp-opr-reg.s: New file.
* testsuite/gas/s12z/cmp-opr-rindirect.d: New file.
* testsuite/gas/s12z/cmp-opr-rindirect.s: New file.
* testsuite/gas/s12z/cmp-opr-sxe4.d: New file.
* testsuite/gas/s12z/cmp-opr-sxe4.s: New file.
* testsuite/gas/s12z/cmp-opr-xys.d: New file.
* testsuite/gas/s12z/cmp-opr-xys.s: New file.
* testsuite/gas/s12z/cmp-s-imm.d: New file.
* testsuite/gas/s12z/cmp-s-imm.s: New file.
* testsuite/gas/s12z/cmp-s-opr.d: New file.
* testsuite/gas/s12z/cmp-s-opr.s: New file.
* testsuite/gas/s12z/cmp-xy.d: New file.
* testsuite/gas/s12z/cmp-xy.s: New file.
* testsuite/gas/s12z/com-opr.d: New file.
* testsuite/gas/s12z/com-opr.s: New file.
* testsuite/gas/s12z/complex-shifts.d: New file.
* testsuite/gas/s12z/complex-shifts.s: New file.
* testsuite/gas/s12z/db-tb-cc-opr.d: New file.
* testsuite/gas/s12z/db-tb-cc-opr.s: New file.
* testsuite/gas/s12z/db-tb-cc-reg.d: New file.
* testsuite/gas/s12z/db-tb-cc-reg.s: New file.
* testsuite/gas/s12z/dbCC.d: New file.
* testsuite/gas/s12z/dbCC.s: New file.
* testsuite/gas/s12z/dec-opr.d: New file.
* testsuite/gas/s12z/dec-opr.s: New file.
* testsuite/gas/s12z/dec.d: New file.
* testsuite/gas/s12z/dec.s: New file.
* testsuite/gas/s12z/div.d: New file.
* testsuite/gas/s12z/div.s: New file.
* testsuite/gas/s12z/eor.d: New file.
* testsuite/gas/s12z/eor.s: New file.
* testsuite/gas/s12z/exg.d: New file.
* testsuite/gas/s12z/exg.s: New file.
* testsuite/gas/s12z/ext24-ld-xy.d: New file.
* testsuite/gas/s12z/ext24-ld-xy.s: New file.
* testsuite/gas/s12z/inc-opr.d: New file.
* testsuite/gas/s12z/inc-opr.s: New file.
* testsuite/gas/s12z/inc.d: New file.
* testsuite/gas/s12z/inc.s: New file.
* testsuite/gas/s12z/inh.d: New file.
* testsuite/gas/s12z/inh.s: New file.
* testsuite/gas/s12z/jmp.d: New file.
* testsuite/gas/s12z/jmp.s: New file.
* testsuite/gas/s12z/jsr.d: New file.
* testsuite/gas/s12z/jsr.s: New file.
* testsuite/gas/s12z/ld-imm-page2.d: New file.
* testsuite/gas/s12z/ld-imm-page2.s: New file.
* testsuite/gas/s12z/ld-imm.d: New file.
* testsuite/gas/s12z/ld-imm.s: New file.
* testsuite/gas/s12z/ld-immu18.d: New file.
* testsuite/gas/s12z/ld-immu18.s: New file.
* testsuite/gas/s12z/ld-large-direct.d: New file.
* testsuite/gas/s12z/ld-large-direct.s: New file.
* testsuite/gas/s12z/ld-opr.d: New file.
* testsuite/gas/s12z/ld-opr.s: New file.
* testsuite/gas/s12z/ld-s-opr.d: New file.
* testsuite/gas/s12z/ld-s-opr.s: New file.
* testsuite/gas/s12z/ld-small-direct.d: New file.
* testsuite/gas/s12z/ld-small-direct.s: New file.
* testsuite/gas/s12z/lea-immu18.d: New file.
* testsuite/gas/s12z/lea-immu18.s: New file.
* testsuite/gas/s12z/lea.d: New file.
* testsuite/gas/s12z/lea.s: New file.
* testsuite/gas/s12z/mac.d: New file.
* testsuite/gas/s12z/mac.s: New file.
* testsuite/gas/s12z/min-max.d: New file.
* testsuite/gas/s12z/min-max.s: New file.
* testsuite/gas/s12z/mod.d: New file.
* testsuite/gas/s12z/mod.s: New file.
* testsuite/gas/s12z/mov.d: New file.
* testsuite/gas/s12z/mov.s: New file.
* testsuite/gas/s12z/mul-imm.d: New file.
* testsuite/gas/s12z/mul-imm.s: New file.
* testsuite/gas/s12z/mul-opr-opr.d: New file.
* testsuite/gas/s12z/mul-opr-opr.s: New file.
* testsuite/gas/s12z/mul-opr.d: New file.
* testsuite/gas/s12z/mul-opr.s: New file.
* testsuite/gas/s12z/mul-reg.d: New file.
* testsuite/gas/s12z/mul-reg.s: New file.
* testsuite/gas/s12z/mul.d: New file.
* testsuite/gas/s12z/mul.s: New file.
* testsuite/gas/s12z/neg-opr.d: New file.
* testsuite/gas/s12z/neg-opr.s: New file.
* testsuite/gas/s12z/not-so-simple-shifts.d: New file.
* testsuite/gas/s12z/not-so-simple-shifts.s: New file.
* testsuite/gas/s12z/opr-18u.d: New file.
* testsuite/gas/s12z/opr-18u.s: New file.
* testsuite/gas/s12z/opr-expr.d: New file.
* testsuite/gas/s12z/opr-expr.s: New file.
* testsuite/gas/s12z/opr-ext-18.d: New file.
* testsuite/gas/s12z/opr-ext-18.s: New file.
* testsuite/gas/s12z/opr-idx-24-reg.d: New file.
* testsuite/gas/s12z/opr-idx-24-reg.s: New file.
* testsuite/gas/s12z/opr-idx3-reg.d: New file.
* testsuite/gas/s12z/opr-idx3-reg.s: New file.
* testsuite/gas/s12z/opr-idx3-xysp-24.d: New file.
* testsuite/gas/s12z/opr-idx3-xysp-24.s: New file.
* testsuite/gas/s12z/opr-indirect-expr.d: New file.
* testsuite/gas/s12z/opr-indirect-expr.s: New file.
* testsuite/gas/s12z/opr-symbol.d: New file.
* testsuite/gas/s12z/opr-symbol.s: New file.
* testsuite/gas/s12z/or-imm.d: New file.
* testsuite/gas/s12z/or-imm.s: New file.
* testsuite/gas/s12z/or-opr.d: New file.
* testsuite/gas/s12z/or-opr.s: New file.
* testsuite/gas/s12z/p2-mul.d: New file.
* testsuite/gas/s12z/p2-mul.s: New file.
* testsuite/gas/s12z/page2-inh.d: New file.
* testsuite/gas/s12z/page2-inh.s: New file.
* testsuite/gas/s12z/psh-pul.d: New file.
* testsuite/gas/s12z/psh-pul.s: New file.
* testsuite/gas/s12z/qmul.d: New file.
* testsuite/gas/s12z/qmul.s: New file.
* testsuite/gas/s12z/rotate.d: New file.
* testsuite/gas/s12z/rotate.s: New file.
* testsuite/gas/s12z/s12z.exp: New file.
* testsuite/gas/s12z/sat.d: New file.
* testsuite/gas/s12z/sat.s: New file.
* testsuite/gas/s12z/sbc-imm.d: New file.
* testsuite/gas/s12z/sbc-imm.s: New file.
* testsuite/gas/s12z/sbc-opr.d: New file.
* testsuite/gas/s12z/sbc-opr.s: New file.
* testsuite/gas/s12z/shift.d: New file.
* testsuite/gas/s12z/shift.s: New file.
* testsuite/gas/s12z/simple-shift.d: New file.
* testsuite/gas/s12z/simple-shift.s: New file.
* testsuite/gas/s12z/single-ops.d: New file.
* testsuite/gas/s12z/single-ops.s: New file.
* testsuite/gas/s12z/specd6.d: New file.
* testsuite/gas/s12z/specd6.s: New file.
* testsuite/gas/s12z/st-large-direct.d: New file.
* testsuite/gas/s12z/st-large-direct.s: New file.
* testsuite/gas/s12z/st-opr.d: New file.
* testsuite/gas/s12z/st-opr.s: New file.
* testsuite/gas/s12z/st-s-opr.d: New file.
* testsuite/gas/s12z/st-s-opr.s: New file.
* testsuite/gas/s12z/st-small-direct.d: New file.
* testsuite/gas/s12z/st-small-direct.s: New file.
* testsuite/gas/s12z/st-xy.d: New file.
* testsuite/gas/s12z/st-xy.s: New file.
* testsuite/gas/s12z/sub-imm.d: New file.
* testsuite/gas/s12z/sub-imm.s: New file.
* testsuite/gas/s12z/sub-opr.d: New file.
* testsuite/gas/s12z/sub-opr.s: New file.
* testsuite/gas/s12z/tfr.d: New file.
* testsuite/gas/s12z/tfr.s: New file.
* testsuite/gas/s12z/trap.d: New file.
* testsuite/gas/s12z/trap.s: New file.

binutils* readelf.c: Add support for s12z architecture.
* testsuite/lib/binutils-common.exp (is_elf_format): Excluse s12z
targets.

259 files changed:
bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/archures.c
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/config.bfd
bfd/configure
bfd/configure.ac
bfd/cpu-s12z.c [new file with mode: 0644]
bfd/elf32-s12z.c [new file with mode: 0644]
bfd/libbfd.c
bfd/libbfd.h
bfd/reloc.c
bfd/targets.c
binutils/ChangeLog
binutils/readelf.c
binutils/testsuite/binutils-all/dw2-1.S
binutils/testsuite/lib/binutils-common.exp
gas/ChangeLog
gas/Makefile.am
gas/Makefile.in
gas/NEWS
gas/config/tc-s12z.c [new file with mode: 0644]
gas/config/tc-s12z.h [new file with mode: 0644]
gas/configure.tgt
gas/doc/Makefile.am
gas/doc/Makefile.in
gas/doc/all.texi
gas/doc/as.texinfo
gas/doc/c-s12z.texi [new file with mode: 0644]
gas/testsuite/gas/s12z/abs.d [new file with mode: 0644]
gas/testsuite/gas/s12z/abs.s [new file with mode: 0644]
gas/testsuite/gas/s12z/adc-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/adc-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/adc-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/adc-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/add-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/add-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/add-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/add-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/and-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/and-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/and-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/and-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/and-or-cc.d [new file with mode: 0644]
gas/testsuite/gas/s12z/and-or-cc.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bfext-special.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bfext-special.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bfext.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bfext.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bit-manip.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bit-manip.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bit.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bit.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bra-expression-defined.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bra-expression-defined.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bra-expression-undef.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bra-expression-undef.s [new file with mode: 0644]
gas/testsuite/gas/s12z/bra.d [new file with mode: 0644]
gas/testsuite/gas/s12z/bra.s [new file with mode: 0644]
gas/testsuite/gas/s12z/brclr-symbols.d [new file with mode: 0644]
gas/testsuite/gas/s12z/brclr-symbols.s [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d [new file with mode: 0644]
gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s [new file with mode: 0644]
gas/testsuite/gas/s12z/clb.d [new file with mode: 0644]
gas/testsuite/gas/s12z/clb.s [new file with mode: 0644]
gas/testsuite/gas/s12z/clr-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/clr-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/clr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/clr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-inc.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-inc.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-rdirect.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-rdirect.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-reg.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-reg.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-rindirect.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-rindirect.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-sxe4.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-sxe4.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-xys.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-opr-xys.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-s-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-s-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-s-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-s-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-xy.d [new file with mode: 0644]
gas/testsuite/gas/s12z/cmp-xy.s [new file with mode: 0644]
gas/testsuite/gas/s12z/com-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/com-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/complex-shifts.d [new file with mode: 0644]
gas/testsuite/gas/s12z/complex-shifts.s [new file with mode: 0644]
gas/testsuite/gas/s12z/db-tb-cc-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/db-tb-cc-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/db-tb-cc-reg.d [new file with mode: 0644]
gas/testsuite/gas/s12z/db-tb-cc-reg.s [new file with mode: 0644]
gas/testsuite/gas/s12z/dbCC.d [new file with mode: 0644]
gas/testsuite/gas/s12z/dbCC.s [new file with mode: 0644]
gas/testsuite/gas/s12z/dec-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/dec-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/dec.d [new file with mode: 0644]
gas/testsuite/gas/s12z/dec.s [new file with mode: 0644]
gas/testsuite/gas/s12z/div.d [new file with mode: 0644]
gas/testsuite/gas/s12z/div.s [new file with mode: 0644]
gas/testsuite/gas/s12z/eor.d [new file with mode: 0644]
gas/testsuite/gas/s12z/eor.s [new file with mode: 0644]
gas/testsuite/gas/s12z/exg.d [new file with mode: 0644]
gas/testsuite/gas/s12z/exg.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ext24-ld-xy.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ext24-ld-xy.s [new file with mode: 0644]
gas/testsuite/gas/s12z/inc-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/inc-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/inc.d [new file with mode: 0644]
gas/testsuite/gas/s12z/inc.s [new file with mode: 0644]
gas/testsuite/gas/s12z/inh.d [new file with mode: 0644]
gas/testsuite/gas/s12z/inh.s [new file with mode: 0644]
gas/testsuite/gas/s12z/jmp.d [new file with mode: 0644]
gas/testsuite/gas/s12z/jmp.s [new file with mode: 0644]
gas/testsuite/gas/s12z/jsr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/jsr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-imm-page2.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-imm-page2.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-immu18.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-immu18.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-large-direct.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-large-direct.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-s-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-s-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-small-direct.d [new file with mode: 0644]
gas/testsuite/gas/s12z/ld-small-direct.s [new file with mode: 0644]
gas/testsuite/gas/s12z/lea-immu18.d [new file with mode: 0644]
gas/testsuite/gas/s12z/lea-immu18.s [new file with mode: 0644]
gas/testsuite/gas/s12z/lea.d [new file with mode: 0644]
gas/testsuite/gas/s12z/lea.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mac.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mac.s [new file with mode: 0644]
gas/testsuite/gas/s12z/min-max.d [new file with mode: 0644]
gas/testsuite/gas/s12z/min-max.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mod.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mod.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mov.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mov.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-opr-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-opr-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-reg.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mul-reg.s [new file with mode: 0644]
gas/testsuite/gas/s12z/mul.d [new file with mode: 0644]
gas/testsuite/gas/s12z/mul.s [new file with mode: 0644]
gas/testsuite/gas/s12z/neg-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/neg-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/not-so-simple-shifts.d [new file with mode: 0644]
gas/testsuite/gas/s12z/not-so-simple-shifts.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-18u.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-18u.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-expr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-expr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-ext-18.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-ext-18.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-idx-24-reg.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-idx-24-reg.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-idx3-reg.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-idx3-reg.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-idx3-xysp-24.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-idx3-xysp-24.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-indirect-expr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-indirect-expr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-symbol.d [new file with mode: 0644]
gas/testsuite/gas/s12z/opr-symbol.s [new file with mode: 0644]
gas/testsuite/gas/s12z/or-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/or-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/or-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/or-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/p2-mul.d [new file with mode: 0644]
gas/testsuite/gas/s12z/p2-mul.s [new file with mode: 0644]
gas/testsuite/gas/s12z/page2-inh.d [new file with mode: 0644]
gas/testsuite/gas/s12z/page2-inh.s [new file with mode: 0644]
gas/testsuite/gas/s12z/psh-pul.d [new file with mode: 0644]
gas/testsuite/gas/s12z/psh-pul.s [new file with mode: 0644]
gas/testsuite/gas/s12z/qmul.d [new file with mode: 0644]
gas/testsuite/gas/s12z/qmul.s [new file with mode: 0644]
gas/testsuite/gas/s12z/rotate.d [new file with mode: 0644]
gas/testsuite/gas/s12z/rotate.s [new file with mode: 0644]
gas/testsuite/gas/s12z/s12z.exp [new file with mode: 0644]
gas/testsuite/gas/s12z/sat.d [new file with mode: 0644]
gas/testsuite/gas/s12z/sat.s [new file with mode: 0644]
gas/testsuite/gas/s12z/sbc-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/sbc-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/sbc-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/sbc-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/shift.d [new file with mode: 0644]
gas/testsuite/gas/s12z/shift.s [new file with mode: 0644]
gas/testsuite/gas/s12z/simple-shift.d [new file with mode: 0644]
gas/testsuite/gas/s12z/simple-shift.s [new file with mode: 0644]
gas/testsuite/gas/s12z/single-ops.d [new file with mode: 0644]
gas/testsuite/gas/s12z/single-ops.s [new file with mode: 0644]
gas/testsuite/gas/s12z/specd6.d [new file with mode: 0644]
gas/testsuite/gas/s12z/specd6.s [new file with mode: 0644]
gas/testsuite/gas/s12z/st-large-direct.d [new file with mode: 0644]
gas/testsuite/gas/s12z/st-large-direct.s [new file with mode: 0644]
gas/testsuite/gas/s12z/st-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/st-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/st-s-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/st-s-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/st-small-direct.d [new file with mode: 0644]
gas/testsuite/gas/s12z/st-small-direct.s [new file with mode: 0644]
gas/testsuite/gas/s12z/st-xy.d [new file with mode: 0644]
gas/testsuite/gas/s12z/st-xy.s [new file with mode: 0644]
gas/testsuite/gas/s12z/sub-imm.d [new file with mode: 0644]
gas/testsuite/gas/s12z/sub-imm.s [new file with mode: 0644]
gas/testsuite/gas/s12z/sub-opr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/sub-opr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/tfr.d [new file with mode: 0644]
gas/testsuite/gas/s12z/tfr.s [new file with mode: 0644]
gas/testsuite/gas/s12z/trap.d [new file with mode: 0644]
gas/testsuite/gas/s12z/trap.s [new file with mode: 0644]
include/ChangeLog
include/elf/s12z.h [new file with mode: 0644]
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/configure.tgt
ld/emulparams/m9s12zelf.sh [new file with mode: 0644]
ld/scripttempl/elfm9s12z.sc [new file with mode: 0644]
ld/testsuite/ld-discard/static.d
ld/testsuite/ld-elf/endsym.d
ld/testsuite/ld-elf/merge.d
ld/testsuite/ld-elf/pr14926.d
ld/testsuite/ld-elf/sec64k.exp
ld/testsuite/ld-s12z/opr-linking.d [new file with mode: 0644]
ld/testsuite/ld-s12z/opr-linking.s [new file with mode: 0644]
ld/testsuite/ld-s12z/relative-linking.d [new file with mode: 0644]
ld/testsuite/ld-s12z/relative-linking.s [new file with mode: 0644]
ld/testsuite/ld-s12z/z12s.exp [new file with mode: 0644]
opcodes/ChangeLog
opcodes/Makefile.am
opcodes/Makefile.in
opcodes/configure
opcodes/configure.ac
opcodes/disassemble.c
opcodes/disassemble.h
opcodes/s12z-dis.c [new file with mode: 0644]
opcodes/s12z.h [new file with mode: 0644]

index a9248e64d5026ad2b3b149f778101e8447bc7953..0319fa7f6dbda4833e616abe4a1fcb6d18d591a9 100644 (file)
@@ -1,3 +1,22 @@
+2018-05-18  John Darrington  <john@darrington.wattle.id.au>
+
+       * Makefile.am: Add s12z files.
+       * Makefile.in: Regenerate.
+       * archures.c: Add bfd_s12z_arch.
+       * bfd-in.h: Add exports of bfd_putb24 and bfd_putl24.
+       * bfd-in2.h: Regenerate.
+       * config.bfd: Add s12z target.
+       * configure.ac: Add s12z target.
+       * configure: Regenerate.
+       * cpu-s12z.c: New file.
+       * elf32-s12z.c: New file.
+       * libbfd.c (bfd_putb24): New function.
+       (bfd_putl24): New function.
+       * libbfd.h: Regenerate.
+       * reloc.c: Add s12z relocations.
+       (bfd_get_reloc_size): Handle size 5 relocs.
+       * targets.c: Add s12z_elf32_vec.
+
 2018-05-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/23189
index 8500a4fa74a9fc2f45812f5d08d43195e7cf120d..8374bbda209130b827649ee7b715345fe4a8708c 100644 (file)
@@ -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 \
index ccd9ce1201b777ef2708d85e14dacad2a96abd29..88b6b8ebd5632a84497773f3280ed0bb416838f1 100644 (file)
@@ -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@
index 4c206642571482c87d333eeb0d7466951065a0f6..3af7ddd19a2ea0d0e66f77499d3aff69cabd00a3 100644 (file)
@@ -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,
index 50a8b52e96fda7fe190561ee1f3e3691b08a3758..481587e458f1ce8f1d5164f114a5a22009ac295d 100644 (file)
@@ -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 *);
 
index 5f7ecd35dbac9d1fe5d3f4033562355a08701d73..c64eee1fe1e58859fabf395eca2cf079ee943b76 100644 (file)
@@ -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 *);
 
@@ -2149,6 +2151,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
@@ -5253,6 +5257,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,
index bbd41941539116271dbb1e5af9fca29bea48874a..0db8ed4562b2c11ce51e6a3b138c317f4014a1aa 100644 (file)
@@ -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"
index edc1de9bcedc014e5485794706cdbbff138c15bb..2f3dbe7de3b0e430c5756119f4d293d8bfc7ac1f 100755 (executable)
@@ -14465,6 +14465,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" ;;
index 12974691ad07a17d044470bc2bcd4ea59f625311..b320828fbb2de1f518711f927b9cdf9a82ee7059 100644 (file)
@@ -520,6 +520,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 (file)
index 0000000..07bcb49
--- /dev/null
@@ -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 (file)
index 0000000..4b638e6
--- /dev/null
@@ -0,0 +1,270 @@
+/* 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 ATTRIBUTE_UNUSED,
+                   void *data ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED,
+                   bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED)
+{
+  /* 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;
+}
+
+static bfd_boolean
+s12z_elf_set_mach_from_flags (bfd *abfd)
+{
+  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                      NULL
+#define elf_info_to_howto_rel                  s12z_info_to_howto_rel
+#define elf_backend_object_p                   s12z_elf_set_mach_from_flags
+#define elf_backend_final_write_processing     NULL
+#define elf_backend_can_gc_sections            1
+
+#include "elf32-target.h"
index c581238515c74ccee9411e38276ebe97e3933eab..971be4f3dec07533e182347422cd9bcbd367ba9f 100644 (file)
@@ -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)
 {
index e8c0fd8675528cb6997a9007814867ec31a5c3db..b810c40c405c620dfe27c11835a1087c3ce3b198 100644 (file)
@@ -2513,6 +2513,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",
index f7e34a993aef31faabb2bcf463e1f9e51d1ece69..411f998f54092df9a16b28192bf3f170db244344 100644 (file)
@@ -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);
@@ -5948,6 +5959,12 @@ ENUMDOC
   Motorola 68HC12/XGATE reloc.
   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
index 5d78f5745128178d681d6318690df87e9eef2842..5a2a684bc820b1a024706c9a0a4dc3f67dfc1a04 100644 (file)
@@ -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,
index 3d90103aba02c42a2835879214ba296de5bfd58c..fd77f44fbea091849685ebdc2a7b555526607f83 100644 (file)
@@ -1,3 +1,9 @@
+2018-05-18  John Darrington  <john@darrington.wattle.id.au>
+
+       * readelf.c: Add support for s12z architecture.
+       * testsuite/lib/binutils-common.exp (is_elf_format): Excluse s12z
+       targets.
+
 2018-05-15  Tamar Christina  <tamar.christina@arm.com>
 
        PR binutils/21446
index 6a9c51d4bb7db68441c1b630287fe285948a1bb8..6a9319f5dbfb545be3bd49a4f1b1c8dc517a018a 100644 (file)
 #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:
index 06cb593a2e258c3c85a297dbadf70671fd4c0e32..6342a0e8f839d275344d25389e06db085e228abe 100644 (file)
@@ -27,6 +27,8 @@ _start:
 func_cu1:
 .Lbegin_func_cu1:
        .4byte 0
+       .global func_cu1_end
+func_cu1_end:  
 .Lend_func_cu1:
        .size func_cu1, .-func_cu1
 .Lend_text1:
index 9fc9a18dae290940304b2bb3cd24d022b1eda4de..dcaab847d2409b808408d41f538744538cf1abcc 100644 (file)
@@ -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;
     }
 # vxworks (and windiss) excluded due to number of ELF tests that need
index c2a5659143b8a8fafb284a8ba3e313f612010260..39c51b23a0658ad90e6951369e15a9a2935e9f50 100644 (file)
@@ -1,3 +1,219 @@
+2018-05-18  John Darrington  <john@darrington.wattle.id.au>
+
+       * Makefile.am: Add support for s12z target.
+       * Makefile.in: Regenerate.
+       * NEWS: Mention the new support.
+       * config/tc-s12z.c: New file.
+       * config/tc-s12z.h: New file.
+       * configure.tgt: Add  s12z support.
+       * doc/Makefile.am: Likewise.
+       * doc/Makefile.in: Regenerate.
+       * doc/all.texi: Add s12z documentation.
+       * doc/as.textinfo: Likewise.
+       * doc/c-s12z.texi: New file.
+       * testsuite/gas/s12z: New directory.
+       * testsuite/gas/s12z/abs.d: New file.
+       * testsuite/gas/s12z/abs.s: New file.
+       * testsuite/gas/s12z/adc-imm.d: New file.
+       * testsuite/gas/s12z/adc-imm.s: New file.
+       * testsuite/gas/s12z/adc-opr.d: New file.
+       * testsuite/gas/s12z/adc-opr.s: New file.
+       * testsuite/gas/s12z/add-imm.d: New file.
+       * testsuite/gas/s12z/add-imm.s: New file.
+       * testsuite/gas/s12z/add-opr.d: New file.
+       * testsuite/gas/s12z/add-opr.s: New file.
+       * testsuite/gas/s12z/and-imm.d: New file.
+       * testsuite/gas/s12z/and-imm.s: New file.
+       * testsuite/gas/s12z/and-opr.d: New file.
+       * testsuite/gas/s12z/and-opr.s: New file.
+       * testsuite/gas/s12z/and-or-cc.d: New file.
+       * testsuite/gas/s12z/and-or-cc.s: New file.
+       * testsuite/gas/s12z/bfext-special.d: New file.
+       * testsuite/gas/s12z/bfext-special.s: New file.
+       * testsuite/gas/s12z/bfext.d: New file.
+       * testsuite/gas/s12z/bfext.s: New file.
+       * testsuite/gas/s12z/bit-manip.d: New file.
+       * testsuite/gas/s12z/bit-manip.s: New file.
+       * testsuite/gas/s12z/bit.d: New file.
+       * testsuite/gas/s12z/bit.s: New file.
+       * testsuite/gas/s12z/bra-expression-defined.d: New file.
+       * testsuite/gas/s12z/bra-expression-defined.s: New file.
+       * testsuite/gas/s12z/bra-expression-undef.d: New file.
+       * testsuite/gas/s12z/bra-expression-undef.s: New file.
+       * testsuite/gas/s12z/bra.d: New file.
+       * testsuite/gas/s12z/bra.s: New file.
+       * testsuite/gas/s12z/brclr-symbols.d: New file.
+       * testsuite/gas/s12z/brclr-symbols.s: New file.
+       * testsuite/gas/s12z/brset-clr-opr-imm-rel.d: New file.
+       * testsuite/gas/s12z/brset-clr-opr-imm-rel.s: New file.
+       * testsuite/gas/s12z/brset-clr-opr-reg-rel.d: New file.
+       * testsuite/gas/s12z/brset-clr-opr-reg-rel.s: New file.
+       * testsuite/gas/s12z/brset-clr-reg-imm-rel.d: New file.
+       * testsuite/gas/s12z/brset-clr-reg-imm-rel.s: New file.
+       * testsuite/gas/s12z/brset-clr-reg-reg-rel.d: New file.
+       * testsuite/gas/s12z/brset-clr-reg-reg-rel.s: New file.
+       * testsuite/gas/s12z/clb.d: New file.
+       * testsuite/gas/s12z/clb.s: New file.
+       * testsuite/gas/s12z/clr-opr.d: New file.
+       * testsuite/gas/s12z/clr-opr.s: New file.
+       * testsuite/gas/s12z/clr.d: New file.
+       * testsuite/gas/s12z/clr.s: New file.
+       * testsuite/gas/s12z/cmp-imm.d: New file.
+       * testsuite/gas/s12z/cmp-imm.s: New file.
+       * testsuite/gas/s12z/cmp-opr-inc.d: New file.
+       * testsuite/gas/s12z/cmp-opr-inc.s: New file.
+       * testsuite/gas/s12z/cmp-opr-rdirect.d: New file.
+       * testsuite/gas/s12z/cmp-opr-rdirect.s: New file.
+       * testsuite/gas/s12z/cmp-opr-reg.d: New file.
+       * testsuite/gas/s12z/cmp-opr-reg.s: New file.
+       * testsuite/gas/s12z/cmp-opr-rindirect.d: New file.
+       * testsuite/gas/s12z/cmp-opr-rindirect.s: New file.
+       * testsuite/gas/s12z/cmp-opr-sxe4.d: New file.
+       * testsuite/gas/s12z/cmp-opr-sxe4.s: New file.
+       * testsuite/gas/s12z/cmp-opr-xys.d: New file.
+       * testsuite/gas/s12z/cmp-opr-xys.s: New file.
+       * testsuite/gas/s12z/cmp-s-imm.d: New file.
+       * testsuite/gas/s12z/cmp-s-imm.s: New file.
+       * testsuite/gas/s12z/cmp-s-opr.d: New file.
+       * testsuite/gas/s12z/cmp-s-opr.s: New file.
+       * testsuite/gas/s12z/cmp-xy.d: New file.
+       * testsuite/gas/s12z/cmp-xy.s: New file.
+       * testsuite/gas/s12z/com-opr.d: New file.
+       * testsuite/gas/s12z/com-opr.s: New file.
+       * testsuite/gas/s12z/complex-shifts.d: New file.
+       * testsuite/gas/s12z/complex-shifts.s: New file.
+       * testsuite/gas/s12z/db-tb-cc-opr.d: New file.
+       * testsuite/gas/s12z/db-tb-cc-opr.s: New file.
+       * testsuite/gas/s12z/db-tb-cc-reg.d: New file.
+       * testsuite/gas/s12z/db-tb-cc-reg.s: New file.
+       * testsuite/gas/s12z/dbCC.d: New file.
+       * testsuite/gas/s12z/dbCC.s: New file.
+       * testsuite/gas/s12z/dec-opr.d: New file.
+       * testsuite/gas/s12z/dec-opr.s: New file.
+       * testsuite/gas/s12z/dec.d: New file.
+       * testsuite/gas/s12z/dec.s: New file.
+       * testsuite/gas/s12z/div.d: New file.
+       * testsuite/gas/s12z/div.s: New file.
+       * testsuite/gas/s12z/eor.d: New file.
+       * testsuite/gas/s12z/eor.s: New file.
+       * testsuite/gas/s12z/exg.d: New file.
+       * testsuite/gas/s12z/exg.s: New file.
+       * testsuite/gas/s12z/ext24-ld-xy.d: New file.
+       * testsuite/gas/s12z/ext24-ld-xy.s: New file.
+       * testsuite/gas/s12z/inc-opr.d: New file.
+       * testsuite/gas/s12z/inc-opr.s: New file.
+       * testsuite/gas/s12z/inc.d: New file.
+       * testsuite/gas/s12z/inc.s: New file.
+       * testsuite/gas/s12z/inh.d: New file.
+       * testsuite/gas/s12z/inh.s: New file.
+       * testsuite/gas/s12z/jmp.d: New file.
+       * testsuite/gas/s12z/jmp.s: New file.
+       * testsuite/gas/s12z/jsr.d: New file.
+       * testsuite/gas/s12z/jsr.s: New file.
+       * testsuite/gas/s12z/ld-imm-page2.d: New file.
+       * testsuite/gas/s12z/ld-imm-page2.s: New file.
+       * testsuite/gas/s12z/ld-imm.d: New file.
+       * testsuite/gas/s12z/ld-imm.s: New file.
+       * testsuite/gas/s12z/ld-immu18.d: New file.
+       * testsuite/gas/s12z/ld-immu18.s: New file.
+       * testsuite/gas/s12z/ld-large-direct.d: New file.
+       * testsuite/gas/s12z/ld-large-direct.s: New file.
+       * testsuite/gas/s12z/ld-opr.d: New file.
+       * testsuite/gas/s12z/ld-opr.s: New file.
+       * testsuite/gas/s12z/ld-s-opr.d: New file.
+       * testsuite/gas/s12z/ld-s-opr.s: New file.
+       * testsuite/gas/s12z/ld-small-direct.d: New file.
+       * testsuite/gas/s12z/ld-small-direct.s: New file.
+       * testsuite/gas/s12z/lea-immu18.d: New file.
+       * testsuite/gas/s12z/lea-immu18.s: New file.
+       * testsuite/gas/s12z/lea.d: New file.
+       * testsuite/gas/s12z/lea.s: New file.
+       * testsuite/gas/s12z/mac.d: New file.
+       * testsuite/gas/s12z/mac.s: New file.
+       * testsuite/gas/s12z/min-max.d: New file.
+       * testsuite/gas/s12z/min-max.s: New file.
+       * testsuite/gas/s12z/mod.d: New file.
+       * testsuite/gas/s12z/mod.s: New file.
+       * testsuite/gas/s12z/mov.d: New file.
+       * testsuite/gas/s12z/mov.s: New file.
+       * testsuite/gas/s12z/mul-imm.d: New file.
+       * testsuite/gas/s12z/mul-imm.s: New file.
+       * testsuite/gas/s12z/mul-opr-opr.d: New file.
+       * testsuite/gas/s12z/mul-opr-opr.s: New file.
+       * testsuite/gas/s12z/mul-opr.d: New file.
+       * testsuite/gas/s12z/mul-opr.s: New file.
+       * testsuite/gas/s12z/mul-reg.d: New file.
+       * testsuite/gas/s12z/mul-reg.s: New file.
+       * testsuite/gas/s12z/mul.d: New file.
+       * testsuite/gas/s12z/mul.s: New file.
+       * testsuite/gas/s12z/neg-opr.d: New file.
+       * testsuite/gas/s12z/neg-opr.s: New file.
+       * testsuite/gas/s12z/not-so-simple-shifts.d: New file.
+       * testsuite/gas/s12z/not-so-simple-shifts.s: New file.
+       * testsuite/gas/s12z/opr-18u.d: New file.
+       * testsuite/gas/s12z/opr-18u.s: New file.
+       * testsuite/gas/s12z/opr-expr.d: New file.
+       * testsuite/gas/s12z/opr-expr.s: New file.
+       * testsuite/gas/s12z/opr-ext-18.d: New file.
+       * testsuite/gas/s12z/opr-ext-18.s: New file.
+       * testsuite/gas/s12z/opr-idx-24-reg.d: New file.
+       * testsuite/gas/s12z/opr-idx-24-reg.s: New file.
+       * testsuite/gas/s12z/opr-idx3-reg.d: New file.
+       * testsuite/gas/s12z/opr-idx3-reg.s: New file.
+       * testsuite/gas/s12z/opr-idx3-xysp-24.d: New file.
+       * testsuite/gas/s12z/opr-idx3-xysp-24.s: New file.
+       * testsuite/gas/s12z/opr-indirect-expr.d: New file.
+       * testsuite/gas/s12z/opr-indirect-expr.s: New file.
+       * testsuite/gas/s12z/opr-symbol.d: New file.
+       * testsuite/gas/s12z/opr-symbol.s: New file.
+       * testsuite/gas/s12z/or-imm.d: New file.
+       * testsuite/gas/s12z/or-imm.s: New file.
+       * testsuite/gas/s12z/or-opr.d: New file.
+       * testsuite/gas/s12z/or-opr.s: New file.
+       * testsuite/gas/s12z/p2-mul.d: New file.
+       * testsuite/gas/s12z/p2-mul.s: New file.
+       * testsuite/gas/s12z/page2-inh.d: New file.
+       * testsuite/gas/s12z/page2-inh.s: New file.
+       * testsuite/gas/s12z/psh-pul.d: New file.
+       * testsuite/gas/s12z/psh-pul.s: New file.
+       * testsuite/gas/s12z/qmul.d: New file.
+       * testsuite/gas/s12z/qmul.s: New file.
+       * testsuite/gas/s12z/rotate.d: New file.
+       * testsuite/gas/s12z/rotate.s: New file.
+       * testsuite/gas/s12z/s12z.exp: New file.
+       * testsuite/gas/s12z/sat.d: New file.
+       * testsuite/gas/s12z/sat.s: New file.
+       * testsuite/gas/s12z/sbc-imm.d: New file.
+       * testsuite/gas/s12z/sbc-imm.s: New file.
+       * testsuite/gas/s12z/sbc-opr.d: New file.
+       * testsuite/gas/s12z/sbc-opr.s: New file.
+       * testsuite/gas/s12z/shift.d: New file.
+       * testsuite/gas/s12z/shift.s: New file.
+       * testsuite/gas/s12z/simple-shift.d: New file.
+       * testsuite/gas/s12z/simple-shift.s: New file.
+       * testsuite/gas/s12z/single-ops.d: New file.
+       * testsuite/gas/s12z/single-ops.s: New file.
+       * testsuite/gas/s12z/specd6.d: New file.
+       * testsuite/gas/s12z/specd6.s: New file.
+       * testsuite/gas/s12z/st-large-direct.d: New file.
+       * testsuite/gas/s12z/st-large-direct.s: New file.
+       * testsuite/gas/s12z/st-opr.d: New file.
+       * testsuite/gas/s12z/st-opr.s: New file.
+       * testsuite/gas/s12z/st-s-opr.d: New file.
+       * testsuite/gas/s12z/st-s-opr.s: New file.
+       * testsuite/gas/s12z/st-small-direct.d: New file.
+       * testsuite/gas/s12z/st-small-direct.s: New file.
+       * testsuite/gas/s12z/st-xy.d: New file.
+       * testsuite/gas/s12z/st-xy.s: New file.
+       * testsuite/gas/s12z/sub-imm.d: New file.
+       * testsuite/gas/s12z/sub-imm.s: New file.
+       * testsuite/gas/s12z/sub-opr.d: New file.
+       * testsuite/gas/s12z/sub-opr.s: New file.
+       * testsuite/gas/s12z/tfr.d: New file.
+       * testsuite/gas/s12z/tfr.s: New file.
+       * testsuite/gas/s12z/trap.d: New file.
+       * testsuite/gas/s12z/trap.s: New file.
+
 2018-05-16  Maciej W. Rozycki  <macro@mips.com>
 
        * tc-nds32.c (md_assemble): Rename `expr' local variable to
index 952377093d069d9b2b4107bd4c0416468beaa119..ff46b0dfefcd2894859cd2da9ecd14f80a145820 100644 (file)
@@ -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 \
index 4feabb3432e2782a9a1e58a53f6f1bf5546798e9..c127d3606f44c6402c7e4b872d4bcf405cbe9590 100644 (file)
@@ -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
index ec1ba78a66a268de156cad06d89adcf087bec868..a05b703d9c87ced784a4732e5fb4d590849cf58b 100644 (file)
--- 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 (file)
index 0000000..e024e72
--- /dev/null
@@ -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;
+
+\f
+/* Options and initialization.  */
+
+const char *md_shortopts = "Sm:";
+
+struct option md_longopts[] =
+  {
+  };
+
+size_t md_longopts_size = sizeof (md_longopts);
+\f
+
+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}
+  };
+\f
+
+/* 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;
+}
+\f
+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)
+{
+}
+\f
+/* 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;
+}
+
+\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;
+}
+
+\f
+
+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;
+}
+
+
+\f
+
+
+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);
+}
+
+\f
+
+
+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;
+}
+
+\f
+
+
+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;
+}
+
+
+\f
+
+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}
+};
+
+\f
+/* 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++)
+    ;
+}
+
+\f
+
+
+\f
+/* 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 (file)
index 0000000..9d6b571
--- /dev/null
@@ -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 *);
index 67edc1d19782cda725fd307e665609658204afe1..3d0415c1aa494630e776e94381950c9c02b3576d 100644 (file)
@@ -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 ;;
index 80893581e12f157a78a9db7733767f8415f5967c..c9c3405272a3e42505552f221505de344f4f348a 100644 (file)
@@ -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 \
index 643df6175d1d3fdb397ce7cc2f0e17bd488c2e28..a126e2f1596b2bb960ff0cdacea694bdb4059eb9 100644 (file)
@@ -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 \
index 47d55df4f6b6c3ec019c7f10630ae5ba634a868d..2b8af690273742957ff07f3bb21a7c9ea6862aca 100644 (file)
@@ -46,6 +46,7 @@
 @set M32R
 @set xc16x
 @set M68HC11
+@set S12Z
 @set M680X0
 @set MCORE
 @set METAG
index 35616c8b55d37c46728898c3d6d50ed229e805c5..b6b16b7b2922537eacf210eb27cc2babaa72942a 100644 (file)
@@ -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 (file)
index 0000000..9c8a97f
--- /dev/null
@@ -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 (file)
index 0000000..b41238f
--- /dev/null
@@ -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 (file)
index 0000000..718a2eb
--- /dev/null
@@ -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 (file)
index 0000000..b13d136
--- /dev/null
@@ -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 (file)
index 0000000..cddf980
--- /dev/null
@@ -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 (file)
index 0000000..d2023a2
--- /dev/null
@@ -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 (file)
index 0000000..b16befc
--- /dev/null
@@ -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 (file)
index 0000000..6125da4
--- /dev/null
@@ -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 (file)
index 0000000..5986c8e
--- /dev/null
@@ -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 (file)
index 0000000..0528312
--- /dev/null
@@ -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 (file)
index 0000000..d86a4aa
--- /dev/null
@@ -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 (file)
index 0000000..fea351d
--- /dev/null
@@ -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 (file)
index 0000000..fcd947a
--- /dev/null
@@ -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 (file)
index 0000000..b9cc366
--- /dev/null
@@ -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 (file)
index 0000000..6569ebe
--- /dev/null
@@ -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 (file)
index 0000000..38117e9
--- /dev/null
@@ -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 (file)
index 0000000..afa4a1e
--- /dev/null
@@ -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 (file)
index 0000000..380e627
--- /dev/null
@@ -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 (file)
index 0000000..1810c9a
--- /dev/null
@@ -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 (file)
index 0000000..84f439a
--- /dev/null
@@ -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 (file)
index 0000000..66cb5b6
--- /dev/null
@@ -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 (file)
index 0000000..6a0c7ee
--- /dev/null
@@ -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 (file)
index 0000000..cebb478
--- /dev/null
@@ -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 (file)
index 0000000..68dd30c
--- /dev/null
@@ -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 (file)
index 0000000..539b593
--- /dev/null
@@ -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 (file)
index 0000000..700f7cd
--- /dev/null
@@ -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 (file)
index 0000000..2a1baeb
--- /dev/null
@@ -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 (file)
index 0000000..ddd7dcb
--- /dev/null
@@ -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 (file)
index 0000000..1d5a81e
--- /dev/null
@@ -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 (file)
index 0000000..7a6cc1c
--- /dev/null
@@ -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 (file)
index 0000000..a2528b3
--- /dev/null
@@ -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 (file)
index 0000000..59de1c0
--- /dev/null
@@ -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 (file)
index 0000000..fa212fe
--- /dev/null
@@ -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 (file)
index 0000000..588e606
--- /dev/null
@@ -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 (file)
index 0000000..1bb8da9
--- /dev/null
@@ -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 (file)
index 0000000..1a87e78
--- /dev/null
@@ -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 (file)
index 0000000..76c3bb5
--- /dev/null
@@ -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 (file)
index 0000000..ddcc61d
--- /dev/null
@@ -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 (file)
index 0000000..3aca621
--- /dev/null
@@ -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 (file)
index 0000000..1cad906
--- /dev/null
@@ -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 (file)
index 0000000..c78ec97
--- /dev/null
@@ -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 (file)
index 0000000..fd142dc
--- /dev/null
@@ -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 (file)
index 0000000..877bbce
--- /dev/null
@@ -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 (file)
index 0000000..7c05ebb
--- /dev/null
@@ -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 (file)
index 0000000..ecfa266
--- /dev/null
@@ -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 (file)
index 0000000..1e902d6
--- /dev/null
@@ -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 (file)
index 0000000..1f0b57f
--- /dev/null
@@ -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 (file)
index 0000000..d756b00
--- /dev/null
@@ -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 (file)
index 0000000..89b41b5
--- /dev/null
@@ -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 (file)
index 0000000..bda08de
--- /dev/null
@@ -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 (file)
index 0000000..48b1d48
--- /dev/null
@@ -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 (file)
index 0000000..879ed98
--- /dev/null
@@ -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 (file)
index 0000000..ff5dcbc
--- /dev/null
@@ -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 (file)
index 0000000..cff87d3
--- /dev/null
@@ -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 (file)
index 0000000..75bb440
--- /dev/null
@@ -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 (file)
index 0000000..7c1108f
--- /dev/null
@@ -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 (file)
index 0000000..27ac5fb
--- /dev/null
@@ -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 (file)
index 0000000..5eac2fd
--- /dev/null
@@ -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 (file)
index 0000000..7b3d113
--- /dev/null
@@ -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 (file)
index 0000000..87d065f
--- /dev/null
@@ -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 (file)
index 0000000..929bb08
--- /dev/null
@@ -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 (file)
index 0000000..d4e7efb
--- /dev/null
@@ -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 (file)
index 0000000..e873d82
--- /dev/null
@@ -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 (file)
index 0000000..77d2ac7
--- /dev/null
@@ -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 (file)
index 0000000..5deb45a
--- /dev/null
@@ -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 (file)
index 0000000..9fef4e1
--- /dev/null
@@ -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 (file)
index 0000000..dcfd47c
--- /dev/null
@@ -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 (file)
index 0000000..ce51785
--- /dev/null
@@ -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 (file)
index 0000000..5eb2760
--- /dev/null
@@ -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 (file)
index 0000000..e17fe90
--- /dev/null
@@ -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 (file)
index 0000000..118296e
--- /dev/null
@@ -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 (file)
index 0000000..ee556e2
--- /dev/null
@@ -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 (file)
index 0000000..a79cbde
--- /dev/null
@@ -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 (file)
index 0000000..54ea832
--- /dev/null
@@ -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 (file)
index 0000000..524f4d0
--- /dev/null
@@ -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 (file)
index 0000000..87dd7fc
--- /dev/null
@@ -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 (file)
index 0000000..3a637e7
--- /dev/null
@@ -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 (file)
index 0000000..4f49088
--- /dev/null
@@ -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 (file)
index 0000000..2f54a4c
--- /dev/null
@@ -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 (file)
index 0000000..74a2c3e
--- /dev/null
@@ -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 (file)
index 0000000..1280bf4
--- /dev/null
@@ -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 (file)
index 0000000..3569519
--- /dev/null
@@ -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 (file)
index 0000000..edd7990
--- /dev/null
@@ -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 (file)
index 0000000..f829a52
--- /dev/null
@@ -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 (file)
index 0000000..cc4985a
--- /dev/null
@@ -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 (file)
index 0000000..58e4ae7
--- /dev/null
@@ -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 (file)
index 0000000..55ce301
--- /dev/null
@@ -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 (file)
index 0000000..a3f075f
--- /dev/null
@@ -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 (file)
index 0000000..2b262f0
--- /dev/null
@@ -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 (file)
index 0000000..d013d6a
--- /dev/null
@@ -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 (file)
index 0000000..1876082
--- /dev/null
@@ -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 (file)
index 0000000..51b912b
--- /dev/null
@@ -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 (file)
index 0000000..89e0b97
--- /dev/null
@@ -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 (file)
index 0000000..4f437f1
--- /dev/null
@@ -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 (file)
index 0000000..22b2858
--- /dev/null
@@ -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 (file)
index 0000000..12ff350
--- /dev/null
@@ -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 (file)
index 0000000..fa4321d
--- /dev/null
@@ -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 (file)
index 0000000..8508a0a
--- /dev/null
@@ -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 (file)
index 0000000..80f0ff1
--- /dev/null
@@ -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 (file)
index 0000000..3f1744f
--- /dev/null
@@ -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 (file)
index 0000000..09c735c
--- /dev/null
@@ -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 (file)
index 0000000..b0e4fcb
--- /dev/null
@@ -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 (file)
index 0000000..569123d
--- /dev/null
@@ -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 (file)
index 0000000..ba071df
--- /dev/null
@@ -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 (file)
index 0000000..563765e
--- /dev/null
@@ -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 (file)
index 0000000..c17f1c9
--- /dev/null
@@ -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 (file)
index 0000000..4c53f2a
--- /dev/null
@@ -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 (file)
index 0000000..c0a8ec2
--- /dev/null
@@ -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 (file)
index 0000000..ee452e9
--- /dev/null
@@ -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 (file)
index 0000000..085ebfb
--- /dev/null
@@ -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 (file)
index 0000000..41ee23e
--- /dev/null
@@ -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 (file)
index 0000000..e6cffd2
--- /dev/null
@@ -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 (file)
index 0000000..5d9ea6d
--- /dev/null
@@ -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 (file)
index 0000000..3088b41
--- /dev/null
@@ -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 (file)
index 0000000..b003922
--- /dev/null
@@ -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 (file)
index 0000000..30722a5
--- /dev/null
@@ -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 (file)
index 0000000..2d75a93
--- /dev/null
@@ -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 (file)
index 0000000..d2758b6
--- /dev/null
@@ -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 (file)
index 0000000..8914524
--- /dev/null
@@ -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 (file)
index 0000000..f01684a
--- /dev/null
@@ -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 (file)
index 0000000..1b6b9d7
--- /dev/null
@@ -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 (file)
index 0000000..34c67dd
--- /dev/null
@@ -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 (file)
index 0000000..c94994a
--- /dev/null
@@ -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 (file)
index 0000000..e9f4086
--- /dev/null
@@ -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 (file)
index 0000000..35af919
--- /dev/null
@@ -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 (file)
index 0000000..fdc4e10
--- /dev/null
@@ -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 (file)
index 0000000..d047934
--- /dev/null
@@ -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 (file)
index 0000000..15bb7a9
--- /dev/null
@@ -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 (file)
index 0000000..a253725
--- /dev/null
@@ -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 (file)
index 0000000..875ba72
--- /dev/null
@@ -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 (file)
index 0000000..22e97fb
--- /dev/null
@@ -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 (file)
index 0000000..3f4c84b
--- /dev/null
@@ -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 (file)
index 0000000..9cb9ac9
--- /dev/null
@@ -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 (file)
index 0000000..e028b85
--- /dev/null
@@ -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 (file)
index 0000000..1626ee4
--- /dev/null
@@ -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 (file)
index 0000000..7d4116d
--- /dev/null
@@ -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 (file)
index 0000000..6e36326
--- /dev/null
@@ -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 (file)
index 0000000..f9b4e11
--- /dev/null
@@ -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 (file)
index 0000000..fe546e1
--- /dev/null
@@ -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 (file)
index 0000000..d3a75cd
--- /dev/null
@@ -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 (file)
index 0000000..79f95f1
--- /dev/null
@@ -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 (file)
index 0000000..e02a78e
--- /dev/null
@@ -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 (file)
index 0000000..d52ac38
--- /dev/null
@@ -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 (file)
index 0000000..481ce9f
--- /dev/null
@@ -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 (file)
index 0000000..e0fdc3e
--- /dev/null
@@ -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 (file)
index 0000000..2ee64f5
--- /dev/null
@@ -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 (file)
index 0000000..e25468c
--- /dev/null
@@ -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 (file)
index 0000000..9b66f06
--- /dev/null
@@ -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 (file)
index 0000000..b4d95ac
--- /dev/null
@@ -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 (file)
index 0000000..28fafbc
--- /dev/null
@@ -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 (file)
index 0000000..384a4cf
--- /dev/null
@@ -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 (file)
index 0000000..95d51b3
--- /dev/null
@@ -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 (file)
index 0000000..ee1fb12
--- /dev/null
@@ -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 (file)
index 0000000..97e5b4f
--- /dev/null
@@ -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 (file)
index 0000000..6ce2afb
--- /dev/null
@@ -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 (file)
index 0000000..dbaa77d
--- /dev/null
@@ -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 (file)
index 0000000..6558525
--- /dev/null
@@ -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 (file)
index 0000000..188bb65
--- /dev/null
@@ -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 (file)
index 0000000..4dabcb6
--- /dev/null
@@ -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 (file)
index 0000000..ce52171
--- /dev/null
@@ -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 (file)
index 0000000..b9952e3
--- /dev/null
@@ -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 (file)
index 0000000..0903fa7
--- /dev/null
@@ -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 (file)
index 0000000..0351ec6
--- /dev/null
@@ -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 (file)
index 0000000..40113e7
--- /dev/null
@@ -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 (file)
index 0000000..57a2d59
--- /dev/null
@@ -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 (file)
index 0000000..6cd5af7
--- /dev/null
@@ -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 (file)
index 0000000..6237d48
--- /dev/null
@@ -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 (file)
index 0000000..a58eb9a
--- /dev/null
@@ -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 (file)
index 0000000..91e3f6d
--- /dev/null
@@ -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 (file)
index 0000000..acd50cf
--- /dev/null
@@ -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 (file)
index 0000000..4cbac0b
--- /dev/null
@@ -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 (file)
index 0000000..ba2ff8e
--- /dev/null
@@ -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 (file)
index 0000000..1bca708
--- /dev/null
@@ -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 (file)
index 0000000..9879e33
--- /dev/null
@@ -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 (file)
index 0000000..bd5ed49
--- /dev/null
@@ -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 (file)
index 0000000..3202174
--- /dev/null
@@ -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 (file)
index 0000000..41e061f
--- /dev/null
@@ -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 (file)
index 0000000..cb41f3c
--- /dev/null
@@ -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 (file)
index 0000000..13af3bf
--- /dev/null
@@ -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 (file)
index 0000000..045e071
--- /dev/null
@@ -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 (file)
index 0000000..ca9b38a
--- /dev/null
@@ -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 (file)
index 0000000..ab6fe2c
--- /dev/null
@@ -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 (file)
index 0000000..0c743cd
--- /dev/null
@@ -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 (file)
index 0000000..92308b4
--- /dev/null
@@ -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 (file)
index 0000000..03ca41e
--- /dev/null
@@ -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 (file)
index 0000000..74956d1
--- /dev/null
@@ -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 (file)
index 0000000..d39bb62
--- /dev/null
@@ -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 (file)
index 0000000..c5257a5
--- /dev/null
@@ -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 (file)
index 0000000..3748914
--- /dev/null
@@ -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 (file)
index 0000000..90cc5e8
--- /dev/null
@@ -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 (file)
index 0000000..df67d4a
--- /dev/null
@@ -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 (file)
index 0000000..c0d736d
--- /dev/null
@@ -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 (file)
index 0000000..335e77e
--- /dev/null
@@ -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 (file)
index 0000000..6e77465
--- /dev/null
@@ -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 (file)
index 0000000..7c1064a
--- /dev/null
@@ -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 (file)
index 0000000..1b4f38c
--- /dev/null
@@ -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 (file)
index 0000000..e98e26c
--- /dev/null
@@ -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 (file)
index 0000000..f1f7b54
--- /dev/null
@@ -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 (file)
index 0000000..58c7642
--- /dev/null
@@ -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 (file)
index 0000000..c61551e
--- /dev/null
@@ -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 (file)
index 0000000..bf69613
--- /dev/null
@@ -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 (file)
index 0000000..7ea72bb
--- /dev/null
@@ -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
index fe9cad661430982df9cd732b6362f36f160e21eb..649b65ce2d61ddb3a3fb3c4e7c56b3318aac03ab 100644 (file)
@@ -1,3 +1,7 @@
+2018-05-18  John Darrington  <john@darrington.wattle.id.au>
+
+       * elf/s12z.h: New header.
+
 2018-05-15  Tamar Christina  <tamar.christina@arm.com>
 
        PR binutils/21446
diff --git a/include/elf/s12z.h b/include/elf/s12z.h
new file mode 100644 (file)
index 0000000..72504ee
--- /dev/null
@@ -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
index 5986f3c15d0c6bfc4348e2910bd793234b171fba..fcd50a5dd02df3250cb9c06580e260b33a691b3f 100644 (file)
@@ -1,3 +1,23 @@
+2018-05-18  John Darrington  <john@darrington.wattle.id.au>
+
+       * Makefile.am: Add support for s12z architecture.
+       * configure.tgt: Likewise.
+       * Makefile.in: Regenerate.
+       * emulparams/m9s12zelf.sh: New file.
+       * scripttempl/elfm9s12z.sc: New file.
+       * testsuite/ld-discard/static.d: Expect to fail for the s12z
+       target.
+       * testsuite/ld-elf/endsym.d: Likewise.
+       * testsuite/ld-elf/merge.d: Likewise.
+       * testsuite/ld-elf/pr14926.d: Skip for the s12z target.
+       * testsuite/ld-elf/sec64k.exp: Likewise.
+       * testsuite/ld-s12z: New directory.
+       * testsuite/ld-s12z/opr-linking.d: New file.
+       * testsuite/ld-s12z/opr-linking.s: New file.
+       * testsuite/ld-s12z/relative-linking.d: New file.
+       * testsuite/ld-s12z/relative-linking.s: New file.
+       * testsuite/ld-s12z/z12s.exp: New file.
+
 2018-05-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/23189
index 8e4c8774d1bc533de0761e98d65e3271f131b19d..151e1e200a4d040db46742e9f18f1389ca213057 100644 (file)
@@ -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}
 
index afd2a4bb8815b138e2b2010beaa13eec02569d9a..5cfd4ab0fbbcbec44f923f1ccb45180a960ab5f3 100644 (file)
@@ -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}
 
index 4c4ab850f2244aa55517fe5b0f44486e70a092ec..3386c3d928711e484cfe2dd87afc49f6bf308dbb 100644 (file)
@@ -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 (file)
index 0000000..7a819e8
--- /dev/null
@@ -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 (file)
index 0000000..c39d270
--- /dev/null
@@ -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
index 7a299cc9c095a1533f85af8dd246ddffa266a5cb..ebdbda840ebd15fcecb88f6666d4f47be20ad69f 100644 (file)
@@ -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
index 86fda2114e7e40590c086c92f5a0d239c0ce48e1..39667e37ce5ab07f7cd1c7f4119bb8be0b62433f 100644 (file)
@@ -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-*-*
 
 #...
index 2ac88ea89c99380d346f94cccdea3c6d143c283e..ebabae8d95e37eec8afaa1eb6d07ea2386e38431 100644 (file)
@@ -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-*-*"
 
index 8fc8e6416c7edc3d7feaf2b69bbb215c65138bb4..4e0a8da4dddff571f489ea2e61c62d42251ea0b7 100644 (file)
@@ -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
 
 #...
index 2495cb85f524f7f4976869c07fac58b39df23f6a..b58139e9dda3ef21335b383e1b7fd092f35bcdb6 100644 (file)
@@ -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 (file)
index 0000000..05d154b
--- /dev/null
@@ -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 (file)
index 0000000..aa70566
--- /dev/null
@@ -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 (file)
index 0000000..286fe52
--- /dev/null
@@ -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 (file)
index 0000000..fa52edb
--- /dev/null
@@ -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 (file)
index 0000000..4c9baa4
--- /dev/null
@@ -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]
+}
index c3f345bafd37aa2871538fad4c84aa68a305c904..a147cc3991da156fea14c7347ace2b5dfb1e5041 100644 (file)
@@ -1,3 +1,14 @@
+2018-05-18  John Darrington  <john@darrington.wattle.id.au>
+
+       * Makefile.am: Add support for s12z architecture.
+       * configure.ac: Likewise.
+       * disassemble.c: Likewise.
+       * disassemble.h: Likewise.
+       * Makefile.in: Regenerate.
+       * configure: Regenerate.
+       * s12z-dis.c: New file.
+       * s12z.h: New file.
+
 2018-05-18  Alan Modra  <amodra@gmail.com>
 
        * nfp-dis.c: Don't #include libbfd.h.
index 0c7d09d7597cb590a130946ae17e3d734e03f250..98fd7f3f70cdc38d338d6eef0559e2e380d06305 100644 (file)
@@ -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 \
index 0d85bd43fa0d66929bbc1f856406eaff95bc629b..b55daea21bdb7121cad1f9214a903ca38e36611e 100644 (file)
@@ -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@
index c7a88054b36d3f8d5c9e34a291389348aa31ee57..c5f0c1000ccf100d8b980f21d4978016e55a07d7 100755 (executable)
@@ -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 ;;
index e42b661fcf3b1cc1f5f29c7a6e08224d3c330cda..86a0ca01ffd7d8ad67843e612c8625b7ce88297a 100644 (file)
@@ -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 ;;
index 100ccd3fac4bc711cbeb0a978d95598cfa01c965..c8fda59b6e1f5a1e2c64c428a868cb660185442e 100644 (file)
@@ -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;
index 9d78b2193f8feef9dff50522f7eed408e3fe1de2..04573446127227095408bdf1a2dca4e2c933a5a7 100644 (file)
@@ -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 (file)
index 0000000..4512311
--- /dev/null
@@ -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;
+}
+
+
+\f
+
+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;
+}
+
+\f
+
+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, "%" BFD_VMA_FMT "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"
+  };
+
+
+\f
+
+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;
+}
+
+\f
+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;
+}
+
+
+\f
+
+
+/* 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;
+}
+\f
+
+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);
+}
+
+\f
+
+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);
+}
+
+\f
+
+/* 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;
+}
+
+
+\f
+
+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 (file)
index 0000000..7e38ac5
--- /dev/null
@@ -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