diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index da140496355d90b4ee3de568c0cf2e32b653c274..83cbe6fd2e546bdf40a5d92e6dd7bb881527f3a3 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,20 @@
+2016-02-02  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+	* cgen-ibld.in (insert_normal): Rework calculation of shift.
+	* epiphany-ibld.c: Regenerate.
+	* fr30-ibld.c: Regenerate.
+	* frv-ibld.c: Regenerate.
+	* ip2k-ibld.c: Regenerate.
+	* iq2000-ibld.c: Regenerate.
+	* lm32-ibld.c: Regenerate.
+	* m32c-ibld.c: Regenerate.
+	* m32r-ibld.c: Regenerate.
+	* mep-ibld.c: Regenerate.
+	* mt-ibld.c: Regenerate.
+	* or1k-ibld.c: Regenerate.
+	* xc16x-ibld.c: Regenerate.
+	* xstormy16-ibld.c: Regenerate.
+
 2016-02-02  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* epiphany-dis.c: Regenerated from latest cpu files.
diff --git a/opcodes/cgen-ibld.in b/opcodes/cgen-ibld.in
index 4730ff4ff6c9ed184f89ff9bd0e25af5ca806c2f..cd6fffa5aee8c029454e51b9f4008d58fae0ae25 100644
--- a/opcodes/cgen-ibld.in
+++ b/opcodes/cgen-ibld.in
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/epiphany-ibld.c b/opcodes/epiphany-ibld.c
index c412169f4af7e2107cb5e29157ab7620e794f472..f978d4682ffda995b2496654100d4e4db23a8d41 100644
--- a/opcodes/epiphany-ibld.c
+++ b/opcodes/epiphany-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/fr30-ibld.c b/opcodes/fr30-ibld.c
index 12b17335ba86096ee67b69c3591772109bb95267..1293e73ba29c5563fe09bc48ab05377d296a8806 100644
--- a/opcodes/fr30-ibld.c
+++ b/opcodes/fr30-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/frv-ibld.c b/opcodes/frv-ibld.c
index bbcec67b3e69805ed94713848e411fcb7ff9375a..dba36aa60420ba778ef5f657eddf54bd2574463f 100644
--- a/opcodes/frv-ibld.c
+++ b/opcodes/frv-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/ip2k-ibld.c b/opcodes/ip2k-ibld.c
index a46e34d7be3dafce2ed018a606ffd92fdf2a695e..fa6a736b060d1a0a7caa34e7f2b582cd2c11ac14 100644
--- a/opcodes/ip2k-ibld.c
+++ b/opcodes/ip2k-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/iq2000-ibld.c b/opcodes/iq2000-ibld.c
index 74aa4da16a9c4bfd12b25f7b070b7ed9a5bea118..96faa3847a073f32ef5132ad27e41aeaab0d540f 100644
--- a/opcodes/iq2000-ibld.c
+++ b/opcodes/iq2000-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/lm32-ibld.c b/opcodes/lm32-ibld.c
index 6a923c7a2f034ccac28c56b3fa9f852f9c00a733..784acc02be43343e0c1b2243d1a519e876bf00d1 100644
--- a/opcodes/lm32-ibld.c
+++ b/opcodes/lm32-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/m32c-ibld.c b/opcodes/m32c-ibld.c
index b93de263f62a68a67c25ca45e7e9ea5ccc0be2a9..7066bbf2ae035cd69ec26da9e1b591a79236a45e 100644
--- a/opcodes/m32c-ibld.c
+++ b/opcodes/m32c-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/m32r-ibld.c b/opcodes/m32r-ibld.c
index a1bbcef8bcd8589b046e50db2bd2b6912e2fbe0a..2b9e93a90101a32eee0506582f2717c79b74a551 100644
--- a/opcodes/m32r-ibld.c
+++ b/opcodes/m32r-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/mep-ibld.c b/opcodes/mep-ibld.c
index d1e33fa730f728241b6ef562fd06a9795597046e..0faf9481d9de4ce444cdff61ddf01d571ef0a1a5 100644
--- a/opcodes/mep-ibld.c
+++ b/opcodes/mep-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/mt-ibld.c b/opcodes/mt-ibld.c
index ffc7910d6ee4e02b7f8572e6f966884445ff17ed..c678e996953e8c08645b901b0846489017df7fb0 100644
--- a/opcodes/mt-ibld.c
+++ b/opcodes/mt-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/or1k-ibld.c b/opcodes/or1k-ibld.c
index 040bd00bacb9f19f636249bd949d307f6067f6e4..b934ce1b9fcd25796e1baf872025f9b2d566e74a 100644
--- a/opcodes/or1k-ibld.c
+++ b/opcodes/or1k-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/xc16x-ibld.c b/opcodes/xc16x-ibld.c
index 3deb3b0241f59ec70a4f7edbbe9c4404d49c8667..43c7a160e2339f6ae69b2a911220dad10e4141ee 100644
--- a/opcodes/xc16x-ibld.c
+++ b/opcodes/xc16x-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }
 
diff --git a/opcodes/xstormy16-ibld.c b/opcodes/xstormy16-ibld.c
index 4d963945c85a622eb69beff45a4697a08200593f..2d05229ba661bc6596f4289d6fcc5f6b88c382f3 100644
--- a/opcodes/xstormy16-ibld.c
+++ b/opcodes/xstormy16-ibld.c
@@ -207,12 +207,19 @@ insert_normal (CGEN_CPU_DESC cd,
 #if CGEN_INT_INSN_P
 
   {
-    int shift;
+    int shift_within_word, shift_to_word, shift;
 
+    /* How to shift the value to BIT0 of the word.  */
+    shift_to_word = total_length - (word_offset + word_length);
+
+    /* How to shift the value to the field within the word.  */
     if (CGEN_INSN_LSB0_P)
-      shift = (word_offset + start + 1) - length;
+      shift_within_word = start + 1 - length;
     else
-      shift = total_length - (word_offset + start + length);
+      shift_within_word = word_length - start - length;
+
+    /* The total SHIFT, then mask in the value.  */
+    shift = shift_to_word + shift_within_word;
     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
   }