From 65677ff251b88389b3de4837f57215dc088dd716 Mon Sep 17 00:00:00 2001
From: Mahesh Bodapati <mbodapat@xilinx.com>
Date: Mon, 26 Aug 2019 15:29:42 +0530
Subject: [PATCH 26/38] [Patch,MicroBlaze] : double imml generation for 64 bit
 values.

Conflicts:
	gas/config/tc-microblaze.c
---
 gas/config/tc-microblaze.c | 321 ++++++++++++++++++++++++++++++-------
 opcodes/microblaze-opc.h   |   4 +-
 2 files changed, 262 insertions(+), 63 deletions(-)

diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
index 1a543c328f2..18dd8524949 100644
--- a/gas/config/tc-microblaze.c
+++ b/gas/config/tc-microblaze.c
@@ -1008,7 +1008,7 @@ md_assemble (char * str)
   char * op_start;
   char * op_end;
   char * temp_op_end;
-  struct op_code_struct * opcode, *opcode1;
+  struct op_code_struct * opcode, *opcode1, *opcode2;
   char * output = NULL;
   int nlen = 0;
   int i;
@@ -1192,7 +1192,12 @@ md_assemble (char * str)
           reg2 = 0;
         }
       if (strcmp (op_end, ""))
+        {
+        if(microblaze_arch_size == 64)
+        op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
+	else
 	op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
+	}
       else
 	as_fatal (_("Error in statement syntax"));
 
