aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/Makefile.am4
-rw-r--r--bfd/Makefile.in6
-rw-r--r--bfd/archures.c4
-rw-r--r--bfd/bfd-in.h2
-rw-r--r--bfd/bfd-in2.h9
-rw-r--r--bfd/config.bfd4
-rwxr-xr-xbfd/configure1
-rw-r--r--bfd/configure.ac1
-rw-r--r--bfd/cpu-s12z.c41
-rw-r--r--bfd/elf32-s12z.c270
-rw-r--r--bfd/libbfd.c21
-rw-r--r--bfd/libbfd.h1
-rw-r--r--bfd/reloc.c17
-rw-r--r--bfd/targets.c3
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/readelf.c7
-rw-r--r--binutils/testsuite/binutils-all/dw2-1.S2
-rw-r--r--binutils/testsuite/lib/binutils-common.exp2
-rw-r--r--gas/ChangeLog216
-rw-r--r--gas/Makefile.am2
-rw-r--r--gas/Makefile.in17
-rw-r--r--gas/NEWS2
-rw-r--r--gas/config/tc-s12z.c3840
-rw-r--r--gas/config/tc-s12z.h105
-rw-r--r--gas/configure.tgt3
-rw-r--r--gas/doc/Makefile.am1
-rw-r--r--gas/doc/Makefile.in1
-rw-r--r--gas/doc/all.texi1
-rw-r--r--gas/doc/as.texinfo7
-rw-r--r--gas/doc/c-s12z.texi212
-rw-r--r--gas/testsuite/gas/s12z/abs.d19
-rw-r--r--gas/testsuite/gas/s12z/abs.s8
-rw-r--r--gas/testsuite/gas/s12z/adc-imm.d21
-rw-r--r--gas/testsuite/gas/s12z/adc-imm.s8
-rw-r--r--gas/testsuite/gas/s12z/adc-opr.d21
-rw-r--r--gas/testsuite/gas/s12z/adc-opr.s9
-rw-r--r--gas/testsuite/gas/s12z/add-imm.d21
-rw-r--r--gas/testsuite/gas/s12z/add-imm.s8
-rw-r--r--gas/testsuite/gas/s12z/add-opr.d21
-rw-r--r--gas/testsuite/gas/s12z/add-opr.s9
-rw-r--r--gas/testsuite/gas/s12z/and-imm.d21
-rw-r--r--gas/testsuite/gas/s12z/and-imm.s8
-rw-r--r--gas/testsuite/gas/s12z/and-opr.d22
-rw-r--r--gas/testsuite/gas/s12z/and-opr.s9
-rw-r--r--gas/testsuite/gas/s12z/and-or-cc.d13
-rw-r--r--gas/testsuite/gas/s12z/and-or-cc.s2
-rw-r--r--gas/testsuite/gas/s12z/bfext-special.d13
-rw-r--r--gas/testsuite/gas/s12z/bfext-special.s2
-rw-r--r--gas/testsuite/gas/s12z/bfext.d47
-rw-r--r--gas/testsuite/gas/s12z/bfext.s23
-rw-r--r--gas/testsuite/gas/s12z/bit-manip.d26
-rw-r--r--gas/testsuite/gas/s12z/bit-manip.s16
-rw-r--r--gas/testsuite/gas/s12z/bit.d33
-rw-r--r--gas/testsuite/gas/s12z/bit.s17
-rw-r--r--gas/testsuite/gas/s12z/bra-expression-defined.d23
-rw-r--r--gas/testsuite/gas/s12z/bra-expression-defined.s11
-rw-r--r--gas/testsuite/gas/s12z/bra-expression-undef.d24
-rw-r--r--gas/testsuite/gas/s12z/bra-expression-undef.s9
-rw-r--r--gas/testsuite/gas/s12z/bra.d34
-rw-r--r--gas/testsuite/gas/s12z/bra.s20
-rw-r--r--gas/testsuite/gas/s12z/brclr-symbols.d32
-rw-r--r--gas/testsuite/gas/s12z/brclr-symbols.s9
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d23
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s7
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d21
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s5
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d24
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s12
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d19
-rw-r--r--gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s6
-rw-r--r--gas/testsuite/gas/s12z/clb.d19
-rw-r--r--gas/testsuite/gas/s12z/clb.s8
-rw-r--r--gas/testsuite/gas/s12z/clr-opr.d15
-rw-r--r--gas/testsuite/gas/s12z/clr-opr.s5
-rw-r--r--gas/testsuite/gas/s12z/clr.d21
-rw-r--r--gas/testsuite/gas/s12z/clr.s10
-rw-r--r--gas/testsuite/gas/s12z/cmp-imm.d23
-rw-r--r--gas/testsuite/gas/s12z/cmp-imm.s12
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-inc.d21
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-inc.s11
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-rdirect.d19
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-rdirect.s9
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-reg.d19
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-reg.s9
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-rindirect.d19
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-rindirect.s9
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-sxe4.d21
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-sxe4.s10
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-xys.d19
-rw-r--r--gas/testsuite/gas/s12z/cmp-opr-xys.s9
-rw-r--r--gas/testsuite/gas/s12z/cmp-s-imm.d27
-rw-r--r--gas/testsuite/gas/s12z/cmp-s-imm.s10
-rw-r--r--gas/testsuite/gas/s12z/cmp-s-opr.d25
-rw-r--r--gas/testsuite/gas/s12z/cmp-s-opr.s10
-rw-r--r--gas/testsuite/gas/s12z/cmp-xy.d12
-rw-r--r--gas/testsuite/gas/s12z/cmp-xy.s1
-rw-r--r--gas/testsuite/gas/s12z/com-opr.d15
-rw-r--r--gas/testsuite/gas/s12z/com-opr.s3
-rw-r--r--gas/testsuite/gas/s12z/complex-shifts.d18
-rw-r--r--gas/testsuite/gas/s12z/complex-shifts.s4
-rw-r--r--gas/testsuite/gas/s12z/db-tb-cc-opr.d30
-rw-r--r--gas/testsuite/gas/s12z/db-tb-cc-opr.s11
-rw-r--r--gas/testsuite/gas/s12z/db-tb-cc-reg.d31
-rw-r--r--gas/testsuite/gas/s12z/db-tb-cc-reg.s21
-rw-r--r--gas/testsuite/gas/s12z/dbCC.d27
-rw-r--r--gas/testsuite/gas/s12z/dbCC.s7
-rw-r--r--gas/testsuite/gas/s12z/dec-opr.d15
-rw-r--r--gas/testsuite/gas/s12z/dec-opr.s3
-rw-r--r--gas/testsuite/gas/s12z/dec.d19
-rw-r--r--gas/testsuite/gas/s12z/dec.s8
-rw-r--r--gas/testsuite/gas/s12z/div.d23
-rw-r--r--gas/testsuite/gas/s12z/div.s8
-rw-r--r--gas/testsuite/gas/s12z/eor.d33
-rw-r--r--gas/testsuite/gas/s12z/eor.s17
-rw-r--r--gas/testsuite/gas/s12z/exg.d29
-rw-r--r--gas/testsuite/gas/s12z/exg.s18
-rw-r--r--gas/testsuite/gas/s12z/ext24-ld-xy.d12
-rw-r--r--gas/testsuite/gas/s12z/ext24-ld-xy.s2
-rw-r--r--gas/testsuite/gas/s12z/inc-opr.d15
-rw-r--r--gas/testsuite/gas/s12z/inc-opr.s3
-rw-r--r--gas/testsuite/gas/s12z/inc.d19
-rw-r--r--gas/testsuite/gas/s12z/inc.s8
-rw-r--r--gas/testsuite/gas/s12z/inh.d15
-rw-r--r--gas/testsuite/gas/s12z/inh.s5
-rw-r--r--gas/testsuite/gas/s12z/jmp.d33
-rw-r--r--gas/testsuite/gas/s12z/jmp.s20
-rw-r--r--gas/testsuite/gas/s12z/jsr.d33
-rw-r--r--gas/testsuite/gas/s12z/jsr.s20
-rw-r--r--gas/testsuite/gas/s12z/ld-imm-page2.d15
-rw-r--r--gas/testsuite/gas/s12z/ld-imm-page2.s2
-rw-r--r--gas/testsuite/gas/s12z/ld-imm.d25
-rw-r--r--gas/testsuite/gas/s12z/ld-imm.s16
-rw-r--r--gas/testsuite/gas/s12z/ld-immu18.d28
-rw-r--r--gas/testsuite/gas/s12z/ld-immu18.s10
-rw-r--r--gas/testsuite/gas/s12z/ld-large-direct.d21
-rw-r--r--gas/testsuite/gas/s12z/ld-large-direct.s11
-rw-r--r--gas/testsuite/gas/s12z/ld-opr.d22
-rw-r--r--gas/testsuite/gas/s12z/ld-opr.s10
-rw-r--r--gas/testsuite/gas/s12z/ld-s-opr.d16
-rw-r--r--gas/testsuite/gas/s12z/ld-s-opr.s4
-rw-r--r--gas/testsuite/gas/s12z/ld-small-direct.d31
-rw-r--r--gas/testsuite/gas/s12z/ld-small-direct.s11
-rw-r--r--gas/testsuite/gas/s12z/lea-immu18.d14
-rw-r--r--gas/testsuite/gas/s12z/lea-immu18.s3
-rw-r--r--gas/testsuite/gas/s12z/lea.d18
-rw-r--r--gas/testsuite/gas/s12z/lea.s8
-rw-r--r--gas/testsuite/gas/s12z/mac.d23
-rw-r--r--gas/testsuite/gas/s12z/mac.s8
-rw-r--r--gas/testsuite/gas/s12z/min-max.d48
-rw-r--r--gas/testsuite/gas/s12z/min-max.s32
-rw-r--r--gas/testsuite/gas/s12z/mod.d23
-rw-r--r--gas/testsuite/gas/s12z/mod.s8
-rw-r--r--gas/testsuite/gas/s12z/mov.d26
-rw-r--r--gas/testsuite/gas/s12z/mov.s8
-rw-r--r--gas/testsuite/gas/s12z/mul-imm.d19
-rw-r--r--gas/testsuite/gas/s12z/mul-imm.s6
-rw-r--r--gas/testsuite/gas/s12z/mul-opr-opr.d19
-rw-r--r--gas/testsuite/gas/s12z/mul-opr-opr.s6
-rw-r--r--gas/testsuite/gas/s12z/mul-opr.d17
-rw-r--r--gas/testsuite/gas/s12z/mul-opr.s6
-rw-r--r--gas/testsuite/gas/s12z/mul-reg.d27
-rw-r--r--gas/testsuite/gas/s12z/mul-reg.s16
-rw-r--r--gas/testsuite/gas/s12z/mul.d19
-rw-r--r--gas/testsuite/gas/s12z/mul.s6
-rw-r--r--gas/testsuite/gas/s12z/neg-opr.d34
-rw-r--r--gas/testsuite/gas/s12z/neg-opr.s21
-rw-r--r--gas/testsuite/gas/s12z/not-so-simple-shifts.d17
-rw-r--r--gas/testsuite/gas/s12z/not-so-simple-shifts.s4
-rw-r--r--gas/testsuite/gas/s12z/opr-18u.d26
-rw-r--r--gas/testsuite/gas/s12z/opr-18u.s15
-rw-r--r--gas/testsuite/gas/s12z/opr-expr.d13
-rw-r--r--gas/testsuite/gas/s12z/opr-expr.s5
-rw-r--r--gas/testsuite/gas/s12z/opr-ext-18.d13
-rw-r--r--gas/testsuite/gas/s12z/opr-ext-18.s5
-rw-r--r--gas/testsuite/gas/s12z/opr-idx-24-reg.d13
-rw-r--r--gas/testsuite/gas/s12z/opr-idx-24-reg.s2
-rw-r--r--gas/testsuite/gas/s12z/opr-idx3-reg.d17
-rw-r--r--gas/testsuite/gas/s12z/opr-idx3-reg.s3
-rw-r--r--gas/testsuite/gas/s12z/opr-idx3-xysp-24.d15
-rw-r--r--gas/testsuite/gas/s12z/opr-idx3-xysp-24.s3
-rw-r--r--gas/testsuite/gas/s12z/opr-indirect-expr.d14
-rw-r--r--gas/testsuite/gas/s12z/opr-indirect-expr.s1
-rw-r--r--gas/testsuite/gas/s12z/opr-symbol.d170
-rw-r--r--gas/testsuite/gas/s12z/opr-symbol.s109
-rw-r--r--gas/testsuite/gas/s12z/or-imm.d21
-rw-r--r--gas/testsuite/gas/s12z/or-imm.s8
-rw-r--r--gas/testsuite/gas/s12z/or-opr.d21
-rw-r--r--gas/testsuite/gas/s12z/or-opr.s8
-rw-r--r--gas/testsuite/gas/s12z/p2-mul.d17
-rw-r--r--gas/testsuite/gas/s12z/p2-mul.s7
-rw-r--r--gas/testsuite/gas/s12z/page2-inh.d15
-rw-r--r--gas/testsuite/gas/s12z/page2-inh.s5
-rw-r--r--gas/testsuite/gas/s12z/psh-pul.d21
-rw-r--r--gas/testsuite/gas/s12z/psh-pul.s8
-rw-r--r--gas/testsuite/gas/s12z/qmul.d23
-rw-r--r--gas/testsuite/gas/s12z/qmul.s8
-rw-r--r--gas/testsuite/gas/s12z/rotate.d22
-rw-r--r--gas/testsuite/gas/s12z/rotate.s10
-rw-r--r--gas/testsuite/gas/s12z/s12z.exp132
-rw-r--r--gas/testsuite/gas/s12z/sat.d19
-rw-r--r--gas/testsuite/gas/s12z/sat.s8
-rw-r--r--gas/testsuite/gas/s12z/sbc-imm.d21
-rw-r--r--gas/testsuite/gas/s12z/sbc-imm.s8
-rw-r--r--gas/testsuite/gas/s12z/sbc-opr.d23
-rw-r--r--gas/testsuite/gas/s12z/sbc-opr.s9
-rw-r--r--gas/testsuite/gas/s12z/shift.d22
-rw-r--r--gas/testsuite/gas/s12z/shift.s11
-rw-r--r--gas/testsuite/gas/s12z/simple-shift.d18
-rw-r--r--gas/testsuite/gas/s12z/simple-shift.s9
-rw-r--r--gas/testsuite/gas/s12z/single-ops.d15
-rw-r--r--gas/testsuite/gas/s12z/single-ops.s4
-rw-r--r--gas/testsuite/gas/s12z/specd6.d14
-rw-r--r--gas/testsuite/gas/s12z/specd6.s4
-rw-r--r--gas/testsuite/gas/s12z/st-large-direct.d21
-rw-r--r--gas/testsuite/gas/s12z/st-large-direct.s11
-rw-r--r--gas/testsuite/gas/s12z/st-opr.d22
-rw-r--r--gas/testsuite/gas/s12z/st-opr.s10
-rw-r--r--gas/testsuite/gas/s12z/st-s-opr.d16
-rw-r--r--gas/testsuite/gas/s12z/st-s-opr.s4
-rw-r--r--gas/testsuite/gas/s12z/st-small-direct.d34
-rw-r--r--gas/testsuite/gas/s12z/st-small-direct.s12
-rw-r--r--gas/testsuite/gas/s12z/st-xy.d12
-rw-r--r--gas/testsuite/gas/s12z/st-xy.s3
-rw-r--r--gas/testsuite/gas/s12z/sub-imm.d21
-rw-r--r--gas/testsuite/gas/s12z/sub-imm.s8
-rw-r--r--gas/testsuite/gas/s12z/sub-opr.d22
-rw-r--r--gas/testsuite/gas/s12z/sub-opr.s9
-rw-r--r--gas/testsuite/gas/s12z/tfr.d20
-rw-r--r--gas/testsuite/gas/s12z/tfr.s9
-rw-r--r--gas/testsuite/gas/s12z/trap.d105
-rw-r--r--gas/testsuite/gas/s12z/trap.s96
-rw-r--r--include/ChangeLog4
-rw-r--r--include/elf/s12z.h36
-rw-r--r--ld/ChangeLog20
-rw-r--r--ld/Makefile.am5
-rw-r--r--ld/Makefile.in6
-rw-r--r--ld/configure.tgt2
-rw-r--r--ld/emulparams/m9s12zelf.sh18
-rw-r--r--ld/scripttempl/elfm9s12z.sc444
-rw-r--r--ld/testsuite/ld-discard/static.d2
-rw-r--r--ld/testsuite/ld-elf/endsym.d2
-rw-r--r--ld/testsuite/ld-elf/merge.d2
-rw-r--r--ld/testsuite/ld-elf/pr14926.d2
-rw-r--r--ld/testsuite/ld-elf/sec64k.exp1
-rw-r--r--ld/testsuite/ld-s12z/opr-linking.d20
-rw-r--r--ld/testsuite/ld-s12z/opr-linking.s7
-rw-r--r--ld/testsuite/ld-s12z/relative-linking.d14
-rw-r--r--ld/testsuite/ld-s12z/relative-linking.s5
-rw-r--r--ld/testsuite/ld-s12z/z12s.exp33
-rw-r--r--opcodes/ChangeLog11
-rw-r--r--opcodes/Makefile.am1
-rw-r--r--opcodes/Makefile.in2
-rwxr-xr-xopcodes/configure1
-rw-r--r--opcodes/configure.ac1
-rw-r--r--opcodes/disassemble.c5
-rw-r--r--opcodes/disassemble.h1
-rw-r--r--opcodes/s12z-dis.c2672
-rw-r--r--opcodes/s12z.h71
259 files changed, 11812 insertions, 5 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index a9248e6..0319fa7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 8500a4f..8374bbd 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -123,6 +123,7 @@ ALL_MACHINES = \
cpu-m68hc11.lo \
cpu-m68hc12.lo \
cpu-m9s12x.lo \
+ cpu-s12z.lo \
cpu-m9s12xg.lo \
cpu-m68k.lo \
cpu-mcore.lo \
@@ -207,6 +208,7 @@ ALL_MACHINES_CFILES = \
cpu-m68hc11.c \
cpu-m68hc12.c \
cpu-m9s12x.c \
+ cpu-s12z.c \
cpu-m9s12xg.c \
cpu-m68k.c \
cpu-mcore.c \
@@ -322,6 +324,7 @@ BFD32_BACKENDS = \
elf32-m68hc12.lo \
elf32-m68hc1x.lo \
elf32-m68k.lo \
+ elf32-s12z.lo \
elf32-mcore.lo \
elf32-mep.lo \
elf32-metag.lo \
@@ -458,6 +461,7 @@ BFD32_BACKENDS_CFILES = \
elf32-m68hc12.c \
elf32-m68hc1x.c \
elf32-m68k.c \
+ elf32-s12z.c \
elf32-mcore.c \
elf32-mep.c \
elf32-metag.c \
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index ccd9ce1..88b6b8e 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -456,6 +456,7 @@ ALL_MACHINES = \
cpu-m68hc11.lo \
cpu-m68hc12.lo \
cpu-m9s12x.lo \
+ cpu-s12z.lo \
cpu-m9s12xg.lo \
cpu-m68k.lo \
cpu-mcore.lo \
@@ -540,6 +541,7 @@ ALL_MACHINES_CFILES = \
cpu-m68hc11.c \
cpu-m68hc12.c \
cpu-m9s12x.c \
+ cpu-s12z.c \
cpu-m9s12xg.c \
cpu-m68k.c \
cpu-mcore.c \
@@ -656,6 +658,7 @@ BFD32_BACKENDS = \
elf32-m68hc12.lo \
elf32-m68hc1x.lo \
elf32-m68k.lo \
+ elf32-s12z.lo \
elf32-mcore.lo \
elf32-mep.lo \
elf32-metag.lo \
@@ -792,6 +795,7 @@ BFD32_BACKENDS_CFILES = \
elf32-m68hc12.c \
elf32-m68hc1x.c \
elf32-m68k.c \
+ elf32-s12z.c \
elf32-mcore.c \
elf32-mep.c \
elf32-metag.c \
@@ -1253,6 +1257,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m68k.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m9s12x.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m9s12xg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-s12z.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-mcore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-mep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-metag.Plo@am__quote@
@@ -1344,6 +1349,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc12.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc1x.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68k.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-s12z.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mcore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-metag.Plo@am__quote@
diff --git a/bfd/archures.c b/bfd/archures.c
index 4c20664..3af7ddd 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -281,6 +281,8 @@ DESCRIPTION
.#define bfd_mach_m6812s 2
. bfd_arch_m9s12x, {* Freescale S12X. *}
. bfd_arch_m9s12xg, {* Freescale XGATE. *}
+. bfd_arch_s12z, {* Freescale S12Z. *}
+.#define bfd_mach_s12z_default 0
. bfd_arch_z8k, {* Zilog Z8000. *}
.#define bfd_mach_z8001 1
.#define bfd_mach_z8002 2
@@ -590,6 +592,7 @@ extern const bfd_arch_info_type bfd_m68hc11_arch;
extern const bfd_arch_info_type bfd_m68hc12_arch;
extern const bfd_arch_info_type bfd_m9s12x_arch;
extern const bfd_arch_info_type bfd_m9s12xg_arch;
+extern const bfd_arch_info_type bfd_s12z_arch;
extern const bfd_arch_info_type bfd_m68k_arch;
extern const bfd_arch_info_type bfd_mcore_arch;
extern const bfd_arch_info_type bfd_mep_arch;
@@ -679,6 +682,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
&bfd_m68hc12_arch,
&bfd_m9s12x_arch,
&bfd_m9s12xg_arch,
+ &bfd_s12z_arch,
&bfd_m68k_arch,
&bfd_mcore_arch,
&bfd_mep_arch,
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index 50a8b52..481587e 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -581,6 +581,8 @@ void bfd_putb64 (bfd_uint64_t, void *);
void bfd_putl64 (bfd_uint64_t, void *);
void bfd_putb32 (bfd_vma, void *);
void bfd_putl32 (bfd_vma, void *);
+void bfd_putb24 (bfd_vma, void *);
+void bfd_putl24 (bfd_vma, void *);
void bfd_putb16 (bfd_vma, void *);
void bfd_putl16 (bfd_vma, void *);
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 5f7ecd3..c64eee1 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -588,6 +588,8 @@ void bfd_putb64 (bfd_uint64_t, void *);
void bfd_putl64 (bfd_uint64_t, void *);
void bfd_putb32 (bfd_vma, void *);
void bfd_putl32 (bfd_vma, void *);
+void bfd_putb24 (bfd_vma, void *);
+void bfd_putl24 (bfd_vma, void *);
void bfd_putb16 (bfd_vma, void *);
void bfd_putl16 (bfd_vma, void *);
@@ -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,
diff --git a/bfd/config.bfd b/bfd/config.bfd
index bbd4194..0db8ed4 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -179,6 +179,7 @@ lm32) targ_archs=bfd_lm32_arch ;;
m6811*|m68hc11*) targ_archs="bfd_m68hc11_arch bfd_m68hc12_arch bfd_m9s12x_arch bfd_m9s12xg_arch" ;;
m6812*|m68hc12*) targ_archs="bfd_m68hc12_arch bfd_m68hc11_arch bfd_m9s12x_arch bfd_m9s12xg_arch" ;;
m68*) targ_archs=bfd_m68k_arch ;;
+s12z*) targ_archs=bfd_s12z_arch ;;
microblaze*) targ_archs=bfd_microblaze_arch ;;
mips*) targ_archs=bfd_mips_arch ;;
nds32*) targ_archs=bfd_nds32_arch ;;
@@ -814,6 +815,9 @@ case "${targ}" in
targ_defvec=m68k_elf32_vec
;;
+ s12z-*-*)
+ targ_defvec=s12z_elf32_vec
+ ;;
mcore-*-elf)
targ_defvec=mcore_elf32_be_vec
targ_selvecs="mcore_elf32_be_vec mcore_elf32_le_vec"
diff --git a/bfd/configure b/bfd/configure
index edc1de9..2f3dbe7 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -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" ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 1297469..b320828 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -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
index 0000000..07bcb49
--- /dev/null
+++ b/bfd/cpu-s12z.c
@@ -0,0 +1,41 @@
+/* BFD support for the Freescale 9S12Z processor
+ Copyright (C) 2008-2018 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_s12z_arch =
+{
+ 16, /* 16 bits in a word. */
+ 24, /* 24 bits in an address. */
+ 8, /* 8 bits in a byte. */
+ bfd_arch_s12z,
+ 0,
+ "s12z",
+ "s12z",
+ 4, /* Section alignment power. */
+ TRUE,
+ bfd_default_compatible,
+ bfd_default_scan,
+ bfd_arch_default_fill,
+ 0,
+};
+
diff --git a/bfd/elf32-s12z.c b/bfd/elf32-s12z.c
new file mode 100644
index 0000000..4b638e6
--- /dev/null
+++ b/bfd/elf32-s12z.c
@@ -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"
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index c581238..971be4f 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -613,6 +613,27 @@ bfd_putl16 (bfd_vma data, void *p)
addr[1] = (data >> 8) & 0xff;
}
+
+void
+bfd_putb24 (bfd_vma data, void *p)
+{
+ bfd_byte *addr = (bfd_byte *) p;
+ addr[0] = (data >> 16) & 0xff;
+ addr[1] = (data >> 8) & 0xff;
+ addr[2] = data & 0xff;
+}
+
+
+void
+bfd_putl24 (bfd_vma data, void *p)
+{
+ bfd_byte *addr = (bfd_byte *) p;
+ addr[0] = data & 0xff;
+ addr[1] = (data >> 8) & 0xff;
+ addr[2] = (data >> 16) & 0xff;
+}
+
+
bfd_vma
bfd_getb32 (const void *p)
{
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index e8c0fd8..b810c40 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -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",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index f7e34a9..411f998 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -431,6 +431,7 @@ bfd_get_reloc_size (reloc_howto_type *howto)
{
switch (howto->size)
{
+ case 5: return 3;
case 0: return 1;
case 1: return 2;
case 2: return 4;
@@ -917,6 +918,16 @@ space consuming. For each target:
switch (howto->size)
{
+ case 5:
+ {
+ long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
+ x >>= 8;
+ DOIT (x);
+ bfd_put_16 (abfd, (bfd_vma) (x >> 8), (bfd_byte *) data + octets);
+ bfd_put_8 (abfd, (x & 0xFF), (unsigned char *) data + 2 + octets);
+ }
+ break;
+
case 0:
{
char x = bfd_get_8 (abfd, (char *) data + octets);
@@ -5949,6 +5960,12 @@ ENUMDOC
This is the 8 bit high part of an absolute address and immediately follows
a matching LO8XG part.
ENUM
+ BFD_RELOC_S12Z_15_PCREL
+ENUMDOC
+ Freescale S12Z reloc.
+ This is a 15 bit relative address. If the most significant bits are all zero
+ then it may be truncated to 8 bits.
+ENUM
BFD_RELOC_16C_NUM08
ENUMX
BFD_RELOC_16C_NUM08_C
diff --git a/bfd/targets.c b/bfd/targets.c
index 5d78f57..5a2a684 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -684,6 +684,7 @@ extern const bfd_target m32r_elf32_linux_le_vec;
extern const bfd_target m68hc11_elf32_vec;
extern const bfd_target m68hc12_elf32_vec;
extern const bfd_target m68k_elf32_vec;
+extern const bfd_target s12z_elf32_vec;
extern const bfd_target mach_o_be_vec;
extern const bfd_target mach_o_le_vec;
extern const bfd_target mach_o_fat_vec;
@@ -1044,6 +1045,8 @@ static const bfd_target * const _bfd_target_vector[] =
&m68k_elf32_vec,
+ &s12z_elf32_vec,
+
&mach_o_be_vec,
&mach_o_le_vec,
&mach_o_fat_vec,
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 3d90103..fd77f44 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 6a9c51d..6a9319f 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -119,6 +119,7 @@
#include "elf/m32r.h"
#include "elf/m68k.h"
#include "elf/m68hc11.h"
+#include "elf/s12z.h"
#include "elf/mcore.h"
#include "elf/mep.h"
#include "elf/metag.h"
@@ -1274,6 +1275,10 @@ dump_relocations (Filedata * filedata,
rtype = elf_m68hc11_reloc_type (type);
break;
+ case EM_S12Z:
+ rtype = elf_s12z_reloc_type (type);
+ break;
+
case EM_68K:
rtype = elf_m68k_reloc_type (type);
break;
@@ -12309,6 +12314,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
case EM_68HC11:
case EM_68HC12:
return reloc_type == 6; /* R_M68HC11_32. */
+ case EM_S12Z:
+ return reloc_type == 6; /* R_S12Z_EXT32. */
case EM_MCORE:
return reloc_type == 1; /* R_MCORE_ADDR32. */
case EM_CYGNUS_MEP:
diff --git a/binutils/testsuite/binutils-all/dw2-1.S b/binutils/testsuite/binutils-all/dw2-1.S
index 06cb593..6342a0e 100644
--- a/binutils/testsuite/binutils-all/dw2-1.S
+++ b/binutils/testsuite/binutils-all/dw2-1.S
@@ -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:
diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp
index 9fc9a18..dcaab84 100644
--- a/binutils/testsuite/lib/binutils-common.exp
+++ b/binutils/testsuite/lib/binutils-common.exp
@@ -23,7 +23,7 @@ proc is_elf_format {} {
# config.sub for these targets curiously transforms a target doublet
# ending in -elf to -none. eg. m68hc12-elf to m68hc12-unknown-none
# They are always elf.
- if { [istarget m68hc1*-*] || [istarget xgate-*] } {
+ if { [istarget m68hc1*-*] || [istarget s12z*-*] || [istarget xgate-*] } {
return 1;
}
# vxworks (and windiss) excluded due to number of ELF tests that need
diff --git a/gas/ChangeLog b/gas/ChangeLog
index c2a5659..39c51b2 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 9523770..ff46b0d 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -156,6 +156,7 @@ TARGET_CPU_CFILES = \
config/tc-m32r.c \
config/tc-m68hc11.c \
config/tc-m68k.c \
+ config/tc-s12z.c \
config/tc-mcore.c \
config/tc-mep.c \
config/tc-metag.c \
@@ -229,6 +230,7 @@ TARGET_CPU_HFILES = \
config/tc-m32r.h \
config/tc-m68hc11.h \
config/tc-m68k.h \
+ config/tc-s12z.h \
config/tc-mcore.h \
config/tc-mep.h \
config/tc-metag.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 4feabb3..c127d36 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -452,6 +452,7 @@ TARGET_CPU_CFILES = \
config/tc-m32r.c \
config/tc-m68hc11.c \
config/tc-m68k.c \
+ config/tc-s12z.c \
config/tc-mcore.c \
config/tc-mep.c \
config/tc-metag.c \
@@ -525,6 +526,7 @@ TARGET_CPU_HFILES = \
config/tc-m32r.h \
config/tc-m68hc11.h \
config/tc-m68k.h \
+ config/tc-s12z.h \
config/tc-mcore.h \
config/tc-mep.h \
config/tc-metag.h \
@@ -872,6 +874,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m32r.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m68hc11.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m68k.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-s12z.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-mcore.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-mep.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-metag.Po@am__quote@
@@ -1318,6 +1321,20 @@ tc-m68k.obj: config/tc-m68k.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-m68k.obj `if test -f 'config/tc-m68k.c'; then $(CYGPATH_W) 'config/tc-m68k.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-m68k.c'; fi`
+tc-s12z.o: config/tc-s12z.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-s12z.o -MD -MP -MF $(DEPDIR)/tc-s12z.Tpo -c -o tc-s12z.o `test -f 'config/tc-s12z.c' || echo '$(srcdir)/'`config/tc-s12z.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-s12z.Tpo $(DEPDIR)/tc-s12z.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-s12z.c' object='tc-s12z.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-s12z.o `test -f 'config/tc-s12z.c' || echo '$(srcdir)/'`config/tc-s12z.c
+
+tc-s12z.obj: config/tc-s12z.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-s12z.obj -MD -MP -MF $(DEPDIR)/tc-s12z.Tpo -c -o tc-s12z.obj `if test -f 'config/tc-s12z.c'; then $(CYGPATH_W) 'config/tc-s12z.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-s12z.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-s12z.Tpo $(DEPDIR)/tc-s12z.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-s12z.c' object='tc-s12z.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-s12z.obj `if test -f 'config/tc-s12z.c'; then $(CYGPATH_W) 'config/tc-s12z.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-s12z.c'; fi`
+
tc-mcore.o: config/tc-mcore.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-mcore.o -MD -MP -MF $(DEPDIR)/tc-mcore.Tpo -c -o tc-mcore.o `test -f 'config/tc-mcore.c' || echo '$(srcdir)/'`config/tc-mcore.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-mcore.Tpo $(DEPDIR)/tc-mcore.Po
diff --git a/gas/NEWS b/gas/NEWS
index ec1ba78..a05b703 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
-*- text -*-
+* Add support for the Freescale S12Z architecture.
+
* Add --generate-missing-build-notes=[yes|no] option to create (or not) GNU
Build Attribute notes if none are present in the input sources. Add a
--enable-generate-build-notes=[yes|no] configure time option to set the
diff --git a/gas/config/tc-s12z.c b/gas/config/tc-s12z.c
new file mode 100644
index 0000000..e024e72
--- /dev/null
+++ b/gas/config/tc-s12z.c
@@ -0,0 +1,3840 @@
+/* tc-s12z.c -- Assembler code for the Freescale S12Z
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "as.h"
+#include "safe-ctype.h"
+#include "subsegs.h"
+#include "dwarf2dbg.h"
+#include "opcodes/s12z.h"
+#include <stdint.h>
+#include <limits.h>
+#include <stdbool.h>
+
+const char comment_chars[] = ";";
+
+const char line_comment_chars[] = "#*";
+const char line_separator_chars[] = "";
+
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "dD";
+
+static char *fail_line_pointer;
+
+
+/* Options and initialization. */
+
+const char *md_shortopts = "Sm:";
+
+struct option md_longopts[] =
+ {
+ };
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+
+relax_typeS md_relax_table[] =
+ {
+
+ };
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function. */
+const pseudo_typeS md_pseudo_table[] =
+ {
+ {0, 0, 0}
+ };
+
+
+/* Get the target cpu for the assembler. */
+const char *
+s12z_arch_format (void)
+{
+ return "elf32-s12z";
+}
+
+enum bfd_architecture
+s12z_arch (void)
+{
+ return bfd_arch_s12z;
+}
+
+int
+s12z_mach (void)
+{
+ return 0;
+}
+
+/* Listing header selected according to cpu. */
+const char *
+s12z_listing_header (void)
+{
+ return "S12Z GAS ";
+}
+
+void
+md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
+{
+}
+
+void
+s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED)
+{
+}
+
+int
+md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+symbolS *
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+const char *
+md_atof (int type, char *litP, int *sizeP)
+{
+ return ieee_md_atof (type, litP, sizeP, TRUE);
+}
+
+valueT
+md_section_align (asection *seg, valueT addr)
+{
+ int align = bfd_get_section_alignment (stdoutput, seg);
+ return ((addr + (1 << align) - 1) & -(1 << align));
+}
+
+void
+md_begin (void)
+{
+}
+
+void
+s12z_init_after_args (void)
+{
+}
+
+/* Builtin help. */
+
+
+static char *
+skip_whites (char *p)
+{
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ return p;
+}
+
+
+
+/* Start a new insn that contains at least 'size' bytes. Record the
+ line information of that insn in the dwarf2 debug sections. */
+static char *
+s12z_new_insn (int size)
+{
+ char *f = frag_more (size);
+
+ dwarf2_emit_insn (size);
+
+ return f;
+}
+
+
+
+static int lex_reg_name (uint16_t which, int *reg);
+
+static int
+lex_constant (long *v)
+{
+ char *end = NULL;
+ char *p = input_line_pointer;
+
+ /* A constant may not have the same value as a register
+ eg: "d6" */
+ int dummy;
+ if (lex_reg_name (~0, &dummy))
+ {
+ input_line_pointer = p;
+ return 0;
+ }
+
+ errno = 0;
+ *v = strtol (p, &end, 0);
+ if (errno == 0 && end != p)
+ {
+ input_line_pointer = end;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+lex_match (char x)
+{
+ char *p = input_line_pointer;
+ if (*p != x)
+ return 0;
+
+ input_line_pointer++;
+ return 1;
+}
+
+
+static int
+lex_expression (expressionS *exp)
+{
+ char *ilp = input_line_pointer;
+ int dummy;
+ exp->X_op = O_absent;
+
+ if (lex_match ('#'))
+ goto fail;
+
+ if (lex_reg_name (~0, &dummy))
+ goto fail;
+
+ expression (exp);
+ if (exp->X_op != O_absent)
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+/* immediate operand */
+static int
+lex_imm (long *v)
+{
+ char *ilp = input_line_pointer;
+
+ if (*input_line_pointer != '#')
+ goto fail;
+
+ input_line_pointer++;
+ expressionS exp;
+ if (!lex_expression (&exp))
+ goto fail;
+
+ if (exp.X_op != O_constant)
+ goto fail;
+
+ *v = exp.X_add_number;
+ return 1;
+
+fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+/* Short mmediate operand */
+static int
+lex_imm_e4 (long *val)
+{
+ char *ilp = input_line_pointer;
+ if ((lex_imm (val)))
+ {
+ if ((*val == -1) || (*val > 0 && *val <= 15))
+ {
+ return 1;
+ }
+ }
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+lex_match_string (const char *s)
+{
+ char *p = input_line_pointer;
+ while (p != 0 && *p != '\t' && *p != ' ' && *p != '\0')
+ {
+ p++;
+ }
+
+ size_t len = p - input_line_pointer;
+ if (len != strlen (s))
+ return 0;
+
+ if (0 == strncasecmp (s, input_line_pointer, len))
+ {
+ input_line_pointer = p;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Parse a register name.
+ WHICH is a ORwise combination of the registers which are accepted.
+ ~0 accepts all.
+ On success, REG will be filled with the index of the register which
+ was successfully scanned.
+*/
+static int
+lex_reg_name (uint16_t which, int *reg)
+{
+ char *p = input_line_pointer;
+ while (p != 0 &&
+ ((*p >= 'a' && *p <='z') || (*p >= '0' && *p <= '9') || (*p >= 'A' && *p <='Z')))
+ {
+ p++;
+ }
+
+ int len = p - input_line_pointer;
+
+ if (len <= 0)
+ return 0;
+
+ int i;
+ for (i = 0; i < S12Z_N_REGISTERS; ++i)
+ {
+ gas_assert (registers[i].name);
+
+ if (0 == strncasecmp (registers[i].name, input_line_pointer, len))
+ {
+ if ((0x1U << i) & which)
+ {
+ input_line_pointer = p;
+ *reg = i;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+lex_force_match (char x)
+{
+ char *p = input_line_pointer;
+ if (*p != x)
+ {
+ as_bad (_("Expecting '%c'"), x);
+ return 0;
+ }
+
+ input_line_pointer++;
+ return 1;
+}
+
+static int
+lex_opr (uint8_t *buffer, int *n_bytes, expressionS *exp)
+{
+ char *ilp = input_line_pointer;
+ uint8_t *xb = buffer;
+ int reg;
+ long imm;
+ exp->X_op = O_absent;
+ *n_bytes = 0;
+ *xb = 0;
+ if (lex_imm_e4 (&imm))
+ {
+ if (imm > 0)
+ *xb = imm;
+ else
+ *xb = 0;
+ *xb |= 0x70;
+ *n_bytes = 1;
+ return 1;
+ }
+ else if (lex_reg_name (REG_BIT_Dn, &reg))
+ {
+ *xb = reg;
+ *xb |= 0xb8;
+ *n_bytes = 1;
+ return 1;
+ }
+ else if (lex_match ('['))
+ {
+ if (lex_expression (exp))
+ {
+ long c = exp->X_add_number;
+ if (lex_match (','))
+ {
+ if (lex_reg_name (REG_BIT_XYSP, &reg))
+ {
+ int i;
+ if (c <= 255 && c >= -256)
+ {
+ *n_bytes = 2;
+ *xb |= 0xc4;
+ }
+ else
+ {
+ *n_bytes = 4;
+ *xb |= 0xc6;
+ }
+ *xb |= (reg - REG_X) << 4;
+
+ if (c < 0)
+ *xb |= 0x01;
+ for (i = 1; i < *n_bytes ; ++i)
+ {
+ buffer[i] = c >> (8 * (*n_bytes - i - 1));
+ }
+ }
+ else
+ {
+ as_bad (_("Bad operand for constant offset"));
+ goto fail;
+ }
+ }
+ else
+ {
+ *xb = 0xfe;
+ *n_bytes = 4;
+ buffer[1] = c >> 16;
+ buffer[2] = c >> 8;
+ buffer[3] = c;
+ }
+ }
+ else if (lex_reg_name (REG_BIT_Dn, &reg))
+ {
+ if (!lex_force_match (','))
+ goto fail;
+
+ int reg2;
+ if (lex_reg_name (REG_BIT_XY, &reg2))
+ {
+ *n_bytes = 1;
+ *xb = reg;
+ *xb |= (reg2 - REG_X) << 4;
+ *xb |= 0xc8;
+ }
+ else
+ {
+ as_bad (_("Invalid operand for register offset"));
+ goto fail;
+ }
+ }
+ else
+ {
+ goto fail;
+ }
+ if (!lex_force_match (']'))
+ goto fail;
+ return 1;
+ }
+ else if (lex_match ('('))
+ {
+ long c;
+ if (lex_constant (&c))
+ {
+ if (!lex_force_match (','))
+ goto fail;
+ int reg2;
+ if (lex_reg_name (REG_BIT_XYSP, &reg2))
+ {
+ if (reg2 != REG_P && c >= 0 && c <= 15)
+ {
+ *n_bytes = 1;
+ *xb = 0x40;
+ *xb |= (reg2 - REG_X) << 4;
+ *xb |= c;
+ }
+ else if (c >= -256 && c <= 255)
+ {
+ *n_bytes = 2;
+ *xb = 0xc0;
+ *xb |= (reg2 - REG_X) << 4;
+ if (c < 0)
+ *xb |= 0x01;
+ buffer[1] = c;
+ }
+ else
+ {
+ *n_bytes = 4;
+ *xb = 0xc2;
+ *xb |= (reg2 - REG_X) << 4;
+ buffer[1] = c >> 16;
+ buffer[2] = c >> 8;
+ buffer[3] = c;
+ }
+ }
+ else if (lex_reg_name (REG_BIT_Dn, &reg2))
+ {
+ if (c >= -1 * (long) (0x1u << 17)
+ &&
+ c < (long) (0x1u << 17) - 1)
+ {
+ *n_bytes = 3;
+ *xb = 0x80;
+ *xb |= reg2;
+ *xb |= ((c >> 16) & 0x03) << 4;
+ buffer[1] = c >> 8;
+ buffer[2] = c;
+ }
+ else
+ {
+ *n_bytes = 4;
+ *xb = 0xe8;
+ *xb |= reg2;
+ buffer[1] = c >> 16;
+ buffer[2] = c >> 8;
+ buffer[3] = c;
+ }
+ }
+ else
+ {
+ as_bad (_("Bad operand for constant offset"));
+ goto fail;
+ }
+ }
+ else if (lex_reg_name (REG_BIT_Dn, &reg))
+ {
+ if (lex_match (','))
+ {
+ int reg2;
+ if (lex_reg_name (REG_BIT_XYS, &reg2))
+ {
+ *n_bytes = 1;
+ *xb = 0x88;
+ *xb |= (reg2 - REG_X) << 4;
+ *xb |= reg;
+ }
+ else
+ {
+ as_bad (_("Invalid operand for register offset"));
+ goto fail;
+ }
+ }
+ else
+ {
+ goto fail;
+ }
+ }
+ else if (lex_reg_name (REG_BIT_XYS, &reg))
+ {
+ if (lex_match ('-'))
+ {
+ if (reg == REG_S)
+ {
+ as_bad (_("Invalid register for postdecrement operation"));
+ goto fail;
+ }
+ *n_bytes = 1;
+ if (reg == REG_X)
+ *xb = 0xc7;
+ else if (reg == REG_Y)
+ *xb = 0xd7;
+ }
+ else if (lex_match ('+'))
+ {
+ *n_bytes = 1;
+ if (reg == REG_X)
+ *xb = 0xe7;
+ else if (reg == REG_Y)
+ *xb = 0xf7;
+ else if (reg == REG_S)
+ *xb = 0xff;
+ }
+ else
+ {
+ goto fail;
+ }
+ }
+ else if (lex_match ('+'))
+ {
+ if (lex_reg_name (REG_BIT_XY, &reg))
+ {
+ *n_bytes = 1;
+ if (reg == REG_X)
+ *xb = 0xe3;
+ else if (reg == REG_Y)
+ *xb = 0xf3;
+ }
+ else
+ {
+ as_bad (_("Invalid register for preincrement operation"));
+ goto fail;
+ }
+ }
+ else if (lex_match ('-'))
+ {
+ if (lex_reg_name (REG_BIT_XYS, &reg))
+ {
+ *n_bytes = 1;
+ if (reg == REG_X)
+ *xb = 0xc3;
+ else if (reg == REG_Y)
+ *xb = 0xd3;
+ else if (reg == REG_S)
+ *xb = 0xfb;
+ }
+ else
+ {
+ as_bad (_("Invalid register for predecrement operation"));
+ goto fail;
+ }
+ }
+ else
+ {
+ goto fail;
+ }
+
+ if (! lex_match (')'))
+ goto fail;
+ return 1;
+ }
+ else if (lex_expression (exp))
+ {
+ *xb = 0xfa;
+ *n_bytes = 4;
+ buffer[1] = 0;
+ buffer[2] = 0;
+ buffer[3] = 0;
+ if (exp->X_op == O_constant)
+ {
+ if (exp->X_add_number < (0x1U << 14))
+ {
+ *xb = 0x00;
+ *n_bytes = 2;
+ *xb |= exp->X_add_number >> 8;
+ buffer[1] = exp->X_add_number;
+ }
+ else if (exp->X_add_number < (0x1U << 19))
+ {
+ *xb = 0xf8;
+ if (exp->X_add_number & (0x1U << 17))
+ *xb |= 0x04;
+ if (exp->X_add_number & (0x1U << 16))
+ *xb |= 0x01;
+ *n_bytes = 3;
+ buffer[1] = exp->X_add_number >> 8;
+ buffer[2] = exp->X_add_number;
+ }
+ else
+ {
+ *xb = 0xfa;
+ *n_bytes = 4;
+ buffer[1] = exp->X_add_number >> 16;
+ buffer[2] = exp->X_add_number >> 8;
+ buffer[3] = exp->X_add_number;
+ }
+ }
+ return 1;
+ }
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+lex_offset (long *val)
+{
+ char *end = NULL;
+ char *p = input_line_pointer;
+
+ if (*p++ != '*')
+ return 0;
+
+ if (*p != '+' && *p != '-')
+ return 0;
+
+ bool negative = (*p == '-');
+ p++;
+
+ errno = 0;
+ *val = strtol (p, &end, 0);
+ if (errno == 0)
+ {
+ if (negative)
+ *val *= -1;
+ input_line_pointer = end;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+struct instruction;
+
+typedef int (*parse_operand_func) (const struct instruction *);
+
+struct instruction
+{
+ const char *name;
+
+ /* The "page" to which the instruction belongs.
+ This is also only a hint. Some instructions might have modes in both
+ pages... */
+ char page;
+
+ /* This is a hint - and only a hint - about the opcode of the instruction.
+ The parse_operand_func is free to ignore it.
+ */
+ uint8_t opc;
+
+ parse_operand_func parse_operands;
+
+ /* Some instructions can be encoded with a different opcode */
+ uint8_t alt_opc;
+};
+
+static int
+no_operands (const struct instruction *insn)
+{
+ if (*input_line_pointer != '\0')
+ {
+ as_bad (_("Garbage at end of instruction"));
+ return 0;
+ }
+
+ char *f = s12z_new_insn (insn->page);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc, 1);
+
+ return 1;
+}
+
+/* Emit the code for an OPR address mode operand */
+static char *
+emit_opr (char *f, const uint8_t *buffer, int n_bytes, expressionS *exp)
+{
+ int i;
+ number_to_chars_bigendian (f++, buffer[0], 1);
+ if (exp->X_op != O_absent && exp->X_op != O_constant)
+ {
+ fix_new_exp (frag_now,
+ f - frag_now->fr_literal,
+ 3,
+ exp,
+ FALSE,
+ BFD_RELOC_24);
+ }
+ for (i = 1; i < n_bytes; ++i)
+ number_to_chars_bigendian (f++, buffer[i], 1);
+
+ return f;
+}
+
+/* Emit the code for a 24 bit direct address operand */
+static char *
+emit_ext24 (char *f, long v)
+{
+ number_to_chars_bigendian (f, v, 3);
+
+ return f + 3;
+}
+
+static int
+opr (const struct instruction *insn)
+{
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (lex_opr (buffer, &n_bytes, &exp))
+ {
+ /* Large constant direct values are more efficiently encoded as ext24 mode.
+ Otherwise a decision has to be deferred to a relax. */
+ if (exp.X_op == O_constant
+ && buffer[0] == 0xFA
+ && insn->alt_opc != 0)
+ {
+ char *f = s12z_new_insn (4);
+
+ /* I don't think there are any instances of page 2 opcodes in this case */
+ gas_assert (insn->page == 1);
+
+ number_to_chars_bigendian (f++, insn->alt_opc, 1);
+
+ emit_ext24 (f, exp.X_add_number);
+ }
+ else
+ {
+ char *f = s12z_new_insn (n_bytes + 1);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Parse a 15 bit offset, as an expression.
+ LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
+ */
+static int
+lex_15_bit_offset (bool *long_displacement, expressionS *exp)
+{
+ char *ilp = input_line_pointer;
+
+ long val;
+ if (lex_offset (&val))
+ {
+ exp->X_op = O_absent;
+ exp->X_add_number = val;
+ }
+ else if (lex_expression (exp))
+ {
+ if (exp->X_op == O_constant)
+ {
+ val = exp->X_add_number;
+ }
+ else
+ {
+ /* If a symbol was parsed we don't know the displacement.
+ We have to assume it is long, and relax it later if possible. */
+ *long_displacement = true;
+ return 1;
+ }
+ }
+ else
+ {
+ exp->X_op = O_absent;
+ goto fail;
+ }
+
+ if (val > 0x3FFF || val < -0x4000)
+ {
+ as_fatal (_("Offset is outside of 15 bit range"));
+ return 0;
+ }
+
+ *long_displacement = (val > 63 || val < -64);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static void
+emit_15_bit_offset (char *f, int where, expressionS *exp)
+{
+ gas_assert (exp);
+ if (exp->X_op != O_absent && exp->X_op != O_constant)
+ {
+ exp->X_add_number += where;
+ fixS *fix = fix_new_exp (frag_now,
+ f - frag_now->fr_literal,
+ 2,
+ exp,
+ TRUE,
+ BFD_RELOC_16_PCREL);
+ fix->fx_addnumber = where - 2;
+ }
+ else
+ {
+ long val = exp->X_add_number;
+ bool long_displacement = (val > 63 || val < -64);
+ if (long_displacement)
+ val |= 0x8000;
+ else
+ val &= 0x7F;
+
+ number_to_chars_bigendian (f++, val, long_displacement ? 2 : 1);
+ }
+}
+
+static int
+rel (const struct instruction *insn)
+{
+ bool long_displacement;
+
+ expressionS exp;
+ if (! lex_15_bit_offset (&long_displacement, &exp))
+ return 0;
+
+ char *f = s12z_new_insn (long_displacement ? 3 : 2);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ emit_15_bit_offset (f, 3, &exp);
+ return 1;
+}
+
+static int
+reg_inh (const struct instruction *insn)
+{
+ int reg;
+ if (lex_reg_name (REG_BIT_Dn, &reg))
+ {
+ char *f = s12z_new_insn (insn->page);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + reg, 1);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Special case for CLR X and CLR Y */
+static int
+clr_xy (const struct instruction *insn ATTRIBUTE_UNUSED)
+{
+ int reg;
+ if (lex_reg_name (REG_BIT_XY, &reg))
+ {
+ char *f = s12z_new_insn (1);
+ number_to_chars_bigendian (f, 0x9a + reg - REG_X, 1);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Some instructions have a suffix like ".l", ".b", ".w" etc
+ which indicates the size of the operands. */
+static int
+size_from_suffix (const struct instruction *insn, int idx)
+{
+ const char *dot = strchr (insn->name, '.');
+
+ if (dot == NULL)
+ return -3;
+
+ int size = -2;
+ switch (dot[1 + idx])
+ {
+ case 'b':
+ size = 1;
+ break;
+ case 'w':
+ size = 2;
+ break;
+ case 'p':
+ size = 3;
+ break;
+ case 'l':
+ size = 4;
+ break;
+ default:
+ as_fatal (_("Bad size"));
+ };
+
+ return size;
+}
+
+static int
+mul_reg_reg_reg (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int Dd;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dj;
+ if (!lex_reg_name (REG_BIT_Dn, &Dj))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dk;
+ if (!lex_reg_name (REG_BIT_Dn, &Dk))
+ goto fail;
+
+ char *f = s12z_new_insn (insn->page + 1);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+ const char *dot = strchrnul (insn->name, '.');
+ uint8_t mb ;
+ switch (dot[-1])
+ {
+ case 's':
+ mb = 0x80;
+ break;
+ case 'u':
+ mb = 0x00;
+ break;
+ default:
+ as_fatal (_("BAD MUL"));
+ break;
+ }
+
+ mb |= Dj << 3;
+ mb |= Dk;
+
+ number_to_chars_bigendian (f++, mb, 1);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+mul_reg_reg_imm (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int Dd;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dj;
+ if (!lex_reg_name (REG_BIT_Dn, &Dj))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long imm;
+ if (!lex_imm (&imm))
+ goto fail;
+
+
+ int size = size_from_suffix (insn, 0);
+
+ char *f = s12z_new_insn (insn->page + 1 + size);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+ uint8_t mb = 0x44;
+ const char *dot = strchrnul (insn->name, '.');
+ switch (dot[-1])
+ {
+ case 's':
+ mb |= 0x80;
+ break;
+ case 'u':
+ mb |= 0x00;
+ break;
+ default:
+ as_fatal (_("BAD MUL"));
+ break;
+ }
+
+ mb |= Dj << 3;
+ mb |= size - 1;
+
+ number_to_chars_bigendian (f++, mb, 1);
+ number_to_chars_bigendian (f++, imm, size);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+mul_reg_reg_opr (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int Dd;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dj;
+ if (!lex_reg_name (REG_BIT_Dn, &Dj))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ int size = size_from_suffix (insn, 0);
+
+ char *f = s12z_new_insn (insn->page + 1 + n_bytes);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+ uint8_t mb = 0x40;
+ const char *dot = strchrnul (insn->name, '.');
+ switch (dot[-1])
+ {
+ case 's':
+ mb |= 0x80;
+ break;
+ case 'u':
+ mb |= 0x00;
+ break;
+ default:
+ as_fatal (_("BAD MUL"));
+ break;
+ }
+
+ mb |= Dj << 3;
+ mb |= size - 1;
+
+ number_to_chars_bigendian (f++, mb, 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+mul_reg_opr_opr (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int Dd;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer1[4];
+ int n_bytes1;
+ expressionS exp1;
+ if (!lex_opr (buffer1, &n_bytes1, &exp1))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer2[4];
+ int n_bytes2;
+ expressionS exp2;
+ if (!lex_opr (buffer2, &n_bytes2, &exp2))
+ goto fail;
+
+ int size1 = size_from_suffix (insn, 0);
+ int size2 = size_from_suffix (insn, 1);
+
+ char *f = s12z_new_insn (insn->page + 1 + n_bytes1 + n_bytes2);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + Dd, 1);
+ uint8_t mb = 0x42;
+ const char *dot = strchrnul (insn->name, '.');
+ switch (dot[-1])
+ {
+ case 's':
+ mb |= 0x80;
+ break;
+ case 'u':
+ mb |= 0x00;
+ break;
+ default:
+ as_fatal (_("BAD MUL"));
+ break;
+ }
+
+ mb |= (size1 - 1) << 4;
+ mb |= (size2 - 1) << 2;
+ number_to_chars_bigendian (f++, mb, 1);
+
+ f = emit_opr (f, buffer1, n_bytes1, &exp1);
+ f = emit_opr (f, buffer2, n_bytes2, &exp2);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+#define REG_BIT_GRP0 \
+ ((0x1U << REG_D2) | \
+ (0x1U << REG_D3) | \
+ (0x1U << REG_CCH) | \
+ (0x1U << REG_CCL) | \
+ (0x1U << REG_D0) | \
+ (0x1U << REG_D1))
+
+#define REG_BIT_GRP1 \
+ ((0x1U << REG_D4) | \
+ (0x1U << REG_D5) | \
+ (0x1U << REG_D6) | \
+ (0x1U << REG_D7) | \
+ (0x1U << REG_X) | \
+ (0x1U << REG_Y))
+
+static const uint8_t reg_map [] =
+ {
+ 0x02, // D2
+ 0x01, // D3
+ 0x20,
+ 0x10, // D5
+ 0x08, // D0
+ 0x04, // D1
+ 0x08, // D6
+ 0x04, // D7
+ 0x02,
+ 0x01, // Y
+ 0x00,
+ 0x00,
+ 0x20, // CCH
+ 0x10, // CCL
+ 0x00
+ };
+
+static int
+lex_reg_list (uint16_t grp, uint16_t *reg_bits)
+{
+ if (lex_match (','))
+ {
+ int reg;
+ if (!lex_reg_name (grp, &reg))
+ return 0;
+ *reg_bits |= 0x1u << reg;
+ lex_reg_list (grp, reg_bits);
+ }
+
+ /* Empty list */
+ return 1;
+}
+
+static int
+psh_pull (const struct instruction *insn)
+{
+ uint8_t pb =
+ (0 == strcmp ("pul", insn->name)) ? 0x80: 0x00;
+
+ if (lex_match_string ("all16b"))
+ {
+ pb |= 0x40;
+ }
+ else if (lex_match_string ("all"))
+ {
+ /* Nothing to do */
+ }
+ else
+ {
+ int reg1;
+ if (!lex_reg_name (REG_BIT_GRP1 | REG_BIT_GRP0, &reg1))
+ goto fail;
+ uint16_t admitted_group = 0;
+
+ if ((0x1U << reg1) & REG_BIT_GRP1)
+ admitted_group = REG_BIT_GRP1;
+ else if ((0x1U << reg1) & REG_BIT_GRP0)
+ admitted_group = REG_BIT_GRP0;
+
+ uint16_t reg_bits = 0x1 << reg1;
+ if (!lex_reg_list (admitted_group, &reg_bits))
+ goto fail;
+
+ if (reg_bits & REG_BIT_GRP1)
+ pb |= 0x40;
+
+ int i;
+ for (i = 0; i < 16; ++i)
+ {
+ if (reg_bits & (0x1u << i))
+ pb |= reg_map[i];
+ }
+ }
+
+ char *f = s12z_new_insn (2);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, pb, 1);
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ return 0;
+}
+
+
+static int
+tfr (const struct instruction *insn)
+{
+ int reg1;
+ if (!lex_reg_name (~0, &reg1))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int reg2;
+ if (!lex_reg_name (~0, &reg2))
+ goto fail;
+
+ if ((0 == strcasecmp ("sex", insn->name))
+ || (0 == strcasecmp ("zex", insn->name)))
+ {
+ if (registers[reg1].bytes >= registers[reg2].bytes)
+ {
+ as_bad (_("Source register for %s must be smaller that the destination register"),
+ insn->name);
+ goto fail;
+ }
+ }
+
+ char *f = s12z_new_insn (1 + insn->page);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, reg1 << 4 | reg2, 1);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ return 0;
+}
+
+static int
+imm8 (const struct instruction *insn)
+{
+ long imm;
+ if (! lex_imm (&imm))
+ return 0;
+ if (imm > 127 || imm < -128)
+ {
+ as_bad (_("Immediate value %ld is out of range for instruction %s"),
+ imm, insn->name);
+ }
+
+ char *f = s12z_new_insn (2);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, imm, 1);
+
+ return 1;
+}
+
+static int
+reg_imm (const struct instruction *insn, int allowed_reg)
+{
+ char *ilp = input_line_pointer;
+ int reg;
+ if (lex_reg_name (allowed_reg, &reg))
+ {
+ if (!lex_force_match (','))
+ goto fail;
+ long imm;
+ if (! lex_imm (&imm))
+ goto fail;
+
+ short size = registers[reg].bytes;
+ char *f = s12z_new_insn (insn->page + size);
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + reg, 1);
+ number_to_chars_bigendian (f++, imm, size);
+ return 1;
+ }
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+regd_imm (const struct instruction *insn)
+{
+ return reg_imm (insn, REG_BIT_Dn);
+}
+
+static int
+regdxy_imm (const struct instruction *insn)
+{
+ return reg_imm (insn, REG_BIT_Dn | REG_BIT_XY);
+}
+
+
+static int
+regs_imm (const struct instruction *insn)
+{
+ return reg_imm (insn, 0x1U << REG_S);
+}
+
+static int
+trap_imm (const struct instruction *insn ATTRIBUTE_UNUSED)
+{
+ long imm = -1;
+ if (! lex_imm (&imm))
+ goto fail;
+
+ if (imm < 0x92 || imm > 0xFF ||
+ (imm >= 0xA0 && imm <= 0xA7) ||
+ (imm >= 0xB0 && imm <= 0xB7))
+ {
+ as_bad (_("trap value %ld is not valid"), imm);
+ return 0;
+ }
+ else
+ {
+ char *f = s12z_new_insn (2);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, imm & 0xFF, 1);
+ return 1;
+ }
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ return 0;
+}
+
+
+
+/* Special one byte instruction CMP X, Y */
+static int
+regx_regy (const struct instruction *insn)
+{
+ int reg;
+ if (lex_reg_name (0x1U << REG_X, &reg))
+ {
+ if (lex_force_match (','))
+ {
+ if (lex_reg_name (0x1U << REG_Y, &reg))
+ {
+ char *f = s12z_new_insn (1);
+ number_to_chars_bigendian (f, insn->opc, 1);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Special one byte instruction SUB D6, X, Y */
+static int
+regd6_regx_regy (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+ int reg;
+ if (!lex_reg_name (0x1U << REG_D6, &reg))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_X, &reg))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_Y, &reg))
+ goto fail;
+
+ char *f = s12z_new_insn (1);
+ number_to_chars_bigendian (f, insn->opc, 1);
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+/* Special one byte instruction SUB D6, Y, X */
+static int
+regd6_regy_regx (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+ int reg;
+ if (!lex_reg_name (0x1U << REG_D6, &reg))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_Y, &reg))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_X, &reg))
+ goto fail;
+
+ char *f = s12z_new_insn (1);
+ number_to_chars_bigendian (f, insn->opc, 1);
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+reg_opr (const struct instruction *insn, int allowed_regs)
+{
+ char *ilp = input_line_pointer;
+ int reg;
+ if (lex_reg_name (allowed_regs, &reg))
+ {
+ if (!lex_force_match (','))
+ goto fail;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (lex_opr (buffer, &n_bytes, &exp))
+ {
+ /* Large constant direct values are more efficiently encoded as ext24 mode.
+ Otherwise a decision has to be deferred to a relax. */
+ if (exp.X_op == O_constant
+ && buffer[0] == 0xFA
+ && insn->alt_opc != 0)
+ {
+ char *f = s12z_new_insn (4);
+
+ /* I don't think there are any instances of page 2 opcodes in this case */
+ gas_assert (insn->page == 1);
+
+ number_to_chars_bigendian (f++, insn->alt_opc + reg, 1);
+
+ emit_ext24 (f, exp.X_add_number);
+ }
+ else
+ {
+ char *f = s12z_new_insn (n_bytes + insn->page);
+
+ if (insn->page == 2)
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+
+ number_to_chars_bigendian (f++, insn->opc + reg, 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+ }
+
+ return 1;
+ }
+ }
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+regdxy_opr (const struct instruction *insn)
+{
+ return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY);
+}
+
+static int
+regd_opr (const struct instruction *insn)
+{
+ return reg_opr (insn, REG_BIT_Dn);
+}
+
+
+static int
+regs_opr (const struct instruction *insn)
+{
+ return reg_opr (insn, 0x1U << REG_S);
+}
+
+static int
+imm_opr (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+ long imm;
+ if (!lex_imm (&imm))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ int size = size_from_suffix (insn, 0);
+ char *f = s12z_new_insn (1 + n_bytes + size);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+
+ int i;
+ for (i = 0; i < size; ++i)
+ number_to_chars_bigendian (f++, imm >> (CHAR_BIT * (size - i - 1)), 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+opr_opr (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer1[4];
+ int n_bytes1;
+ expressionS exp1;
+ if (!lex_opr (buffer1, &n_bytes1, &exp1))
+ goto fail;
+
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer2[4];
+ int n_bytes2;
+ expressionS exp2;
+ if (!lex_opr (buffer2, &n_bytes2, &exp2))
+ goto fail;
+
+ char *f = s12z_new_insn (1 + n_bytes1 + n_bytes2);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+
+ f = emit_opr (f, buffer1, n_bytes1, &exp1);
+ f = emit_opr (f, buffer2, n_bytes2, &exp2);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+reg67sxy_opr (const struct instruction *insn)
+{
+ int reg;
+ if (!lex_reg_name (REG_BIT_XYS | (0x1U << REG_D6) | (0x1U << REG_D7), &reg))
+ return 0;
+
+ if (!lex_match (','))
+ return 0;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ return 0;
+
+ char *f = s12z_new_insn (1 + n_bytes);
+ number_to_chars_bigendian (f++, insn->opc + reg - REG_D6, 1);
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+}
+
+static int
+rotate (const struct instruction *insn, short dir)
+{
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (lex_opr (buffer, &n_bytes, &exp))
+ {
+ char *f = s12z_new_insn (n_bytes + 2);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ int size = size_from_suffix (insn, 0);
+ if (size < 0)
+ size = 1;
+ uint8_t sb = 0x24;
+ sb |= size - 1;
+ if (dir)
+ sb |= 0x40;
+ number_to_chars_bigendian (f++, sb, 1);
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+rol (const struct instruction *insn)
+{
+ return rotate (insn, 1);
+}
+
+static int
+ror (const struct instruction *insn)
+{
+ return rotate (insn, 0);
+}
+
+
+/* Shift instruction with a register operand and an immediate #1 or #2
+ left = 1; right = 0;
+ logical = 0; arithmetic = 1;
+*/
+static int
+lex_shift_reg_imm1 (const struct instruction *insn, short type, short dir)
+{
+ /*
+ This function is highly unusual and a bit wierd!
+ It first matches the input against a register {d0, d1, ... d7} followed by an immediate
+ {#1, #2}.
+ Then, it rewinds the input and parses it again as a OPR.
+ */
+ char *ilp = input_line_pointer;
+
+ int Dd;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ {
+ goto fail;
+ }
+
+ if (!lex_match (','))
+ goto fail;
+
+ long imm = -1;
+ if (!lex_imm (&imm))
+ goto fail;
+
+ if (imm != 1 && imm != 2)
+ goto fail;
+ input_line_pointer = ilp;
+
+ /* Now parse the first operand again */
+
+ uint8_t buffer[4];
+ int n_bytes;
+
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ gas_assert (n_bytes == 1);
+
+ uint8_t sb = 0x34;
+ sb |= dir << 6;
+ sb |= type << 7;
+ if (imm == 2)
+ sb |= 0x08;
+
+ char *f = s12z_new_insn (3);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, sb, 1);
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+/* Shift instruction with a register operand.
+ left = 1; right = 0;
+ logical = 0; arithmetic = 1; */
+static int
+lex_shift_reg (const struct instruction *insn, short type, short dir)
+{
+ int Dd, Ds, Dn;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ {
+ goto fail;
+ }
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (REG_BIT_Dn, &Ds))
+ {
+ goto fail;
+ }
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t sb = 0x10;
+ sb |= Ds;
+ sb |= dir << 6;
+ sb |= type << 7;
+ long imm;
+ if (lex_reg_name (REG_BIT_Dn, &Dn))
+ {
+ char *f = s12z_new_insn (3);
+ number_to_chars_bigendian (f++, insn->opc | Dd, 1);
+ number_to_chars_bigendian (f++, sb, 1);
+ uint8_t xb = 0xb8;
+ xb |= Dn;
+ number_to_chars_bigendian (f++, xb, 1);
+
+ return 1;
+ }
+ else if (lex_imm (&imm))
+ {
+ if (imm < 0 || imm > 31)
+ {
+ as_bad (_("Shift value should be in the range [0,31]"));
+ goto fail;
+ }
+
+ int n_bytes = 3;
+ if (imm == 1 || imm == 2)
+ {
+ n_bytes = 2;
+ sb &= ~0x10;
+ }
+ else
+ {
+ sb |= (imm & 0x01) << 3;
+ }
+
+ char *f = s12z_new_insn (n_bytes);
+ number_to_chars_bigendian (f++, insn->opc | Dd, 1);
+ number_to_chars_bigendian (f++, sb, 1);
+ if (n_bytes > 2)
+ {
+ uint8_t xb = 0x70;
+ xb |= imm >> 1;
+ number_to_chars_bigendian (f++, xb, 1);
+ }
+
+ return 1;
+ }
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ return 0;
+}
+
+static void
+impute_shift_dir_and_type (const struct instruction *insn, short *type, short *dir)
+{
+ *dir = -1;
+ *type = -1;
+ switch (insn->name[0])
+ {
+ case 'l':
+ *type = 0;
+ break;
+ case 'a':
+ *type = 1;
+ break;
+ default:
+ as_fatal (_("Bad shift mode"));
+ break;
+ }
+
+ switch (insn->name[2])
+ {
+ case 'l':
+ *dir = 1;
+ break;
+ case 'r':
+ *dir = 0;
+ break;
+ default:
+ as_fatal (_("Bad shift *direction"));
+ break;
+ }
+}
+
+/* Shift instruction with a OPR operand */
+static int
+shift_two_operand (const struct instruction *insn)
+{
+ uint8_t sb = 0x34;
+ char *ilp = input_line_pointer;
+
+ short dir = -1;
+ short type = -1;
+ impute_shift_dir_and_type (insn, &type, &dir);
+ sb |= dir << 6;
+ sb |= type << 7;
+
+ int size = size_from_suffix (insn, 0);
+ sb |= size - 1;
+
+ uint8_t buffer[4];
+ int n_opr_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_opr_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long imm = -1;
+ if (!lex_imm (&imm))
+ goto fail;
+
+ if (imm != 1 && imm != 2)
+ goto fail;
+
+ if (imm == 2)
+ sb |= 0x08;
+
+ char *f = s12z_new_insn (2 + n_opr_bytes);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, sb, 1);
+ emit_opr (f, buffer, n_opr_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+/* Shift instruction with a OPR operand */
+static int
+shift_opr_imm (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ short dir = -1;
+ short type = -1;
+ impute_shift_dir_and_type (insn, &type, &dir);
+
+ int Dd = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int n_bytes = 2;
+
+ uint8_t buffer1[4];
+ int n_opr_bytes1;
+
+ expressionS exp1;
+ if (!lex_opr (buffer1, &n_opr_bytes1, &exp1))
+ goto fail;
+
+ n_bytes += n_opr_bytes1;
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer2[4];
+ int n_opr_bytes2 = 0;
+ expressionS exp2;
+ long imm;
+ bool immediate = false;
+ if (lex_imm (&imm))
+ {
+ immediate = true;
+ }
+ else if (!lex_opr (buffer2, &n_opr_bytes2, &exp2))
+ goto fail;
+
+ uint8_t sb = 0x20;
+
+ int size = size_from_suffix (insn, 0);
+
+ if (size != -1)
+ sb |= size - 1;
+
+ sb |= dir << 6;
+ sb |= type << 7;
+
+ if (immediate)
+ {
+ if (imm == 2 || imm == 1)
+ {
+ if (imm == 2)
+ sb |= 0x08;
+ }
+ else
+ {
+ n_bytes++;
+ sb |= 0x10;
+ if (imm % 2)
+ sb |= 0x08;
+ }
+ }
+ else
+ {
+ n_bytes += n_opr_bytes2;
+ sb |= 0x10;
+ }
+
+ char *f = s12z_new_insn (n_bytes);
+ number_to_chars_bigendian (f++, insn->opc | Dd, 1);
+ number_to_chars_bigendian (f++, sb, 1);
+ f = emit_opr (f, buffer1, n_opr_bytes1, &exp1);
+ if (immediate)
+ {
+ if (imm != 1 && imm != 2)
+ {
+ number_to_chars_bigendian (f++, 0x70 | (imm >> 1), 1);
+ }
+ }
+ else
+ {
+ f = emit_opr (f, buffer2, n_opr_bytes2, &exp2);
+ }
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+/* Shift instruction with a register operand */
+static int
+shift_reg (const struct instruction *insn)
+{
+ short dir = -1;
+ short type = -1;
+ impute_shift_dir_and_type (insn, &type, &dir);
+
+ if (lex_shift_reg_imm1 (insn, type, dir))
+ return 1;
+
+ return lex_shift_reg (insn, type, dir);
+}
+
+static int
+bm_regd_imm (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+ int Di = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Di))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long imm;
+ if (!lex_imm (&imm))
+ goto fail;
+
+
+ uint8_t bm = imm << 3;
+ bm |= Di;
+
+ char *f = s12z_new_insn (2);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+bm_opr_reg (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer[4];
+ int n_opr_bytes;
+
+ expressionS exp;
+ if (!lex_opr (buffer, &n_opr_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dn = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dn))
+ goto fail;
+
+ uint8_t bm = Dn << 4;
+ int size = size_from_suffix (insn, 0);
+ bm |= (size - 1) << 2;
+ bm |= 0x81;
+
+ char *f = s12z_new_insn (2 + n_opr_bytes);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+
+ emit_opr (f, buffer, n_opr_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+bm_opr_imm (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer[4];
+ int n_opr_bytes;
+
+ expressionS exp;
+ if (!lex_opr (buffer, &n_opr_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+
+ long imm;
+ if (!lex_imm (&imm))
+ goto fail;
+
+ int size = size_from_suffix (insn, 0);
+
+ if (imm < 0 || imm >= size * 8)
+ {
+ as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm);
+ goto fail;
+ }
+
+ uint8_t bm = 0x80;
+ if (size == 2)
+ bm |= 0x02;
+ else if (size == 4)
+ bm |= 0x08;
+ bm |= (imm & 0x07) << 4;
+ bm |= (imm >> 3);
+
+
+ char *f = s12z_new_insn (2 + n_opr_bytes);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+ emit_opr (f, buffer, n_opr_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+bm_regd_reg (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+ int Di = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Di))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dn = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dn))
+ goto fail;
+
+ uint8_t bm = Dn << 4;
+ bm |= 0x81;
+
+ uint8_t xb = Di | 0xb8;
+
+ char *f = s12z_new_insn (3);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+ number_to_chars_bigendian (f++, xb, 1);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+
+
+
+static int
+bf_reg_opr_imm (const struct instruction *insn, short ie)
+{
+ char *ilp = input_line_pointer;
+ int Dd = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t buffer[4];
+ int n_bytes;
+
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long width;
+ if (!lex_imm (&width))
+ goto fail;
+
+ if (width < 0 || width > 31)
+ {
+ as_bad (_("Invalid width value for %s"), insn->name);
+ goto fail;
+ }
+
+ if (!lex_match (':'))
+ goto fail;
+
+ long offset;
+ if (!lex_constant (&offset))
+ goto fail;
+
+ if (offset < 0 || offset > 31)
+ {
+ as_bad (_("Invalid offset value for %s"), insn->name);
+ goto fail;
+ }
+
+ uint8_t i1 = width << 5;
+ i1 |= offset;
+
+ int size = size_from_suffix (insn, 0);
+ uint8_t bb = ie ? 0x80 : 0x00;
+ bb |= 0x60;
+ bb |= (size - 1) << 2;
+ bb |= width >> 3;
+
+ char *f = s12z_new_insn (4 + n_bytes);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+ number_to_chars_bigendian (f++, bb, 1);
+ number_to_chars_bigendian (f++, i1, 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+bf_opr_reg_imm (const struct instruction *insn, short ie)
+{
+ char *ilp = input_line_pointer;
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Ds = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Ds))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long width;
+ if (!lex_imm (&width))
+ goto fail;
+
+ if (width < 0 || width > 31)
+ {
+ as_bad (_("Invalid width value for %s"), insn->name);
+ goto fail;
+ }
+
+ if (!lex_match (':'))
+ goto fail;
+
+ long offset;
+ if (!lex_constant (&offset))
+ goto fail;
+
+ if (offset < 0 || offset > 31)
+ {
+ as_bad (_("Invalid offset value for %s"), insn->name);
+ goto fail;
+ }
+
+ uint8_t i1 = width << 5;
+ i1 |= offset;
+
+ int size = size_from_suffix (insn, 0);
+ uint8_t bb = ie ? 0x80 : 0x00;
+ bb |= 0x70;
+ bb |= (size - 1) << 2;
+ bb |= width >> 3;
+
+ char *f = s12z_new_insn (4 + n_bytes);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, 0x08 | Ds, 1);
+ number_to_chars_bigendian (f++, bb, 1);
+ number_to_chars_bigendian (f++, i1, 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+
+static int
+bf_reg_reg_imm (const struct instruction *insn, short ie)
+{
+ char *ilp = input_line_pointer;
+ int Dd = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Ds = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Ds))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long width;
+ if (!lex_imm (&width))
+ goto fail;
+
+ if (width < 0 || width > 31)
+ {
+ as_bad (_("Invalid width value for %s"), insn->name);
+ goto fail;
+ }
+
+ if (!lex_match (':'))
+ goto fail;
+
+ long offset;
+ if (!lex_constant (&offset))
+ goto fail;
+
+ if (offset < 0 || offset > 31)
+ {
+ as_bad (_("Invalid offset value for %s"), insn->name);
+ goto fail;
+ }
+
+ uint8_t bb = ie ? 0x80 : 0x00;
+ bb |= 0x20;
+ bb |= Ds << 2;
+ bb |= width >> 3;
+
+ uint8_t i1 = width << 5;
+ i1 |= offset;
+
+ char *f = s12z_new_insn (4);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+ number_to_chars_bigendian (f++, bb, 1);
+ number_to_chars_bigendian (f++, i1, 1);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+bf_reg_reg_reg (const struct instruction *insn ATTRIBUTE_UNUSED, short ie)
+{
+ char *ilp = input_line_pointer;
+ int Dd = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Ds = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Ds))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dp = 0;
+ if (!lex_reg_name ((0x01u << REG_D2) |
+ (0x01u << REG_D3) |
+ (0x01u << REG_D4) |
+ (0x01u << REG_D5),
+ &Dp))
+ goto fail;
+
+ uint8_t bb = ie ? 0x80 : 0x00;
+ bb |= Ds << 2;
+ bb |= Dp;
+
+ char *f = s12z_new_insn (3);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+ number_to_chars_bigendian (f++, bb , 1);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+bf_opr_reg_reg (const struct instruction *insn, short ie)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+
+ int Ds = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Ds))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+
+ int Dp = 0;
+ if (!lex_reg_name ((0x01u << REG_D2) |
+ (0x01u << REG_D3) |
+ (0x01u << REG_D4) |
+ (0x01u << REG_D5),
+ &Dp))
+ goto fail;
+
+ int size = size_from_suffix (insn, 0);
+ uint8_t bb = ie ? 0x80 : 0x00;
+ bb |= 0x50;
+ bb |= Dp;
+ bb |= (size - 1) << 2;
+
+ char *f = s12z_new_insn (3 + n_bytes);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, 0x08 | Ds, 1);
+ number_to_chars_bigendian (f++, bb , 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+bf_reg_opr_reg (const struct instruction *insn, short ie)
+{
+ char *ilp = input_line_pointer;
+ int Dd = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dd))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dp = 0;
+ if (!lex_reg_name ((0x01u << REG_D2) |
+ (0x01u << REG_D3) |
+ (0x01u << REG_D4) |
+ (0x01u << REG_D5),
+ &Dp))
+ goto fail;
+
+ int size = size_from_suffix (insn, 0);
+ uint8_t bb = ie ? 0x80 : 0x00;
+ bb |= 0x40;
+ bb |= Dp;
+ bb |= (size - 1) << 2;
+
+ char *f = s12z_new_insn (3 + n_bytes);
+ number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
+ number_to_chars_bigendian (f++, 0x08 | Dd, 1);
+ number_to_chars_bigendian (f++, bb , 1);
+
+ emit_opr (f, buffer, n_bytes, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+
+static int
+bfe_reg_reg_reg (const struct instruction *insn)
+{
+ return bf_reg_reg_reg (insn, 0);
+}
+
+static int
+bfi_reg_reg_reg (const struct instruction *insn)
+{
+ return bf_reg_reg_reg (insn, 1);
+}
+
+static int
+bfe_reg_reg_imm (const struct instruction *insn)
+{
+ return bf_reg_reg_imm (insn, 0);
+}
+
+static int
+bfi_reg_reg_imm (const struct instruction *insn)
+{
+ return bf_reg_reg_imm (insn, 1);
+}
+
+
+static int
+bfe_reg_opr_reg (const struct instruction *insn)
+{
+ return bf_reg_opr_reg (insn, 0);
+}
+
+static int
+bfi_reg_opr_reg (const struct instruction *insn)
+{
+ return bf_reg_opr_reg (insn, 1);
+}
+
+
+static int
+bfe_opr_reg_reg (const struct instruction *insn)
+{
+ return bf_opr_reg_reg (insn, 0);
+}
+
+static int
+bfi_opr_reg_reg (const struct instruction *insn)
+{
+ return bf_opr_reg_reg (insn, 1);
+}
+
+static int
+bfe_reg_opr_imm (const struct instruction *insn)
+{
+ return bf_reg_opr_imm (insn, 0);
+}
+
+static int
+bfi_reg_opr_imm (const struct instruction *insn)
+{
+ return bf_reg_opr_imm (insn, 1);
+}
+
+static int
+bfe_opr_reg_imm (const struct instruction *insn)
+{
+ return bf_opr_reg_imm (insn, 0);
+}
+
+static int
+bfi_opr_reg_imm (const struct instruction *insn)
+{
+ return bf_opr_reg_imm (insn, 1);
+}
+
+
+
+
+static int
+tb_reg_rel (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int reg;
+ if (!lex_reg_name (REG_BIT_Dn | REG_BIT_XY, &reg))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ bool long_displacement;
+ expressionS exp;
+ if (! lex_15_bit_offset (&long_displacement, &exp))
+ goto fail;
+
+ uint8_t lb = 0x00;
+ if (reg == REG_X || reg == REG_Y)
+ {
+ lb |= 0x08;
+ }
+ else
+ {
+ lb |= reg;
+ }
+ if (reg == REG_Y)
+ lb |= 0x01;
+
+ if (0 == strncmp (insn->name + 2, "ne", 2))
+ lb |= 0x00 << 4;
+ else if (0 == strncmp (insn->name + 2, "eq", 2))
+ lb |= 0x01 << 4;
+ else if (0 == strncmp (insn->name + 2, "pl", 2))
+ lb |= 0x02 << 4;
+ else if (0 == strncmp (insn->name + 2, "mi", 2))
+ lb |= 0x03 << 4;
+ else if (0 == strncmp (insn->name + 2, "gt", 2))
+ lb |= 0x04 << 4;
+ else if (0 == strncmp (insn->name + 2, "le", 2))
+ lb |= 0x05 << 4;
+
+ switch (insn->name[0])
+ {
+ case 'd':
+ lb |= 0x80;
+ break;
+ case 't':
+ break;
+ default:
+ gas_assert (0);
+ break;
+ };
+
+ char *f = s12z_new_insn (long_displacement ? 4 : 3);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, lb, 1);
+
+ emit_15_bit_offset (f, 4, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+tb_opr_rel (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ bool long_displacement;
+ expressionS exp2;
+ if (! lex_15_bit_offset (&long_displacement, &exp2))
+ goto fail;
+
+ uint8_t lb = 0x0C;
+
+ if (0 == strncmp (insn->name + 2, "ne", 2))
+ lb |= 0x00 << 4;
+ else if (0 == strncmp (insn->name + 2, "eq", 2))
+ lb |= 0x01 << 4;
+ else if (0 == strncmp (insn->name + 2, "pl", 2))
+ lb |= 0x02 << 4;
+ else if (0 == strncmp (insn->name + 2, "mi", 2))
+ lb |= 0x03 << 4;
+ else if (0 == strncmp (insn->name + 2, "gt", 2))
+ lb |= 0x04 << 4;
+ else if (0 == strncmp (insn->name + 2, "le", 2))
+ lb |= 0x05 << 4;
+
+ switch (insn->name[0])
+ {
+ case 'd':
+ lb |= 0x80;
+ break;
+ case 't':
+ break;
+ default:
+ gas_assert (0);
+ break;
+ };
+
+ int size = size_from_suffix (insn, 0);
+
+ lb |= size -1;
+
+ char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, lb, 1);
+ f = emit_opr (f, buffer, n_bytes, &exp);
+
+ emit_15_bit_offset (f, n_bytes + 4, &exp2);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+
+
+static int
+test_br_reg_reg_rel (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int Di = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Di))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+
+ int Dn = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dn))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+
+ bool long_displacement;
+ expressionS exp;
+ if (! lex_15_bit_offset (&long_displacement, &exp))
+ goto fail;
+
+ uint8_t bm = 0x81;
+ uint8_t xb = 0xb8;
+
+ bm |= Dn << 4;
+ xb |= Di;
+
+ char *f = s12z_new_insn (long_displacement ? 5 : 4);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+ number_to_chars_bigendian (f++, xb, 1);
+
+ emit_15_bit_offset (f, 5, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+static int
+test_br_opr_reg_rel (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int Dn = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Dn))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ uint8_t bm = 0x81;
+ bm |= Dn << 4;
+ int size = size_from_suffix (insn, 0);
+ bm |= (size -1) << 2;
+
+ bool long_displacement;
+
+ expressionS exp2;
+ if (! lex_15_bit_offset (&long_displacement, &exp2))
+ goto fail;
+
+ int n = n_bytes + (long_displacement ? 4 : 3);
+ char *f = s12z_new_insn (n);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+ f = emit_opr (f, buffer, n_bytes, &exp);
+
+ emit_15_bit_offset (f, n, &exp2);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+test_br_opr_imm_rel (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ uint8_t buffer[4];
+ int n_bytes;
+ expressionS exp;
+ if (!lex_opr (buffer, &n_bytes, &exp))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long imm;
+ if (!lex_imm (&imm))
+ goto fail;
+
+ if (imm < 0 || imm > 31)
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ bool long_displacement;
+ expressionS exp2;
+ if (! lex_15_bit_offset (&long_displacement, &exp2))
+ goto fail;
+
+ int size = size_from_suffix (insn, 0);
+
+ uint8_t bm = 0x80;
+ bm |= (imm & 0x07) << 4;
+ bm |= (imm >> 3) & 0x03;
+ if (size == 4)
+ bm |= 0x08;
+ else if (size == 2)
+ bm |= 0x02;
+
+ char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+ f = emit_opr (f, buffer, n_bytes, &exp);
+
+ emit_15_bit_offset (f, n_bytes + 4, &exp2);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+static int
+test_br_reg_imm_rel (const struct instruction *insn)
+{
+ char *ilp = input_line_pointer;
+
+ int Di = 0;
+ if (!lex_reg_name (REG_BIT_Dn, &Di))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ long imm;
+ if (!lex_imm (&imm))
+ goto fail;
+
+ if (imm < 0 || imm > 31)
+ goto fail;
+
+
+ if (!lex_match (','))
+ goto fail;
+
+ bool long_displacement;
+ expressionS exp;
+ if (! lex_15_bit_offset (&long_displacement, &exp))
+ goto fail;
+
+ uint8_t bm = Di;
+ bm |= imm << 3;
+
+ char *f = s12z_new_insn (long_displacement ? 4 : 3);
+ number_to_chars_bigendian (f++, insn->opc, 1);
+ number_to_chars_bigendian (f++, bm, 1);
+
+ emit_15_bit_offset (f, 4, &exp);
+
+ return 1;
+
+ fail:
+ fail_line_pointer = input_line_pointer;
+ input_line_pointer = ilp;
+ return 0;
+}
+
+
+
+
+static const struct instruction opcodes[] = {
+ {"bgnd", 1, 0x00, no_operands, 0},
+ {"nop", 1, 0x01, no_operands, 0},
+
+ {"brclr", 1, 0x02, test_br_reg_reg_rel, 0},
+ {"brset", 1, 0x03, test_br_reg_reg_rel, 0},
+
+ {"brclr", 1, 0x02, test_br_reg_imm_rel, 0},
+ {"brset", 1, 0x03, test_br_reg_imm_rel, 0},
+
+ {"brclr.b", 1, 0x02, test_br_opr_reg_rel, 0},
+ {"brclr.w", 1, 0x02, test_br_opr_reg_rel, 0},
+ {"brclr.l", 1, 0x02, test_br_opr_reg_rel, 0},
+
+ {"brset.b", 1, 0x03, test_br_opr_reg_rel, 0},
+ {"brset.w", 1, 0x03, test_br_opr_reg_rel, 0},
+ {"brset.l", 1, 0x03, test_br_opr_reg_rel, 0},
+
+ {"brclr.b", 1, 0x02, test_br_opr_imm_rel, 0},
+ {"brclr.w", 1, 0x02, test_br_opr_imm_rel, 0},
+ {"brclr.l", 1, 0x02, test_br_opr_imm_rel, 0},
+
+ {"brset.b", 1, 0x03, test_br_opr_imm_rel, 0},
+ {"brset.w", 1, 0x03, test_br_opr_imm_rel, 0},
+ {"brset.l", 1, 0x03, test_br_opr_imm_rel, 0},
+
+ {"psh", 1, 0x04, psh_pull, 0},
+ {"pul", 1, 0x04, psh_pull, 0},
+
+ {"rts", 1, 0x05, no_operands, 0},
+ {"lea", 1, 0x06, reg67sxy_opr, 0},
+
+ {"dbne", 1, 0x0b, tb_reg_rel, 0},
+ {"dbeq", 1, 0x0b, tb_reg_rel, 0},
+ {"dbpl", 1, 0x0b, tb_reg_rel, 0},
+ {"dbmi", 1, 0x0b, tb_reg_rel, 0},
+ {"dbgt", 1, 0x0b, tb_reg_rel, 0},
+ {"dble", 1, 0x0b, tb_reg_rel, 0},
+
+ {"dbne.b", 1, 0x0b, tb_opr_rel, 0},
+ {"dbeq.b", 1, 0x0b, tb_opr_rel, 0},
+ {"dbpl.b", 1, 0x0b, tb_opr_rel, 0},
+ {"dbmi.b", 1, 0x0b, tb_opr_rel, 0},
+ {"dbgt.b", 1, 0x0b, tb_opr_rel, 0},
+ {"dble.b", 1, 0x0b, tb_opr_rel, 0},
+
+ {"dbne.w", 1, 0x0b, tb_opr_rel, 0},
+ {"dbeq.w", 1, 0x0b, tb_opr_rel, 0},
+ {"dbpl.w", 1, 0x0b, tb_opr_rel, 0},
+ {"dbmi.w", 1, 0x0b, tb_opr_rel, 0},
+ {"dbgt.w", 1, 0x0b, tb_opr_rel, 0},
+ {"dble.w", 1, 0x0b, tb_opr_rel, 0},
+
+ {"dbne.p", 1, 0x0b, tb_opr_rel, 0},
+ {"dbeq.p", 1, 0x0b, tb_opr_rel, 0},
+ {"dbpl.p", 1, 0x0b, tb_opr_rel, 0},
+ {"dbmi.p", 1, 0x0b, tb_opr_rel, 0},
+ {"dbgt.p", 1, 0x0b, tb_opr_rel, 0},
+ {"dble.p", 1, 0x0b, tb_opr_rel, 0},
+
+ {"dbne.l", 1, 0x0b, tb_opr_rel, 0},
+ {"dbeq.l", 1, 0x0b, tb_opr_rel, 0},
+ {"dbpl.l", 1, 0x0b, tb_opr_rel, 0},
+ {"dbmi.l", 1, 0x0b, tb_opr_rel, 0},
+ {"dbgt.l", 1, 0x0b, tb_opr_rel, 0},
+ {"dble.l", 1, 0x0b, tb_opr_rel, 0},
+
+ {"tbne", 1, 0x0b, tb_reg_rel, 0},
+ {"tbeq", 1, 0x0b, tb_reg_rel, 0},
+ {"tbpl", 1, 0x0b, tb_reg_rel, 0},
+ {"tbmi", 1, 0x0b, tb_reg_rel, 0},
+ {"tbgt", 1, 0x0b, tb_reg_rel, 0},
+ {"tble", 1, 0x0b, tb_reg_rel, 0},
+
+ {"tbne.b", 1, 0x0b, tb_opr_rel, 0},
+ {"tbeq.b", 1, 0x0b, tb_opr_rel, 0},
+ {"tbpl.b", 1, 0x0b, tb_opr_rel, 0},
+ {"tbmi.b", 1, 0x0b, tb_opr_rel, 0},
+ {"tbgt.b", 1, 0x0b, tb_opr_rel, 0},
+ {"tble.b", 1, 0x0b, tb_opr_rel, 0},
+
+ {"tbne.w", 1, 0x0b, tb_opr_rel, 0},
+ {"tbeq.w", 1, 0x0b, tb_opr_rel, 0},
+ {"tbpl.w", 1, 0x0b, tb_opr_rel, 0},
+ {"tbmi.w", 1, 0x0b, tb_opr_rel, 0},
+ {"tbgt.w", 1, 0x0b, tb_opr_rel, 0},
+ {"tble.w", 1, 0x0b, tb_opr_rel, 0},
+
+ {"tbne.p", 1, 0x0b, tb_opr_rel, 0},
+ {"tbeq.p", 1, 0x0b, tb_opr_rel, 0},
+ {"tbpl.p", 1, 0x0b, tb_opr_rel, 0},
+ {"tbmi.p", 1, 0x0b, tb_opr_rel, 0},
+ {"tbgt.p", 1, 0x0b, tb_opr_rel, 0},
+ {"tble.p", 1, 0x0b, tb_opr_rel, 0},
+
+ {"tbne.l", 1, 0x0b, tb_opr_rel, 0},
+ {"tbeq.l", 1, 0x0b, tb_opr_rel, 0},
+ {"tbpl.l", 1, 0x0b, tb_opr_rel, 0},
+ {"tbmi.l", 1, 0x0b, tb_opr_rel, 0},
+ {"tbgt.l", 1, 0x0b, tb_opr_rel, 0},
+ {"tble.l", 1, 0x0b, tb_opr_rel, 0},
+
+ {"mov.b", 1, 0x0c, imm_opr, 0},
+ {"mov.w", 1, 0x0d, imm_opr, 0},
+ {"mov.p", 1, 0x0e, imm_opr, 0},
+ {"mov.l", 1, 0x0f, imm_opr, 0},
+
+ {"rol", 1, 0x10, rol, 0},
+ {"rol.b", 1, 0x10, rol, 0},
+ {"rol.w", 1, 0x10, rol, 0},
+ {"rol.p", 1, 0x10, rol, 0},
+ {"rol.l", 1, 0x10, rol, 0},
+
+ {"ror", 1, 0x10, ror, 0},
+ {"ror.b", 1, 0x10, ror, 0},
+ {"ror.w", 1, 0x10, ror, 0},
+ {"ror.p", 1, 0x10, ror, 0},
+ {"ror.l", 1, 0x10, ror, 0},
+
+ {"lsl", 1, 0x10, shift_reg, 0},
+ {"lsr", 1, 0x10, shift_reg, 0},
+ {"asl", 1, 0x10, shift_reg, 0},
+ {"asr", 1, 0x10, shift_reg, 0},
+
+ {"lsl.b", 1, 0x10, shift_two_operand, 0},
+ {"lsl.w", 1, 0x10, shift_two_operand, 0},
+ {"lsl.p", 1, 0x10, shift_two_operand, 0},
+ {"lsl.l", 1, 0x10, shift_two_operand, 0},
+ {"asl.b", 1, 0x10, shift_two_operand, 0},
+ {"asl.w", 1, 0x10, shift_two_operand, 0},
+ {"asl.p", 1, 0x10, shift_two_operand, 0},
+ {"asl.l", 1, 0x10, shift_two_operand, 0},
+
+ {"lsr.b", 1, 0x10, shift_two_operand, 0},
+ {"lsr.w", 1, 0x10, shift_two_operand, 0},
+ {"lsr.p", 1, 0x10, shift_two_operand, 0},
+ {"lsr.l", 1, 0x10, shift_two_operand, 0},
+ {"asr.b", 1, 0x10, shift_two_operand, 0},
+ {"asr.w", 1, 0x10, shift_two_operand, 0},
+ {"asr.p", 1, 0x10, shift_two_operand, 0},
+ {"asr.l", 1, 0x10, shift_two_operand, 0},
+
+ {"lsl.b", 1, 0x10, shift_opr_imm, 0},
+ {"lsl.w", 1, 0x10, shift_opr_imm, 0},
+ {"lsl.p", 1, 0x10, shift_opr_imm, 0},
+ {"lsl.l", 1, 0x10, shift_opr_imm, 0},
+ {"asl.b", 1, 0x10, shift_opr_imm, 0},
+ {"asl.w", 1, 0x10, shift_opr_imm, 0},
+ {"asl.p", 1, 0x10, shift_opr_imm, 0},
+ {"asl.l", 1, 0x10, shift_opr_imm, 0},
+
+ {"lsr.b", 1, 0x10, shift_opr_imm, 0},
+ {"lsr.w", 1, 0x10, shift_opr_imm, 0},
+ {"lsr.p", 1, 0x10, shift_opr_imm, 0},
+ {"lsr.l", 1, 0x10, shift_opr_imm, 0},
+ {"asr.b", 1, 0x10, shift_opr_imm, 0},
+ {"asr.w", 1, 0x10, shift_opr_imm, 0},
+ {"asr.p", 1, 0x10, shift_opr_imm, 0},
+ {"asr.l", 1, 0x10, shift_opr_imm, 0},
+
+ {"mov.b", 1, 0x1c, opr_opr, 0},
+ {"mov.w", 1, 0x1d, opr_opr, 0},
+ {"mov.p", 1, 0x1e, opr_opr, 0},
+ {"mov.l", 1, 0x1f, opr_opr, 0},
+
+ {"bra", 1, 0x20, rel, 0},
+ {"bsr", 1, 0x21, rel, 0},
+ {"bhi", 1, 0x22, rel, 0},
+ {"bls", 1, 0x23, rel, 0},
+ {"bcc", 1, 0x24, rel, 0},
+ {"bcs", 1, 0x25, rel, 0},
+ {"bne", 1, 0x26, rel, 0},
+ {"beq", 1, 0x27, rel, 0},
+ {"bvc", 1, 0x28, rel, 0},
+ {"bvs", 1, 0x29, rel, 0},
+ {"bpl", 1, 0x2a, rel, 0},
+ {"bmi", 1, 0x2b, rel, 0},
+ {"bge", 1, 0x2c, rel, 0},
+ {"blt", 1, 0x2d, rel, 0},
+ {"bgt", 1, 0x2e, rel, 0},
+ {"ble", 1, 0x2f, rel, 0},
+
+ {"inc", 1, 0x30, reg_inh, 0},
+ {"clr", 1, 0x38, reg_inh, 0},
+ {"dec", 1, 0x40, reg_inh, 0},
+
+ {"muls", 1, 0x48, mul_reg_reg_reg, 0},
+ {"mulu", 1, 0x48, mul_reg_reg_reg, 0},
+
+ {"muls.b", 1, 0x48, mul_reg_reg_opr, 0},
+ {"muls.w", 1, 0x48, mul_reg_reg_opr, 0},
+ {"muls.l", 1, 0x48, mul_reg_reg_opr, 0},
+
+ {"mulu.b", 1, 0x48, mul_reg_reg_opr, 0},
+ {"mulu.w", 1, 0x48, mul_reg_reg_opr, 0},
+ {"mulu.l", 1, 0x48, mul_reg_reg_opr, 0},
+
+ {"muls.b", 1, 0x48, mul_reg_reg_imm, 0},
+ {"muls.w", 1, 0x48, mul_reg_reg_imm, 0},
+ {"muls.l", 1, 0x48, mul_reg_reg_imm, 0},
+
+ {"mulu.b", 1, 0x48, mul_reg_reg_imm, 0},
+ {"mulu.w", 1, 0x48, mul_reg_reg_imm, 0},
+ {"mulu.l", 1, 0x48, mul_reg_reg_imm, 0},
+
+ {"muls.bb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.bw", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.bp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.bl", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"muls.wb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.ww", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.wp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.wl", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"muls.pb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.pw", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.pp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.pl", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"muls.lb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.lw", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.lp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"muls.ll", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"mulu.bb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.bw", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.bp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.bl", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"mulu.wb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.ww", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.wp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.wl", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"mulu.pb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.pw", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.pp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.pl", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"mulu.lb", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.lw", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.lp", 1, 0x48, mul_reg_opr_opr, 0},
+ {"mulu.ll", 1, 0x48, mul_reg_opr_opr, 0},
+
+ {"add", 1, 0x50, regd_imm, 0},
+ {"and", 1, 0x58, regd_imm, 0},
+
+ {"add", 1, 0x60, regd_opr, 0},
+ {"and", 1, 0x68, regd_opr, 0},
+
+ {"sub", 1, 0x70, regd_imm, 0},
+ {"or", 1, 0x78, regd_imm, 0},
+
+ {"sub", 1, 0x80, regd_opr, 0},
+ {"or", 1, 0x88, regd_opr, 0},
+
+ {"ld", 1, 0x90, regdxy_imm, 0},
+
+ {"clr", 1, 0x9a, clr_xy, 0},
+ {"tfr", 1, 0x9e, tfr, 0},
+ {"zex", 1, 0x9e, tfr, 0},
+
+ {"ld", 1, 0xa0, regdxy_opr, 0xb0},
+
+ {"jmp", 1, 0xaa, opr, 0xba},
+ {"jsr", 1, 0xab, opr, 0xbb},
+
+ {"exg", 1, 0xae, tfr, 0},
+ {"sex", 1, 0xae, tfr, 0},
+
+ {"st", 1, 0xc0, regdxy_opr, 0xd0},
+
+ {"andcc", 1, 0xce, imm8, 0},
+ {"orcc", 1, 0xde, imm8, 0},
+
+ {"inc.b", 1, 0x9c, opr, 0},
+ {"inc.w", 1, 0x9d, opr, 0},
+ {"inc.l", 1, 0x9f, opr, 0},
+
+ {"dec.b", 1, 0xac, opr, 0},
+ {"dec.w", 1, 0xad, opr, 0},
+ {"dec.l", 1, 0xaf, opr, 0},
+
+ {"clr.b", 1, 0xbc, opr, 0},
+ {"clr.w", 1, 0xbd, opr, 0},
+ {"clr.p", 1, 0xbe, opr, 0},
+ {"clr.l", 1, 0xbf, opr, 0},
+
+ {"com.b", 1, 0xcc, opr, 0},
+ {"com.w", 1, 0xcd, opr, 0},
+ {"com.l", 1, 0xcf, opr, 0},
+
+ {"neg.b", 1, 0xdc, opr, 0},
+ {"neg.w", 1, 0xdd, opr, 0},
+ {"neg.l", 1, 0xdf, opr, 0},
+
+ {"bclr", 1, 0xec, bm_regd_imm, 0},
+ {"bset", 1, 0xed, bm_regd_imm, 0},
+ {"btgl", 1, 0xee, bm_regd_imm, 0},
+
+ {"bclr", 1, 0xec, bm_regd_reg, 0},
+ {"bset", 1, 0xed, bm_regd_reg, 0},
+ {"btgl", 1, 0xee, bm_regd_reg, 0},
+
+ {"bclr.b", 1, 0xec, bm_opr_imm, 0},
+ {"bclr.w", 1, 0xec, bm_opr_imm, 0},
+ {"bclr.l", 1, 0xec, bm_opr_imm, 0},
+
+ {"bset.b", 1, 0xed, bm_opr_imm, 0},
+ {"bset.w", 1, 0xed, bm_opr_imm, 0},
+ {"bset.l", 1, 0xed, bm_opr_imm, 0},
+
+ {"btgl.b", 1, 0xee, bm_opr_imm, 0},
+ {"btgl.w", 1, 0xee, bm_opr_imm, 0},
+ {"btgl.l", 1, 0xee, bm_opr_imm, 0},
+
+ {"bclr.b", 1, 0xec, bm_opr_reg, 0},
+ {"bclr.w", 1, 0xec, bm_opr_reg, 0},
+ {"bclr.l", 1, 0xec, bm_opr_reg, 0},
+
+ {"bset.b", 1, 0xed, bm_opr_reg, 0},
+ {"bset.w", 1, 0xed, bm_opr_reg, 0},
+ {"bset.l", 1, 0xed, bm_opr_reg, 0},
+
+ {"btgl.b", 1, 0xee, bm_opr_reg, 0},
+ {"btgl.w", 1, 0xee, bm_opr_reg, 0},
+ {"btgl.l", 1, 0xee, bm_opr_reg, 0},
+
+ {"cmp", 1, 0xe0, regdxy_imm, 0},
+ {"cmp", 1, 0xf0, regdxy_opr, 0},
+
+ {"cmp", 1, 0xfc, regx_regy, 0},
+ {"sub", 1, 0xfd, regd6_regx_regy, 0},
+ {"sub", 1, 0xfe, regd6_regy_regx, 0},
+
+ {"swi", 1, 0xff, no_operands, 0},
+
+ /* Page 2 */
+
+ /* The -10 below is a kludge. The opcode is in fact 0x00 */
+ {"ld", 2, -10, regs_opr, 0},
+
+ /* The -9 below is a kludge. The opcode is in fact 0x01 */
+ {"st", 2, -9, regs_opr, 0},
+
+ /* The -8 below is a kludge. The opcode is in fact 0x02 */
+ {"cmp", 2, -8, regs_opr, 0},
+
+ /* The -7 below is a kludge. The opcode is in fact 0x03 */
+ {"ld", 2, -7, regs_imm, 0},
+
+ /* The -6 below is a kludge. The opcode is in fact 0x04 */
+ {"cmp", 2, -6, regs_imm, 0},
+
+ {"bfext", 2, 0x08, bfe_reg_reg_reg, 0},
+ {"bfext", 2, 0x08, bfe_reg_reg_imm, 0},
+ {"bfext.b", 2, 0x08, bfe_reg_opr_reg, 0},
+ {"bfext.w", 2, 0x08, bfe_reg_opr_reg, 0},
+ {"bfext.p", 2, 0x08, bfe_reg_opr_reg, 0},
+ {"bfext.l", 2, 0x08, bfe_reg_opr_reg, 0},
+ {"bfext.b", 2, 0x08, bfe_opr_reg_reg, 0},
+ {"bfext.w", 2, 0x08, bfe_opr_reg_reg, 0},
+ {"bfext.p", 2, 0x08, bfe_opr_reg_reg, 0},
+ {"bfext.l", 2, 0x08, bfe_opr_reg_reg, 0},
+ {"bfext.b", 2, 0x08, bfe_reg_opr_imm, 0},
+ {"bfext.w", 2, 0x08, bfe_reg_opr_imm, 0},
+ {"bfext.p", 2, 0x08, bfe_reg_opr_imm, 0},
+ {"bfext.l", 2, 0x08, bfe_reg_opr_imm, 0},
+ {"bfext.b", 2, 0x08, bfe_opr_reg_imm, 0},
+ {"bfext.w", 2, 0x08, bfe_opr_reg_imm, 0},
+ {"bfext.p", 2, 0x08, bfe_opr_reg_imm, 0},
+ {"bfext.l", 2, 0x08, bfe_opr_reg_imm, 0},
+
+
+ {"bfins", 2, 0x08, bfi_reg_reg_reg, 0},
+ {"bfins", 2, 0x08, bfi_reg_reg_imm, 0},
+ {"bfins.b", 2, 0x08, bfi_reg_opr_reg, 0},
+ {"bfins.w", 2, 0x08, bfi_reg_opr_reg, 0},
+ {"bfins.p", 2, 0x08, bfi_reg_opr_reg, 0},
+ {"bfins.l", 2, 0x08, bfi_reg_opr_reg, 0},
+ {"bfins.b", 2, 0x08, bfi_opr_reg_reg, 0},
+ {"bfins.w", 2, 0x08, bfi_opr_reg_reg, 0},
+ {"bfins.p", 2, 0x08, bfi_opr_reg_reg, 0},
+ {"bfins.l", 2, 0x08, bfi_opr_reg_reg, 0},
+ {"bfins.b", 2, 0x08, bfi_reg_opr_imm, 0},
+ {"bfins.w", 2, 0x08, bfi_reg_opr_imm, 0},
+ {"bfins.p", 2, 0x08, bfi_reg_opr_imm, 0},
+ {"bfins.l", 2, 0x08, bfi_reg_opr_imm, 0},
+ {"bfins.b", 2, 0x08, bfi_opr_reg_imm, 0},
+ {"bfins.w", 2, 0x08, bfi_opr_reg_imm, 0},
+ {"bfins.p", 2, 0x08, bfi_opr_reg_imm, 0},
+ {"bfins.l", 2, 0x08, bfi_opr_reg_imm, 0},
+
+
+ {"minu", 2, 0x10, regd_opr, 0},
+ {"maxu", 2, 0x18, regd_opr, 0},
+ {"mins", 2, 0x20, regd_opr, 0},
+ {"maxs", 2, 0x28, regd_opr, 0},
+
+ {"clb", 2, 0x91, tfr, 0},
+
+ {"trap", 2, 0x00, trap_imm, 0},
+ {"abs", 2, 0x40, reg_inh, 0},
+ {"sat", 2, 0xa0, reg_inh, 0},
+
+ {"rti", 2, 0x90, no_operands, 0},
+ {"stop", 2, 0x05, no_operands, 0},
+ {"wai", 2, 0x06, no_operands, 0},
+ {"sys", 2, 0x07, no_operands, 0},
+
+ {"bit", 2, 0x58, regd_imm, 0},
+ {"bit", 2, 0x68, regd_opr, 0},
+
+ {"adc", 2, 0x50, regd_imm, 0},
+ {"adc", 2, 0x60, regd_opr, 0},
+
+ {"sbc", 2, 0x70, regd_imm, 0},
+ {"eor", 2, 0x78, regd_imm, 0},
+
+ {"sbc", 2, 0x80, regd_opr, 0},
+ {"eor", 2, 0x88, regd_opr, 0},
+
+ {"divs", 2, 0x30, mul_reg_reg_reg, 0},
+ {"divu", 2, 0x30, mul_reg_reg_reg, 0},
+
+ {"divs.b", 2, 0x30, mul_reg_reg_opr, 0},
+ {"divs.w", 2, 0x30, mul_reg_reg_opr, 0},
+ {"divs.l", 2, 0x30, mul_reg_reg_opr, 0},
+
+ {"divu.b", 2, 0x30, mul_reg_reg_opr, 0},
+ {"divu.w", 2, 0x30, mul_reg_reg_opr, 0},
+ {"divu.l", 2, 0x30, mul_reg_reg_opr, 0},
+
+ {"divs.b", 2, 0x30, mul_reg_reg_imm, 0},
+ {"divs.w", 2, 0x30, mul_reg_reg_imm, 0},
+ {"divs.l", 2, 0x30, mul_reg_reg_imm, 0},
+
+ {"divu.b", 2, 0x30, mul_reg_reg_imm, 0},
+ {"divu.w", 2, 0x30, mul_reg_reg_imm, 0},
+ {"divu.l", 2, 0x30, mul_reg_reg_imm, 0},
+
+ {"divs.bb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.bw", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.bp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.bl", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divs.wb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.ww", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.wp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.wl", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divs.pb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.pw", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.pp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.pl", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divs.lb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.lw", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.lp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divs.ll", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divu.bb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.bw", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.bp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.bl", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divu.wb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.ww", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.wp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.wl", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divu.pb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.pw", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.pp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.pl", 2, 0x30, mul_reg_opr_opr, 0},
+
+ {"divu.lb", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.lw", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.lp", 2, 0x30, mul_reg_opr_opr, 0},
+ {"divu.ll", 2, 0x30, mul_reg_opr_opr, 0},
+
+ //
+
+ {"qmuls", 2, 0xb0, mul_reg_reg_reg, 0},
+ {"qmulu", 2, 0xb0, mul_reg_reg_reg, 0},
+
+ {"qmuls.b", 2, 0xb0, mul_reg_reg_opr, 0},
+ {"qmuls.w", 2, 0xb0, mul_reg_reg_opr, 0},
+ {"qmuls.l", 2, 0xb0, mul_reg_reg_opr, 0},
+
+ {"qmulu.b", 2, 0xb0, mul_reg_reg_opr, 0},
+ {"qmulu.w", 2, 0xb0, mul_reg_reg_opr, 0},
+ {"qmulu.l", 2, 0xb0, mul_reg_reg_opr, 0},
+
+ {"qmuls.b", 2, 0xb0, mul_reg_reg_imm, 0},
+ {"qmuls.w", 2, 0xb0, mul_reg_reg_imm, 0},
+ {"qmuls.l", 2, 0xb0, mul_reg_reg_imm, 0},
+
+ {"qmulu.b", 2, 0xb0, mul_reg_reg_imm, 0},
+ {"qmulu.w", 2, 0xb0, mul_reg_reg_imm, 0},
+ {"qmulu.l", 2, 0xb0, mul_reg_reg_imm, 0},
+
+ {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr, 0},
+
+ {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr, 0},
+ {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr, 0},
+
+
+ //
+
+ {"macs", 2, 0x48, mul_reg_reg_reg, 0},
+ {"macu", 2, 0x48, mul_reg_reg_reg, 0},
+
+ {"macs.b", 2, 0x48, mul_reg_reg_opr, 0},
+ {"macs.w", 2, 0x48, mul_reg_reg_opr, 0},
+ {"macs.l", 2, 0x48, mul_reg_reg_opr, 0},
+
+ {"macu.b", 2, 0x48, mul_reg_reg_opr, 0},
+ {"macu.w", 2, 0x48, mul_reg_reg_opr, 0},
+ {"macu.l", 2, 0x48, mul_reg_reg_opr, 0},
+
+ {"macs.b", 2, 0x48, mul_reg_reg_imm, 0},
+ {"macs.w", 2, 0x48, mul_reg_reg_imm, 0},
+ {"macs.l", 2, 0x48, mul_reg_reg_imm, 0},
+
+ {"macu.b", 2, 0x48, mul_reg_reg_imm, 0},
+ {"macu.w", 2, 0x48, mul_reg_reg_imm, 0},
+ {"macu.l", 2, 0x48, mul_reg_reg_imm, 0},
+
+ {"macs.bb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.bw", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.bp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.bl", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macs.wb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.ww", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.wp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.wl", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macs.pb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.pw", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.pp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.pl", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macs.lb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.lw", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.lp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macs.ll", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macu.bb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.bw", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.bp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.bl", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macu.wb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.ww", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.wp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.wl", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macu.pb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.pw", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.pp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.pl", 2, 0x48, mul_reg_opr_opr, 0},
+
+ {"macu.lb", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.lw", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.lp", 2, 0x48, mul_reg_opr_opr, 0},
+ {"macu.ll", 2, 0x48, mul_reg_opr_opr, 0},
+
+
+ //
+
+ {"mods", 2, 0x38, mul_reg_reg_reg, 0},
+ {"modu", 2, 0x38, mul_reg_reg_reg, 0},
+
+ {"mods.b", 2, 0x38, mul_reg_reg_opr, 0},
+ {"mods.w", 2, 0x38, mul_reg_reg_opr, 0},
+ {"mods.l", 2, 0x38, mul_reg_reg_opr, 0},
+
+ {"modu.b", 2, 0x38, mul_reg_reg_opr, 0},
+ {"modu.w", 2, 0x38, mul_reg_reg_opr, 0},
+ {"modu.l", 2, 0x38, mul_reg_reg_opr, 0},
+
+ {"mods.b", 2, 0x38, mul_reg_reg_imm, 0},
+ {"mods.w", 2, 0x38, mul_reg_reg_imm, 0},
+ {"mods.l", 2, 0x38, mul_reg_reg_imm, 0},
+
+ {"modu.b", 2, 0x38, mul_reg_reg_imm, 0},
+ {"modu.w", 2, 0x38, mul_reg_reg_imm, 0},
+ {"modu.l", 2, 0x38, mul_reg_reg_imm, 0},
+
+ {"mods.bb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.bw", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.bp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.bl", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"mods.wb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.ww", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.wp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.wl", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"mods.pb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.pw", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.pp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.pl", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"mods.lb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.lw", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.lp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"mods.ll", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"modu.bb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.bw", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.bp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.bl", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"modu.wb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.ww", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.wp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.wl", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"modu.pb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.pw", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.pp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.pl", 2, 0x38, mul_reg_opr_opr, 0},
+
+ {"modu.lb", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.lw", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.lp", 2, 0x38, mul_reg_opr_opr, 0},
+ {"modu.ll", 2, 0x38, mul_reg_opr_opr, 0}
+};
+
+
+/* Gas line assembler entry point. */
+
+/* This is the main entry point for the machine-dependent assembler. str
+ points to a machine-dependent instruction. This function is supposed to
+ emit the frags/bytes it assembles to. */
+void
+md_assemble (char *str)
+{
+ char *op_start;
+ char *op_end;
+ char name[20];
+ size_t nlen = 0;
+
+ fail_line_pointer = NULL;
+
+ /* Find the opcode end and get the opcode in 'name'. The opcode is forced
+ lower case (the opcode table only has lower case op-codes). */
+ for (op_start = op_end = str;
+ *op_end && !is_end_of_line[(int)*op_end] && *op_end != ' ';
+ op_end++)
+ {
+ name[nlen] = TOLOWER (op_start[nlen]);
+ nlen++;
+ gas_assert (nlen < sizeof (name) - 1);
+ }
+ name[nlen] = 0;
+
+ if (nlen == 0)
+ {
+ as_bad (_("No instruction or missing opcode."));
+ return;
+ }
+
+ input_line_pointer = skip_whites (op_end);
+
+ size_t i;
+ for (i = 0; i < sizeof (opcodes) / sizeof (opcodes[0]); ++i)
+ {
+ const struct instruction *opc = opcodes + i;
+ if (0 == strcmp (name, opc->name))
+ {
+ if (opc->parse_operands (opc))
+ return;
+ continue;
+ }
+ }
+
+ as_bad (_("Invalid instruction: \"%s\""), str);
+ as_bad (_("First invalid token: \"%s\""), fail_line_pointer);
+ while (*input_line_pointer++)
+ ;
+}
+
+
+
+
+
+/* Relocation, relaxation and frag conversions. */
+
+/* PC-relative offsets are relative to the start of the
+ next instruction. That is, the address of the offset, plus its
+ size, since the offset is always the last part of the insn. */
+long
+md_pcrel_from (fixS *fixP)
+{
+ long ret = fixP->fx_size + fixP->fx_frag->fr_address;
+ if (fixP->fx_addsy && S_IS_DEFINED (fixP->fx_addsy))
+ ret += fixP->fx_where;
+
+ return ret;
+}
+
+
+/* We need a port-specific relaxation function to cope with sym2 - sym1
+ relative expressions with both symbols in the same segment (but not
+ necessarily in the same frag as this insn), for example:
+ ldab sym2-(sym1-2),pc
+ sym1:
+ The offset can be 5, 9 or 16 bits long. */
+
+long
+s12z_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP ATTRIBUTE_UNUSED,
+ long stretch ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED,
+ fragS *fragP ATTRIBUTE_UNUSED)
+{
+}
+
+/* On an ELF system, we can't relax a weak symbol. The weak symbol
+ can be overridden at final link time by a non weak symbol. We can
+ relax externally visible symbol because there is no shared library
+ and such symbol can't be overridden (unless they are weak). */
+
+/* Force truly undefined symbols to their maximum size, and generally set up
+ the frag list to be relaxed. */
+int
+md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, asection *segment ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+
+/* If while processing a fixup, a reloc really needs to be created
+ then it is done here. */
+arelent *
+tc_gen_reloc (asection *section, fixS *fixp)
+{
+ arelent *reloc = XNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Relocation %d is not supported by object file format."),
+ (int) fixp->fx_r_type);
+ return NULL;
+ }
+
+ if (0 == (section->flags & SEC_CODE))
+ reloc->addend = fixp->fx_offset;
+ else
+ reloc->addend = fixp->fx_addnumber;
+
+ return reloc;
+}
+
+/* See whether we need to force a relocation into the output file. */
+int
+tc_s12z_force_relocation (fixS *fixP)
+{
+ return generic_force_reloc (fixP);
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+ to the beginning of the section instead of the symbol. Basically
+ we need to make sure that the linker relaxation is done
+ correctly, so in some cases we force the original symbol to be
+ used. */
+int
+tc_s12z_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+void
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
+{
+ long value = *valP;
+
+ if (fixP->fx_addsy == (symbolS *) NULL)
+ fixP->fx_done = 1;
+
+ /* We don't actually support subtracting a symbol. */
+ if (fixP->fx_subsy != (symbolS *) NULL)
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));
+
+ /*
+ Patch the instruction with the resolved operand. Elf relocation
+ info will also be generated to take care of linker/loader fixups.
+ */
+ char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ ((bfd_byte *) where)[0] = (bfd_byte) value;
+ break;
+ case BFD_RELOC_24:
+ bfd_putb24 ((bfd_vma) value, (unsigned char *) where);
+ break;
+ case BFD_RELOC_32:
+ bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
+ break;
+ case BFD_RELOC_16_PCREL:
+ if (value < -0x8000 || value > 0x7FFF)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Value out of 16-bit range."));
+
+ bfd_putb16 ((bfd_vma) value | 0x8000, (unsigned char *) where);
+ break;
+
+ default:
+ as_fatal (_("Line %d: unknown relocation type: 0x%x."),
+ fixP->fx_line, fixP->fx_r_type);
+ }
+}
+
+/* Set the ELF specific flags. */
+void
+s12z_elf_final_processing (void)
+{
+}
diff --git a/gas/config/tc-s12z.h b/gas/config/tc-s12z.h
new file mode 100644
index 0000000..9d6b571
--- /dev/null
+++ b/gas/config/tc-s12z.h
@@ -0,0 +1,105 @@
+/* tc-s12z.h -- Header file for tc-s12z.c.
+ Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+struct fix;
+
+/* Define TC_M68K so that we can use the MRI mode. */
+#define TC_M68K
+
+#define TARGET_BYTES_BIG_ENDIAN 1
+
+/* Motorola assembler specs does not require '.' before pseudo-ops. */
+#define NO_PSEUDO_DOT 1
+
+/* The target BFD architecture. */
+#define TARGET_ARCH (s12z_arch ())
+extern enum bfd_architecture s12z_arch (void);
+
+#define TARGET_MACH (s12z_mach ())
+extern int s12z_mach (void);
+
+#define TARGET_FORMAT (s12z_arch_format ())
+extern const char *s12z_arch_format (void);
+
+#define LISTING_WORD_SIZE 1 /* A word is 1 bytes */
+#define LISTING_LHS_WIDTH 4 /* One word on the first line */
+#define LISTING_LHS_WIDTH_SECOND 4 /* One word on the second line */
+#define LISTING_LHS_CONT_LINES 4 /* And 4 lines max */
+#define LISTING_HEADER s12z_listing_header ()
+extern const char *s12z_listing_header (void);
+
+/* Permit temporary numeric labels. */
+#define LOCAL_LABELS_FB 1
+
+#define tc_init_after_args s12z_init_after_args
+extern void s12z_init_after_args (void);
+
+#define md_parse_long_option s12z_parse_long_option
+extern int s12z_parse_long_option (char *);
+
+#define DWARF2_LINE_MIN_INSN_LENGTH 1
+
+/* Use 32-bit address to represent a symbol address so that we can
+ represent them with their page number. */
+#define DWARF2_ADDR_SIZE(bfd) 4
+
+/* We don't need to handle .word strangely. */
+#define WORKING_DOT_WORD
+
+#define md_number_to_chars number_to_chars_bigendian
+
+/* Relax table to translate short relative branches (-128..127) into
+ absolute branches. */
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+extern struct relax_type md_relax_table[];
+
+/* GAS only handles relaxations for pc-relative data targeting addresses
+ in the same segment, so we have to handle the rest on our own. */
+#define md_relax_frag(SEG, FRAGP, STRETCH) \
+ ((FRAGP)->fr_symbol != NULL \
+ && S_GET_SEGMENT ((FRAGP)->fr_symbol) == (SEG) \
+ ? relax_frag (SEG, FRAGP, STRETCH) \
+ : s12z_relax_frag (SEG, FRAGP, STRETCH))
+extern long s12z_relax_frag (segT, fragS*, long);
+
+#define TC_HANDLES_FX_DONE
+
+#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
+
+/* Values passed to md_apply_fix don't include the symbol value. */
+#define MD_APPLY_SYM_VALUE(FIX) 0
+
+/* No shared lib support, so we don't need to ensure externally
+ visible symbols can be overridden. */
+#define EXTERN_FORCE_RELOC 0
+
+#define TC_FORCE_RELOCATION(fix) tc_s12z_force_relocation (fix)
+extern int tc_s12z_force_relocation (struct fix *);
+
+#define tc_fix_adjustable(X) tc_s12z_fix_adjustable(X)
+extern int tc_s12z_fix_adjustable (struct fix *);
+
+#define md_operand(x)
+
+#define elf_tc_final_processing s12z_elf_final_processing
+extern void s12z_elf_final_processing (void);
+
+#define tc_print_statistics(FILE) s12z_print_statistics (FILE)
+extern void s12z_print_statistics (FILE *);
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 67edc1d..3d0415c 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -75,6 +75,7 @@ case ${cpu} in
m680[012346]0) cpu_type=m68k ;;
m6811|m6812|m68hc12) cpu_type=m68hc11 ;;
m683??) cpu_type=m68k ;;
+ s12z) cpu_type=s12z ;;
mep) cpu_type=mep endian=little ;;
microblazeel*) cpu_type=microblaze endian=little;;
microblaze*) cpu_type=microblaze endian=big;;
@@ -285,6 +286,8 @@ case ${generic_target} in
m68k-*-gnu*) fmt=elf ;;
m68k-*-netbsdelf*) fmt=elf em=nbsd ;;
+ s12z-*-*) fmt=elf ;;
+
mep-*-elf) fmt=elf ;;
metag-*-elf) fmt=elf ;;
diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am
index 8089358..c9c3405 100644
--- a/gas/doc/Makefile.am
+++ b/gas/doc/Makefile.am
@@ -65,6 +65,7 @@ CPU_DOCS = \
c-m32r.texi \
c-m68hc11.texi \
c-m68k.texi \
+ c-s12z.texi \
c-metag.texi \
c-microblaze.texi \
c-mips.texi \
diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in
index 643df61..a126e2f 100644
--- a/gas/doc/Makefile.in
+++ b/gas/doc/Makefile.in
@@ -340,6 +340,7 @@ CPU_DOCS = \
c-m32r.texi \
c-m68hc11.texi \
c-m68k.texi \
+ c-s12z.texi \
c-metag.texi \
c-microblaze.texi \
c-mips.texi \
diff --git a/gas/doc/all.texi b/gas/doc/all.texi
index 47d55df..2b8af69 100644
--- a/gas/doc/all.texi
+++ b/gas/doc/all.texi
@@ -46,6 +46,7 @@
@set M32R
@set xc16x
@set M68HC11
+@set S12Z
@set M680X0
@set MCORE
@set METAG
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 35616c8..b6b16b7 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -7565,6 +7565,9 @@ subject, see the hardware manufacturer's manual.
@ifset M68HC11
* M68HC11-Dependent:: M68HC11 and 68HC12 Dependent Features
@end ifset
+@ifset S12Z
+* S12Z-Dependent:: S12Z Dependent Features
+@end ifset
@ifset METAG
* Meta-Dependent :: Meta Dependent Features
@end ifset
@@ -7776,6 +7779,10 @@ family.
@include c-m68hc11.texi
@end ifset
+@ifset S12Z
+@include c-s12z.texi
+@end ifset
+
@ifset METAG
@include c-metag.texi
@end ifset
diff --git a/gas/doc/c-s12z.texi b/gas/doc/c-s12z.texi
new file mode 100644
index 0000000..9c8a97f
--- /dev/null
+++ b/gas/doc/c-s12z.texi
@@ -0,0 +1,212 @@
+@c Copyright (C) 2018 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@ifset GENERIC
+@page
+@node S12Z-Dependent
+@chapter S12Z Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter S12Z Dependent Features
+@end ifclear
+
+The Freescale S12Z version of @code{@value{AS}} has a few machine
+dependent features.
+
+@cindex S12Z support
+@menu
+* S12Z-Opts:: S12Z Options
+* S12Z-Syntax:: Syntax
+* S12Z-Directives:: Assembler Directives
+* S12Z-opcodes:: Opcodes
+@end menu
+
+@node S12Z-Opts
+@section S12Z Options
+
+@cindex options, S12Z
+@cindex S12Z options
+
+@node S12Z-Syntax
+@section Syntax
+
+@cindex S12Z syntax
+@cindex syntax, S12Z
+
+In the S12Z syntax, the instruction name comes first and it may
+be followed by one or by several operands.
+In most cases the maximum number of operands is three.
+Some instructions accept and (in certain situations require) a suffix
+indicating the size of the operand.
+The suffix is separated from the instruction name by a period (@samp{.})
+and may be one of @samp{b}, @samp{w}, @samp{p} or @samp{l} indicating
+`byte' (a single byte), `word' (2 bytes), `pointer' (3 bytes) or `long' (4 bytes)
+respectively.
+Operands are separated by a comma (@samp{,}).
+A comma however does not act as a separator if it appears within parentheses
+(@samp{()}) or within square brackets (@samp{[]}).
+@code{@value{AS}} will complain if too many, too few or inappropriate operands
+are specified for a given instruction.
+The MRI mode is not supported for this architecture.
+Example:
+
+@smallexample
+ bset.b 0xA98, #5
+ mov.b #6, 0x2409
+ ld d0, #4
+ mov.l (d0, x), 0x2409
+ inc d0
+ cmp d0, #12
+ blt *-4
+ lea x, 0x2409
+ st y, (1, x)
+@end smallexample
+
+@cindex line comment character, S12Z
+@cindex S12Z line comment character
+The presence of a @samp{;} character anywhere
+on a line indicates the start of a comment that extends to the end of
+that line.
+
+A @samp{*} or a @samp{#} character at the start of a line also
+introduces a line comment, but these characters do not work elsewhere
+on the line. If the first character of the line is a @samp{#} then as
+well as starting a comment, the line could also be logical line number
+directive (@pxref{Comments}) or a preprocessor control command
+(@pxref{Preprocessing}).
+
+@cindex line separator, S12Z
+@cindex statement separator, S12Z
+@cindex S12Z line separator
+The S12Z assembler does not currently support a line separator
+character.
+
+@cindex S12Z addressing modes
+@cindex addressing modes, S12Z
+The following addressing modes are understood for the S12Z.
+@table @dfn
+@item Immediate
+@samp{#@var{number}}
+
+@item Immediate Bit Field
+@samp{#@var{width}:@var{offset}}
+
+Bit field instructions in the immediate mode require the width and offset to
+be specified.
+The @var{width} pararmeter specifies the number of bits in the field.
+It should be a number in the range [1,32].
+@var{Offset} determines the position within the field where the operation
+should start.
+It should be a number in the range [0,31].
+
+@item Relative
+@samp{*@var{symbol}}, or @samp{*[+-]@var{digits}}
+
+Program counter relative addresses have a width of 15 bits.
+Thus, they must be within the range [-32768, 32767].
+
+@item Register
+@samp{@var{reg}}
+
+Some instructions accept a register as an operand.
+In general, @var{reg} may be a data register (@samp{D0}, @samp{D1} @dots{}
+@samp{D7}), the @var{X} register or the @var{Y} register.
+
+A few instructions accept as an argument the stack pointer
+register (@samp{S}), and/or the program counter (@samp{P}).
+
+Some very special instructions accept arguments which refer to the
+condition code register. For these arguments the syntax is
+@samp{CCR}, @samp{CCH} or @samp{CCL} which refer to the complete condition code register, the condition code register high byte and the condition code register low byte respectively.
+
+@item Absolute Direct
+@samp{@var{symbol}}, or @samp{@var{digits}}
+
+@item Absolute Indirect
+@samp{[@var{symbol}}, or @samp{@var{digits}]}
+
+
+@item Constant Offset Indexed
+@samp{(@var{number},@var{reg})}
+
+@var{Reg} may be either @samp{X}, @samp{Y}, @samp{S} or
+@samp{P} or one of the data registers @samp{D0}, @samp{D1} @dots{}
+@samp{D7}.
+If any of the registers @samp{D2} @dots{} @samp{D5} are specified, then the
+register value is treated as a signed value.
+Otherwise it is treated as unsigned.
+@var{Number} may be any integer in the range [-8388608,8388607].
+
+@item Offset Indexed Indirect
+@samp{[@var{number},@var{reg}]}
+
+@var{Reg} may be either @samp{X}, @samp{Y}, @samp{S} or
+@samp{P}.
+@var{Number} may be any integer in the range [-8388608,8388607].
+
+@item Auto Pre-Increment/Pre-Decrement/Post-Increment/Post-Decrement
+@samp{-@var{reg}},
+@samp{+@var{reg}},
+@samp{@var{reg}-} or
+@samp{@var{reg}+}
+
+This addressing mode is typically used to access a value at an address,
+and simultaneously to increment/decrement the register pointing to that
+address.
+Thus @var{reg} may be any of the 24 bit registers @samp{X}, @samp{Y}, or
+@samp{S}.
+Pre-increment and post-decrement are not available for
+register @samp{S} (only post-increment and pre-decrement are available).
+
+@item Register Offset Direct
+@samp{(@var{data-reg},@var{reg})}
+
+@var{Reg} can be either @samp{X}, @samp{Y}, or @samp{S}.
+@var{Data-reg}
+must be one of the data registers @samp{D0}, @samp{D1} @dots{} @samp{D7}.
+If any of the registers @samp{D2} @dots{} @samp{D5} are specified, then
+the register value is treated as a signed value.
+Otherwise it is treated as unsigned.
+
+@item Register Offset Indirect
+@samp{[@var{data-reg},@var{reg}]}
+
+@var{Reg} can be either @samp{X} or @samp{Y}.
+@var{Data-reg}
+must be one of the data registers @samp{D0}, @samp{D1} @dots{} @samp{D7}.
+If any of the registers @samp{D2} @dots{} @samp{D5} are specified, then
+the register value is treated as a signed value.
+Otherwise it is treated as unsigned.
+
+
+@end table
+
+For example:
+
+@smallexample
+ trap #197
+ bra *+49
+ bra .L0
+ jmp 0xFE0034
+ jmp [0xFD0012]
+ inc.b (4,x)
+ dec.w [4,y]
+ clr.p (-s)
+ neg.l (d0, s)
+ com.b [d1, x]
+ jsr (45, d0)
+ psh cch
+@end smallexample
+
+@node S12Z-Directives
+@section Assembler Directives
+
+@cindex assembler directives, S12Z
+
+@node S12Z-opcodes
+@section Opcodes
+
+@cindex S12Z opcodes
+@cindex opcodes, S12Z
+@cindex instruction set, S12Z
diff --git a/gas/testsuite/gas/s12z/abs.d b/gas/testsuite/gas/s12z/abs.d
new file mode 100644
index 0000000..b41238f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/abs.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: abs.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 40 abs d2
+ 2: 1b 41 abs d3
+ 4: 1b 42 abs d4
+ 6: 1b 43 abs d5
+ 8: 1b 44 abs d0
+ a: 1b 45 abs d1
+ c: 1b 46 abs d6
+ e: 1b 47 abs d7
diff --git a/gas/testsuite/gas/s12z/abs.s b/gas/testsuite/gas/s12z/abs.s
new file mode 100644
index 0000000..718a2eb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/abs.s
@@ -0,0 +1,8 @@
+ abs d2
+ abs d3
+ abs d4
+ abs d5
+ abs d0
+ abs d1
+ abs d6
+ abs d7
diff --git a/gas/testsuite/gas/s12z/adc-imm.d b/gas/testsuite/gas/s12z/adc-imm.d
new file mode 100644
index 0000000..b13d136
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: adc-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 50 12 34 adc d2, #4660
+ 4: 1b 51 12 34 adc d3, #4660
+ 8: 1b 52 12 34 adc d4, #4660
+ c: 1b 53 12 34 adc d5, #4660
+ 10: 1b 54 12 adc d0, #18
+ 13: 1b 55 34 adc d1, #52
+ 16: 1b 56 00 56 adc d6, #5666970
+ 1a: 78 9a
+ 1c: 1b 57 00 98 adc d7, #9991764
+ 20: 76 54
diff --git a/gas/testsuite/gas/s12z/adc-imm.s b/gas/testsuite/gas/s12z/adc-imm.s
new file mode 100644
index 0000000..cddf980
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-imm.s
@@ -0,0 +1,8 @@
+ adc d2, #0x1234
+ adc d3, #0x1234
+ adc d4, #0x1234
+ adc d5, #0x1234
+ adc d0, #0x12
+ adc d1, #0x34
+ adc d6, #0x56789A
+ adc d7, #0x987654
diff --git a/gas/testsuite/gas/s12z/adc-opr.d b/gas/testsuite/gas/s12z/adc-opr.d
new file mode 100644
index 0000000..d2023a2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-opr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: adc-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 64 c5 21 adc d0, \[-223,x\]
+ 4: 1b 65 e2 ff adc d1, \(-2000,s\)
+ 8: f8 30
+ a: 1b 60 c7 adc d2, \(x-\)
+ d: 1b 61 f3 adc d3, \(\+y\)
+ 10: 1b 62 bb adc d4, d5
+ 13: 1b 63 3e ce adc d5, 16078
+ 17: 1b 66 fe 01 adc d6, \[73056\]
+ 1b: 1d 60
+ 1d: 1b 67 8a adc d7, \(d4,x\)
diff --git a/gas/testsuite/gas/s12z/adc-opr.s b/gas/testsuite/gas/s12z/adc-opr.s
new file mode 100644
index 0000000..b16befc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/adc-opr.s
@@ -0,0 +1,9 @@
+ adc d0, [-223,x]
+ adc d1, (-2000, s)
+ adc d2, (x-)
+ adc d3, (+y)
+ adc d4, d5
+ adc d5, 16078
+ adc d6, [73056]
+ adc d7, (d4,x)
+
diff --git a/gas/testsuite/gas/s12z/add-imm.d b/gas/testsuite/gas/s12z/add-imm.d
new file mode 100644
index 0000000..6125da4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: add-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 50 12 34 add d2, #4660
+ 3: 51 12 34 add d3, #4660
+ 6: 52 12 34 add d4, #4660
+ 9: 53 12 34 add d5, #4660
+ c: 54 12 add d0, #18
+ e: 55 34 add d1, #52
+ 10: 56 00 56 78 add d6, #5666970
+ 14: 9a
+ 15: 57 00 98 76 add d7, #9991764
+ 19: 54
diff --git a/gas/testsuite/gas/s12z/add-imm.s b/gas/testsuite/gas/s12z/add-imm.s
new file mode 100644
index 0000000..5986c8e7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-imm.s
@@ -0,0 +1,8 @@
+start: add d2, #0x1234
+ add d3, #0x1234
+ add d4, #0x1234
+ add d5, #0x1234
+ add d0, #0x12
+ add d1, #0x34
+ add d6, #0x56789A
+ add d7, #0x987654
diff --git a/gas/testsuite/gas/s12z/add-opr.d b/gas/testsuite/gas/s12z/add-opr.d
new file mode 100644
index 0000000..0528312
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-opr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: add-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 64 c5 21 add d0, \[-223,x\]
+ 3: 65 e2 00 75 add d1, \(30000,s\)
+ 7: 30
+ 8: 60 c7 add d2, \(x-\)
+ a: 61 f3 add d3, \(\+y\)
+ c: 62 bf add d4, d7
+ e: 63 17 be add d5, 6078
+ 11: 66 fe 01 1d add d6, \[73056\]
+ 15: 60
+ 16: 67 8a add d7, \(d4,x\)
diff --git a/gas/testsuite/gas/s12z/add-opr.s b/gas/testsuite/gas/s12z/add-opr.s
new file mode 100644
index 0000000..d86a4aa
--- /dev/null
+++ b/gas/testsuite/gas/s12z/add-opr.s
@@ -0,0 +1,9 @@
+ add d0, [-223,x]
+ add d1, (30000, s)
+ add d2, (x-)
+ add d3, (+y)
+ add d4, d7
+ add d5, 6078
+ add d6, [73056]
+ add d7, (d4,x)
+
diff --git a/gas/testsuite/gas/s12z/and-imm.d b/gas/testsuite/gas/s12z/and-imm.d
new file mode 100644
index 0000000..fea351d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: and-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 58 12 34 and d2, #4660
+ 3: 59 12 34 and d3, #4660
+ 6: 5a 12 34 and d4, #4660
+ 9: 5b 12 34 and d5, #4660
+ c: 5c 12 and d0, #18
+ e: 5d 34 and d1, #52
+ 10: 5e 56 78 9a and d6, #1450744508
+ 14: bc
+ 15: 5f 98 76 54 and d7, #-1737075662
+ 19: 32
diff --git a/gas/testsuite/gas/s12z/and-imm.s b/gas/testsuite/gas/s12z/and-imm.s
new file mode 100644
index 0000000..fcd947a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-imm.s
@@ -0,0 +1,8 @@
+start: and d2, #0x1234
+ and d3, #0x1234
+ and d4, #0x1234
+ and d5, #0x1234
+ and d0, #0x12
+ and d1, #0x34
+ and d6, #0x56789ABC
+ and d7, #-1737075662
diff --git a/gas/testsuite/gas/s12z/and-opr.d b/gas/testsuite/gas/s12z/and-opr.d
new file mode 100644
index 0000000..b9cc366
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:
+#source: and-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 6c c4 17 and d0, \[23,x\]
+ 3: 6d d2 ff 8a and d1, \(-30000,y\)
+ 7: d0
+ 8: 68 c7 and d2, \(x-\)
+ a: 69 f3 and d3, \(\+y\)
+ c: 6a bb and d4, d5
+ e: 6b fa 23 ca and d5, 2345678
+ 12: ce
+ 13: 6e fe 01 e2 and d6, \[123456\]
+ 17: 40
+ 18: 6f ac and d7, \(d0,s\)
diff --git a/gas/testsuite/gas/s12z/and-opr.s b/gas/testsuite/gas/s12z/and-opr.s
new file mode 100644
index 0000000..6569ebe
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-opr.s
@@ -0,0 +1,9 @@
+ and d0, [23,x]
+ and d1, (-30000, y)
+ and d2, (x-)
+ and d3, (+y)
+ and d4, d5
+ and d5, 2345678
+ and d6, [123456]
+ and d7, (d0,s)
+
diff --git a/gas/testsuite/gas/s12z/and-or-cc.d b/gas/testsuite/gas/s12z/and-or-cc.d
new file mode 100644
index 0000000..38117e9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-or-cc.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:
+#source: and-or-cc.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <xx>:
+ 0: ce 7b andcc #123
+ 2: de 20 orcc #32
diff --git a/gas/testsuite/gas/s12z/and-or-cc.s b/gas/testsuite/gas/s12z/and-or-cc.s
new file mode 100644
index 0000000..afa4a1e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/and-or-cc.s
@@ -0,0 +1,2 @@
+xx: andcc #123
+ orcc #32
diff --git a/gas/testsuite/gas/s12z/bfext-special.d b/gas/testsuite/gas/s12z/bfext-special.d
new file mode 100644
index 0000000..380e627
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext-special.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:
+#source: bfext-special.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 0f 75 a3 bfext.w \(45,d1\), d7, #13:3
+ 4: 85 00 2d
diff --git a/gas/testsuite/gas/s12z/bfext-special.s b/gas/testsuite/gas/s12z/bfext-special.s
new file mode 100644
index 0000000..1810c9a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext-special.s
@@ -0,0 +1,2 @@
+ bfext.w (45,d1), d7, #13:3
+
diff --git a/gas/testsuite/gas/s12z/bfext.d b/gas/testsuite/gas/s12z/bfext.d
new file mode 100644
index 0000000..84f439a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext.d
@@ -0,0 +1,47 @@
+#objdump: -d
+#name:
+#source: bfext.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 0c 14 bfext d0, d1, d2
+ 3: 1b 0d 21 17 bfext d1, d2, #8:23
+ 7: 1b 08 41 e3 bfext.b d2, \(\+x\), d3
+ b: 1b 09 46 c4 bfext.w d3, \[123,x\], d4
+ f: 7b
+ 10: 1b 0a 4b ac bfext.p d4, \(d0,s\), d5
+ 14: 1b 0b 4c 84 bfext.l d5, \(45,d0\), d2
+ 18: 00 2d
+ 1a: 1b 0e 51 84 bfext.b \(45,d0\), d6, d3
+ 1e: 00 2d
+ 20: 1b 0f 54 c4 bfext.w \[45,x\], d7, d2
+ 24: 2d
+ 25: 1b 0c 61 a2 bfext.b d0, \(45,d1\), #13:2
+ 29: 85 00 2d
+ 2c: 1b 0f 75 a3 bfext.w \(45,d1\), d7, #13:3
+ 30: 85 00 2d
+ 33: 1b 0f 58 c6 bfext.p \[451,x\], d7, d2
+ 37: 00 01 c3
+ 3a: 1b 0c 94 bfins d0, d1, d2
+ 3d: 1b 0d a1 17 bfins d1, d2, #8:23
+ 41: 1b 08 c1 e3 bfins.b d2, \(\+x\), d3
+ 45: 1b 09 c6 c4 bfins.w d3, \[123,x\], d4
+ 49: 7b
+ 4a: 1b 0a cb ac bfins.p d4, \(d0,s\), d5
+ 4e: 1b 0b cc 84 bfins.l d5, \(45,d0\), d2
+ 52: 00 2d
+ 54: 1b 0e d1 84 bfins.b \(45,d0\), d6, d3
+ 58: 00 2d
+ 5a: 1b 0f d4 c4 bfins.w \[45,x\], d7, d2
+ 5e: 2d
+ 5f: 1b 0c e1 a2 bfins.b d0, \(45,d1\), #13:2
+ 63: 85 00 2d
+ 66: 1b 0f f5 a3 bfins.w \(45,d1\), d7, #13:3
+ 6a: 85 00 2d
+ 6d: 1b 0f d8 c6 bfins.p \[451,x\], d7, d2
+ 71: 00 01 c3
diff --git a/gas/testsuite/gas/s12z/bfext.s b/gas/testsuite/gas/s12z/bfext.s
new file mode 100644
index 0000000..66cb5b6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bfext.s
@@ -0,0 +1,23 @@
+ bfext d0, d1, d2
+ bfext d1, d2, #8:23
+ bfext.b d2, (+x), d3
+ bfext.w d3, [123,x], d4
+ bfext.p d4, (d0, s), d5
+ bfext.l d5, (45,d0), d2
+ bfext.b (45,d0), d6, d3
+ bfext.w [45,x], d7, d2
+ bfext.b d0, (45,d1), #13:2
+ bfext.w (45,d1), d7, #13:3
+ bfext.p [451,x], d7, d2
+
+ bfins d0, d1, d2
+ bfins d1, d2, #8:23
+ bfins.b d2, (+x), d3
+ bfins.w d3, [123,x], d4
+ bfins.p d4, (d0, s), d5
+ bfins.l d5, (45,d0), d2
+ bfins.b (45,d0), d6, d3
+ bfins.w [45,x], d7, d2
+ bfins.b d0, (45,d1), #13:2
+ bfins.w (45,d1), d7, #13:3
+ bfins.p [451,x], d7, d2
diff --git a/gas/testsuite/gas/s12z/bit-manip.d b/gas/testsuite/gas/s12z/bit-manip.d
new file mode 100644
index 0000000..6a0c7ee
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit-manip.d
@@ -0,0 +1,26 @@
+#objdump: -d
+#name:
+#source: bit-manip.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: ec 1c bclr d0, #3
+ 2: ed 25 bset d1, #4
+ 4: ee 28 btgl d2, #5
+ 6: ec b1 b9 bclr d3, d5
+ 9: ed e1 ba bset d4, d6
+ c: ee f1 bb btgl d5, d7
+ f: ec a0 c0 22 bclr.b \(34,x\), #2
+ 13: ec c3 ff bclr.w \(s\+\), #12
+ 16: ec fd e0 38 bclr.l \(56,s\), d7
+ 1a: ed d0 c4 22 bset.b \[34,x\], #5
+ 1e: ed db fb bset.l \(-s\), #29
+ 21: ed f5 c0 9c bset.w \(156,x\), d7
+ 25: ee d0 c4 22 btgl.b \[34,x\], #5
+ 29: ee f3 fb btgl.w \(-s\), #15
+ 2c: ee fd f0 0f btgl.l \(15,p\), d7
diff --git a/gas/testsuite/gas/s12z/bit-manip.s b/gas/testsuite/gas/s12z/bit-manip.s
new file mode 100644
index 0000000..cebb478
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit-manip.s
@@ -0,0 +1,16 @@
+ bclr d0, #3
+ bset d1, #4
+ btgl d2, #5
+ bclr d3, d5
+ bset d4, d6
+ btgl d5, d7
+ bclr.b (34,x), #2
+ bclr.w (s+), #12
+ bclr.l (56,s), d7
+ bset.b [34,x], #5
+ bset.l (-s), #29
+ bset.w (156,x), d7
+ btgl.b [34,x], #5
+ btgl.w (-s), #15
+ btgl.l (15,p), d7
+
diff --git a/gas/testsuite/gas/s12z/bit.d b/gas/testsuite/gas/s12z/bit.d
new file mode 100644
index 0000000..68dd30c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name:
+#source: bit.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 58 fc 84 bit d2, #-892
+ 4: 1b 59 ef 32 bit d3, #-4302
+ 8: 1b 5f 00 01 bit d7, #123456
+ c: e2 40
+ e: 1b 5b 04 d2 bit d5, #1234
+ 12: 1b 5c 7b bit d0, #123
+ 15: 1b 5d 22 bit d1, #34
+ 18: 1b 5e ff ff bit d6, #-56789
+ 1c: 22 2b
+ 1e: 1b 5a 22 3d bit d4, #8765
+ 22: 1b 6c d5 21 bit d0, \[-223,y\]
+ 26: 1b 6d f2 00 bit d1, \(34000,p\)
+ 2a: 84 d0
+ 2c: 1b 68 fb bit d2, \(-s\)
+ 2f: 1b 59 00 04 bit d3, #4
+ 33: 1b 6a bc bit d4, d0
+ 36: 1b 6b f9 4c bit d5, 85178
+ 3a: ba
+ 3b: 1b 6e fe 00 bit d6, \[15256\]
+ 3f: 3b 98
+ 41: 1b 6f 8b bit d7, \(d5,x\)
+ 44: 1b 69 f3 bit d3, \(\+y\)
diff --git a/gas/testsuite/gas/s12z/bit.s b/gas/testsuite/gas/s12z/bit.s
new file mode 100644
index 0000000..539b593
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bit.s
@@ -0,0 +1,17 @@
+ bit d2, #-892
+ bit d3, #-4302
+ bit d7, #123456
+ bit d5, #1234
+ bit d0, #123
+ bit d1, #34
+ bit d6, #-56789
+ bit d4, #8765
+ bit d0, [-223,y]
+ bit d1, (34000, p)
+ bit d2, (-s)
+ bit d3, #4
+ bit d4, d0
+ bit d5, 85178
+ bit d6, [15256]
+ bit d7, (d5, x)
+ bit d3, (+y)
diff --git a/gas/testsuite/gas/s12z/bra-expression-defined.d b/gas/testsuite/gas/s12z/bra-expression-defined.d
new file mode 100644
index 0000000..700f7cd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-defined.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name: pc_relative expressions defined at assembly time
+#source: bra-expression-defined.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <loop-0x11>:
+ 0: 01 nop
+ 1: 01 nop
+ 2: 20 80 19 bra \*\+25
+ 5: 01 nop
+ 6: 02 c0 bc 80 brclr.b d0, #4, \*\+31
+ a: 1f
+ b: 01 nop
+ c: 0b 06 80 23 tbne d6, \*\+35
+ 10: 01 nop
+
+00000011 <loop>:
+ 11: 01 nop
diff --git a/gas/testsuite/gas/s12z/bra-expression-defined.s b/gas/testsuite/gas/s12z/bra-expression-defined.s
new file mode 100644
index 0000000..2a1baeb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-defined.s
@@ -0,0 +1,11 @@
+
+ nop
+ nop
+ bra loop+10
+ nop
+ brclr.b d0, #4, loop+20
+ nop
+ tbne d6, loop+30
+ nop
+loop:
+ nop
diff --git a/gas/testsuite/gas/s12z/bra-expression-undef.d b/gas/testsuite/gas/s12z/bra-expression-undef.d
new file mode 100644
index 0000000..ddd7dcb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-undef.d
@@ -0,0 +1,24 @@
+#objdump: -dr
+#name: pc_relative expressions without a definition
+#source: bra-expression-undef.s
+
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 01 nop
+ 1: 01 nop
+ 2: 20 80 0b bra \*\+11
+ 3: R_S12Z_PCREL_7_15 loop\+0x8000
+ 5: 01 nop
+ 6: 02 c0 bc 80 brclr.b d0, #4, \*\+23
+ a: 17
+ 9: R_S12Z_PCREL_7_15 loop\+0x18000
+ b: 01 nop
+ c: 0b 06 80 20 tbne d6, \*\+32
+ e: R_S12Z_PCREL_7_15 loop\+0x10000
+ 10: 01 nop
diff --git a/gas/testsuite/gas/s12z/bra-expression-undef.s b/gas/testsuite/gas/s12z/bra-expression-undef.s
new file mode 100644
index 0000000..1d5a81e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra-expression-undef.s
@@ -0,0 +1,9 @@
+
+ nop
+ nop
+ bra loop+10
+ nop
+ brclr.b d0, #4, loop+20
+ nop
+ tbne d6, loop+30
+ nop
diff --git a/gas/testsuite/gas/s12z/bra.d b/gas/testsuite/gas/s12z/bra.d
new file mode 100644
index 0000000..7a6cc1c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra.d
@@ -0,0 +1,34 @@
+#objdump: -d
+#name:
+#source: bra.s
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: 20 80 0f bra L4
+
+00000003 <L2>:
+ 3: 21 ff fd bsr L1
+ 6: 22 ff fa bhi L1
+
+00000009 <L3>:
+ 9: 23 80 00 bls L3
+ c: 24 ff f4 bcc L1
+
+0000000f <L4>:
+ f: 25 ff f4 bcs L2
+ 12: 26 ff f7 bne L3
+ 15: 27 ff fa beq L4
+ 18: 28 ff f7 bvc L4
+ 1b: 29 ff e8 bvs L2
+ 1e: 2a ff e2 bpl L1
+ 21: 2b ff e2 bmi L2
+ 24: 2c ff dc bge L1
+ 27: 2d ff e8 blt L4
+ 2a: 2e ff df bgt L3
+ 2d: 2f ff d3 ble L1
+ 30: 20 02 bra \*\+2
+ 32: 20 7c bra \*-4
diff --git a/gas/testsuite/gas/s12z/bra.s b/gas/testsuite/gas/s12z/bra.s
new file mode 100644
index 0000000..a2528b3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/bra.s
@@ -0,0 +1,20 @@
+L1: bra L4
+L2: bsr L1
+ bhi L1
+L3: bls L3
+ bcc L1
+L4: bcs L2
+ bne L3
+ beq L4
+ bvc L4
+ bvs L2
+ bpl L1
+ bmi L2
+ bge L1
+ blt L4
+ bgt L3
+ ble L1
+
+ bra *+2
+ bra *-4
+
diff --git a/gas/testsuite/gas/s12z/brclr-symbols.d b/gas/testsuite/gas/s12z/brclr-symbols.d
new file mode 100644
index 0000000..59de1c0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brclr-symbols.d
@@ -0,0 +1,32 @@
+#objdump: -dt
+#name:
+#source: brclr-symbols.s
+
+
+dump.o: file format elf32-s12z
+
+SYMBOL TABLE:
+00000000 l d .text 00000000 .text
+00000000 l d .data 00000000 .data
+00000000 l d .bss 00000000 .bss
+00000001 l .text 00000000 foo
+
+
+
+Disassembly of section .text:
+
+00000000 <foo-0x1>:
+ 0: 01 nop
+
+00000001 <foo>:
+ 1: 01 nop
+ 2: 01 nop
+ 3: 02 0c ff fe brclr d0, #1, foo
+ 7: 03 81 bd ff brset d1, d2, foo
+ b: fa
+ c: 02 a0 e7 ff brclr.b \(x\+\), #2, foo
+ 10: f5
+ 11: 03 c1 84 00 brset.b \(23,d0\), d0, foo
+ 15: 17 ff f0
+ 18: 02 a0 03 86 brclr.b 902, #2, foo
+ 1c: ff e9 \ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/brclr-symbols.s b/gas/testsuite/gas/s12z/brclr-symbols.s
new file mode 100644
index 0000000..fa212fe
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brclr-symbols.s
@@ -0,0 +1,9 @@
+ nop
+foo:
+ nop
+ nop
+ brclr d0, #1, foo
+ brset d1, d2, foo
+ brclr.b (x+), #2, foo
+ brset.b (23,d0), d0, foo
+ brclr.b 902, #2, foo
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d
new file mode 100644
index 0000000..588e606
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: brset-clr-opr-imm-rel.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 03 c0 e4 2d brset.b \[45,s\], #4, \*\+3
+ 4: 03
+ 5: 03 e3 e6 00 brset.w \[345,s\], #14, \*\+32
+ 9: 01 59 20
+ c: 03 99 e2 00 brset.l \(345,s\), #9, \*\+309
+ 10: 01 59 81 35
+ 14: 02 c0 e6 00 brclr.b \[345,s\], #4, \*\+3
+ 18: 01 59 03
+ 1b: 02 f3 e6 00 brclr.w \[345,s\], #15, \*\+3087
+ 1f: 01 59 8c 0f
+ 23: 02 fb e6 00 brclr.l \[345,s\], #31, \*\+3
+ 27: 01 59 03
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s
new file mode 100644
index 0000000..1bb8da9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s
@@ -0,0 +1,7 @@
+ brset.b [45,s], #4, *+3
+ brset.w [345,s], #14, *+32
+ brset.l (345,s), #9, *+309
+ brclr.b [345,s], #4, *+3
+ brclr.w [345,s], #15, *+3087
+ brclr.l [345,s], #31, *+3
+
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d
new file mode 100644
index 0000000..1a87e78
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: brset-clr-opr-reg-rel.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1-0x6>:
+ 0: 02 85 d0 22 brclr.w \(34,y\), d2, \*\+3034
+ 4: 8b da
+
+00000006 <L1>:
+ 6: 03 c1 d3 81 brset.b \(-y\), d0, \*\+434
+ a: b2
+ b: 03 9d e3 88 brset.l \(\+x\), d3, \*\+2134
+ f: 56
+ 10: 02 ad c4 22 brclr.l \[34,x\], d4, L1
+ 14: ff f6
diff --git a/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s
new file mode 100644
index 0000000..76c3bb5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s
@@ -0,0 +1,5 @@
+ brclr.w (34,y), d2, *+3034
+L1: brset.b (-y), d0, *+434
+ brset.l (+x), d3, *+2134
+ brclr.l [34,x], d4, L1
+
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d
new file mode 100644
index 0000000..ddcc61d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d
@@ -0,0 +1,24 @@
+#objdump: -d
+#name:
+#source: brset-clr-reg-imm-rel.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: 03 10 05 brset d2, #2, \*\+5
+ 3: 03 19 17 brset d3, #3, \*\+23
+ 6: 03 11 71 brset d3, #2, \*-15
+ 9: 03 40 43 brset d2, #8, \*-61
+ c: 03 40 fd 01 brset d2, #8, \*-767
+ 10: 03 6e fd 01 brset d6, #13, \*-767
+
+00000014 <L2>:
+ 14: 02 10 05 brclr d2, #2, \*\+5
+ 17: 02 19 17 brclr d3, #3, \*\+23
+ 1a: 02 11 fc c0 brclr d3, #2, \*-832
+ 1e: 02 40 43 brclr d2, #8, \*-61
+ 21: 02 40 fd 01 brclr d2, #8, \*-767
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s
new file mode 100644
index 0000000..3aca621
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s
@@ -0,0 +1,12 @@
+L1: brset d2, #2, *+5
+ brset d3, #3, *+23
+ brset d3, #2, *-15
+ brset d2, #8, *-61
+ brset d2, #8, *-767
+ brset d6, #13, *-767
+L2: brclr d2, #2, *+5
+ brclr d3, #3, *+23
+ brclr d3, #2, *-832
+ brclr d2, #8, *-61
+ brclr d2, #8, *-767
+
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d
new file mode 100644
index 0000000..1cad906
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: brset-clr-reg-reg-rel.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 03 e1 bb 2d brset d5, d6, \*\+45
+ 4: 02 d1 b8 6f brclr d2, d1, \*-17
+ 8: 03 91 be ff brset d6, d3, \*-90
+ c: a6
+ d: 02 f1 bc ff brclr d0, d7, \*-90
+ 11: a6
+ 12: 02 81 bd ff brclr d1, d2, \*-190
+ 16: 42
diff --git a/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s
new file mode 100644
index 0000000..c78ec97
--- /dev/null
+++ b/gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s
@@ -0,0 +1,6 @@
+ brset d5, d6, *+45
+ brclr d2, d1, *-17
+ brset d6, d3, *-90
+ brclr d0, d7, *-90
+ brclr d1, d2, *-190
+
diff --git a/gas/testsuite/gas/s12z/clb.d b/gas/testsuite/gas/s12z/clb.d
new file mode 100644
index 0000000..fd142dc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clb.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: clb.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 91 47 clb d0, d7
+ 3: 1b 91 56 clb d1, d6
+ 6: 1b 91 03 clb d2, d5
+ 9: 1b 91 12 clb d3, d4
+ c: 1b 91 21 clb d4, d3
+ f: 1b 91 30 clb d5, d2
+ 12: 1b 91 65 clb d6, d1
+ 15: 1b 91 74 clb d7, d0
diff --git a/gas/testsuite/gas/s12z/clb.s b/gas/testsuite/gas/s12z/clb.s
new file mode 100644
index 0000000..877bbce
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clb.s
@@ -0,0 +1,8 @@
+ clb d0, d7
+ clb d1, d6
+ clb d2, d5
+ clb d3, d4
+ clb d4, d3
+ clb d5, d2
+ clb d6, d1
+ clb d7, d0
diff --git a/gas/testsuite/gas/s12z/clr-opr.d b/gas/testsuite/gas/s12z/clr-opr.d
new file mode 100644
index 0000000..7c05ebb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: clr-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: bc ff clr.b \(s\+\)
+ 2: bd c0 2d clr.w \(45,x\)
+ 5: be f9 e2 32 clr.p 123442
+ 9: bf d4 03 clr.l \[3,y\]
diff --git a/gas/testsuite/gas/s12z/clr-opr.s b/gas/testsuite/gas/s12z/clr-opr.s
new file mode 100644
index 0000000..ecfa266
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr-opr.s
@@ -0,0 +1,5 @@
+ clr.b (s+)
+ clr.w (45,x)
+ clr.p 123442
+ clr.l [3,y]
+
diff --git a/gas/testsuite/gas/s12z/clr.d b/gas/testsuite/gas/s12z/clr.d
new file mode 100644
index 0000000..1e902d6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: clr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: 38 clr d2
+ 1: 39 clr d3
+ 2: 3a clr d4
+ 3: 3b clr d5
+ 4: 3c clr d0
+ 5: 3d clr d1
+ 6: 3e clr d6
+ 7: 3f clr d7
+ 8: 9a clr x
+ 9: 9b clr y
diff --git a/gas/testsuite/gas/s12z/clr.s b/gas/testsuite/gas/s12z/clr.s
new file mode 100644
index 0000000..1f0b57f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/clr.s
@@ -0,0 +1,10 @@
+L1: clr d2
+ clr d3
+ clr d4
+ clr d5
+ clr d0
+ clr d1
+ clr d6
+ clr d7
+ clr x
+ clr y
diff --git a/gas/testsuite/gas/s12z/cmp-imm.d b/gas/testsuite/gas/s12z/cmp-imm.d
new file mode 100644
index 0000000..d756b00
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-imm.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: cmp-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <here>:
+ 0: e4 12 cmp d0, #18
+ 2: e5 34 cmp d1, #52
+ 4: e0 34 56 cmp d2, #13398
+ 7: e1 34 56 cmp d3, #13398
+ a: e2 34 56 cmp d4, #13398
+ d: e3 34 56 cmp d5, #13398
+ 10: e6 00 34 56 cmp d6, #3430008
+ 14: 78
+ 15: e7 00 34 56 cmp d7, #3430008
+ 19: 78
+ 1a: e8 aa bb cc cmp x, #-5588020
+ 1e: e9 dd ee ff cmp y, #-2232577
diff --git a/gas/testsuite/gas/s12z/cmp-imm.s b/gas/testsuite/gas/s12z/cmp-imm.s
new file mode 100644
index 0000000..89b41b5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-imm.s
@@ -0,0 +1,12 @@
+here: cmp d0, #0x12
+ cmp d1, #0x34
+ cmp d2, #0x3456
+ cmp d3, #0x3456
+ cmp d4, #0x3456
+ cmp d5, #0x3456
+ cmp d6, #0x345678
+ cmp d7, #0x345678
+
+ cmp x, #-5588020
+ cmp y, #-2232577
+
diff --git a/gas/testsuite/gas/s12z/cmp-opr-inc.d b/gas/testsuite/gas/s12z/cmp-opr-inc.d
new file mode 100644
index 0000000..bda08de
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-inc.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: cmp-opr-inc.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: f0 e3 cmp d2, \(\+x\)
+ 2: f1 f3 cmp d3, \(\+y\)
+ 4: f2 c3 cmp d4, \(-x\)
+ 6: f3 d3 cmp d5, \(-y\)
+ 8: f4 fb cmp d0, \(-s\)
+ a: f6 ff cmp d6, \(s\+\)
+ c: f8 d7 cmp x, \(y-\)
+ e: f8 c7 cmp x, \(x-\)
+ 10: f9 f7 cmp y, \(y\+\)
+ 12: f9 e7 cmp y, \(x\+\)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-inc.s b/gas/testsuite/gas/s12z/cmp-opr-inc.s
new file mode 100644
index 0000000..48b1d48
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-inc.s
@@ -0,0 +1,11 @@
+;; Pre/Post increment/decrement xys
+ cmp d2, (+x)
+ cmp d3, (+y)
+ cmp d4, (-x)
+ cmp d5, (-y)
+ cmp d0, (-s)
+ cmp d6, (s+)
+ cmp x, (y-)
+ cmp x, (x-)
+ cmp y, (y+)
+ cmp y, (x+)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rdirect.d b/gas/testsuite/gas/s12z/cmp-opr-rdirect.d
new file mode 100644
index 0000000..879ed98
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rdirect.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: cmp-opr-rdirect.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: f0 ad cmp d2, \(d1,s\)
+ 2: f1 88 cmp d3, \(d2,x\)
+ 4: f2 89 cmp d4, \(d3,x\)
+ 6: f3 99 cmp d5, \(d3,y\)
+ 8: f4 8a cmp d0, \(d4,x\)
+ a: f5 8b cmp d1, \(d5,x\)
+ c: f6 8e cmp d6, \(d6,x\)
+ e: f7 8f cmp d7, \(d7,x\)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rdirect.s b/gas/testsuite/gas/s12z/cmp-opr-rdirect.s
new file mode 100644
index 0000000..ff5dcbc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rdirect.s
@@ -0,0 +1,9 @@
+;;; Direct register offset
+ cmp d2, (d1,s)
+ cmp d3, (d2,x)
+ cmp d4, (d3,x)
+ cmp d5, (d3,y)
+ cmp d0, (d4,x)
+ cmp d1, (d5,x)
+ cmp d6, (d6,x)
+ cmp d7, (d7,x)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-reg.d b/gas/testsuite/gas/s12z/cmp-opr-reg.d
new file mode 100644
index 0000000..cff87d3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-reg.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: cmp-opr-reg.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: f0 b8 cmp d2, d2
+ 2: f1 b9 cmp d3, d3
+ 4: f2 ba cmp d4, d4
+ 6: f3 bb cmp d5, d5
+ 8: f4 bc cmp d0, d0
+ a: f5 bd cmp d1, d1
+ c: f6 be cmp d6, d6
+ e: f7 bf cmp d7, d7
diff --git a/gas/testsuite/gas/s12z/cmp-opr-reg.s b/gas/testsuite/gas/s12z/cmp-opr-reg.s
new file mode 100644
index 0000000..75bb440
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-reg.s
@@ -0,0 +1,9 @@
+;; Register as operand
+ cmp d2, d2
+ cmp d3, d3
+ cmp d4, d4
+ cmp d5, d5
+ cmp d0, d0
+ cmp d1, d1
+ cmp d6, d6
+ cmp d7, d7
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rindirect.d b/gas/testsuite/gas/s12z/cmp-opr-rindirect.d
new file mode 100644
index 0000000..7c1108f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rindirect.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: cmp-opr-rindirect.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: f0 dd cmp d2, \[d1,y\]
+ 2: f1 dd cmp d3, \[d1,y\]
+ 4: f2 dc cmp d4, \[d0,y\]
+ 6: f3 dc cmp d5, \[d0,y\]
+ 8: f4 ce cmp d0, \[d6,x\]
+ a: f5 ce cmp d1, \[d6,x\]
+ c: f6 ce cmp d6, \[d6,x\]
+ e: f7 cf cmp d7, \[d7,x\]
diff --git a/gas/testsuite/gas/s12z/cmp-opr-rindirect.s b/gas/testsuite/gas/s12z/cmp-opr-rindirect.s
new file mode 100644
index 0000000..27ac5fb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-rindirect.s
@@ -0,0 +1,9 @@
+;;; Indirect register offset
+ cmp d2, [d1,y]
+ cmp d3, [d1,y]
+ cmp d4, [d0,y]
+ cmp d5, [d0,y]
+ cmp d0, [d6,x]
+ cmp d1, [d6,x]
+ cmp d6, [d6,x]
+ cmp d7, [d7,x]
diff --git a/gas/testsuite/gas/s12z/cmp-opr-sxe4.d b/gas/testsuite/gas/s12z/cmp-opr-sxe4.d
new file mode 100644
index 0000000..5eac2fd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-sxe4.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: cmp-opr-sxe4.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: e0 ff ff cmp d2, #-1
+ 3: e1 00 01 cmp d3, #1
+ 6: e2 00 02 cmp d4, #2
+ 9: e3 00 03 cmp d5, #3
+ c: e4 0e cmp d0, #14
+ e: e5 0f cmp d1, #15
+ 10: e6 00 00 00 cmp d6, #4
+ 14: 04
+ 15: e7 00 00 00 cmp d7, #10
+ 19: 0a
diff --git a/gas/testsuite/gas/s12z/cmp-opr-sxe4.s b/gas/testsuite/gas/s12z/cmp-opr-sxe4.s
new file mode 100644
index 0000000..7b3d113
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-sxe4.s
@@ -0,0 +1,10 @@
+;; Short immediate forms
+ cmp d2, #-1
+ cmp d3, #1
+ cmp d4, #2
+ cmp d5, #3
+ cmp d0, #14
+ cmp d1, #15
+ cmp d6, #4
+ cmp d7, #10
+
diff --git a/gas/testsuite/gas/s12z/cmp-opr-xys.d b/gas/testsuite/gas/s12z/cmp-opr-xys.d
new file mode 100644
index 0000000..87d065f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-xys.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: cmp-opr-xys.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: f0 61 cmp d2, \(1,s\)
+ 2: f1 42 cmp d3, \(2,x\)
+ 4: f2 43 cmp d4, \(3,x\)
+ 6: f3 53 cmp d5, \(3,y\)
+ 8: f4 44 cmp d0, \(4,x\)
+ a: f5 45 cmp d1, \(5,x\)
+ c: f6 46 cmp d6, \(6,x\)
+ e: f7 47 cmp d7, \(7,x\)
diff --git a/gas/testsuite/gas/s12z/cmp-opr-xys.s b/gas/testsuite/gas/s12z/cmp-opr-xys.s
new file mode 100644
index 0000000..929bb08
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-opr-xys.s
@@ -0,0 +1,9 @@
+;; Constant offset from xys
+ cmp d2, (1,s)
+ cmp d3, (2,x)
+ cmp d4, (3,x)
+ cmp d5, (3,y)
+ cmp d0, (4,x)
+ cmp d1, (5,x)
+ cmp d6, (6,x)
+ cmp d7, (7,x)
diff --git a/gas/testsuite/gas/s12z/cmp-s-imm.d b/gas/testsuite/gas/s12z/cmp-s-imm.d
new file mode 100644
index 0000000..d4e7efb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-imm.d
@@ -0,0 +1,27 @@
+#objdump: -d
+#name:
+#source: cmp-s-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 04 00 00 cmp s, #0
+ 4: 00
+ 5: 1b 02 71 cmp s, #1
+ 8: 1b 02 70 cmp s, #-1
+ b: 1b 04 00 00 cmp s, #255
+ f: ff
+ 10: 1b 04 ff ff cmp s, #-256
+ 14: 00
+ 15: 1b 04 00 7f cmp s, #32767
+ 19: ff
+ 1a: 1b 04 ff 80 cmp s, #-32768
+ 1e: 00
+ 1f: 1b 04 07 ff cmp s, #524287
+ 23: ff
+ 24: 1b 04 f8 00 cmp s, #-524288
+ 28: 00
diff --git a/gas/testsuite/gas/s12z/cmp-s-imm.s b/gas/testsuite/gas/s12z/cmp-s-imm.s
new file mode 100644
index 0000000..e873d82
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-imm.s
@@ -0,0 +1,10 @@
+ cmp s, #0
+ cmp s, #1
+ cmp s, #-1
+ cmp s, #255
+ cmp s, #-256
+ cmp s, #32767
+ cmp s, #-32768
+ cmp s, #524287
+ cmp s, #-524288
+
diff --git a/gas/testsuite/gas/s12z/cmp-s-opr.d b/gas/testsuite/gas/s12z/cmp-s-opr.d
new file mode 100644
index 0000000..77d2ac7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-opr.d
@@ -0,0 +1,25 @@
+#objdump: -d
+#name:
+#source: cmp-s-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 02 e0 43 cmp s, \(67,s\)
+ 4: 1b 02 e3 cmp s, \(\+x\)
+ 7: 1b 02 8c cmp s, \(d0,x\)
+ a: 1b 02 dd cmp s, \[d1,y\]
+ d: 1b 02 f2 00 cmp s, \(2134,p\)
+ 11: 08 56
+ 13: 1b 02 f6 00 cmp s, \[2134,p\]
+ 17: 08 56
+ 19: 1b 02 fa 0f cmp s, 987654
+ 1d: 12 06
+ 1f: 1b 02 e6 08 cmp s, \[565543,s\]
+ 23: a1 27
+ 25: 1b 02 80 04 cmp s, \(1233,d2\)
+ 29: d1
diff --git a/gas/testsuite/gas/s12z/cmp-s-opr.s b/gas/testsuite/gas/s12z/cmp-s-opr.s
new file mode 100644
index 0000000..5deb45a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-s-opr.s
@@ -0,0 +1,10 @@
+ cmp s, (67,s)
+ cmp s, (+x)
+ cmp s, (d0,x)
+ cmp s, [d1,y]
+ cmp s, (2134,p)
+ cmp s, [2134,p]
+ cmp s, 987654
+ cmp s, [565543,s]
+ cmp s, (1233, d2)
+
diff --git a/gas/testsuite/gas/s12z/cmp-xy.d b/gas/testsuite/gas/s12z/cmp-xy.d
new file mode 100644
index 0000000..9fef4e1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-xy.d
@@ -0,0 +1,12 @@
+#objdump: -d
+#name:
+#source: cmp-xy.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: fc cmp x, y
diff --git a/gas/testsuite/gas/s12z/cmp-xy.s b/gas/testsuite/gas/s12z/cmp-xy.s
new file mode 100644
index 0000000..dcfd47c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/cmp-xy.s
@@ -0,0 +1 @@
+ cmp x, y
diff --git a/gas/testsuite/gas/s12z/com-opr.d b/gas/testsuite/gas/s12z/com-opr.d
new file mode 100644
index 0000000..ce51785
--- /dev/null
+++ b/gas/testsuite/gas/s12z/com-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: com-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: cc df com.b \[d7,y\]
+ 2: cd fe 00 1f com.w \[8134\]
+ 6: c6
+ 7: cf ae com.l \(d6,s\)
diff --git a/gas/testsuite/gas/s12z/com-opr.s b/gas/testsuite/gas/s12z/com-opr.s
new file mode 100644
index 0000000..5eb2760
--- /dev/null
+++ b/gas/testsuite/gas/s12z/com-opr.s
@@ -0,0 +1,3 @@
+ com.b [d7, y]
+ com.w [8134]
+ com.l (d6, s)
diff --git a/gas/testsuite/gas/s12z/complex-shifts.d b/gas/testsuite/gas/s12z/complex-shifts.d
new file mode 100644
index 0000000..e17fe90
--- /dev/null
+++ b/gas/testsuite/gas/s12z/complex-shifts.d
@@ -0,0 +1,18 @@
+#objdump: -d
+#name:
+#source: complex-shifts.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 14 73 e3 e6 lsl.l d0, \(\+x\), \[345,s\]
+ 4: 00 01 59
+ 7: 13 32 8e fb lsr.p d5, \(d6,x\), \(-s\)
+ b: 17 f1 f4 2d asl.w d7, \[45,p\], \(278,y\)
+ f: d2 00 01 16
+ 13: 12 b0 84 00 asr.b d4, \(145,d0\), \(d0,s\)
+ 17: 91 ac
diff --git a/gas/testsuite/gas/s12z/complex-shifts.s b/gas/testsuite/gas/s12z/complex-shifts.s
new file mode 100644
index 0000000..118296e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/complex-shifts.s
@@ -0,0 +1,4 @@
+ lsl.l d0, (+x), [345, s]
+ lsr.p d5, (d6,x), (-s)
+ asl.w d7, [45,p], (278, y)
+ asr.b d4, (145,d0), (d0,s)
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-opr.d b/gas/testsuite/gas/s12z/db-tb-cc-opr.d
new file mode 100644
index 0000000..ee556e2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-opr.d
@@ -0,0 +1,30 @@
+#objdump: -d
+#name:
+#source: db-tb-cc-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0b dc 82 00 dble.b \(3,d4\), \*\+1
+ 4: 03 01
+ 6: 0b cd 83 00 dbgt.w \(23,d5\), \*\+18
+ a: 17 12
+ c: 0b de 84 00 dble.p \(2,d0\), \*-19
+ 10: 02 6d
+ 12: 0b bf fb ff dbmi.l \(-s\), \*-137
+ 16: 77
+ 17: 0b 3c e4 22 tbmi.b \[34,s\], \*\+43
+ 1b: 2b
+ 1c: 0b 4d ff 5f tbgt.w \(s\+\), \*-33
+ 20: 0b 1e c4 ea tbeq.p \[234,x\], \*-134
+ 24: ff 7a
+ 26: 0b 5f f0 22 tble.l \(34,p\), \*\+331
+ 2a: 81 4b
+ 2c: 0b 0c 5e 81 tbne.b \(14,y\), \*\+431
+ 30: af
+ 31: 0b 2e 4e 80 tbpl.p \(14,x\), \*\+231
+ 35: e7 \ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-opr.s b/gas/testsuite/gas/s12z/db-tb-cc-opr.s
new file mode 100644
index 0000000..a79cbde
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-opr.s
@@ -0,0 +1,11 @@
+ dble.b (3,d4), *+1
+ dbgt.w (23,d5), *+18
+ dble.p (2,d0), *-19
+ dbmi.l (-s), *-137
+ tbmi.b [34,s], *+43
+ tbgt.w (s+), *-33
+ tbeq.p [234,x], *-134
+ tble.l (34, p), *+331
+ tbne.b (14, y), *+431
+ tbpl.p (14, x), *+231
+
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-reg.d b/gas/testsuite/gas/s12z/db-tb-cc-reg.d
new file mode 100644
index 0000000..54ea832
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-reg.d
@@ -0,0 +1,31 @@
+#objdump: -d
+#name:
+#source: db-tb-cc-reg.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0b 84 0c dbne d0, \*\+12
+ 3: 0b 95 0d dbeq d1, \*\+13
+ 6: 0b a8 72 dbpl x, \*-14
+ 9: 0b b9 0f dbmi y, \*\+15
+ c: 0b c1 80 7b dbgt d3, \*\+123
+ 10: 0b d7 fb 1f dble d7, \*-1249
+ 14: 0b 04 16 tbne d0, \*\+22
+ 17: 0b 15 17 tbeq d1, \*\+23
+ 1a: 0b 28 18 tbpl x, \*\+24
+ 1d: 0b 39 19 tbmi y, \*\+25
+ 20: 0b 41 80 df tbgt d3, \*\+223
+ 24: 0b 57 88 c9 tble d7, \*\+2249
+ 28: 0b 39 28 tbmi y, \*\+40
+ 2b: 0b 84 ff 75 dbne d0, \*-139
+ 2f: 0b a5 04 dbpl d1, \*\+4
+ 32: 0b c2 ff 76 dbgt d4, \*-138
+ 36: 0b 90 29 dbeq d2, \*\+41
+ 39: 0b 06 04 tbne d6, \*\+4
+ 3c: 0b 27 ff 78 tbpl d7, \*-136
+ 40: 0b 18 28 tbeq x, \*\+40
diff --git a/gas/testsuite/gas/s12z/db-tb-cc-reg.s b/gas/testsuite/gas/s12z/db-tb-cc-reg.s
new file mode 100644
index 0000000..524f4d0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/db-tb-cc-reg.s
@@ -0,0 +1,21 @@
+ dbne d0, *+12
+ dbeq d1, *+13
+ dbpl x, *-14
+ dbmi y, *+15
+ dbgt d3, *+123
+ dble d7, *-1249
+ tbne d0, *+22
+ tbeq d1, *+23
+ tbpl x, *+24
+ tbmi y, *+25
+ tbgt d3, *+223
+ tble d7, *+2249
+ tbmi y, *+40
+ dbne d0, *-139
+ dbpl d1, *+4
+ dbgt d4, *-138
+ dbeq d2, *+41
+ tbne d6, *+4
+ tbpl d7, *-136
+ tbeq x, *+40
+
diff --git a/gas/testsuite/gas/s12z/dbCC.d b/gas/testsuite/gas/s12z/dbCC.d
new file mode 100644
index 0000000..87dd7fc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dbCC.d
@@ -0,0 +1,27 @@
+#objdump: -dt
+#name:
+#source: dbCC.s
+
+
+dump.o: file format elf32-s12z
+
+SYMBOL TABLE:
+00000000 l d .text 00000000 .text
+00000000 l d .data 00000000 .data
+00000000 l d .bss 00000000 .bss
+00000001 l .text 00000000 foo
+
+
+
+Disassembly of section .text:
+
+00000000 <foo-0x1>:
+ 0: 01 nop
+
+00000001 <foo>:
+ 1: 01 nop
+ 2: 0b 84 ff ff dbne d0, foo
+ 6: 0b 88 ff fb dbne x, foo
+ a: 0b 89 ff f7 dbne y, foo
+ e: 0b 8c f3 ff dbne.b \(\+y\), foo
+ 12: f3
diff --git a/gas/testsuite/gas/s12z/dbCC.s b/gas/testsuite/gas/s12z/dbCC.s
new file mode 100644
index 0000000..3a637e7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dbCC.s
@@ -0,0 +1,7 @@
+ nop
+foo:
+ nop
+ dbne d0, foo
+ dbne x, foo
+ dbne y, foo
+ dbne.b (+y), foo
diff --git a/gas/testsuite/gas/s12z/dec-opr.d b/gas/testsuite/gas/s12z/dec-opr.d
new file mode 100644
index 0000000..4f49088
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: dec-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: ac ca dec.b \[d4,x\]
+ 2: ad fe 00 00 dec.w \[134\]
+ 6: 86
+ 7: af ad dec.l \(d1,s\)
diff --git a/gas/testsuite/gas/s12z/dec-opr.s b/gas/testsuite/gas/s12z/dec-opr.s
new file mode 100644
index 0000000..2f54a4c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec-opr.s
@@ -0,0 +1,3 @@
+ dec.b [d4, x]
+ dec.w [134]
+ dec.l (d1, s)
diff --git a/gas/testsuite/gas/s12z/dec.d b/gas/testsuite/gas/s12z/dec.d
new file mode 100644
index 0000000..74a2c3e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: dec.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: 40 dec d2
+ 1: 41 dec d3
+ 2: 42 dec d4
+ 3: 43 dec d5
+ 4: 44 dec d0
+ 5: 45 dec d1
+ 6: 46 dec d6
+ 7: 47 dec d7
diff --git a/gas/testsuite/gas/s12z/dec.s b/gas/testsuite/gas/s12z/dec.s
new file mode 100644
index 0000000..1280bf4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/dec.s
@@ -0,0 +1,8 @@
+L1: dec d2
+ dec d3
+ dec d4
+ dec d5
+ dec d0
+ dec d1
+ dec d6
+ dec d7
diff --git a/gas/testsuite/gas/s12z/div.d b/gas/testsuite/gas/s12z/div.d
new file mode 100644
index 0000000..3569519
--- /dev/null
+++ b/gas/testsuite/gas/s12z/div.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: div.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 34 ec 62 divs.b d0, d1, #98
+ 4: 1b 35 c0 b9 divs.b d1, d2, d3
+ 8: 1b 30 c9 ba divs.w d2, d3, d4
+ c: 1b 31 ff 00 divs.l d3, d7, #9842
+ 10: 00 26 72
+ 13: 1b 32 68 e0 divu.b d4, d1, \(32,s\)
+ 17: 20
+ 18: 1b 33 49 c4 divu.w d5, d3, \[34,x\]
+ 1c: 22
+ 1d: 1b 36 7b ff divu.l d6, d7, \(s\+\)
+ 21: 1b 37 7a d4 divu.lp d7, \[12,y\], \(7,d1\)
+ 25: 0c 85 00 07
diff --git a/gas/testsuite/gas/s12z/div.s b/gas/testsuite/gas/s12z/div.s
new file mode 100644
index 0000000..edd7990
--- /dev/null
+++ b/gas/testsuite/gas/s12z/div.s
@@ -0,0 +1,8 @@
+ divs.b d0, d1, #98
+ divs.b d1, d2, d3
+ divs.w d2, d3, d4
+ divs.l d3, d7, #9842
+ divu.b d4, d1, (32,s)
+ divu.w d5, d3, [34,x]
+ divu.l d6, d7, (s+)
+ divu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/eor.d b/gas/testsuite/gas/s12z/eor.d
new file mode 100644
index 0000000..f829a52
--- /dev/null
+++ b/gas/testsuite/gas/s12z/eor.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name:
+#source: eor.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 78 fc 84 eor d2, #-892
+ 4: 1b 79 ef 32 eor d3, #-4302
+ 8: 1b 7f 00 01 eor d7, #123456
+ c: e2 40
+ e: 1b 7b 04 d2 eor d5, #1234
+ 12: 1b 7c 7b eor d0, #123
+ 15: 1b 7d 22 eor d1, #34
+ 18: 1b 7e ff ff eor d6, #-56789
+ 1c: 22 2b
+ 1e: 1b 7a 22 3d eor d4, #8765
+ 22: 1b 8c d5 21 eor d0, \[-223,y\]
+ 26: 1b 8d f2 00 eor d1, \(34000,p\)
+ 2a: 84 d0
+ 2c: 1b 88 fb eor d2, \(-s\)
+ 2f: 1b 79 00 04 eor d3, #4
+ 33: 1b 8a bc eor d4, d0
+ 36: 1b 8b f9 4c eor d5, 85178
+ 3a: ba
+ 3b: 1b 8e fe 00 eor d6, \[15256\]
+ 3f: 3b 98
+ 41: 1b 8f 8b eor d7, \(d5,x\)
+ 44: 1b 89 f7 eor d3, \(y\+\)
diff --git a/gas/testsuite/gas/s12z/eor.s b/gas/testsuite/gas/s12z/eor.s
new file mode 100644
index 0000000..cc4985a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/eor.s
@@ -0,0 +1,17 @@
+ eor d2, #-892
+ eor d3, #-4302
+ eor d7, #123456
+ eor d5, #1234
+ eor d0, #123
+ eor d1, #34
+ eor d6, #-56789
+ eor d4, #8765
+ eor d0, [-223,y]
+ eor d1, (34000, p)
+ eor d2, (-s)
+ eor d3, #4
+ eor d4, d0
+ eor d5, 85178
+ eor d6, [15256]
+ eor d7, (d5, x)
+ eor d3, (y+)
diff --git a/gas/testsuite/gas/s12z/exg.d b/gas/testsuite/gas/s12z/exg.d
new file mode 100644
index 0000000..58e4ae7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/exg.d
@@ -0,0 +1,29 @@
+#objdump: -d
+#name:
+#source: exg.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: ae 45 exg d0, d1
+ 2: ae 55 exg d1, d1
+ 4: ae 05 exg d2, d1
+ 6: ae 15 exg d3, d1
+ 8: ae 25 exg d4, d1
+ a: ae 35 exg d5, d1
+ c: ae 65 exg d6, d1
+ e: ae 75 exg d7, d1
+ 10: ae 85 exg x, d1
+ 12: ae 95 exg y, d1
+ 14: ae c5 exg cch, d1
+ 16: ae d5 exg ccl, d1
+ 18: ae e5 exg ccw, d1
+ 1a: ae 68 exg d6, x
+ 1c: ae 79 exg d7, y
+ 1e: ae 8e exg x, ccw
+ 20: ae 97 sex y, d7
+ 22: ae cd exg cch, ccl
diff --git a/gas/testsuite/gas/s12z/exg.s b/gas/testsuite/gas/s12z/exg.s
new file mode 100644
index 0000000..55ce301
--- /dev/null
+++ b/gas/testsuite/gas/s12z/exg.s
@@ -0,0 +1,18 @@
+ exg d0, d1
+ exg d1, d1
+ exg d2, d1
+ exg d3, d1
+ exg d4, d1
+ exg d5, d1
+ exg d6, d1
+ exg d7, d1
+ exg x, d1
+ exg y, d1
+ exg cch, d1
+ exg ccl, d1
+ exg ccw, d1
+ exg d6, x
+ exg d7, y
+ exg x, ccw
+ sex y, d7
+ exg cch, ccl
diff --git a/gas/testsuite/gas/s12z/ext24-ld-xy.d b/gas/testsuite/gas/s12z/ext24-ld-xy.d
new file mode 100644
index 0000000..a3f075f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ext24-ld-xy.d
@@ -0,0 +1,12 @@
+#objdump: -d
+#name:
+#source: ext24-ld-xy.s
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: b8 74 cb b1 ld x, 7654321
+ 4: b9 63 d7 6a ld y, 6543210
diff --git a/gas/testsuite/gas/s12z/ext24-ld-xy.s b/gas/testsuite/gas/s12z/ext24-ld-xy.s
new file mode 100644
index 0000000..2b262f0
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ext24-ld-xy.s
@@ -0,0 +1,2 @@
+ .long 0xB874CBB1 ;; LD X,7654321
+ .long 0xB963D76A ;; LD Y,6543210
diff --git a/gas/testsuite/gas/s12z/inc-opr.d b/gas/testsuite/gas/s12z/inc-opr.d
new file mode 100644
index 0000000..d013d6a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc-opr.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: inc-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 9c 88 inc.b \(d2,x\)
+ 2: 9d fe 00 04 inc.w \[1234\]
+ 6: d2
+ 7: 9f 88 inc.l \(d2,x\)
diff --git a/gas/testsuite/gas/s12z/inc-opr.s b/gas/testsuite/gas/s12z/inc-opr.s
new file mode 100644
index 0000000..1876082
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc-opr.s
@@ -0,0 +1,3 @@
+ inc.b (d2, x)
+ inc.w [1234]
+ inc.l (d2, x)
diff --git a/gas/testsuite/gas/s12z/inc.d b/gas/testsuite/gas/s12z/inc.d
new file mode 100644
index 0000000..51b912b
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: inc.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: 30 inc d2
+ 1: 31 inc d3
+ 2: 32 inc d4
+ 3: 33 inc d5
+ 4: 34 inc d0
+ 5: 35 inc d1
+ 6: 36 inc d6
+ 7: 37 inc d7
diff --git a/gas/testsuite/gas/s12z/inc.s b/gas/testsuite/gas/s12z/inc.s
new file mode 100644
index 0000000..89e0b97
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inc.s
@@ -0,0 +1,8 @@
+L1: inc d2
+ inc d3
+ inc d4
+ inc d5
+ inc d0
+ inc d1
+ inc d6
+ inc d7
diff --git a/gas/testsuite/gas/s12z/inh.d b/gas/testsuite/gas/s12z/inh.d
new file mode 100644
index 0000000..4f437f1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inh.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: inh.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: ff swi
+ 1: 05 rts
+ 2: 00 bgnd
+ 3: 01 nop
diff --git a/gas/testsuite/gas/s12z/inh.s b/gas/testsuite/gas/s12z/inh.s
new file mode 100644
index 0000000..22b2858
--- /dev/null
+++ b/gas/testsuite/gas/s12z/inh.s
@@ -0,0 +1,5 @@
+ swi
+ rts
+ bgnd
+ nop
+
diff --git a/gas/testsuite/gas/s12z/jmp.d b/gas/testsuite/gas/s12z/jmp.d
new file mode 100644
index 0000000..12ff350
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jmp.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name: JMP instruction
+#source: jmp.s
+
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: aa bb jmp d5
+ 2: aa 4c jmp \(12,x\)
+ 4: aa f3 jmp \(\+y\)
+ 6: aa d3 jmp \(-y\)
+ 8: aa f7 jmp \(y\+\)
+ a: aa d7 jmp \(y-\)
+ c: aa e3 jmp \(\+x\)
+ e: aa c3 jmp \(-x\)
+ 10: aa e7 jmp \(x\+\)
+ 12: aa c7 jmp \(x-\)
+ 14: aa fb jmp \(-s\)
+ 16: aa ff jmp \(s\+\)
+ 18: aa ab jmp \(d5,s\)
+ 1a: aa 87 00 5a jmp \(90,d7\)
+ 1e: aa f0 5a jmp \(90,p\)
+ 21: aa d4 2d jmp \[45,y\]
+ 24: aa 00 10 jmp 16
+ 27: aa 37 f1 jmp 14321
+ 2a: aa f9 be 91 jmp 114321
+ 2e: aa fe 06 98 jmp \[432134\]
+ 32: 06
diff --git a/gas/testsuite/gas/s12z/jmp.s b/gas/testsuite/gas/s12z/jmp.s
new file mode 100644
index 0000000..fa4321d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jmp.s
@@ -0,0 +1,20 @@
+ jmp d5
+ jmp (12, x)
+ jmp (+y)
+ jmp (-y)
+ jmp (y+)
+ jmp (y-)
+ jmp (+x)
+ jmp (-x)
+ jmp (x+)
+ jmp (x-)
+ jmp (-s)
+ jmp (s+)
+ jmp (d5,s)
+ jmp (90,d7)
+ jmp (90,p)
+ jmp [45,y]
+ jmp 16
+ jmp 14321
+ jmp 114321
+ jmp [432134]
diff --git a/gas/testsuite/gas/s12z/jsr.d b/gas/testsuite/gas/s12z/jsr.d
new file mode 100644
index 0000000..8508a0a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jsr.d
@@ -0,0 +1,33 @@
+#objdump: -d
+#name: JSR instruction
+#source: jsr.s
+
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: ab b8 jsr d2
+ 2: ab 52 jsr \(2,y\)
+ 4: ab f3 jsr \(\+y\)
+ 6: ab d3 jsr \(-y\)
+ 8: ab f7 jsr \(y\+\)
+ a: ab d7 jsr \(y-\)
+ c: ab e3 jsr \(\+x\)
+ e: ab c3 jsr \(-x\)
+ 10: ab e7 jsr \(x\+\)
+ 12: ab c7 jsr \(x-\)
+ 14: ab fb jsr \(-s\)
+ 16: ab ff jsr \(s\+\)
+ 18: ab 89 jsr \(d3,x\)
+ 1a: ab 86 00 1e jsr \(30,d6\)
+ 1e: ab f0 5d jsr \(93,p\)
+ 21: ab d4 2d jsr \[45,y\]
+ 24: ab 00 0c jsr 12
+ 27: ab 0f b5 jsr 4021
+ 2a: ab f9 be 91 jsr 114321
+ 2e: ab fe 07 82 jsr \[492134\]
+ 32: 66
diff --git a/gas/testsuite/gas/s12z/jsr.s b/gas/testsuite/gas/s12z/jsr.s
new file mode 100644
index 0000000..80f0ff1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/jsr.s
@@ -0,0 +1,20 @@
+ jsr d2
+ jsr (2, y)
+ jsr (+y)
+ jsr (-y)
+ jsr (y+)
+ jsr (y-)
+ jsr (+x)
+ jsr (-x)
+ jsr (x+)
+ jsr (x-)
+ jsr (-s)
+ jsr (s+)
+ jsr (d3,x)
+ jsr (30,d6)
+ jsr (93,p)
+ jsr [45,y]
+ jsr 12
+ jsr 4021
+ jsr 114321
+ jsr [492134]
diff --git a/gas/testsuite/gas/s12z/ld-imm-page2.d b/gas/testsuite/gas/s12z/ld-imm-page2.d
new file mode 100644
index 0000000..3f1744f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm-page2.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: ld-imm-page2.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 03 aa bb ld s, #-5588020
+ 4: cc
+ 5: 1b 03 00 30 ld s, #12309
+ 9: 15
diff --git a/gas/testsuite/gas/s12z/ld-imm-page2.s b/gas/testsuite/gas/s12z/ld-imm-page2.s
new file mode 100644
index 0000000..09c735c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm-page2.s
@@ -0,0 +1,2 @@
+ ld s, #-5588020
+ ld s, #12309
diff --git a/gas/testsuite/gas/s12z/ld-imm.d b/gas/testsuite/gas/s12z/ld-imm.d
new file mode 100644
index 0000000..b0e4fcb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm.d
@@ -0,0 +1,25 @@
+#objdump: -d
+#name:
+#source: ld-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <here>:
+ 0: 90 01 23 ld d2, #291
+ 3: 91 01 23 ld d3, #291
+ 6: 92 01 23 ld d4, #291
+ 9: 93 01 23 ld d5, #291
+ c: 94 56 ld d0, #86
+ e: 95 78 ld d1, #120
+ 10: 96 12 34 56 ld d6, #305419896
+ 14: 78
+ 15: 97 12 34 56 ld d7, #305419896
+ 19: 78
+ 1a: 98 ab cd ef ld x, #-5517841
+ 1e: 99 fe dc ba ld y, #-74566
+ 22: 98 00 cd ef ld x, #52719
+ 26: 99 00 dc ba ld y, #56506
diff --git a/gas/testsuite/gas/s12z/ld-imm.s b/gas/testsuite/gas/s12z/ld-imm.s
new file mode 100644
index 0000000..569123d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-imm.s
@@ -0,0 +1,16 @@
+here: ld d2, #0x0123
+ ld d3, #0x0123
+ ld d4, #0x0123
+ ld d5, #0x0123
+ ld d0, #0x56
+ ld d1, #0x78
+ ld d6, #0x12345678
+ ld d7, #0x12345678
+
+ ld x, #-5517841
+ ld y, #-74566
+
+
+ ;; The following two can be encoded using {CDEF}{AB}
+ ld x, #0xcdef
+ ld y, #0xdcba
diff --git a/gas/testsuite/gas/s12z/ld-immu18.d b/gas/testsuite/gas/s12z/ld-immu18.d
new file mode 100644
index 0000000..ba071df
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-immu18.d
@@ -0,0 +1,28 @@
+#objdump: -d
+#name:
+#source: ld-immu18.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 00 bgnd
+ 1: ca ff ee ld x, #65518
+ 4: 00 bgnd
+ 5: cb df e4 ld y, #57316
+ 8: 00 bgnd
+ 9: da f0 ea ld x, #127210
+ c: 00 bgnd
+ d: db 7f 6e ld y, #98158
+ 10: 00 bgnd
+ 11: ea 6f ea ld x, #159722
+ 14: 00 bgnd
+ 15: eb 7f 9e ld y, #163742
+ 18: 00 bgnd
+ 19: fa 1f ca ld x, #204746
+ 1c: 00 bgnd
+ 1d: fb 7f 0e ld y, #229134
+ 20: 01 nop
diff --git a/gas/testsuite/gas/s12z/ld-immu18.s b/gas/testsuite/gas/s12z/ld-immu18.s
new file mode 100644
index 0000000..563765e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-immu18.s
@@ -0,0 +1,10 @@
+ .long 0xCAFFEE
+ .long 0xCBDFE4
+ .long 0xDAF0EA
+ .long 0xDB7F6E
+ .long 0xEA6FEA
+ .long 0xEB7F9E
+ .long 0xFA1FCA
+ .long 0xFB7F0E
+ nop
+
diff --git a/gas/testsuite/gas/s12z/ld-large-direct.d b/gas/testsuite/gas/s12z/ld-large-direct.d
new file mode 100644
index 0000000..c17f1c9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-large-direct.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name: LD reg - conldant optimised to EXT24
+#source: ld-large-direct.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: b0 12 34 56 ld d2, 1193046
+ 4: b1 c0 ff ee ld d3, 12648430
+ 8: b2 80 00 02 ld d4, 8388610
+ c: b4 80 00 03 ld d0, 8388611
+ 10: b5 80 00 03 ld d1, 8388611
+ 14: b3 80 00 04 ld d5, 8388612
+ 18: b6 80 00 06 ld d6, 8388614
+ 1c: b7 80 00 07 ld d7, 8388615
+ 20: b8 80 00 08 ld x, 8388616
+ 24: b9 80 00 09 ld y, 8388617
diff --git a/gas/testsuite/gas/s12z/ld-large-direct.s b/gas/testsuite/gas/s12z/ld-large-direct.s
new file mode 100644
index 0000000..4c53f2a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-large-direct.s
@@ -0,0 +1,11 @@
+ ld d2, 0x123456
+ ld d3, 0xc0ffee
+ ld d4, 0x800002
+ ld d0, 0x800003
+ ld d1, 0x800003
+ ld d5, 0x800004
+ ld d6, 0x800006
+ ld d7, 0x800007
+ ld x, 0x800008
+ ld y, 0x800009
+
diff --git a/gas/testsuite/gas/s12z/ld-opr.d b/gas/testsuite/gas/s12z/ld-opr.d
new file mode 100644
index 0000000..c0a8ec2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:
+#source: ld-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: a4 dc ld d0, \[d0,y\]
+ 2: a5 cd ld d1, \[d1,x\]
+ 4: a0 cd ld d2, \[d1,x\]
+ 6: a1 80 04 d2 ld d3, \(1234,d2\)
+ a: a2 e2 ff fb ld d4, \(-1234,s\)
+ e: 2e
+ f: a3 bf ld d5, d7
+ 11: a6 88 ld d6, \(d2,x\)
+ 13: a7 d9 ld d7, \[d3,y\]
+ 15: a8 ac ld x, \(d0,s\)
+ 17: a9 cd ld y, \[d1,x\]
diff --git a/gas/testsuite/gas/s12z/ld-opr.s b/gas/testsuite/gas/s12z/ld-opr.s
new file mode 100644
index 0000000..ee452e9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-opr.s
@@ -0,0 +1,10 @@
+ ld d0, [d0,y]
+ ld d1, [d1,x]
+ ld d2, [d1, x]
+ ld d3, (1234,d2)
+ ld d4, (-1234,s)
+ ld d5, d7
+ ld d6, (d2, x)
+ ld d7, [d3, y]
+ ld x, (d0, s)
+ ld y, [d1, x]
diff --git a/gas/testsuite/gas/s12z/ld-s-opr.d b/gas/testsuite/gas/s12z/ld-s-opr.d
new file mode 100644
index 0000000..085ebfb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-s-opr.d
@@ -0,0 +1,16 @@
+#objdump: -d
+#name:
+#source: ld-s-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 00 df ld s, \[d7,y\]
+ 3: 1b 00 fe 00 ld s, \[8134\]
+ 7: 1f c6
+ 9: 1b 00 ae ld s, \(d6,s\)
+ c: 1b 00 fb ld s, \(-s\)
diff --git a/gas/testsuite/gas/s12z/ld-s-opr.s b/gas/testsuite/gas/s12z/ld-s-opr.s
new file mode 100644
index 0000000..41ee23e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-s-opr.s
@@ -0,0 +1,4 @@
+ ld s, [d7, y]
+ ld s, [8134]
+ ld s, (d6, s)
+ ld s, (-s)
diff --git a/gas/testsuite/gas/s12z/ld-small-direct.d b/gas/testsuite/gas/s12z/ld-small-direct.d
new file mode 100644
index 0000000..e6cffd2
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-small-direct.d
@@ -0,0 +1,31 @@
+#objdump: -d
+#name: LD reg - small constants left in OPR mode
+#source: ld-small-direct.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: a0 fa 00 00 ld d2, L1
+ 4: 00
+ 5: a1 fa 00 00 ld d3, 25
+ 9: 19
+ a: a2 fa 00 00 ld d4, L1
+ e: 00
+
+0000000f <L3>:
+ f: a4 fa 00 00 ld d0, 25
+ 13: 19
+ 14: a5 fa 00 00 ld d1, L3
+ 18: 0f
+ 19: a3 fa 00 00 ld d5, L1
+ 1d: 00
+ 1e: a6 fa 00 00 ld d6, L3
+ 22: 0f
+ 23: a7 fa 00 00 ld d7, 25
+ 27: 19
+ 28: a8 30 39 ld x, 12345
+ 2b: a9 26 94 ld y, 9876
diff --git a/gas/testsuite/gas/s12z/ld-small-direct.s b/gas/testsuite/gas/s12z/ld-small-direct.s
new file mode 100644
index 0000000..5d9ea6d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/ld-small-direct.s
@@ -0,0 +1,11 @@
+L1: ld d2, L1
+ ld d3, .L2
+ ld d4, L1
+L3: ld d0, .L2
+ ld d1, L3
+.L2: ld d5, L1
+ ld d6, L3
+ ld d7, .L2
+ ld x, 12345
+ ld y, 9876
+
diff --git a/gas/testsuite/gas/s12z/lea-immu18.d b/gas/testsuite/gas/s12z/lea-immu18.d
new file mode 100644
index 0000000..3088b41
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea-immu18.d
@@ -0,0 +1,14 @@
+#objdump: -d
+#name:
+#source: lea-immu18.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 18 55 lea x, \(85,x\)
+ 2: 19 aa lea y, \(-86,y\)
+ 4: 1a 12 lea s, \(18,s\)
diff --git a/gas/testsuite/gas/s12z/lea-immu18.s b/gas/testsuite/gas/s12z/lea-immu18.s
new file mode 100644
index 0000000..b003922
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea-immu18.s
@@ -0,0 +1,3 @@
+ .short 0x1855
+ .short 0x19AA
+ .short 0x1A12
diff --git a/gas/testsuite/gas/s12z/lea.d b/gas/testsuite/gas/s12z/lea.d
new file mode 100644
index 0000000..30722a5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea.d
@@ -0,0 +1,18 @@
+#objdump: -d
+#name:
+#source: lea.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0a 44 lea s, \(4,x\)
+ 2: 06 c0 7b lea d6, \(123,x\)
+ 5: 07 d1 16 lea d7, \(-234,y\)
+ 8: 08 c1 ea lea x, \(-22,x\)
+ b: 09 d0 16 lea y, \(22,y\)
+ e: 0a e0 16 lea s, \(22,s\)
+ 11: 09 c1 d3 lea y, \(-45,x\)
diff --git a/gas/testsuite/gas/s12z/lea.s b/gas/testsuite/gas/s12z/lea.s
new file mode 100644
index 0000000..2d75a93
--- /dev/null
+++ b/gas/testsuite/gas/s12z/lea.s
@@ -0,0 +1,8 @@
+ lea s, (4,x)
+ lea d6, (123,x)
+ lea d7, (-234,y)
+ lea x, (-22,x)
+ lea y, (22,y)
+ lea s, (22,s)
+ lea y, (-45,x)
+
diff --git a/gas/testsuite/gas/s12z/mac.d b/gas/testsuite/gas/s12z/mac.d
new file mode 100644
index 0000000..d2758b6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mac.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: mac.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 4c ec 62 macs.b d0, d1, #98
+ 4: 1b 4d c0 b9 macs.b d1, d2, d3
+ 8: 1b 48 c9 ba macs.w d2, d3, d4
+ c: 1b 49 ff 00 macs.l d3, d7, #9842
+ 10: 00 26 72
+ 13: 1b 4a 68 e0 macu.b d4, d1, \(32,s\)
+ 17: 20
+ 18: 1b 4b 49 c4 macu.w d5, d3, \[34,x\]
+ 1c: 22
+ 1d: 1b 4e 7b ff macu.l d6, d7, \(s\+\)
+ 21: 1b 4f 7a d4 macu.lp d7, \[12,y\], \(7,d1\)
+ 25: 0c 85 00 07
diff --git a/gas/testsuite/gas/s12z/mac.s b/gas/testsuite/gas/s12z/mac.s
new file mode 100644
index 0000000..8914524
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mac.s
@@ -0,0 +1,8 @@
+ macs.b d0, d1, #98
+ macs.b d1, d2, d3
+ macs.w d2, d3, d4
+ macs.l d3, d7, #9842
+ macu.b d4, d1, (32,s)
+ macu.w d5, d3, [34,x]
+ macu.l d6, d7, (s+)
+ macu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/min-max.d b/gas/testsuite/gas/s12z/min-max.d
new file mode 100644
index 0000000..f01684a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/min-max.d
@@ -0,0 +1,48 @@
+#objdump: -d
+#name:
+#source: min-max.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 2c fe 01 maxs d0, \[123456\]
+ 4: e2 40
+ 6: 1b 2d c4 04 maxs d1, \[4,x\]
+ a: 1b 28 b8 maxs d2, d2
+ d: 1b 29 dc maxs d3, \[d0,y\]
+ 10: 1b 2a e4 0c maxs d4, \[12,s\]
+ 14: 1b 2b 63 maxs d5, \(3,s\)
+ 17: 1b 2e e1 85 maxs d6, \(-123,s\)
+ 1b: 1b 2f f2 01 maxs d7, \(123987,p\)
+ 1f: e4 53
+ 21: 1b 24 c7 mins d0, \(x-\)
+ 24: 1b 25 d7 mins d1, \(y-\)
+ 27: 1b 20 e7 mins d2, \(x\+\)
+ 2a: 1b 21 f7 mins d3, \(y\+\)
+ 2d: 1b 22 ff mins d4, \(s\+\)
+ 30: 1b 23 e3 mins d5, \(\+x\)
+ 33: 1b 26 f3 mins d6, \(\+y\)
+ 36: 1b 27 c3 mins d7, \(-x\)
+ 39: 1b 1c d3 maxu d0, \(-y\)
+ 3c: 1b 1d fb maxu d1, \(-s\)
+ 3f: 1b 18 8b maxu d2, \(d5,x\)
+ 42: 1b 19 9e maxu d3, \(d6,y\)
+ 45: 1b 1a af maxu d4, \(d7,s\)
+ 48: 1b 1b e2 ff maxu d5, \(-1023,s\)
+ 4c: fc 01
+ 4e: 1b 1e f6 00 maxu d6, \[1087,p\]
+ 52: 04 3f
+ 54: 1b 1f d3 maxu d7, \(-y\)
+ 57: 1b 14 c3 minu d0, \(-x\)
+ 5a: 1b 15 ff minu d1, \(s\+\)
+ 5d: 1b 10 8d minu d2, \(d1,x\)
+ 60: 1b 11 98 minu d3, \(d2,y\)
+ 63: 1b 12 a9 minu d4, \(d3,s\)
+ 66: 1b 13 e1 85 minu d5, \(-123,s\)
+ 6a: 1b 16 f6 01 minu d6, \[123987,p\]
+ 6e: e4 53
+ 70: 1b 17 d7 minu d7, \(y-\)
diff --git a/gas/testsuite/gas/s12z/min-max.s b/gas/testsuite/gas/s12z/min-max.s
new file mode 100644
index 0000000..1b6b9d7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/min-max.s
@@ -0,0 +1,32 @@
+ maxs d0, [123456]
+ maxs d1, [4,x]
+ maxs d2, d2
+ maxs d3, [d0, y]
+ maxs d4, [12,s]
+ maxs d5, (3,s)
+ maxs d6, (-123,s)
+ maxs d7, (123987, p)
+ mins d0, (x-)
+ mins d1, (y-)
+ mins d2, (x+)
+ mins d3, (y+)
+ mins d4, (s+)
+ mins d5, (+x)
+ mins d6, (+y)
+ mins d7, (-x)
+ maxu d0, (-y)
+ maxu d1, (-s)
+ maxu d2, (d5, x)
+ maxu d3, (d6, y)
+ maxu d4, (d7, s)
+ maxu d5, (-1023,s)
+ maxu d6, [1087, p]
+ maxu d7, (-y)
+ minu d0, (-x)
+ minu d1, (s+)
+ minu d2, (d1, x)
+ minu d3, (d2, y)
+ minu d4, (d3, s)
+ minu d5, (-123,s)
+ minu d6, [123987, p]
+ minu d7, (y-)
diff --git a/gas/testsuite/gas/s12z/mod.d b/gas/testsuite/gas/s12z/mod.d
new file mode 100644
index 0000000..34c67dd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mod.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: mod.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 3c ec 62 mods.b d0, d1, #98
+ 4: 1b 3d c0 b9 mods.b d1, d2, d3
+ 8: 1b 38 c9 ba mods.w d2, d3, d4
+ c: 1b 39 ff 00 mods.l d3, d7, #9842
+ 10: 00 26 72
+ 13: 1b 3a 68 e0 modu.b d4, d1, \(32,s\)
+ 17: 20
+ 18: 1b 3b 49 c4 modu.w d5, d3, \[34,x\]
+ 1c: 22
+ 1d: 1b 3e 7b ff modu.l d6, d7, \(s\+\)
+ 21: 1b 3f 7a d4 modu.lp d7, \[12,y\], \(7,d1\)
+ 25: 0c 85 00 07
diff --git a/gas/testsuite/gas/s12z/mod.s b/gas/testsuite/gas/s12z/mod.s
new file mode 100644
index 0000000..c94994a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mod.s
@@ -0,0 +1,8 @@
+ mods.b d0, d1, #98
+ mods.b d1, d2, d3
+ mods.w d2, d3, d4
+ mods.l d3, d7, #9842
+ modu.b d4, d1, (32,s)
+ modu.w d5, d3, [34,x]
+ modu.l d6, d7, (s+)
+ modu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/mov.d b/gas/testsuite/gas/s12z/mov.d
new file mode 100644
index 0000000..e9f4086
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mov.d
@@ -0,0 +1,26 @@
+#objdump: -d
+#name:
+#source: mov.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0c 7b e3 mov.b #123, \(\+x\)
+ 3: 0d 11 70 80 mov.w #4464, \(45,d2\)
+ 7: 00 2d
+ 9: 0e 12 34 56 mov.p #1193046, \[34,s\]
+ d: e4 22
+ f: 0f 12 34 56 mov.l #305419896, \(2234,d7\)
+ 13: 78 87 08 ba
+ 17: 1c 84 00 01 mov.b \(1,d0\), \(2,d1\)
+ 1b: 85 00 02
+ 1e: 1d 82 00 01 mov.w \(1,d4\), \(-s\)
+ 22: fb
+ 23: 1e 83 00 03 mov.p \(3,d5\), \(-x\)
+ 27: c3
+ 28: 1f 87 00 26 mov.l \(38,d7\), \(\+x\)
+ 2c: e3
diff --git a/gas/testsuite/gas/s12z/mov.s b/gas/testsuite/gas/s12z/mov.s
new file mode 100644
index 0000000..35af919
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mov.s
@@ -0,0 +1,8 @@
+ mov.b #123, (+x)
+ mov.w #4464, (45,d2)
+ mov.p #0x123456, [34,s]
+ mov.l #0x12345678, (2234, d7)
+ mov.b (1,d0), (2,d1)
+ mov.w (1,d4), (-s)
+ mov.p (3,d5), (-x)
+ mov.l (38,d7), (+x)
diff --git a/gas/testsuite/gas/s12z/mul-imm.d b/gas/testsuite/gas/s12z/mul-imm.d
new file mode 100644
index 0000000..fdc4e10
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-imm.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: mul-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 4c ec 85 muls.b d0, d1, #-123
+ 3: 4d ed cf c7 muls.w d1, d1, #-12345
+ 7: 48 ef ff ed muls.l d2, d1, #-1234567
+ b: 29 79
+ d: 4c 6c 7b mulu.b d0, d1, #123
+ 10: 4d 6d 30 39 mulu.w d1, d1, #12345
+ 14: 48 6f 00 12 mulu.l d2, d1, #1234567
+ 18: d6 87
diff --git a/gas/testsuite/gas/s12z/mul-imm.s b/gas/testsuite/gas/s12z/mul-imm.s
new file mode 100644
index 0000000..d047934
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-imm.s
@@ -0,0 +1,6 @@
+ muls.b d0, d1, #-123
+ muls.w d1, d1, #-12345
+ muls.l d2, d1, #-1234567
+ mulu.b d0, d1, #123
+ mulu.w d1, d1, #12345
+ mulu.l d2, d1, #1234567
diff --git a/gas/testsuite/gas/s12z/mul-opr-opr.d b/gas/testsuite/gas/s12z/mul-opr-opr.d
new file mode 100644
index 0000000..15bb7a9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr-opr.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: mul-opr-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 4c c2 ff fb muls.bb d0, \(s\+\), \(-s\)
+ 4: 4d 46 e0 2d mulu.bw d1, \(45,s\), \(d0,s\)
+ 8: ac
+ 9: 48 ca e5 d3 muls.bp d2, \[-45,s\], \[1239\]
+ d: fe 00 04 d7
+ 11: 49 4e c5 6f mulu.bl d3, \[-145,x\], \(\+x\)
+ 15: e3
+ 16: 4c d2 e7 d3 muls.wb d0, \(x\+\), \(-y\)
diff --git a/gas/testsuite/gas/s12z/mul-opr-opr.s b/gas/testsuite/gas/s12z/mul-opr-opr.s
new file mode 100644
index 0000000..a253725
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr-opr.s
@@ -0,0 +1,6 @@
+ muls.bb d0, (s+), (-s)
+ mulu.bw d1, (45, s), (d0, s)
+ muls.bp d2, [-45, s], [1239]
+ mulu.bl d3, [-145, x], (+x)
+ muls.wb d0, (x+), (-y)
+
diff --git a/gas/testsuite/gas/s12z/mul-opr.d b/gas/testsuite/gas/s12z/mul-opr.d
new file mode 100644
index 0000000..875ba72
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:
+#source: mul-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 4c e8 70 muls.b d0, d1, #-1
+ 3: 49 f9 fb muls.w d3, d7, \(-s\)
+ 6: 49 fb e3 muls.l d3, d7, \(\+x\)
+ 9: 4a 68 e0 20 mulu.b d4, d1, \(32,s\)
+ d: 4b 49 c4 22 mulu.w d5, d3, \[34,x\]
+ 11: 4e 7b ff mulu.l d6, d7, \(s\+\)
diff --git a/gas/testsuite/gas/s12z/mul-opr.s b/gas/testsuite/gas/s12z/mul-opr.s
new file mode 100644
index 0000000..22e97fb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-opr.s
@@ -0,0 +1,6 @@
+ muls.b d0, d1, #-1
+ muls.w d3, d7, (-s)
+ muls.l d3, d7, (+x)
+ mulu.b d4, d1, (32,s)
+ mulu.w d5, d3, [34,x]
+ mulu.l d6, d7, (s+)
diff --git a/gas/testsuite/gas/s12z/mul-reg.d b/gas/testsuite/gas/s12z/mul-reg.d
new file mode 100644
index 0000000..3f4c84b
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-reg.d
@@ -0,0 +1,27 @@
+#objdump: -d
+#name:
+#source: mul-reg.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 4c a8 muls d0, d1, d2
+ 2: 4d 81 muls d1, d2, d3
+ 4: 48 8a muls d2, d3, d4
+ 6: 49 93 muls d3, d4, d5
+ 8: 4a 9e muls d4, d5, d6
+ a: 4b b7 muls d5, d6, d7
+ c: 4e bc muls d6, d7, d0
+ e: 4f a5 muls d7, d0, d1
+ 10: 4c 28 mulu d0, d1, d2
+ 12: 4d 01 mulu d1, d2, d3
+ 14: 48 0a mulu d2, d3, d4
+ 16: 49 13 mulu d3, d4, d5
+ 18: 4a 1e mulu d4, d5, d6
+ 1a: 4b 37 mulu d5, d6, d7
+ 1c: 4e 3c mulu d6, d7, d0
+ 1e: 4f 25 mulu d7, d0, d1
diff --git a/gas/testsuite/gas/s12z/mul-reg.s b/gas/testsuite/gas/s12z/mul-reg.s
new file mode 100644
index 0000000..9cb9ac9
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul-reg.s
@@ -0,0 +1,16 @@
+ muls d0, d1, d2
+ muls d1, d2, d3
+ muls d2, d3, d4
+ muls d3, d4, d5
+ muls d4, d5, d6
+ muls d5, d6, d7
+ muls d6, d7, d0
+ muls d7, d0, d1
+ mulu d0, d1, d2
+ mulu d1, d2, d3
+ mulu d2, d3, d4
+ mulu d3, d4, d5
+ mulu d4, d5, d6
+ mulu d5, d6, d7
+ mulu d6, d7, d0
+ mulu d7, d0, d1
diff --git a/gas/testsuite/gas/s12z/mul.d b/gas/testsuite/gas/s12z/mul.d
new file mode 100644
index 0000000..e028b85
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: mul.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 4c ec 62 muls.b d0, d1, #98
+ 3: 49 ff 00 00 muls.l d3, d7, #9842
+ 7: 26 72
+ 9: 4a 68 e0 20 mulu.b d4, d1, \(32,s\)
+ d: 4b 49 c4 22 mulu.w d5, d3, \[34,x\]
+ 11: 4e 7b ff mulu.l d6, d7, \(s\+\)
+ 14: 4f 7a d4 0c mulu.lp d7, \[12,y\], \(7,d1\)
+ 18: 85 00 07
diff --git a/gas/testsuite/gas/s12z/mul.s b/gas/testsuite/gas/s12z/mul.s
new file mode 100644
index 0000000..1626ee4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/mul.s
@@ -0,0 +1,6 @@
+ muls.b d0, d1, #98
+ muls.l d3, d7, #9842
+ mulu.b d4, d1, (32,s)
+ mulu.w d5, d3, [34,x]
+ mulu.l d6, d7, (s+)
+ mulu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/neg-opr.d b/gas/testsuite/gas/s12z/neg-opr.d
new file mode 100644
index 0000000..7d4116d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/neg-opr.d
@@ -0,0 +1,34 @@
+#objdump: -d
+#name:
+#source: neg-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: df fe 12 34 neg.l \[1193046\]
+ 4: 56
+ 5: dc c4 04 neg.b \[4,x\]
+ 8: dd b8 neg.w d2
+ a: dc dc neg.b \[d0,y\]
+ c: dc e4 0c neg.b \[12,s\]
+ f: dc 63 neg.b \(3,s\)
+ 11: dc e1 85 neg.b \(-123,s\)
+ 14: df f2 12 3a neg.l \(1194684,p\)
+ 18: bc
+ 19: dd c7 neg.w \(x-\)
+ 1b: dd d7 neg.w \(y-\)
+ 1d: dc e7 neg.b \(x\+\)
+ 1f: dc f7 neg.b \(y\+\)
+ 21: dc ff neg.b \(s\+\)
+ 23: df e3 neg.l \(\+x\)
+ 25: dd f3 neg.w \(\+y\)
+ 27: df c3 neg.l \(-x\)
+ 29: dd d3 neg.w \(-y\)
+ 2b: dc fb neg.b \(-s\)
+ 2d: df 8d neg.l \(d1,x\)
+ 2f: df 98 neg.l \(d2,y\)
+ 31: df a9 neg.l \(d3,s\)
diff --git a/gas/testsuite/gas/s12z/neg-opr.s b/gas/testsuite/gas/s12z/neg-opr.s
new file mode 100644
index 0000000..6e36326
--- /dev/null
+++ b/gas/testsuite/gas/s12z/neg-opr.s
@@ -0,0 +1,21 @@
+ neg.l [0x123456]
+ neg.b [4,x]
+ neg.w d2
+ neg.b [d0, y]
+ neg.b [12,s]
+ neg.b (3,s)
+ neg.b (-123,s)
+ neg.l (0x123abc,p)
+ neg.w (x-)
+ neg.w (y-)
+ neg.b (x+)
+ neg.b (y+)
+ neg.b (s+)
+ neg.l (+x)
+ neg.w (+y)
+ neg.l (-x)
+ neg.w (-y)
+ neg.b (-s)
+ neg.l (d1, x)
+ neg.l (d2, y)
+ neg.l (d3, s)
diff --git a/gas/testsuite/gas/s12z/not-so-simple-shifts.d b/gas/testsuite/gas/s12z/not-so-simple-shifts.d
new file mode 100644
index 0000000..f9b4e11
--- /dev/null
+++ b/gas/testsuite/gas/s12z/not-so-simple-shifts.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:
+#source: not-so-simple-shifts.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 14 7b e3 71 lsl.l d0, \(\+x\), #3
+ 4: 13 2a 8e lsr.p d5, \(d6,x\), #2
+ 7: 17 f9 f4 2d asl.w d7, \[45,p\], #13
+ b: 76
+ c: 12 b8 84 00 asr.b d4, \(145,d0\), #3
+ 10: 91 71
diff --git a/gas/testsuite/gas/s12z/not-so-simple-shifts.s b/gas/testsuite/gas/s12z/not-so-simple-shifts.s
new file mode 100644
index 0000000..fe546e1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/not-so-simple-shifts.s
@@ -0,0 +1,4 @@
+ lsl.l d0, (+x), #3
+ lsr.p d5, (d6,x), #2
+ asl.w d7, [45,p], #13
+ asr.b d4, (145,d0), #3
diff --git a/gas/testsuite/gas/s12z/opr-18u.d b/gas/testsuite/gas/s12z/opr-18u.d
new file mode 100644
index 0000000..d3a75cd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-18u.d
@@ -0,0 +1,26 @@
+#objdump: -d
+#name:
+#source: opr-18u.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 87 84 00 2d sub d7, \(45,d0\)
+ 4: 87 85 00 2d sub d7, \(45,d1\)
+ 8: 87 80 00 2d sub d7, \(45,d2\)
+ c: 87 81 00 2d sub d7, \(45,d3\)
+ 10: 87 82 00 2d sub d7, \(45,d4\)
+ 14: 87 83 00 2d sub d7, \(45,d5\)
+ 18: 87 83 00 2d sub d7, \(45,d5\)
+ 1c: 87 86 00 2d sub d7, \(45,d6\)
+ 20: 87 87 00 2d sub d7, \(45,d7\)
+ 24: 87 ef 03 ff sub d7, \(262143,d7\)
+ 28: ff
+ 29: 87 ef 04 00 sub d7, \(262144,d7\)
+ 2d: 00
+ 2e: 87 ef 04 00 sub d7, \(262145,d7\)
+ 32: 01
diff --git a/gas/testsuite/gas/s12z/opr-18u.s b/gas/testsuite/gas/s12z/opr-18u.s
new file mode 100644
index 0000000..79f95f1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-18u.s
@@ -0,0 +1,15 @@
+ sub d7, (45,D0)
+ sub d7, (45,D1)
+ sub d7, (45,D2)
+ sub d7, (45,D3)
+ sub d7, (45,D4)
+ sub d7, (45,D5)
+ sub d7, (45,D5)
+ sub d7, (45,D6)
+ sub d7, (45,D7)
+
+ sub d7, (262143,D7)
+ sub d7, (262144,D7)
+ sub d7, (262145,D7)
+
+
diff --git a/gas/testsuite/gas/s12z/opr-expr.d b/gas/testsuite/gas/s12z/opr-expr.d
new file mode 100644
index 0000000..e02a78e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-expr.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name: Expressions in OPR direct submode
+#source: opr-expr.s
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 01 nop
+ 1: 01 nop
+ 2: bc 12 39 clr.b 4665
diff --git a/gas/testsuite/gas/s12z/opr-expr.s b/gas/testsuite/gas/s12z/opr-expr.s
new file mode 100644
index 0000000..d52ac38
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-expr.s
@@ -0,0 +1,5 @@
+ equiv FOO, 0x1230
+
+ nop
+ nop
+ clr.b FOO+9
diff --git a/gas/testsuite/gas/s12z/opr-ext-18.d b/gas/testsuite/gas/s12z/opr-ext-18.d
new file mode 100644
index 0000000..481ce9f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-ext-18.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:
+#source: opr-ext-18.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 85 fc ab cd sub d1, 175053
+ 4: 84 f9 fe ed sub d0, 130797 \ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/opr-ext-18.s b/gas/testsuite/gas/s12z/opr-ext-18.s
new file mode 100644
index 0000000..e0fdc3e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-ext-18.s
@@ -0,0 +1,5 @@
+;;; Test the 18 bit OPR mode
+;;; This should encode to four bytes only
+ sub d1, 0x2abcd
+ sub d0, 0x1feed
+
diff --git a/gas/testsuite/gas/s12z/opr-idx-24-reg.d b/gas/testsuite/gas/s12z/opr-idx-24-reg.d
new file mode 100644
index 0000000..2ee64f5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx-24-reg.d
@@ -0,0 +1,13 @@
+#objdump: -d
+#name:
+#source: opr-idx-24-reg.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: bc e8 02 ab clr.b \(175053,d2\)
+ 4: cd
diff --git a/gas/testsuite/gas/s12z/opr-idx-24-reg.s b/gas/testsuite/gas/s12z/opr-idx-24-reg.s
new file mode 100644
index 0000000..e25468c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx-24-reg.s
@@ -0,0 +1,2 @@
+ clr.b (175053, d2)
+
diff --git a/gas/testsuite/gas/s12z/opr-idx3-reg.d b/gas/testsuite/gas/s12z/opr-idx3-reg.d
new file mode 100644
index 0000000..9b66f06
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-reg.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name:
+#source: opr-idx3-reg.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: a9 c6 11 22 ld y, \[1122867,x\]
+ 4: 33
+ 5: df fe 11 77 neg.l \[1144678\]
+ 9: 66
+ a: 0c 9a fa 11 mov.b #-102, 1162188
+ e: bb cc
diff --git a/gas/testsuite/gas/s12z/opr-idx3-reg.s b/gas/testsuite/gas/s12z/opr-idx3-reg.s
new file mode 100644
index 0000000..b4d95ac
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-reg.s
@@ -0,0 +1,3 @@
+L1: ld y, [0x112233, x]
+ neg.l [0x117766]
+ mov.b #-102, 0x11bbcc
diff --git a/gas/testsuite/gas/s12z/opr-idx3-xysp-24.d b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.d
new file mode 100644
index 0000000..28fafbc
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: opr-idx3-xysp-24.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: a6 c2 99 aa ld d6, \(-6706501,x\)
+ 4: bb
+ 5: a7 d2 0a d3 ld d7, \(709501,y\)
+ 9: 7d
diff --git a/gas/testsuite/gas/s12z/opr-idx3-xysp-24.s b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.s
new file mode 100644
index 0000000..384a4cf
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-idx3-xysp-24.s
@@ -0,0 +1,3 @@
+ ld d6, (-6706501,x)
+ ld d7, (709501,y)
+
diff --git a/gas/testsuite/gas/s12z/opr-indirect-expr.d b/gas/testsuite/gas/s12z/opr-indirect-expr.d
new file mode 100644
index 0000000..95d51b3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-indirect-expr.d
@@ -0,0 +1,14 @@
+#objdump: -dr
+#name: Expressions in OPR indirect mode
+#source: opr-indirect-expr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: a7 fe 00 00 ld d7, \[1\]
+ 4: 01
+ 2: R_S12Z_EXT24 FOO
diff --git a/gas/testsuite/gas/s12z/opr-indirect-expr.s b/gas/testsuite/gas/s12z/opr-indirect-expr.s
new file mode 100644
index 0000000..ee1fb12
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-indirect-expr.s
@@ -0,0 +1 @@
+ ld d7, [FOO+1]
diff --git a/gas/testsuite/gas/s12z/opr-symbol.d b/gas/testsuite/gas/s12z/opr-symbol.d
new file mode 100644
index 0000000..97e5b4f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-symbol.d
@@ -0,0 +1,170 @@
+#objdump: -dt
+#name: OPR addressing mode: symbols in its direct submode
+#source: opr-symbol.s
+
+dump.o: file format elf32-s12z
+
+SYMBOL TABLE:
+00000000 l d .text 00000000 .text
+00000000 l d .data 00000000 .data
+00000000 l d .bss 00000000 .bss
+00123456 l \*ABS\* 00000000 sym1
+00abcdef l \*ABS\* 00000000 sym2
+
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 0c 17 fa 12 mov.b #23, sym1
+ 4: 34 56
+ 6: 0d 00 17 fa mov.w #23, sym1
+ a: 12 34 56
+ d: 0e 00 00 17 mov.p #23, sym1
+ 11: fa 12 34 56
+ 15: 0f 00 00 00 mov.l #23, sym1
+ 19: 17 fa 12 34
+ 1d: 56
+ 1e: 1c fa 12 34 mov.b sym1, sym2
+ 22: 56 fa ab cd
+ 26: ef
+ 27: 1d fa 12 34 mov.w sym1, sym2
+ 2b: 56 fa ab cd
+ 2f: ef
+ 30: 1e fa 12 34 mov.p sym1, sym2
+ 34: 56 fa ab cd
+ 38: ef
+ 39: 1f fa 12 34 mov.l sym1, sym2
+ 3d: 56 fa ab cd
+ 41: ef
+ 42: 65 fa 12 34 add d1, sym1
+ 46: 56
+ 47: 68 fa 12 34 and d2, sym1
+ 4b: 56
+ 4c: 81 fa 12 34 sub d3, sym1
+ 50: 56
+ 51: 8a fa 12 34 or d4, sym1
+ 55: 56
+ 56: 9c fa 12 34 inc.b sym1
+ 5a: 56
+ 5b: 9d fa 12 34 inc.w sym1
+ 5f: 56
+ 60: 9f fa 12 34 inc.l sym1
+ 64: 56
+ 65: b2 12 34 56 ld d4, sym1
+ 69: ba ab cd ef jmp sym2
+ 6d: bb 12 34 56 jsr sym1
+ 71: ac fa 12 34 dec.b sym1
+ 75: 56
+ 76: ad fa 12 34 dec.w sym1
+ 7a: 56
+ 7b: af fa 12 34 dec.l sym1
+ 7f: 56
+ 80: bc fa 12 34 clr.b sym1
+ 84: 56
+ 85: bd fa 12 34 clr.w sym1
+ 89: 56
+ 8a: bf fa 12 34 clr.l sym1
+ 8e: 56
+ 8f: d3 12 34 56 st d5, sym1
+ 93: cc fa 12 34 com.b sym1
+ 97: 56
+ 98: cd fa 12 34 com.w sym1
+ 9c: 56
+ 9d: cf fa 12 34 com.l sym1
+ a1: 56
+ a2: dc fa 12 34 neg.b sym1
+ a6: 56
+ a7: dd fa 12 34 neg.w sym1
+ ab: 56
+ ac: df fa 12 34 neg.l sym1
+ b0: 56
+ b1: f3 fa 12 34 cmp d5, sym1
+ b5: 56
+ b6: 1b 00 fa 12 ld s, sym1
+ ba: 34 56
+ bc: 1b 01 fa 12 st s, sym1
+ c0: 34 56
+ c2: 1b 02 fa 12 cmp s, sym1
+ c6: 34 56
+ c8: 1b 10 fa 12 minu d2, sym1
+ cc: 34 56
+ ce: 1b 18 fa 12 maxu d2, sym1
+ d2: 34 56
+ d4: 1b 20 fa 12 mins d2, sym1
+ d8: 34 56
+ da: 1b 28 fa 12 maxs d2, sym1
+ de: 34 56
+ e0: 1b 61 fa 12 adc d3, sym1
+ e4: 34 56
+ e6: 1b 69 fa 12 bit d3, sym1
+ ea: 34 56
+ ec: 1b 81 fa 12 sbc d3, sym1
+ f0: 34 56
+ f2: 1b 89 fa 12 eor d3, sym1
+ f6: 34 56
+ f8: 02 d1 fa 12 brclr.b sym1, d1, \*\+3
+ fc: 34 56 03
+ ff: 02 a2 fa 12 brclr.w sym1, #2, \*\+4
+ 103: 34 56 04
+ 106: 03 81 fa ab brset.b sym2, d2, \*\+5
+ 10a: cd ef 05
+ 10d: 03 b2 fa ab brset.w sym2, #3, \*\+6
+ 111: cd ef 06
+ 114: 4d 40 fa 12 mulu.b d1, d2, sym1
+ 118: 34 56
+ 11a: 4e 7e fa 12 mulu.ll d6, sym1, sym2
+ 11e: 34 56 fa ab
+ 122: cd ef
+ 124: 4d c0 fa 12 muls.b d1, d2, sym1
+ 128: 34 56
+ 12a: 4e fe fa 12 muls.ll d6, sym1, sym2
+ 12e: 34 56 fa ab
+ 132: cd ef
+ 134: 1b b5 c0 fa qmuls.b d1, d2, sym1
+ 138: 12 34 56
+ 13b: 1b b6 fe fa qmuls.ll d6, sym1, sym2
+ 13f: 12 34 56 fa
+ 143: ab cd ef
+ 146: 1b 35 40 fa divu.b d1, d2, sym1
+ 14a: 12 34 56
+ 14d: 1b 36 7e fa divu.ll d6, sym1, sym2
+ 151: 12 34 56 fa
+ 155: ab cd ef
+ 158: 1b 35 c0 fa divs.b d1, d2, sym1
+ 15c: 12 34 56
+ 15f: 1b 36 fe fa divs.ll d6, sym1, sym2
+ 163: 12 34 56 fa
+ 167: ab cd ef
+ 16a: ec a0 fa 12 bclr.b sym1, #2
+ 16e: 34 56
+ 170: ec 85 fa ab bclr.w sym2, d2
+ 174: cd ef
+ 176: ed a0 fa 12 bset.b sym1, #2
+ 17a: 34 56
+ 17c: ed 85 fa ab bset.w sym2, d2
+ 180: cd ef
+ 182: ee a0 fa 12 btgl.b sym1, #2
+ 186: 34 56
+ 188: ee 85 fa ab btgl.w sym2, d2
+ 18c: cd ef
+ 18e: 0b 0c fa 12 tbne.b sym1, \*\+8
+ 192: 34 56 08
+ 195: 0b ad fa ab dbpl.w sym2, \*\+9
+ 199: cd ef 09
+ 19c: 1b 08 c0 fa bfins.b d2, sym1, d2
+ 1a0: 12 34 56
+ 1a3: 1b 08 d4 fa bfins.w sym1, d2, d2
+ 1a7: 12 34 56
+ 1aa: 1b 08 e9 01 bfins.p d2, sym1, #8\:1
+ 1ae: fa 12 34 56
+ 1b2: 1b 08 fd 01 bfins.l sym1, d2, #8\:1
+ 1b6: fa 12 34 56
+ 1ba: 1b 08 40 fa bfext.b d2, sym1, d2
+ 1be: 12 34 56
+ 1c1: 1b 08 54 fa bfext.w sym1, d2, d2
+ 1c5: 12 34 56
+ 1c8: 1b 08 69 01 bfext.p d2, sym1, #8\:1
+ 1cc: fa 12 34 56
+ 1d0: 1b 08 7c e2 bfext.l sym1, d2, #7\:2
+ 1d4: fa 12 34 56
diff --git a/gas/testsuite/gas/s12z/opr-symbol.s b/gas/testsuite/gas/s12z/opr-symbol.s
new file mode 100644
index 0000000..6ce2afb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/opr-symbol.s
@@ -0,0 +1,109 @@
+#sym1: set $123456
+
+#sym2: set $abcdef
+
+ .equiv sym1, 0x123456
+ .equiv sym2, 0xabcdef
+
+ mov.b #23, sym1
+ mov.w #23, sym1
+ mov.p #23, sym1
+ mov.l #23, sym1
+
+ mov.b sym1, sym2
+ mov.w sym1, sym2
+ mov.p sym1, sym2
+ mov.l sym1, sym2
+
+ add d1, sym1
+ and d2, sym1
+ sub d3, sym1
+ or d4, sym1
+
+ inc.b sym1
+ inc.w sym1
+ inc.l sym1
+
+ ld d4, sym1
+
+ jmp sym2
+ jsr sym1
+
+ dec.b sym1
+ dec.w sym1
+ dec.l sym1
+
+ clr.b sym1
+ clr.w sym1
+ clr.l sym1
+
+ st d5, sym1
+
+ com.b sym1
+ com.w sym1
+ com.l sym1
+
+ neg.b sym1
+ neg.w sym1
+ neg.l sym1
+
+ cmp d5, sym1
+
+ ld s, sym1
+ st s, sym1
+ cmp s, sym1
+
+ minu d2, sym1
+ maxu d2, sym1
+
+ mins d2, sym1
+ maxs d2, sym1
+
+ adc d3, sym1
+ bit d3, sym1
+ sbc d3, sym1
+ eor d3, sym1
+
+ brclr.b sym1, d1, *+3
+ brclr.w sym1, #2, *+4
+
+ brset.b sym2, d2, *+5
+ brset.w sym2, #3, *+6
+
+ mulu.b d1, d2, sym1
+ mulu.ll d6, sym1, sym2
+
+ muls.b d1, d2, sym1
+ muls.ll d6, sym1, sym2
+
+ qmuls.b d1, d2, sym1
+ qmuls.ll d6, sym1, sym2
+
+ divu.b d1, d2, sym1
+ divu.ll d6, sym1, sym2
+
+ divs.b d1, d2, sym1
+ divs.ll d6, sym1, sym2
+
+ bclr.b sym1, #2
+ bclr.w sym2, d2
+
+ bset.b sym1, #2
+ bset.w sym2, d2
+
+ btgl.b sym1, #2
+ btgl.w sym2, d2
+
+ tbne.b sym1, *+8
+ dbpl.w sym2, *+9
+
+ bfins.b d2, sym1, d2
+ bfins.w sym1, d2, d2
+ bfins.p d2, sym1, #8:1
+ bfins.l sym1, d2, #8:1
+
+ bfext.b d2, sym1, d2
+ bfext.w sym1, d2, d2
+ bfext.p d2, sym1, #8:1
+ bfext.l sym1, d2, #7:2
+
diff --git a/gas/testsuite/gas/s12z/or-imm.d b/gas/testsuite/gas/s12z/or-imm.d
new file mode 100644
index 0000000..dbaa77d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: or-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 78 12 34 or d2, #4660
+ 3: 79 12 34 or d3, #4660
+ 6: 7a fc 7a or d4, #-902
+ 9: 7b 01 59 or d5, #345
+ c: 7c 12 or d0, #18
+ e: 7d 34 or d1, #52
+ 10: 7e 56 78 9a or d6, #1450744508
+ 14: bc
+ 15: 7f ff 43 9e or d7, #-12345678
+ 19: b2
diff --git a/gas/testsuite/gas/s12z/or-imm.s b/gas/testsuite/gas/s12z/or-imm.s
new file mode 100644
index 0000000..6558525
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-imm.s
@@ -0,0 +1,8 @@
+start: or d2, #0x1234
+ or d3, #0x1234
+ or d4, #-902
+ or d5, #345
+ or d0, #0x12
+ or d1, #0x34
+ or d6, #0x56789ABC
+ or d7, #-12345678
diff --git a/gas/testsuite/gas/s12z/or-opr.d b/gas/testsuite/gas/s12z/or-opr.d
new file mode 100644
index 0000000..188bb65
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-opr.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: or-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 8c d5 21 or d0, \[-223,y\]
+ 3: 8d f2 00 84 or d1, \(34000,p\)
+ 7: d0
+ 8: 88 c3 or d2, \(-x\)
+ a: 89 f7 or d3, \(y\+\)
+ c: 8a ba or d4, d4
+ e: 8b f8 77 d6 or d5, 30678
+ 12: 8e fe 01 64 or d6, \[91256\]
+ 16: 78
+ 17: 8f 9a or d7, \(d4,y\)
diff --git a/gas/testsuite/gas/s12z/or-opr.s b/gas/testsuite/gas/s12z/or-opr.s
new file mode 100644
index 0000000..4dabcb6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/or-opr.s
@@ -0,0 +1,8 @@
+ or d0, [-223,y]
+ or d1, (34000, p)
+ or d2, (-x)
+ or d3, (y+)
+ or d4, d4
+ or d5, 30678
+ or d6, [91256]
+ or d7, (d4,y)
diff --git a/gas/testsuite/gas/s12z/p2-mul.d b/gas/testsuite/gas/s12z/p2-mul.d
new file mode 100644
index 0000000..ce52171
--- /dev/null
+++ b/gas/testsuite/gas/s12z/p2-mul.d
@@ -0,0 +1,17 @@
+#objdump: -d
+#name: Multiply instructions from page2 in all reg-reg-reg mode
+#source: p2-mul.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b b4 a9 qmuls d0, d1, d3
+ 3: 1b b2 1e qmulu d4, d5, d6
+ 6: 1b 37 a5 divs d7, d0, d1
+ 9: 1b 30 0a divu d2, d3, d4
+ c: 1b 3b b7 mods d5, d6, d7
+ f: 1b 3c 28 modu d0, d1, d2
diff --git a/gas/testsuite/gas/s12z/p2-mul.s b/gas/testsuite/gas/s12z/p2-mul.s
new file mode 100644
index 0000000..b9952e3
--- /dev/null
+++ b/gas/testsuite/gas/s12z/p2-mul.s
@@ -0,0 +1,7 @@
+ qmuls d0, d1, d3
+ qmulu d4, d5, d6
+ divs d7, d0, d1
+ divu d2, d3, d4
+ mods d5, d6, d7
+ modu d0, d1, d2
+
diff --git a/gas/testsuite/gas/s12z/page2-inh.d b/gas/testsuite/gas/s12z/page2-inh.d
new file mode 100644
index 0000000..0903fa7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/page2-inh.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: page2-inh.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 90 rti
+ 2: 1b 07 sys
+ 4: 1b 05 stop
+ 6: 1b 06 wai
diff --git a/gas/testsuite/gas/s12z/page2-inh.s b/gas/testsuite/gas/s12z/page2-inh.s
new file mode 100644
index 0000000..0351ec6
--- /dev/null
+++ b/gas/testsuite/gas/s12z/page2-inh.s
@@ -0,0 +1,5 @@
+ RTI
+ SYS
+ STOP
+ WAI
+
diff --git a/gas/testsuite/gas/s12z/psh-pul.d b/gas/testsuite/gas/s12z/psh-pul.d
new file mode 100644
index 0000000..40113e7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/psh-pul.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: psh-pul.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <here>:
+ 0: 04 00 psh ALL
+ 2: 04 40 psh ALL16b
+ 4: 04 3c psh cch, ccl, d0, d1
+ 6: 04 43 psh x, y
+
+00000008 <there>:
+ 8: 04 80 pul ALL
+ a: 04 c0 pul ALL16b
+ c: 04 bc pul cch, ccl, d0, d1
+ e: 04 c3 pul x, y
diff --git a/gas/testsuite/gas/s12z/psh-pul.s b/gas/testsuite/gas/s12z/psh-pul.s
new file mode 100644
index 0000000..57a2d59
--- /dev/null
+++ b/gas/testsuite/gas/s12z/psh-pul.s
@@ -0,0 +1,8 @@
+here: psh all
+ psh all16b
+ psh cch, ccl, d1, d0
+ psh x, y
+there: pul all
+ pul all16b
+ pul cch, ccl, d1, d0
+ pul x, y
diff --git a/gas/testsuite/gas/s12z/qmul.d b/gas/testsuite/gas/s12z/qmul.d
new file mode 100644
index 0000000..6cd5af7
--- /dev/null
+++ b/gas/testsuite/gas/s12z/qmul.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: qmul.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b b4 ec 62 qmuls.b d0, d1, #98
+ 4: 1b b5 c0 b9 qmuls.b d1, d2, d3
+ 8: 1b b0 c9 ba qmuls.w d2, d3, d4
+ c: 1b b1 ff 00 qmuls.l d3, d7, #9842
+ 10: 00 26 72
+ 13: 1b b2 68 e0 qmulu.b d4, d1, \(32,s\)
+ 17: 20
+ 18: 1b b3 49 c4 qmulu.w d5, d3, \[34,x\]
+ 1c: 22
+ 1d: 1b b6 7b ff qmulu.l d6, d7, \(s\+\)
+ 21: 1b b7 7a d4 qmulu.lp d7, \[12,y\], \(7,d1\)
+ 25: 0c 85 00 07
diff --git a/gas/testsuite/gas/s12z/qmul.s b/gas/testsuite/gas/s12z/qmul.s
new file mode 100644
index 0000000..6237d48
--- /dev/null
+++ b/gas/testsuite/gas/s12z/qmul.s
@@ -0,0 +1,8 @@
+ qmuls.b d0, d1, #98
+ qmuls.b d1, d2, d3
+ qmuls.w d2, d3, d4
+ qmuls.l d3, d7, #9842
+ qmulu.b d4, d1, (32,s)
+ qmulu.w d5, d3, [34,x]
+ qmulu.l d6, d7, (s+)
+ qmulu.lp d7, [12,y], (7,d1)
diff --git a/gas/testsuite/gas/s12z/rotate.d b/gas/testsuite/gas/s12z/rotate.d
new file mode 100644
index 0000000..a58eb9a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/rotate.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:
+#source: rotate.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 10 24 b8 ror.b d2
+ 3: 10 64 fb rol.b \(-s\)
+ 6: 10 65 ff rol.w \(s\+\)
+ 9: 10 66 d4 2d rol.p \[45,y\]
+ d: 10 67 87 00 rol.l \(78,d7\)
+ 11: 4e
+ 12: 10 24 bc ror.b d0
+ 15: 10 24 c3 ror.b \(-x\)
+ 18: 10 25 f7 ror.w \(y\+\)
+ 1b: 10 26 f4 29 ror.p \[41,p\]
+ 1f: 10 27 8b ror.l \(d5,x\)
diff --git a/gas/testsuite/gas/s12z/rotate.s b/gas/testsuite/gas/s12z/rotate.s
new file mode 100644
index 0000000..91e3f6d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/rotate.s
@@ -0,0 +1,10 @@
+ ror d2
+ rol.b (-s)
+ rol.w (s+)
+ rol.p [45,y]
+ rol.l (78, d7)
+ ror d0
+ ror.b (-x)
+ ror.w (y+)
+ ror.p [41,p]
+ ror.l (d5, x)
diff --git a/gas/testsuite/gas/s12z/s12z.exp b/gas/testsuite/gas/s12z/s12z.exp
new file mode 100644
index 0000000..acd50cf
--- /dev/null
+++ b/gas/testsuite/gas/s12z/s12z.exp
@@ -0,0 +1,132 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+#
+# Some s12z tests
+#
+if { ![istarget "s12z*-*-*"] } then {
+ return
+}
+
+
+run_dump_test abs
+run_dump_test adc-imm
+run_dump_test adc-opr
+run_dump_test add-imm
+run_dump_test add-opr
+run_dump_test and-imm
+run_dump_test and-opr
+run_dump_test and-or-cc
+run_dump_test bfext-special
+run_dump_test bfext
+run_dump_test bit-manip
+run_dump_test bit
+run_dump_test bra
+run_dump_test brset-clr-opr-imm-rel
+run_dump_test brset-clr-opr-reg-rel
+run_dump_test brset-clr-reg-imm-rel
+run_dump_test brset-clr-reg-reg-rel
+run_dump_test clb
+run_dump_test clr-opr
+run_dump_test clr
+run_dump_test cmp-imm
+run_dump_test cmp-opr-inc
+run_dump_test cmp-opr-rdirect
+run_dump_test cmp-opr-reg
+run_dump_test cmp-opr-rindirect
+run_dump_test cmp-opr-sxe4
+run_dump_test cmp-opr-xys
+run_dump_test cmp-s-imm
+run_dump_test cmp-s-opr
+run_dump_test cmp-xy
+run_dump_test com-opr
+run_dump_test complex-shifts
+run_dump_test db-tb-cc-opr
+run_dump_test db-tb-cc-reg
+run_dump_test dec-opr
+run_dump_test dec
+run_dump_test div
+run_dump_test eor
+run_dump_test exg
+run_dump_test inc-opr
+run_dump_test inc
+run_dump_test inh
+run_dump_test jmp
+run_dump_test jsr
+run_dump_test ld-imm-page2
+run_dump_test ld-imm
+run_dump_test ld-opr
+run_dump_test ld-s-opr
+run_dump_test lea
+run_dump_test mac
+run_dump_test min-max
+run_dump_test mod
+run_dump_test mov
+run_dump_test p2-mul
+run_dump_test mul-imm
+run_dump_test mul-opr-opr
+run_dump_test mul-opr
+run_dump_test mul-reg
+run_dump_test mul
+run_dump_test neg-opr
+run_dump_test not-so-simple-shifts
+run_dump_test opr-18u
+run_dump_test opr-ext-18
+run_dump_test opr-idx-24-reg
+run_dump_test opr-idx3-reg
+run_dump_test opr-idx3-xysp-24
+run_dump_test or-imm
+run_dump_test or-opr
+run_dump_test page2-inh
+run_dump_test psh-pul
+run_dump_test qmul
+run_dump_test rotate
+run_dump_test sat
+run_dump_test sbc-imm
+run_dump_test sbc-opr
+run_dump_test shift
+run_dump_test simple-shift
+run_dump_test single-ops
+run_dump_test st-opr
+run_dump_test st-s-opr
+run_dump_test sub-imm
+run_dump_test sub-opr
+run_dump_test tfr
+run_dump_test trap
+run_dump_test specd6
+
+# Tests of the disassembler - these are hard to force the assembler to generate
+run_dump_test ld-immu18
+run_dump_test lea-immu18
+run_dump_test ext24-ld-xy
+run_dump_test st-xy
+
+# Symbol related tests
+run_dump_test opr-symbol
+run_dump_test brclr-symbols
+run_dump_test dbCC
+
+# Expression related tests
+run_dump_test opr-expr
+run_dump_test opr-indirect-expr
+run_dump_test bra-expression-defined
+run_dump_test bra-expression-undef
+
+# Tests related to optimisation
+run_dump_test ld-large-direct
+run_dump_test ld-small-direct
+run_dump_test st-large-direct
+run_dump_test st-small-direct
diff --git a/gas/testsuite/gas/s12z/sat.d b/gas/testsuite/gas/s12z/sat.d
new file mode 100644
index 0000000..4cbac0b
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sat.d
@@ -0,0 +1,19 @@
+#objdump: -d
+#name:
+#source: sat.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b a0 sat d2
+ 2: 1b a1 sat d3
+ 4: 1b a2 sat d4
+ 6: 1b a3 sat d5
+ 8: 1b a4 sat d0
+ a: 1b a5 sat d1
+ c: 1b a6 sat d6
+ e: 1b a7 sat d7
diff --git a/gas/testsuite/gas/s12z/sat.s b/gas/testsuite/gas/s12z/sat.s
new file mode 100644
index 0000000..ba2ff8e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sat.s
@@ -0,0 +1,8 @@
+ sat d2
+ sat d3
+ sat d4
+ sat d5
+ sat d0
+ sat d1
+ sat d6
+ sat d7
diff --git a/gas/testsuite/gas/s12z/sbc-imm.d b/gas/testsuite/gas/s12z/sbc-imm.d
new file mode 100644
index 0000000..1bca708
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: sbc-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 70 12 34 sbc d2, #4660
+ 4: 1b 71 12 34 sbc d3, #4660
+ 8: 1b 72 12 34 sbc d4, #4660
+ c: 1b 73 12 34 sbc d5, #4660
+ 10: 1b 74 ef sbc d0, #-17
+ 13: 1b 75 34 sbc d1, #52
+ 16: 1b 76 56 78 sbc d6, #1450744508
+ 1a: 9a bc
+ 1c: 1b 77 98 77 sbc d7, #-1737025662
+ 20: 17 82
diff --git a/gas/testsuite/gas/s12z/sbc-imm.s b/gas/testsuite/gas/s12z/sbc-imm.s
new file mode 100644
index 0000000..9879e33
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-imm.s
@@ -0,0 +1,8 @@
+ sbc d2, #0x1234
+ sbc d3, #0x1234
+ sbc d4, #0x1234
+ sbc d5, #0x1234
+ sbc d0, #-17
+ sbc d1, #0x34
+ sbc d6, #0x56789ABC
+ sbc d7, #-1737025662
diff --git a/gas/testsuite/gas/s12z/sbc-opr.d b/gas/testsuite/gas/s12z/sbc-opr.d
new file mode 100644
index 0000000..bd5ed49
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-opr.d
@@ -0,0 +1,23 @@
+#objdump: -d
+#name:
+#source: sbc-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 84 d5 21 sbc d0, \[-223,y\]
+ 4: 1b 85 f2 00 sbc d1, \(34000,p\)
+ 8: 84 d0
+ a: 1b 80 fb sbc d2, \(-s\)
+ d: 1b 71 00 22 sbc d3, #34
+ 11: 1b 82 bc sbc d4, d0
+ 14: 1b 83 0a 76 sbc d5, 2678
+ 18: 1b 86 fe 00 sbc d6, \[56\]
+ 1c: 00 38
+ 1e: 1b 87 9b sbc d7, \(d5,y\)
+ 21: 1b 81 85 00 sbc d3, \(34,d1\)
+ 25: 22
diff --git a/gas/testsuite/gas/s12z/sbc-opr.s b/gas/testsuite/gas/s12z/sbc-opr.s
new file mode 100644
index 0000000..3202174
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sbc-opr.s
@@ -0,0 +1,9 @@
+ sbc d0, [-223,y]
+ sbc d1, (34000, p)
+ sbc d2, (-s)
+ sbc d3, #34
+ sbc d4, d0
+ sbc d5, 2678
+ sbc d6, [56]
+ sbc d7, (d5,y)
+ sbc d3, (34, d1)
diff --git a/gas/testsuite/gas/s12z/shift.d b/gas/testsuite/gas/s12z/shift.d
new file mode 100644
index 0000000..41e061f
--- /dev/null
+++ b/gas/testsuite/gas/s12z/shift.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:
+#source: shift.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 14 11 bb lsr d0, d3, d5
+ 3: 15 9a 76 asr d1, d4, #13
+ 6: 15 84 asr d1, d0, #1
+ 8: 17 68 fb lsl.b d7, \(-s\), #2
+ b: 17 69 fb lsl.w d7, \(-s\), #2
+ e: 17 6b fb lsl.l d7, \(-s\), #2
+ 11: 17 2a fb lsr.p d7, \(-s\), #2
+ 14: 10 3d f3 lsr.w \(\+y\), #2
+ 17: 10 3e 8e lsr.p \(d6,x\), #2
+ 1a: 10 f4 bf asl d7, #1
+ 1d: 10 bc bd asr d1, #2
diff --git a/gas/testsuite/gas/s12z/shift.s b/gas/testsuite/gas/s12z/shift.s
new file mode 100644
index 0000000..cb41f3c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/shift.s
@@ -0,0 +1,11 @@
+ lsr d0, d3, d5
+ asr d1, d4, #13
+ asr d1, d0, #1
+ lsl.b d7, (-s), #2
+ lsl.w d7, (-s), #2
+ lsl.l d7, (-s), #2
+ lsr.p d7, (-s), #2
+ lsr.w (+y), #2
+ lsr.p (d6,x), #2
+ asl d7, #1
+ asr d1, #2
diff --git a/gas/testsuite/gas/s12z/simple-shift.d b/gas/testsuite/gas/s12z/simple-shift.d
new file mode 100644
index 0000000..13af3bf
--- /dev/null
+++ b/gas/testsuite/gas/s12z/simple-shift.d
@@ -0,0 +1,18 @@
+#objdump: -d
+#name:
+#source: simple-shift.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 14 55 b8 lsl d0, d1, d2
+ 3: 11 12 bb lsr d3, d4, d5
+ 6: 17 d4 bd asl d7, d0, d1
+ 9: 10 91 ba asr d2, d3, d4
+ c: 16 d5 b8 asl d6, d1, d2
+ f: 15 5a 76 lsl d1, d4, #13
+ 12: 13 46 lsl d5, d6, #1
diff --git a/gas/testsuite/gas/s12z/simple-shift.s b/gas/testsuite/gas/s12z/simple-shift.s
new file mode 100644
index 0000000..045e071
--- /dev/null
+++ b/gas/testsuite/gas/s12z/simple-shift.s
@@ -0,0 +1,9 @@
+ lsl d0, d1, d2
+ lsr d3, d4, d5
+ asl d7, d0, d1
+ asr d2, d3, d4
+ asl d6, d1, d2
+
+ lsl d1, d4, #13
+ lsl d5, d6, #1 ; this creates a short form
+
diff --git a/gas/testsuite/gas/s12z/single-ops.d b/gas/testsuite/gas/s12z/single-ops.d
new file mode 100644
index 0000000..ca9b38a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/single-ops.d
@@ -0,0 +1,15 @@
+#objdump: -d
+#name:
+#source: single-ops.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 01 nop
+ 1: 05 rts
+ 2: 00 bgnd
+ 3: ff swi
diff --git a/gas/testsuite/gas/s12z/single-ops.s b/gas/testsuite/gas/s12z/single-ops.s
new file mode 100644
index 0000000..ab6fe2c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/single-ops.s
@@ -0,0 +1,4 @@
+ nop
+ rts
+ bgnd
+ swi
diff --git a/gas/testsuite/gas/s12z/specd6.d b/gas/testsuite/gas/s12z/specd6.d
new file mode 100644
index 0000000..0c743cd
--- /dev/null
+++ b/gas/testsuite/gas/s12z/specd6.d
@@ -0,0 +1,14 @@
+#objdump: -d
+#name:
+#source: specd6.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: fc cmp x, y
+ 1: fd sub d6, x, y
+ 2: fe sub d6, y, x
diff --git a/gas/testsuite/gas/s12z/specd6.s b/gas/testsuite/gas/s12z/specd6.s
new file mode 100644
index 0000000..92308b4
--- /dev/null
+++ b/gas/testsuite/gas/s12z/specd6.s
@@ -0,0 +1,4 @@
+ cmp x, y
+ sub d6, x, y
+ sub d6, y, x
+
diff --git a/gas/testsuite/gas/s12z/st-large-direct.d b/gas/testsuite/gas/s12z/st-large-direct.d
new file mode 100644
index 0000000..03ca41e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-large-direct.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name: ST reg - constant optimised to EXT24
+#source: st-large-direct.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: d0 12 34 56 st d2, 1193046
+ 4: d1 c0 ff ee st d3, 12648430
+ 8: d2 80 00 02 st d4, 8388610
+ c: d4 80 00 03 st d0, 8388611
+ 10: d5 80 00 03 st d1, 8388611
+ 14: d3 80 00 04 st d5, 8388612
+ 18: d6 80 00 06 st d6, 8388614
+ 1c: d7 80 00 07 st d7, 8388615
+ 20: d8 80 00 08 st x, 8388616
+ 24: d9 80 00 09 st y, 8388617
diff --git a/gas/testsuite/gas/s12z/st-large-direct.s b/gas/testsuite/gas/s12z/st-large-direct.s
new file mode 100644
index 0000000..74956d1
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-large-direct.s
@@ -0,0 +1,11 @@
+ st d2, 0x123456
+ st d3, 0xc0ffee
+ st d4, 0x800002
+ st d0, 0x800003
+ st d1, 0x800003
+ st d5, 0x800004
+ st d6, 0x800006
+ st d7, 0x800007
+ st x, 0x800008
+ st y, 0x800009
+
diff --git a/gas/testsuite/gas/s12z/st-opr.d b/gas/testsuite/gas/s12z/st-opr.d
new file mode 100644
index 0000000..d39bb62
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:
+#source: st-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: c4 d8 st d0, \[d2,y\]
+ 2: c5 c9 st d1, \[d3,x\]
+ 4: c0 ca st d2, \[d4,x\]
+ 6: c1 87 3b 82 st d3, \(15234,d7\)
+ a: c2 e1 16 st d4, \(-234,s\)
+ d: c3 bc st d5, d0
+ f: c6 88 st d6, \(d2,x\)
+ 11: c7 fe 00 04 st d7, \[1234\]
+ 15: d2
+ 16: c8 88 st x, \(d2,x\)
+ 18: c9 db st y, \[d5,y\]
diff --git a/gas/testsuite/gas/s12z/st-opr.s b/gas/testsuite/gas/s12z/st-opr.s
new file mode 100644
index 0000000..c5257a5
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-opr.s
@@ -0,0 +1,10 @@
+ st d0, [d2,y]
+ st d1, [d3,x]
+ st d2, [d4,x]
+ st d3, (15234,d7)
+ st d4, (-234,s)
+ st d5, d0
+ st d6, (d2, x)
+ st d7, [1234]
+ st x, (d2, x)
+ st y, [d5, y]
diff --git a/gas/testsuite/gas/s12z/st-s-opr.d b/gas/testsuite/gas/s12z/st-s-opr.d
new file mode 100644
index 0000000..3748914
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-s-opr.d
@@ -0,0 +1,16 @@
+#objdump: -d
+#name:
+#source: st-s-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 01 aa st s, \(d4,s\)
+ 3: 1b 01 fe 00 st s, \[1340\]
+ 7: 05 3c
+ 9: 1b 01 9b st s, \(d5,y\)
+ c: 1b 01 d3 st s, \(-y\)
diff --git a/gas/testsuite/gas/s12z/st-s-opr.s b/gas/testsuite/gas/s12z/st-s-opr.s
new file mode 100644
index 0000000..90cc5e8
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-s-opr.s
@@ -0,0 +1,4 @@
+ st s, (d4, s)
+ st s, [1340]
+ st s, (d5, y)
+ st s, (-y)
diff --git a/gas/testsuite/gas/s12z/st-small-direct.d b/gas/testsuite/gas/s12z/st-small-direct.d
new file mode 100644
index 0000000..df67d4a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-small-direct.d
@@ -0,0 +1,34 @@
+#objdump: -d
+#name: ST reg - small constants left in OPR mode
+#source: st-small-direct.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: c0 fa 00 00 st d2, L1
+ 4: 00
+ 5: c1 fa 00 00 st d3, L2
+ 9: 1a
+ a: c2 fa 00 00 st d4, L1
+ e: 00
+
+0000000f <L3>:
+ f: 01 nop
+ 10: c4 fa 00 00 st d0, L2
+ 14: 1a
+ 15: c5 fa 00 00 st d1, L3
+ 19: 0f
+
+0000001a <L2>:
+ 1a: c3 fa 00 00 st d5, L1
+ 1e: 00
+ 1f: c6 fa 00 00 st d6, L3
+ 23: 0f
+ 24: c7 fa 00 00 st d7, L2
+ 28: 1a
+ 29: c8 30 39 st x, 12345
+ 2c: c9 26 94 st y, 9876
diff --git a/gas/testsuite/gas/s12z/st-small-direct.s b/gas/testsuite/gas/s12z/st-small-direct.s
new file mode 100644
index 0000000..c0d736d
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-small-direct.s
@@ -0,0 +1,12 @@
+L1: st d2, L1
+ st d3, L2
+ st d4, L1
+L3: nop
+ st d0, L2
+ st d1, L3
+L2: st d5, L1
+ st d6, L3
+ st d7, L2
+ st x, 12345
+ st y, 9876
+
diff --git a/gas/testsuite/gas/s12z/st-xy.d b/gas/testsuite/gas/s12z/st-xy.d
new file mode 100644
index 0000000..335e77e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-xy.d
@@ -0,0 +1,12 @@
+#objdump: -d
+#name:
+#source: st-xy.s
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: d8 90 12 34 st x, 9441844
+ 4: d9 80 12 34 st y, 8393268
diff --git a/gas/testsuite/gas/s12z/st-xy.s b/gas/testsuite/gas/s12z/st-xy.s
new file mode 100644
index 0000000..6e77465
--- /dev/null
+++ b/gas/testsuite/gas/s12z/st-xy.s
@@ -0,0 +1,3 @@
+ .long 0xD8901234 ;; ST X,9441844
+ .long 0xD9801234 ;; ST Y,8393268
+
diff --git a/gas/testsuite/gas/s12z/sub-imm.d b/gas/testsuite/gas/s12z/sub-imm.d
new file mode 100644
index 0000000..7c1064a
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-imm.d
@@ -0,0 +1,21 @@
+#objdump: -d
+#name:
+#source: sub-imm.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <start>:
+ 0: 70 12 34 sub d2, #4660
+ 3: 71 12 34 sub d3, #4660
+ 6: 72 12 34 sub d4, #4660
+ 9: 73 12 34 sub d5, #4660
+ c: 74 ef sub d0, #-17
+ e: 75 34 sub d1, #52
+ 10: 76 56 78 9a sub d6, #1450744508
+ 14: bc
+ 15: 77 98 77 17 sub d7, #-1737025662
+ 19: 82
diff --git a/gas/testsuite/gas/s12z/sub-imm.s b/gas/testsuite/gas/s12z/sub-imm.s
new file mode 100644
index 0000000..1b4f38c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-imm.s
@@ -0,0 +1,8 @@
+start: sub d2, #0x1234
+ sub d3, #0x1234
+ sub d4, #0x1234
+ sub d5, #0x1234
+ sub d0, #-17
+ sub d1, #0x34
+ sub d6, #0x56789ABC
+ sub d7, #-1737025662
diff --git a/gas/testsuite/gas/s12z/sub-opr.d b/gas/testsuite/gas/s12z/sub-opr.d
new file mode 100644
index 0000000..e98e26c
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-opr.d
@@ -0,0 +1,22 @@
+#objdump: -d
+#name:
+#source: sub-opr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 84 d5 21 sub d0, \[-223,y\]
+ 3: 85 f2 00 84 sub d1, \(34000,p\)
+ 7: d0
+ 8: 80 fb sub d2, \(-s\)
+ a: 71 00 04 sub d3, #4
+ d: 82 bc sub d4, d0
+ f: 83 f9 4e ae sub d5, 85678
+ 13: 86 fe 00 4b sub d6, \[19256\]
+ 17: 38
+ 18: 87 8a sub d7, \(d4,x\)
+ 1a: 81 81 00 0b sub d3, \(11,d3\) \ No newline at end of file
diff --git a/gas/testsuite/gas/s12z/sub-opr.s b/gas/testsuite/gas/s12z/sub-opr.s
new file mode 100644
index 0000000..f1f7b54
--- /dev/null
+++ b/gas/testsuite/gas/s12z/sub-opr.s
@@ -0,0 +1,9 @@
+ sub d0, [-223,y]
+ sub d1, (34000, p)
+ sub d2, (-s)
+ sub d3, #4
+ sub d4, d0
+ sub d5, 85678
+ sub d6, [19256]
+ sub d7, (d4,x)
+ sub d3, (11, d3)
diff --git a/gas/testsuite/gas/s12z/tfr.d b/gas/testsuite/gas/s12z/tfr.d
new file mode 100644
index 0000000..58c7642
--- /dev/null
+++ b/gas/testsuite/gas/s12z/tfr.d
@@ -0,0 +1,20 @@
+#objdump: -d
+#name: The TFR (incl ZEX) instruction
+#source: tfr.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <L1>:
+ 0: 9e 45 tfr d0, d1
+ 2: 9e 58 tfr d1, x
+ 4: 9e 0a tfr d2, s
+ 6: 9e 0d tfr d2, ccl
+ 8: 9e 6e tfr d6, ccw
+ a: 9e 29 tfr d4, y
+ c: 9e 37 tfr d5, d7
+ e: 9e 5e tfr d1, ccw
+ 10: 9e 40 tfr d0, d2
diff --git a/gas/testsuite/gas/s12z/tfr.s b/gas/testsuite/gas/s12z/tfr.s
new file mode 100644
index 0000000..c61551e
--- /dev/null
+++ b/gas/testsuite/gas/s12z/tfr.s
@@ -0,0 +1,9 @@
+L1: tfr d0,d1
+ tfr d1, x
+ tfr d2, s
+ tfr d2, ccl
+ tfr d6, ccw
+ tfr d4, y
+ zex d5, d7
+ zex d1, ccw
+ zex d0, d2
diff --git a/gas/testsuite/gas/s12z/trap.d b/gas/testsuite/gas/s12z/trap.d
new file mode 100644
index 0000000..bf69613
--- /dev/null
+++ b/gas/testsuite/gas/s12z/trap.d
@@ -0,0 +1,105 @@
+#objdump: -d
+#name:
+#source: trap.s
+
+
+dump.o: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00000000 <.text>:
+ 0: 1b 92 trap #146
+ 2: 1b 93 trap #147
+ 4: 1b 94 trap #148
+ 6: 1b 95 trap #149
+ 8: 1b 96 trap #150
+ a: 1b 97 trap #151
+ c: 1b 98 trap #152
+ e: 1b 99 trap #153
+ 10: 1b 9a trap #154
+ 12: 1b 9b trap #155
+ 14: 1b 9c trap #156
+ 16: 1b 9d trap #157
+ 18: 1b 9e trap #158
+ 1a: 1b 9f trap #159
+ 1c: 1b a8 trap #168
+ 1e: 1b a9 trap #169
+ 20: 1b aa trap #170
+ 22: 1b ab trap #171
+ 24: 1b ac trap #172
+ 26: 1b ad trap #173
+ 28: 1b ae trap #174
+ 2a: 1b af trap #175
+ 2c: 1b b8 trap #184
+ 2e: 1b b9 trap #185
+ 30: 1b ba trap #186
+ 32: 1b bb trap #187
+ 34: 1b bc trap #188
+ 36: 1b bd trap #189
+ 38: 1b be trap #190
+ 3a: 1b bf trap #191
+ 3c: 1b c0 trap #192
+ 3e: 1b c1 trap #193
+ 40: 1b c2 trap #194
+ 42: 1b c3 trap #195
+ 44: 1b c4 trap #196
+ 46: 1b c5 trap #197
+ 48: 1b c6 trap #198
+ 4a: 1b c7 trap #199
+ 4c: 1b c8 trap #200
+ 4e: 1b c9 trap #201
+ 50: 1b ca trap #202
+ 52: 1b cb trap #203
+ 54: 1b cc trap #204
+ 56: 1b cd trap #205
+ 58: 1b ce trap #206
+ 5a: 1b cf trap #207
+ 5c: 1b d0 trap #208
+ 5e: 1b d1 trap #209
+ 60: 1b d2 trap #210
+ 62: 1b d3 trap #211
+ 64: 1b d4 trap #212
+ 66: 1b d5 trap #213
+ 68: 1b d6 trap #214
+ 6a: 1b d7 trap #215
+ 6c: 1b d8 trap #216
+ 6e: 1b d9 trap #217
+ 70: 1b da trap #218
+ 72: 1b db trap #219
+ 74: 1b dc trap #220
+ 76: 1b dd trap #221
+ 78: 1b de trap #222
+ 7a: 1b df trap #223
+ 7c: 1b e0 trap #224
+ 7e: 1b e1 trap #225
+ 80: 1b e2 trap #226
+ 82: 1b e3 trap #227
+ 84: 1b e4 trap #228
+ 86: 1b e5 trap #229
+ 88: 1b e6 trap #230
+ 8a: 1b e7 trap #231
+ 8c: 1b e8 trap #232
+ 8e: 1b e9 trap #233
+ 90: 1b ea trap #234
+ 92: 1b eb trap #235
+ 94: 1b ec trap #236
+ 96: 1b ed trap #237
+ 98: 1b ee trap #238
+ 9a: 1b ef trap #239
+ 9c: 1b f0 trap #240
+ 9e: 1b f1 trap #241
+ a0: 1b f2 trap #242
+ a2: 1b f3 trap #243
+ a4: 1b f4 trap #244
+ a6: 1b f5 trap #245
+ a8: 1b f6 trap #246
+ aa: 1b f7 trap #247
+ ac: 1b f8 trap #248
+ ae: 1b f9 trap #249
+ b0: 1b fa trap #250
+ b2: 1b fb trap #251
+ b4: 1b fc trap #252
+ b6: 1b fd trap #253
+ b8: 1b fe trap #254
+ ba: 1b ff trap #255
diff --git a/gas/testsuite/gas/s12z/trap.s b/gas/testsuite/gas/s12z/trap.s
new file mode 100644
index 0000000..7ea72bb
--- /dev/null
+++ b/gas/testsuite/gas/s12z/trap.s
@@ -0,0 +1,96 @@
+ trap #146
+ trap #147
+ trap #148
+ trap #149
+ trap #150
+ trap #151
+ trap #152
+ trap #153
+ trap #154
+ trap #155
+ trap #156
+ trap #157
+ trap #158
+ trap #159
+
+ trap #168
+ trap #169
+ trap #170
+ trap #171
+ trap #172
+ trap #173
+ trap #174
+ trap #175
+
+ trap #184
+ trap #185
+ trap #186
+ trap #187
+ trap #188
+ trap #189
+ trap #190
+ trap #191
+ trap #192
+ trap #193
+ trap #194
+ trap #195
+ trap #196
+ trap #197
+ trap #198
+ trap #199
+ trap #200
+ trap #201
+ trap #202
+ trap #203
+ trap #204
+ trap #205
+ trap #206
+ trap #207
+ trap #208
+ trap #209
+ trap #210
+ trap #211
+ trap #212
+ trap #213
+ trap #214
+ trap #215
+ trap #216
+ trap #217
+ trap #218
+ trap #219
+ trap #220
+ trap #221
+ trap #222
+ trap #223
+ trap #224
+ trap #225
+ trap #226
+ trap #227
+ trap #228
+ trap #229
+ trap #230
+ trap #231
+ trap #232
+ trap #233
+ trap #234
+ trap #235
+ trap #236
+ trap #237
+ trap #238
+ trap #239
+ trap #240
+ trap #241
+ trap #242
+ trap #243
+ trap #244
+ trap #245
+ trap #246
+ trap #247
+ trap #248
+ trap #249
+ trap #250
+ trap #251
+ trap #252
+ trap #253
+ trap #254
+ trap #255
diff --git a/include/ChangeLog b/include/ChangeLog
index fe9cad6..649b65c 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -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
index 0000000..72504ee
--- /dev/null
+++ b/include/elf/s12z.h
@@ -0,0 +1,36 @@
+/* s12z ELF support for BFD.
+ Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _ELF_S12Z_H
+#define _ELF_S12Z_H
+
+#include "elf/reloc-macros.h"
+
+/* Relocation types. */
+START_RELOC_NUMBERS (elf_s12z_reloc_type)
+ RELOC_NUMBER (R_S12Z_NONE, 0)
+ RELOC_NUMBER (R_S12Z_OPR, 1)
+ RELOC_NUMBER (R_S12Z_UKNWN_2, 2)
+ RELOC_NUMBER (R_S12Z_PCREL_7_15, 3)
+ RELOC_NUMBER (R_S12Z_EXT24, 4)
+ RELOC_NUMBER (R_S12Z_UKNWN_3, 5)
+ RELOC_NUMBER (R_S12Z_EXT32, 6)
+END_RELOC_NUMBERS (R_S12Z_max)
+
+#endif
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 5986f3c..fcd50a5 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 8e4c877..151e1e2 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -324,6 +324,7 @@ ALL_EMULATION_SOURCES = \
em68hc12elfb.c \
em68kelf.c \
em68kelfnbsd.c \
+ em9s12zelf.c \
emcorepe.c \
emn10200.c \
emn10300.c \
@@ -1433,6 +1434,10 @@ em68kelfnbsd.c: $(srcdir)/emulparams/m68kelfnbsd.sh \
$(ELF_DEPS) $(srcdir)/emultempl/m68kelf.em \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+em9s12zelf.c: $(srcdir)/emulparams/m9s12zelf.sh \
+ $(ELF_DEPS) $(srcdir)/emultempl/generic.em \
+ $(srcdir)/scripttempl/elfm9s12z.sc ${GEN_DEPENDS}
+
emcorepe.c: $(srcdir)/emulparams/mcorepe.sh \
$(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
diff --git a/ld/Makefile.in b/ld/Makefile.in
index afd2a4b..5cfd4ab 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -693,6 +693,7 @@ ALL_EMULATION_SOURCES = \
em68hc12elfb.c \
em68kelf.c \
em68kelfnbsd.c \
+ em9s12zelf.c \
emcorepe.c \
emn10200.c \
emn10300.c \
@@ -1305,6 +1306,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68hc12elfb.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelfnbsd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em9s12zelf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emcorepe.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emmo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@
@@ -2938,6 +2940,10 @@ em68kelfnbsd.c: $(srcdir)/emulparams/m68kelfnbsd.sh \
$(ELF_DEPS) $(srcdir)/emultempl/m68kelf.em \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+em9s12zelf.c: $(srcdir)/emulparams/m9s12zelf.sh \
+ $(ELF_DEPS) $(srcdir)/emultempl/generic.em \
+ $(srcdir)/scripttempl/elfm9s12z.sc ${GEN_DEPENDS}
+
emcorepe.c: $(srcdir)/emulparams/mcorepe.sh \
$(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 4c4ab85..3386c3d 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -402,6 +402,8 @@ m68hc12-*-*|m6812-*-*) targ_emul=m68hc12elf
targ_extra_emuls="m68hc12elfb m68hc11elf m68hc11elfb" ;;
m68*-*-netbsdelf*) targ_emul=m68kelfnbsd ;;
m68*-*-*) targ_emul=m68kelf ;;
+s12z-*-*) targ_emul=m9s12zelf
+ ;;
mcore-*-pe) targ_emul=mcorepe ;
targ_extra_ofiles="deffilep.o pe-dll.o" ;;
mcore-*-elf) targ_emul=elf32mcore
diff --git a/ld/emulparams/m9s12zelf.sh b/ld/emulparams/m9s12zelf.sh
new file mode 100644
index 0000000..7a819e8
--- /dev/null
+++ b/ld/emulparams/m9s12zelf.sh
@@ -0,0 +1,18 @@
+MACHINE=
+SCRIPT_NAME=elfm9s12z
+OUTPUT_FORMAT="elf32-s12z"
+ROM_TOP=0xFFFFFF
+ROM_SIZE=0x20000
+RAM_START_ADDR=0x001000
+RAM_SIZE=8192
+EEPROM_START_ADDR=0x100000
+EEPROM_SIZE=2048
+TEXT_MEMORY=text
+DATA_MEMORY=data
+EEPROM_MEMORY=eeprom
+ARCH=s12z
+EMBEDDED=yes
+GENERIC_BOARD=no
+TEMPLATE_NAME=elf32
+NOP=0x00
+
diff --git a/ld/scripttempl/elfm9s12z.sc b/ld/scripttempl/elfm9s12z.sc
new file mode 100644
index 0000000..c39d270
--- /dev/null
+++ b/ld/scripttempl/elfm9s12z.sc
@@ -0,0 +1,444 @@
+# Copyright (C) 2014-2018 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+# Unusual variables checked by this code:
+# NOP - four byte opcode for no-op (defaults to 0)
+# DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
+# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
+# (e.g., .PARISC.global)
+# OTHER_SECTIONS - at the end
+# EXECUTABLE_SYMBOLS - symbols that must be defined for an
+# executable (e.g., _DYNAMIC_LINK)
+# TEXT_START_SYMBOLS - symbols that appear at the start of the
+# .text section.
+# DATA_START_SYMBOLS - symbols that appear at the start of the
+# .data section.
+# OTHER_BSS_SYMBOLS - symbols that appear at the start of the
+# .bss section besides __bss_start.
+# EMBEDDED - whether this is for an embedded system.
+#
+# When adding sections, do note that the names of some sections are used
+# when specifying the start address of the next.
+#
+test -z "$ENTRY" && ENTRY=_start
+test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
+test "$LD_FLAG" = "N" && DATA_ADDR=.
+
+CTOR=".ctors ${CONSTRUCTING-0} :
+ {
+ ${CONSTRUCTING+ PROVIDE (__CTOR_LIST__ = .); }
+ ${CONSTRUCTING+${CTOR_START}}
+ KEEP (*(.ctors))
+
+ ${CONSTRUCTING+${CTOR_END}}
+ ${CONSTRUCTING+ PROVIDE(__CTOR_END__ = .); }
+ } ${RELOCATING+ > ${TEXT_MEMORY}}"
+
+DTOR=" .dtors ${CONSTRUCTING-0} :
+ {
+ ${CONSTRUCTING+ PROVIDE(__DTOR_LIST__ = .); }
+ KEEP (*(.dtors))
+ ${CONSTRUCTING+ PROVIDE(__DTOR_END__ = .); }
+ } ${RELOCATING+ > ${TEXT_MEMORY}}"
+
+
+VECTORS="
+ /* If the 'vectors_addr' symbol is defined, it indicates the start address
+ of interrupt vectors.
+
+ In general, the vectors address is 0xfffe00. This can be overriden
+ with the '-defsym vectors_addr=0xbfc000' ld option. If you do this,
+ then your startup code should also set the IVBR register accordingly.
+ */
+
+ PROVIDE (_vectors_addr = DEFINED (vectors_addr) ? vectors_addr : 0xfffe00);
+ .vectors DEFINED (vectors_addr) ? vectors_addr : 0xfffe00 :
+ {
+ KEEP (*(.vectors))
+ }"
+
+#
+# We provide two emulations: a fixed on that defines some memory banks
+# and a configurable one that includes a user provided memory definition.
+#
+case $GENERIC_BOARD in
+ yes|1|YES)
+ MEMORY_DEF="
+/* Get memory banks definition from some user configuration file.
+ This file must be located in some linker directory (search path
+ with -L<dir>). See fixed memory banks emulation script. */
+INCLUDE memory.x;
+"
+ ;;
+ *)
+MEMORY_DEF="
+/* Fixed definition of the available memory banks.
+ See generic emulation script for a user defined configuration. */
+MEMORY
+{
+ text (rx) : ORIGIN = $[$ROM_TOP - $ROM_SIZE + 1], LENGTH = ${ROM_SIZE} - 4
+ data : ORIGIN = ${RAM_START_ADDR}, LENGTH = ${RAM_SIZE}
+ eeprom : ORIGIN = ${EEPROM_START_ADDR}, LENGTH = ${EEPROM_SIZE}
+ rvec : ORIGIN = 0xFFFFFC, LENGTH = 4
+}
+
+/* Setup the stack on the top of the data memory bank. */
+PROVIDE (_stack = ${RAM_START_ADDR} + ${RAM_SIZE} - 1);
+"
+ ;;
+esac
+
+STARTUP_CODE="
+ /* Startup code. */
+ KEEP (*(.install0)) /* Section should setup the stack pointer. */
+ KEEP (*(.install1)) /* Place holder for applications. */
+ KEEP (*(.install2)) /* Optional installation of data sections in RAM. */
+ KEEP (*(.install3)) /* Place holder for applications. */
+ KEEP (*(.install4)) /* Section that calls the main. */
+"
+
+FINISH_CODE="
+ /* Finish code. */
+ KEEP (*(.fini0)) /* Beginning of finish code (_exit symbol). */
+ KEEP (*(.fini1)) /* Place holder for applications. */
+ KEEP (*(.fini2)) /* C++ destructors. */
+ KEEP (*(.fini3)) /* Place holder for applications. */
+ KEEP (*(.fini4)) /* Runtime exit. */
+"
+
+PRE_COMPUTE_DATA_SIZE="
+/* SCz: this does not work yet... This is supposed to force the loading
+ of _map_data.o (from libgcc.a) when the .data section is not empty.
+ By doing so, this should bring the code that copies the .data section
+ from ROM to RAM at init time.
+
+ ___pre_comp_data_size = SIZEOF(.data);
+ __install_data_sections = ___pre_comp_data_size > 0 ?
+ __map_data_sections : 0;
+*/
+"
+
+INSTALL_RELOC="
+ .install0 0 : { *(.install0) }
+ .install1 0 : { *(.install1) }
+ .install2 0 : { *(.install2) }
+ .install3 0 : { *(.install3) }
+ .install4 0 : { *(.install4) }
+"
+
+FINISH_RELOC="
+ .fini0 0 : { *(.fini0) }
+ .fini1 0 : { *(.fini1) }
+ .fini2 0 : { *(.fini2) }
+ .fini3 0 : { *(.fini3) }
+ .fini4 0 : { *(.fini4) }
+"
+
+BSS_DATA_RELOC="
+ .data1 0 : { *(.data1) }
+
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata 0 : { *(.sdata) }
+ .sbss 0 : { *(.sbss) }
+ .scommon 0 : { *(.scommon) }
+"
+
+SOFT_REGS_RELOC="
+ .softregs 0 : { *(.softregs) }
+"
+
+cat <<EOF
+/* Copyright (C) 2014-2018 Free Software Foundation, Inc.
+
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
+
+${RELOCATING+/* Linker script for HCS12Z executable (PROM). */}
+${RELOCATING-/* Linker script for HCS12Z object file (ld -r). */}
+
+OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
+ "${LITTLE_OUTPUT_FORMAT}")
+OUTPUT_ARCH(${OUTPUT_ARCH})
+${RELOCATING+ENTRY(${ENTRY})}
+
+${RELOCATING+${LIB_SEARCH_DIRS}}
+${RELOCATING+${EXECUTABLE_SYMBOLS}}
+${RELOCATING+${MEMORY_DEF}}
+
+PROVIDE (_start = $[$ROM_TOP - $ROM_SIZE + 1]);
+SECTIONS
+{
+ .hash ${RELOCATING-0} : { *(.hash) }
+ .dynsym ${RELOCATING-0} : { *(.dynsym) }
+ .dynstr ${RELOCATING-0} : { *(.dynstr) }
+ .gnu.version ${RELOCATING-0} : { *(.gnu.version) }
+ .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
+ .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
+
+ .rel.text ${RELOCATING-0} :
+ {
+ *(.rel.text)
+ ${RELOCATING+*(.rel.text.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.t.*)}
+ }
+ .rela.text ${RELOCATING-0} :
+ {
+ *(.rela.text)
+ ${RELOCATING+*(.rela.text.*)}
+ ${RELOCATING+*(.rela.gnu.linkonce.t.*)}
+ }
+ .rel.data ${RELOCATING-0} :
+ {
+ *(.rel.data)
+ ${RELOCATING+*(.rel.data.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.d.*)}
+ }
+ .rela.data ${RELOCATING-0} :
+ {
+ *(.rela.data)
+ ${RELOCATING+*(.rela.data.*)}
+ ${RELOCATING+*(.rela.gnu.linkonce.d.*)}
+ }
+ .rel.rodata ${RELOCATING-0} :
+ {
+ *(.rel.rodata)
+ ${RELOCATING+*(.rel.rodata.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.r.*)}
+ }
+ .rela.rodata ${RELOCATING-0} :
+ {
+ *(.rela.rodata)
+ ${RELOCATING+*(.rela.rodata.*)}
+ ${RELOCATING+*(.rela.gnu.linkonce.r.*)}
+ }
+ .rel.sdata ${RELOCATING-0} :
+ {
+ *(.rel.sdata)
+ ${RELOCATING+*(.rel.sdata.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.s.*)}
+ }
+ .rela.sdata ${RELOCATING-0} :
+ {
+ *(.rela.sdata)
+ ${RELOCATING+*(.rela.sdata.*)}
+ ${RELOCATING+*(.rela.gnu.linkonce.s.*)}
+ }
+ .rel.sbss ${RELOCATING-0} :
+ {
+ *(.rel.sbss)
+ ${RELOCATING+*(.rel.sbss.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.sb.*)}
+ }
+ .rela.sbss ${RELOCATING-0} :
+ {
+ *(.rela.sbss)
+ ${RELOCATING+*(.rela.sbss.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.sb.*)}
+ }
+ .rel.bss ${RELOCATING-0} :
+ {
+ *(.rel.bss)
+ ${RELOCATING+*(.rel.bss.*)}
+ ${RELOCATING+*(.rel.gnu.linkonce.b.*)}
+ }
+ .rela.bss ${RELOCATING-0} :
+ {
+ *(.rela.bss)
+ ${RELOCATING+*(.rela.bss.*)}
+ ${RELOCATING+*(.rela.gnu.linkonce.b.*)}
+ }
+ .rel.stext ${RELOCATING-0} : { *(.rel.stest) }
+ .rela.stext ${RELOCATING-0} : { *(.rela.stest) }
+ .rel.etext ${RELOCATING-0} : { *(.rel.etest) }
+ .rela.etext ${RELOCATING-0} : { *(.rela.etest) }
+ .rel.sdata ${RELOCATING-0} : { *(.rel.sdata) }
+ .rela.sdata ${RELOCATING-0} : { *(.rela.sdata) }
+ .rel.edata ${RELOCATING-0} : { *(.rel.edata) }
+ .rela.edata ${RELOCATING-0} : { *(.rela.edata) }
+ .rel.eit_v ${RELOCATING-0} : { *(.rel.eit_v) }
+ .rela.eit_v ${RELOCATING-0} : { *(.rela.eit_v) }
+ .rel.ebss ${RELOCATING-0} : { *(.rel.ebss) }
+ .rela.ebss ${RELOCATING-0} : { *(.rela.ebss) }
+ .rel.srodata ${RELOCATING-0} : { *(.rel.srodata) }
+ .rela.srodata ${RELOCATING-0} : { *(.rela.srodata) }
+ .rel.erodata ${RELOCATING-0} : { *(.rel.erodata) }
+ .rela.erodata ${RELOCATING-0} : { *(.rela.erodata) }
+ .rel.got ${RELOCATING-0} : { *(.rel.got) }
+ .rela.got ${RELOCATING-0} : { *(.rela.got) }
+ .rel.ctors ${RELOCATING-0} : { *(.rel.ctors) }
+ .rela.ctors ${RELOCATING-0} : { *(.rela.ctors) }
+ .rel.dtors ${RELOCATING-0} : { *(.rel.dtors) }
+ .rela.dtors ${RELOCATING-0} : { *(.rela.dtors) }
+ .rel.init ${RELOCATING-0} : { *(.rel.init) }
+ .rela.init ${RELOCATING-0} : { *(.rela.init) }
+ .rel.fini ${RELOCATING-0} : { *(.rel.fini) }
+ .rela.fini ${RELOCATING-0} : { *(.rela.fini) }
+ .rel.plt ${RELOCATING-0} : { *(.rel.plt) }
+ .rela.plt ${RELOCATING-0} : { *(.rela.plt) }
+
+ /* Start of text section. */
+ .stext ${RELOCATING-0} :
+ {
+ *(.stext)
+ } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+ .init ${RELOCATING-0} :
+ {
+ *(.init)
+ } ${RELOCATING+=${NOP-0}}
+
+ ${RELOCATING-${INSTALL_RELOC}}
+ ${RELOCATING-${FINISH_RELOC}}
+
+ .text ${RELOCATING-0}:
+ {
+ /* Put startup code at beginning so that _start keeps same address. */
+ ${RELOCATING+${STARTUP_CODE}}
+
+ ${RELOCATING+*(.init)}
+ *(.text)
+ ${RELOCATING+*(.text.*)}
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ ${RELOCATING+*(.gnu.linkonce.t.*)}
+ ${RELOCATING+*(.tramp)}
+ ${RELOCATING+*(.tramp.*)}
+
+ ${RELOCATING+${FINISH_CODE}}
+
+ ${RELOCATING+_etext = .;}
+ ${RELOCATING+PROVIDE (etext = .);}
+ ${RELOCATING+. = ALIGN(2);}
+ } ${RELOCATING+ > ${TEXT_MEMORY} =${NOP}}
+ .rvec ${RELOCATING-0} :
+ {
+ ${RELOCATING+LONG(_start);}
+ } ${RELOCATING+ > rvec}
+ .eh_frame ${RELOCATING-0} :
+ {
+ KEEP (*(.eh_frame))
+ } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+ .gcc_except_table ${RELOCATING-0} :
+ {
+ *(.gcc_except_table)
+ } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+ .rodata ${RELOCATING-0} :
+ {
+ *(.rodata)
+ ${RELOCATING+*(.rodata.*)}
+ ${RELOCATING+*(.gnu.linkonce.r*)}
+ ${RELOCATING+. = ALIGN(2);}
+ } ${RELOCATING+ > ${TEXT_MEMORY} =0xffffffff}
+
+ .rodata1 ${RELOCATING-0} :
+ {
+ *(.rodata1)
+ ${RELOCATING+. = ALIGN(2);}
+ } ${RELOCATING+ > ${TEXT_MEMORY} =0xffffffff}
+
+ /* Constructor and destructor tables are in ROM. */
+ ${RELOCATING+${CTOR}}
+ ${RELOCATING+${DTOR}}
+
+ .jcr ${RELOCATING-0} :
+ {
+ KEEP (*(.jcr))
+ } ${RELOCATING+ > ${TEXT_MEMORY}}
+
+ /* Start of the data section image in ROM. */
+ ${RELOCATING+__data_image = .;}
+ ${RELOCATING+PROVIDE (__data_image = .);}
+
+ /* All read-only sections that normally go in PROM must be above.
+ We construct the DATA image section in PROM at end of all these
+ read-only sections. The data image must be copied at init time.
+ Refer to GNU ld, Section 3.6.8.2 Output Section LMA. */
+ .data ${RELOCATING-0} : ${RELOCATING+AT (__data_image)}
+ {
+ ${RELOCATING+__data_section_start = .;}
+ ${RELOCATING+PROVIDE (__data_section_start = .);}
+
+ ${RELOCATING+${DATA_START_SYMBOLS}}
+ ${RELOCATING+*(.sdata)}
+ *(.data)
+ ${RELOCATING+*(.data.*)}
+ ${RELOCATING+*(.data1)}
+ ${RELOCATING+*(.gnu.linkonce.d.*)}
+ ${CONSTRUCTING+CONSTRUCTORS}
+
+ ${RELOCATING+_edata = .;}
+ ${RELOCATING+PROVIDE (edata = .);}
+ ${RELOCATING+. = ALIGN(2);}
+ } ${RELOCATING+ > ${DATA_MEMORY} =0xffffffff}
+
+ ${RELOCATING+__data_section_size = SIZEOF(.data);}
+ ${RELOCATING+PROVIDE (__data_section_size = SIZEOF(.data));}
+ ${RELOCATING+__data_image_end = __data_image + __data_section_size;}
+
+ ${RELOCATING+${PRE_COMPUTE_DATA_SIZE}}
+
+ /* .install ${RELOCATING-0}:
+ {
+ . = _data_image_end;
+ } ${RELOCATING+ > ${TEXT_MEMORY}} */
+
+ /* Relocation for some bss and data sections. */
+ ${RELOCATING-${BSS_DATA_RELOC}}
+ ${RELOCATING-${SOFT_REGS_RELOC}}
+
+ .bss ${RELOCATING-0} :
+ {
+ ${RELOCATING+__bss_start = .;}
+ ${RELOCATING+*(.softregs)}
+ ${RELOCATING+*(.sbss)}
+ ${RELOCATING+*(.scommon)}
+
+ *(.dynbss)
+ *(.bss)
+ ${RELOCATING+*(.bss.*)}
+ ${RELOCATING+*(.gnu.linkonce.b.*)}
+ *(COMMON)
+ ${RELOCATING+PROVIDE (_end = .);}
+ } ${RELOCATING+ > ${DATA_MEMORY}}
+ ${RELOCATING+__bss_size = SIZEOF(.bss);}
+ ${RELOCATING+PROVIDE (__bss_size = SIZEOF(.bss));}
+
+ .eeprom ${RELOCATING-0} :
+ {
+ *(.eeprom)
+ *(.eeprom.*)
+ } ${RELOCATING+ > ${EEPROM_MEMORY}}
+
+ ${RELOCATING+${VECTORS}}
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+
+ .comment 0 : { *(.comment) }
+
+ /* Treatment of DWARF debug section must be at end of the linker
+ script to avoid problems when there are undefined symbols. It's necessary
+ to avoid that the DWARF section is relocated before such undefined
+ symbols are found. */
+EOF
+
+. $srcdir/scripttempl/DWARF.sc
+
+cat <<EOF
+}
+EOF
diff --git a/ld/testsuite/ld-discard/static.d b/ld/testsuite/ld-discard/static.d
index 7a299cc..ebdbda8 100644
--- a/ld/testsuite/ld-discard/static.d
+++ b/ld/testsuite/ld-discard/static.d
@@ -3,5 +3,5 @@
#error: `(\.data\.exit|data)' referenced in section `\.text' of tmpdir/static.o: defined in discarded section `\.data\.exit' of tmpdir/static.o
#objdump: -p
#xfail: d30v-*-* dlx-*-* pj*-*-*
-#xfail: m68hc12-*-* m6812-*-*
+#xfail: m68hc12-*-* m6812-*-*
#pass
diff --git a/ld/testsuite/ld-elf/endsym.d b/ld/testsuite/ld-elf/endsym.d
index 86fda21..39667e3 100644
--- a/ld/testsuite/ld-elf/endsym.d
+++ b/ld/testsuite/ld-elf/endsym.d
@@ -2,7 +2,7 @@
#source: endsym.s
#ld: --sort-common
#nm: -n
-#xfail: m68hc1*-* xgate-* cr16-*-* crx-*-* dlx-*-* nds32*-*-* visium-*-*
+#xfail: m68hc1*-* xgate-* cr16-*-* crx-*-* dlx-*-* nds32*-*-* visium-*-* s12z-*-*
#xfail: pru-*-*
#...
diff --git a/ld/testsuite/ld-elf/merge.d b/ld/testsuite/ld-elf/merge.d
index 2ac88ea..ebabae8 100644
--- a/ld/testsuite/ld-elf/merge.d
+++ b/ld/testsuite/ld-elf/merge.d
@@ -4,7 +4,7 @@
#xfail: "bfin-*-*" "cr16-*-*" "cris*-*-*" "crx-*-*" "d10v-*-*" "d30v-*-*"
#xfail: "dlx-*-*" "fr30-*-*" "frv-*-*" "hppa*64*-*-*" "h8300-*-*" "score-*-*"
#xfail: "ip2k-*-*" "iq2000-*-*" "lm32-*-*"
-#xfail: "mcore-*-*" "mn102*-*-*" "ms1-*-*" "mep-*-*" "m68hc11-*-*" "nios2-*-*"
+#xfail: "mcore-*-*" "mn102*-*-*" "ms1-*-*" "mep-*-*" "m68hc11-*-*" "nios2-*-*" s12z-*-*
#xfail: "or32-*-*" "pj-*-*" "tic6x-*-*" "vax-*-*" "xstormy16-*-*"
#xfail: "xtensa*-*-*" "metag-*-*" "ft32-*-*" "pru-*-*"
diff --git a/ld/testsuite/ld-elf/pr14926.d b/ld/testsuite/ld-elf/pr14926.d
index 8fc8e64..4e0a8da 100644
--- a/ld/testsuite/ld-elf/pr14926.d
+++ b/ld/testsuite/ld-elf/pr14926.d
@@ -1,6 +1,6 @@
#ld: -Ttext=0x60
#readelf: -S --wide
-#notarget: d10v-* m68hc1*-* msp*-* visium-* xgate-* xstormy*-* pru-*-*
+#notarget: d10v-* m68hc1*-* msp*-* visium-* xgate-* xstormy*-* pru-*-* s12z-*-*
# the above targets use memory regions that don't allow 0x60 for .text
#...
diff --git a/ld/testsuite/ld-elf/sec64k.exp b/ld/testsuite/ld-elf/sec64k.exp
index 2495cb8..b58139e 100644
--- a/ld/testsuite/ld-elf/sec64k.exp
+++ b/ld/testsuite/ld-elf/sec64k.exp
@@ -40,6 +40,7 @@ if {[istarget "ft32-*-*"]
|| [istarget "h8300-*-*"]
|| [istarget "ip2k-*-*"]
|| [istarget "m68hc1*-*"]
+ || [istarget "s12z-*"]
|| [istarget "xgate-*"] } {
return
}
diff --git a/ld/testsuite/ld-s12z/opr-linking.d b/ld/testsuite/ld-s12z/opr-linking.d
new file mode 100644
index 0000000..05d154b
--- /dev/null
+++ b/ld/testsuite/ld-s12z/opr-linking.d
@@ -0,0 +1,20 @@
+#source: opr-linking.s
+#ld: --no-relax --defsym here=0xfe0000 --defsym=foo=0xfe0050 --defsym=bar=0xfe0010 --defsym=wiz=0xfe0040
+#objdump: -d -r
+
+tmpdir/dump: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+
+00fe0000 .*:
+ fe0000: 01 nop
+ fe0001: 01 nop
+ fe0002: 01 nop
+ fe0003: 01 nop
+ fe0004: 1b 37 f6 fa divs\.lw d7, bar, wiz
+ fe0008: fe 00 10 fa
+ fe000c: fe 00 40
+ fe000f: bc fa fe 00 clr\.b foo
+ fe0013: 50
diff --git a/ld/testsuite/ld-s12z/opr-linking.s b/ld/testsuite/ld-s12z/opr-linking.s
new file mode 100644
index 0000000..aa70566
--- /dev/null
+++ b/ld/testsuite/ld-s12z/opr-linking.s
@@ -0,0 +1,7 @@
+here:
+ nop
+ nop
+ nop
+ nop
+ divs.lw d7, bar, wiz
+ clr.b foo
diff --git a/ld/testsuite/ld-s12z/relative-linking.d b/ld/testsuite/ld-s12z/relative-linking.d
new file mode 100644
index 0000000..286fe52
--- /dev/null
+++ b/ld/testsuite/ld-s12z/relative-linking.d
@@ -0,0 +1,14 @@
+#source: relative-linking.s
+#ld: --no-relax --defsym here=0xfe0020 --defsym=foo=0xfe0008 --defsym=bar=0xfe0010 --defsym=wiz=0xfe0040
+#objdump: -d -r
+
+tmpdir/dump: file format elf32-s12z
+
+
+Disassembly of section .text:
+
+00fe0000 <here>:
+ fe0000: 20 80 08 bra foo
+ fe0003: 02 b0 bc 80 brclr.b d0, #3, bar
+ fe0007: 0d
+ fe0008: 0b 85 80 38 dbne d1, wiz
diff --git a/ld/testsuite/ld-s12z/relative-linking.s b/ld/testsuite/ld-s12z/relative-linking.s
new file mode 100644
index 0000000..fa52edb
--- /dev/null
+++ b/ld/testsuite/ld-s12z/relative-linking.s
@@ -0,0 +1,5 @@
+
+here:
+ bra foo
+ brclr.b d0, #3, bar
+ dbne d1, wiz
diff --git a/ld/testsuite/ld-s12z/z12s.exp b/ld/testsuite/ld-s12z/z12s.exp
new file mode 100644
index 0000000..4c9baa4
--- /dev/null
+++ b/ld/testsuite/ld-s12z/z12s.exp
@@ -0,0 +1,33 @@
+# Expect script for run_dump_test based ld-m68hc11 tests.
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# Test S12Z linker tests. This tests the assembler as well as the linker.
+
+if { ![istarget s12z-*-*] } {
+ return
+}
+
+set rd_test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach shtest $rd_test_list {
+ # We need to strip the ".d", but can leave the dirname.
+ verbose [file rootname $shtest]
+ run_dump_test [file rootname $shtest]
+}
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index c3f345b..a147cc3 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -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.
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index 0c7d09d..98fd7f3 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -175,6 +175,7 @@ TARGET_LIBOPCODES_CFILES = \
m68hc11-opc.c \
m68k-dis.c \
m68k-opc.c \
+ s12z-dis.c \
mcore-dis.c \
mep-asm.c \
mep-desc.c \
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index 0d85bd4..b55daea 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -477,6 +477,7 @@ TARGET_LIBOPCODES_CFILES = \
m68hc11-opc.c \
m68k-dis.c \
m68k-opc.c \
+ s12z-dis.c \
mcore-dis.c \
mep-asm.c \
mep-desc.c \
@@ -878,6 +879,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68hc11-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68k-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68k-opc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s12z-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcore-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mep-asm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mep-desc.Plo@am__quote@
diff --git a/opcodes/configure b/opcodes/configure
index c7a8805..c5f0c10 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12659,6 +12659,7 @@ if test x${all_targets} = xfalse ; then
bfd_m68hc12_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
bfd_m9s12x_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
bfd_m9s12xg_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
+ bfd_s12z_arch) ta="$ta s12z-dis.lo m68hc11-opc.lo" ;;
bfd_m68k_arch) ta="$ta m68k-dis.lo m68k-opc.lo" ;;
bfd_mcore_arch) ta="$ta mcore-dis.lo" ;;
bfd_mep_arch) ta="$ta mep-asm.lo mep-desc.lo mep-dis.lo mep-ibld.lo mep-opc.lo" using_cgen=yes ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index e42b661..86a0ca0 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -283,6 +283,7 @@ if test x${all_targets} = xfalse ; then
bfd_m68hc12_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
bfd_m9s12x_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
bfd_m9s12xg_arch) ta="$ta m68hc11-dis.lo m68hc11-opc.lo" ;;
+ bfd_s12z_arch) ta="$ta s12z-dis.lo m68hc11-opc.lo" ;;
bfd_m68k_arch) ta="$ta m68k-dis.lo m68k-opc.lo" ;;
bfd_mcore_arch) ta="$ta mcore-dis.lo" ;;
bfd_mep_arch) ta="$ta mep-asm.lo mep-desc.lo mep-dis.lo mep-ibld.lo mep-opc.lo" using_cgen=yes ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 100ccd3..c8fda59 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -251,6 +251,11 @@ disassembler (enum bfd_architecture a,
disassemble = print_insn_m9s12xg;
break;
#endif
+#if defined(ARCH_s12z)
+ case bfd_arch_s12z:
+ disassemble = print_insn_s12z;
+ break;
+#endif
#ifdef ARCH_m68k
case bfd_arch_m68k:
disassemble = print_insn_m68k;
diff --git a/opcodes/disassemble.h b/opcodes/disassemble.h
index 9d78b21..0457344 100644
--- a/opcodes/disassemble.h
+++ b/opcodes/disassemble.h
@@ -61,6 +61,7 @@ extern int print_insn_m68hc11 (bfd_vma, disassemble_info *);
extern int print_insn_m68hc12 (bfd_vma, disassemble_info *);
extern int print_insn_m9s12x (bfd_vma, disassemble_info *);
extern int print_insn_m9s12xg (bfd_vma, disassemble_info *);
+extern int print_insn_s12z (bfd_vma, disassemble_info *);
extern int print_insn_m68k (bfd_vma, disassemble_info *);
extern int print_insn_mcore (bfd_vma, disassemble_info *);
extern int print_insn_metag (bfd_vma, disassemble_info *);
diff --git a/opcodes/s12z-dis.c b/opcodes/s12z-dis.c
new file mode 100644
index 0000000..4512311
--- /dev/null
+++ b/opcodes/s12z-dis.c
@@ -0,0 +1,2672 @@
+/* s12z-dis.c -- Freescale S12Z disassembly
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This file is part of the GNU opcodes library.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include "s12z.h"
+
+#include "bfd.h"
+#include "dis-asm.h"
+
+
+#include "disassemble.h"
+
+static int
+read_memory (bfd_vma memaddr, bfd_byte* buffer, int size,
+ struct disassemble_info* info)
+{
+ int status = (*info->read_memory_func) (memaddr, buffer, size, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+ return 0;
+}
+
+typedef int (* insn_bytes_f) (bfd_vma memaddr,
+ struct disassemble_info* info);
+
+typedef void (*operands_f) (bfd_vma memaddr, struct disassemble_info* info);
+
+enum OPR_MODE
+ {
+ OPR_IMMe4,
+ OPR_REG,
+ OPR_OFXYS,
+ OPR_XY_PRE_INC,
+ OPR_XY_POST_INC,
+ OPR_XY_PRE_DEC,
+ OPR_XY_POST_DEC,
+ OPR_S_PRE_DEC,
+ OPR_S_POST_INC,
+ OPR_REG_DIRECT,
+ OPR_REG_INDIRECT,
+ OPR_IDX_DIRECT,
+ OPR_IDX_INDIRECT,
+ OPR_EXT1,
+ OPR_IDX2_REG,
+ OPR_IDX3_DIRECT,
+ OPR_IDX3_INDIRECT,
+
+ OPR_EXT18,
+ OPR_IDX3_DIRECT_REG,
+ OPR_EXT3_DIRECT,
+ OPR_EXT3_INDIRECT
+ };
+
+struct opr_pb
+{
+ uint8_t mask;
+ uint8_t value;
+ int n_operands;
+ enum OPR_MODE mode;
+};
+
+static const struct opr_pb opr_pb[] = {
+ {0xF0, 0x70, 1, OPR_IMMe4},
+ {0xF8, 0xB8, 1, OPR_REG},
+ {0xC0, 0x40, 1, OPR_OFXYS},
+ {0xEF, 0xE3, 1, OPR_XY_PRE_INC},
+ {0xEF, 0xE7, 1, OPR_XY_POST_INC},
+ {0xEF, 0xC3, 1, OPR_XY_PRE_DEC},
+ {0xEF, 0xC7, 1, OPR_XY_POST_DEC},
+ {0xFF, 0xFB, 1, OPR_S_PRE_DEC},
+ {0xFF, 0xFF, 1, OPR_S_POST_INC},
+ {0xC8, 0x88, 1, OPR_REG_DIRECT},
+ {0xE8, 0xC8, 1, OPR_REG_INDIRECT},
+
+ {0xCE, 0xC0, 2, OPR_IDX_DIRECT},
+ {0xCE, 0xC4, 2, OPR_IDX_INDIRECT},
+ {0xC0, 0x00, 2, OPR_EXT1},
+
+ {0xC8, 0x80, 3, OPR_IDX2_REG},
+ {0xFA, 0xF8, 3, OPR_EXT18},
+
+ {0xCF, 0xC2, 4, OPR_IDX3_DIRECT},
+ {0xCF, 0xC6, 4, OPR_IDX3_INDIRECT},
+
+ {0xF8, 0xE8, 4, OPR_IDX3_DIRECT_REG},
+ {0xFF, 0xFA, 4, OPR_EXT3_DIRECT},
+ {0xFF, 0xFE, 4, OPR_EXT3_INDIRECT},
+};
+
+
+/* Return the number of bytes in a OPR operand, including the XB postbyte.
+ It does not include any preceeding opcodes. */
+static int
+opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte xb;
+ int status = read_memory (memaddr, &xb, 1, info);
+ if (status < 0)
+ return status;
+
+ size_t i;
+ for (i = 0; i < sizeof (opr_pb) / sizeof (opr_pb[0]); ++i)
+ {
+ const struct opr_pb *pb = opr_pb + i;
+ if ((xb & pb->mask) == pb->value)
+ {
+ return pb->n_operands;
+ }
+ }
+
+ return 1;
+}
+
+static int
+opr_n_bytes_p1 (bfd_vma memaddr, struct disassemble_info* info)
+{
+ return 1 + opr_n_bytes (memaddr, info);
+}
+
+static int
+opr_n_bytes2 (bfd_vma memaddr, struct disassemble_info* info)
+{
+ int s = opr_n_bytes (memaddr, info);
+ s += opr_n_bytes (memaddr + s, info);
+ return s + 1;
+}
+
+enum BB_MODE
+ {
+ BB_REG_REG_REG,
+ BB_REG_REG_IMM,
+ BB_REG_OPR_REG,
+ BB_OPR_REG_REG,
+ BB_REG_OPR_IMM,
+ BB_OPR_REG_IMM
+ };
+
+struct opr_bb
+{
+ uint8_t mask;
+ uint8_t value;
+ int n_operands;
+ bool opr;
+ enum BB_MODE mode;
+};
+
+static const struct opr_bb bb_modes[] =
+ {
+ {0x60, 0x00, 2, false, BB_REG_REG_REG},
+ {0x60, 0x20, 3, false, BB_REG_REG_IMM},
+ {0x70, 0x40, 2, true, BB_REG_OPR_REG},
+ {0x70, 0x50, 2, true, BB_OPR_REG_REG},
+ {0x70, 0x60, 3, true, BB_REG_OPR_IMM},
+ {0x70, 0x70, 3, true, BB_OPR_REG_IMM}
+ };
+
+static int
+bfextins_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte bb;
+ int status = read_memory (memaddr, &bb, 1, info);
+ if (status < 0)
+ return status;
+
+ size_t i;
+ const struct opr_bb *bbs = 0;
+ for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
+ {
+ bbs = bb_modes + i;
+ if ((bb & bbs->mask) == bbs->value)
+ {
+ break;
+ }
+ }
+
+ int n = bbs->n_operands;
+ if (bbs->opr)
+ n += opr_n_bytes (memaddr + n - 1, info);
+
+ return n;
+}
+
+static int
+single (bfd_vma memaddr ATTRIBUTE_UNUSED,
+ struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+static int
+two (bfd_vma memaddr ATTRIBUTE_UNUSED,
+ struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+ return 2;
+}
+
+static int
+three (bfd_vma memaddr ATTRIBUTE_UNUSED,
+ struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+ return 3;
+}
+
+static int
+four (bfd_vma memaddr ATTRIBUTE_UNUSED,
+ struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+ return 4;
+}
+
+static int
+five (bfd_vma memaddr ATTRIBUTE_UNUSED,
+ struct disassemble_info* info ATTRIBUTE_UNUSED)
+{
+ return 5;
+}
+
+static int
+pcrel_15bit (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte byte;
+ int status = read_memory (memaddr, &byte, 1, info);
+ if (status < 0)
+ return status;
+ return (byte & 0x80) ? 3 : 2;
+}
+
+
+
+
+static void
+operand_separator (struct disassemble_info *info)
+{
+ if ((info->flags & 0x2))
+ {
+ (*info->fprintf_func) (info->stream, ", ");
+ }
+ else
+ {
+ (*info->fprintf_func) (info->stream, " ");
+ }
+
+ info->flags |= 0x2;
+}
+
+
+
+static void
+imm1 (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte byte;
+ int status = read_memory (memaddr, &byte, 1, info);
+ if (status < 0)
+ return;
+
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "#%d", byte);
+}
+
+static void
+trap_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+ imm1 (memaddr - 1, info);
+}
+
+
+const struct reg registers[S12Z_N_REGISTERS] =
+ {
+ {"d2", 2},
+ {"d3", 2},
+ {"d4", 2},
+ {"d5", 2},
+
+ {"d0", 1},
+ {"d1", 1},
+
+ {"d6", 4},
+ {"d7", 4},
+
+ {"x", 3},
+ {"y", 3},
+ {"s", 3},
+ {"p", 3},
+ {"cch", 1},
+ {"ccl", 1},
+ {"ccw", 2}
+ };
+
+static char *
+xys_from_postbyte (uint8_t postbyte)
+{
+ char *reg = "?";
+ switch ((postbyte & 0x30) >> 4)
+ {
+ case 0:
+ reg = "x";
+ break;
+ case 1:
+ reg = "y";
+ break;
+ case 2:
+ reg = "s";
+ break;
+ default:
+ reg = "?";
+ break;
+ }
+ return reg;
+}
+
+static char *
+xysp_from_postbyte (uint8_t postbyte)
+{
+ char *reg = "?";
+ switch ((postbyte & 0x30) >> 4)
+ {
+ case 0:
+ reg = "x";
+ break;
+ case 1:
+ reg = "y";
+ break;
+ case 2:
+ reg = "s";
+ break;
+ default:
+ reg = "p";
+ break;
+ }
+ return reg;
+}
+
+/* Render the symbol name whose value is ADDR or the adddress itself if there is
+ no symbol. */
+static void
+decode_possible_symbol (bfd_vma addr, struct disassemble_info *info)
+{
+ if (!info->symbol_at_address_func (addr, info))
+ {
+ (*info->fprintf_func) (info->stream, "%" 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"
+ };
+
+
+
+
+enum MUL_MODE
+ {
+ MUL_REG_REG,
+ MUL_REG_OPR,
+ MUL_REG_IMM,
+ MUL_OPR_OPR
+ };
+
+struct mb
+{
+ uint8_t mask;
+ uint8_t value;
+ enum MUL_MODE mode;
+};
+
+static const struct mb mul_table[] = {
+ {0x40, 0x00, MUL_REG_REG},
+
+ {0x47, 0x40, MUL_REG_OPR},
+ {0x47, 0x41, MUL_REG_OPR},
+ {0x47, 0x43, MUL_REG_OPR},
+
+ {0x47, 0x44, MUL_REG_IMM},
+ {0x47, 0x45, MUL_REG_IMM},
+ {0x47, 0x47, MUL_REG_IMM},
+
+ {0x43, 0x42, MUL_OPR_OPR},
+};
+
+static void
+mul_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+ uint8_t mb;
+ int status = read_memory (memaddr, &mb, 1, info);
+ if (status < 0)
+ return;
+
+
+ uint8_t byte;
+ status = read_memory (memaddr - 1, &byte, 1, info);
+ if (status < 0)
+ return;
+
+ (*info->fprintf_func) (info->stream, "%c", (mb & 0x80) ? 's' : 'u');
+
+ enum MUL_MODE mode = -1;
+ size_t i;
+ for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
+ {
+ const struct mb *mm = mul_table + i;
+ if ((mb & mm->mask) == mm->value)
+ {
+ mode = mm->mode;
+ break;
+ }
+ }
+
+ switch (mode)
+ {
+ case MUL_REG_REG:
+ break;
+ case MUL_OPR_OPR:
+ {
+ int size1 = (mb & 0x30) >> 4;
+ int size2 = (mb & 0x0c) >> 2;
+ (*info->fprintf_func) (info->stream, ".%c%c",
+ shift_size_table [size1],
+ shift_size_table [size2]);
+ }
+ break;
+ default:
+ {
+ int size = (mb & 0x3);
+ (*info->fprintf_func) (info->stream, ".%c", shift_size_table [size]);
+ }
+ break;
+ }
+
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x7].name);
+
+ switch (mode)
+ {
+ case MUL_REG_REG:
+ case MUL_REG_IMM:
+ case MUL_REG_OPR:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[(mb & 0x38) >> 3].name);
+ break;
+ default:
+ break;
+ }
+
+ switch (mode)
+ {
+ case MUL_REG_IMM:
+ operand_separator (info);
+ int size = (mb & 0x3);
+ uint32_t imm = decode_signed_value (memaddr + 1, info, size + 1);
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ break;
+ case MUL_REG_REG:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[mb & 0x07].name);
+ break;
+ case MUL_REG_OPR:
+ opr_decode (memaddr + 1, info);
+ break;
+ case MUL_OPR_OPR:
+ {
+ int first = opr_n_bytes (memaddr + 1, info);
+ opr_decode (memaddr + 1, info);
+ opr_decode (memaddr + first + 1, info);
+ break;
+ }
+ }
+}
+
+
+static int
+mul_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ int nx = 2;
+ uint8_t mb;
+ int status = read_memory (memaddr, &mb, 1, info);
+ if (status < 0)
+ return 0;
+
+ enum MUL_MODE mode = -1;
+ size_t i;
+ for (i = 0; i < sizeof (mul_table) / sizeof (mul_table[0]); ++i)
+ {
+ const struct mb *mm = mul_table + i;
+ if ((mb & mm->mask) == mm->value)
+ {
+ mode = mm->mode;
+ break;
+ }
+ }
+
+ int size = (mb & 0x3) + 1;
+
+ switch (mode)
+ {
+ case MUL_REG_IMM:
+ nx += size;
+ break;
+ case MUL_REG_REG:
+ break;
+ case MUL_REG_OPR:
+ nx += opr_n_bytes (memaddr + 1, info);
+ break;
+ case MUL_OPR_OPR:
+ {
+ int first = opr_n_bytes (memaddr + nx - 1, info);
+ nx += first;
+ int second = opr_n_bytes (memaddr + nx - 1, info);
+ nx += second;
+ }
+ break;
+ }
+
+ return nx;
+}
+
+
+enum BM_MODE {
+ BM_REG_IMM,
+ BM_RESERVED0,
+ BM_OPR_B,
+ BM_OPR_W,
+ BM_OPR_L,
+ BM_OPR_REG,
+ BM_RESERVED1
+};
+
+struct bm
+{
+ uint8_t mask;
+ uint8_t value;
+ enum BM_MODE mode;
+};
+
+static const struct bm bm_table[] = {
+ { 0xC6, 0x04, BM_REG_IMM},
+ { 0x84, 0x00, BM_REG_IMM},
+ { 0x06, 0x06, BM_REG_IMM},
+ { 0xC6, 0x44, BM_RESERVED0},
+ // 00
+ { 0x8F, 0x80, BM_OPR_B},
+ { 0x8E, 0x82, BM_OPR_W},
+ { 0x8C, 0x88, BM_OPR_L},
+
+ { 0x83, 0x81, BM_OPR_REG},
+ { 0x87, 0x84, BM_RESERVED1},
+};
+
+static void
+bm_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+ uint8_t bm;
+ int status = read_memory (memaddr, &bm, 1, info);
+ if (status < 0)
+ return;
+
+ size_t i;
+ enum BM_MODE mode = -1;
+ for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
+ {
+ const struct bm *bme = bm_table + i;
+ if ((bm & bme->mask) == bme->value)
+ {
+ mode = bme->mode;
+ break;
+ }
+ }
+
+ switch (mode)
+ {
+ case BM_REG_IMM:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[bm & 0x07].name);
+ break;
+ case BM_OPR_B:
+ (*info->fprintf_func) (info->stream, ".%c", 'b');
+ opr_decode (memaddr + 1, info);
+ break;
+ case BM_OPR_W:
+ (*info->fprintf_func) (info->stream, ".%c", 'w');
+ opr_decode (memaddr + 1, info);
+ break;
+ case BM_OPR_L:
+ (*info->fprintf_func) (info->stream, ".%c", 'l');
+ opr_decode (memaddr + 1, info);
+ break;
+ case BM_OPR_REG:
+ {
+ uint8_t xb;
+ read_memory (memaddr + 1, &xb, 1, info);
+ /* Don't emit a size suffix for register operands */
+ if ((xb & 0xF8) != 0xB8)
+ (*info->fprintf_func) (info->stream, ".%c", shift_size_table[(bm & 0x0c) >> 2]);
+ opr_decode (memaddr + 1, info);
+ }
+ break;
+ case BM_RESERVED0:
+ case BM_RESERVED1:
+ assert (0);
+ break;
+ }
+
+ uint8_t imm = 0;
+ operand_separator (info);
+ switch (mode)
+ {
+ case BM_REG_IMM:
+ {
+ imm = (bm & 0xF8) >> 3;
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ }
+ break;
+ case BM_OPR_L:
+ imm |= (bm & 0x03) << 3;
+ /* fallthrough */
+ case BM_OPR_W:
+ imm |= (bm & 0x01) << 3;
+ /* fallthrough */
+ case BM_OPR_B:
+ imm |= (bm & 0x70) >> 4;
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ break;
+ case BM_OPR_REG:
+ (*info->fprintf_func) (info->stream, "%s", registers[(bm & 0x70) >> 4].name);
+ break;
+ case BM_RESERVED0:
+ case BM_RESERVED1:
+ assert (0);
+ break;
+ }
+}
+
+
+static void
+bm_rel_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+ uint8_t bm;
+ int status = read_memory (memaddr, &bm, 1, info);
+ if (status < 0)
+ return;
+
+ size_t i;
+ enum BM_MODE mode = -1;
+ for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
+ {
+ const struct bm *bme = bm_table + i;
+ if ((bm & bme->mask) == bme->value)
+ {
+ mode = bme->mode;
+ break;
+ }
+ }
+
+ switch (mode)
+ {
+ case BM_REG_IMM:
+ break;
+ case BM_OPR_B:
+ (*info->fprintf_func) (info->stream, ".%c", 'b');
+ break;
+ case BM_OPR_W:
+ (*info->fprintf_func) (info->stream, ".%c", 'w');
+ break;
+ case BM_OPR_L:
+ (*info->fprintf_func) (info->stream, ".%c", 'l');
+ break;
+ case BM_OPR_REG:
+ {
+ uint8_t xb;
+ read_memory (memaddr + 1, &xb, 1, info);
+ /* Don't emit a size suffix for register operands */
+ if ((xb & 0xF8) != 0xB8)
+ (*info->fprintf_func) (info->stream, ".%c",
+ shift_size_table[(bm & 0x0C) >> 2]);
+ }
+ break;
+ case BM_RESERVED0:
+ case BM_RESERVED1:
+ assert (0);
+ break;
+ }
+
+ int n = 1;
+ switch (mode)
+ {
+ case BM_REG_IMM:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[bm & 0x07].name);
+ break;
+ case BM_OPR_B:
+ case BM_OPR_W:
+ case BM_OPR_L:
+ opr_decode (memaddr + 1, info);
+ n = 1 + opr_n_bytes (memaddr + 1, info);
+ break;
+ case BM_OPR_REG:
+ opr_decode (memaddr + 1, info);
+ break;
+ case BM_RESERVED0:
+ case BM_RESERVED1:
+ assert (0);
+ break;
+ }
+
+
+ int imm = 0;
+ operand_separator (info);
+ switch (mode)
+ {
+ case BM_OPR_L:
+ imm |= (bm & 0x02) << 3;
+ /* fall through */
+ case BM_OPR_W:
+ imm |= (bm & 0x01) << 3;
+ /* fall through */
+ case BM_OPR_B:
+ imm |= (bm & 0x70) >> 4;
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ break;
+ case BM_REG_IMM:
+ imm = (bm & 0xF8) >> 3;
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ break;
+ case BM_RESERVED0:
+ case BM_RESERVED1:
+ assert (0);
+ break;
+ case BM_OPR_REG:
+ (*info->fprintf_func) (info->stream, "%s", registers[(bm & 0x70) >> 4].name);
+ n += opr_n_bytes (memaddr + 1, info);
+ break;
+ }
+
+ rel_15_7 (memaddr + n, info, n + 1);
+}
+
+static int
+bm_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ uint8_t bm;
+ int status = read_memory (memaddr, &bm, 1, info);
+ if (status < 0)
+ return status;
+
+ size_t i;
+ enum BM_MODE mode = -1;
+ for (i = 0; i < sizeof (bm_table) / sizeof (bm_table[0]); ++i)
+ {
+ const struct bm *bme = bm_table + i;
+ if ((bm & bme->mask) == bme->value)
+ {
+ mode = bme->mode;
+ break;
+ }
+ }
+
+ int n = 2;
+ switch (mode)
+ {
+ case BM_REG_IMM:
+ break;
+
+ case BM_OPR_B:
+ case BM_OPR_W:
+ case BM_OPR_L:
+ n += opr_n_bytes (memaddr + 1, info);
+ break;
+ case BM_OPR_REG:
+ n += opr_n_bytes (memaddr + 1, info);
+ break;
+ default:
+ break;
+ }
+
+ return n;
+}
+
+static int
+bm_rel_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ int n = 1 + bm_n_bytes (memaddr, info);
+
+ bfd_byte rb;
+ int status = read_memory (memaddr + n - 2, &rb, 1, info);
+ if (status != 0)
+ return status;
+
+ if (rb & 0x80)
+ n++;
+
+ return n;
+}
+
+
+
+
+
+/* shift direction */
+enum SB_DIR
+ {
+ SB_LEFT,
+ SB_RIGHT
+ };
+
+enum SB_TYPE
+ {
+ SB_ARITHMETIC,
+ SB_LOGICAL
+ };
+
+
+enum SB_MODE
+ {
+ SB_REG_REG_N_EFF,
+ SB_REG_REG_N,
+ SB_REG_OPR_EFF,
+ SB_ROT,
+ SB_REG_OPR_OPR,
+ SB_OPR_N
+ };
+
+struct sb
+{
+ uint8_t mask;
+ uint8_t value;
+ enum SB_MODE mode;
+};
+
+static const struct sb sb_table[] = {
+ {0x30, 0x00, SB_REG_REG_N_EFF},
+ {0x30, 0x10, SB_REG_REG_N},
+ {0x34, 0x20, SB_REG_OPR_EFF},
+ {0x34, 0x24, SB_ROT},
+ {0x34, 0x30, SB_REG_OPR_OPR},
+ {0x34, 0x34, SB_OPR_N},
+};
+
+static int
+shift_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte sb;
+ int status = read_memory (memaddr++, &sb, 1, info);
+ if (status != 0)
+ return status;
+
+ size_t i;
+ enum SB_MODE mode = -1;
+ for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
+ {
+ const struct sb *sbe = sb_table + i;
+ if ((sb & sbe->mask) == sbe->value)
+ mode = sbe->mode;
+ }
+
+ switch (mode)
+ {
+ case SB_REG_REG_N_EFF:
+ return 2;
+ break;
+ case SB_REG_OPR_EFF:
+ case SB_ROT:
+ return 2 + opr_n_bytes (memaddr, info);
+ break;
+ case SB_REG_OPR_OPR:
+ {
+ int opr1 = opr_n_bytes (memaddr, info);
+ int opr2 = 0;
+ if ((sb & 0x30) != 0x20)
+ opr2 = opr_n_bytes (memaddr + opr1, info);
+ return 2 + opr1 + opr2;
+ }
+ break;
+ default:
+ return 3;
+ }
+
+ /* not reached */
+ return -1;
+}
+
+
+static int
+mov_imm_opr_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte byte;
+ int status = read_memory (memaddr - 1, &byte, 1, info);
+ if (status < 0)
+ return status;
+
+ int size = byte - 0x0c + 1;
+
+ return size + opr_n_bytes (memaddr + size, info) + 1;
+}
+
+static void
+mov_imm_opr (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte byte;
+ int status = read_memory (memaddr - 1, &byte, 1, info);
+ if (status < 0)
+ return ;
+
+ int size = byte - 0x0c + 1;
+ uint32_t imm = decode_signed_value (memaddr, info, size);
+
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ opr_decode (memaddr + size, info);
+}
+
+
+
+static void
+ld_18bit_decode (bfd_vma memaddr, struct disassemble_info* info)
+{
+ size_t size = 3;
+ bfd_byte buffer[3];
+ int status = read_memory (memaddr, buffer + 1, 2, info);
+ if (status < 0)
+ return ;
+
+
+ status = read_memory (memaddr - 1, buffer, 1, info);
+ if (status < 0)
+ return ;
+
+ buffer[0] = (buffer[0] & 0x30) >> 4;
+
+ size_t i;
+ uint32_t imm = 0;
+ for (i = 0; i < size; ++i)
+ {
+ imm |= buffer[i] << (8 * (size - i - 1));
+ }
+
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+}
+
+
+
+/* Loop Primitives */
+
+enum LP_MODE {
+ LP_REG,
+ LP_XY,
+ LP_OPR
+};
+
+struct lp
+{
+ uint8_t mask;
+ uint8_t value;
+ enum LP_MODE mode;
+};
+
+static const struct lp lp_mode[] = {
+ {0x08, 0x00, LP_REG},
+ {0x0C, 0x08, LP_XY},
+ {0x0C, 0x0C, LP_OPR},
+};
+
+
+static const char *lb_condition[] =
+ {
+ "ne", "eq", "pl", "mi", "gt", "le",
+ "??", "??"
+ };
+
+static int
+loop_prim_n_bytes (bfd_vma memaddr, struct disassemble_info* info)
+{
+ int mx = 0;
+ uint8_t lb;
+ read_memory (memaddr + mx++, &lb, 1, info);
+
+ enum LP_MODE mode = -1;
+ size_t i;
+ for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
+ {
+ const struct lp *pb = lp_mode + i;
+ if ((lb & pb->mask) == pb->value)
+ {
+ mode = pb->mode;
+ break;
+ }
+ }
+
+ if (mode == LP_OPR)
+ {
+ mx += opr_n_bytes (memaddr + mx, info) ;
+ }
+
+ uint8_t rb;
+ read_memory (memaddr + mx++, &rb, 1, info);
+ if (rb & 0x80)
+ mx++;
+
+ return mx + 1;
+}
+
+
+
+
+static int
+print_insn_exg_sex (bfd_vma memaddr, struct disassemble_info* info)
+{
+ uint8_t eb;
+ int status = read_memory (memaddr, &eb, 1, info);
+ if (status < 0)
+ return -1;
+
+ const struct reg *first = &registers[(eb & 0xf0) >> 4];
+ const struct reg *second = &registers[(eb & 0xf)];
+
+ if (first->bytes < second->bytes)
+ (*info->fprintf_func) (info->stream, "sex");
+ else
+ (*info->fprintf_func) (info->stream, "exg");
+
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", first->name);
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", second->name);
+ return 0;
+}
+
+
+
+static int
+print_insn_loop_primitive (bfd_vma memaddr, struct disassemble_info* info)
+{
+ int offs = 1;
+ uint8_t lb;
+ int status = read_memory (memaddr, &lb, 1, info);
+
+ char mnemonic[7];
+ int x = 0;
+ mnemonic[x++] = (lb & 0x80) ? 'd' : 't';
+ mnemonic[x++] = 'b';
+ stpcpy (mnemonic + x, lb_condition [(lb & 0x70) >> 4]);
+ x += 2;
+
+ const char *reg = NULL;
+ enum LP_MODE mode = -1;
+ size_t i;
+ for (i = 0; i < sizeof (lp_mode) / sizeof (lp_mode[0]); ++i)
+ {
+ const struct lp *pb = lp_mode + i;
+ if ((lb & pb->mask) == pb->value)
+ {
+ mode = pb->mode;
+ break;
+ }
+ }
+
+ switch (mode)
+ {
+ case LP_REG:
+ reg = registers [lb & 0x07].name;
+ break;
+ case LP_XY:
+ reg = (lb & 0x1) ? "y" : "x";
+ break;
+ case LP_OPR:
+ mnemonic[x++] = '.';
+ mnemonic[x++] = shift_size_table [lb & 0x03];
+ offs += opr_n_bytes (memaddr + 1, info);
+ break;
+ }
+
+ mnemonic[x++] = '\0';
+
+ (*info->fprintf_func) (info->stream, "%s", mnemonic);
+
+ if (mode == LP_OPR)
+ opr_decode (memaddr + 1, info);
+ else
+ {
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", reg);
+ }
+
+ rel_15_7 (memaddr + offs, info, offs + 1);
+
+ return status;
+}
+
+
+static int
+print_insn_shift (bfd_vma memaddr, struct disassemble_info* info, uint8_t byte)
+{
+ size_t i;
+ uint8_t sb;
+ int status = read_memory (memaddr, &sb, 1, info);
+ if (status < 0)
+ return status;
+
+ enum SB_DIR dir = (sb & 0x40) ? SB_LEFT : SB_RIGHT;
+ enum SB_TYPE type = (sb & 0x80) ? SB_ARITHMETIC : SB_LOGICAL;
+ enum SB_MODE mode = -1;
+ for (i = 0; i < sizeof (sb_table) / sizeof (sb_table[0]); ++i)
+ {
+ const struct sb *sbe = sb_table + i;
+ if ((sb & sbe->mask) == sbe->value)
+ mode = sbe->mode;
+ }
+
+ char mnemonic[6];
+ int x = 0;
+ if (mode == SB_ROT)
+ {
+ mnemonic[x++] = 'r';
+ mnemonic[x++] = 'o';
+ }
+ else
+ {
+ mnemonic[x++] = (type == SB_LOGICAL) ? 'l' : 'a';
+ mnemonic[x++] = 's';
+ }
+
+ mnemonic[x++] = (dir == SB_LEFT) ? 'l' : 'r';
+
+ switch (mode)
+ {
+ case SB_REG_OPR_EFF:
+ case SB_ROT:
+ case SB_REG_OPR_OPR:
+ mnemonic[x++] = '.';
+ mnemonic[x++] = shift_size_table[sb & 0x03];
+ break;
+ case SB_OPR_N:
+ {
+ uint8_t xb;
+ read_memory (memaddr + 1, &xb, 1, info);
+ /* The size suffix is not printed if the OPR operand refers
+ directly to a register, because the size is implied by the
+ size of that register. */
+ if ((xb & 0xF8) != 0xB8)
+ {
+ mnemonic[x++] = '.';
+ mnemonic[x++] = shift_size_table[sb & 0x03];
+ }
+ }
+ break;
+ default:
+ break;
+ };
+
+ mnemonic[x++] = '\0';
+
+ (*info->fprintf_func) (info->stream, "%s", mnemonic);
+
+ /* Destination register */
+ switch (mode)
+ {
+ case SB_REG_REG_N_EFF:
+ case SB_REG_REG_N:
+ case SB_REG_OPR_EFF:
+ case SB_REG_OPR_OPR:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[byte & 0x7].name);
+ break;
+
+ case SB_ROT:
+ opr_decode (memaddr + 1, info);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Source register */
+ switch (mode)
+ {
+ case SB_REG_REG_N_EFF:
+ case SB_REG_REG_N:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", registers[sb & 0x7].name);
+ break;
+
+ case SB_REG_OPR_OPR:
+ opr_decode (memaddr + 1, info);
+ break;
+
+ default:
+ break;
+ }
+
+ /* 3rd arg */
+ switch (mode)
+ {
+ case SB_REG_OPR_EFF:
+ case SB_OPR_N:
+ opr_decode (memaddr + 1, info);
+ break;
+
+ case SB_REG_REG_N:
+ if (sb & 0x08)
+ {
+ operand_separator (info);
+ if (byte & 0x10)
+ {
+ uint8_t xb;
+ read_memory (memaddr + 1, &xb, 1, info);
+ int shift = ((sb & 0x08) >> 3) | ((xb & 0x0f) << 1);
+ (*info->fprintf_func) (info->stream, "#%d", shift);
+ }
+ else
+ {
+ (*info->fprintf_func) (info->stream, "%s:%d", __FILE__, __LINE__);
+ }
+ }
+ else
+ {
+ opr_decode (memaddr + 1, info);
+ }
+ break;
+ case SB_REG_OPR_OPR:
+ {
+ uint8_t xb;
+ int n = opr_n_bytes (memaddr + 1, info);
+ read_memory (memaddr + 1 + n, &xb, 1, info);
+
+ if ((xb & 0xF0) == 0x70)
+ {
+ int imm = xb & 0x0F;
+ imm <<= 1;
+ imm |= (sb & 0x08) >> 3;
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "#%d", imm);
+ }
+ else
+ {
+ opr_decode (memaddr + 1 + n, info);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (mode)
+ {
+ case SB_REG_REG_N_EFF:
+ case SB_REG_OPR_EFF:
+ case SB_OPR_N:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "#%d",
+ (sb & 0x08) ? 2 : 1);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int
+print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
+{
+ bfd_byte byte;
+ int status = read_memory (memaddr++, &byte, 1, info);
+ if (status != 0)
+ return status;
+
+ const struct opcode *opc2 = NULL;
+ const struct opcode *opc = page1 + byte;
+ if (opc->mnemonic)
+ {
+ (*info->fprintf_func) (info->stream, "%s", opc->mnemonic);
+ }
+ else
+ {
+ /* The special cases ... */
+ switch (byte)
+ {
+ case PAGE2_PREBYTE:
+ {
+ bfd_byte byte2;
+ read_memory (memaddr++, &byte2, 1, info);
+ opc2 = page2 + byte2;
+ if (opc2->mnemonic)
+ {
+ (*info->fprintf_func) (info->stream, "%s", opc2->mnemonic);
+
+ if (opc2->operands)
+ {
+ opc2->operands (memaddr, info);
+ }
+
+ if (opc2->operands2)
+ {
+ opc2->operands2 (memaddr, info);
+ }
+ }
+ else if (byte2 >= 0x08 && byte2 <= 0x1F)
+ {
+ bfd_byte bb;
+ read_memory (memaddr, &bb, 1, info);
+ if (bb & 0x80)
+ (*info->fprintf_func) (info->stream, "bfins");
+ else
+ (*info->fprintf_func) (info->stream, "bfext");
+
+ enum BB_MODE mode = -1;
+ size_t i;
+ const struct opr_bb *bbs = 0;
+ for (i = 0; i < sizeof (bb_modes) / sizeof (bb_modes[0]); ++i)
+ {
+ bbs = bb_modes + i;
+ if ((bb & bbs->mask) == bbs->value)
+ {
+ mode = bbs->mode;
+ break;
+ }
+ }
+
+ switch (mode)
+ {
+ case BB_REG_OPR_REG:
+ case BB_REG_OPR_IMM:
+ case BB_OPR_REG_REG:
+ case BB_OPR_REG_IMM:
+ {
+ int size = (bb >> 2) & 0x03;
+ (*info->fprintf_func) (info->stream, ".%c",
+ shift_size_table [size]);
+ }
+ break;
+ default:
+ break;
+ }
+
+ int reg1 = byte2 & 0x07;
+ /* First operand */
+ switch (mode)
+ {
+ case BB_REG_REG_REG:
+ case BB_REG_REG_IMM:
+ case BB_REG_OPR_REG:
+ case BB_REG_OPR_IMM:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s",
+ registers[reg1].name);
+ break;
+ case BB_OPR_REG_REG:
+ opr_decode (memaddr + 1, info);
+ break;
+ case BB_OPR_REG_IMM:
+ opr_decode (memaddr + 2, info);
+ break;
+ }
+
+ /* Second operand */
+ switch (mode)
+ {
+ case BB_REG_REG_REG:
+ case BB_REG_REG_IMM:
+ {
+ int reg_src = (bb >> 2) & 0x07;
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s",
+ registers[reg_src].name);
+ }
+ break;
+ case BB_OPR_REG_REG:
+ case BB_OPR_REG_IMM:
+ {
+ int reg_src = (byte2 & 0x07);
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s",
+ registers[reg_src].name);
+ }
+ break;
+ case BB_REG_OPR_REG:
+ opr_decode (memaddr + 1, info);
+ break;
+ case BB_REG_OPR_IMM:
+ opr_decode (memaddr + 2, info);
+ break;
+ }
+
+ /* Third operand */
+ operand_separator (info);
+ switch (mode)
+ {
+ case BB_REG_REG_REG:
+ case BB_OPR_REG_REG:
+ case BB_REG_OPR_REG:
+ {
+ int reg_parm = bb & 0x03;
+ (*info->fprintf_func) (info->stream, "%s",
+ registers[reg_parm].name);
+ }
+ break;
+ case BB_REG_REG_IMM:
+ case BB_OPR_REG_IMM:
+ case BB_REG_OPR_IMM:
+ {
+ bfd_byte i1;
+ read_memory (memaddr + 1, &i1, 1, info);
+ int offset = i1 & 0x1f;
+ int width = bb & 0x03;
+ width <<= 3;
+ width |= i1 >> 5;
+ (*info->fprintf_func) (info->stream, "#%d:%d", width, offset);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case 0xae: /* EXG / SEX */
+ status = print_insn_exg_sex (memaddr, info);
+ break;
+ case 0x0b: /* Loop Primitives TBcc and DBcc */
+ status = print_insn_loop_primitive (memaddr, info);
+ break;
+ case 0x10: /* shift */
+ case 0x11: /* shift */
+ case 0x12: /* shift */
+ case 0x13: /* shift */
+ case 0x14: /* shift */
+ case 0x15: /* shift */
+ case 0x16: /* shift */
+ case 0x17: /* shift */
+ status = print_insn_shift (memaddr, info, byte);
+ break;
+ case 0x04: /* psh / pul */
+ {
+ read_memory (memaddr, &byte, 1, info);
+ (*info->fprintf_func) (info->stream, (byte & 0x80) ? "pul" : "psh");
+ int bit;
+ if (byte & 0x40)
+ {
+ if ((byte & 0x3F) == 0)
+ {
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", "ALL16b");
+ }
+ else
+ for (bit = 5; bit >= 0; --bit)
+ {
+ if (byte & (0x1 << bit))
+ {
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", oprregs2[bit]);
+ }
+ }
+ }
+ else
+ {
+ if ((byte & 0x3F) == 0)
+ {
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", "ALL");
+ }
+ else
+ for (bit = 5; bit >= 0; --bit)
+ {
+ if (byte & (0x1 << bit))
+ {
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "%s", oprregs1[bit]);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ operand_separator (info);
+ (*info->fprintf_func) (info->stream, "???");
+ break;
+ }
+ }
+
+ if (opc2 == NULL)
+ {
+ if (opc->operands)
+ {
+ opc->operands (memaddr, info);
+ }
+
+ if (opc->operands2)
+ {
+ opc->operands2 (memaddr, info);
+ }
+ }
+
+ int n = 0;
+
+ /* Opcodes in page2 have an additional byte */
+ if (opc2)
+ n++;
+
+ if (opc2 && opc2->insn_bytes == 0)
+ return n;
+
+ if (!opc2 && opc->insn_bytes == 0)
+ return n;
+
+ if (opc2)
+ n += opc2->insn_bytes (memaddr, info);
+ else
+ n += opc->insn_bytes (memaddr, info);
+
+ return n;
+}
diff --git a/opcodes/s12z.h b/opcodes/s12z.h
new file mode 100644
index 0000000..7e38ac5
--- /dev/null
+++ b/opcodes/s12z.h
@@ -0,0 +1,71 @@
+#ifndef S12Z_H
+#define S12Z_H
+
+/* This byte is used to prefix instructions in "page 2" of the opcode
+ space */
+#define PAGE2_PREBYTE (0x1b)
+
+struct reg
+{
+ char *name; /* The canonical name of the register */
+ int bytes; /* its size, in bytes */
+};
+
+
+/* How many registers do we have. Actually there are only 13,
+ because CCL and CCH are the low and high bytes of CCW. But
+ for assemnbly / disassembly purposes they are considered
+ distinct registers. */
+#define S12Z_N_REGISTERS 15
+
+extern const struct reg registers[S12Z_N_REGISTERS];
+
+enum {
+ REG_D2 = 0,
+ REG_D3,
+ REG_D4,
+ REG_D5,
+ REG_D0,
+ REG_D1,
+ REG_D6,
+ REG_D7,
+ REG_X,
+ REG_Y,
+ REG_S,
+ REG_P,
+ REG_CCH,
+ REG_CCL,
+ REG_CCW
+ };
+
+/* Any of the registers d0, d1, ... d7 */
+#define REG_BIT_Dn \
+((0x1U << REG_D2) | \
+ (0x1U << REG_D3) | \
+ (0x1U << REG_D4) | \
+ (0x1U << REG_D5) | \
+ (0x1U << REG_D6) | \
+ (0x1U << REG_D7) | \
+ (0x1U << REG_D0) | \
+ (0x1U << REG_D1))
+
+/* Any of the registers x, y or z */
+#define REG_BIT_XYS \
+((0x1U << REG_X) | \
+ (0x1U << REG_Y) | \
+ (0x1U << REG_S))
+
+/* Any of the registers x, y, z or p */
+#define REG_BIT_XYSP \
+((0x1U << REG_X) | \
+ (0x1U << REG_Y) | \
+ (0x1U << REG_S) | \
+ (0x1U << REG_P))
+
+/* The x register or the y register */
+#define REG_BIT_XY \
+((0x1U << REG_X) | \
+ (0x1U << REG_Y))
+
+
+#endif