[binutils-gdb] Add support for the Freescale s12z processor.
Nick Clifton
nickc@sourceware.org
Fri May 18 14:29:00 GMT 2018
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7b4ae824289504c173a597e86a00ceab452095b7
commit 7b4ae824289504c173a597e86a00ceab452095b7
Author: John Darrington <john@darrington.wattle.id.au>
Date: Fri May 18 15:26:18 2018 +0100
Add support for the Freescale s12z processor.
bfd * Makefile.am: Add s12z files.
* Makefile.in: Regenerate.
* archures.c: Add bfd_s12z_arch.
* bfd-in.h: Add exports of bfd_putb24 and bfd_putl24.
* bfd-in2.h: Regenerate.
* config.bfd: Add s12z target.
* configure.ac: Add s12z target.
* configure: Regenerate.
* cpu-s12z.c: New file.
* elf32-s12z.c: New file.
* libbfd.c (bfd_putb24): New function.
(bfd_putl24): New function.
* libbfd.h: Regenerate.
* reloc.c: Add s12z relocations.
(bfd_get_reloc_size): Handle size 5 relocs.
* targets.c: Add s12z_elf32_vec.
opcodes * Makefile.am: Add support for s12z architecture.
* configure.ac: Likewise.
* disassemble.c: Likewise.
* disassemble.h: Likewise.
* Makefile.in: Regenerate.
* configure: Regenerate.
* s12z-dis.c: New file.
* s12z.h: New file.
include * elf/s12z.h: New header.
ld * Makefile.am: Add support for s12z architecture.
* configure.tgt: Likewise.
* Makefile.in: Regenerate.
* emulparams/m9s12zelf.sh: New file.
* scripttempl/elfm9s12z.sc: New file.
* testsuite/ld-discard/static.d: Expect to fail for the s12z
target.
* testsuite/ld-elf/endsym.d: Likewise.
* testsuite/ld-elf/merge.d: Likewise.
* testsuite/ld-elf/pr14926.d: Skip for the s12z target.
* testsuite/ld-elf/sec64k.exp: Likewise.
* testsuite/ld-s12z: New directory.
* testsuite/ld-s12z/opr-linking.d: New file.
* testsuite/ld-s12z/opr-linking.s: New file.
* testsuite/ld-s12z/relative-linking.d: New file.
* testsuite/ld-s12z/relative-linking.s: New file.
* testsuite/ld-s12z/z12s.exp: New file.
gas * Makefile.am: Add support for s12z target.
* Makefile.in: Regenerate.
* NEWS: Mention the new support.
* config/tc-s12z.c: New file.
* config/tc-s12z.h: New file.
* configure.tgt: Add s12z support.
* doc/Makefile.am: Likewise.
* doc/Makefile.in: Regenerate.
* doc/all.texi: Add s12z documentation.
* doc/as.textinfo: Likewise.
* doc/c-s12z.texi: New file.
* testsuite/gas/s12z: New directory.
* testsuite/gas/s12z/abs.d: New file.
* testsuite/gas/s12z/abs.s: New file.
* testsuite/gas/s12z/adc-imm.d: New file.
* testsuite/gas/s12z/adc-imm.s: New file.
* testsuite/gas/s12z/adc-opr.d: New file.
* testsuite/gas/s12z/adc-opr.s: New file.
* testsuite/gas/s12z/add-imm.d: New file.
* testsuite/gas/s12z/add-imm.s: New file.
* testsuite/gas/s12z/add-opr.d: New file.
* testsuite/gas/s12z/add-opr.s: New file.
* testsuite/gas/s12z/and-imm.d: New file.
* testsuite/gas/s12z/and-imm.s: New file.
* testsuite/gas/s12z/and-opr.d: New file.
* testsuite/gas/s12z/and-opr.s: New file.
* testsuite/gas/s12z/and-or-cc.d: New file.
* testsuite/gas/s12z/and-or-cc.s: New file.
* testsuite/gas/s12z/bfext-special.d: New file.
* testsuite/gas/s12z/bfext-special.s: New file.
* testsuite/gas/s12z/bfext.d: New file.
* testsuite/gas/s12z/bfext.s: New file.
* testsuite/gas/s12z/bit-manip.d: New file.
* testsuite/gas/s12z/bit-manip.s: New file.
* testsuite/gas/s12z/bit.d: New file.
* testsuite/gas/s12z/bit.s: New file.
* testsuite/gas/s12z/bra-expression-defined.d: New file.
* testsuite/gas/s12z/bra-expression-defined.s: New file.
* testsuite/gas/s12z/bra-expression-undef.d: New file.
* testsuite/gas/s12z/bra-expression-undef.s: New file.
* testsuite/gas/s12z/bra.d: New file.
* testsuite/gas/s12z/bra.s: New file.
* testsuite/gas/s12z/brclr-symbols.d: New file.
* testsuite/gas/s12z/brclr-symbols.s: New file.
* testsuite/gas/s12z/brset-clr-opr-imm-rel.d: New file.
* testsuite/gas/s12z/brset-clr-opr-imm-rel.s: New file.
* testsuite/gas/s12z/brset-clr-opr-reg-rel.d: New file.
* testsuite/gas/s12z/brset-clr-opr-reg-rel.s: New file.
* testsuite/gas/s12z/brset-clr-reg-imm-rel.d: New file.
* testsuite/gas/s12z/brset-clr-reg-imm-rel.s: New file.
* testsuite/gas/s12z/brset-clr-reg-reg-rel.d: New file.
* testsuite/gas/s12z/brset-clr-reg-reg-rel.s: New file.
* testsuite/gas/s12z/clb.d: New file.
* testsuite/gas/s12z/clb.s: New file.
* testsuite/gas/s12z/clr-opr.d: New file.
* testsuite/gas/s12z/clr-opr.s: New file.
* testsuite/gas/s12z/clr.d: New file.
* testsuite/gas/s12z/clr.s: New file.
* testsuite/gas/s12z/cmp-imm.d: New file.
* testsuite/gas/s12z/cmp-imm.s: New file.
* testsuite/gas/s12z/cmp-opr-inc.d: New file.
* testsuite/gas/s12z/cmp-opr-inc.s: New file.
* testsuite/gas/s12z/cmp-opr-rdirect.d: New file.
* testsuite/gas/s12z/cmp-opr-rdirect.s: New file.
* testsuite/gas/s12z/cmp-opr-reg.d: New file.
* testsuite/gas/s12z/cmp-opr-reg.s: New file.
* testsuite/gas/s12z/cmp-opr-rindirect.d: New file.
* testsuite/gas/s12z/cmp-opr-rindirect.s: New file.
* testsuite/gas/s12z/cmp-opr-sxe4.d: New file.
* testsuite/gas/s12z/cmp-opr-sxe4.s: New file.
* testsuite/gas/s12z/cmp-opr-xys.d: New file.
* testsuite/gas/s12z/cmp-opr-xys.s: New file.
* testsuite/gas/s12z/cmp-s-imm.d: New file.
* testsuite/gas/s12z/cmp-s-imm.s: New file.
* testsuite/gas/s12z/cmp-s-opr.d: New file.
* testsuite/gas/s12z/cmp-s-opr.s: New file.
* testsuite/gas/s12z/cmp-xy.d: New file.
* testsuite/gas/s12z/cmp-xy.s: New file.
* testsuite/gas/s12z/com-opr.d: New file.
* testsuite/gas/s12z/com-opr.s: New file.
* testsuite/gas/s12z/complex-shifts.d: New file.
* testsuite/gas/s12z/complex-shifts.s: New file.
* testsuite/gas/s12z/db-tb-cc-opr.d: New file.
* testsuite/gas/s12z/db-tb-cc-opr.s: New file.
* testsuite/gas/s12z/db-tb-cc-reg.d: New file.
* testsuite/gas/s12z/db-tb-cc-reg.s: New file.
* testsuite/gas/s12z/dbCC.d: New file.
* testsuite/gas/s12z/dbCC.s: New file.
* testsuite/gas/s12z/dec-opr.d: New file.
* testsuite/gas/s12z/dec-opr.s: New file.
* testsuite/gas/s12z/dec.d: New file.
* testsuite/gas/s12z/dec.s: New file.
* testsuite/gas/s12z/div.d: New file.
* testsuite/gas/s12z/div.s: New file.
* testsuite/gas/s12z/eor.d: New file.
* testsuite/gas/s12z/eor.s: New file.
* testsuite/gas/s12z/exg.d: New file.
* testsuite/gas/s12z/exg.s: New file.
* testsuite/gas/s12z/ext24-ld-xy.d: New file.
* testsuite/gas/s12z/ext24-ld-xy.s: New file.
* testsuite/gas/s12z/inc-opr.d: New file.
* testsuite/gas/s12z/inc-opr.s: New file.
* testsuite/gas/s12z/inc.d: New file.
* testsuite/gas/s12z/inc.s: New file.
* testsuite/gas/s12z/inh.d: New file.
* testsuite/gas/s12z/inh.s: New file.
* testsuite/gas/s12z/jmp.d: New file.
* testsuite/gas/s12z/jmp.s: New file.
* testsuite/gas/s12z/jsr.d: New file.
* testsuite/gas/s12z/jsr.s: New file.
* testsuite/gas/s12z/ld-imm-page2.d: New file.
* testsuite/gas/s12z/ld-imm-page2.s: New file.
* testsuite/gas/s12z/ld-imm.d: New file.
* testsuite/gas/s12z/ld-imm.s: New file.
* testsuite/gas/s12z/ld-immu18.d: New file.
* testsuite/gas/s12z/ld-immu18.s: New file.
* testsuite/gas/s12z/ld-large-direct.d: New file.
* testsuite/gas/s12z/ld-large-direct.s: New file.
* testsuite/gas/s12z/ld-opr.d: New file.
* testsuite/gas/s12z/ld-opr.s: New file.
* testsuite/gas/s12z/ld-s-opr.d: New file.
* testsuite/gas/s12z/ld-s-opr.s: New file.
* testsuite/gas/s12z/ld-small-direct.d: New file.
* testsuite/gas/s12z/ld-small-direct.s: New file.
* testsuite/gas/s12z/lea-immu18.d: New file.
* testsuite/gas/s12z/lea-immu18.s: New file.
* testsuite/gas/s12z/lea.d: New file.
* testsuite/gas/s12z/lea.s: New file.
* testsuite/gas/s12z/mac.d: New file.
* testsuite/gas/s12z/mac.s: New file.
* testsuite/gas/s12z/min-max.d: New file.
* testsuite/gas/s12z/min-max.s: New file.
* testsuite/gas/s12z/mod.d: New file.
* testsuite/gas/s12z/mod.s: New file.
* testsuite/gas/s12z/mov.d: New file.
* testsuite/gas/s12z/mov.s: New file.
* testsuite/gas/s12z/mul-imm.d: New file.
* testsuite/gas/s12z/mul-imm.s: New file.
* testsuite/gas/s12z/mul-opr-opr.d: New file.
* testsuite/gas/s12z/mul-opr-opr.s: New file.
* testsuite/gas/s12z/mul-opr.d: New file.
* testsuite/gas/s12z/mul-opr.s: New file.
* testsuite/gas/s12z/mul-reg.d: New file.
* testsuite/gas/s12z/mul-reg.s: New file.
* testsuite/gas/s12z/mul.d: New file.
* testsuite/gas/s12z/mul.s: New file.
* testsuite/gas/s12z/neg-opr.d: New file.
* testsuite/gas/s12z/neg-opr.s: New file.
* testsuite/gas/s12z/not-so-simple-shifts.d: New file.
* testsuite/gas/s12z/not-so-simple-shifts.s: New file.
* testsuite/gas/s12z/opr-18u.d: New file.
* testsuite/gas/s12z/opr-18u.s: New file.
* testsuite/gas/s12z/opr-expr.d: New file.
* testsuite/gas/s12z/opr-expr.s: New file.
* testsuite/gas/s12z/opr-ext-18.d: New file.
* testsuite/gas/s12z/opr-ext-18.s: New file.
* testsuite/gas/s12z/opr-idx-24-reg.d: New file.
* testsuite/gas/s12z/opr-idx-24-reg.s: New file.
* testsuite/gas/s12z/opr-idx3-reg.d: New file.
* testsuite/gas/s12z/opr-idx3-reg.s: New file.
* testsuite/gas/s12z/opr-idx3-xysp-24.d: New file.
* testsuite/gas/s12z/opr-idx3-xysp-24.s: New file.
* testsuite/gas/s12z/opr-indirect-expr.d: New file.
* testsuite/gas/s12z/opr-indirect-expr.s: New file.
* testsuite/gas/s12z/opr-symbol.d: New file.
* testsuite/gas/s12z/opr-symbol.s: New file.
* testsuite/gas/s12z/or-imm.d: New file.
* testsuite/gas/s12z/or-imm.s: New file.
* testsuite/gas/s12z/or-opr.d: New file.
* testsuite/gas/s12z/or-opr.s: New file.
* testsuite/gas/s12z/p2-mul.d: New file.
* testsuite/gas/s12z/p2-mul.s: New file.
* testsuite/gas/s12z/page2-inh.d: New file.
* testsuite/gas/s12z/page2-inh.s: New file.
* testsuite/gas/s12z/psh-pul.d: New file.
* testsuite/gas/s12z/psh-pul.s: New file.
* testsuite/gas/s12z/qmul.d: New file.
* testsuite/gas/s12z/qmul.s: New file.
* testsuite/gas/s12z/rotate.d: New file.
* testsuite/gas/s12z/rotate.s: New file.
* testsuite/gas/s12z/s12z.exp: New file.
* testsuite/gas/s12z/sat.d: New file.
* testsuite/gas/s12z/sat.s: New file.
* testsuite/gas/s12z/sbc-imm.d: New file.
* testsuite/gas/s12z/sbc-imm.s: New file.
* testsuite/gas/s12z/sbc-opr.d: New file.
* testsuite/gas/s12z/sbc-opr.s: New file.
* testsuite/gas/s12z/shift.d: New file.
* testsuite/gas/s12z/shift.s: New file.
* testsuite/gas/s12z/simple-shift.d: New file.
* testsuite/gas/s12z/simple-shift.s: New file.
* testsuite/gas/s12z/single-ops.d: New file.
* testsuite/gas/s12z/single-ops.s: New file.
* testsuite/gas/s12z/specd6.d: New file.
* testsuite/gas/s12z/specd6.s: New file.
* testsuite/gas/s12z/st-large-direct.d: New file.
* testsuite/gas/s12z/st-large-direct.s: New file.
* testsuite/gas/s12z/st-opr.d: New file.
* testsuite/gas/s12z/st-opr.s: New file.
* testsuite/gas/s12z/st-s-opr.d: New file.
* testsuite/gas/s12z/st-s-opr.s: New file.
* testsuite/gas/s12z/st-small-direct.d: New file.
* testsuite/gas/s12z/st-small-direct.s: New file.
* testsuite/gas/s12z/st-xy.d: New file.
* testsuite/gas/s12z/st-xy.s: New file.
* testsuite/gas/s12z/sub-imm.d: New file.
* testsuite/gas/s12z/sub-imm.s: New file.
* testsuite/gas/s12z/sub-opr.d: New file.
* testsuite/gas/s12z/sub-opr.s: New file.
* testsuite/gas/s12z/tfr.d: New file.
* testsuite/gas/s12z/tfr.s: New file.
* testsuite/gas/s12z/trap.d: New file.
* testsuite/gas/s12z/trap.s: New file.
binutils* readelf.c: Add support for s12z architecture.
* testsuite/lib/binutils-common.exp (is_elf_format): Excluse s12z
targets.
Diff:
---
bfd/ChangeLog | 19 +
bfd/Makefile.am | 4 +
bfd/Makefile.in | 6 +
bfd/archures.c | 4 +
bfd/bfd-in.h | 2 +
bfd/bfd-in2.h | 9 +
bfd/config.bfd | 4 +
bfd/configure | 1 +
bfd/configure.ac | 1 +
bfd/cpu-s12z.c | 41 +
bfd/elf32-s12z.c | 270 ++
bfd/libbfd.c | 21 +
bfd/libbfd.h | 1 +
bfd/reloc.c | 17 +
bfd/targets.c | 3 +
binutils/ChangeLog | 6 +
binutils/readelf.c | 7 +
binutils/testsuite/binutils-all/dw2-1.S | 2 +
binutils/testsuite/lib/binutils-common.exp | 2 +-
gas/ChangeLog | 216 ++
gas/Makefile.am | 2 +
gas/Makefile.in | 17 +
gas/NEWS | 2 +
gas/config/tc-s12z.c | 3840 +++++++++++++++++++++++
gas/config/tc-s12z.h | 105 +
gas/configure.tgt | 3 +
gas/doc/Makefile.am | 1 +
gas/doc/Makefile.in | 1 +
gas/doc/all.texi | 1 +
gas/doc/as.texinfo | 7 +
gas/doc/c-s12z.texi | 212 ++
gas/testsuite/gas/s12z/abs.d | 19 +
gas/testsuite/gas/s12z/abs.s | 8 +
gas/testsuite/gas/s12z/adc-imm.d | 21 +
gas/testsuite/gas/s12z/adc-imm.s | 8 +
gas/testsuite/gas/s12z/adc-opr.d | 21 +
gas/testsuite/gas/s12z/adc-opr.s | 9 +
gas/testsuite/gas/s12z/add-imm.d | 21 +
gas/testsuite/gas/s12z/add-imm.s | 8 +
gas/testsuite/gas/s12z/add-opr.d | 21 +
gas/testsuite/gas/s12z/add-opr.s | 9 +
gas/testsuite/gas/s12z/and-imm.d | 21 +
gas/testsuite/gas/s12z/and-imm.s | 8 +
gas/testsuite/gas/s12z/and-opr.d | 22 +
gas/testsuite/gas/s12z/and-opr.s | 9 +
gas/testsuite/gas/s12z/and-or-cc.d | 13 +
gas/testsuite/gas/s12z/and-or-cc.s | 2 +
gas/testsuite/gas/s12z/bfext-special.d | 13 +
gas/testsuite/gas/s12z/bfext-special.s | 2 +
gas/testsuite/gas/s12z/bfext.d | 47 +
gas/testsuite/gas/s12z/bfext.s | 23 +
gas/testsuite/gas/s12z/bit-manip.d | 26 +
gas/testsuite/gas/s12z/bit-manip.s | 16 +
gas/testsuite/gas/s12z/bit.d | 33 +
gas/testsuite/gas/s12z/bit.s | 17 +
gas/testsuite/gas/s12z/bra-expression-defined.d | 23 +
gas/testsuite/gas/s12z/bra-expression-defined.s | 11 +
gas/testsuite/gas/s12z/bra-expression-undef.d | 24 +
gas/testsuite/gas/s12z/bra-expression-undef.s | 9 +
gas/testsuite/gas/s12z/bra.d | 34 +
gas/testsuite/gas/s12z/bra.s | 20 +
gas/testsuite/gas/s12z/brclr-symbols.d | 32 +
gas/testsuite/gas/s12z/brclr-symbols.s | 9 +
gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.d | 23 +
gas/testsuite/gas/s12z/brset-clr-opr-imm-rel.s | 7 +
gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.d | 21 +
gas/testsuite/gas/s12z/brset-clr-opr-reg-rel.s | 5 +
gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.d | 24 +
gas/testsuite/gas/s12z/brset-clr-reg-imm-rel.s | 12 +
gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.d | 19 +
gas/testsuite/gas/s12z/brset-clr-reg-reg-rel.s | 6 +
gas/testsuite/gas/s12z/clb.d | 19 +
gas/testsuite/gas/s12z/clb.s | 8 +
gas/testsuite/gas/s12z/clr-opr.d | 15 +
gas/testsuite/gas/s12z/clr-opr.s | 5 +
gas/testsuite/gas/s12z/clr.d | 21 +
gas/testsuite/gas/s12z/clr.s | 10 +
gas/testsuite/gas/s12z/cmp-imm.d | 23 +
gas/testsuite/gas/s12z/cmp-imm.s | 12 +
gas/testsuite/gas/s12z/cmp-opr-inc.d | 21 +
gas/testsuite/gas/s12z/cmp-opr-inc.s | 11 +
gas/testsuite/gas/s12z/cmp-opr-rdirect.d | 19 +
gas/testsuite/gas/s12z/cmp-opr-rdirect.s | 9 +
gas/testsuite/gas/s12z/cmp-opr-reg.d | 19 +
gas/testsuite/gas/s12z/cmp-opr-reg.s | 9 +
gas/testsuite/gas/s12z/cmp-opr-rindirect.d | 19 +
gas/testsuite/gas/s12z/cmp-opr-rindirect.s | 9 +
gas/testsuite/gas/s12z/cmp-opr-sxe4.d | 21 +
gas/testsuite/gas/s12z/cmp-opr-sxe4.s | 10 +
gas/testsuite/gas/s12z/cmp-opr-xys.d | 19 +
gas/testsuite/gas/s12z/cmp-opr-xys.s | 9 +
gas/testsuite/gas/s12z/cmp-s-imm.d | 27 +
gas/testsuite/gas/s12z/cmp-s-imm.s | 10 +
gas/testsuite/gas/s12z/cmp-s-opr.d | 25 +
gas/testsuite/gas/s12z/cmp-s-opr.s | 10 +
gas/testsuite/gas/s12z/cmp-xy.d | 12 +
gas/testsuite/gas/s12z/cmp-xy.s | 1 +
gas/testsuite/gas/s12z/com-opr.d | 15 +
gas/testsuite/gas/s12z/com-opr.s | 3 +
gas/testsuite/gas/s12z/complex-shifts.d | 18 +
gas/testsuite/gas/s12z/complex-shifts.s | 4 +
gas/testsuite/gas/s12z/db-tb-cc-opr.d | 30 +
gas/testsuite/gas/s12z/db-tb-cc-opr.s | 11 +
gas/testsuite/gas/s12z/db-tb-cc-reg.d | 31 +
gas/testsuite/gas/s12z/db-tb-cc-reg.s | 21 +
gas/testsuite/gas/s12z/dbCC.d | 27 +
gas/testsuite/gas/s12z/dbCC.s | 7 +
gas/testsuite/gas/s12z/dec-opr.d | 15 +
gas/testsuite/gas/s12z/dec-opr.s | 3 +
gas/testsuite/gas/s12z/dec.d | 19 +
gas/testsuite/gas/s12z/dec.s | 8 +
gas/testsuite/gas/s12z/div.d | 23 +
gas/testsuite/gas/s12z/div.s | 8 +
gas/testsuite/gas/s12z/eor.d | 33 +
gas/testsuite/gas/s12z/eor.s | 17 +
gas/testsuite/gas/s12z/exg.d | 29 +
gas/testsuite/gas/s12z/exg.s | 18 +
gas/testsuite/gas/s12z/ext24-ld-xy.d | 12 +
gas/testsuite/gas/s12z/ext24-ld-xy.s | 2 +
gas/testsuite/gas/s12z/inc-opr.d | 15 +
gas/testsuite/gas/s12z/inc-opr.s | 3 +
gas/testsuite/gas/s12z/inc.d | 19 +
gas/testsuite/gas/s12z/inc.s | 8 +
gas/testsuite/gas/s12z/inh.d | 15 +
gas/testsuite/gas/s12z/inh.s | 5 +
gas/testsuite/gas/s12z/jmp.d | 33 +
gas/testsuite/gas/s12z/jmp.s | 20 +
gas/testsuite/gas/s12z/jsr.d | 33 +
gas/testsuite/gas/s12z/jsr.s | 20 +
gas/testsuite/gas/s12z/ld-imm-page2.d | 15 +
gas/testsuite/gas/s12z/ld-imm-page2.s | 2 +
gas/testsuite/gas/s12z/ld-imm.d | 25 +
gas/testsuite/gas/s12z/ld-imm.s | 16 +
gas/testsuite/gas/s12z/ld-immu18.d | 28 +
gas/testsuite/gas/s12z/ld-immu18.s | 10 +
gas/testsuite/gas/s12z/ld-large-direct.d | 21 +
gas/testsuite/gas/s12z/ld-large-direct.s | 11 +
gas/testsuite/gas/s12z/ld-opr.d | 22 +
gas/testsuite/gas/s12z/ld-opr.s | 10 +
gas/testsuite/gas/s12z/ld-s-opr.d | 16 +
gas/testsuite/gas/s12z/ld-s-opr.s | 4 +
gas/testsuite/gas/s12z/ld-small-direct.d | 31 +
gas/testsuite/gas/s12z/ld-small-direct.s | 11 +
gas/testsuite/gas/s12z/lea-immu18.d | 14 +
gas/testsuite/gas/s12z/lea-immu18.s | 3 +
gas/testsuite/gas/s12z/lea.d | 18 +
gas/testsuite/gas/s12z/lea.s | 8 +
gas/testsuite/gas/s12z/mac.d | 23 +
gas/testsuite/gas/s12z/mac.s | 8 +
gas/testsuite/gas/s12z/min-max.d | 48 +
gas/testsuite/gas/s12z/min-max.s | 32 +
gas/testsuite/gas/s12z/mod.d | 23 +
gas/testsuite/gas/s12z/mod.s | 8 +
gas/testsuite/gas/s12z/mov.d | 26 +
gas/testsuite/gas/s12z/mov.s | 8 +
gas/testsuite/gas/s12z/mul-imm.d | 19 +
gas/testsuite/gas/s12z/mul-imm.s | 6 +
gas/testsuite/gas/s12z/mul-opr-opr.d | 19 +
gas/testsuite/gas/s12z/mul-opr-opr.s | 6 +
gas/testsuite/gas/s12z/mul-opr.d | 17 +
gas/testsuite/gas/s12z/mul-opr.s | 6 +
gas/testsuite/gas/s12z/mul-reg.d | 27 +
gas/testsuite/gas/s12z/mul-reg.s | 16 +
gas/testsuite/gas/s12z/mul.d | 19 +
gas/testsuite/gas/s12z/mul.s | 6 +
gas/testsuite/gas/s12z/neg-opr.d | 34 +
gas/testsuite/gas/s12z/neg-opr.s | 21 +
gas/testsuite/gas/s12z/not-so-simple-shifts.d | 17 +
gas/testsuite/gas/s12z/not-so-simple-shifts.s | 4 +
gas/testsuite/gas/s12z/opr-18u.d | 26 +
gas/testsuite/gas/s12z/opr-18u.s | 15 +
gas/testsuite/gas/s12z/opr-expr.d | 13 +
gas/testsuite/gas/s12z/opr-expr.s | 5 +
gas/testsuite/gas/s12z/opr-ext-18.d | 13 +
gas/testsuite/gas/s12z/opr-ext-18.s | 5 +
gas/testsuite/gas/s12z/opr-idx-24-reg.d | 13 +
gas/testsuite/gas/s12z/opr-idx-24-reg.s | 2 +
gas/testsuite/gas/s12z/opr-idx3-reg.d | 17 +
gas/testsuite/gas/s12z/opr-idx3-reg.s | 3 +
gas/testsuite/gas/s12z/opr-idx3-xysp-24.d | 15 +
gas/testsuite/gas/s12z/opr-idx3-xysp-24.s | 3 +
gas/testsuite/gas/s12z/opr-indirect-expr.d | 14 +
gas/testsuite/gas/s12z/opr-indirect-expr.s | 1 +
gas/testsuite/gas/s12z/opr-symbol.d | 170 +
gas/testsuite/gas/s12z/opr-symbol.s | 109 +
gas/testsuite/gas/s12z/or-imm.d | 21 +
gas/testsuite/gas/s12z/or-imm.s | 8 +
gas/testsuite/gas/s12z/or-opr.d | 21 +
gas/testsuite/gas/s12z/or-opr.s | 8 +
gas/testsuite/gas/s12z/p2-mul.d | 17 +
gas/testsuite/gas/s12z/p2-mul.s | 7 +
gas/testsuite/gas/s12z/page2-inh.d | 15 +
gas/testsuite/gas/s12z/page2-inh.s | 5 +
gas/testsuite/gas/s12z/psh-pul.d | 21 +
gas/testsuite/gas/s12z/psh-pul.s | 8 +
gas/testsuite/gas/s12z/qmul.d | 23 +
gas/testsuite/gas/s12z/qmul.s | 8 +
gas/testsuite/gas/s12z/rotate.d | 22 +
gas/testsuite/gas/s12z/rotate.s | 10 +
gas/testsuite/gas/s12z/s12z.exp | 132 +
gas/testsuite/gas/s12z/sat.d | 19 +
gas/testsuite/gas/s12z/sat.s | 8 +
gas/testsuite/gas/s12z/sbc-imm.d | 21 +
gas/testsuite/gas/s12z/sbc-imm.s | 8 +
gas/testsuite/gas/s12z/sbc-opr.d | 23 +
gas/testsuite/gas/s12z/sbc-opr.s | 9 +
gas/testsuite/gas/s12z/shift.d | 22 +
gas/testsuite/gas/s12z/shift.s | 11 +
gas/testsuite/gas/s12z/simple-shift.d | 18 +
gas/testsuite/gas/s12z/simple-shift.s | 9 +
gas/testsuite/gas/s12z/single-ops.d | 15 +
gas/testsuite/gas/s12z/single-ops.s | 4 +
gas/testsuite/gas/s12z/specd6.d | 14 +
gas/testsuite/gas/s12z/specd6.s | 4 +
gas/testsuite/gas/s12z/st-large-direct.d | 21 +
gas/testsuite/gas/s12z/st-large-direct.s | 11 +
gas/testsuite/gas/s12z/st-opr.d | 22 +
gas/testsuite/gas/s12z/st-opr.s | 10 +
gas/testsuite/gas/s12z/st-s-opr.d | 16 +
gas/testsuite/gas/s12z/st-s-opr.s | 4 +
gas/testsuite/gas/s12z/st-small-direct.d | 34 +
gas/testsuite/gas/s12z/st-small-direct.s | 12 +
gas/testsuite/gas/s12z/st-xy.d | 12 +
gas/testsuite/gas/s12z/st-xy.s | 3 +
gas/testsuite/gas/s12z/sub-imm.d | 21 +
gas/testsuite/gas/s12z/sub-imm.s | 8 +
gas/testsuite/gas/s12z/sub-opr.d | 22 +
gas/testsuite/gas/s12z/sub-opr.s | 9 +
gas/testsuite/gas/s12z/tfr.d | 20 +
gas/testsuite/gas/s12z/tfr.s | 9 +
gas/testsuite/gas/s12z/trap.d | 105 +
gas/testsuite/gas/s12z/trap.s | 96 +
include/ChangeLog | 4 +
include/elf/s12z.h | 36 +
ld/ChangeLog | 20 +
ld/Makefile.am | 5 +
ld/Makefile.in | 6 +
ld/configure.tgt | 2 +
ld/emulparams/m9s12zelf.sh | 18 +
ld/scripttempl/elfm9s12z.sc | 444 +++
ld/testsuite/ld-discard/static.d | 2 +-
ld/testsuite/ld-elf/endsym.d | 2 +-
ld/testsuite/ld-elf/merge.d | 2 +-
ld/testsuite/ld-elf/pr14926.d | 2 +-
ld/testsuite/ld-elf/sec64k.exp | 1 +
ld/testsuite/ld-s12z/opr-linking.d | 20 +
ld/testsuite/ld-s12z/opr-linking.s | 7 +
ld/testsuite/ld-s12z/relative-linking.d | 14 +
ld/testsuite/ld-s12z/relative-linking.s | 5 +
ld/testsuite/ld-s12z/z12s.exp | 33 +
opcodes/ChangeLog | 11 +
opcodes/Makefile.am | 1 +
opcodes/Makefile.in | 2 +
opcodes/configure | 1 +
opcodes/configure.ac | 1 +
opcodes/disassemble.c | 5 +
opcodes/disassemble.h | 1 +
opcodes/s12z-dis.c | 2672 ++++++++++++++++
opcodes/s12z.h | 71 +
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, ®))
+ {
+ *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, ®))
+ {
+ 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, ®))
+ {
+ if (!lex_force_match (','))
+ goto fail;
+
+ int reg2;
+ if (lex_reg_name (REG_BIT_XY, ®2))
+ {
+ *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, ®2))
+ {
+ 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, ®2))
+ {
+ 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, ®))
+ {
+ if (lex_match (','))
+ {
+ int reg2;
+ if (lex_reg_name (REG_BIT_XYS, ®2))
+ {
+ *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, ®))
+ {
+ 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, ®))
+ {
+ *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, ®))
+ {
+ *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, ®))
+ {
+ 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, ®))
+ {
+ 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, ®))
+ 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, ®1))
+ 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, ®_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, ®1))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ int reg2;
+ if (!lex_reg_name (~0, ®2))
+ 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, ®))
+ {
+ 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, ®))
+ {
+ if (lex_force_match (','))
+ {
+ if (lex_reg_name (0x1U << REG_Y, ®))
+ {
+ 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, ®))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_X, ®))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_Y, ®))
+ 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, ®))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_Y, ®))
+ goto fail;
+
+ if (!lex_match (','))
+ goto fail;
+
+ if (!lex_reg_name (0x1U << REG_X, ®))
+ 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, ®))
+ {
+ 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), ®))
+ 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[...]
[diff truncated at 100000 bytes]
More information about the Binutils-cvs
mailing list