aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorKuan-Lin Chen <kuanlinchentw@gmail.com>2013-12-13 11:52:32 +0000
committerNick Clifton <nickc@redhat.com>2013-12-13 11:52:32 +0000
commit35c081572f32263b24554ae40502fb5b51ece8c6 (patch)
tree800c0d49d0635671e8e28c56635702212c6f7fc1 /gas
parent8a48ac9579f34efea9bc4f2d5b02230e2ac3dfc1 (diff)
downloadgdb-35c081572f32263b24554ae40502fb5b51ece8c6.zip
gdb-35c081572f32263b24554ae40502fb5b51ece8c6.tar.gz
gdb-35c081572f32263b24554ae40502fb5b51ece8c6.tar.bz2
Add support for Andes NDS32:
BFD: * Makefile.am (BFD32_BACKENDS, BFD32_BACKENDS_CFILES): Add nds32 files. * Makefile.in: Regenerate. * archures.c (bfd_nds32_arch): Add nds32 target. * bfd-in2.h: Regenerate. * config.bfd (nds32*le-*-linux): Add bfd_elf32_nds32lelin_vec and bfd_elf32_nds32belin_vec. (nds32*be-*-linux*): Likewise. (nds32*le-*-*): Add bfd_elf32_nds32le_vec and bfd_elf32_nds32be_vec. (nds32*be-*-*): Likewise. * configure.in (bfd_elf32_nds32be_vec): Add elf32-nds32.lo. (bfd_elf32_nds32le_vec): Likewise. (bfd_elf32_nds32belin_vec): Likewise. (bfd_elf32_nds32lelin_vec): Likewise. * configure: Regenerate. * cpu-nds32.c: New file for nds32. * elf-bfd.h: Add NDS32_ELF_DATA. * elf32-nds32.c: New file for nds32. * elf32-nds32.h: New file for nds32. * libbfd.h: Regenerate. * reloc.c: Add relocations for nds32. * targets.c (bfd_elf32_nds32be_vec): New declaration for nds32. (bfd_elf32_nds32le_vec): Likewise. (bfd_elf32_nds32belin_vec): Likewise. (bfd_elf32_nds32lelin_vec): Likewise. BINUTILS: * readelf.c: Include elf/nds32.h (guess_is_rela): Add case for EM_NDS32. (dump_relocations): Add case for EM_NDS32. (decode_NDS32_machine_flags): New. (get_machine_flags): Add case for EM_NDS32. (is_32bit_abs_reloc): Likewise. (is_16bit_abs_reloc): Likewise. (process_nds32_specific): New. (process_arch_specific): Add case for EM_NDS32. * NEWS: Announce Andes nds32 support. * MAINTAINERS: Add nds32 maintainers. TESTSUITE: * binutils-all/objdump.exp: Add NDS32 cpu. * binutils-all/readelf.r: Skip extra reloc created by NDS32. GAS: * Makefile.am (TARGET_CPU_CFILES): Add config/tc-nds32.c. (TARGET_CPU_HFILES): Add config/tc-nds32.h. * Makefile.in: Regenerate. * configure.in (nds32): Add nds32 target extension config support. * configure.tgt : Add case for nds32-*-elf* and nds32-*-linux*. * configure: Regenerate. * config/tc-nds32.c: New file for nds32. * config/tc-nds32.h: New file for nds32. * doc/Makefile.am (CPU_DOCS): Add c-nds32.texi. * doc/Makefile.in: Regenerate. * doc/as.texinfo: Add nds32 options. * doc/all.texi: Set NDS32. * doc/c-nds32.texi: New file dor nds32 document. * NEWS: Announce Andes nds32 support. TESTSUITE: * gas/all/gas.exp: Add expected failures for NDS32. * gas/elf/elf.exp: Likewise. * gas/lns/lns.exp: Use alternate test. * gas/macros/irp.d: Skip for NDS32. * gas/macros/macros.exp: Skip some tests for the NDS32. * gas/macros/rept.d: Skip for NDS32. * gas/macros/test3.d: Skip for NDS32. * gas/nds32: New directory. * gas/nds32/alu-1.s: New test. * gas/nds32/alu-1.d: Likewise. * gas/nds32/alu-2.s: Likewise. * gas/nds32/alu-2.d: Likewise. * gas/nds32/br-1.d: Likewise. * gas/nds32/br-1.s: Likewise. * gas/nds32/br-2.d: Likewise. * gas/nds32/br-2.s: Likewise. * gas/nds32/ji-jr.d: Likewise. * gas/nds32/ji-jr.s: Likewise. * gas/nds32/ls.d: Likewise. * gas/nds32/ls.s: Likewise. * gas/nds32/lsi.d: Likewise. * gas/nds32/lsi.s: Likewise. * gas/nds32/to-16bit-v1.d: Likewise. * gas/nds32/to-16bit-v1.s: Likewise. * gas/nds32/to-16bit-v2.d: Likewise. * gas/nds32/to-16bit-v2.s: Likewise. * gas/nds32/to-16bit-v3.d: Likewise. * gas/nds32/to-16bit-v3.s: Likewise. * gas/nds32/nds32.exp: New test driver. LD: * Makefile.am (ALL_EMULATION_SOURCES): Add nds32 target. * Makefile.in: Regenerate. * configure.tgt: Add case for nds32*le-*-elf*, nds32*be-*-elf*, nds32*le-*-linux-gnu*, and nds32*be-*-linux-gnu*. * emulparams/nds32belf.sh: New file for nds32. * emulparams/nds32belf_linux.sh: Likewise. * emulparams/nds32belf16m.sh: Likewise. * emulparams/nds32elf.sh: Likewise. * emulparams/nds32elf_linux.sh: Likewise. * emulparams/nds32elf16m.sh: Likewise. * emultempl/nds32elf.em: Likewise. * scripttempl/nds32elf.sc}: Likewise. * gen-doc.texi: Set NDS32. * ld.texinfo: Set NDS32. * NEWS: Announce Andes nds32 support. TESTSUITE: * lib/ld-lib.exp: Add NDS32 to list of targets that do not support shared library generation. * ld-nds32: New directory. * ld-nds32/branch.d: New test. * ld-nds32/branch.ld: New test. * ld-nds32/branch.s: New test. * ld-nds32/diff.d: New test. * ld-nds32/diff.ld: New test. * ld-nds32/diff.s: New test. * ld-nds32/gp.d: New test. * ld-nds32/gp.ld: New test. * ld-nds32/gp.s: New test. * ld-nds32/imm.d: New test. * ld-nds32/imm.ld: New test. * ld-nds32/imm.s: New test. * ld-nds32/imm_symbol.s: New test. * ld-nds32/relax_jmp.d: New test. * ld-nds32/relax_jmp.ld: New test. * ld-nds32/relax_jmp.s: New test. * ld-nds32/relax_load_store.d: New test. * ld-nds32/relax_load_store.ld: New test. * ld-nds32/relax_load_store.s: New test. * ld-nds32/nds32.exp: New file. OPCODES: * Makefile.am (TARGET_LIBOPCODES_CFILES): Add nds32-asm.c and nds32-dis.c. * Makefile.in: Regenerate. * configure.in: Add case for bfd_nds32_arch. * configure: Regenerate. * disassemble.c (ARCH_nds32): Define. * nds32-asm.c: New file for nds32. * nds32-asm.h: New file for nds32. * nds32-dis.c: New file for nds32. * nds32-opc.h: New file for nds32. INCLUDE: * dis-asm.h (print_insn_nds32): Add nds32 target. * elf/nds32.h: New file for nds32. * opcode/nds32.h: New file for nds32.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog20
-rw-r--r--gas/Makefile.am2
-rw-r--r--gas/Makefile.in17
-rw-r--r--gas/NEWS2
-rw-r--r--gas/config/tc-nds32.c5920
-rw-r--r--gas/config/tc-nds32.h264
-rwxr-xr-xgas/configure94
-rw-r--r--gas/configure.in69
-rw-r--r--gas/configure.tgt5
-rw-r--r--gas/doc/Makefile.am1
-rw-r--r--gas/doc/Makefile.in1
-rw-r--r--gas/doc/all.texi5
-rw-r--r--gas/doc/as.texinfo38
-rw-r--r--gas/doc/c-nds32.texi299
-rw-r--r--gas/testsuite/ChangeLog32
-rw-r--r--gas/testsuite/gas/all/gas.exp8
-rw-r--r--gas/testsuite/gas/elf/elf.exp2
-rw-r--r--gas/testsuite/gas/lns/lns.exp1
-rw-r--r--gas/testsuite/gas/macros/irp.d2
-rw-r--r--gas/testsuite/gas/macros/macros.exp4
-rw-r--r--gas/testsuite/gas/macros/rept.d2
-rw-r--r--gas/testsuite/gas/macros/test3.d1
-rw-r--r--gas/testsuite/gas/nds32/alu-1.d47
-rw-r--r--gas/testsuite/gas/nds32/alu-1.s39
-rw-r--r--gas/testsuite/gas/nds32/alu-2.d42
-rw-r--r--gas/testsuite/gas/nds32/alu-2.s33
-rw-r--r--gas/testsuite/gas/nds32/br-1.d15
-rw-r--r--gas/testsuite/gas/nds32/br-1.s3
-rw-r--r--gas/testsuite/gas/nds32/br-2.d25
-rw-r--r--gas/testsuite/gas/nds32/br-2.s8
-rw-r--r--gas/testsuite/gas/nds32/ji-jr.d18
-rw-r--r--gas/testsuite/gas/nds32/ji-jr.s6
-rw-r--r--gas/testsuite/gas/nds32/ls.d25
-rw-r--r--gas/testsuite/gas/nds32/ls.s17
-rw-r--r--gas/testsuite/gas/nds32/lsi.d26
-rw-r--r--gas/testsuite/gas/nds32/lsi.s17
-rw-r--r--gas/testsuite/gas/nds32/nds32.exp30
-rw-r--r--gas/testsuite/gas/nds32/to-16bit-v1.d79
-rw-r--r--gas/testsuite/gas/nds32/to-16bit-v1.s70
-rw-r--r--gas/testsuite/gas/nds32/to-16bit-v2.d15
-rw-r--r--gas/testsuite/gas/nds32/to-16bit-v2.s6
-rw-r--r--gas/testsuite/gas/nds32/to-16bit-v3.d25
-rw-r--r--gas/testsuite/gas/nds32/to-16bit-v3.s16
43 files changed, 7342 insertions, 9 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2c2068d..f745bf5 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,23 @@
+2013-12-13 Kuan-Lin Chen <kuanlinchentw@gmail.com>
+ Wei-Cheng Wang <cole945@gmail.com>
+ Hsiang-Kai Wang <hsiangkai@gmail.com>
+ Hui-Wen Ni <sabrinanitw@gmail.com>
+
+ * Makefile.am (TARGET_CPU_CFILES): Add config/tc-nds32.c.
+ (TARGET_CPU_HFILES): Add config/tc-nds32.h.
+ * Makefile.in: Regenerate.
+ * configure.in (nds32): Add nds32 target extension config support.
+ * configure.tgt : Add case for nds32-*-elf* and nds32-*-linux*.
+ * configure: Regenerate.
+ * config/tc-nds32.c: New file for nds32.
+ * config/tc-nds32.h: New file for nds32.
+ * doc/Makefile.am (CPU_DOCS): Add c-nds32.texi.
+ * doc/Makefile.in: Regenerate.
+ * doc/as.texinfo: Add nds32 options.
+ * doc/all.texi: Set NDS32.
+ * doc/c-nds32.texi: New file dor nds32 document.
+ * NEWS: Announce Andes nds32 support.
+
2013-12-10 Roland McGrath <mcgrathr@google.com>
* Makefile.am (install-exec-bindir): Prefix libtool invocation
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 40a833c..cf6d877 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -164,6 +164,7 @@ TARGET_CPU_CFILES = \
config/tc-moxie.c \
config/tc-msp430.c \
config/tc-mt.c \
+ config/tc-nds32.c \
config/tc-nios2.c \
config/tc-ns32k.c \
config/tc-openrisc.c \
@@ -235,6 +236,7 @@ TARGET_CPU_HFILES = \
config/tc-mn10300.h \
config/tc-msp430.h \
config/tc-mt.h \
+ config/tc-nds32.h \
config/tc-nios2.h \
config/tc-ns32k.h \
config/tc-openrisc.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index dd0318f..01475a1 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -433,6 +433,7 @@ TARGET_CPU_CFILES = \
config/tc-moxie.c \
config/tc-msp430.c \
config/tc-mt.c \
+ config/tc-nds32.c \
config/tc-nios2.c \
config/tc-ns32k.c \
config/tc-openrisc.c \
@@ -504,6 +505,7 @@ TARGET_CPU_HFILES = \
config/tc-mn10300.h \
config/tc-msp430.h \
config/tc-mt.h \
+ config/tc-nds32.h \
config/tc-nios2.h \
config/tc-ns32k.h \
config/tc-openrisc.h \
@@ -854,6 +856,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-moxie.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-msp430.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-mt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-nds32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-nios2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-ns32k.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-openrisc.Po@am__quote@
@@ -1468,6 +1471,20 @@ tc-mt.obj: config/tc-mt.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-mt.obj `if test -f 'config/tc-mt.c'; then $(CYGPATH_W) 'config/tc-mt.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-mt.c'; fi`
+tc-nds32.o: config/tc-nds32.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-nds32.o -MD -MP -MF $(DEPDIR)/tc-nds32.Tpo -c -o tc-nds32.o `test -f 'config/tc-nds32.c' || echo '$(srcdir)/'`config/tc-nds32.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-nds32.Tpo $(DEPDIR)/tc-nds32.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-nds32.c' object='tc-nds32.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-nds32.o `test -f 'config/tc-nds32.c' || echo '$(srcdir)/'`config/tc-nds32.c
+
+tc-nds32.obj: config/tc-nds32.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-nds32.obj -MD -MP -MF $(DEPDIR)/tc-nds32.Tpo -c -o tc-nds32.obj `if test -f 'config/tc-nds32.c'; then $(CYGPATH_W) 'config/tc-nds32.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-nds32.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-nds32.Tpo $(DEPDIR)/tc-nds32.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-nds32.c' object='tc-nds32.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-nds32.obj `if test -f 'config/tc-nds32.c'; then $(CYGPATH_W) 'config/tc-nds32.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-nds32.c'; fi`
+
tc-nios2.o: config/tc-nios2.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-nios2.o -MD -MP -MF $(DEPDIR)/tc-nios2.Tpo -c -o tc-nios2.o `test -f 'config/tc-nios2.c' || echo '$(srcdir)/'`config/tc-nios2.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-nios2.Tpo $(DEPDIR)/tc-nios2.Po
diff --git a/gas/NEWS b/gas/NEWS
index fc1514e..2e62450 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
-*- text -*-
+* Add support for the Andes NDS32.
+
Changes in 2.24:
* Add support for the Texas Instruments MSP430X processor.
diff --git a/gas/config/tc-nds32.c b/gas/config/tc-nds32.c
new file mode 100644
index 0000000..91f8855
--- /dev/null
+++ b/gas/config/tc-nds32.c
@@ -0,0 +1,5920 @@
+/* tc-nds32.c -- Assemble for the nds32
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ 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 "symcat.h"
+#include "dwarf2dbg.h"
+#include "dw2gencfi.h"
+#include "opcodes/nds32-asm.h"
+#include "elf/nds32.h"
+#include "bfd/elf32-nds32.h"
+#include "hash.h"
+#include "sb.h"
+#include "macro.h"
+#include "struc-symbol.h"
+#include "opcode/nds32.h"
+
+#include <stdio.h>
+
+/* GAS definitions. */
+
+/* Characters which start a comment. */
+const char comment_chars[] = "!";
+/* Characters which start a comment when they appear at the start of a line. */
+const char line_comment_chars[] = "#!";
+/* Characters which separate lines (null and newline are by default). */
+const char line_separator_chars[] = ";";
+/* Characters which may be used as the exponent character
+ in a floating point number. */
+const char EXP_CHARS[] = "eE";
+/* Characters which may be used to indicate a floating point constant. */
+const char FLT_CHARS[] = "dDfF";
+
+static int enable_16bit = 1;
+/* Save for md_assemble to distinguish if this instruction is
+ expanded from the pseudo instruction. */
+static bfd_boolean pseudo_opcode = FALSE;
+static struct nds32_relocs_pattern *relocs_list = NULL;
+struct nds32_relocs_pattern
+{
+ segT seg;
+ fragS *frag;
+ frchainS *frchain;
+ symbolS *sym;
+ int reloc;
+ unsigned int insn;
+ unsigned int size;
+ char *where;
+ struct nds32_relocs_pattern *next;
+};
+/*
+static int relax_jal_bound = 3;
+static int multi_call_relax;
+static int pltgot_call_relax;
+*/
+static int vec_size = 0;
+/* If the assembly code is generated by compiler, it is supposed to have
+ ".flag verbatim" at beginning of the content. We have
+ 'nds32_flag' to parse it and set this field to be non-zero. */
+static int verbatim = 0;
+static struct hash_control *nds32_gprs_hash;
+static struct hash_control *nds32_hint_hash;
+
+/* Generate relocation for relax or not, and the default is true. */
+static int enable_relax_relocs = 1;
+/* The value will be used in RELAX_ENTRY. */
+static int enable_relax_ex9 = 0;
+/* The value will be used in RELAX_ENTRY. */
+static int enable_relax_ifc = 0;
+/* Save option -O for perfomance. */
+static int optimize = 0;
+/* Save option -Os for code size. */
+static int optimize_for_space = 0;
+
+struct nds32_keyword nds32_fsrs[] =
+{
+ /* Standard names. */
+ {"$fs0", 0, 0}, {"$fs1", 1, 0}, {"$fs2", 2, 0}, {"$fs3", 3, 0},
+ {"$fs4", 4, 0}, {"$fs5", 5, 0}, {"$fs6", 6, 0}, {"$fs7", 7, 0},
+ {"$fs8", 8, 0}, {"$fs9", 9, 0}, {"$fs10", 10, 0}, {"$fs11", 11, 0},
+ {"$fs12", 12, 0}, {"$fs13", 13, 0}, {"$fs14", 14, 0}, {"$fs15", 15, 0},
+ {"$fs16", 16, 0}, {"$fs17", 17, 0}, {"$fs18", 18, 0}, {"$fs19", 19, 0},
+ {"$fs20", 20, 0}, {"$fs21", 21, 0}, {"$fs22", 22, 0}, {"$fs23", 23, 0},
+ {"$fs24", 24, 0}, {"$fs25", 25, 0}, {"$fs26", 26, 0}, {"$fs27", 27, 0},
+ {"$fs28", 28, 0}, {"$fs29", 29, 0}, {"$fs30", 30, 0}, {"$fs31", 31, 0},
+ {NULL, 0, 0}
+};
+
+struct nds32_keyword nds32_fdrs[] =
+{
+ /* Standard names. */
+ {"$fd0", 0, 0}, {"$fd1", 1, 0}, {"$fd2", 2, 0}, {"$fd3", 3, 0},
+ {"$fd4", 4, 0}, {"$fd5", 5, 0}, {"$fd6", 6, 0}, {"$fd7", 7, 0},
+ {"$fd8", 8, 0}, {"$fd9", 9, 0}, {"$fd10", 10, 0}, {"$fd11", 11, 0},
+ {"$fd12", 12, 0}, {"$fd13", 13, 0}, {"$fd14", 14, 0}, {"$fd15", 15, 0},
+ {"$fd16", 16, 0}, {"$fd17", 17, 0}, {"$fd18", 18, 0}, {"$fd19", 19, 0},
+ {"$fd20", 20, 0}, {"$fd21", 21, 0}, {"$fd22", 22, 0}, {"$fd23", 23, 0},
+ {"$fd24", 24, 0}, {"$fd25", 25, 0}, {"$fd26", 26, 0}, {"$fd27", 27, 0},
+ {"$fd28", 28, 0}, {"$fd29", 29, 0}, {"$fd30", 30, 0}, {"$fd31", 31, 0},
+ {NULL, 0, 0}
+};
+
+struct nds32_keyword nds32_gprs[] =
+{
+ /* Standard names. */
+ {"$r0", 0, 0}, {"$r1", 1, 0}, {"$r2", 2, 0}, {"$r3", 3, 0},
+ {"$r4", 4, 0}, {"$r5", 5, 0}, {"$r6", 6, 0}, {"$r7", 7, 0},
+ {"$r8", 8, 0}, {"$r9", 9, 0}, {"$r10", 10, 0}, {"$r11", 11, 0},
+ {"$r12", 12, 0}, {"$r13", 13, 0}, {"$r14", 14, 0}, {"$r15", 15, 0},
+ {"$r16", 16, 0}, {"$r17", 17, 0}, {"$r18", 18, 0}, {"$r19", 19, 0},
+ {"$r20", 20, 0}, {"$r21", 21, 0}, {"$r22", 22, 0}, {"$r23", 23, 0},
+ {"$r24", 24, 0}, {"$r25", 25, 0}, {"$r26", 26, 0}, {"$r27", 27, 0},
+ {"$r28", 28, 0}, {"$r29", 29, 0}, {"$r30", 30, 0}, {"$r31", 31, 0},
+ /* Names for parameter passing. */
+ {"$a0", 0, 0}, {"$a1", 1, 0}, {"$a2", 2, 0}, {"$a3", 3, 0},
+ {"$a4", 4, 0}, {"$a5", 5, 0},
+ /* Names reserved for 5-bit addressing only. */
+ {"$s0", 6, 0}, {"$s1", 7, 0}, {"$s2", 8, 0}, {"$s3", 9, 0},
+ {"$s4", 10, 0}, {"$s5", 11, 0}, {"$s6", 12, 0}, {"$s7", 13, 0},
+ {"$s8", 14, 0}, {"$s9", 28, 0},
+ {"$ta", 15, 0},
+ {"$t0", 16, 0}, {"$t1", 17, 0}, {"$t2", 18, 0}, {"$t3", 19, 0},
+ {"$t4", 20, 0}, {"$t5", 21, 0}, {"$t6", 22, 0}, {"$t7", 23, 0},
+ {"$t8", 24, 0}, {"$t9", 25, 0},
+ {"$p0", 26, 0}, {"$p1", 27, 0},
+ {"$fp", 28, 0}, {"$gp", 29, 0}, {"$lp", 30, 0}, {"$sp", 31, 0},
+ /* Names reserved for 4-bit addressing only. */
+ {"$h0", 0, 0}, {"$h1", 1, 0}, {"$h2", 2, 0}, {"$h3", 3, 0},
+ {"$h4", 4, 0}, {"$h5", 5, 0}, {"$h6", 6, 0}, {"$h7", 7, 0},
+ {"$h8", 8, 0}, {"$h9", 9, 0}, {"$h10", 10, 0}, {"$h11", 11, 0},
+ {"$h12", 16, 0}, {"$h13", 17, 0}, {"$h14", 18, 0}, {"$h15", 19, 0},
+ /* Names reserved for 3-bit addressing only. */
+ {"$o0", 0, 0}, {"$o1", 1, 0}, {"$o2", 2, 0}, {"$o3", 3, 0},
+ {"$o4", 4, 0}, {"$o5", 5, 0}, {"$o6", 6, 0}, {"$o7", 7, 0},
+ {NULL, 0, 0}
+};
+
+
+static struct hash_control *nds32_relax_info_hash;
+static relax_info_t relax_table[] =
+{
+ {
+ "jal", /* opcode */
+ BR_RANGE_S16M, /* br_range */
+ {{0, 0, 0}}, /* cond_field */
+ {
+ {
+ INSN_JAL /* jal label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_JAL /* jal label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_JAL /* jal label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_JAL /* jal label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JRAL_TA
+ }, /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {{0, 0, 0}}, /* BR_RANGE_S256 */
+ {{0, 0, 0}}, /* BR_RANGE_S16K */
+ {{0, 0, 0}}, /* BR_RANGE_S64K */
+ {{0, 0, 0}}, /* BR_RANGE_S16M */
+ {{0, 0, 0}} /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 4, 12}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_HI20},
+ {0, 12, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL1},
+ {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {8, 4, NDS32_ORIGIN, 0},
+ {8, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bltzal", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BLTZAL /* bltzal $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BLTZAL /* bltzal $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BLTZAL /* bltzal $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BGEZ, /* bgez $rt, $1 */
+ INSN_JAL /* jal label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BGEZ, /* bgez $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JRAL_TA /* jral $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bgezal", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BGEZAL /* bgezal $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BGEZAL /* bgezal $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BGEZAL /* bgezal $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BLTZ, /* bltz $rt, $1 */
+ INSN_JAL /* jal label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BLTZ, /* bltz $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JRAL_TA /* jral $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "j", /* opcode */
+ BR_RANGE_S16M, /* br_range */
+ {{0, 0, 0}}, /* cond_field */
+ {
+ {
+ (INSN_J8 << 16) /* j8 label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_J /* j label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ }, /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {{0, 0, 0}}, /* BR_RANGE_S256 */
+ {{0, 0, 0}}, /* BR_RANGE_S16K */
+ {{0, 0, 0}}, /* BR_RANGE_S64K */
+ {{0, 0, 0}}, /* BR_RANGE_S16M */
+ {{0, 0, 0}} /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {2, 4, 4, 4, 12}, /* relax_code_size */
+ {2, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_HI20},
+ {0, 12, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP1},
+ {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {8, 4, NDS32_ORIGIN, 0},
+ {8, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "j8", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {{0, 0, 0}}, /* cond_field */
+ {
+ {
+ (INSN_J8 << 16) /* j8 label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_J /* j label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ }, /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {{0, 0, 0}}, /* BR_RANGE_S256 */
+ {{0, 0, 0}}, /* BR_RANGE_S16K */
+ {{0, 0, 0}}, /* BR_RANGE_S64K */
+ {{0, 0, 0}}, /* BR_RANGE_S16M */
+ {{0, 0, 0}} /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {2, 4, 4, 4, 12}, /* relax_code_size */
+ {2, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 2, 0, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_HI20},
+ {0, 12, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP1},
+ {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {8, 4, NDS32_ORIGIN, 0},
+ {8, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "beqz", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BEQZ /* beqz $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BEQZ /* beqz $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BEQZ /* beqz $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BNEZ, /* bnez $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BNEZ, /* bnez $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bgez", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BGEZ /* bgez $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BGEZ /* bgez $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BGEZ /* bgez $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BLTZ, /* bltz $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BLTZ, /* bltz $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bnez", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BEQZ, /* beqz $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BEQZ, /* beqz $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bgtz", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BGTZ /* bgtz $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BGTZ /* bgtz $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BGTZ /* bgtz $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BLEZ, /* blez $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BLEZ, /* blez $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "blez", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BLEZ /* blez $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BLEZ /* blez $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BLEZ /* blez $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BGTZ, /* bgtz $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BGTZ, /* bgtz $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bltz", /* opcode */
+ BR_RANGE_S64K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BLTZ /* bltz $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BLTZ /* bltz $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BLTZ /* bltz $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BGEZ, /* bgez $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BGEZ, /* bgez $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "beq", /* opcode */
+ BR_RANGE_S16K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BEQ /* beq $rt, $ra, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BEQ /* beq $rt, $ra, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BNE, /* bne $rt, $ra, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BNE, /* bne $rt, $ra, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BNE, /* bne $rt, $ra, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 8, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bne", /* opcode */
+ BR_RANGE_S16K, /* br_range */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BNE /* bne $rt, $ra, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BNE /* bne $rt, $ra, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BEQ, /* beq $rt, $ra, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BEQ, /* beq $rt, $ra, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BEQ, /* beq $rt, $ra, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 15, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 8, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "beqz38", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {
+ {0, 8, 0x7},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BEQZ /* beqz $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BEQZ /* beqz $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BEQZ /* beqz $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BNEZ, /* bnez $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BNEZ, /* bnez $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bnez38", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {
+ {0, 8, 0x7},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BEQZ, /* beqz $rt, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BEQZ, /* beqz $rt, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "beqzs8", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {{0, 0, 0}}, /* cond_field */
+ {
+ {
+ INSN_BEQZ_TA /* beqz $r15, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BNEZ /* bnez $rt, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BNEZ_TA, /* bnez $r15, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BNEZ_TA, /* bnez $r15, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {{0, 0, 0}}, /* BR_RANGE_S256 */
+ {{0, 0, 0}}, /* BR_RANGE_S16K */
+ {{0, 0, 0}}, /* BR_RANGE_S64K */
+ {{0, 0, 0}}, /* BR_RANGE_S16M */
+ {{0, 0, 0}} /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bnezs8", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {{0, 0, 0}}, /* cond_field */
+ {
+ {
+ INSN_BNEZ_TA /* bnez $r15, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BNEZ_TA /* bnez $r15, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BNEZ_TA /* bnez $r15, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BEQZ_TA, /* beqz $r15, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BEQZ_TA, /* beqz $r15, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {{0, 0, 0}}, /* BR_RANGE_S256 */
+ {{0, 0, 0}}, /* BR_RANGE_S16K */
+ {{0, 0, 0}}, /* BR_RANGE_S64K */
+ {{0, 0, 0}}, /* BR_RANGE_S16M */
+ {{0, 0, 0}} /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 4, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_17_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bnes38", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {
+ {0, 8, 0x7},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BNE_R5 /* bne $rt, $r5, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BNE_R5 /* bne $rt, $r5, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BEQ_R5, /* beq $rt, $r5, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BEQ_R5, /* beq $rt, $r5, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BEQ_R5, /* beq $rt, $r5, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 8, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "beqs38", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {
+ {0, 8, 0x7},
+ { 0, 0, 0 }
+ }, /* cond_field */
+ {
+ {
+ INSN_BEQ_R5 /* beq $rt, $r5, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_BEQ_R5 /* beq $rt, $r5, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_BNE_R5, /* bne $rt, $r5, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BNE_R5, /* bne $rt, $r5, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BNE_R5, /* bne $rt, $r5, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 4, 8, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL},
+ {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL},
+ {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL},
+ {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "beqc", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* cond_field */
+ {
+ {
+ INSN_BEQC /* beqc $rt, imm11s, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_MOVI_TA, /* movi $ta, imm11s */
+ INSN_BEQ_TA /* beq $rt, $ta, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_MOVI_TA, /* movi $ta, imm11s */
+ INSN_BEQ_TA /* beq $rt, $ta, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BNEC, /* bnec $rt, imm11s, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BNEC, /* bnec $rt, imm11s, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 0, 0xFFFFF},
+ {4, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 0, 0xFFFFF},
+ {4, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 8, 8, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_WORD_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {4, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {4, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ "bnec", /* opcode */
+ BR_RANGE_S256, /* br_range */
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* cond_field */
+ {
+ {
+ INSN_BNEC /* bnec $rt, imm11s, label */
+ }, /* BR_RANGE_S256 */
+ {
+ INSN_MOVI_TA, /* movi $ta, imm11s */
+ INSN_BNE_TA /* bne $rt, $ta, label */
+ }, /* BR_RANGE_S16K */
+ {
+ INSN_MOVI_TA, /* movi $ta, imm11s */
+ INSN_BNE_TA /* bne $rt, $ta, label */
+ }, /* BR_RANGE_S64K */
+ {
+ INSN_BEQC, /* beqc $rt, imm11s, $1 */
+ INSN_J /* j label */
+ }, /* BR_RANGE_S16M */
+ {
+ INSN_BEQC, /* beqc $rt, imm11s, $1 */
+ INSN_SETHI_TA, /* sethi $ta, label */
+ INSN_ORI_TA, /* ori $ta, $ta, label */
+ INSN_JR_TA /* jr $ta */
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_seq */
+ {
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {0, 0, 0xFFFFF},
+ {4, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {0, 0, 0xFFFFF},
+ {4, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 8, 0x7FF},
+ {0, 20, 0x1F},
+ {0, 0, 0}
+ } /* BR_RANGE_U4G */
+ }, /* relax_code_condition */
+ {4, 8, 8, 8, 16}, /* relax_code_size */
+ {4, 4, 4, 4, 4}, /* relax_branch_isize */
+ {
+ {
+ {0, 4, 0, BFD_RELOC_NDS32_WORD_9_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S256 */
+ {
+ {4, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16K */
+ {
+ {4, 4, 0, BFD_RELOC_NDS32_15_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S64K */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL},
+ {4, 4, 0, BFD_RELOC_NDS32_25_PCREL},
+ {0, 0, 0, 0}
+ }, /* BR_RANGE_S16M */
+ {
+ {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL},
+ {4, 4, 0, BFD_RELOC_NDS32_HI20},
+ {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
+ {12, 4, NDS32_ORIGIN, 0},
+ {12, 2, NDS32_CONVERT, 0},
+ {0, 0, 0, 0}
+ } /* BR_RANGE_U4G */
+ } /* relax_fixup */
+ },
+ {
+ NULL, /* opcode */
+ 0, /* br_range */
+ {{0, 0, 0}}, /* cond_field */
+ {{0}}, /* relax_code_seq */
+ {{{0, 0, 0}}}, /* relax_code_condition */
+ {0}, /* relax_code_size */
+ {0}, /* relax_branch_isize */
+ {{{0, 0, 0, 0}}}, /* relax_fixup */
+ },
+};
+
+
+/* GAS definitions for command-line options. */
+enum options
+{
+ OPTION_BIG = OPTION_MD_BASE,
+ OPTION_LITTLE,
+ OPTION_TURBO,
+ OPTION_PIC,
+ OPTION_RELAX_FP_AS_GP_OFF,
+ OPTION_RELAX_B2BB_ON,
+ OPTION_RELAX_ALL_OFF,
+ OPTION_OPTIMIZE,
+ OPTION_OPTIMIZE_SPACE
+};
+
+const char *md_shortopts = "m:G:O";
+struct option md_longopts[] =
+{
+ {"O1", no_argument, NULL, OPTION_OPTIMIZE},
+ {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
+ {"big", no_argument, NULL, OPTION_BIG},
+ {"little", no_argument, NULL, OPTION_LITTLE},
+ {"EB", no_argument, NULL, OPTION_BIG},
+ {"EL", no_argument, NULL, OPTION_LITTLE},
+ {"meb", no_argument, NULL, OPTION_BIG},
+ {"mel", no_argument, NULL, OPTION_LITTLE},
+ {"mall-ext", no_argument, NULL, OPTION_TURBO},
+ {"mpic", no_argument, NULL, OPTION_PIC},
+ /* Relaxation related options. */
+ {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
+ {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
+ {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
+ {NULL, no_argument, NULL, 0}
+};
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+struct nds32_parse_option_table
+{
+ const char *name; /* Option string. */
+ char *help; /* Help description. */
+ int (*func) (char *arg); /* How to parse it. */
+};
+
+
+/* The value `-1' represents this option has *NOT* been set. */
+#ifdef NDS32_DEFAULT_ARCH_NAME
+static char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
+#else
+static char* nds32_arch_name = "v3";
+#endif
+static int nds32_baseline = -1;
+static int nds32_gpr16 = -1;
+static int nds32_fpu_sp_ext = -1;
+static int nds32_fpu_dp_ext = -1;
+static int nds32_freg = -1;
+static int nds32_abi = -1;
+
+/* Record ELF flags */
+static int nds32_elf_flags = 0;
+static int nds32_fpu_com = 0;
+
+static int nds32_parse_arch (char *str);
+static int nds32_parse_baseline (char *str);
+static int nds32_parse_freg (char *str);
+static int nds32_parse_abi (char *str);
+
+static struct nds32_parse_option_table parse_opts [] =
+{
+ {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
+ <arch name> could be\n\
+ v3, v3j, v3m, v3f, v3s, "\
+ "v2, v2j, v2f, v2s"), nds32_parse_arch},
+ {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
+ <baseline> could be v2, v3, v3m"),
+ nds32_parse_baseline},
+ {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
+ <freg>\n\
+ 0: 8 SP / 4 DP registers\n\
+ 1: 16 SP / 8 DP registers\n\
+ 2: 32 SP / 16 DP registers\n\
+ 3: 32 SP / 32 DP registers"), nds32_parse_freg},
+ {"abi=", N_("<abi>\t Specify a abi version\n\
+ <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
+ {NULL, NULL, NULL}
+};
+
+static int nds32_mac = 1;
+static int nds32_div = 1;
+static int nds32_16bit_ext = 1;
+static int nds32_dx_regs = 1;
+static int nds32_perf_ext = 1;
+static int nds32_perf_ext2 = 1;
+static int nds32_string_ext = 1;
+static int nds32_audio_ext = 1;
+static int nds32_fpu_fma = 0;
+static int nds32_pic = 0;
+static int nds32_relax_fp_as_gp = 1;
+static int nds32_relax_b2bb = 0;
+static int nds32_relax_all = 1;
+struct nds32_set_option_table
+{
+ const char *name; /* Option string. */
+ char *help; /* Help description. */
+ int *var; /* Variable to be set. */
+ int value; /* Value to set. */
+};
+
+/* The option in this group has both Enable/Disable settings.
+ Just list on here. */
+
+static struct nds32_set_option_table toggle_opts [] =
+{
+ {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
+ {"div", N_("Divide instructions support"), &nds32_div, 1},
+ {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
+ {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
+ {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
+ {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
+ {"string-ext", N_("String extension"), &nds32_string_ext, 1},
+ {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
+ {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
+ {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
+ {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
+ {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
+ {NULL, NULL, NULL, 0}
+};
+
+
+/* GAS declarations. */
+
+/* This is the callback for nds32-asm.c to parse operands. */
+int
+nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
+ struct nds32_asm_insn *pinsn,
+ char **pstr, int64_t *value);
+
+
+struct nds32_asm_desc asm_desc;
+
+/* md_after_parse_args ()
+
+ GAS will call md_after_parse_args whenever it is defined.
+ This function checks any conflicting options specified. */
+
+void
+nds32_after_parse_args (void)
+{
+ /* If -march option is not used in command-line, set the value of option
+ variable according to NDS32_DEFAULT_ARCH_NAME. */
+ nds32_parse_arch (nds32_arch_name);
+}
+
+/* This function is called when printing usage message (--help). */
+
+void
+md_show_usage (FILE *stream)
+{
+ struct nds32_parse_option_table *coarse_tune;
+ struct nds32_set_option_table *fine_tune;
+
+ fprintf (stream, _("\n NDS32-specific assembler options:\n"));
+ fprintf (stream, _("\
+ -O1, Optimize for performance\n\
+ -Os Optimize for space\n"));
+ fprintf (stream, _("\
+ -EL, -mel or -little Produce little endian output\n\
+ -EB, -meb or -big Produce big endian output\n\
+ -mpic Generate PIC\n\
+ -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
+ -mb2bb-relax Back-to-back branch optimization\n\
+ -mno-all-relax Suppress all relaxation for this file\n"));
+
+ for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
+ {
+ if (coarse_tune->help != NULL)
+ fprintf (stream, _(" -m%s%s\n"),
+ coarse_tune->name, _(coarse_tune->help));
+ }
+
+ for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
+ {
+ if (fine_tune->help != NULL)
+ fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"),
+ fine_tune->name, _(fine_tune->help));
+ }
+
+ fprintf (stream, _("\
+ -mall-ext Turn on all extensions and instructions support\n"));
+}
+
+void
+nds32_frag_init (fragS *fragp)
+{
+ fragp->tc_frag_data.flag = 0;
+ fragp->tc_frag_data.opcode = NULL;
+ fragp->tc_frag_data.fixup = NULL;
+}
+
+
+
+/* This function reads an expression from a C string and returns a pointer past
+ the end of the expression. */
+
+static char *
+parse_expression (char *str, expressionS *exp)
+{
+ char *s;
+ char *tmp;
+
+ tmp = input_line_pointer; /* Save line pointer. */
+ input_line_pointer = str;
+ expression (exp);
+ s = input_line_pointer;
+ input_line_pointer = tmp; /* Restore line pointer. */
+
+ return s; /* Return pointer to where parsing stopped. */
+}
+
+void
+nds32_start_line_hook (void)
+{
+}
+
+/*
+ * Pseudo opcodes
+ */
+
+typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv);
+struct nds32_pseudo_opcode
+{
+ const char *opcode;
+ int argc;
+ nds32_pseudo_opcode_func proc;
+ int pseudo_val;
+
+ /* Some instructions are not pseudo opcode, but they might still be
+ expanded or changed with other instruction combination for some
+ conditions. We also apply this structure to assist such work.
+
+ For example, if the distance of branch target '.L0' is larger than
+ imm8s<<1 range,
+
+ the instruction:
+
+ beqzs8 .L0
+
+ will be transformed into:
+
+ bnezs8 .LCB0
+ j .L0
+ .LCB0:
+
+ However, sometimes we do not want assembler to do such changes
+ because compiler knows how to generate corresponding instruction sequence.
+ Use this field to indicate that this opcode is also a physical instruction.
+ If the flag 'verbatim' is nozero and this opcode
+ is a physical instruction, we should not expand it. */
+ int physical_op;
+};
+#define PV_DONT_CARE 0
+
+static struct hash_control *nds32_pseudo_opcode_hash = NULL;
+
+static int
+builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
+{
+ return s[0] == '$';
+}
+
+static int
+builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
+{
+ struct nds32_keyword *k;
+
+ k = hash_find (nds32_gprs_hash, s);
+
+ if (k == NULL)
+ return -1;
+
+ return k->value;
+}
+
+static int
+builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
+{
+ const char *ptr = s;
+
+ while (*ptr != '+' && *ptr != '-' && *ptr)
+ ++ptr;
+
+ if (*ptr == 0)
+ return 0;
+ else
+ return strtol (ptr, NULL, 0);
+}
+
+static void
+md_assemblef (char *format, ...)
+{
+ /* FIXME: hope this is long enough. */
+ char line[1024];
+ va_list ap;
+ unsigned int r;
+
+ va_start (ap, format);
+ r = vsnprintf (line, sizeof (line), format, ap);
+ md_assemble (line);
+
+ gas_assert (r < sizeof (line));
+}
+
+/* Some prototypes here, since some op may use another op. */
+static void do_pseudo_li_internal (char *rt, int imm32s);
+static void do_pseudo_move_reg_internal (char *dst, char *src);
+
+static void
+do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ char *arg_label = argv[0];
+ /* b label */
+ if (nds32_pic
+ && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT")))
+ {
+ md_assemblef ("sethi $ta,hi20(%s)", arg_label);
+ md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
+ md_assemble ("add $ta,$ta,$gp");
+ md_assemble ("jr $ta");
+ }
+ else
+ {
+ md_assemblef ("j %s", arg_label);
+ }
+}
+
+static void
+do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ char *arg_label = argv[0];
+ /* bal|call label */
+ if (nds32_pic
+ && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT")))
+ {
+ md_assemblef ("sethi $ta,hi20(%s)", arg_label);
+ md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
+ md_assemble ("add $ta,$ta,$gp");
+ md_assemble ("jral $ta");
+ }
+ else
+ {
+ md_assemblef ("jal %s", arg_label);
+ }
+}
+
+static void
+do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* rt5, ra5, label */
+ md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
+ md_assemblef ("beqz $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* rt5, ra5, label */
+ md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
+ md_assemblef ("beqz $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* bgt rt5, ra5, label */
+ md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
+ md_assemblef ("bnez $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* bgt rt5, ra5, label */
+ md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
+ md_assemblef ("bnez $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* bgt rt5, ra5, label */
+ md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
+ md_assemblef ("beqz $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* bgt rt5, ra5, label */
+ md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
+ md_assemblef ("beqz $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* rt5, ra5, label */
+ md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
+ md_assemblef ("bnez $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* rt5, ra5, label */
+ md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
+ md_assemblef ("bnez $ta,%s", argv[2]);
+}
+
+static void
+do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ md_assemblef ("jr %s", argv[0]);
+}
+
+static void
+do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ if (argc == 1)
+ md_assemblef ("jral $lp,%s", argv[0]);
+ else
+ md_assemblef ("jral %s,%s", argv[0], argv[1]);
+}
+
+static void
+do_pseudo_la_internal (const char *arg_reg, const char *arg_label, const char *line)
+{
+ /* rt, label */
+ if (!nds32_pic)
+ {
+ md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
+ md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
+ }
+ else if ((strstr (arg_label, "@PLT") || strstr (arg_label, "@GOTOFF")))
+ {
+ md_assemblef ("sethi $ta,hi20(%s)", arg_label);
+ md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
+ md_assemblef ("add %s,$ta,$gp", arg_reg);
+ }
+ else if (strstr (arg_label, "@GOT"))
+ {
+ long addend = builtin_addend (arg_label, NULL);
+
+ md_assemblef ("sethi $ta,hi20(%s)", arg_label);
+ md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
+ md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
+ if (addend != 0)
+ {
+ if (addend < 0x4000 && addend >= -0x4000)
+ {
+ md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
+ }
+ else
+ {
+ do_pseudo_li_internal ("$ta", addend);
+ md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
+ }
+ }
+ }
+ else
+ as_bad (_("need PIC qualifier with symbol. '%s'"), line);
+}
+
+static void
+do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
+}
+
+static void
+do_pseudo_li_internal (char *rt, int imm32s)
+{
+ if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
+ md_assemblef ("movi55 %s,%d", rt, imm32s);
+ else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
+ md_assemblef ("movi %s,%d", rt, imm32s);
+ else if ((imm32s & 0xfff) == 0)
+ md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
+ else
+ {
+ md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
+ md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
+ }
+}
+
+static void
+do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* Validate argv[1] for constant expression. */
+ expressionS exp;
+
+ parse_expression (argv[1], &exp);
+ if (exp.X_op != O_constant)
+ {
+ as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
+ return;
+ }
+
+ do_pseudo_li_internal (argv[0], exp.X_add_number);
+}
+
+static void
+do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+{
+ char ls = 'r';
+ char size = 'x';
+ const char *sign = "";
+
+ /* Prepare arguments for various load/store. */
+ sign = (pv & 0x10) ? "s" : "";
+ ls = (pv & 0x80000000) ? 's' : 'l';
+ switch (pv & 0x3)
+ {
+ case 0: size = 'b'; break;
+ case 1: size = 'h'; break;
+ case 2: size = 'w'; break;
+ }
+
+ if (ls == 's' || size == 'w')
+ sign = "";
+
+ if (builtin_isreg (argv[1], NULL))
+ {
+ /* lwi */
+ md_assemblef ("%c%c%si %s,[%s]", ls, size, argv[0], argv[1]);
+ }
+ else if (!nds32_pic)
+ {
+ /* lwi */
+ md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
+ md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
+ }
+ else
+ {
+ /* PIC code. */
+ if (strstr (argv[1], "@GOTOFF"))
+ {
+ /* lw */
+ md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
+ md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
+ md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
+ }
+ else if (strstr (argv[1], "@GOT"))
+ {
+ long addend = builtin_addend (argv[1], NULL);
+ /* lw */
+ md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
+ md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
+ md_assemble ("lw $ta,[$gp+$ta]"); /* Load address word. */
+ if (addend < 0x10000 && addend >= -0x10000)
+ {
+ md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
+ }
+ else
+ {
+ /* lw */
+ do_pseudo_li_internal (argv[0], addend);
+ md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
+ }
+ }
+ else
+ {
+ as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
+ }
+ }
+}
+
+static void
+do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+{
+ char *arg_rt = argv[0];
+ char *arg_label = argv[1];
+ char *arg_inc = argv[2];
+ char ls = 'r';
+ char size = 'x';
+ const char *sign = "";
+
+ /* Prepare arguments for various load/store. */
+ sign = (pv & 0x10) ? "s" : "";
+ ls = (pv & 0x80000000) ? 's' : 'l';
+ switch (pv & 0x3)
+ {
+ case 0: size = 'b'; break;
+ case 1: size = 'h'; break;
+ case 2: size = 'w'; break;
+ }
+
+ if (ls == 's' || size == 'w')
+ sign = "";
+
+ do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
+ md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
+}
+
+static void
+do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+{
+ char *arg_rt = argv[0];
+ char *arg_inc = argv[2];
+ char ls = 'r';
+ char size = 'x';
+ const char *sign = "";
+
+ /* Prepare arguments for various load/store. */
+ sign = (pv & 0x10) ? "s" : "";
+ ls = (pv & 0x80000000) ? 's' : 'l';
+ switch (pv & 0x3)
+ {
+ case 0: size = 'b'; break;
+ case 1: size = 'h'; break;
+ case 2: size = 'w'; break;
+ }
+
+ if (ls == 's' || size == 'w')
+ sign = "";
+
+ md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
+}
+
+static void
+do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
+{
+ char ls = 'r';
+ char size = 'x';
+ const char *sign = "";
+
+ /* Prepare arguments for various load/store. */
+ sign = (pv & 0x10) ? "s" : "";
+ ls = (pv & 0x80000000) ? 's' : 'l';
+ switch (pv & 0x3)
+ {
+ case 0: size = 'b'; break;
+ case 1: size = 'h'; break;
+ case 2: size = 'w'; break;
+ }
+
+ if (ls == 's' || size == 'w')
+ sign = "";
+
+ md_assemblef ("%c%c%si.bi %s,%s,%s",
+ ls, size, sign, argv[0], argv[1], argv[2]);
+}
+
+static void
+do_pseudo_move_reg_internal (char *dst, char *src)
+{
+ if (enable_16bit)
+ md_assemblef ("mov55 %s,%s", dst, src);
+ else
+ md_assemblef ("ori %s,%s,0", dst, src);
+}
+
+static void
+do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ if (builtin_isreg (argv[1], NULL))
+ do_pseudo_move_reg_internal (argv[0], argv[1]);
+ else
+ /* move $rt, imm -> li $rt, imm */
+ do_pseudo_li (argc, argv, PV_DONT_CARE);
+}
+
+static void
+do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ md_assemble ("movi $ta,0");
+ md_assemblef ("sub %s,$ta,%s", argv[0], argv[1]);
+}
+
+static void
+do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
+}
+
+static void
+do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* posh/pop $ra, $rb */
+ /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
+ int rb, re, ra, en4;
+ int i;
+ char *opc = "pushpopm";
+
+ if (argc == 3)
+ as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
+ "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
+ else if (argc == 1)
+ as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
+
+ if (strstr (argv[argc], "pop") == argv[argc])
+ opc = "lmw.bim";
+ else if (strstr (argv[argc], "push") == argv[argc])
+ opc = "smw.adm";
+ else
+ as_fatal ("nds32-as internal error. %s", argv[argc]);
+
+ rb = builtin_regnum (argv[0], NULL);
+ re = builtin_regnum (argv[1], NULL);
+
+ if (re < rb)
+ {
+ as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
+ /* Swap to right order. */
+ ra = re;
+ re = rb;
+ rb = ra;
+ }
+
+ /* Build enable4 mask. */
+ en4 = 0;
+ if (re >= 28 || rb >= 28)
+ {
+ for (i = (rb >= 28? rb: 28); i <= re; i++)
+ en4 |= 1 << (3 - (i - 28));
+ }
+
+ /* Adjust $re, $rb. */
+ if (rb >= 28)
+ rb = re = 31;
+ else if (re >= 28)
+ re = 27;
+
+ md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
+}
+
+static void
+do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* push/pop $ra5, $label=$sp */
+ char *argvm[3];
+
+ if (argc == 2)
+ as_bad ("'push/pop $ra5, rb5' is deprecated. "
+ "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
+
+ argvm[0] = argv[0];
+ argvm[1] = argv[0];
+ argvm[2] = argv[argc];
+ do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
+}
+
+static void
+do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ md_assemblef ("push25 %s,%s", argv[0], argv[1]);
+}
+
+static void
+do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
+}
+
+/* pv == 0, parsing "push.s" pseudo instruction operands.
+ pv != 0, parsing "pop.s" pseudo instruction operands. */
+
+static void
+do_pseudo_pushpop_stack (int argc, char *argv[], int pv)
+{
+ /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
+ /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
+
+ int rb, re;
+ int en4;
+ int last_arg_index;
+ char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
+
+ rb = re = 0;
+
+ if (argc == 1)
+ {
+ /* argc=1, operands pattern: { $fp $gp $lp $sp } */
+
+ /* Set register number Rb = Re = $sp = $r31. */
+ rb = re = 31;
+ }
+ else if (argc == 2 || argc == 3)
+ {
+ /* argc=2, operands pattern: Rb, Re */
+ /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
+
+ /* Get register number in integer. */
+ rb = builtin_regnum (argv[0], NULL);
+ re = builtin_regnum (argv[1], NULL);
+
+ /* Rb should be equal/less than Re. */
+ if (rb > re)
+ as_bad ("The first operand (%s) should be equal to or smaller than "
+ "second operand (%s).", argv[0], argv[1]);
+
+ /* forbid using $fp|$gp|$lp|$sp in Rb or Re
+ r28 r29 r30 r31 */
+ if (rb >= 28)
+ as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
+ if (re >= 28)
+ as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
+ }
+ else
+ {
+ as_bad ("Invalid operands pattern !!");
+ }
+
+ /* Build Enable4 mask. */
+ /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
+ and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
+ which is also valid for code generation. */
+ en4 = 0;
+ last_arg_index = argc - 1;
+ if (strstr (argv[last_arg_index], "$fp"))
+ en4 |= 8;
+ if (strstr (argv[last_arg_index], "$gp"))
+ en4 |= 4;
+ if (strstr (argv[last_arg_index], "$lp"))
+ en4 |= 2;
+ if (strstr (argv[last_arg_index], "$sp"))
+ en4 |= 1;
+
+ md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
+}
+
+static void
+do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ char size = 'x';
+ /* If users omit push location, use $sp as default value. */
+ char location[8] = "$sp"; /* 8 is enough for register name. */
+
+ switch (pv & 0x3)
+ {
+ case 0: size = 'b'; break;
+ case 1: size = 'h'; break;
+ case 2: size = 'w'; break;
+ case 3: size = 'w'; break;
+ }
+
+ if (argc == 2)
+ {
+ strncpy (location, argv[1], 8);
+ location[7] = '\0';
+ }
+
+ md_assemblef ("l.%c $ta,%s", size, argv[0]);
+ md_assemblef ("smw.adm $ta,[%s],$ta", location);
+
+ if ((pv & 0x3) == 0x3) /* double-word */
+ {
+ md_assemblef ("l.w $ta,%s+4", argv[0]);
+ md_assemblef ("smw.adm $ta,[%s],$ta", location);
+ }
+}
+
+static void
+do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ char size = 'x';
+ /* If users omit pop location, use $sp as default value. */
+ char location[8] = "$sp"; /* 8 is enough for register name. */
+
+ switch (pv & 0x3)
+ {
+ case 0: size = 'b'; break;
+ case 1: size = 'h'; break;
+ case 2: size = 'w'; break;
+ case 3: size = 'w'; break;
+ }
+
+ if (argc == 3)
+ {
+ strncpy (location, argv[2], 8);
+ location[7] = '\0';
+ }
+
+ if ((pv & 0x3) == 0x3) /* double-word */
+ {
+ md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
+ md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
+ }
+
+ md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
+ md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
+}
+
+static void
+do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* If users omit push location, use $sp as default value. */
+ char location[8] = "$sp"; /* 8 is enough for register name. */
+
+ if (argc == 2)
+ {
+ strncpy (location, argv[1], 8);
+ location[7] = '\0';
+ }
+
+ md_assemblef ("la $ta,%s", argv[0]);
+ md_assemblef ("smw.adm $ta,[%s],$ta", location);
+}
+
+static void
+do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
+{
+ /* If users omit push location, use $sp as default value. */
+ char location[8] = "$sp"; /* 8 is enough for register name. */
+
+ if (argc == 2)
+ {
+ strncpy (location, argv[1], 8);
+ location[7] = '\0';
+ }
+
+ md_assemblef ("li $ta,%s", argv[0]);
+ md_assemblef ("smw.adm $ta,[%s],$ta", location);
+}
+
+struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
+{
+ {"b", 1, do_pseudo_b, 0, 0},
+ {"bal", 1, do_pseudo_bal, 0, 0},
+
+ {"bge", 3, do_pseudo_bge, 0, 0},
+ {"bges", 3, do_pseudo_bges, 0, 0},
+
+ {"bgt", 3, do_pseudo_bgt, 0, 0},
+ {"bgts", 3, do_pseudo_bgts, 0, 0},
+
+ {"ble", 3, do_pseudo_ble, 0, 0},
+ {"bles", 3, do_pseudo_bles, 0, 0},
+
+ {"blt", 3, do_pseudo_blt, 0, 0},
+ {"blts", 3, do_pseudo_blts, 0, 0},
+
+ {"br", 1, do_pseudo_br, 0, 0},
+ {"bral", 1, do_pseudo_bral, 0, 0},
+
+ {"call", 1, do_pseudo_bal, 0, 0},
+
+ {"la", 2, do_pseudo_la, 0, 0},
+ {"li", 2, do_pseudo_li, 0, 0},
+
+ {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
+ {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
+ {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
+ {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
+ {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
+ {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
+ {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
+ {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
+
+ {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
+ {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
+ {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
+ {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
+ {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
+ {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
+ {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
+ {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
+ {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
+ {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
+ {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
+ {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
+ {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
+ {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
+ {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
+ {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
+ {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
+ {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
+
+ {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
+ {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
+ {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
+ {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
+ {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
+ {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
+ {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
+ {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
+ {"lwsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
+
+ {"move", 2, do_pseudo_move, 0, 0},
+ {"neg", 2, do_pseudo_neg, 0, 0},
+ {"not", 2, do_pseudo_not, 0, 0},
+
+ {"pop", 2, do_pseudo_pushpop, 0, 0},
+ {"push", 2, do_pseudo_pushpop, 0, 0},
+ {"popm", 2, do_pseudo_pushpopm, 0, 0},
+ {"pushm", 3, do_pseudo_pushpopm, 0, 0},
+
+ {"v3push", 2, do_pseudo_v3push, 0, 0},
+ {"v3pop", 2, do_pseudo_v3pop, 0, 0},
+
+ /* Support pseudo instructions of pushing/poping registers into/from stack
+ push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
+ pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
+ { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
+ { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
+ { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
+ { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
+ { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
+ { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
+ { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
+ { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
+ { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
+ { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
+ { "pusha", 2, do_pseudo_pusha, 0, 0 },
+ { "pushi", 2, do_pseudo_pushi, 0, 0 },
+
+ {NULL, 0, NULL, 0, 0}
+};
+
+static void
+nds32_init_nds32_pseudo_opcodes (void)
+{
+ struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table;
+
+ nds32_pseudo_opcode_hash = hash_new ();
+ for ( ; opcode->opcode; opcode++)
+ {
+ void *op;
+
+ op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode);
+ if (op != NULL)
+ {
+ as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode);
+ continue;
+ }
+ hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode);
+ }
+}
+
+static struct nds32_pseudo_opcode *
+nds32_lookup_pseudo_opcode (char *str)
+{
+ int i = 0;
+ /* Assume pseudo-opcode are less than 16-char in length. */
+ char op[16] = {0};
+
+ for (i = 0; i < (int)ARRAY_SIZE (op); i++)
+ {
+ if (ISSPACE (op[i] = str[i]))
+ break;
+ }
+
+ if (i >= (int)ARRAY_SIZE (op))
+ return NULL;
+
+ op[i] = '\0';
+
+ return hash_find (nds32_pseudo_opcode_hash, op);
+}
+
+static void
+nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
+{
+ int argc = 0;
+ char *argv[8] = {NULL};
+ char *s;
+ char *str = xstrdup (line);
+
+ /* Parse arguments for opcode. */
+ s = str + strlen (opcode->opcode);
+
+ if (!s[0])
+ goto end;
+
+ /* Dummy comma to ease separate arguments as below. */
+ s[0] = ',';
+ do
+ {
+ if (s[0] == ',')
+ {
+ if (argc >= opcode->argc
+ || (argc >= (int)ARRAY_SIZE (argv) - 1))
+ as_bad (_("Too many argument. `%s'"), line);
+
+ argv[argc] = s + 1;
+ argc ++;
+ s[0] = '\0';
+ }
+ ++s;
+ } while (s[0] != '\0');
+end:
+ /* Put the origin line for debugging. */
+ argv[argc] = line;
+ opcode->proc (argc, argv, opcode->pseudo_val);
+ free (str);
+}
+
+/* This function will be invoked from function `nds32_after_parse_args'.
+ Thus, if the value of option has been set, keep the value the way it is. */
+
+static int
+nds32_parse_arch (char *str)
+{
+ static const struct nds32_arch
+ {
+ const char *name;
+ int baseline;
+ int reduced_reg;
+ int fpu_sp_ext;
+ int fpu_dp_ext;
+ int fpu_freg;
+ int abi;
+ } archs[] =
+ {
+ {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
+ {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
+ {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
+ {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
+ {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
+ {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
+ {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
+ {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
+ {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE (archs); i++)
+ {
+ if (strcmp (str, archs[i].name) != 0)
+ continue;
+
+ /* The value `-1' represents this option has *NOT* been set. */
+ nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
+ nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
+ nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
+ nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
+ nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
+ nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
+
+ return 1;
+ }
+
+ /* Logic here rejects the input arch name. */
+ as_bad (_("unknown arch name `%s'\n"), str);
+
+ return 1;
+}
+
+/* This function parses "baseline" specified. */
+
+static int
+nds32_parse_baseline (char *str)
+{
+ if (strcmp (str, "v3") == 0)
+ nds32_baseline = ISA_V3;
+ else if (strcmp (str, "v3m") == 0)
+ nds32_baseline = ISA_V3M;
+ else if (strcmp (str, "v2") == 0)
+ nds32_baseline = ISA_V2;
+ else
+ {
+ /* Logic here rejects the input baseline. */
+ as_bad (_("unknown baseline `%s'\n"), str);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* This function parses "fpu-freg" specified. */
+
+static int
+nds32_parse_freg (char *str)
+{
+ if (strcmp (str, "2") == 0)
+ nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
+ else if (strcmp (str, "3") == 0)
+ nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
+ else if (strcmp (str, "1") == 0)
+ nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
+ else if (strcmp (str, "0") == 0)
+ nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
+ else
+ {
+ /* Logic here rejects the input FPU configuration. */
+ as_bad (_("unknown FPU configuration `%s'\n"), str);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* This function parse "abi=" specified. */
+
+static int
+nds32_parse_abi (char *str)
+{
+ if (strcmp (str, "v2") == 0)
+ nds32_abi = E_NDS_ABI_AABI;
+ /* Obsolete. */
+ else if (strcmp (str, "v2fp") == 0)
+ nds32_abi = E_NDS_ABI_V2FP;
+ else if (strcmp (str, "v1") == 0)
+ nds32_abi = E_NDS_ABI_V1;
+ else if (strcmp (str,"v2fpp") == 0)
+ nds32_abi = E_NDS_ABI_V2FP_PLUS;
+ else
+ {
+ /* Logic here rejects the input abi version. */
+ as_bad (_("unknown ABI version`%s'\n"), str);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* This function turn on all extensions and instructions support. */
+
+static int
+nds32_all_ext (void)
+{
+ nds32_mac = 1;
+ nds32_div = 1;
+ nds32_dx_regs = 1;
+ nds32_16bit_ext = 1;
+ nds32_perf_ext = 1;
+ nds32_perf_ext2 = 1;
+ nds32_string_ext = 1;
+ nds32_audio_ext = 1;
+ nds32_fpu_fma = 1;
+ nds32_fpu_sp_ext = 1;
+ nds32_fpu_dp_ext = 1;
+
+ return 1;
+}
+
+/* GAS will call md_parse_option whenever getopt returns an unrecognized code,
+ presumably indicating a special code value which appears in md_longopts.
+ This function should return non-zero if it handled the option and zero
+ otherwise. There is no need to print a message about an option not being
+ recognized. This will be handled by the generic code. */
+
+int
+nds32_parse_option (int c, char *arg)
+{
+ struct nds32_parse_option_table *coarse_tune;
+ struct nds32_set_option_table *fine_tune;
+ char *ptr_arg = NULL;
+
+ switch (c)
+ {
+ case OPTION_OPTIMIZE:
+ optimize = 1;
+ optimize_for_space = 0;
+ break;
+ case OPTION_OPTIMIZE_SPACE:
+ optimize = 0;
+ optimize_for_space = 1;
+ break;
+ case OPTION_BIG:
+ target_big_endian = 1;
+ break;
+ case OPTION_LITTLE:
+ target_big_endian = 0;
+ break;
+ case OPTION_TURBO:
+ nds32_all_ext ();
+ break;
+ case OPTION_PIC:
+ nds32_pic = 1;
+ break;
+ case OPTION_RELAX_FP_AS_GP_OFF:
+ nds32_relax_fp_as_gp = 0;
+ break;
+ case OPTION_RELAX_B2BB_ON:
+ nds32_relax_b2bb = 1;
+ break;
+ case OPTION_RELAX_ALL_OFF:
+ nds32_relax_all = 0;
+ break;
+ default:
+ /* Determination of which option table to search for to save time. */
+ ptr_arg = strchr (arg, '=');
+ if (ptr_arg)
+ {
+ /* Find the value after '='. */
+ if (ptr_arg != NULL)
+ ptr_arg++;
+ for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
+ {
+ if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
+ {
+ coarse_tune->func (ptr_arg);
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
+ {
+ int disable = 0;
+
+ /* Filter out the Disable option first. */
+ if (strncmp (arg, "no-", 3) == 0)
+ {
+ disable = 1;
+ arg += 3;
+ }
+
+ if (strcmp (arg, fine_tune->name) == 0)
+ {
+ if (fine_tune->var != NULL)
+ *fine_tune->var = (disable) ? 0 : 1;
+ return 1;
+ }
+ }
+ }
+ /* Nothing match. */
+ return 0;
+ }
+
+ return 1;
+}
+
+/* tc_check_label */
+
+void
+nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
+{
+ /* The code used to create BB is move to frob_label.
+ They should go there. */
+}
+
+static void
+set_endian_little (int on)
+{
+ target_big_endian = !on;
+}
+
+/* These functions toggles the generation of 16-bit. First encounter signals
+ the beginning of not generating 16-bit instructions and next encounter
+ signals the restoring back to default behavior. */
+
+static void
+trigger_16bit (int trigger)
+{
+ enable_16bit = trigger;
+}
+
+static int backup_16bit_mode;
+static void
+restore_16bit (int no_use ATTRIBUTE_UNUSED)
+{
+ enable_16bit = backup_16bit_mode;
+}
+
+static void
+off_16bit (int no_use ATTRIBUTE_UNUSED)
+{
+ backup_16bit_mode = enable_16bit;
+ enable_16bit = 0;
+}
+
+/* Built-in segments for small object. */
+typedef struct nds32_seg_entryT
+{
+ segT s;
+ const char *name;
+ flagword flags;
+} nds32_seg_entry;
+
+nds32_seg_entry nds32_seg_table[] =
+{
+ {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
+ {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
+ {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
+ {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
+ {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
+ | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
+ {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
+ {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
+ {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
+ {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
+ {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
+};
+
+/* Indexes to nds32_seg_table[]. */
+enum NDS32_SECTIONS_ENUM
+{
+ SDATA_F_SECTION = 0,
+ SDATA_B_SECTION = 1,
+ SDATA_H_SECTION = 2,
+ SDATA_W_SECTION = 3,
+ SDATA_D_SECTION = 4,
+ SBSS_F_SECTION = 5,
+ SBSS_B_SECTION = 6,
+ SBSS_H_SECTION = 7,
+ SBSS_W_SECTION = 8,
+ SBSS_D_SECTION = 9
+};
+
+/* The following code is borrowed from v850_seg. Revise this is needed. */
+
+static void
+do_nds32_seg (int i, subsegT sub)
+{
+ nds32_seg_entry *seg = nds32_seg_table + i;
+
+ obj_elf_section_change_hook ();
+
+ if (seg->s != NULL)
+ subseg_set (seg->s, sub);
+ else
+ {
+ seg->s = subseg_new (seg->name, sub);
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ bfd_set_section_flags (stdoutput, seg->s, seg->flags);
+ if ((seg->flags & SEC_LOAD) == 0)
+ seg_info (seg->s)->bss = 1;
+ }
+ }
+}
+
+static void
+nds32_seg (int i)
+{
+ subsegT sub = get_absolute_expression ();
+
+ do_nds32_seg (i, sub);
+ demand_empty_rest_of_line ();
+}
+
+/* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
+static symbolS *nds32_last_label; /* Last label for aligment. */
+
+/* This code is referred from D30V for adjust label to be with pedning
+ aligment. For example,
+ LBYTE: .byte 0x12
+ LHALF: .half 0x12
+ LWORD: .word 0x12
+ Without this, the above label will not attatch to incoming data. */
+
+static void
+nds32_adjust_label (int n)
+{
+ /* FIXME: I think adjust lable and alignment is
+ the programmer's obligation. Saddly, VLSI team doesn't
+ properly use .align for their test cases.
+ So I re-implement cons_align and auto adjust labels, again.
+
+ I think d30v's implmentation is simple and good enough. */
+
+ symbolS *label = nds32_last_label;
+ nds32_last_label = NULL;
+
+ /* SEC_ALLOC is used to eliminate .debug_ sections.
+ SEC_CODE is used to include section for ILM. */
+ if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
+ || strcmp (now_seg->name, ".eh_frame") == 0
+ || strcmp (now_seg->name, ".gcc_except_table") == 0)
+ return;
+
+ /* Only frag by alignment when needed.
+ Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
+ See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
+ if (frag_now_fix () & ((1 << n) -1 ))
+ {
+ if (subseg_text_p (now_seg))
+ frag_align_code (n, 0);
+ else
+ frag_align (n, 0, 0);
+
+ /* Record the minimum alignment for this segment. */
+ record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
+ }
+
+ if (label != NULL)
+ {
+ symbolS *sym;
+ int label_seen = FALSE;
+ struct frag *old_frag;
+ valueT old_value, new_value;
+
+ gas_assert (S_GET_SEGMENT (label) == now_seg);
+
+ old_frag = symbol_get_frag (label);
+ old_value = S_GET_VALUE (label);
+ new_value = (valueT) frag_now_fix ();
+
+ /* Multiple labels may be on the same address. And the last symbol
+ may not be a label at all, e.g., register name, external function names,
+ so I have to track the last label in tc_frob_label instead of
+ just using symbol_lastP. */
+ for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
+ {
+ if (symbol_get_frag (sym) == old_frag
+ && S_GET_VALUE (sym) == old_value)
+ {
+ /* Warning HERE! */
+ label_seen = TRUE;
+ symbol_set_frag (sym, frag_now);
+ S_SET_VALUE (sym, new_value);
+ }
+ else if (label_seen && symbol_get_frag (sym) != old_frag)
+ break;
+ }
+ }
+}
+
+void
+nds32_cons_align (int size ATTRIBUTE_UNUSED)
+{
+ /* Do nothing here.
+ This is called before `md_flush_pending_output' is called by `cons'.
+
+ There are two things should be done for auto-adjust-label.
+ 1. Align data/instructions and adjust label to be attached to them.
+ 2. Clear auto-adjust state, so incommng data/instructions will not
+ adjust the label.
+
+ For example,
+ .byte 0x1
+ .L0:
+ .word 0x2
+ .word 0x3
+ in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
+
+ I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
+ but it is also called by `cons' before this function.
+ To simplify the code, instead of overriding .zero, .fill, .space, etc,
+ I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
+}
+
+static void
+nds32_aligned_cons (int idx)
+{
+ nds32_adjust_label (idx);
+ /* Call default handler. */
+ cons (1 << idx);
+ if (now_seg->flags & SEC_CODE
+ && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
+ {
+ /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */
+ expressionS exp;
+
+ exp.X_add_number = 0;
+ exp.X_op = O_constant;
+ fix_new_exp (frag_now,
+ frag_now_fix () - (1 << idx),
+ 1 << idx,
+ &exp,
+ 0,
+ BFD_RELOC_NDS32_DATA);
+ }
+}
+
+/* `.double' directive. */
+
+static void
+nds32_aligned_float_cons (int type)
+{
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ nds32_adjust_label (2);
+ break;
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ nds32_adjust_label (4);
+ break;
+ default:
+ as_bad ("Unrecognized float type, %c\n", (char)type);
+ }
+ /* Call default handler. */
+ float_cons (type);
+}
+
+static void
+nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
+{
+ /* Another way to do -mpic.
+ This is for GCC internal use and should always be first line
+ of code, otherwise, the effect is not determined. */
+ nds32_pic = 1;
+}
+
+static void
+nds32_set_abi (int ver)
+{
+ nds32_abi = ver;
+}
+
+/* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
+
+static void
+nds32_relax_relocs (int relax)
+{
+ char saved_char;
+ char *name;
+ int i;
+ char *subtype_relax[] =
+ {"", "", "ex9", "ifc"};
+
+ name = input_line_pointer;
+ while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+ input_line_pointer++;
+ saved_char = *input_line_pointer;
+ *input_line_pointer = 0;
+
+ for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
+ {
+ if (strcmp (name, subtype_relax[i]) == 0)
+ {
+ switch (i)
+ {
+ case 0:
+ case 1:
+ enable_relax_relocs = relax & enable_relax_relocs;
+ enable_relax_ex9 = relax & enable_relax_ex9;
+ enable_relax_ifc = relax & enable_relax_ifc;
+ break;
+ case 2:
+ enable_relax_ex9 = relax;
+ break;
+ case 3:
+ enable_relax_ifc = relax;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ *input_line_pointer = saved_char;
+ ignore_rest_of_line ();
+}
+
+/* Record which arguments register($r0 ~ $r5) is not used in callee.
+ bit[i] for $ri */
+
+static void
+nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
+{
+ ignore_rest_of_line ();
+}
+
+/* Insert relocations to mark the begin and end of a fp-omitted function,
+ for further relaxation use.
+ bit[i] for $ri */
+
+static void
+nds32_omit_fp_begin (int mode)
+{
+ expressionS exp;
+
+ if (nds32_relax_fp_as_gp == 0)
+ return;
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = abs_section_sym;
+ if (mode == 1)
+ {
+ exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
+ fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
+ BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
+ }
+ else
+ {
+ exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
+ fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
+ BFD_RELOC_NDS32_RELAX_REGION_END);
+ }
+}
+
+/* Insert relocations to mark the begin and end of ex9 region,
+ for further relaxation use.
+ bit[i] for $ri */
+
+static void
+nds32_no_ex9_begin (int mode)
+{
+ expressionS exp;
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = abs_section_sym;
+ if (mode == 1)
+ {
+ exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
+ fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
+ BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
+ }
+ else
+ {
+ exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
+ fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
+ BFD_RELOC_NDS32_RELAX_REGION_END);
+ }
+}
+
+static void
+nds32_loop_begin (int mode)
+{
+ /* Insert loop region relocation here. */
+ expressionS exp;
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = abs_section_sym;
+ if (mode == 1)
+ {
+ exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
+ fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
+ BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
+ }
+ else
+ {
+ exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
+ fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
+ BFD_RELOC_NDS32_RELAX_REGION_END);
+ }
+}
+
+struct nds32_relocs_group
+{
+ struct nds32_relocs_pattern *pattern;
+ struct nds32_relocs_group *next;
+};
+
+static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
+
+/* Insert a relax hint. */
+
+static void
+nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
+{
+ char *name;
+ char saved_char;
+ struct nds32_relocs_pattern *relocs = NULL;
+ struct nds32_relocs_group *group, *new;
+
+ name = input_line_pointer;
+ while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+ input_line_pointer++;
+ saved_char = *input_line_pointer;
+ *input_line_pointer = 0;
+ name = strdup (name);
+
+ /* Find relax hint entry for next instruction, and all member will be
+ initialized at that time. */
+ relocs = hash_find (nds32_hint_hash, name);
+ if (relocs == NULL)
+ {
+ relocs = malloc (sizeof (struct nds32_relocs_pattern));
+ hash_insert (nds32_hint_hash, name, relocs);
+ }
+ else
+ {
+ while (relocs->next)
+ relocs=relocs->next;
+ relocs->next = malloc (sizeof (struct nds32_relocs_pattern));
+ relocs = relocs->next;
+ }
+
+ relocs->next = NULL;
+ *input_line_pointer = saved_char;
+ ignore_rest_of_line ();
+
+ /* Get the final one of relax hint series. */
+
+ /* It has to build this list because there are maybe more than one
+ instructions relative to the same instruction. It to connect to
+ next instruction after md_assemble. */
+ new = malloc (sizeof (struct nds32_relocs_group));
+ new->pattern = relocs;
+ new->next = NULL;
+ group = nds32_relax_hint_current;
+ if (!group)
+ nds32_relax_hint_current = new;
+ else
+ {
+ while (group->next != NULL)
+ group = group->next;
+ group->next = new;
+ }
+}
+
+/* Decide the size of vector entries, only accepts 4 or 16 now. */
+
+static void
+nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
+{
+ expressionS exp;
+
+ expression (&exp);
+
+ if (exp.X_op == O_constant)
+ {
+ if (exp.X_add_number == 4 || exp.X_add_number == 16)
+ {
+ if (vec_size == 0)
+ vec_size = exp.X_add_number;
+ else if (vec_size != exp.X_add_number)
+ as_warn (_("Different arguments of .vec_size are found, "
+ "previous %d, current %d"),
+ (int) vec_size, (int) exp.X_add_number);
+ }
+ else
+ as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
+ (int) exp.X_add_number);
+ }
+ else
+ as_warn (_("Argument of .vec_size is not a constant."));
+}
+
+/* The behavior of ".flag" directive varies depending on the target.
+ In nds32 target, we use it to recognize whether this assembly content is
+ generated by compiler. Other features can also be added in this function
+ in the future. */
+
+static void
+nds32_flag (int ignore ATTRIBUTE_UNUSED)
+{
+ char *name;
+ char saved_char;
+ int i;
+ char *possible_flags[] = { "verbatim" };
+
+ /* Skip whitespaces. */
+ name = input_line_pointer;
+ while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+ input_line_pointer++;
+ saved_char = *input_line_pointer;
+ *input_line_pointer = 0;
+
+ for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
+ {
+ if (strcmp (name, possible_flags[i]) == 0)
+ {
+ switch (i)
+ {
+ case 0:
+ /* flag: verbatim */
+ verbatim = 1;
+ break;
+ default:
+ break;
+ }
+ /* Already found the flag, no need to continue next loop. */
+ break;
+ }
+ }
+
+ *input_line_pointer = saved_char;
+ ignore_rest_of_line ();
+}
+
+static void
+nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
+{
+ /* N1213HC core is used. */
+}
+
+
+/* The target specific pseudo-ops which we support. */
+const pseudo_typeS md_pseudo_table[] =
+{
+ /* Forced alignment if declared these ways. */
+ {"ascii", stringer, 8 + 0},
+ {"asciz", stringer, 8 + 1},
+ {"double", nds32_aligned_float_cons, 'd'},
+ {"dword", nds32_aligned_cons, 3},
+ {"float", nds32_aligned_float_cons, 'f'},
+ {"half", nds32_aligned_cons, 1},
+ {"hword", nds32_aligned_cons, 1},
+ {"int", nds32_aligned_cons, 2},
+ {"long", nds32_aligned_cons, 2},
+ {"octa", nds32_aligned_cons, 4},
+ {"quad", nds32_aligned_cons, 3},
+ {"qword", nds32_aligned_cons, 4},
+ {"short", nds32_aligned_cons, 1},
+ {"byte", nds32_aligned_cons, 0},
+ {"single", nds32_aligned_float_cons, 'f'},
+ {"string", stringer, 8 + 1},
+ {"word", nds32_aligned_cons, 2},
+
+ {"little", set_endian_little, 1},
+ {"big", set_endian_little, 0},
+ {"16bit_on", trigger_16bit, 1},
+ {"16bit_off", trigger_16bit, 0},
+ {"restore_16bit", restore_16bit, 0},
+ {"off_16bit", off_16bit, 0},
+
+ {"sdata_d", nds32_seg, SDATA_D_SECTION},
+ {"sdata_w", nds32_seg, SDATA_W_SECTION},
+ {"sdata_h", nds32_seg, SDATA_H_SECTION},
+ {"sdata_b", nds32_seg, SDATA_B_SECTION},
+ {"sdata_f", nds32_seg, SDATA_F_SECTION},
+
+ {"sbss_d", nds32_seg, SBSS_D_SECTION},
+ {"sbss_w", nds32_seg, SBSS_W_SECTION},
+ {"sbss_h", nds32_seg, SBSS_H_SECTION},
+ {"sbss_b", nds32_seg, SBSS_B_SECTION},
+ {"sbss_f", nds32_seg, SBSS_F_SECTION},
+
+ {"pic", nds32_enable_pic, 0},
+ {"n12_hc", nds32_n12hc, 0},
+ {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
+ {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
+ /* Obsolete. */
+ {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
+ {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
+ {"relax", nds32_relax_relocs, 1},
+ {"no_relax", nds32_relax_relocs, 0},
+ {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
+ {"omit_fp_begin", nds32_omit_fp_begin, 1},
+ {"omit_fp_end", nds32_omit_fp_begin, 0},
+ {"no_ex9_begin", nds32_no_ex9_begin, 1},
+ {"no_ex9_end", nds32_no_ex9_begin, 0},
+ {"vec_size", nds32_vec_size, 0},
+ {"flag", nds32_flag, 0},
+ {"innermost_loop_begin", nds32_loop_begin, 1},
+ {"innermost_loop_end", nds32_loop_begin, 0},
+ {"relax_hint", nds32_relax_hint, 0},
+ {NULL, NULL, 0}
+};
+
+void
+nds32_pre_do_align (int n, char *fill, int len, int max)
+{
+ /* Only make a frag if we HAVE to... */
+ if (n != 0 && !need_pass_2)
+ {
+ if (fill == NULL)
+ {
+ if (subseg_text_p (now_seg))
+ frag_align_code (n, max);
+ else
+ frag_align (n, 0, max);
+ }
+ else if (len <= 1)
+ frag_align (n, *fill, max);
+ else
+ frag_align_pattern (n, fill, len, max);
+ }
+}
+
+void
+nds32_do_align (int n)
+{
+ /* Optimize for space and label exists. */
+ expressionS exp;
+
+ /* FIXME:I think this will break debug info sections and except_table. */
+ if (!enable_relax_relocs || !subseg_text_p (now_seg))
+ return;
+
+ /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
+ the size of instruction may not be correct because
+ it could be relaxable. */
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = section_symbol (now_seg);
+ exp.X_add_number = n;
+ fix_new_exp (frag_now,
+ frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
+}
+
+/* Supported Andes machines. */
+struct nds32_machs
+{
+ enum bfd_architecture bfd_mach;
+ int mach_flags;
+};
+
+/* This is the callback for nds32-asm.c to parse operands. */
+
+int
+nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
+ struct nds32_asm_insn *pinsn,
+ char **pstr, int64_t *value)
+{
+ char *hold;
+ expressionS *pexp = pinsn->info;
+
+ hold = input_line_pointer;
+ input_line_pointer = *pstr;
+ expression (pexp);
+ *pstr = input_line_pointer;
+ input_line_pointer = hold;
+
+ switch (pexp->X_op)
+ {
+ case O_symbol:
+ *value = 0;
+ return NASM_R_SYMBOL;
+ case O_constant:
+ *value = pexp->X_add_number;
+ return NASM_R_CONST;
+ case O_illegal:
+ case O_absent:
+ case O_register:
+ default:
+ return NASM_R_ILLEGAL;
+ }
+}
+
+/* GAS will call this function at the start of the assembly, after the command
+ line arguments have been parsed and all the machine independent
+ initializations have been completed. */
+
+void
+md_begin (void)
+{
+ struct nds32_keyword *k;
+ relax_info_t *relax_info;
+
+ bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
+
+ nds32_init_nds32_pseudo_opcodes ();
+ asm_desc.parse_operand = nds32_asm_parse_operand;
+ nds32_asm_init (&asm_desc, 0);
+
+ /* Initial general pupose registers hash table. */
+ nds32_gprs_hash = hash_new ();
+ for (k = nds32_gprs; k->name; k++)
+ hash_insert (nds32_gprs_hash, k->name, k);
+
+ /* Initial branch hash table. */
+ nds32_relax_info_hash = hash_new ();
+ for (relax_info = relax_table; relax_info->opcode; relax_info++)
+ hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info);
+
+ /* Initial relax hint hash table. */
+ nds32_hint_hash = hash_new ();
+}
+
+/* HANDLE_ALIGN in write.c. */
+
+void
+nds32_handle_align (fragS *fragp)
+{
+ static const unsigned char nop16[] = { 0x92, 0x00 };
+ static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
+ int bytes;
+ char *p;
+
+ if (fragp->fr_type != rs_align_code)
+ return;
+
+ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+ p = fragp->fr_literal + fragp->fr_fix;
+
+ if (bytes & 1)
+ {
+ *p++ = 0;
+ bytes--;
+ }
+
+ if (bytes & 2)
+ {
+ expressionS exp_t;
+ exp_t.X_op = O_symbol;
+ exp_t.X_add_symbol = abs_section_sym;
+ exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
+ fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
+ BFD_RELOC_NDS32_INSN16);
+ memcpy (p, nop16, 2);
+ p += 2;
+ bytes -= 2;
+ }
+
+ while (bytes >= 4)
+ {
+ memcpy (p, nop32, 4);
+ p += 4;
+ bytes -= 4;
+ }
+
+ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+ fragp->fr_fix += bytes;
+}
+
+/* md_flush_pending_output */
+
+void
+nds32_flush_pending_output (void)
+{
+ nds32_last_label = NULL;
+}
+
+void
+nds32_frob_label (symbolS *label)
+{
+ dwarf2_emit_label (label);
+}
+
+/* TC_START_LABEL */
+
+int
+nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
+{
+ return 1;
+}
+
+/* TARGET_FORMAT */
+
+const char *
+nds32_target_format (void)
+{
+#ifdef TE_LINUX
+ if (target_big_endian)
+ return "elf32-nds32be-linux";
+ else
+ return "elf32-nds32le-linux";
+#else
+ if (target_big_endian)
+ return "elf32-nds32be";
+ else
+ return "elf32-nds32le";
+#endif
+}
+
+static enum nds32_br_range
+get_range_type (const struct nds32_field *field)
+{
+ gas_assert (field != NULL);
+
+ if (field->bitpos != 0)
+ return BR_RANGE_U4G;
+
+ if (field->bitsize == 24 && field->shift == 1)
+ return BR_RANGE_S16M;
+ else if (field->bitsize == 16 && field->shift == 1)
+ return BR_RANGE_S64K;
+ else if (field->bitsize == 14 && field->shift == 1)
+ return BR_RANGE_S16K;
+ else if (field->bitsize == 8 && field->shift == 1)
+ return BR_RANGE_S256;
+ else
+ return BR_RANGE_U4G;
+}
+
+/* Save pseudo instruction relocation list. */
+
+static struct nds32_relocs_pattern*
+nds32_elf_save_pseudo_pattern (int reloc, struct nds32_asm_insn *insn,
+ char *out, symbolS *sym,
+ struct nds32_relocs_pattern *reloc_ptr)
+{
+ if (!reloc_ptr)
+ reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern));
+ reloc_ptr->seg = now_seg;
+ reloc_ptr->sym = sym;
+ reloc_ptr->frag = frag_now;
+ reloc_ptr->frchain = frchain_now;
+ reloc_ptr->reloc = reloc;
+ reloc_ptr->insn = insn->opcode->value;
+ reloc_ptr->size = insn->opcode->isize;
+ reloc_ptr->where = out;
+ reloc_ptr->next = NULL;
+ return reloc_ptr;
+}
+
+/* Check X_md to transform relocation. */
+
+static void
+nds32_elf_record_fixup_exp (char *str, const struct nds32_field *fld,
+ expressionS *pexp, char* out,
+ struct nds32_asm_insn *insn)
+{
+ int reloc = -1;
+ symbolS *sym = NULL;
+ struct nds32_relocs_group *group;
+ struct nds32_relocs_pattern *reloc_ptr;
+
+ /* Handle instruction relocation. */
+ if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
+ {
+ /* Relocation for hi20 modifier. */
+ sym = pexp->X_add_symbol;
+ switch (pexp->X_md)
+ {
+ case BFD_RELOC_NDS32_GOTOFF:
+ /* @GOTOFF */
+ reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
+ break;
+ case BFD_RELOC_NDS32_GOT20:
+ /* @GOT */
+ reloc = BFD_RELOC_NDS32_GOT_HI20;
+ break;
+ case BFD_RELOC_NDS32_25_PLTREL:
+ /* @PLT */
+ if (!nds32_pic)
+ as_bad (_("Invalid PIC expression."));
+ else
+ reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
+ break;
+ default:
+ /* No suffix. */
+ reloc = BFD_RELOC_NDS32_HI20;
+ break;
+ }
+
+ fix_new_exp (frag_now, out - frag_now->fr_literal,
+ insn->opcode->isize, insn->info, 0 /* pcrel */,
+ reloc);
+ }
+ else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
+ {
+ /* Relocation for lo12 modifier. */
+ if (fld->bitsize == 15 && fld->shift == 0)
+ {
+ switch (pexp->X_md)
+ {
+ case BFD_RELOC_NDS32_GOTOFF:
+ /* @GOTOFF */
+ reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
+ break;
+ case BFD_RELOC_NDS32_GOT20:
+ /* @GOT */
+ reloc = BFD_RELOC_NDS32_GOT_LO12;
+ break;
+ case BFD_RELOC_NDS32_25_PLTREL:
+ /* @PLT */
+ if (!nds32_pic)
+ as_bad (_("Invalid PIC expression."));
+ else
+ reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
+ break;
+ default:
+ /* No suffix. */
+ reloc = BFD_RELOC_NDS32_LO12S0; /* [ls]bi || ori */
+ break;
+ }
+ }
+ else if (fld->bitsize == 15 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
+ else if (fld->bitsize == 15 && fld->shift == 2)
+ reloc = BFD_RELOC_NDS32_LO12S2; /* [ls]wi */
+ else if (fld->bitsize == 15 && fld->shift == 3)
+ reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
+ else if (fld->bitsize == 12 && fld->shift == 2)
+ reloc = BFD_RELOC_NDS32_LO12S2; /* f[ls][sd]i */
+
+ fix_new_exp (frag_now, out - frag_now->fr_literal,
+ insn->opcode->isize, insn->info, 0 /* pcrel */,
+ reloc);
+ }
+ else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
+ && (insn->attr & NASM_ATTR_PCREL))
+ {
+ /* Relocation for 32-bit branch instructions. */
+ if (fld->bitsize == 24 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_25_PCREL;
+ else if (fld->bitsize == 16 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_17_PCREL;
+ else if (fld->bitsize == 14 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_15_PCREL;
+ else if (fld->bitsize == 8 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
+ else
+ abort ();
+
+ fix_new_exp (frag_now, out - frag_now->fr_literal,
+ insn->opcode->isize, insn->info, 1 /* pcrel */,
+ reloc);
+ }
+ else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
+ && (insn->attr & NASM_ATTR_GPREL))
+ {
+ /* Relocation for 32-bit gp-relative instructions. */
+ if (fld->bitsize == 19 && fld->shift == 0)
+ reloc = BFD_RELOC_NDS32_SDA19S0;
+ else if (fld->bitsize == 18 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_SDA18S1;
+ else if (fld->bitsize == 17 && fld->shift == 2)
+ reloc = BFD_RELOC_NDS32_SDA17S2;
+ else
+ abort ();
+
+ fix_new_exp (frag_now, out - frag_now->fr_literal,
+ insn->opcode->isize, insn->info, 0 /* pcrel */,
+ reloc);
+ }
+ else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
+ && (insn->attr & NASM_ATTR_PCREL))
+ {
+ /* Relocation for 16-bit branch instructions. */
+ if (fld->bitsize == 8 && fld->shift == 1)
+ reloc = BFD_RELOC_NDS32_9_PCREL;
+ else
+ abort ();
+
+ fix_new_exp (frag_now, out - frag_now->fr_literal,
+ insn->opcode->isize, insn->info, 1 /* pcrel */,
+ reloc);
+ }
+ else if (fld)
+ {
+ as_bad (_("Don't know how to handle this field. %s"),
+ str);
+ }
+
+ if (pseudo_opcode)
+ {
+ /* Save instruction relation for pseudo instruction expanding pattern. */
+ reloc_ptr = nds32_elf_save_pseudo_pattern (reloc, insn, out, sym, NULL);
+ if (!relocs_list)
+ relocs_list = reloc_ptr;
+ else
+ {
+ struct nds32_relocs_pattern *temp = relocs_list;
+ while (temp->next)
+ temp = temp->next;
+ temp->next = reloc_ptr;
+ }
+ }
+ else if (nds32_relax_hint_current)
+ {
+ /* Save instruction relation by relax hint. */
+ group = nds32_relax_hint_current;
+ while (group)
+ {
+ nds32_elf_save_pseudo_pattern (reloc, insn, out, sym, group->pattern);
+ group = group->next;
+ free (nds32_relax_hint_current);
+ nds32_relax_hint_current = group;
+ }
+ }
+}
+
+#define N32_MEM_EXT(insn) (N32_OP6_MEM<< 25| insn)
+
+/* Relax pattern for link time relaxation. */
+
+static struct nds32_relocation_map relocation_table[] =
+{
+ {
+ /* Load-Store: sethi lwi+
+ Load address: sethi ori */
+ BFD_RELOC_NDS32_HI20, /* main_type */
+ {
+ {
+ {BFD_RELOC_NDS32_LOADSTORE, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_INSN16, 0},
+ {0, 0}
+ },
+ {
+ {0, 0}
+ }
+ },
+ },
+ {
+ /* Load-Store: sethi ori lwi+
+ Load address: sethi ori add */
+ BFD_RELOC_NDS32_GOTOFF_HI20, /* main_type */
+ {
+ {
+ {BFD_RELOC_NDS32_LOADSTORE, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_INSN16, 0},
+ {BFD_RELOC_NDS32_PTR, 0},
+ {BFD_RELOC_NDS32_PTR_COUNT, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_GOTOFF_SUFF, 0},
+ {BFD_RELOC_NDS32_PTR_RESOLVED, 0},
+ {0, 0}
+ },
+ {
+ {0, 0}
+ }
+ },
+ },
+ {
+ /* Load-Store: sethi ori lw lwi+
+ Load address: sethi ori lw [addi|add] */
+ BFD_RELOC_NDS32_GOT_HI20, /* main_type */
+ {
+ {
+ {BFD_RELOC_NDS32_LOADSTORE, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_INSN16, 0},
+ /* For pseudo la and l.w.
+ Lw is the next one instruction. */
+ {BFD_RELOC_NDS32_PTR, N32_MEM_EXT (N32_MEM_LW)},
+ {BFD_RELOC_NDS32_PTR_COUNT, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_GOT_SUFF, N32_MEM_EXT (N32_MEM_LW)},
+ {BFD_RELOC_NDS32_PTR_RESOLVED, N32_MEM_EXT (N32_MEM_LW)},
+ {0, 0}
+ },
+ {
+ {0, 0},
+ },
+ },
+ },
+ {
+ BFD_RELOC_NDS32_PLT_GOTREL_HI20, /* main_type */
+ {
+ {
+ {BFD_RELOC_NDS32_LOADSTORE, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_INSN16, 0},
+ /* For pseudo bal.
+ jral is the target instruction. */
+ {BFD_RELOC_NDS32_PTR, INSN_JRAL},
+ {BFD_RELOC_NDS32_PTR, (INSN_JRAL | (REG_LP << 20))},
+ {BFD_RELOC_NDS32_PTR_COUNT, 0},
+ {0, 0}
+ },
+ {
+ /* For pseudo bal.
+ jral is the target instruction. */
+ {BFD_RELOC_NDS32_PTR, INSN_JRAL},
+ {BFD_RELOC_NDS32_PTR, (INSN_JRAL | (REG_LP << 20))},
+ {BFD_RELOC_NDS32_PTR_COUNT, 0},
+ {0, 0}
+ },
+ {
+ {BFD_RELOC_NDS32_PLT_GOT_SUFF, 0},
+ {BFD_RELOC_NDS32_PTR_RESOLVED, 0},
+ {0, 0}
+ },
+ {
+ {0, 0},
+ },
+ },
+ },
+ {
+ 0,
+ {
+ {
+ {0, 0},
+ },
+ },
+ }
+};
+
+/* Since sethi loadstore relocation has to using next instruction to determine
+ elimination itself or not, we have to return the next instruction range. */
+
+static int
+nds32_elf_sethi_range (struct nds32_relocs_pattern *relocs_ptr)
+{
+ unsigned int insn = relocs_ptr->insn;
+ int range;
+ switch (insn)
+ {
+ case INSN_LBI:
+ case INSN_SBI:
+ case INSN_LBSI:
+ case N32_MEM_EXT (N32_MEM_LB):
+ case N32_MEM_EXT (N32_MEM_LBS):
+ case N32_MEM_EXT (N32_MEM_SB):
+ range = 0x01;
+ break;
+ case INSN_LHI:
+ case INSN_SHI:
+ case INSN_LHSI:
+ case N32_MEM_EXT (N32_MEM_LH):
+ case N32_MEM_EXT (N32_MEM_LHS):
+ case N32_MEM_EXT (N32_MEM_SH):
+ range = 0x02;
+ break;
+ case INSN_LWI:
+ case INSN_SWI:
+ case N32_MEM_EXT (N32_MEM_LW):
+ case N32_MEM_EXT (N32_MEM_SW):
+ range = 0x04;
+ break;
+ case INSN_FLSI:
+ case INSN_FSSI:
+ range = 0x08;
+ break;
+ case INSN_FLDI:
+ case INSN_FSDI:
+ range = 0x10;
+ break;
+ case INSN_ORI:
+ range = 0x20;
+ break;
+ default:
+ range = 0x0;
+ break;
+ }
+ return range;
+}
+
+/* The args means: instruction size, the 1st instruction is converted to 16 or
+ not, optimize option, 16 bit instruction is enable. */
+#define SET_ADDEND( size, convertible, optimize, insn16_on ) \
+ (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
+ | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
+
+/* Insert new fix. */
+
+static void
+nds32_elf_insert_relocation (struct nds32_relocs_pattern *pattern, unsigned int reloc,
+ unsigned int insn_mask, symbolS *sym)
+{
+ expressionS exp;
+ symbolS *sym_t;
+ struct nds32_relocs_pattern *pattern_t;
+ int range;
+ fragS *frag = pattern->frag;
+ char *out = pattern->where;
+ unsigned int size = pattern->size;
+ static int ptr_count = 0;
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = abs_section_sym;
+ exp.X_add_number = 0;
+
+ switch (reloc)
+ {
+ case BFD_RELOC_NDS32_LOADSTORE:
+ /* To get the sethi match pattern. */
+ range = nds32_elf_sethi_range (pattern->next);
+ exp.X_add_number = SET_ADDEND (4 /* size */, 0, optimize, enable_16bit);
+ exp.X_add_number |= ((range & 0x3f) << 8);
+ fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0 /* pcrel */, reloc);
+ break;
+
+ case BFD_RELOC_NDS32_PTR:
+ pattern_t = pattern->next;
+ while (pattern_t)
+ {
+ if (insn_mask == 0 || pattern_t->insn == insn_mask)
+ {
+ sym_t = symbol_temp_new (pattern_t->seg,
+ pattern_t->where - pattern_t->frag->fr_literal,
+ pattern_t->frag);
+ exp.X_add_symbol = sym_t;
+ fix_new_exp (frag, out - frag->fr_literal, 0, &exp, 0 /* pcrel */, reloc);
+ ptr_count++;
+ break;
+ }
+ pattern_t = pattern_t->next;
+ }
+ break;
+
+ case BFD_RELOC_NDS32_PTR_COUNT:
+ /* In current design, it only be referanced once. */
+ if (ptr_count != 0)
+ {
+ exp.X_add_number = ptr_count;
+ fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0, reloc);
+ }
+ ptr_count = 0;
+ break;
+
+ case BFD_RELOC_NDS32_GOTOFF_SUFF:
+ case BFD_RELOC_NDS32_GOT_SUFF:
+ case BFD_RELOC_NDS32_PLT_GOT_SUFF:
+ /* It has to record symbol. */
+ if (insn_mask == 0 || pattern->insn == insn_mask)
+ {
+ exp.X_add_symbol = sym;
+ fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0, reloc);
+ }
+ break;
+
+ case BFD_RELOC_NDS32_PTR_RESOLVED:
+ default:
+ if (insn_mask == 0 || pattern->insn == insn_mask)
+ {
+ fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0, reloc);
+ }
+ }
+}
+
+static void
+nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
+{
+ /* Set E_NDS32_HAS_EXT_INST. */
+ if (insn->opcode->attr & NASM_ATTR_PERF_EXT)
+ {
+ if (nds32_perf_ext)
+ nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
+ else
+ as_bad (_("instruction %s requires enabling performance extension"),
+ insn->opcode->opcode);
+ }
+ else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT)
+ {
+ if (nds32_perf_ext2)
+ nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
+ else
+ as_bad (_("instruction %s requires enabling performance extension II"),
+ insn->opcode->opcode);
+ }
+ else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT)
+ {
+ if (nds32_audio_ext)
+ nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
+ else
+ as_bad (_("instruction %s requires enabling AUDIO extension"),
+ insn->opcode->opcode);
+ }
+ else if (insn->opcode->attr & NASM_ATTR_STR_EXT)
+ {
+ if (nds32_string_ext)
+ nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
+ else
+ as_bad (_("instruction %s requires enabling STRING extension"),
+ insn->opcode->opcode);
+ }
+ else if ((insn->opcode->attr & NASM_ATTR_DIV)
+ && (insn->opcode->attr & NASM_ATTR_DXREG))
+ {
+ if (nds32_div && nds32_dx_regs)
+ nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
+ else
+ as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"),
+ insn->opcode->opcode);
+ }
+ else if (insn->opcode->attr & NASM_ATTR_FPU)
+ {
+ if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
+ {
+ if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
+ nds32_fpu_com = 1;
+ }
+ else
+ as_bad (_("instruction %s requires enabling FPU extension"),
+ insn->opcode->opcode);
+ }
+ else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
+ {
+ if (nds32_fpu_sp_ext)
+ nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
+ else
+ as_bad (_("instruction %s requires enabling FPU_SP extension"),
+ insn->opcode->opcode);
+ }
+ else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
+ && (insn->opcode->attr & NASM_ATTR_MAC))
+ {
+ if (nds32_fpu_sp_ext && nds32_mac)
+ {
+ nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
+ nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
+ }
+ else
+ as_bad (_("instruction %s requires enabling FPU_MAC extension"),
+ insn->opcode->opcode);
+ }
+ else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
+ {
+ if (nds32_fpu_dp_ext)
+ nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
+ else
+ as_bad (_("instruction %s requires enabling FPU_DP extension"),
+ insn->opcode->opcode);
+ }
+ else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
+ && (insn->opcode->attr & NASM_ATTR_MAC))
+ {
+ if (nds32_fpu_dp_ext && nds32_mac)
+ {
+ nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
+ nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
+ }
+ else
+ as_bad (_("instruction %s requires enabling FPU_MAC extension"),
+ insn->opcode->opcode);
+ }
+ /* TODO: FPU_BOTH */
+ else if ((insn->opcode->attr & NASM_ATTR_MAC)
+ && (insn->opcode->attr & NASM_ATTR_DXREG))
+ {
+ if (nds32_mac && nds32_dx_regs)
+ nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
+ else
+ as_bad (_("instruction %s requires enabling DX_REGS extension"),
+ insn->opcode->opcode);
+ }
+ /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */
+ else if (insn->opcode->attr & NASM_ATTR_IFC_EXT)
+ {
+ nds32_elf_flags |= E_NDS32_HAS_IFC_INST;
+ }
+ /* TODO: E_NDS32_HAS_SATURATION_INST */
+}
+
+/* Append relax relocation for link time relaxing. */
+
+static void
+nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
+{
+ struct nds32_relocs_pattern *relocs_temp =
+ (struct nds32_relocs_pattern *) value;
+ unsigned int reloc, group_type, insn;
+ symbolS *sym;
+ unsigned int i = 0, x = 0, y;
+ segT seg_bak = now_seg;
+ frchainS *frchain_bak = frchain_now;
+
+ if (!relocs_temp)
+ return;
+
+ group_type = relocs_temp->reloc;
+ sym = relocs_temp->sym;
+ /* Inserting fix up must specify now_seg or frchain_now. */
+ now_seg = relocs_temp->seg;
+ frchain_now = relocs_temp->frchain;
+
+ /* Find pattern in relocation table. */
+ while (i < (sizeof (relocation_table)/sizeof (relocation_table[0]))
+ &&relocation_table[i].main_type != group_type)
+ i++;
+
+ /* Can not find relocation pattern. */
+ if (relocation_table[i].main_type == 0)
+ return;
+
+ while (relocs_temp)
+ {
+ y = 0;
+
+ while (relocation_table[i].reloc_insn[x][y][0] != 0)
+ {
+ reloc = relocation_table[i].reloc_insn[x][y][0];
+ insn = relocation_table[i].reloc_insn[x][y][1];
+ nds32_elf_insert_relocation (relocs_temp, reloc, insn, sym);
+ y++;
+ }
+
+ /* Next instruction. */
+ relocs_temp = relocs_temp->next;
+
+ /* There are load store instruction shared setting symbol part, so
+ re-using the final relocation. */
+ if (relocation_table[i].reloc_insn[x+1][0][0] != 0)
+ x++;
+ }
+
+ now_seg = seg_bak;
+ frchain_now = frchain_bak;
+}
+
+/* Check instruction if it can be used for the baseline. */
+
+static bfd_boolean
+nds32_check_insn_available (struct nds32_asm_insn insn, char *str)
+{
+ int attr = insn.attr & ATTR_ALL;
+ static int baseline_isa = 0;
+ /* No isa setting or all isa can use. */
+ if (attr == 0 || attr == ATTR_ALL)
+ return TRUE;
+
+ if (baseline_isa == 0)
+ {
+ /* Map option baseline and instruction attribute. */
+ switch (nds32_baseline)
+ {
+ case ISA_V2:
+ baseline_isa = ATTR (ISA_V2);
+ break;
+ case ISA_V3:
+ baseline_isa = ATTR (ISA_V3);
+ break;
+ case ISA_V3M:
+ baseline_isa = ATTR (ISA_V3M);
+ break;
+ }
+ }
+
+ if ((baseline_isa & attr) == 0)
+ {
+ as_bad (_("Not support instrcution %s in the baseline."), str);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Stub of machine dependent. */
+
+void
+md_assemble (char *str)
+{
+ struct nds32_asm_insn insn;
+ char *out;
+ struct nds32_pseudo_opcode *popcode;
+ const struct nds32_field *fld = NULL;
+ fixS *fixP ATTRIBUTE_UNUSED;
+ int insn_type;
+ uint16_t insn_16;
+ uint32_t insn_32;
+ struct nds32_relocs_pattern *relocs_temp;
+ expressionS *pexp;
+
+ popcode = nds32_lookup_pseudo_opcode (str);
+ /* Note that we need to check 'verbatim' and
+ 'opcode->physical_op'. If the assembly content is generated by
+ compiler and this opcode is a physical instruction, there is no
+ need to perform pseudo instruction expansion/transformation. */
+ if (popcode && !(verbatim && popcode->physical_op))
+ {
+ pseudo_opcode = TRUE;
+ nds32_pseudo_opcode_wrapper (str, popcode);
+ pseudo_opcode = FALSE;
+ nds32_elf_append_relax_relocs (NULL, relocs_list);
+
+ /* Free pseudo list. */
+ relocs_temp = relocs_list;
+ while (relocs_temp)
+ {
+ relocs_list = relocs_list->next;
+ free (relocs_temp);
+ relocs_temp = relocs_list;
+ }
+
+ return;
+ }
+
+ insn.info = (expressionS *) alloca (sizeof (expressionS));
+ nds32_assemble (&asm_desc, &insn, str);
+
+ switch (asm_desc.result)
+ {
+ case NASM_ERR_UNKNOWN_OP:
+ as_bad (_("Unrecognized opcode, %s."), str);
+ return;
+ case NASM_ERR_SYNTAX:
+ as_bad (_("Incorrect syntax, %s."), str);
+ return;
+ case NASM_ERR_OPERAND:
+ as_bad (_("Unrecognized operand, %s."), str);
+ return;
+ case NASM_ERR_OUT_OF_RANGE:
+ as_bad (_("Operand out of range, %s."), str);
+ return;
+ case NASM_ERR_REG_REDUCED:
+ as_bad (_("Prohibited register used for reduced-register, %s."), str);
+ return;
+ case NASM_ERR_JUNK_EOL:
+ as_bad (_("Junk at end of line, %s."), str);
+ return;
+ }
+
+ gas_assert (insn.opcode);
+
+ nds32_set_elf_flags_by_insn (&insn);
+
+ gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
+
+ if (!nds32_check_insn_available (insn, str))
+ return;
+
+ /* Create new frag if the instruction can be relaxed. */
+ fld = insn.field;
+ if (!verbatim && fld && (insn.attr & NASM_ATTR_BRANCH))
+ {
+ /* User assembly code branch relax for it. */
+ fragS *fragp = frag_now;
+
+ /* If fld is not NULL, it is a symbol. */
+ /* Get branch range type. */
+ enum nds32_br_range range_type;
+ range_type = get_range_type (fld);
+
+ pexp = insn.info;
+
+ out = frag_var (rs_machine_dependent,
+ NDS32_MAXCHAR,
+ 0, /* VAR is un-used. */
+ range_type, /* SUBTYPE is used as range type. */
+ pexp->X_add_symbol,
+ pexp->X_add_number,
+ 0);
+ /* If the original frag is full, the instruction must save in next
+ one. */
+ while (fragp->fr_next != frag_now)
+ fragp = fragp->fr_next;
+ fragp->fr_fix += insn.opcode->isize;
+ fragp->tc_frag_data.opcode = insn.opcode;
+ fragp->tc_frag_data.insn = insn.insn;
+ dwarf2_emit_insn (insn.opcode->isize);
+ if (insn.opcode->isize == 4)
+ bfd_putb32 (insn.insn, out);
+ else if (insn.opcode->isize == 2)
+ bfd_putb16 (insn.insn, out);
+ return;
+ /* md_convert_frag will insert relocations. */
+ }
+ else if (!verbatim && !fld && (optimize || optimize_for_space))
+ {
+ /* User assembly code without relocating convert it to 16bits if needed. */
+ insn_32 = insn.insn;
+
+ /* Convert instruction to 16-bits. */
+ if (insn.opcode->isize == 4
+ && nds32_convert_32_to_16 (stdoutput, insn_32,
+ &insn_16, &insn_type))
+ {
+ out = frag_more (2);
+ frag_var (rs_fill, 0, 0, 0, NULL, 0, NULL);
+ bfd_putb16 (insn_16, out);
+ dwarf2_emit_insn (2);
+ return;
+ }
+ }
+
+ out = frag_more (insn.opcode->isize);
+
+ if (insn.opcode->isize == 4)
+ bfd_putb32 (insn.insn, out);
+ else if (insn.opcode->isize == 2)
+ bfd_putb16 (insn.insn, out);
+
+ dwarf2_emit_insn (insn.opcode->isize);
+
+ if (fld)
+ {
+ /* Compiler generating code and user assembly pseudo load-store, insert
+ fixup here. */
+ pexp = insn.info;
+ nds32_elf_record_fixup_exp (str, fld, pexp, out, &insn);
+ }
+}
+
+/* md_macro_start */
+
+void
+nds32_macro_start (void)
+{
+}
+
+/* md_macro_info */
+
+void
+nds32_macro_info (void *info ATTRIBUTE_UNUSED)
+{
+}
+
+/* md_macro_end */
+
+void
+nds32_macro_end (void)
+{
+}
+
+/* GAS will call this function with one argument, an expressionS pointer, for
+ any expression that can not be recognized. When the function is called,
+ input_line_pointer will point to the start of the expression. */
+
+void
+md_operand (expressionS *expressionP)
+{
+ if (*input_line_pointer == '#')
+ {
+ input_line_pointer++;
+ expression (expressionP);
+ }
+}
+
+/* GAS will call this function for each section at the end of the assembly, to
+ permit the CPU back end to adjust the alignment of a section. The function
+ must take two arguments, a segT for the section and a valueT for the size of
+ the section, and return a valueT for the rounded size. */
+
+valueT
+md_section_align (segT segment, valueT size)
+{
+ int align = bfd_get_section_alignment (stdoutput, segment);
+
+ return ((size + (1 << align) - 1) & (-1 << align));
+}
+
+/* GAS will call this function when a symbol table lookup fails, before it
+ creates a new symbol. Typically this would be used to supply symbols whose
+ name or value changes dynamically, possibly in a context sensitive way.
+ Predefined symbols with fixed values, such as register names or condition
+ codes, are typically entered directly into the symbol table when md_begin
+ is called. One argument is passed, a char * for the symbol. */
+
+symbolS *
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
+
+static long
+nds32_calc_branch_offset (segT segment, fragS *fragP,
+ long stretch ATTRIBUTE_UNUSED,
+ relax_info_t *relax_info,
+ enum nds32_br_range branch_range_type)
+{
+ struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
+ symbolS *branch_symbol = fragP->fr_symbol;
+ offsetT branch_offset = fragP->fr_offset;
+ offsetT branch_target_address;
+ offsetT branch_insn_address;
+ long offset = 0;
+
+ if ((S_GET_SEGMENT (branch_symbol) != segment)
+ || S_IS_WEAK (branch_symbol))
+ {
+ /* The symbol is not in the SEGMENT. It could be far far away. */
+ offset = 0x80000000;
+ }
+ else
+ {
+ /* Calculate symbol-to-instruction offset. */
+ branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
+ /* If the destination symbol is beyond current frag address,
+ STRETCH will take effect to symbol's position. */
+ if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
+ branch_target_address += stretch;
+
+ branch_insn_address = fragP->fr_address + fragP->fr_fix;
+ branch_insn_address -= opcode->isize;
+
+ /* Update BRANCH_INSN_ADDRESS to relaxed position. */
+ branch_insn_address += (relax_info->relax_code_size[branch_range_type]
+ - relax_info->relax_branch_isize[branch_range_type]);
+
+ offset = branch_target_address - branch_insn_address;
+ }
+
+ return offset;
+}
+
+static enum nds32_br_range
+nds32_convert_to_range_type (long offset)
+{
+ enum nds32_br_range range_type;
+
+ if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
+ range_type = BR_RANGE_S256;
+ else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
+ range_type = BR_RANGE_S16K;
+ else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
+ range_type = BR_RANGE_S64K;
+ else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
+ range_type = BR_RANGE_S16M;
+ else /* 4G bytes */
+ range_type = BR_RANGE_U4G;
+
+ return range_type;
+}
+
+/* Set insntruction register mask. */
+
+static void
+nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
+ uint32_t ori_insn, int range)
+{
+ nds32_cond_field_t *cond_fields = relax_info->cond_field;
+ nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
+ uint32_t mask;
+ int i = 0;
+
+ /* The instruction has conditions. Collect condition values. */
+ while (offset == code_seq_cond[i].offset)
+ {
+ mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
+ *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
+ i++;
+ }
+}
+
+
+static int
+nds32_relax_branch_instructions (segT segment, fragS *fragP,
+ long stretch ATTRIBUTE_UNUSED,
+ int init)
+{
+ enum nds32_br_range branch_range_type;
+ struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
+ long offset = 0;
+ enum nds32_br_range real_range_type;
+ int adjust = 0;
+ relax_info_t *relax_info;
+ int diff = 0;
+ int i, j, k;
+ int code_seq_size;
+ uint32_t *code_seq;
+ uint32_t insn;
+ int insn_size;
+ uint16_t insn_16;
+ int insn_type;
+ int code_seq_offset;
+
+ /* Replace with gas_assert (fragP->fr_symbol != NULL); */
+ if (fragP->fr_symbol == NULL)
+ return adjust;
+
+ /* If frag_var is not enough room, the previos frag is fr_full and with
+ opcode. The new one is rs_dependent but without opcode. */
+ if (opcode == NULL)
+ return adjust;
+
+ relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
+
+ if (relax_info == NULL)
+ return adjust;
+
+ if (init)
+ branch_range_type = relax_info->br_range;
+ else
+ branch_range_type = fragP->fr_subtype;
+
+ offset = nds32_calc_branch_offset (segment, fragP, stretch,
+ relax_info, branch_range_type);
+
+ real_range_type = nds32_convert_to_range_type (offset);
+
+ /* If actual range is equal to instruction jump range, do nothing. */
+ if (real_range_type == branch_range_type)
+ return adjust;
+
+ /* Find out proper relaxation code sequence. */
+ for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++)
+ {
+ if (real_range_type <= (unsigned int) i)
+ {
+ if (init)
+ diff = relax_info->relax_code_size[i] - opcode->isize;
+ else
+ diff = relax_info->relax_code_size[i]
+ - relax_info->relax_code_size[branch_range_type];
+
+ /* If the instruction could be converted to 16-bits,
+ minus the difference. */
+ code_seq_offset = 0;
+ j = 0;
+ k = 0;
+ code_seq_size = relax_info->relax_code_size[i];
+ code_seq = relax_info->relax_code_seq[i];
+ while (code_seq_offset < code_seq_size)
+ {
+ insn = code_seq[j];
+ if (insn & 0x80000000) /* 16-bits instruction. */
+ {
+ insn_size = 2;
+ }
+ else /* 32-bits instruction. */
+ {
+ insn_size = 4;
+
+ while (relax_info->relax_fixup[i][k].size !=0
+ && relax_info->relax_fixup[i][k].offset < code_seq_offset)
+ k++;
+ if (relax_info->relax_fixup[i][k].size !=0
+ && relax_info->relax_fixup[i][k].ramp & NDS32_ORIGIN)
+ {
+ /* Set register num to insntruction. */
+ nds32_elf_get_set_cond (relax_info, code_seq_offset, &insn,
+ fragP->tc_frag_data.insn, i);
+
+ /* Try to convert to 16-bits instruction. */
+ if (nds32_convert_32_to_16 (stdoutput,
+ insn, &insn_16, &insn_type))
+ diff -= 2;
+ }
+ }
+
+ code_seq_offset += insn_size;
+ j++;
+ }
+
+ /* Update fr_subtype to new NDS32_BR_RANGE. */
+ fragP->fr_subtype = i;
+ break;
+ }
+ }
+
+ return diff + adjust;
+}
+
+/* md_relax_frag */
+
+int
+nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
+{
+ /* Currently, there are two kinds of relaxation in nds32 assembler.
+ 1. relax for branch
+ 2. relax for 32-bits to 16-bits */
+
+ int adjust;
+
+ adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
+
+ return adjust;
+}
+
+/* This function returns an initial guess of the length by which a fragment
+ must grow to hold a branch to reach its destination. Also updates
+ fr_type/fr_subtype as necessary.
+
+ It is called just before doing relaxation. Any symbol that is now undefined
+ will not become defined. The guess for fr_var is ACTUALLY the growth beyond
+ fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
+ value. Although it may not be explicit in the frag, pretend fr_var starts
+ with a 0 value. */
+
+int
+md_estimate_size_before_relax (fragS *fragP, segT segment)
+{
+ /* Currently, there are two kinds of relaxation in nds32 assembler.
+ 1. relax for branch
+ 2. relax for 32-bits to 16-bits */
+
+ int adjust;
+
+ adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
+
+ return adjust;
+}
+
+/* GAS will call this for each rs_machine_dependent fragment. The instruction
+ is completed using the data from the relaxation pass. It may also create any
+ necessary relocations.
+
+ *FRAGP has been relaxed to its final size, and now needs to have the bytes
+ inside it modified to conform to the new size. It is called after relaxation
+ is finished.
+
+ fragP->fr_type == rs_machine_dependent.
+ fragP->fr_subtype is the subtype of what the address relaxed to. */
+
+void
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
+{
+ /* Convert branch relaxation instructions. */
+ symbolS *branch_symbol = fragP->fr_symbol;
+ offsetT branch_offset = fragP->fr_offset;
+ enum nds32_br_range branch_range_type = fragP->fr_subtype;
+ struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
+ uint32_t origin_insn = fragP->tc_frag_data.insn;
+ int backup_endian;
+ relax_info_t *relax_info;
+ char *fr_buffer;
+ int fr_where;
+ int addend ATTRIBUTE_UNUSED;
+ offsetT branch_target_address;
+ offsetT branch_insn_address;
+ expressionS exp;
+ fixS *fixP;
+ uint32_t *code_seq;
+ int code_size;
+ uint32_t insn;
+ int insn_size;
+ int offset;
+ int i, j, k;
+ uint16_t insn_16;
+ int insn_type;
+ int buf_offset;
+ nds32_relax_fixup_info_t fixup_info[MAX_RELAX_NUM];
+ /* Save the 1st instruction is converted to 16 bit or not. */
+ bfd_boolean insn_convert = FALSE;
+ int fixup_size;
+
+ /* Replace with gas_assert (branch_symbol != NULL); */
+ if (branch_symbol == NULL)
+ return;
+
+ /* If frag_var is not enough room, the previos frag is fr_full and with
+ opcode. The new one is rs_dependent but without opcode. */
+ if (opcode == NULL)
+ return;
+
+ relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
+
+ if (relax_info == NULL)
+ return;
+
+ backup_endian = target_big_endian;
+ target_big_endian = 1;
+
+ fr_where = fragP->fr_fix - opcode->isize;
+ fr_buffer = fragP->fr_literal + fr_where;
+
+ if ((S_GET_SEGMENT (branch_symbol) != sec)
+ || S_IS_WEAK (branch_symbol))
+ {
+ if (fragP->fr_offset & 3)
+ as_warn (_("Addend to unresolved symbol is not on word boundary."));
+ addend = 0;
+ }
+ else
+ {
+ /* Calculate symbol-to-instruction offset. */
+ branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
+ branch_insn_address = fragP->fr_address + fr_where;
+ addend = (branch_target_address - branch_insn_address) >> 1;
+ }
+
+ code_size = relax_info->relax_code_size[branch_range_type];
+ code_seq = relax_info->relax_code_seq[branch_range_type];
+
+ memcpy (fixup_info,
+ relax_info->relax_fixup[branch_range_type],
+ sizeof (fixup_info));
+
+ /* Fill in frag. */
+ i = 0;
+ k = 0;
+ offset = 0; /* code_seq offset */
+ buf_offset = 0; /* fr_buffer offset */
+ while (offset < code_size)
+ {
+ insn = code_seq[i];
+ if (insn & 0x80000000) /* 16-bits instruction. */
+ {
+ insn = (insn >> 16) & 0xFFFF;
+ insn_size = 2;
+ }
+ else /* 32-bits instruction. */
+ {
+ insn_size = 4;
+ }
+
+ nds32_elf_get_set_cond (relax_info, offset, &insn,
+ origin_insn, branch_range_type);
+
+ /* Try to convert to 16-bits instruction. Currently, only the first
+ insntruction in pattern can be converted. EX: bnez sethi ori jr,
+ only bnez can be converted to 16 bit and ori can't. */
+
+ while (fixup_info[k].size != 0
+ && relax_info->relax_fixup[branch_range_type][k].offset < offset)
+ k++;
+ if ((fixup_info[k].size != 0
+ && fixup_info[k].ramp & NDS32_ORIGIN)
+ && nds32_convert_32_to_16 (stdoutput, insn, &insn_16, &insn_type))
+ {
+ /* Reduce to 16-bits instructions, adjust fixup_info[j]->offset. */
+ for (j = 0; fixup_info[j].size != 0; j++)
+ {
+ if (fixup_info[j].ramp & NDS32_RELAX)
+ fixup_info[j].size -= 2;
+
+ if (fixup_info[j].offset > buf_offset)
+ fixup_info[j].offset -= 2;
+ }
+
+ md_number_to_chars (fr_buffer + buf_offset, insn_16, 2);
+ buf_offset += 2;
+ if (offset == 0)
+ insn_convert = TRUE;
+ }
+ else
+ {
+ md_number_to_chars (fr_buffer + buf_offset, insn, insn_size);
+ buf_offset += insn_size;
+ }
+
+ offset += insn_size;
+ i++;
+ }
+
+ /* Set up fixup. */
+ exp.X_op = O_symbol;
+
+ for (i = 0; fixup_info[i].size != 0; i++)
+ {
+ fixup_size = fixup_info[i].size;
+
+ if (((fixup_info[i].ramp & NDS32_ORIGIN) && insn_convert == TRUE)
+ ||((fixup_info[i].ramp & NDS32_CONVERT) && insn_convert == FALSE))
+ continue;
+
+ if ((fixup_info[i].ramp & NDS32_CREATE_LABLE) != 0)
+ {
+ /* This is a reverse branch. */
+ exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next);
+ exp.X_add_number = 0;
+ }
+ else if ((fixup_info[i].ramp & NDS32_RELAX) != 0)
+ {
+ /* This is a relax relocation. */
+ exp.X_add_symbol = abs_section_sym;
+ exp.X_add_number =
+ SET_ADDEND (fixup_size /* size */ ,
+ insn_convert , optimize, enable_16bit);
+ }
+ else
+ {
+ exp.X_add_symbol = branch_symbol;
+ exp.X_add_number = branch_offset;
+ }
+
+ if (fixup_info[i].r_type != 0)
+ {
+ fixP = fix_new_exp (fragP,
+ fr_where + fixup_info[i].offset,
+ fixup_size,
+ &exp,
+ 0,
+ fixup_info[i].r_type);
+ fixP->fx_addnumber = fixP->fx_offset;
+ }
+ }
+
+ fragP->fr_fix = fr_where + buf_offset;
+
+ target_big_endian = backup_endian;
+}
+
+/* tc_frob_file_before_fix */
+
+void
+nds32_frob_file_before_fix (void)
+{
+}
+
+/* TC_FORCE_RELOCATION */
+
+int
+nds32_force_relocation (fixS *fix ATTRIBUTE_UNUSED)
+{
+ /* Always force relocation, because linker may adjust the code. */
+ return 1;
+}
+
+
+/* TC_VALIDATE_FIX_SUB */
+
+int
+nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
+{
+ segT sub_symbol_segment;
+
+ /* This code is referred from Xtensa. Check their implementation for
+ details. */
+
+ /* Make sure both symbols are in the same segment, and that segment is
+ "normal" and relaxable. */
+ sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
+ return (sub_symbol_segment == add_symbol_segment
+ && add_symbol_segment != undefined_section);
+}
+
+void
+md_number_to_chars (char *buf, valueT val, int n)
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+/* Equal to MAX_PRECISION in atof-ieee.c. */
+#define MAX_LITTLENUMS 6
+
+/* This function is called to convert an ASCII string into a floating point
+ value in format used by the CPU. */
+
+char *
+md_atof (int type, char *litP, int *sizeP)
+{
+ int i;
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ char *t;
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+ default:
+ *sizeP = 0;
+ return _("Bad call to md_atof()");
+ }
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ if (target_big_endian)
+ {
+ for (i = 0; i < prec; i++)
+ {
+ md_number_to_chars (litP, (valueT) words[i],
+ sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+ else
+ {
+ for (i = prec - 1; i >= 0; i--)
+ {
+ md_number_to_chars (litP, (valueT) words[i],
+ sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+
+ return 0;
+}
+
+/* md_elf_section_change_hook */
+
+void
+nds32_elf_section_change_hook (void)
+{
+}
+
+/* md_cleanup */
+
+void
+nds32_cleanup (void)
+{
+}
+
+/* This function is used to scan leb128 subtraction expressions,
+ and insert fixups for them.
+
+ e.g., .leb128 .L1 - .L0
+
+ These expressions are heavily used in debug information or
+ exception tables. Because relaxation will change code size,
+ we must resolve them in link time. */
+
+static void
+nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec, void *xxx ATTRIBUTE_UNUSED)
+{
+ segment_info_type *seginfo = seg_info (sec);
+ struct frag *fragP;
+
+ subseg_set (sec, 0);
+
+ for (fragP = seginfo->frchainP->frch_root;
+ fragP; fragP = fragP->fr_next)
+ {
+ expressionS *exp;
+
+ /* Only unsigned leb128 can be handle. */
+ if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
+ || fragP->fr_symbol == NULL)
+ continue;
+
+ exp = symbol_get_value_expression (fragP->fr_symbol);
+
+ if (exp->X_op != O_subtract)
+ continue;
+
+ fix_new_exp (fragP, fragP->fr_fix, 0,
+ exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
+ }
+}
+
+static void
+nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
+ void *xxx ATTRIBUTE_UNUSED)
+{
+ segment_info_type *seginfo;
+ fragS *fragP;
+ fixS *fixP;
+ expressionS exp;
+ fixS *fixp;
+
+ seginfo = seg_info (sec);
+ if (!seginfo || !symbol_rootP || !subseg_text_p (sec))
+ return;
+ /* If there is no relocation and relax is disabled, it is not necessary to
+ insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */
+ for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
+ if (!fixp->fx_done)
+ break;
+ if (!fixp && !enable_relax_ex9 && !verbatim)
+ return;
+
+ subseg_change (sec, 0);
+
+ /* Set RELAX_ENTRY flags for linker. */
+ fragP = seginfo->frchainP->frch_root;
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = section_symbol (sec);
+ exp.X_add_number = 0;
+ if (!enable_relax_relocs)
+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
+ else
+ {
+ /* These flags are only enabled when global relax is enabled.
+ Maybe we can check DISABLE_RELAX_FLAG at linke-time,
+ so we set them anyway. */
+ if (enable_relax_ex9)
+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG;
+ if (enable_relax_ifc)
+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG;
+ if (verbatim)
+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
+ }
+ if (optimize)
+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
+ if (optimize_for_space)
+ exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
+
+ fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
+ fixP->fx_no_overflow = 1;
+}
+
+/* Analysis relax hint and insert suitable relocation pattern. */
+
+static void
+nds32_elf_analysis_relax_hint (void)
+{
+ hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
+}
+
+void
+md_end (void)
+{
+ nds32_elf_analysis_relax_hint ();
+ bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
+}
+
+/* Implement md_allow_local_subtract. */
+
+bfd_boolean
+nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
+ expressionS *expr_r ATTRIBUTE_UNUSED,
+ segT sec ATTRIBUTE_UNUSED)
+{
+ /* Don't allow any subtraction, because relax may change the code. */
+ return FALSE;
+}
+
+/* Sort relocation by address.
+
+ We didn't use qsort () in stdlib, because quick-sort is not a stable
+ sorting algorithm. Relocations at the same address (r_offset) must keep
+ their relative order. For example, RELAX_ENTRY must be the very first
+ relocation entry.
+
+ Currently, this function implements insertion-sort. */
+
+static int
+compar_relent (const void *lhs, const void *rhs)
+{
+ const arelent **l = (const arelent **) lhs;
+ const arelent **r = (const arelent **) rhs;
+
+ if ((*l)->address > (*r)->address)
+ return 1;
+ else if ((*l)->address == (*r)->address)
+ return 0;
+ else
+ return -1;
+}
+
+/* SET_SECTION_RELOCS ()
+
+ Although this macro is originally used to set a relocation for each section,
+ we use it to sort relocations in the same section by the address of the
+ relocation. */
+
+void
+nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED,
+ unsigned int n ATTRIBUTE_UNUSED)
+{
+ bfd *abfd ATTRIBUTE_UNUSED = sec->owner;
+ if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC)
+ nds32_insertion_sort (sec->orelocation, sec->reloc_count, sizeof (arelent**),
+ compar_relent);
+}
+
+long
+nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
+{
+ if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
+ || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
+ {
+ /* Let linker resolve undefined symbols. */
+ return 0;
+ }
+
+ return fixP->fx_frag->fr_address + fixP->fx_where;
+}
+
+/* md_post_relax_hook ()
+ Insert relax entry relocation into sections. */
+
+void
+nds32_post_relax_hook (void)
+{
+ bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
+}
+
+
+
+/* tc_fix_adjustable ()
+
+ Return whether this symbol (fixup) can be replaced with
+ section symbols. */
+
+bfd_boolean
+nds32_fix_adjustable (fixS *fixP)
+{
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_NDS32_WORD_9_PCREL:
+ case BFD_RELOC_NDS32_9_PCREL:
+ case BFD_RELOC_NDS32_15_PCREL:
+ case BFD_RELOC_NDS32_17_PCREL:
+ case BFD_RELOC_NDS32_25_PCREL:
+ case BFD_RELOC_NDS32_HI20:
+ case BFD_RELOC_NDS32_LO12S0:
+ case BFD_RELOC_8:
+ case BFD_RELOC_16:
+ case BFD_RELOC_32:
+ case BFD_RELOC_NDS32_PTR:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* elf_tc_final_processing */
+
+void
+elf_nds32_final_processing (void)
+{
+ /* An FPU_COM instruction is found without previous non-FPU_COM instruction. */
+ if (nds32_fpu_com
+ && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
+ {
+ /* Since only FPU_COM instructions are used and no other FPU instructions
+ are used. The nds32_elf_flags will be decided by the enabled options by
+ command line or default configuration. */
+ if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
+ {
+ nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
+ nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
+ }
+ else
+ {
+ /* Should never here. */
+ as_bad (_("Used FPU instructions requires enabling FPU extension"));
+ }
+ }
+
+ if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
+ {
+ /* Single/double FPU has been used, set FPU register config. */
+ /* We did not check the actual number of register used. We may
+ want to do it while assemble. */
+ nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
+ nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
+ }
+
+ if (nds32_pic)
+ nds32_elf_flags |= E_NDS32_HAS_PIC;
+
+ if (nds32_gpr16)
+ nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
+
+ nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
+ elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
+}
+
+/* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for
+ later relocation generation. */
+
+void
+nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
+{
+ char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
+ bfd_vma value = *valP;
+
+ if (fixP->fx_r_type < BFD_RELOC_UNUSED
+ && fixP->fx_r_type > BFD_RELOC_NONE
+ && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
+ {
+ /* FIXME: This implementation is partially borrowed from our old
+ nds32 binutils. Its purpose is to leave original bfd
+ relocation untouched, while other relocation created by CGEN
+ will be converted into general bfd relocations.
+ However, since we no longer use CGEN, we can simply use
+ a little piece of code to deal with general bfd relocation,
+ especially for the BFD_RELOC_NDS32_DATA, which is just used
+ as a marker for different purpose.
+ It is believed that we can construct a better mechanism to
+ deal with the whole relocation issue in nds32 target
+ without using CGEN. */
+ fixP->fx_addnumber = value;
+ fixP->tc_fix_data = NULL;
+ if (fixP->fx_r_type == BFD_RELOC_NDS32_DATA)
+ fixP->fx_done = 1;
+ return;
+ }
+
+ if (fixP->fx_addsy == (symbolS *) NULL)
+ fixP->fx_done = 1;
+
+ if (fixP->fx_subsy != (symbolS *) NULL)
+ {
+ /* HOW DIFF RELOCATION WORKS.
+
+ First of all, this relocation is used to calculate the distance
+ between two symbols in the SAME section. It is used for jump-
+ table, debug information, exception table, et al. Therefore,
+ it is a unsigned positive value. It is NOT used for general-
+ purpose arithmetic.
+
+ Consider this example, the distance between .LEND and .LBEGIN
+ is stored at the address of foo.
+
+ ---- >8 ---- >8 ---- >8 ---- >8 ----
+ .data
+ foo:
+ .word .LBEGIN - .LEND
+
+ .text
+ [before]
+ .LBEGIN
+ \
+ [between] distance
+ /
+ .LEND
+ [after]
+ ---- 8< ---- 8< ---- 8< ---- 8< ----
+
+ We use a single relocation entry for this expression.
+ * The initial distance value is stored direcly in that location
+ specified by r_offset (i.e., foo in this example.)
+ * The begin of the region, i.e., .LBEGIN, is specified by
+ r_info/R_SYM and r_addend, e.g., .text + 0x32.
+ * The end of region, i.e., .LEND, is represented by
+ .LBEGIN + distance instead of .LEND, so we only need
+ a single relocation entry instead of two.
+
+ When an instruction is relaxed, we adjust the relocation entry
+ depending on where the instruction locates. There are three
+ cases, before, after and between the region.
+ * between: Distance value is read from r_offset, adjusted and
+ written back into r_offset.
+ * before: Only r_addend is adjust.
+ * after: We don't care about it.
+
+ Hereby, there are some limitation.
+
+ `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
+ are semantically different, and we cannot handle latter case
+ when relaxation.
+
+ The latter expression means subtracting 1 from the distance
+ between .LEND and .LBEGIN. And the former expression means
+ the distance between (.LEND - 1) and .LBEGIN.
+
+ The nuance affects whether to adjust distance value when relax
+ an instruction. In another words, whether the instruction
+ locates in the region. Because we use a single relocation entry,
+ there is no field left for .LEND and the subtrahend.
+
+ Since GCC-4.5, GCC may produce debug information in such expression
+ .long .L1-1-.L0
+ in order to describe register clobbering during an function-call.
+ .L0:
+ call foo
+ .L1:
+
+ Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
+ for details. */
+
+ value -= S_GET_VALUE (fixP->fx_subsy);
+ *valP = value;
+ fixP->fx_subsy = NULL;
+ fixP->fx_offset -= value;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
+ md_number_to_chars (where, value, 1);
+ break;
+ case BFD_RELOC_16:
+ fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
+ md_number_to_chars (where, value, 2);
+ break;
+ case BFD_RELOC_32:
+ fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
+ md_number_to_chars (where, value, 4);
+ break;
+ case BFD_RELOC_NDS32_DIFF_ULEB128:
+ /* cvt_frag_to_fill () has called output_leb128 () for us. */
+ break;
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+ return;
+ }
+ }
+ else if (fixP->fx_done)
+ {
+ /* We're finished with this fixup. Install it because
+ bfd_install_relocation won't be called to do it. */
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_8:
+ md_number_to_chars (where, value, 1);
+ break;
+ case BFD_RELOC_16:
+ md_number_to_chars (where, value, 2);
+ break;
+ case BFD_RELOC_32:
+ md_number_to_chars (where, value, 4);
+ break;
+ case BFD_RELOC_64:
+ md_number_to_chars (where, value, 8);
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Internal error: Unknown fixup type %d (`%s')"),
+ fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
+ break;
+ }
+ }
+}
+
+/* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
+
+arelent *
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
+{
+ arelent *reloc;
+ bfd_reloc_code_real_type code;
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+
+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
+ reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
+
+ code = fixP->fx_r_type;
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("internal error: can't export reloc type %d (`%s')"),
+ fixP->fx_r_type, bfd_get_reloc_code_name (code));
+ return NULL;
+ }
+
+ /* Add relocation handling here. */
+
+ switch (fixP->fx_r_type)
+ {
+ default:
+ /* In general, addend of a relocation is the offset to the
+ associated symbol. */
+ reloc->addend = fixP->fx_offset;
+ break;
+
+ case BFD_RELOC_NDS32_DATA:
+ /* Prevent linker from optimizing data in text sections.
+ For example, jump table. */
+ reloc->addend = fixP->fx_size;
+ break;
+ }
+
+ return reloc;
+}
+
+/* Implement md_parse_name. */
+
+int
+nds32_parse_name (char const *name, expressionS *exprP,
+ enum expr_mode mode ATTRIBUTE_UNUSED,
+ char *nextcharP ATTRIBUTE_UNUSED)
+{
+ char *suffix_table[] = { "GOTOFF", "GOT", "PLT" };
+ short unsigned int reloc_table [] =
+ {
+ BFD_RELOC_NDS32_GOTOFF, BFD_RELOC_NDS32_GOT20,
+ BFD_RELOC_NDS32_25_PLTREL
+ };
+ segT segment;
+
+ exprP->X_op_symbol = NULL;
+ exprP->X_md = BFD_RELOC_UNUSED;
+
+ exprP->X_add_symbol = symbol_find_or_make (name);
+
+ segment = S_GET_SEGMENT (exprP->X_add_symbol);
+ if (segment != undefined_section)
+ return 0;
+
+ if (*nextcharP == '@')
+ {
+ size_t i;
+ char *next;
+ for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
+ {
+ next = input_line_pointer + 1 + strlen (suffix_table[i]);
+ if (strncasecmp (input_line_pointer + 1, suffix_table[i],
+ strlen (suffix_table[i])) == 0
+ && !is_part_of_name (*next))
+ {
+ exprP->X_md = reloc_table[i];
+ *input_line_pointer = *nextcharP;
+ input_line_pointer = next;
+ *nextcharP = *input_line_pointer;
+ *input_line_pointer = '\0';
+ break;
+ }
+ }
+ }
+
+ exprP->X_op = O_symbol;
+ exprP->X_add_number = 0;
+
+ return 1;
+}
+
+/* Implement tc_regname_to_dw2regnum. */
+
+int
+tc_nds32_regname_to_dw2regnum (char *regname)
+{
+ symbolS *sym = symbol_find (regname);
+
+ if (S_GET_SEGMENT (sym) == reg_section
+ && sym->sy_value.X_add_number < 32)
+ return sym->sy_value.X_add_number;
+ return -1;
+}
+
+void
+tc_nds32_frame_initial_instructions (void)
+{
+ /* CIE */
+ /* Default cfa is register-28/sp. */
+ cfi_add_CFA_def_cfa (31, 0);
+}
diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h
new file mode 100644
index 0000000..255fbae
--- /dev/null
+++ b/gas/config/tc-nds32.h
@@ -0,0 +1,264 @@
+/* tc-nds32.h -- Header file for tc-nds32.c.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GAS.
+
+ 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. */
+
+#ifndef TC_NDS32
+#define TC_NDS32
+
+#include "bfd_stdint.h"
+
+#define LISTING_HEADER \
+ (target_big_endian ? "NDS32 GAS" : "NDS32 GAS Little Endian")
+
+/* The target BFD architecture. */
+#define TARGET_ARCH bfd_arch_nds32
+
+/* mapping to mach_table[5] */
+#define ISA_V1 bfd_mach_n1h
+#define ISA_V2 bfd_mach_n1h_v2
+#define ISA_V3 bfd_mach_n1h_v3
+#define ISA_V3M bfd_mach_n1h_v3m
+
+/* Default to big endian. Please note that for Andes architecture,
+ instructions are always in big-endian format. */
+#ifndef TARGET_BYTES_BIG_ENDIAN
+#define TARGET_BYTES_BIG_ENDIAN 1
+#endif
+
+/* This is used to construct expressions out of @GOTOFF, @PLT and @GOT
+ symbols. The relocation type is stored in X_md. */
+#define O_PIC_reloc O_md1
+
+/* as.c. */
+/* Extend GAS command line option handling capability. */
+extern int nds32_parse_option (int, char *);
+extern void nds32_after_parse_args (void);
+/* The endianness of the target format may change based on command
+ line arguments. */
+extern const char * nds32_target_format (void);
+
+#define md_parse_option(optc, optarg) nds32_parse_option (optc, optarg)
+#define md_after_parse_args() nds32_after_parse_args ()
+#define TARGET_FORMAT nds32_target_format()
+
+/* expr.c */
+extern int nds32_parse_name (char const *, expressionS *, enum expr_mode, char *);
+extern bfd_boolean nds32_allow_local_subtract (expressionS *, expressionS *, segT);
+#define md_parse_name(name, exprP, mode, nextcharP) \
+ nds32_parse_name (name, exprP, mode, nextcharP)
+#define md_allow_local_subtract(lhs,rhs,sect) nds32_allow_local_subtract (lhs, rhs, sect)
+
+/* dwarf2dbg.c. */
+#define DWARF2_USE_FIXED_ADVANCE_PC 1
+
+/* write.c. */
+extern long nds32_pcrel_from_section (struct fix *, segT);
+extern bfd_boolean nds32_fix_adjustable (struct fix *);
+extern void nds32_frob_file (void);
+extern void nds32_post_relax_hook (void);
+extern void nds32_frob_file_before_fix (void);
+extern void elf_nds32_final_processing (void);
+extern int nds32_validate_fix_sub (struct fix *, segT);
+extern int nds32_force_relocation (struct fix *);
+extern void nds32_set_section_relocs (asection *, arelent ** , unsigned int);
+
+/* Fill in rs_align_code fragments. TODO: Review this. */
+extern void nds32_handle_align (fragS *);
+extern int nds32_relax_frag (segT, fragS *, long);
+extern int tc_nds32_regname_to_dw2regnum (char *);
+extern void tc_nds32_frame_initial_instructions (void);
+
+#define MD_PCREL_FROM_SECTION(fix, sect) nds32_pcrel_from_section (fix, sect)
+#define TC_FINALIZE_SYMS_BEFORE_SIZE_SEG 0
+#define tc_fix_adjustable(FIX) nds32_fix_adjustable (FIX)
+#define md_apply_fix(fixP, addn, seg) nds32_apply_fix (fixP, addn, seg)
+#define md_post_relax_hook nds32_post_relax_hook ()
+#define tc_frob_file_before_fix() nds32_frob_file_before_fix ()
+#define elf_tc_final_processing() elf_nds32_final_processing ()
+/* For DIFF relocations. The default behavior is inconsistent with the
+ asm internal document. */
+#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEC) \
+ (! SEG_NORMAL (SEC) || TC_FORCE_RELOCATION (FIX))
+#define TC_FORCE_RELOCATION(fix) nds32_force_relocation (fix)
+#define TC_VALIDATE_FIX_SUB(FIX,SEG) nds32_validate_fix_sub (FIX,SEG)
+#define SET_SECTION_RELOCS(sec, relocs, n) nds32_set_section_relocs (sec, relocs, n)
+/* Values passed to md_apply_fix don't include the symbol value. */
+#define MD_APPLY_SYM_VALUE(FIX) 0
+#define HANDLE_ALIGN(f) nds32_handle_align (f)
+#undef DIFF_EXPR_OK /* They should be fixed in linker. */
+#define md_relax_frag(segment, fragP, stretch) nds32_relax_frag (segment, fragP, stretch)
+#define WORKING_DOT_WORD /* We don't need to handle .word strangely. */
+/* Using to chain fixup with previous fixup. */
+#define TC_FIX_TYPE struct fix *
+#define TC_INIT_FIX_DATA(fixP) \
+ do \
+ { \
+ fixP->tc_fix_data = NULL; \
+ } \
+ while (0)
+
+/* read.c. */
+/* Extend GAS macro handling capability. */
+extern void nds32_macro_start (void);
+extern void nds32_macro_end (void);
+extern void nds32_macro_info (void *);
+extern void nds32_start_line_hook (void);
+extern void nds32_elf_section_change_hook (void);
+extern void md_begin (void);
+extern void md_end (void);
+extern int nds32_start_label (int, int);
+extern void nds32_cleanup (void);
+extern void nds32_flush_pending_output (void);
+extern void nds32_cons_align (int);
+extern void nds32_check_label (symbolS *);
+extern void nds32_frob_label (symbolS *);
+extern void nds32_pre_do_align (int, char *, int, int);
+extern void nds32_do_align (int);
+
+#define md_macro_start() nds32_macro_start ()
+#define md_macro_end() nds32_macro_end ()
+#define md_macro_info(args) nds32_macro_info (args)
+#define TC_START_LABEL(C, S, STR) (C == ':' && nds32_start_label (0, 0))
+#define tc_check_label(label) nds32_check_label (label)
+#define tc_frob_label(label) nds32_frob_label (label)
+#define md_end md_end
+#define md_start_line_hook() nds32_start_line_hook ()
+#define md_cons_align(n) nds32_cons_align (n)
+/* COLE: TODO: Review md_do_align. */
+#define md_do_align(N, FILL, LEN, MAX, LABEL) \
+ nds32_pre_do_align (N, FILL, LEN, MAX); \
+ if ((N) > 1 && (subseg_text_p (now_seg) \
+ || strncmp (now_seg->name, ".gcc_except_table", sizeof(".gcc_except_table") - 1) == 0)) \
+ nds32_do_align (N); \
+ goto LABEL;
+#define md_elf_section_change_hook() nds32_elf_section_change_hook ()
+#define md_flush_pending_output() nds32_flush_pending_output ()
+#define md_cleanup() nds32_cleanup ()
+#define LOCAL_LABELS_FB 1 /* Permit temporary numeric labels. */
+
+/* frags.c. */
+struct nds32_frag_type
+{
+ relax_substateT flag;
+ struct nds32_opcode *opcode;
+ uint32_t insn;
+ /* To Save previos label fixup if existence. */
+ struct fix *fixup;
+};
+
+extern void nds32_frag_init (fragS *);
+
+#define TC_FRAG_TYPE struct nds32_frag_type
+#define TC_FRAG_INIT(fragP) nds32_frag_init (fragP)
+
+/* CFI directive. */
+extern void nds32_elf_frame_initial_instructions (void);
+extern int tc_nds32_regname_to_dw2regnum (char *);
+
+#define TARGET_USE_CFIPOP 1
+#define DWARF2_DEFAULT_RETURN_COLUMN 30
+#define DWARF2_CIE_DATA_ALIGNMENT -4
+#define DWARF2_LINE_MIN_INSN_LENGTH 2
+
+#define tc_regname_to_dw2regnum tc_nds32_regname_to_dw2regnum
+#define tc_cfi_frame_initial_instructions tc_nds32_frame_initial_instructions
+
+/* COLE: TODO: Review These. They seem to be obsoleted. */
+#if 1
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy)))
+#define TC_HANDLES_FX_DONE
+/* This arranges for gas/write.c to not apply a relocation if
+ obj_fix_adjustable() says it is not adjustable. */
+#define TC_FIX_ADJUSTABLE(fixP) obj_fix_adjustable (fixP)
+#endif
+
+/* Because linker may relax the code, assemble-time expression
+ optimization is not allowed. */
+#define md_allow_eh_opt 0
+
+/* For nds32 relax. */
+enum nds32_br_range
+{
+ BR_RANGE_S256 = 0,
+ BR_RANGE_S16K,
+ BR_RANGE_S64K,
+ BR_RANGE_S16M,
+ BR_RANGE_U4G,
+ BR_RANGE_NUM
+};
+
+enum nds32_ramp
+{
+ NDS32_CREATE_LABLE = 1,
+ NDS32_RELAX = 2,
+ NDS32_ORIGIN = 4,
+ NDS32_CONVERT = 8
+};
+
+typedef struct nds32_relax_fixup_info
+{
+ int offset;
+ int size;
+ /* Reverse branch has to jump to the end of instruction pattern. */
+ int ramp;
+ enum bfd_reloc_code_real r_type;
+} nds32_relax_fixup_info_t;
+
+typedef struct nds32_cond_field
+{
+ int offset;
+ int bitpos; /* Register position. */
+ int bitmask; /* Number of register bits. */
+} nds32_cond_field_t;
+
+/* The max relaxation pattern is 20-bytes including the nop. */
+#define NDS32_MAXCHAR 20
+/* In current, the max entend number of instruction for one pseudo instruction
+ is 4, but its number of relocation may be 5. */
+#define MAX_RELAX_NUM 8
+
+typedef struct nds32_relax_info
+{
+ /* Opcode for the instruction. */
+ const char *opcode;
+ enum nds32_br_range br_range;
+ nds32_cond_field_t cond_field[MAX_RELAX_NUM]; /* TODO: Reuse nds32_field? */
+ /* Code sequences for different branch range. */
+ uint32_t relax_code_seq[BR_RANGE_NUM][MAX_RELAX_NUM];
+ nds32_cond_field_t relax_code_condition[BR_RANGE_NUM][MAX_RELAX_NUM];
+ int relax_code_size[BR_RANGE_NUM];
+ int relax_branch_isize[BR_RANGE_NUM];
+ nds32_relax_fixup_info_t relax_fixup[BR_RANGE_NUM][MAX_RELAX_NUM];
+} relax_info_t;
+
+/* Relocation table. */
+struct nds32_relocation_map
+{
+ unsigned int main_type;
+ /* Number of instructions, {relocations type, instruction type}. */
+ unsigned int reloc_insn[6][6][3];
+};
+
+#endif /* TC_NDS32 */
diff --git a/gas/configure b/gas/configure
index 590528c..8a89e4f 100755
--- a/gas/configure
+++ b/gas/configure
@@ -12192,6 +12192,100 @@ _ACEOF
using_cgen=yes
;;
+ nds32)
+ # Decide BASELINE, REDUCED_REGS, FPU_DP_EXT, FPU_SP_EXT features
+ # based on arch_name.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-arch" >&5
+$as_echo_n "checking for default configuration of --with-arch... " >&6; }
+ if test "x${with_arch}" != x; then
+ case ${with_arch} in
+ v2j | v2s | v2f | v2 | v3m | v3j | v3s | v3f | v3 )
+
+cat >>confdefs.h <<_ACEOF
+#define NDS32_DEFAULT_ARCH_NAME "$with_arch"
+_ACEOF
+
+ ;;
+ *)
+ as_fn_error "This kind of arch name does *NOT* exist!" "$LINENO" 5
+ ;;
+ esac
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_arch" >&5
+$as_echo "$with_arch" >&6; }
+
+ # Decide features one by one.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-dx-regs" >&5
+$as_echo_n "checking for default configuration of --enable-dx-regs... " >&6; }
+ if test "x${enable_dx_regs}" == xyes; then
+
+$as_echo "#define NDS32_DEFAULT_DX_REGS 1" >>confdefs.h
+
+ else
+
+$as_echo "#define NDS32_DEFAULT_DX_REGS 0" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_dx_regs" >&5
+$as_echo "$enable_dx_regs" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-perf-ext" >&5
+$as_echo_n "checking for default configuration of --enable-perf-ext... " >&6; }
+ if test "x${enable_perf_ext}" == xno; then
+
+$as_echo "#define NDS32_DEFAULT_PERF_EXT 0" >>confdefs.h
+
+ else
+
+$as_echo "#define NDS32_DEFAULT_PERF_EXT 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_perf_ext" >&5
+$as_echo "$enable_perf_ext" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-perf-ext2" >&5
+$as_echo_n "checking for default configuration of --enable-perf-ext2... " >&6; }
+ if test "x${enable_perf_ext2}" == xno; then
+
+$as_echo "#define NDS32_DEFAULT_PERF_EXT2 0" >>confdefs.h
+
+ else
+
+$as_echo "#define NDS32_DEFAULT_PERF_EXT2 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_perf_ext2" >&5
+$as_echo "$enable_perf_ext2" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-string-ext" >&5
+$as_echo_n "checking for default configuration of --enable-string-ext... " >&6; }
+ if test "x${enable_string_ext}" == xno; then
+
+$as_echo "#define NDS32_DEFAULT_STRING_EXT 0" >>confdefs.h
+
+ else
+
+$as_echo "#define NDS32_DEFAULT_STRING_EXT 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_string_ext" >&5
+$as_echo "$enable_string_ext" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-audio-ext" >&5
+$as_echo_n "checking for default configuration of --enable-audio-ext... " >&6; }
+ if test "x${enable_audio_ext}" == xno; then
+
+$as_echo "#define NDS32_DEFAULT_AUDIO_EXT 0" >>confdefs.h
+
+ else
+
+$as_echo "#define NDS32_DEFAULT_AUDIO_EXT 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_audio_ext" >&5
+$as_echo "$enable_audio_ext" >&6; }
+ ;;
+
i386 | s390 | sparc)
if test $this_target = $target ; then
diff --git a/gas/configure.in b/gas/configure.in
index 121fcfc..9e1ba59 100644
--- a/gas/configure.in
+++ b/gas/configure.in
@@ -363,6 +363,75 @@ changequote([,])dnl
using_cgen=yes
;;
+ nds32)
+ # Decide BASELINE, REDUCED_REGS, FPU_DP_EXT, FPU_SP_EXT features
+ # based on arch_name.
+ AC_MSG_CHECKING(for default configuration of --with-arch)
+ if test "x${with_arch}" != x; then
+ case ${with_arch} in
+ v2j | v2s | v2f | v2 | v3m | v3j | v3s | v3f | v3 )
+ AC_DEFINE_UNQUOTED(NDS32_DEFAULT_ARCH_NAME, "$with_arch",
+ [Define value for nds32_arch_name])
+ ;;
+ *)
+ AC_MSG_ERROR(This kind of arch name does *NOT* exist!)
+ ;;
+ esac
+ fi
+ AC_MSG_RESULT($with_arch)
+
+ # Decide features one by one.
+ AC_MSG_CHECKING(for default configuration of --enable-dx-regs)
+ if test "x${enable_dx_regs}" == xyes; then
+ AC_DEFINE(NDS32_DEFAULT_DX_REGS, 1,
+ [Define value for nds32_dx_regs])
+ else
+ AC_DEFINE(NDS32_DEFAULT_DX_REGS, 0,
+ [Define default value for nds32_dx_regs])
+ fi
+ AC_MSG_RESULT($enable_dx_regs)
+
+ AC_MSG_CHECKING(for default configuration of --enable-perf-ext)
+ if test "x${enable_perf_ext}" == xno; then
+ AC_DEFINE(NDS32_DEFAULT_PERF_EXT, 0,
+ [Define value for nds32_perf_ext])
+ else
+ AC_DEFINE(NDS32_DEFAULT_PERF_EXT, 1,
+ [Define default value for nds32_perf_ext])
+ fi
+ AC_MSG_RESULT($enable_perf_ext)
+
+ AC_MSG_CHECKING(for default configuration of --enable-perf-ext2)
+ if test "x${enable_perf_ext2}" == xno; then
+ AC_DEFINE(NDS32_DEFAULT_PERF_EXT2, 0,
+ [Define value for nds32_perf_ext2])
+ else
+ AC_DEFINE(NDS32_DEFAULT_PERF_EXT2, 1,
+ [Define default value for nds32_perf_ext2])
+ fi
+ AC_MSG_RESULT($enable_perf_ext2)
+
+ AC_MSG_CHECKING(for default configuration of --enable-string-ext)
+ if test "x${enable_string_ext}" == xno; then
+ AC_DEFINE(NDS32_DEFAULT_STRING_EXT, 0,
+ [Define value for nds32_string_ext])
+ else
+ AC_DEFINE(NDS32_DEFAULT_STRING_EXT, 1,
+ [Define default value for nds32_string_ext])
+ fi
+ AC_MSG_RESULT($enable_string_ext)
+
+ AC_MSG_CHECKING(for default configuration of --enable-audio-ext)
+ if test "x${enable_audio_ext}" == xno; then
+ AC_DEFINE(NDS32_DEFAULT_AUDIO_EXT, 0,
+ [Define value for nds32_audio_ext])
+ else
+ AC_DEFINE(NDS32_DEFAULT_AUDIO_EXT, 1,
+ [Define default value for nds32_audio_ext])
+ fi
+ AC_MSG_RESULT($enable_audio_ext)
+ ;;
+
i386 | s390 | sparc)
if test $this_target = $target ; then
AC_DEFINE_UNQUOTED(DEFAULT_ARCH, "${arch}", [Default architecture.])
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 77c1d9b..fdc0612 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -79,6 +79,8 @@ case ${cpu} in
mips*el) cpu_type=mips endian=little ;;
mips*) cpu_type=mips endian=big ;;
mt) cpu_type=mt endian=big ;;
+ nds32be) cpu_type=nds32 endian=big ;;
+ nds32le) cpu_type=nds32 endian=little ;;
or32*) cpu_type=or32 endian=big ;;
pjl*) cpu_type=pj endian=little ;;
pj*) cpu_type=pj endian=big ;;
@@ -344,6 +346,9 @@ case ${generic_target} in
msp430-*-*) fmt=elf ;;
+ nds32-*-elf*) fmt=elf ;;
+ nds32-*-linux*) fmt=elf em=linux ;;
+
nios2-*-rtems*) fmt=elf ;;
nios2*-linux*) fmt=elf em=linux ;;
diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am
index 3d1e933..e5b3c5f 100644
--- a/gas/doc/Makefile.am
+++ b/gas/doc/Makefile.am
@@ -75,6 +75,7 @@ CPU_DOCS = \
c-mt.texi \
c-msp430.texi \
c-nios2.texi \
+ c-nds32.texi \
c-ns32k.texi \
c-pdp11.texi \
c-pj.texi \
diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in
index 4c3c4fb..5a65e17 100644
--- a/gas/doc/Makefile.in
+++ b/gas/doc/Makefile.in
@@ -317,6 +317,7 @@ CPU_DOCS = \
c-mt.texi \
c-msp430.texi \
c-nios2.texi \
+ c-nds32.texi \
c-ns32k.texi \
c-pdp11.texi \
c-pj.texi \
diff --git a/gas/doc/all.texi b/gas/doc/all.texi
index 99dbf8f..5e1ed04 100644
--- a/gas/doc/all.texi
+++ b/gas/doc/all.texi
@@ -1,6 +1,4 @@
-@c Copyright 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002,
-@c 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-@c Free Software Foundation, Inc.
+@c Copyright 1992-2013 Free Software Foundation, Inc.
@c This file is part of the documentation for the GAS manual
@c Configuration settings for all-inclusive version of manual
@@ -59,6 +57,7 @@
@set MS1
@set MSP430
@set NIOSII
+@set NDS32
@set NS32K
@set PDP11
@set PJ
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 5fe06e6..739b5b9 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -437,6 +437,18 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
[@b{-relax-all}] [@b{-relax-section}] [@b{-no-relax}]
[@b{-EB}] [@b{-EL}]
@end ifset
+@ifset NDS32
+
+@emph{Target NDS32 options:}
+ [@b{-EL}] [@b{-EB}] [@b{-O}] [@b{-Os}] [@b{-mcpu=@var{cpu}}]
+ [@b{-misa=@var{isa}}] [@b{-mabi=@var{abi}}] [@b{-mall-ext}]
+ [@b{-m[no-]16-bit}] [@b{-m[no-]perf-ext}] [@b{-m[no-]perf2-ext}]
+ [@b{-m[no-]string-ext}] [@b{-m[no-]dsp-ext}] [@b{-m[no-]mac}] [@b{-m[no-]div}]
+ [@b{-m[no-]audio-isa-ext}] [@b{-m[no-]fpu-sp-ext}] [@b{-m[no-]fpu-dp-ext}]
+ [@b{-m[no-]fpu-fma}] [@b{-mfpu-freg=@var{FREG}}] [@b{-mreduced-regs}]
+ [@b{-mfull-regs}] [@b{-m[no-]dx-regs}] [@b{-mpic}] [@b{-mno-relax}]
+ [@b{-mb2bb}]
+@end ifset
@ifset PDP11
@emph{Target PDP11 options:}
@@ -1471,6 +1483,25 @@ Meta processor.
See the info pages for documentation of the MMIX-specific options.
@end ifset
+@ifset NDS32
+
+@ifclear man
+@xref{NDS32 Options}, for the options available when @value{AS} is configured
+for a NDS32 processor.
+@end ifclear
+@c ended inside the included file
+@end ifset
+
+@ifset man
+@c man begin OPTIONS
+The following options are available when @value{AS} is configured for a
+NDS32 processor.
+@c man end
+@c man begin INCLUDE
+@include c-nds32.texi
+@c ended inside the included file
+@end ifset
+
@c man end
@ifset PPC
@@ -7127,6 +7158,9 @@ subject, see the hardware manufacturer's manual.
@ifset MSP430
* MSP430-Dependent:: MSP430 Dependent Features
@end ifset
+@ifset NDS32
+* NDS32-Dependent:: Andes NDS32 Dependent Features
+@end ifset
@ifset NIOSII
* NiosII-Dependent:: Altera Nios II Dependent Features
@end ifset
@@ -7341,6 +7375,10 @@ family.
@include c-msp430.texi
@end ifset
+@ifset NDS32
+@include c-nds32.texi
+@end ifset
+
@ifset NIOSII
@include c-nios2.texi
@end ifset
diff --git a/gas/doc/c-nds32.texi b/gas/doc/c-nds32.texi
new file mode 100644
index 0000000..9636fcc
--- /dev/null
+++ b/gas/doc/c-nds32.texi
@@ -0,0 +1,299 @@
+@c Copyright 2013 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@c man end
+
+@ifset GENERIC
+@page
+@node NDS32-Dependent
+@chapter NDS32 Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter NDS32 Dependent Features
+@end ifclear
+
+@cindex NDS32 processor
+The NDS32 processors family includes high-performance and low-power 32-bit
+processors for high-end to low-end. @sc{gnu} @code{@value{AS}} for NDS32
+architectures supports NDS32 ISA version 3. For detail about NDS32
+instruction set, please see the AndeStar ISA User Manual which is availible
+at http://www.andestech.com/en/index/index.htm
+
+@menu
+* NDS32 Options:: Assembler options
+* NDS32 Syntax:: High-level assembly macros
+@end menu
+
+@node NDS32 Options
+@section NDS32 Options
+
+@cindex NDS32 options
+@cindex options for NDS32
+The NDS32 configurations of @sc{gnu} @code{@value{AS}} support these
+special options:
+
+@c man begin OPTIONS
+@table @code
+
+@item -O1
+Optimize for performance.
+
+@item -Os
+Optimize for space.
+
+@item -EL
+Produce little endian data output.
+
+@item -EB
+Produce little endian data output.
+
+@item -mpic
+Generate PIC.
+
+@item -mno-fp-as-gp-relax
+Suppress fp-as-gp relaxation for this file.
+
+@item -mb2bb-relax
+Back-to-back branch optimization.
+
+@item -mno-all-relax
+Suppress all relaxation for this file.
+
+@item -march=<arch name>
+Assemble for architecture <arch name> which could be v3, v3j, v3m, v3f,
+v3s, v2, v2j, v2f, v2s.
+
+@item -mbaseline=<baseline>
+Assemble for baseline <baseline> which could be v2, v3, v3m.
+
+@item -mfpu-freg=@var{FREG}
+Specify a FPU configuration.
+@table @code
+@item 0 8 SP / 4 DP registers
+@item 1 16 SP / 8 DP registers
+@item 2 32 SP / 16 DP registers
+@item 3 32 SP / 32 DP registers
+@end table
+
+@item -mabi=@var{abi}
+Specify a abi version <abi> could be v1, v2, v2fp, v2fpp.
+
+@item -m[no-]mac
+Enable/Disable Multiply instructions support.
+
+@item -m[no-]div
+Enable/Disable Divide instructions support.
+
+@item -m[no-]16bit-ext
+Enable/Disable 16-bit extension
+
+@item -m[no-]dx-regs
+Enable/Disable d0/d1 registers
+
+@item -m[no-]perf-ext
+Enable/Disable Performance extension
+
+@item -m[no-]perf2-ext
+Enable/Disable Performance extension 2
+
+@item -m[no-]string-ext
+Enable/Disable String extension
+
+@item -m[no-]reduced-regs
+Enable/Disable Reduced Register configuration (GPR16) option
+
+@item -m[no-]audio-isa-ext
+Enable/Disable AUDIO ISA extension
+
+@item -m[no-]fpu-sp-ext
+Enable/Disable FPU SP extension
+
+@item -m[no-]fpu-dp-ext
+Enable/Disable FPU DP extension
+
+@item -m[no-]fpu-fma
+Enable/Disable FPU fused-multiply-add instructions
+
+@item -mall-ext
+Turn on all extensions and instructions support
+@end table
+@c man end
+
+@node NDS32 Syntax
+@section Syntax
+
+@menu
+* NDS32-Chars:: Special Characters
+* NDS32-Regs:: Register Names
+* NDS32-Ops:: Pseudo Instructions
+@end menu
+
+@node NDS32-Chars
+@subsection Special Characters
+
+Use @samp{#} at column 1 and @samp{!} anywhere in the line except inside
+quotes.
+
+Multiple instructions in a line are allowed though not recommended and
+should be separated by @samp{;}.
+
+Assembler is not case-sensitive in general except user defined label.
+For example, @samp{jral F1} is different from @samp{jral f1} while it is
+the same as @samp{JRAL F1}.
+
+@node NDS32-Regs
+@subsection Register Names
+@table @code
+@item General purpose registers (GPR)
+There are 32 32-bit general purpose registers $r0 to $r31.
+
+@item Accumulators d0 and d1
+64-bit accumulators: $d0.hi, $d0.lo, $d1.hi, and $d1.lo.
+
+@item Assembler reserved register $ta
+Register $ta ($r15) is reserved for assembler using.
+
+@item Operating system reserved registers $p0 and $p1
+Registers $p0 ($r26) and $p1 ($r27) are used by operating system as scratch
+registers.
+
+@item Frame pointer $fp
+Register $r28 is regarded as the frame pointer.
+
+@item Global pointer
+Register $r29 is regarded as the global pointer.
+
+@item Link pointer
+Register $r30 is regarded as the link pointer.
+
+@item Stack pointer
+Register $r31 is regarded as the stack pointer.
+@end table
+
+@node NDS32-Ops
+@subsection Pseudo Instructions
+@table @code
+@item li rt5,imm32
+load 32-bit integer into register rt5. @samp{sethi rt5,hi20(imm32)} and then
+@samp{ori rt5,reg,lo12(imm32)}.
+
+@item la rt5,var
+Load 32-bit address of var into register rt5. @samp{sethi rt5,hi20(var)} and
+then @samp{ori reg,rt5,lo12(var)}
+
+@item l.[bhw] rt5,var
+Load value of var into register rt5. @samp{sethi $ta,hi20(var)} and then
+@samp{l[bhw]i rt5,[$ta+lo12(var)]}
+
+@item l.[bh]s rt5,var
+Load value of var into register rt5. @samp{sethi $ta,hi20(var)} and then
+@samp{l[bh]si rt5,[$ta+lo12(var)]}
+
+@item l.[bhw]p rt5,var,inc
+Load value of var into register rt5 and increment $ta by amount inc.
+@samp{la $ta,var} and then @samp{l[bhw]i.bi rt5,[$ta],inc}
+
+@item l.[bhw]pc rt5,inc
+Continue loading value of var into register rt5 and increment $ta by amount inc.
+@samp{l[bhw]i.bi rt5,[$ta],inc.}
+
+@item l.[bh]sp rt5,var,inc
+Load value of var into register rt5 and increment $ta by amount inc.
+@samp{la $ta,var} and then @samp{l[bh]si.bi rt5,[$ta],inc}
+
+@item l.[bh]spc rt5,inc
+Continue loading value of var into register rt5 and increment $ta by amount inc.
+@samp{l[bh]si.bi rt5,[$ta],inc.}
+
+@item s.[bhw] rt5,var
+Store register rt5 to var.
+@samp{sethi $ta,hi20(var)} and then @samp{s[bhw]i rt5,[$ta+lo12(var)]}
+
+@item s.[bhw]p rt5,var,inc
+Store register rt5 to var and increment $ta by amount inc.
+@samp{la $ta,var} and then @samp{s[bhw]i.bi rt5,[$ta],inc}
+
+@item s.[bhw]pc rt5,inc
+Continue storing register rt5 to var and increment $ta by amount inc.
+@samp{s[bhw]i.bi rt5,[$ta],inc.}
+
+@item not rt5,ra5
+Alias of @samp{nor rt5,ra5,ra5}.
+
+@item neg rt5,ra5
+Alias of @samp{subri rt5,ra5,0}.
+
+@item br rb5
+Depending on how it is assembled, it is translated into @samp{r5 rb5}
+or @samp{jr rb5}.
+
+@item b label
+Branch to label depending on how it is assembled, it is translated into
+@samp{j8 label}, @samp{j label}, or "@samp{la $ta,label} @samp{br $ta}".
+
+@item bral rb5
+Alias of jral br5 depending on how it is assembled, it is translated
+into @samp{jral5 rb5} or @samp{jral rb5}.
+
+@item bal fname
+Alias of jal fname depending on how it is assembled, it is translated into
+@samp{jal fname} or "@samp{la $ta,fname} @samp{bral $ta}".
+
+@item call fname
+Call function fname same as @samp{jal fname}.
+
+@item move rt5,ra5
+For 16-bit, this is @samp{mov55 rt5,ra5}.
+For no 16-bit, this is @samp{ori rt5,ra5,0}.
+
+@item move rt5,var
+This is the same as @samp{l.w rt5,var}.
+
+@item move rt5,imm32
+This is the same as @samp{li rt5,imm32}.
+
+@item pushm ra5,rb5
+Push contents of registers from ra5 to rb5 into stack.
+
+@item push ra5
+Push content of register ra5 into stack. (same @samp{pushm ra5,ra5}).
+
+@item push.d var
+Push value of double-word variable var into stack.
+
+@item push.w var
+Push value of word variable var into stack.
+
+@item push.h var
+Push value of half-word variable var into stack.
+
+@item push.b var
+Push value of byte variable var into stack.
+
+@item pusha var
+Push 32-bit address of variable var into stack.
+
+@item pushi imm32
+Push 32-bit immediate value into stack.
+
+@item popm ra5,rb5
+Pop top of stack values into registers ra5 to rb5.
+
+@item pop rt5
+Pop top of stack value into register. (same as @samp{popm rt5,rt5}.)
+
+@item pop.d var,ra5
+Pop value of double-word variable var from stack using register ra5
+as 2nd scratch register. (1st is $ta)
+
+@item pop.w var,ra5
+Pop value of word variable var from stack using register ra5.
+
+@item pop.h var,ra5
+Pop value of half-word variable var from stack using register ra5.
+
+@item pop.b var,ra5
+Pop value of byte variable var from stack using register ra5.
+
+@end table
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index a0dba9f..d9ae4c0 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,35 @@
+2013-12-13 Kuan-Lin Chen <kuanlinchentw@gmail.com>
+
+ * gas/all/gas.exp: Add expected failures for NDS32.
+ * gas/elf/elf.exp: Likewise.
+ * gas/lns/lns.exp: Use alternate test.
+ * gas/macros/irp.d: Skip for NDS32.
+ * gas/macros/macros.exp: Skip some tests for the NDS32.
+ * gas/macros/rept.d: Skip for NDS32.
+ * gas/macros/test3.d: Skip for NDS32.
+ * gas/nds32: New directory.
+ * gas/nds32/alu-1.s: New test.
+ * gas/nds32/alu-1.d: Likewise.
+ * gas/nds32/alu-2.s: Likewise.
+ * gas/nds32/alu-2.d: Likewise.
+ * gas/nds32/br-1.d: Likewise.
+ * gas/nds32/br-1.s: Likewise.
+ * gas/nds32/br-2.d: Likewise.
+ * gas/nds32/br-2.s: Likewise.
+ * gas/nds32/ji-jr.d: Likewise.
+ * gas/nds32/ji-jr.s: Likewise.
+ * gas/nds32/ls.d: Likewise.
+ * gas/nds32/ls.s: Likewise.
+ * gas/nds32/lsi.d: Likewise.
+ * gas/nds32/lsi.s: Likewise.
+ * gas/nds32/to-16bit-v1.d: Likewise.
+ * gas/nds32/to-16bit-v1.s: Likewise.
+ * gas/nds32/to-16bit-v2.d: Likewise.
+ * gas/nds32/to-16bit-v2.s: Likewise.
+ * gas/nds32/to-16bit-v3.d: Likewise.
+ * gas/nds32/to-16bit-v3.s: Likewise.
+ * gas/nds32/nds32.exp: New test driver.
+
2013-12-07 Mike Frysinger <vapier@gentoo.org>
* gas/bfin/bit2.s: Remove +x file mode.
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
index 35bcd95..f04a6d3 100644
--- a/gas/testsuite/gas/all/gas.exp
+++ b/gas/testsuite/gas/all/gas.exp
@@ -101,7 +101,7 @@ case $target_triplet in {
# Some targets don't manage to resolve BFD_RELOC_8 for constants.
setup_xfail "alpha*-*-*" "*c30*-*-*" "*c4x*-*-*" \
"d\[13\]0v*-*-*" "i860-*-*" "mips*-*-*" \
- "pdp11-*-*" "xtensa*-*-*"
+ "nds32*-*-*" "pdp11-*-*" "xtensa*-*-*"
run_dump_test forward
}
}
@@ -118,6 +118,7 @@ if { ![is_aout_format] } {
{ hppa*-*-hpux* } { }
{ mep-*-* } { }
{ mmix-*-* } { }
+ { nds32*-*-* } { }
{ tic30*-*-* } { }
{ tic4x*-*-* } { }
{ tic54x*-*-* } { }
@@ -140,6 +141,7 @@ case $target_triplet in {
{ mn10200-*-* } { }
{ mn10300-*-* } { }
{ msp430*-*-* } { }
+ { nds32*-*-* } { }
{ pdp11-*-* } { }
{ tic30*-*-* } { }
{ tic4x*-*-* } { }
@@ -366,12 +368,13 @@ if { ([istarget "i*86-*-*pe*"] && ![istarget "i*86-*-openbsd*"]) \
gas_test "fastcall.s" "" "" "fastcall labels"
}
-if { ![istarget "bfin-*-*"] } then {
+if { ![istarget "bfin-*-*"] && ![istarget "nds32*-*-*"] } then {
run_dump_test assign
}
run_dump_test sleb128
run_dump_test sleb128-2
run_dump_test sleb128-3
+setup_xfail "nds32*-*-*"
run_dump_test sleb128-4
run_dump_test sleb128-5
# .byte is not 8 bits on either tic4x or tic54x
@@ -414,6 +417,7 @@ case $target_triplet in {
{ *c54x*-*-* } { }
{ z80-*-* } { }
default {
+ setup_xfail "nds32*-*-*"
run_dump_test weakref1
run_dump_test weakref1g
run_dump_test weakref1l
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 4196fd7..d40e9f3 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -94,6 +94,7 @@ if { [is_elf_format] } then {
if {![istarget "mn10300-*-*"]
&& ![istarget "xtensa*-*-*"]
&& ![istarget "msp430*-*-*"]
+ && ![istarget "nds32*-*-*"]
&& ![istarget "am3*-*-*"]} then {
run_dump_test "ehopt0"
}
@@ -111,6 +112,7 @@ if { [is_elf_format] } then {
run_dump_test "file"
}
}
+ setup_xfail "nds32*-*-*"
run_dump_test "group0a"
run_dump_test "group0b"
run_dump_test "group0c"
diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
index f1d7f98..8f81998 100644
--- a/gas/testsuite/gas/lns/lns.exp
+++ b/gas/testsuite/gas/lns/lns.exp
@@ -39,6 +39,7 @@ if {
|| [istarget cr16-*-*]
|| [istarget crx-*-*]
|| [istarget msp430-*-*]
+ || [istarget nds32*-*-*]
|| [istarget mn10*-*-*] } {
run_dump_test "lns-common-1-alt"
run_dump_test "lns-big-delta"
diff --git a/gas/testsuite/gas/macros/irp.d b/gas/testsuite/gas/macros/irp.d
index 2c07f8e..7773792 100644
--- a/gas/testsuite/gas/macros/irp.d
+++ b/gas/testsuite/gas/macros/irp.d
@@ -1,7 +1,7 @@
#objdump: -r
#name: macro irp
#darwin (mach-o) reverses relocs.
-#not-target: *-*-darwin*
+#not-target: *-*-darwin* nds32*-*-*
.*: +file format .*
diff --git a/gas/testsuite/gas/macros/macros.exp b/gas/testsuite/gas/macros/macros.exp
index 4a2716d..1253415 100644
--- a/gas/testsuite/gas/macros/macros.exp
+++ b/gas/testsuite/gas/macros/macros.exp
@@ -21,13 +21,13 @@ if { ![istarget hppa*-*-*] || [istarget *-*-linux*] } {
run_dump_test test1
}
-if { ![istarget *c54x*-*-*] && ![istarget *c4x*-*-*] } {
+if { ![istarget *c54x*-*-*] && ![istarget *c4x*-*-*] && ![istarget "nds32*-*-*"] } {
run_dump_test test2
}
run_dump_test test3
-if { ![istarget *c54x*-*-*] && ![istarget *c4x*-*-*] } {
+if { ![istarget *c54x*-*-*] && ![istarget *c4x*-*-*] && ![istarget "nds32*-*-*"] } {
run_dump_test irp
run_dump_test rept
run_dump_test repeat
diff --git a/gas/testsuite/gas/macros/rept.d b/gas/testsuite/gas/macros/rept.d
index df2ed96..92d6410 100644
--- a/gas/testsuite/gas/macros/rept.d
+++ b/gas/testsuite/gas/macros/rept.d
@@ -1,7 +1,7 @@
#objdump: -r
#name: macro rept
#darwin (mach-o) reverses relocs.
-#not-target: *-*-darwin*
+#not-target: *-*-darwin* nds32*-*-*
.*: +file format .*
diff --git a/gas/testsuite/gas/macros/test3.d b/gas/testsuite/gas/macros/test3.d
index 7680ad4..afd47fa 100644
--- a/gas/testsuite/gas/macros/test3.d
+++ b/gas/testsuite/gas/macros/test3.d
@@ -1,5 +1,6 @@
#objdump: -r
#name: macro test 3
+#not-target: nds32*-*-*
.*: +file format .*
diff --git a/gas/testsuite/gas/nds32/alu-1.d b/gas/testsuite/gas/nds32/alu-1.d
new file mode 100644
index 0000000..f1385cd
--- /dev/null
+++ b/gas/testsuite/gas/nds32/alu-1.d
@@ -0,0 +1,47 @@
+#objdump: -d --prefix-addresses
+#name: nds32 alu_1 instructions
+#as:
+
+# Test alu_1 instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> add \$r0, \$r1, \$r2
+0+0004 <[^>]*> and \$r0, \$r1, \$r2
+0+0008 <[^>]*> cmovn \$r0, \$r1, \$r2
+0+000c <[^>]*> cmovz \$r0, \$r1, \$r2
+0+0010 <[^>]*> nop
+0+0014 <[^>]*> nor \$r0, \$r1, \$r2
+0+0018 <[^>]*> or \$r0, \$r1, \$r2
+0+001c <[^>]*> rotr \$r0, \$r1, \$r2
+0+0020 <[^>]*> rotri \$r0, \$r1, #1
+0+0024 <[^>]*> seb \$r0, \$r1
+0+0028 <[^>]*> seh \$r0, \$r1
+0+002c <[^>]*> sll \$r0, \$r1, \$r2
+0+0030 <[^>]*> slli \$r0, \$r1, #1
+0+0034 <[^>]*> slt \$r0, \$r1, \$r2
+0+0038 <[^>]*> slts \$r0, \$r1, \$r2
+0+003c <[^>]*> sra \$r0, \$r1, \$r2
+0+0040 <[^>]*> srai \$r0, \$r1, #1
+0+0044 <[^>]*> srl \$r0, \$r1, \$r2
+0+0048 <[^>]*> srli \$r0, \$r1, #1
+0+004c <[^>]*> sub \$r0, \$r1, \$r2
+0+0050 <[^>]*> sva \$r0, \$r1, \$r2
+0+0054 <[^>]*> svs \$r0, \$r1, \$r2
+0+0058 <[^>]*> wsbh \$r0, \$r1
+0+005c <[^>]*> xor \$r0, \$r1, \$r2
+0+0060 <[^>]*> zeh \$r0, \$r1
+0+0064 <[^>]*> divr \$r0, \$r1, \$r2, \$r3
+0+0068 <[^>]*> divsr \$r0, \$r1, \$r2, \$r3
+0+006c <[^>]*> add_slli \$r0, \$r1, \$r2, #1
+0+0070 <[^>]*> add_srli \$r0, \$r1, \$r2, #1
+0+0074 <[^>]*> and_slli \$r0, \$r1, \$r2, #1
+0+0078 <[^>]*> and_srli \$r0, \$r1, \$r2, #1
+0+007c <[^>]*> bitc \$r0, \$r1, \$r2
+0+0080 <[^>]*> or_slli \$r0, \$r1, \$r2, #1
+0+0084 <[^>]*> or_srli \$r0, \$r1, \$r2, #1
+0+0088 <[^>]*> sub_slli \$r0, \$r1, \$r2, #1
+0+008c <[^>]*> sub_srli \$r0, \$r1, \$r2, #1
+0+0090 <[^>]*> xor_slli \$r0, \$r1, \$r2, #1
+0+0094 <[^>]*> xor_srli \$r0, \$r1, \$r2, #1
diff --git a/gas/testsuite/gas/nds32/alu-1.s b/gas/testsuite/gas/nds32/alu-1.s
new file mode 100644
index 0000000..5f12783
--- /dev/null
+++ b/gas/testsuite/gas/nds32/alu-1.s
@@ -0,0 +1,39 @@
+foo:
+ add $r0, $r1, $r2
+ and $r0, $r1, $r2
+ cmovn $r0, $r1, $r2
+ cmovz $r0, $r1, $r2
+ nop
+ nor $r0, $r1, $r2
+ or $r0, $r1, $r2
+ rotr $r0, $r1, $r2
+ rotri $r0, $r1, 1
+ seb $r0, $r1
+ seh $r0, $r1
+ sll $r0, $r1, $r2
+ slli $r0, $r1, 1
+ slt $r0, $r1, $r2
+ slts $r0, $r1, $r2
+ sra $r0, $r1, $r2
+ srai $r0, $r1, 1
+ srl $r0, $r1, $r2
+ srli $r0, $r1, 1
+ sub $r0, $r1, $r2
+ sva $r0, $r1, $r2
+ svs $r0, $r1, $r2
+ wsbh $r0, $r1
+ xor $r0, $r1, $r2
+ zeh $r0, $r1
+ divr $r0, $r1, $r2, $r3
+ divsr $r0, $r1, $r2, $r3
+ add_slli $r0, $r1, $r2, 1
+ add_srli $r0, $r1, $r2, 1
+ and_slli $r0, $r1, $r2, 1
+ and_srli $r0, $r1, $r2, 1
+ bitc $r0, $r1, $r2
+ or_slli $r0, $r1, $r2, 1
+ or_srli $r0, $r1, $r2, 1
+ sub_slli $r0, $r1, $r2, 1
+ sub_srli $r0, $r1, $r2, 1
+ xor_slli $r0, $r1, $r2, 1
+ xor_srli $r0, $r1, $r2, 1
diff --git a/gas/testsuite/gas/nds32/alu-2.d b/gas/testsuite/gas/nds32/alu-2.d
new file mode 100644
index 0000000..1b32f0b
--- /dev/null
+++ b/gas/testsuite/gas/nds32/alu-2.d
@@ -0,0 +1,42 @@
+#objdump: -d --prefix-addresses
+#name: nds32 alu_2 instructions
+#as:
+
+# Test alu_2 instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> madd64 \$d0, \$r0, \$r1
+0+0004 <[^>]*> madds64 \$d0, \$r0, \$r1
+0+0008 <[^>]*> mfusr \$r0, \$pc
+0+000c <[^>]*> msub64 \$d0, \$r0, \$r1
+0+0010 <[^>]*> msubs64 \$d0, \$r0, \$r1
+0+0014 <[^>]*> mtusr \$r0, \$pc
+0+0018 <[^>]*> mul \$r0, \$r1, \$r2
+0+001c <[^>]*> mult32 \$d0, \$r1, \$r2
+0+0020 <[^>]*> mult64 \$d0, \$r1, \$r2
+0+0024 <[^>]*> mults64 \$d0, \$r1, \$r2
+0+0028 <[^>]*> abs \$r0, \$r1
+0+002c <[^>]*> ave \$r0, \$r1, \$r2
+0+0030 <[^>]*> bclr \$r0, \$r1, #1
+0+0034 <[^>]*> bset \$r0, \$r1, #1
+0+0038 <[^>]*> btgl \$r0, \$r1, #1
+0+003c <[^>]*> btst \$r0, \$r1, #1
+0+0040 <[^>]*> clip \$r0, \$r1, #1
+0+0044 <[^>]*> clips \$r0, \$r1, #1
+0+0048 <[^>]*> clo \$r0, \$r1
+0+004c <[^>]*> clz \$r0, \$r1
+0+0050 <[^>]*> max \$r0, \$r1, \$r2
+0+0054 <[^>]*> min \$r0, \$r1, \$r2
+0+0058 <[^>]*> bse \$r0, \$r1, \$r2
+0+005c <[^>]*> bsp \$r0, \$r1, \$r2
+0+0060 <[^>]*> ffb \$r0, \$r1, \$r2
+0+0064 <[^>]*> ffbi \$r0, \$r1, #0x8
+0+0068 <[^>]*> ffmism \$r0, \$r1, \$r2
+0+006c <[^>]*> flmism \$r0, \$r1, \$r2
+0+0070 <[^>]*> maddr32 \$r0, \$r0, \$r1
+0+0074 <[^>]*> msubr32 \$r0, \$r1, \$r2
+0+0078 <[^>]*> mulr64 \$r0, \$r1, \$r2
+0+007c <[^>]*> mulsr64 \$r0, \$r1, \$r2
+
diff --git a/gas/testsuite/gas/nds32/alu-2.s b/gas/testsuite/gas/nds32/alu-2.s
new file mode 100644
index 0000000..d1743db
--- /dev/null
+++ b/gas/testsuite/gas/nds32/alu-2.s
@@ -0,0 +1,33 @@
+foo:
+ madd64 $d0, $r0, $r1
+ madds64 $d0, $r0, $r1
+ mfusr $r0, $pc
+ msub64 $d0, $r0, $r1
+ msubs64 $d0, $r0, $r1
+ mtusr $r0, $pc
+ mul $r0, $r1, $r2
+ mult32 $d0, $r1, $r2
+ mult64 $d0, $r1, $r2
+ mults64 $d0, $r1, $r2
+ abs $r0, $r1
+ ave $r0, $r1, $r2
+ bclr $r0, $r1, 1
+ bset $r0, $r1, 1
+ btgl $r0, $r1, 1
+ btst $r0, $r1, 1
+ clip $r0, $r1, 1
+ clips $r0, $r1, 1
+ clo $r0, $r1
+ clz $r0, $r1
+ max $r0, $r1, $r2
+ min $r0, $r1, $r2
+ bse $r0, $r1, $r2
+ bsp $r0, $r1, $r2
+ ffb $r0, $r1, $r2
+ ffbi $r0, $r1, 1
+ ffmism $r0, $r1, $r2
+ flmism $r0, $r1, $r2
+ maddr32 $r0, $r0, $r1
+ msubr32 $r0, $r1, $r2
+ mulr64 $r0, $r1, $r2
+ mulsr64 $r0, $r1, $r2
diff --git a/gas/testsuite/gas/nds32/br-1.d b/gas/testsuite/gas/nds32/br-1.d
new file mode 100644
index 0000000..e27f96c
--- /dev/null
+++ b/gas/testsuite/gas/nds32/br-1.d
@@ -0,0 +1,15 @@
+#objdump: -dr --prefix-addresses
+#name: nds32 branch 1 instructions
+#as:
+
+# Test br-1 instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> beq \$r0, \$r1, 00000000 <foo>
+ 0: R_NDS32_15_PCREL_RELA .text
+ 0: R_NDS32_RELAX_ENTRY .text
+0+0004 <[^>]*> bne \$r0, \$r1, 00000004 <foo\+0x4>
+ 4: R_NDS32_15_PCREL_RELA .text
+
diff --git a/gas/testsuite/gas/nds32/br-1.s b/gas/testsuite/gas/nds32/br-1.s
new file mode 100644
index 0000000..58d993a
--- /dev/null
+++ b/gas/testsuite/gas/nds32/br-1.s
@@ -0,0 +1,3 @@
+foo:
+ beq $r0, $r1, foo
+ bne $r0, $r1, foo
diff --git a/gas/testsuite/gas/nds32/br-2.d b/gas/testsuite/gas/nds32/br-2.d
new file mode 100644
index 0000000..0edc375
--- /dev/null
+++ b/gas/testsuite/gas/nds32/br-2.d
@@ -0,0 +1,25 @@
+#objdump: -dr --prefix-addresses
+#name: nds32 branch 2 instructions
+#as:
+
+# Test br-2 instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> beqz \$r0, 00000000 <foo>
+ 0: R_NDS32_17_PCREL_RELA .text
+ 0: R_NDS32_RELAX_ENTRY .text
+0+0004 <[^>]*> bgez \$r0, 00000004 <foo\+0x4>
+ 4: R_NDS32_17_PCREL_RELA .text
+0+0008 <[^>]*> bgezal \$r0, 00000008 <foo\+0x8>
+ 8: R_NDS32_17_PCREL_RELA .text
+0+000c <[^>]*> bgtz \$r0, 0000000c <foo\+0xc>
+ c: R_NDS32_17_PCREL_RELA .text
+0+0010 <[^>]*> blez \$r0, 00000010 <foo\+0x10>
+ 10: R_NDS32_17_PCREL_RELA .text
+0+0014 <[^>]*> bltz \$r0, 00000014 <foo\+0x14>
+ 14: R_NDS32_17_PCREL_RELA .text
+0+0018 <[^>]*> bltzal \$r0, 00000018 <foo\+0x18>
+ 18: R_NDS32_17_PCREL_RELA .text
+
diff --git a/gas/testsuite/gas/nds32/br-2.s b/gas/testsuite/gas/nds32/br-2.s
new file mode 100644
index 0000000..554a8de
--- /dev/null
+++ b/gas/testsuite/gas/nds32/br-2.s
@@ -0,0 +1,8 @@
+foo:
+ beqz $r0, foo
+ bgez $r0, foo
+ bgezal $r0, foo
+ bgtz $r0, foo
+ blez $r0, foo
+ bltz $r0, foo
+ bltzal $r0, foo
diff --git a/gas/testsuite/gas/nds32/ji-jr.d b/gas/testsuite/gas/nds32/ji-jr.d
new file mode 100644
index 0000000..31969e1
--- /dev/null
+++ b/gas/testsuite/gas/nds32/ji-jr.d
@@ -0,0 +1,18 @@
+#objdump: -dr --prefix-addresses
+#name: nds32 load-store instructions
+#as:
+
+# Test ls instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> j8 00000000 <foo>
+ 0: R_NDS32_9_PCREL_RELA .text
+ 0: R_NDS32_RELAX_ENTRY .text
+0+0002 <[^>]*> jal 00000002 <foo\+0x2>
+ 2: R_NDS32_25_PCREL_RELA .text
+0+0006 <[^>]*> jr \$r0
+0+000a <[^>]*> jral \$lp, \$r0
+0+000e <[^>]*> ret \$lp
+
diff --git a/gas/testsuite/gas/nds32/ji-jr.s b/gas/testsuite/gas/nds32/ji-jr.s
new file mode 100644
index 0000000..2457d0b
--- /dev/null
+++ b/gas/testsuite/gas/nds32/ji-jr.s
@@ -0,0 +1,6 @@
+foo:
+ j foo
+ jal foo
+ jr $r0
+ jral $r0
+ ret
diff --git a/gas/testsuite/gas/nds32/ls.d b/gas/testsuite/gas/nds32/ls.d
new file mode 100644
index 0000000..688ed11
--- /dev/null
+++ b/gas/testsuite/gas/nds32/ls.d
@@ -0,0 +1,25 @@
+#objdump: -d --prefix-addresses
+#name: nds32 load-store instructions
+#as:
+
+# Test ls instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lw \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+0004 <[^>]*> lh \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+0008 <[^>]*> lhs \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+000c <[^>]*> lb \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+0010 <[^>]*> lbs \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+0014 <[^>]*> sw \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+0018 <[^>]*> sh \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+001c <[^>]*> sb \$r0, \[\$r1 \+ \(\$r2 << 1\)\]
+0+0020 <[^>]*> lw.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+0024 <[^>]*> lh.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+0028 <[^>]*> lhs.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+002c <[^>]*> lb.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+0030 <[^>]*> lbs.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+0034 <[^>]*> sw.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+0038 <[^>]*> sh.bi \$r0, \[\$r1\], \(\$r2 << 1\)
+0+003c <[^>]*> sb.bi \$r0, \[\$r1\], \(\$r2 << 1\)
diff --git a/gas/testsuite/gas/nds32/ls.s b/gas/testsuite/gas/nds32/ls.s
new file mode 100644
index 0000000..88d3d33
--- /dev/null
+++ b/gas/testsuite/gas/nds32/ls.s
@@ -0,0 +1,17 @@
+foo:
+ lw $r0, [$r1 + ($r2 << 1)]
+ lh $r0, [$r1 + ($r2 << 1)]
+ lhs $r0, [$r1 + ($r2 << 1)]
+ lb $r0, [$r1 + ($r2 << 1)]
+ lbs $r0, [$r1 + ($r2 << 1)]
+ sw $r0, [$r1 + ($r2 << 1)]
+ sh $r0, [$r1 + ($r2 << 1)]
+ sb $r0, [$r1 + ($r2 << 1)]
+ lw.bi $r0, [$r1], $r2 << 1
+ lh.bi $r0, [$r1], $r2 << 1
+ lhs.bi $r0, [$r1], $r2 << 1
+ lb.bi $r0, [$r1], $r2 << 1
+ lbs.bi $r0, [$r1], $r2 << 1
+ sw.bi $r0, [$r1], $r2 << 1
+ sh.bi $r0, [$r1], $r2 << 1
+ sb.bi $r0, [$r1], $r2 << 1
diff --git a/gas/testsuite/gas/nds32/lsi.d b/gas/testsuite/gas/nds32/lsi.d
new file mode 100644
index 0000000..9fe5371
--- /dev/null
+++ b/gas/testsuite/gas/nds32/lsi.d
@@ -0,0 +1,26 @@
+#objdump: -d --prefix-addresses
+#name: nds32 load-store immediate instructions
+#as:
+
+# Test lsi instructions
+
+.*: file format .*
+
+Disassembly of section .text:
+0+0000 <[^>]*> lwi \$r0, \[\$r1 \+ #4\]
+0+0004 <[^>]*> lhi \$r0, \[\$r1 \+ #2\]
+0+0008 <[^>]*> lhsi \$r0, \[\$r1 \+ #-2\]
+0+000c <[^>]*> lbi \$r0, \[\$r1 \+ #1\]
+0+0010 <[^>]*> lbsi \$r0, \[\$r1 \+ #-1\]
+0+0014 <[^>]*> swi \$r0, \[\$r1 \+ #4\]
+0+0018 <[^>]*> shi \$r0, \[\$r1 \+ #2\]
+0+001c <[^>]*> sbi \$r0, \[\$r1 \+ #1\]
+0+0020 <[^>]*> lwi.bi \$r0, \[\$r1\], #4
+0+0024 <[^>]*> lhi.bi \$r0, \[\$r1\], #2
+0+0028 <[^>]*> lhsi.bi \$r0, \[\$r1\], #-2
+0+002c <[^>]*> lbi.bi \$r0, \[\$r1\], #1
+0+0030 <[^>]*> lbsi.bi \$r0, \[\$r1\], #-1
+0+0034 <[^>]*> swi.bi \$r0, \[\$r1\], #4
+0+0038 <[^>]*> shi.bi \$r0, \[\$r1\], #2
+0+003c <[^>]*> sbi.bi \$r0, \[\$r1\], #1
+
diff --git a/gas/testsuite/gas/nds32/lsi.s b/gas/testsuite/gas/nds32/lsi.s
new file mode 100644
index 0000000..a2dd62a
--- /dev/null
+++ b/gas/testsuite/gas/nds32/lsi.s
@@ -0,0 +1,17 @@
+foo:
+ lwi $r0, [$r1 + (1 << 2)]
+ lhi $r0, [$r1 + (1 << 1)]
+ lhsi $r0, [$r1 + (-1 << 1)]
+ lbi $r0, [$r1 + 1]
+ lbsi $r0, [$r1 + (-1)]
+ swi $r0, [$r1 + (1 << 2)]
+ shi $r0, [$r1 + (1 << 1)]
+ sbi $r0, [$r1 + 1]
+ lwi.bi $r0, [$r1], (1 << 2)
+ lhi.bi $r0, [$r1], (1 << 1)
+ lhsi.bi $r0, [$r1], (-1 << 1)
+ lbi.bi $r0, [$r1], 1
+ lbsi.bi $r0, [$r1], -1
+ swi.bi $r0, [$r1], (1 << 2)
+ shi.bi $r0, [$r1], (1 << 1)
+ sbi.bi $r0, [$r1], 1
diff --git a/gas/testsuite/gas/nds32/nds32.exp b/gas/testsuite/gas/nds32/nds32.exp
new file mode 100644
index 0000000..f547697
--- /dev/null
+++ b/gas/testsuite/gas/nds32/nds32.exp
@@ -0,0 +1,30 @@
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+
+# 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.
+
+if { [istarget nds32*] } {
+ run_dump_test "alu-1"
+ run_dump_test "alu-2"
+ run_dump_test "lsi"
+ run_dump_test "ls"
+ run_dump_test "br-1"
+ run_dump_test "br-2"
+ run_dump_test "ji-jr"
+ run_dump_test "to-16bit-v1"
+ run_dump_test "to-16bit-v2"
+ run_dump_test "to-16bit-v3"
+}
diff --git a/gas/testsuite/gas/nds32/to-16bit-v1.d b/gas/testsuite/gas/nds32/to-16bit-v1.d
new file mode 100644
index 0000000..a45de36
--- /dev/null
+++ b/gas/testsuite/gas/nds32/to-16bit-v1.d
@@ -0,0 +1,79 @@
+#objdump: -d --prefix-addresses
+#name: nds32 convert 32 to 16 (v1 instructions)
+#as: -Os -mno-reduced-regs
+
+# Test the convert 32bits to 16bits
+
+.*: file format .*
+
+
+Disassembly of section .text:
+0+0000 .*
+0+0002 .*
+0+0004 .*
+0+0006 .*
+0+0008 .*
+0+000a .*
+0+000c .*
+0+000e .*
+0+0010 .*
+0+0012 .*
+0+0014 .*
+0+0016 .*
+0+0018 .*
+0+001a .*
+0+001c .*
+0+001e .*
+0+0020 .*
+0+0022 .*
+0+0024 .*
+0+0026 .*
+0+0028 .*
+0+002a .*
+0+002c .*
+0+002e .*
+0+0030 .*
+0+0032 .*
+0+0034 .*
+0+0036 .*
+0+0038 .*
+0+003a .*
+0+003c .*
+0+003e .*
+0+0040 .*
+0+0042 .*
+0+0044 .*
+0+0046 .*
+0+0048 .*
+0+004a .*
+0+004c .*
+0+004e .*
+0+0050 .*
+0+0052 .*
+0+0054 .*
+0+0056 .*
+0+0058 .*
+0+005a .*
+0+005c .*
+0+005e .*
+0+0060 .*
+0+0062 .*
+0+0064 .*
+0+0066 .*
+0+0068 .*
+0+006a .*
+0+006c .*
+0+006e .*
+0+0070 .*
+0+0072 .*
+0+0074 .*
+0+0076 .*
+0+0078 .*
+0+007a .*
+0+007c .*
+0+007e .*
+0+0080 .*
+0+0082 .*
+0+0084 .*
+0+0086 .*
+0+0088 .*
diff --git a/gas/testsuite/gas/nds32/to-16bit-v1.s b/gas/testsuite/gas/nds32/to-16bit-v1.s
new file mode 100644
index 0000000..195463c
--- /dev/null
+++ b/gas/testsuite/gas/nds32/to-16bit-v1.s
@@ -0,0 +1,70 @@
+foo:
+ move $r0, $r0
+ move $sp, $sp
+ movi $r0, -16
+ movi $sp, 15
+ add $r0, $r0, $r0
+ add $r19, $sp, $r19
+ sub $r0, $r0, $r0
+ sub $r19, $r19, $sp
+ addi $r0, $r0, 0
+ addi $r19, $r19, 31
+ srai $r0, $r0, 0
+ srai $r19, $r19, 31
+ srli $r0, $r0, 0
+ srli $r19, $r19, 31
+ slli $r0, $r0, 0
+ slli $r7, $r7, 7
+ zeb $r0, $r0
+ zeb $r7, $r7
+ zeh $r0, $r0
+ zeh $r7, $r7
+ seb $r0, $r0
+ seb $r7, $r7
+ seh $r0, $r0
+ seh $r7, $r7
+ andi $r0, $r0, 1
+ andi $r7, $r7, 0x7ff
+ add $r0, $r0, $r0
+ add $r7, $r7, $r7
+ sub $r0, $r0, $r0
+ sub $r7, $r7, $r7
+ addi $r0, $r0, 0
+ addi $r7, $r7, 7
+ lwi $r0, [$r0 + 0]
+ lwi $r7, [$r7 + 28]
+ lwi.bi $r0, [$r0], 0
+ lwi.bi $r7, [$r7], 28
+ lhi $r0, [$r0 + 0]
+ lhi $r7, [$r7 + 14]
+ lbi $r0, [$r0 + 0]
+ lbi $r7, [$r7 + 7]
+ swi $r0, [$r0 + 0]
+ swi $r7, [$r7 + 28]
+ swi.bi $r0, [$r0], 0
+ swi.bi $r7, [$r7], 28
+ shi $r0, [$r0 + 0]
+ shi $r7, [$r7 + 14]
+ sbi $r0, [$r0 + 0]
+ sbi $r7, [$r7 + 7]
+ lwi $r0, [$r0 + 0]
+ lwi $r19, [$sp + 0]
+ swi $r0, [$r0 + 0]
+ swi $r19, [$sp + 0]
+ lwi $r0, [$fp + 0]
+ lwi $r7, [$fp + 508]
+ swi $r0, [$fp + 0]
+ swi $r7, [$fp + 508]
+ jr $r0
+ jr $sp
+ ret $r0
+ ret $sp
+ jral $r0
+ jral $sp
+ slts $r15, $r0, $r0
+ slts $r15, $r19, $sp
+ slt $r15, $r0, $r0
+ slt $r15, $r19, $sp
+ sltsi $r15, $r0, 0
+ sltsi $r15, $r19, 31
+ slti $r15, $r0, 0
diff --git a/gas/testsuite/gas/nds32/to-16bit-v2.d b/gas/testsuite/gas/nds32/to-16bit-v2.d
new file mode 100644
index 0000000..5ca929c
--- /dev/null
+++ b/gas/testsuite/gas/nds32/to-16bit-v2.d
@@ -0,0 +1,15 @@
+#objdump: -d --prefix-addresses
+#name: nds32 convert 32 to 16 (v2 instructions)
+#as: -Os -mno-reduced-regs
+
+# Test the convert 32bits to 16bits
+
+.*: file format .*
+
+
+Disassembly of section .text:
+0+0000 .*
+0+0002 .*
+0+0004 .*
+0+0006 .*
+0+0008 .*
diff --git a/gas/testsuite/gas/nds32/to-16bit-v2.s b/gas/testsuite/gas/nds32/to-16bit-v2.s
new file mode 100644
index 0000000..1ac3328
--- /dev/null
+++ b/gas/testsuite/gas/nds32/to-16bit-v2.s
@@ -0,0 +1,6 @@
+foo:
+addi $sp, $sp, -512
+addi $sp, $sp, 511
+lwi $r0, [$sp + 0]
+lwi $r7, [$sp + 508]
+swi $r0, [$sp + 0]
diff --git a/gas/testsuite/gas/nds32/to-16bit-v3.d b/gas/testsuite/gas/nds32/to-16bit-v3.d
new file mode 100644
index 0000000..2efa8b7
--- /dev/null
+++ b/gas/testsuite/gas/nds32/to-16bit-v3.d
@@ -0,0 +1,25 @@
+#objdump: -d --prefix-addresses
+#name: nds32 convert 32 to 16 (v3 instructions)
+#as: -Os -mno-reduced-regs
+
+# Test the convert 32bits to 16bits
+
+.*: file format .*
+
+
+Disassembly of section .text:
+0+0000 .*
+0+0002 .*
+0+0004 .*
+0+0006 .*
+0+0008 .*
+0+000a .*
+0+000c .*
+0+000e .*
+0+0010 .*
+0+0012 .*
+0+0014 .*
+0+0016 .*
+0+0018 .*
+0+001a .*
+0+001c .*
diff --git a/gas/testsuite/gas/nds32/to-16bit-v3.s b/gas/testsuite/gas/nds32/to-16bit-v3.s
new file mode 100644
index 0000000..595a782
--- /dev/null
+++ b/gas/testsuite/gas/nds32/to-16bit-v3.s
@@ -0,0 +1,16 @@
+foo:
+andi $r0, $r0, 1
+andi $r7, $r7, 255
+movi $r0, 16
+movi $r19, 47
+subri $r0, $r0, 0
+subri $r7, $r7, 0
+nor $r0, $r0, $r0
+nor $r7, $r7, $r7
+mul $r0, $r0, $r0
+mul $r7, $r7, $r7
+xor $r0, $r0, $r0
+xor $r7, $r7, $r7
+and $r0, $r0, $r0
+and $r7, $r7, $r7
+or $r0, $r0, $r0