diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ede940ec26b3983fc29fcaf46448be93844cf35e..e52036f9ddacab500356991232adb26c3fc078a1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2004-08-24  Richard Henderson  <rth@redhat.com>
+
+	PR target/16298
+	* config/i386/i386.c (legitimate_constant_p): Rework to not accept
+	random codes within CONST.
+
 2004-08-24  James E Wilson  <wilson@specifixinc.com>
 
 	* Makefile.in (STAGEFEEDBACK_FLAGS_TO_PASS): Remove
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 22a062d6fd7283121b9d7b40e9b8872f237e5a03..53ed7f1db5dcf704b95c8e3d1c54f548fa718cfa 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4824,54 +4824,43 @@ darwin_local_data_pic (rtx disp)
 bool
 legitimate_constant_p (rtx x)
 {
-  rtx inner;
-
   switch (GET_CODE (x))
     {
-    case SYMBOL_REF:
-      /* TLS symbols are not constant.  */
-      if (tls_symbolic_operand (x, Pmode))
-	return false;
-      break;
-
     case CONST:
-      inner = XEXP (x, 0);
-
-      /* Offsets of TLS symbols are never valid.
-	 Discourage CSE from creating them.  */
-      if (GET_CODE (inner) == PLUS
-	  && tls_symbolic_operand (XEXP (inner, 0), Pmode))
-	return false;
+      x = XEXP (x, 0);
 
-      if (GET_CODE (inner) == PLUS)
+      if (GET_CODE (x) == PLUS)
 	{
-	  if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
+	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
 	    return false;
-	  inner = XEXP (inner, 0);
+	  x = XEXP (x, 0);
 	}
 
-      if (TARGET_MACHO && darwin_local_data_pic (inner))
+      if (TARGET_MACHO && darwin_local_data_pic (x))
 	return true;
 
-      if (GET_CODE (inner) == MINUS)
-	{
-	  if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
-	    return false;
-	  inner = XEXP (inner, 0);
-	}
-
       /* Only some unspecs are valid as "constants".  */
-      if (GET_CODE (inner) == UNSPEC)
-	switch (XINT (inner, 1))
+      if (GET_CODE (x) == UNSPEC)
+	switch (XINT (x, 1))
 	  {
 	  case UNSPEC_TPOFF:
 	  case UNSPEC_NTPOFF:
-	    return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+	    return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
 	  case UNSPEC_DTPOFF:
-	    return local_dynamic_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+	    return local_dynamic_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
 	  default:
 	    return false;
 	  }
+
+      /* We must have drilled down to a symbol.  */
+      if (!symbolic_operand (x, Pmode))
+	return false;
+      /* FALLTHRU */
+
+    case SYMBOL_REF:
+      /* TLS symbols are never valid.  */
+      if (tls_symbolic_operand (x, Pmode))
+	return false;
       break;
 
     default: