arc/nps400 : New cmem instructions and associated relocation
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 29 Mar 2016 23:02:19 +0000 (00:02 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 14 Apr 2016 16:16:46 +0000 (17:16 +0100)
Add support for arc/nps400 cmem instructions, these load and store
instructions are hard-wired to access "0x57f00000 + 16-bit-offset".

Supporting this relocation required some additions to the arc relocation
handling in the bfd library, as well as the standard changes required to
add a new relocation type.

There's a test of the new instructions in the assembler, and a test of
the relocation in the linker.

bfd/ChangeLog:

* reloc.c: Add BFD_RELOC_ARC_NPS_CMEM16 entry.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elf32-arc.c: Add 'opcode/arc.h' include.
(struct arc_relocation_data): Add symbol_name.
(arc_special_overflow_checks): New function.
(arc_do_relocation): Use arc_special_overflow_checks, reindent as
required, add an extra comment.
(elf_arc_relocate_section): Setup symbol_name in reloc_data.

gas/ChangeLog:

* testsuite/gas/arc/nps400-3.d: New file.
* testsuite/gas/arc/nps400-3.s: New file.

include/ChangeLog:

* elf/arc-reloc.def: Add ARC_NPS_CMEM16 reloc.
* opcode/arc.h (NPS_CMEM_HIGH_VALUE): Define.

ld/ChangeLog:

* testsuite/ld-arc/arc.exp: New file.
* testsuite/ld-arc/nps-1.s: New file.
* testsuite/ld-arc/nps-1a.d: New file.
* testsuite/ld-arc/nps-1b.d: New file.
* testsuite/ld-arc/nps-1b.err: New file.

opcodes/ChangeLog:

* arc-nps400-tbl.h: Add xldb, xldw, xld, xstb, xstw, and xst
instructions.
* arc-opc.c (insert_nps_cmem_uimm16): New function.
(extract_nps_cmem_uimm16): New function.
(arc_operands): Add NPS_XLDST_UIMM16 operand.

20 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-arc.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/testsuite/gas/arc/nps400-3.d [new file with mode: 0644]
gas/testsuite/gas/arc/nps400-3.s [new file with mode: 0644]
include/ChangeLog
include/elf/arc-reloc.def
include/opcode/arc.h
ld/ChangeLog
ld/testsuite/ld-arc/arc.exp [new file with mode: 0644]
ld/testsuite/ld-arc/nps-1.s [new file with mode: 0644]
ld/testsuite/ld-arc/nps-1a.d [new file with mode: 0644]
ld/testsuite/ld-arc/nps-1b.d [new file with mode: 0644]
ld/testsuite/ld-arc/nps-1b.err [new file with mode: 0644]
opcodes/ChangeLog
opcodes/arc-nps400-tbl.h
opcodes/arc-opc.c

index 3d04690..eb702c2 100644 (file)
@@ -1,5 +1,17 @@
 2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+       * reloc.c: Add BFD_RELOC_ARC_NPS_CMEM16 entry.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Regenerate.
+       * elf32-arc.c: Add 'opcode/arc.h' include.
+       (struct arc_relocation_data): Add symbol_name.
+       (arc_special_overflow_checks): New function.
+       (arc_do_relocation): Use arc_special_overflow_checks, reindent as
+       required, add an extra comment.
+       (elf_arc_relocate_section): Setup symbol_name in reloc_data.
+
+2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
+
        * elf32-arc.c (tls_got_entries): Add 'TLS_GOT_' prefix to all
        entries.
        (elf_arc_relocate_section): Update enum uses.
index f02e2aa..6532f6e 100644 (file)
@@ -3721,6 +3721,7 @@ pc-relative or some form of GOT-indirect relocation.  */
   BFD_RELOC_ARC_TLS_LE_32,
   BFD_RELOC_ARC_S25W_PCREL_PLT,
   BFD_RELOC_ARC_S21H_PCREL_PLT,
+  BFD_RELOC_ARC_NPS_CMEM16,
 
 /* ADI Blackfin 16 bit immediate absolute reloc.  */
   BFD_RELOC_BFIN_16_IMM,
index d67e88c..2df91b1 100644 (file)
@@ -26,6 +26,7 @@
 #include "elf/arc.h"
 #include "libiberty.h"
 #include "opcode/arc-func.h"
+#include "opcode/arc.h"
 #include "arc-plt.h"
 
 #ifdef DEBUG
@@ -722,6 +723,8 @@ struct arc_relocation_data
   bfd_signed_vma  got_symbol_vma;
 
   bfd_boolean    should_relocate;
+
+  const char *    symbol_name;
 };
 
 static void
