This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch, nios2, committed] remove broken assembler dwim support


The Nios II assembler has historically had an undocumented feature to map ORI/XORI/ANDI/ADDI onto ORHI (etc) when given an immediate operand with only high bits set. Altera recently passed on a bug report where we found that this code was trying to apply the DWIM rewrite even when the high-bits-only operand was already explicitly modified with %hi or %lo. They asked us to remove this feature rather than try to fix it, the rationale being that assembly-language programmers need to depend on the instructions being predictably encoded exactly as written.

GCC does not emit code that depends on this feature and Altera does not need it for their support libraries either. If there's any other code out there that actually depends on it (or was using it inadvertently), it will now give an overflow error instead; I've modified the existing test case to check for the overflow error messages instead of the instruction substitution.

-Sandra

2014-11-28  Sandra Loosemore  <sandra@codesourcery.com>

	include/opcode/
	* nios2.h (NIOS2_INSN_ADDI, NIOS2_INSN_ANDI): Delete.
	(NIOS2_INSN_ORI, NIOS2_INSN_XORI): Delete.
	(NIOS2_INSN_OPTARG): Renumber.

	opcodes/
	* nios2-opc.c (nios2_r1_opcodes): Remove deleted attributes
	from descriptors.

	gas/
	* config/tc-nios2.c (can_evaluate_expr, get_expr_value): Delete.
	(output_addi, output_andi, output_ori, output_xori): Delete.
	(md_assemble): Remove calls to deleted functions.

	gas/testsuite/
	* gas/nios2/nios2.exp: Make "movi" a list test.
	* gas/nios2/movi.s: Adjust comments, add another case.
	* gas/nios2/movi.l: New.
	* gas/nios2/movi.d: Delete.
diff --git a/include/opcode/nios2.h b/include/opcode/nios2.h
index 6b4c2f5..6df9702 100644
--- a/include/opcode/nios2.h
+++ b/include/opcode/nios2.h
@@ -120,12 +120,7 @@ struct nios2_opcode
 #define NIOS2_INSN_CBRANCH	0x00000020
 #define NIOS2_INSN_CALL		0x00000040
 
-#define NIOS2_INSN_ADDI		0x00000080
-#define NIOS2_INSN_ANDI		0x00000100
-#define NIOS2_INSN_ORI		0x00000200
-#define NIOS2_INSN_XORI		0x00000400
-
-#define NIOS2_INSN_OPTARG	0x00000800
+#define NIOS2_INSN_OPTARG	0x00000080
 
 /* Register attributes.  */
 #define REG_NORMAL	(1<<0)	/* Normal registers.  */
diff --git a/opcodes/nios2-opc.c b/opcodes/nios2-opc.c
index a12a2f8..4d24c79 100644
--- a/opcodes/nios2-opc.c
+++ b/opcodes/nios2-opc.c
@@ -179,13 +179,13 @@ const struct nios2_opcode nios2_r1_opcodes[] =
   {"add", "d,s,t", "d,s,t,E", 3, 4, iw_r_type,
    MATCH_R1_ADD, MASK_R1_ADD, 0, no_overflow},
   {"addi", "t,s,i", "t,s,i,E", 3, 4, iw_i_type,
-   MATCH_R1_ADDI, MASK_R1_ADDI, NIOS2_INSN_ADDI, signed_immed16_overflow},
+   MATCH_R1_ADDI, MASK_R1_ADDI, 0, signed_immed16_overflow},
   {"and", "d,s,t", "d,s,t,E", 3, 4, iw_r_type,
    MATCH_R1_AND, MASK_R1_AND, 0, no_overflow},
   {"andhi", "t,s,u", "t,s,u,E", 3, 4, iw_i_type,
    MATCH_R1_ANDHI, MASK_R1_ANDHI, 0, unsigned_immed16_overflow},
   {"andi", "t,s,u", "t,s,u,E", 3, 4, iw_i_type,
-   MATCH_R1_ANDI, MASK_R1_ANDI, NIOS2_INSN_ANDI, unsigned_immed16_overflow},
+   MATCH_R1_ANDI, MASK_R1_ANDI, 0, unsigned_immed16_overflow},
   {"beq", "s,t,o", "s,t,o,E", 3, 4, iw_i_type,
    MATCH_R1_BEQ, MASK_R1_BEQ, NIOS2_INSN_CBRANCH, branch_target_overflow},
   {"bge", "s,t,o", "s,t,o,E", 3, 4, iw_i_type,
@@ -341,7 +341,7 @@ const struct nios2_opcode nios2_r1_opcodes[] =
   {"orhi", "t,s,u", "t,s,u,E", 3, 4, iw_i_type,
    MATCH_R1_ORHI, MASK_R1_ORHI, 0, unsigned_immed16_overflow},
   {"ori", "t,s,u", "t,s,u,E", 3, 4, iw_i_type,
-   MATCH_R1_ORI, MASK_R1_ORI, NIOS2_INSN_ORI, unsigned_immed16_overflow},
+   MATCH_R1_ORI, MASK_R1_ORI, 0, unsigned_immed16_overflow},
   {"rdctl", "d,c", "d,c,E", 2, 4, iw_r_type,
    MATCH_R1_RDCTL, MASK_R1_RDCTL, 0, no_overflow},
   {"rdprs", "t,s,i", "t,s,i,E", 3, 4, iw_i_type,
@@ -395,7 +395,7 @@ const struct nios2_opcode nios2_r1_opcodes[] =
   {"xorhi", "t,s,u", "t,s,u,E", 3, 4, iw_i_type,
    MATCH_R1_XORHI, MASK_R1_XORHI, 0, unsigned_immed16_overflow},
   {"xori", "t,s,u", "t,s,u,E", 3, 4, iw_i_type,
-   MATCH_R1_XORI, MASK_R1_XORI, NIOS2_INSN_XORI, unsigned_immed16_overflow}
+   MATCH_R1_XORI, MASK_R1_XORI, 0, unsigned_immed16_overflow}
 };
 
 #define NIOS2_NUM_OPCODES \