@@ -1292,26 +1297,51 @@ md_assemble (char * str)
 		|| streq (name, "lwi") || streq (name, "sbi")
                 || streq (name, "shi") || streq (name, "swi"))))
         {
-          temp = immed & 0xFFFFFF8000;
-          if (temp != 0 && temp != 0xFFFFFF8000)
+          temp = ((long long)immed) & 0xFFFFFFFFFFFF8000;
+          if (temp != 0 && temp != 0xFFFFFFFFFFFF8000)
             {
               /* Needs an immediate inst.  */
-	      opcode1
-		= (struct op_code_struct *) str_hash_find (opcode_hash_control,
-							   "imml");
-              if (opcode1 == NULL)
+	   if (((long long)immed) > (long long)-549755813888 && ((long long)immed) < (long long)549755813887)
+	     {
+             opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+             if (opcode1 == NULL)
                 {
                   as_bad (_("unknown opcode \"%s\""), "imml");
                   return;
                 }
               inst1 = opcode1->bit_sequence;
-	      inst1 |= ((immed & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
+              inst1 |= ((immed & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
               output[0] = INST_BYTE0 (inst1);
               output[1] = INST_BYTE1 (inst1);
               output[2] = INST_BYTE2 (inst1);
               output[3] = INST_BYTE3 (inst1);
               output = frag_more (isize);
             }
+	  else 
+           {
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+              if (opcode1 == NULL || opcode2 == NULL)
+                {
+                  as_bad (_("unknown opcode \"%s\""), "imml");
+                  return;
+                }
+              inst1 = opcode2->bit_sequence;
+              inst1 |= ((immed & 0xFFFFFF0000000000L) >> 40) & IMML_MASK;
+              output[0] = INST_BYTE0 (inst1);
+              output[1] = INST_BYTE1 (inst1);
+              output[2] = INST_BYTE2 (inst1);
+              output[3] = INST_BYTE3 (inst1);
+              output = frag_more (isize);
+              inst1 = opcode1->bit_sequence;
+              inst1 |= ((immed & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+              output[0] = INST_BYTE0 (inst1);
+              output[1] = INST_BYTE1 (inst1);
+              output[2] = INST_BYTE2 (inst1);
+              output[3] = INST_BYTE3 (inst1);
+              output = frag_more (isize);
+            }
+	  }
           inst |= (reg1 << RD_LOW) & RD_MASK;
           inst |= (reg2 << RA_LOW) & RA_MASK;
           inst |= (immed << IMM_LOW) & IMM_MASK;
@@ -1328,8 +1358,7 @@ md_assemble (char * str)
                    as_bad (_("unknown opcode \"%s\""), "imm");
                    return;
                  }
-
-               inst1 = opcode1->bit_sequence;
+	       inst1 = opcode1->bit_sequence;
                inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
                output[0] = INST_BYTE0 (inst1);
                output[1] = INST_BYTE1 (inst1);
@@ -1570,7 +1599,7 @@ md_assemble (char * str)
         as_fatal (_("Cannot use special register with this instruction"));
 
       if (exp.X_op != O_constant)
-        as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions"));
+        as_fatal (_("Symbol used as immediate value for arithmetic long instructions"));
       else
 	{
           output = frag_more (isize);
@@ -1904,6 +1933,7 @@ md_assemble (char * str)
       temp = immed & 0xFFFF8000;
       if ((temp != 0) && (temp != 0xFFFF8000))
 	{
+
           /* Needs an immediate inst.  */
 	  opcode1
 	    = (struct op_code_struct *) str_hash_find (opcode_hash_control,
@@ -1936,7 +1966,12 @@ md_assemble (char * str)
           reg1 = 0;
         }
       if (strcmp (op_end, ""))
+      {
+        if(microblaze_arch_size == 64)
+        op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
+        else
         op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
+      }
       else
         as_fatal (_("Error in statement syntax"));
 
@@ -1975,30 +2010,55 @@ md_assemble (char * str)
         }
       if (streq (name, "brealid") || streq (name, "breaid") || streq (name, "breai"))
         {
-          temp = immed & 0xFFFFFF8000;
-          if (temp != 0 && temp != 0xFFFFFF8000)
+          temp = ((long long)immed) & 0xFFFFFFFFFFFF8000;
+          if (temp != 0 && temp != 0xFFFFFFFFFFFF8000)
             {
               /* Needs an immediate inst.  */
-              opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           if (((long long)immed) > (long long)-549755813888 && ((long long)immed) < (long long)549755813887)
+	    {
+            opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
               if (opcode1 == NULL)
                 {
                   as_bad (_("unknown opcode \"%s\""), "imml");
                   return;
                 }
               inst1 = opcode1->bit_sequence;
-	      inst1 |= ((immed & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
+              inst1 |= ((immed & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
               output[0] = INST_BYTE0 (inst1);
               output[1] = INST_BYTE1 (inst1);
               output[2] = INST_BYTE2 (inst1);
               output[3] = INST_BYTE3 (inst1);
               output = frag_more (isize);
             }
+          else {
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+              if (opcode1 == NULL || opcode2 == NULL)
+                {
+                  as_bad (_("unknown opcode \"%s\""), "imml");
+                  return;
+                }
+              inst1 = opcode2->bit_sequence;
+              inst1 |= ((immed & 0xFFFFFF0000000000L) >> 40) & IMML_MASK;
+              output[0] = INST_BYTE0 (inst1);
+              output[1] = INST_BYTE1 (inst1);
+              output[2] = INST_BYTE2 (inst1);
+              output[3] = INST_BYTE3 (inst1);
+              output = frag_more (isize);
+              inst1 = opcode1->bit_sequence;
+              inst1 |= ((immed & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+              output[0] = INST_BYTE0 (inst1);
+              output[1] = INST_BYTE1 (inst1);
+              output[2] = INST_BYTE2 (inst1);
+              output[3] = INST_BYTE3 (inst1);
+              output = frag_more (isize);
+          }
+	  }
       	  inst |= (reg1 << RD_LOW) & RD_MASK;
           inst |= (immed << IMM_LOW) & IMM_MASK;
          }
        else 
 	 {
-
       temp = immed & 0xFFFF8000;
       if ((temp != 0) && (temp != 0xFFFF8000))
 	{
@@ -2086,24 +2146,50 @@ md_assemble (char * str)
             streq (name, "breaid") || 
 	    streq (name, "brai") || streq (name, "braid")))
         {
-          temp = immed & 0xFFFFFF8000;
+          temp = immed & 0xFFFFFFFFFFFF8000;
           if (temp != 0)
 	    {
               /* Needs an immediate inst.  */
-              opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+	  if (((long long)immed) > (long long)-549755813888 && ((long long)immed) < (long long)549755813887)
+	   {
+            opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
               if (opcode1 == NULL)
                 {
                   as_bad (_("unknown opcode \"%s\""), "imml");
                   return;
                 }
               inst1 = opcode1->bit_sequence;
-              inst1 |= ((immed & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
+              inst1 |= ((immed & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
               output[0] = INST_BYTE0 (inst1);
               output[1] = INST_BYTE1 (inst1);
               output[2] = INST_BYTE2 (inst1);
               output[3] = INST_BYTE3 (inst1);
               output = frag_more (isize);
             }
+           else {
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+              if (opcode1 == NULL || opcode2 == NULL)
+                {
+                  as_bad (_("unknown opcode \"%s\""), "imml");
+                  return;
+                }
+              inst1 = opcode2->bit_sequence;
+              inst1 |= ((immed & 0xFFFFFF0000000000L) >> 40) & IMML_MASK;
+              output[0] = INST_BYTE0 (inst1);
+              output[1] = INST_BYTE1 (inst1);
+              output[2] = INST_BYTE2 (inst1);
+              output[3] = INST_BYTE3 (inst1);
+              output = frag_more (isize);
+              inst1 = opcode1->bit_sequence;
+              inst1 |= ((immed & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+              output[0] = INST_BYTE0 (inst1);
+              output[1] = INST_BYTE1 (inst1);
+              output[2] = INST_BYTE2 (inst1);
+              output[3] = INST_BYTE3 (inst1);
+              output = frag_more (isize);
+            }
+            }
           inst |= (immed << IMM_LOW) & IMM_MASK;
 	}
       else
@@ -2203,21 +2289,45 @@ md_assemble (char * str)
 	{
 	  output = frag_more (isize);
 	  immedl = exp.X_add_number;
-
-	  opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
-	  if (opcode1 == NULL)
-	    {
-	      as_bad (_("unknown opcode \"%s\""), "imml");
-	      return;
-	    }
-
-	  inst1 = opcode1->bit_sequence;
-	  inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
-	  output[0] = INST_BYTE0 (inst1);
-	  output[1] = INST_BYTE1 (inst1);
-	  output[2] = INST_BYTE2 (inst1);
-	  output[3] = INST_BYTE3 (inst1);
-	  output = frag_more (isize);
+	  if (((long long)immedl) > (long long)-549755813888 && ((long long)immedl) < (long long)549755813887)
+            {
+             opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+             if (opcode1 == NULL)
+             {
+              as_bad (_("unknown opcode \"%s\""), "imml");
+              return;
+             }
+          inst1 = opcode1->bit_sequence;
+          inst1 |= ((immedl & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+          output[0] = INST_BYTE0 (inst1);
+          output[1] = INST_BYTE1 (inst1);
+          output[2] = INST_BYTE2 (inst1);
+          output[3] = INST_BYTE3 (inst1);
+          output = frag_more (isize);
+        }
+           else {
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+       if (opcode2 == NULL || opcode1 == NULL)
+            {
+              as_bad (_("unknown opcode \"%s\""), "imml");
+              return;
+            }
+          inst1 = opcode2->bit_sequence;
+          inst1 |= ((immedl & 0xFFFFFF0000000000L) >> 40) & IMML_MASK;
+          output[0] = INST_BYTE0 (inst1);
+          output[1] = INST_BYTE1 (inst1);
+          output[2] = INST_BYTE2 (inst1);
+          output[3] = INST_BYTE3 (inst1);
+          output = frag_more (isize);
+          inst1 = opcode1->bit_sequence;
+          inst1 |= ((immedl & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+          output[0] = INST_BYTE0 (inst1);
+          output[1] = INST_BYTE1 (inst1);
+          output[2] = INST_BYTE2 (inst1);
+          output[3] = INST_BYTE3 (inst1);
+          output = frag_more (isize);
+        }
         }
 
       inst |= (reg1 << RD_LOW) & RD_MASK;
@@ -2266,21 +2376,46 @@ md_assemble (char * str)
 	{
           output = frag_more (isize);
           immedl = exp.X_add_number;
-	  opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
-	  if (opcode1 == NULL)
-	    {
-	      as_bad (_("unknown opcode \"%s\""), "imml");
-	      return;
-	    }
-
+	   if (((long long)immedl) > (long long)-549755813888 && ((long long)immedl) < (long long)549755813887)
+             {
+            opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           if (opcode1 == NULL)
+            {
+              as_bad (_("unknown opcode \"%s\""), "imml");
+              return;
+            }
+          inst1 = opcode1->bit_sequence;
+          inst1 |= ((immedl & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+          output[0] = INST_BYTE0 (inst1);
+          output[1] = INST_BYTE1 (inst1);
+          output[2] = INST_BYTE2 (inst1);
+          output[3] = INST_BYTE3 (inst1);
+          output = frag_more (isize);
+          }
+           else {
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+       if (opcode2 == NULL || opcode1 == NULL)
+            {
+              as_bad (_("unknown opcode \"%s\""), "imml");
+              return;
+            }
+          inst1 = opcode2->bit_sequence;
+          inst1 |= ((immedl & 0xFFFFFF0000000000L) >> 40) & IMML_MASK;
+          output[0] = INST_BYTE0 (inst1);
+          output[1] = INST_BYTE1 (inst1);
+          output[2] = INST_BYTE2 (inst1);
+          output[3] = INST_BYTE3 (inst1);
+          output = frag_more (isize);
           inst1 = opcode1->bit_sequence;
-	  inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
+          inst1 |= ((immedl & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
           output[0] = INST_BYTE0 (inst1);
           output[1] = INST_BYTE1 (inst1);
           output[2] = INST_BYTE2 (inst1);
           output[3] = INST_BYTE3 (inst1);
           output = frag_more (isize);
         }
+        }
 
       inst |= (reg1 << RA_LOW) & RA_MASK;
       inst |= (immedl << IMM_LOW) & IMM_MASK;
@@ -2560,8 +2695,8 @@ md_apply_fix (fixS *   fixP,
   /* Note: use offsetT because it is signed, valueT is unsigned.  */
   offsetT      val  = (offsetT) * valp;
   int          i;
-  struct op_code_struct * opcode1;
-  unsigned long inst1;
+  struct op_code_struct * opcode1, * opcode2;
+  unsigned long inst1,inst2;
 
   symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
 
@@ -2743,30 +2878,75 @@ md_apply_fix (fixS *   fixP,
     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
     case BFD_RELOC_MICROBLAZE_64:
     case BFD_RELOC_MICROBLAZE_64_PCREL:
-      /* Add an imm instruction.  First save the current instruction.  */
-      for (i = 0; i < INST_WORD_SIZE; i++)
-	buf[i + INST_WORD_SIZE] = buf[i];
       if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64
             || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PCREL)
         {
           /* Generate the imm instruction.  */
-          opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           if (((long long)val) > (long long)-549755813888 && ((long long)val) < (long long)549755813887)
+	   {
+        /* Add an imm instruction.  First save the current instruction.  */
+        for (i = 0; i < INST_WORD_SIZE; i++)
+        buf[i + INST_WORD_SIZE] = buf[i];
+        opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
           if (opcode1 == NULL)
-	    {
-	      as_bad (_("unknown opcode \"%s\""), "imml");
-	      return;
-	    }
+            {
+              as_bad (_("unknown opcode \"%s\""), "imml");
+              return;
+            }
 
            inst1 = opcode1->bit_sequence;
            if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
-	     inst1 |= ((val & 0xFFFFFF0000L) >> 16) & IMML_MASK;
+             inst1 |= ((val & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
            if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
-             fixP->fx_r_type = BFD_RELOC_64; 
+             fixP->fx_r_type = BFD_RELOC_64;
            if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PCREL)
-             fixP->fx_r_type = BFD_RELOC_64_PCREL; 
+             fixP->fx_r_type = BFD_RELOC_64_PCREL;
+      buf[0] = INST_BYTE0 (inst1);
+      buf[1] = INST_BYTE1 (inst1);
+      buf[2] = INST_BYTE2 (inst1);
+      buf[3] = INST_BYTE3 (inst1);
+	 }
+           else {
+      /* Add an imm instruction.  First save the current instruction.  */
+        for (i = 0; i < INST_WORD_SIZE; i++)
+        buf[i + INST_WORD_SIZE + 4] = buf[i];
+
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+	   if (opcode1 == NULL || opcode2 ==NULL)
+              {
+	      as_bad (_("unknown opcode \"%s\""), "imml");
+              return;
+	      }
+           inst1 = opcode2->bit_sequence;
+           if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
+             inst1 |= ((val & 0x000000FFFFFF0000L) >> 40) & IMML_MASK;
+           if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
+             fixP->fx_r_type = BFD_RELOC_64;
+           if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PCREL)
+             fixP->fx_r_type = BFD_RELOC_64_PCREL;
+           inst2 = opcode1->bit_sequence;
+           if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
+             inst1 |= ((val & 0x000000FFFFFF0000L) >> 16) & IMML_MASK;
+           if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
+             fixP->fx_r_type = BFD_RELOC_64;
+           if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PCREL)
+             fixP->fx_r_type = BFD_RELOC_64_PCREL;
+	buf[0] = INST_BYTE0 (inst1);
+	buf[1] = INST_BYTE1 (inst1);
+	buf[2] = INST_BYTE2 (inst1);
+	buf[3] = INST_BYTE3 (inst1);
+	buf[4] = INST_BYTE0 (inst2);
+	buf[5] = INST_BYTE1 (inst2);
+	buf[6] = INST_BYTE2 (inst2);
+	buf[7] = INST_BYTE3 (inst2);
+           }
          }
       else
         {
+      /* Add an imm instruction.  First save the current instruction.  */
+        for (i = 0; i < INST_WORD_SIZE; i++)
+        buf[i + INST_WORD_SIZE] = buf[i];
           /* Generate the imm instruction.  */
           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
           if (opcode1 == NULL)
@@ -2778,12 +2958,11 @@ md_apply_fix (fixS *   fixP,
           inst1 = opcode1->bit_sequence;
           if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
 	    inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
-         }
       buf[0] = INST_BYTE0 (inst1);
       buf[1] = INST_BYTE1 (inst1);
       buf[2] = INST_BYTE2 (inst1);
       buf[3] = INST_BYTE3 (inst1);
-
+         }
       /* Add the value only if the symbol is defined.  */
       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
 	{
@@ -2816,21 +2995,41 @@ md_apply_fix (fixS *   fixP,
       for (i = 0; i < INST_WORD_SIZE; i++)
 	buf[i + INST_WORD_SIZE] = buf[i];
       /* Generate the imm instruction.  */
-      if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC)
-        opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+      if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC) {
+           if (((long long)val) > (long long)-549755813888 && ((long long)val) < (long long)549755813887)
+           {
+           for (i = 0; i < INST_WORD_SIZE; i++)
+           buf[i + INST_WORD_SIZE] = buf[i];
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+	   }
+           else {
+       for (i = 0; i < INST_WORD_SIZE; i++)
+        buf[i + INST_WORD_SIZE + 4] = buf[i]; 
+           opcode2 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+           opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
+      inst2 = opcode2->bit_sequence;
+
+      /* We can fixup call to a defined non-global address
+ *          within the same section only.  */
+      buf[4] = INST_BYTE0 (inst2);
+      buf[5] = INST_BYTE1 (inst2);
+      buf[6] = INST_BYTE2 (inst2);
+      buf[7] = INST_BYTE3 (inst2);
+           }
+	}
       else
         opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
       if (opcode1 == NULL)
 	{
+      for (i = 0; i < INST_WORD_SIZE; i++)
+        buf[i + INST_WORD_SIZE] = buf[i];
           if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC)
 	    as_bad (_("unknown opcode \"%s\""), "imml");
           else
 	    as_bad (_("unknown opcode \"%s\""), "imm");
 	  return;
 	}
-
       inst1 = opcode1->bit_sequence;
-
       /* We can fixup call to a defined non-global address
 	 within the same section only.  */
       buf[0] = INST_BYTE0 (inst1);
diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h
index c25383f2de9..6f9a5a60dab 100644
--- a/opcodes/microblaze-opc.h
+++ b/opcodes/microblaze-opc.h
@@ -626,8 +626,8 @@ char pvr_register_prefix[] = "rpvr";
 #define MIN_IMM6_WIDTH  ((int) 0x00000001)
 #define MAX_IMM6_WIDTH  ((int) 0x00000040)
 
-#define MIN_IMML  ((long long) 0xffffff8000000000L)
-#define MAX_IMML  ((long long) 0x0000007fffffffffL)
+#define MIN_IMML  ((long long) -9223372036854775808)
+#define MAX_IMML  ((long long) 9223372036854775807)
 
 #endif /* MICROBLAZE_OPC */
 
-- 
2.17.1