@@ -788,6 +791,52 @@ middle_endian_convert (bfd_vma insn, bfd_boolean do_it)
   return insn;
 }
 
+/* This function is called for relocations that are otherwise marked as NOT
+   requiring overflow checks.  In here we perform non-standard checks of
+   the relocation value.  */
+
+static inline bfd_reloc_status_type
+arc_special_overflow_checks (const struct arc_relocation_data reloc_data,
+                             bfd_signed_vma relocation,
+                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  switch (reloc_data.howto->type)
+    {
+    case R_ARC_NPS_CMEM16:
+      if (((relocation >> 16) & 0xffff) != NPS_CMEM_HIGH_VALUE)
+        {
+          if (reloc_data.reloc_addend == 0)
+            (*_bfd_error_handler)
+              (_("%B(%A+0x%lx): CMEM relocation to `%s' is invalid, "
+                 "16 MSB should be 0x%04x (value is 0x%lx)"),
+               reloc_data.input_section->owner,
+               reloc_data.input_section,
+               reloc_data.reloc_offset,
+               reloc_data.symbol_name,
+               NPS_CMEM_HIGH_VALUE,
+               (relocation));
+          else
+            (*_bfd_error_handler)
+              (_("%B(%A+0x%lx): CMEM relocation to `%s+0x%lx' is invalid, "
+                 "16 MSB should be 0x%04x (value is 0x%lx)"),
+               reloc_data.input_section->owner,
+               reloc_data.input_section,
+               reloc_data.reloc_offset,
+               reloc_data.symbol_name,
+               reloc_data.reloc_addend,
+               NPS_CMEM_HIGH_VALUE,
+               (relocation));
+          return bfd_reloc_overflow;
+        }
+      break;
+
+    default:
+      break;
+    }
+
+  return bfd_reloc_ok;
+}
+
 #define ME(reloc) (reloc)
 
 #define IS_ME(FORMULA,BFD) ((strstr (FORMULA, "ME") != NULL) \