diff --git a/gas/config/tc-nios2.c b/gas/config/tc-nios2.c
index 7691fd1..59e9709 100644
--- a/gas/config/tc-nios2.c
+++ b/gas/config/tc-nios2.c
@@ -2062,34 +2062,6 @@ const int nios2_num_ps_insn_info_structs = NIOS2_NUM_PSEUDO_INSNS;
 
 /** Assembler output support.  */
 
-static int
-can_evaluate_expr (nios2_insn_infoS *insn)
-{
-  /* Remove this check for null and the invalid insn "ori r9, 1234" seg faults. */
-  if (!insn->insn_reloc) 
-    /* ??? Ideally we should do something other than as_fatal here as we can
-       continue to assemble.
-       However this function (actually the output_* functions) should not 
-       have been called in the first place once an illegal instruction had 
-       been encountered.  */
-    as_fatal (_("Invalid instruction encountered, cannot recover. No assembly attempted."));
-
-  if (insn->insn_reloc->reloc_expression.X_op == O_constant)
-    return 1;
-
-  return 0;
-}
-
-static int
-get_expr_value (nios2_insn_infoS *insn)
-{
-  int value = 0;
-
-  if (insn->insn_reloc->reloc_expression.X_op == O_constant)
-    value = insn->insn_reloc->reloc_expression.X_add_number;
-  return value;
-}
-
 /* Output a normal instruction.  */
 static void
 output_insn (nios2_insn_infoS *insn)
@@ -2203,107 +2175,6 @@ output_call (nios2_insn_infoS *insn)
   dwarf2_emit_insn (4);
 }
 
-/* Output an addi - will silently convert to
-   orhi if rA = r0 and (expr & 0xffff0000) == 0.  */
-static void
-output_addi (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      unsigned int rega = GET_IW_I_A (insn->insn_code);
-      unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-      if (rega == 0
-	  && (expr_val & 0xffff) == 0
-	  && expr_val != 0)
-	{
-	  /* We really want a movhi (orhi) here.  */
-	  insn->insn_code
-	    = MATCH_R1_ORHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-	  insn->insn_reloc->reloc_expression.X_add_number
-	    = (expr_val >> 16) & 0xffff;
-	  insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-	}
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-static void
-output_andi (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      if (expr_val != 0 && (expr_val & 0xffff) == 0)
-	{
-	  unsigned int rega = GET_IW_I_A (insn->insn_code);
-	  unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-	  /* We really want an andhi here.  */
-	  insn->insn_code
-	    = MATCH_R1_ANDHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-	  insn->insn_reloc->reloc_expression.X_add_number
-	    = (expr_val >> 16) & 0xffff;
-	  insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-	}
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-static void
-output_ori (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      if (expr_val != 0 && (expr_val & 0xffff) == 0)
-	{
-	  unsigned int rega = GET_IW_I_A (insn->insn_code);
-	  unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-	  /* We really want a movhi (orhi) here.  */
-	  insn->insn_code
-	    = MATCH_R1_ORHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-	  insn->insn_reloc->reloc_expression.X_add_number
-	    = (expr_val >> 16) & 0xffff;
-	  insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-	}
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-static void
-output_xori (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      if (expr_val != 0 && (expr_val & 0xffff) == 0)
-	{
-	  unsigned int rega = GET_IW_I_A (insn->insn_code);
-	  unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-	  /* We really want an xorhi here.  */
-	  insn->insn_code
-	    = MATCH_R1_XORHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-	  insn->insn_reloc->reloc_expression.X_add_number
-	    = (expr_val >> 16) & 0xffff;
-	  insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-	}
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-
 /* Output a movhi/addi pair for the movia pseudo-op.  */
 static void
 output_movia (nios2_insn_infoS *insn)
@@ -2540,14 +2411,6 @@ md_assemble (char *op_str)
 		   || (insn->insn_reloc->reloc_type
 		       == BFD_RELOC_NIOS2_CALL26_NOAT)))
 	output_call (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_ANDI)
-	output_andi (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_ORI)
-	output_ori (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_XORI)
-	output_xori (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_ADDI)
-	output_addi (insn);
       else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA)
 	output_movia (insn);
       else
diff --git a/gas/testsuite/gas/nios2/nios2.exp b/gas/testsuite/gas/nios2/nios2.exp
index bd68c6c..a4e7d7a 100644
--- a/gas/testsuite/gas/nios2/nios2.exp
+++ b/gas/testsuite/gas/nios2/nios2.exp
@@ -24,4 +24,5 @@ if { [istarget nios2-*-*] } {
     run_list_test "illegal" ""
     run_list_test "warn_nobreak" ""
     run_list_test "warn_noat" ""
+    run_list_test "movi" ""
 }
diff --git a/gas/testsuite/gas/nios2/movi.s b/gas/testsuite/gas/nios2/movi.s
index 07d9fed..20df564 100644
--- a/gas/testsuite/gas/nios2/movi.s
+++ b/gas/testsuite/gas/nios2/movi.s
@@ -1,21 +1,21 @@
-# Source file used to test silent conversion of
-# movi to orhi etc
+# Source file used to test that former silent conversion of
+# movi to orhi etc now gives range errors instead.
 
 foo:
-# this doesn't get converted
+# This doesn't get converted.
 movi r2, 0x20	
 
-# this does
+# This used to convert.
 movi r2, 0x20000000
 
-# addi should convert only if the source register is r0
+# addi used to convert only if the source register is r0.
 addi r2, r0, 0xffff0000
-# but we can't test for non-conversion because the value would
-# be out of range
 
-# logical ops should convert for any register
+# Logical ops used to convert to equivalent *hi for any register.
 ori r2, r5, 0xffff0000
 xori r2, r10, 0xffff0000
 andi r2, r15, 0xffff0000
 
-	
+# This one used to be buggy and convert even though it wasn't supposed to,
+# because it was failing to take the %lo relocation into account.
+ori   r23,r23,%lo(0x12340000)
diff --git a/gas/testsuite/gas/nios2/movi.l b/gas/testsuite/gas/nios2/movi.l
new file mode 100644
index 0000000..2eb47a1
--- /dev/null
+++ b/gas/testsuite/gas/nios2/movi.l
@@ -0,0 +1,6 @@
+.*movi.s: Assembler messages:
+.*movi.s:9: Error: immediate value 536870912 out of range -32768 to 32767
+.*movi.s:12: Error: immediate value -65536 out of range -32768 to 32767
+.*movi.s:15: Error: immediate value 4294901760 out of range 0 to 65535
+.*movi.s:16: Error: immediate value 4294901760 out of range 0 to 65535
+.*movi.s:17: Error: immediate value 4294901760 out of range 0 to 65535
diff --git a/gas/testsuite/gas/nios2/movi.d b/gas/testsuite/gas/nios2/movi.d
deleted file mode 100644
index e306017..0000000
--- a/gas/testsuite/gas/nios2/movi.d
+++ /dev/null
@@ -1,13 +0,0 @@
-#objdump: -dr --prefix-addresses --show-raw-insn
-#name: NIOS2 movi
-
-# Test implicit conversion of movi/movhi etc
-.*:     file format elf32-littlenios2
-
-Disassembly of section .text:
-0+0000 <[^>]*> 00800804 	movi	r2,32
-0+0004 <[^>]*> 00880034 	movhi	r2,8192
-0+0008 <[^>]*> 00bffff4 	movhi	r2,65535
-0+000c <[^>]*> 28bffff4 	orhi	r2,r5,65535
-0+0010 <[^>]*> 50bffffc 	xorhi	r2,r10,65535
-0+0014 <[^>]*> 78bfffec 	andhi	r2,r15,65535

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]