@@ -896,6 +945,7 @@ arc_do_relocation (bfd_byte * contents,
   bfd_vma orig_insn ATTRIBUTE_UNUSED;
   bfd * abfd = reloc_data.input_section->owner;
   struct elf_link_hash_table *htab ATTRIBUTE_UNUSED = elf_hash_table (info);
+  bfd_reloc_status_type flag;
 
   if (reloc_data.should_relocate == FALSE)
     return bfd_reloc_ok;
@@ -936,34 +986,34 @@ arc_do_relocation (bfd_byte * contents,
 
   /* Check for relocation overflow.  */
   if (reloc_data.howto->complain_on_overflow != complain_overflow_dont)
-    {
-      bfd_reloc_status_type flag;
-      flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow,
-                                reloc_data.howto->bitsize,
-                                reloc_data.howto->rightshift,
-                                bfd_arch_bits_per_address (abfd),
-                                relocation);
+    flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow,
+                               reloc_data.howto->bitsize,
+                               reloc_data.howto->rightshift,
+                               bfd_arch_bits_per_address (abfd),
+                               relocation);
+  else
+    flag = arc_special_overflow_checks (reloc_data, relocation, info);
 
 #undef  DEBUG_ARC_RELOC
 #define DEBUG_ARC_RELOC(A) debug_arc_reloc (A)
-      if (flag != bfd_reloc_ok)
-       {
-         PR_DEBUG ( "Relocation overflows !!!!\n");
+  if (flag != bfd_reloc_ok)
+    {
+      PR_DEBUG ( "Relocation overflows !!!!\n");
 
-         DEBUG_ARC_RELOC (reloc_data);
+      DEBUG_ARC_RELOC (reloc_data);
 
-         PR_DEBUG (
-                 "Relocation value = signed -> %d, unsigned -> %u"
-                 ", hex -> (0x%08x)\n",
-                 (int) relocation,
-                 (unsigned int) relocation,
-                 (unsigned int) relocation);
-         return flag;
-       }
+      PR_DEBUG (
+                "Relocation value = signed -> %d, unsigned -> %u"
+                ", hex -> (0x%08x)\n",
+                (int) relocation,
+                (unsigned int) relocation,
+                (unsigned int) relocation);
+      return flag;
     }
 #undef  DEBUG_ARC_RELOC
 #define DEBUG_ARC_RELOC(A)
 
+  /* Write updated instruction back to memory.  */
   switch (reloc_data.howto->size)
     {
       case 2:
@@ -1168,6 +1218,10 @@ elf_arc_relocate_section (bfd *             output_bfd,
 
          reloc_data.sym_value = sym->st_value;
          reloc_data.sym_section = sec;
+         reloc_data.symbol_name =
+            bfd_elf_string_from_elf_section (input_bfd,
+                                             symtab_hdr->sh_link,
+                                             sym->st_name);
 
          /* Mergeable section handling.  */
          if ((sec->flags & SEC_MERGE)
@@ -1284,6 +1338,7 @@ elf_arc_relocate_section (bfd *              output_bfd,
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
          BFD_ASSERT ((h->dynindx == -1) >= (h->forced_local != 0));
+         reloc_data.symbol_name = h->root.root.string;
          /* If we have encountered a definition for this symbol.  */
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
index d7183d3..16c0aee 100644 (file)
@@ -1738,6 +1738,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_ARC_TLS_LE_32",
   "BFD_RELOC_ARC_S25W_PCREL_PLT",
   "BFD_RELOC_ARC_S21H_PCREL_PLT",
+  "BFD_RELOC_ARC_NPS_CMEM16",
   "BFD_RELOC_BFIN_16_IMM",
   "BFD_RELOC_BFIN_16_HIGH",
   "BFD_RELOC_BFIN_4_PCREL",
index 0135c04..c3b713b 100644 (file)
@@ -3668,6 +3668,8 @@ ENUMX
   BFD_RELOC_ARC_S25W_PCREL_PLT
 ENUMX
   BFD_RELOC_ARC_S21H_PCREL_PLT
+ENUMX
+  BFD_RELOC_ARC_NPS_CMEM16
 ENUMDOC
   ARC relocs.
 
index c9ea846..f95cd7a 100644 (file)
@@ -1,5 +1,10 @@
 2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+       * testsuite/gas/arc/nps400-3.d: New file.
+       * testsuite/gas/arc/nps400-3.s: New file.
+
+2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
+
        * testsuite/gas/arc/add_s-err.s: Update target pattern.
        * testsuite/gas/arc/warn.s: Likewise.
        * testsuite/gas/elf/elf.exp: Run test for arc.
diff --git a/gas/testsuite/gas/arc/nps400-3.d b/gas/testsuite/gas/arc/nps400-3.d
new file mode 100644 (file)
index 0000000..ea52554
--- /dev/null
@@ -0,0 +1,56 @@
+#as: -mcpu=nps400
+#objdump: -dr
+
+.*: +file format .*arc.*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.*>:
+   0:  5988 0000               xldb    r12,\[0x57f00000\]
+   4:  5ae8 ffff               xldb    r23,\[0x57f0ffff\]
+   8:  5868 0000               xldb    r3,\[0x57f00000\]
+   c:  5968 ffff               xldb    r11,\[0x57f0ffff\]
+  10:  5a88 0000               xldb    r20,\[0x57f00000\]
+                       10: R_ARC_NPS_CMEM16    foo
+  14:  5828 0000               xldb    r1,\[0x57f00000\]
+                       14: R_ARC_NPS_CMEM16    foo\+0x20
+  18:  5989 0000               xldw    r12,\[0x57f00000\]
+  1c:  5ae9 ffff               xldw    r23,\[0x57f0ffff\]
+  20:  5869 0000               xldw    r3,\[0x57f00000\]
+  24:  5969 ffff               xldw    r11,\[0x57f0ffff\]
+  28:  5a89 0000               xldw    r20,\[0x57f00000\]
+                       28: R_ARC_NPS_CMEM16    foo
+  2c:  5829 0000               xldw    r1,\[0x57f00000\]
+                       2c: R_ARC_NPS_CMEM16    foo\+0x20
+  30:  598a 0000               xld     r12,\[0x57f00000\]
+  34:  5aea ffff               xld     r23,\[0x57f0ffff\]
+  38:  586a 0000               xld     r3,\[0x57f00000\]
+  3c:  596a ffff               xld     r11,\[0x57f0ffff\]
+  40:  5a8a 0000               xld     r20,\[0x57f00000\]
+                       40: R_ARC_NPS_CMEM16    foo
+  44:  582a 0000               xld     r1,\[0x57f00000\]
+                       44: R_ARC_NPS_CMEM16    foo\+0x20
+  48:  598c 0000               xstb    r12,\[0x57f00000\]
+  4c:  5aec ffff               xstb    r23,\[0x57f0ffff\]
+  50:  586c 0000               xstb    r3,\[0x57f00000\]
+  54:  596c ffff               xstb    r11,\[0x57f0ffff\]
+  58:  5a8c 0000               xstb    r20,\[0x57f00000\]
+                       58: R_ARC_NPS_CMEM16    foo
+  5c:  582c 0000               xstb    r1,\[0x57f00000\]
+                       5c: R_ARC_NPS_CMEM16    foo\+0x20
+  60:  598d 0000               xstw    r12,\[0x57f00000\]
+  64:  5aed ffff               xstw    r23,\[0x57f0ffff\]
+  68:  586d 0000               xstw    r3,\[0x57f00000\]
+  6c:  596d ffff               xstw    r11,\[0x57f0ffff\]
+  70:  5a8d 0000               xstw    r20,\[0x57f00000\]
+                       70: R_ARC_NPS_CMEM16    foo
+  74:  582d 0000               xstw    r1,\[0x57f00000\]
+                       74: R_ARC_NPS_CMEM16    foo\+0x20
+  78:  598e 0000               xst     r12,\[0x57f00000\]
+  7c:  5aee ffff               xst     r23,\[0x57f0ffff\]
+  80:  586e 0000               xst     r3,\[0x57f00000\]
+  84:  596e ffff               xst     r11,\[0x57f0ffff\]
+  88:  5a8e 0000               xst     r20,\[0x57f00000\]
+                       88: R_ARC_NPS_CMEM16    foo
+  8c:  582e 0000               xst     r1,\[0x57f00000\]
+                       8c: R_ARC_NPS_CMEM16    foo\+0x20
diff --git a/gas/testsuite/gas/arc/nps400-3.s b/gas/testsuite/gas/arc/nps400-3.s
new file mode 100644 (file)
index 0000000..6840223
--- /dev/null
@@ -0,0 +1,23 @@
+        .macro  xldst_test mnem
+        \mnem r12, [ 0x0 ]
+        \mnem r23, [ 0xffff ]
+        \mnem r3, [ 0x57f00000 ]
+        \mnem r11, [ 0x57f0ffff ]
+        \mnem r20, [ foo ]
+        \mnem r1, [ foo + 0x20 ]
+        .endm
+
+        .text
+        ;; xldb
+        xldst_test xldb
+        ;; xldw
+        xldst_test xldw
+        ;; xld
+        xldst_test xld
+        ;; xstb
+        xldst_test xstb
+        ;; xstw
+        xldst_test xstw
+        ;; xst
+        xldst_test xst
+
index c7ac36b..8c16d79 100644 (file)
@@ -1,3 +1,8 @@
+2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * elf/arc-reloc.def: Add ARC_NPS_CMEM16 reloc.
+       * opcode/arc.h (NPS_CMEM_HIGH_VALUE): Define.
+
 2016-04-12  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * opcode/arc.h (flag_class_t): Update.
index 36a3516..10703d2 100644 (file)
@@ -490,3 +490,10 @@ ARC_RELOC_HOWTO(ARC_S21H_PCREL_PLT, 77, \
                 replace_disp21h, \
                 signed, \
                 ( ME ( ( ( ( L + A ) - P ) >> 1 ) ) ))
+
+ARC_RELOC_HOWTO(ARC_NPS_CMEM16, 78, \
+                2, \
+                16, \
+                replace_bits16, \
+                dont, \
+                ( S + A ))
index 7cd78e4..2811877 100644 (file)
@@ -437,6 +437,9 @@ extern const unsigned arc_num_aux_regs;
 extern const struct arc_opcode arc_relax_opcodes[];
 extern const unsigned arc_num_relax_opcodes;
 
+/* Macro used for generating one class of NPS instructions.  */
+#define NPS_CMEM_HIGH_VALUE 0x57f0
+
 /* Macros to help generating regular pattern instructions.  */
 #define FIELDA(word) (word & 0x3F)
 #define FIELDB(word) (((word & 0x07) << 24) | (((word >> 3) & 0x07) << 12))
index 4458f99..ea4d20d 100644 (file)
@@ -1,3 +1,11 @@
+2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * testsuite/ld-arc/arc.exp: New file.
+       * testsuite/ld-arc/nps-1.s: New file.
+       * testsuite/ld-arc/nps-1a.d: New file.
+       * testsuite/ld-arc/nps-1b.d: New file.
+       * testsuite/ld-arc/nps-1b.err: New file.
+
 2016-04-14  Nick Clifton  <nickc@redhat.com>
 
        PR 19457
diff --git a/ld/testsuite/ld-arc/arc.exp b/ld/testsuite/ld-arc/arc.exp
new file mode 100644 (file)
index 0000000..0cf6228
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright (C) 2016 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if { ![istarget arc*-*-*] } {
+    return
+}
+
+set arc_test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach arc_test $arc_test_list {
+    verbose [file rootname $arc_test]
+    run_dump_test [file rootname $arc_test]
+}
+
diff --git a/ld/testsuite/ld-arc/nps-1.s b/ld/testsuite/ld-arc/nps-1.s
new file mode 100644 (file)
index 0000000..295fa2c
--- /dev/null
@@ -0,0 +1,10 @@
+        .text
+        .global __start
+__start:
+        xldb r10, [ foo ]
+        xldw r10, [ foo ]
+        xld r10, [ foo ]
+        xstb r10, [ foo ]
+        xstw r10, [ foo ]
+        xst r10, [ foo ]
+
diff --git a/ld/testsuite/ld-arc/nps-1a.d b/ld/testsuite/ld-arc/nps-1a.d
new file mode 100644 (file)
index 0000000..120c71c
--- /dev/null
@@ -0,0 +1,16 @@
+#source: nps-1.s
+#as: -mcpu=nps400
+#ld: -defsym=foo=0x57f03000
+#objdump: -d
+
+.*: +file format .*arc.*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+:   5948 3000               xldb    r10,\[0x57f03000\]
+ *[0-9a-f]+:   5949 3000               xldw    r10,\[0x57f03000\]
+ *[0-9a-f]+:   594a 3000               xld     r10,\[0x57f03000\]
+ *[0-9a-f]+:   594c 3000               xstb    r10,\[0x57f03000\]
+ *[0-9a-f]+:   594d 3000               xstw    r10,\[0x57f03000\]
+ *[0-9a-f]+:   594e 3000               xst     r10,\[0x57f03000\]
diff --git a/ld/testsuite/ld-arc/nps-1b.d b/ld/testsuite/ld-arc/nps-1b.d
new file mode 100644 (file)
index 0000000..56c29ae
--- /dev/null
@@ -0,0 +1,4 @@
+#source: nps-1.s
+#as: -mcpu=nps400
+#ld: -defsym=foo=0x56f03000
+#error_output: nps-1b.err
diff --git a/ld/testsuite/ld-arc/nps-1b.err b/ld/testsuite/ld-arc/nps-1b.err
new file mode 100644 (file)
index 0000000..a44b3c1
--- /dev/null
@@ -0,0 +1 @@
+.*\.o\(\.text\+0x0\): CMEM relocation to `foo' is invalid, 16 MSB should be 0x57f0 \(value is 0x56f03000\)
index 7744f67..c9ff573 100644 (file)
@@ -1,5 +1,13 @@
 2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
 
+       * arc-nps400-tbl.h: Add xldb, xldw, xld, xstb, xstw, and xst
+       instructions.
+       * arc-opc.c (insert_nps_cmem_uimm16): New function.
+       (extract_nps_cmem_uimm16): New function.
+       (arc_operands): Add NPS_XLDST_UIMM16 operand.
+
+2016-04-14  Andrew Burgess  <andrew.burgess@embecosm.com>
+
        * arc-dis.c (arc_insn_length): New function.
        (print_insn_arc): Use arc_insn_length, change insnLen to unsigned.
        (find_format): Change insnLen parameter to unsigned.
index 58d479f..832d2ff 100644 (file)
 
 /* hwscd.restore 0,C */
 { "hwschd", 0x3e6f7003, 0xfffff03f, ARC_OPCODE_NPS400, CONTROL, NONE, { ZA, RC }, { C_NPS_HWS_RESTORE }},
+
+/****      Load / Store From (0x57f00000 + Offset) Instructions       ****/
+
+#define XLDST_LIKE(NAME,SUBOP2)                                          \
+  { NAME, (0x58000000 | (SUBOP2 << 16)), 0xf81f0000, ARC_OPCODE_NPS400, MEMORY, NONE, { NPS_R_DST, BRAKET, NPS_XLDST_UIMM16, BRAKETdup }, { 0 }},
+
+XLDST_LIKE("xldb", 0x8)
+XLDST_LIKE("xldw", 0x9)
+XLDST_LIKE("xld", 0xa)
+XLDST_LIKE("xstb", 0xc)
+XLDST_LIKE("xstw", 0xd)
+XLDST_LIKE("xst", 0xe)
index 5603ded..2ce8853 100644 (file)
@@ -838,6 +838,25 @@ extract_nps_dst_pos_and_size (unsigned insn ATTRIBUTE_UNUSED,
   return (insn & 0x1f);
 }
 
+static unsigned
+insert_nps_cmem_uimm16 (unsigned insn ATTRIBUTE_UNUSED,
+                        int value ATTRIBUTE_UNUSED,
+                        const char **errmsg ATTRIBUTE_UNUSED)
+{
+  int top = (value >> 16) & 0xffff;
+  if (top != 0x0 && top != NPS_CMEM_HIGH_VALUE)
+    *errmsg = _("invalid value for CMEM ld/st immediate");
+  insn |= (value & 0xffff);
+  return insn;
+}
+
+static int
+extract_nps_cmem_uimm16 (unsigned insn ATTRIBUTE_UNUSED,
+                         bfd_boolean * invalid ATTRIBUTE_UNUSED)
+{
+  return (NPS_CMEM_HIGH_VALUE << 16) | (insn & 0xffff);
+}
+
 /* Include the generic extract/insert functions.  Order is important
    as some of the functions present in the .h may be disabled via
    defines.  */
@@ -1498,6 +1517,9 @@ const struct arc_operand arc_operands[] =
 
 #define NPS_RFLT_UIMM6         (NPS_UIMM16 + 1)
   { 6, 6, 0, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, insert_nps_rflt_uimm6, extract_nps_rflt_uimm6 },
+
+#define NPS_XLDST_UIMM16       (NPS_RFLT_UIMM6 + 1)
+  { 16, 0, BFD_RELOC_ARC_NPS_CMEM16, ARC_OPERAND_UNSIGNED | ARC_OPERAND_NCHK, insert_nps_cmem_uimm16, extract_nps_cmem_uimm16 },
 };
 
 const unsigned arc_num_operands = ARRAY_SIZE (arc_operands);