public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] x86: further adjust extend-to-32bit-address conditions
@ 2023-05-19  7:19 Jan Beulich
  0 siblings, 0 replies; only message in thread
From: Jan Beulich @ 2023-05-19  7:19 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5cc007751cdb8ea713c98294e37cd447c12c9bab

commit 5cc007751cdb8ea713c98294e37cd447c12c9bab
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri May 19 09:18:09 2023 +0200

    x86: further adjust extend-to-32bit-address conditions
    
    While a442cac5084e ("ix86: wrap constants") helped address a number of
    inconsistencies between BFD64 and !BFD64 builds, it has also resulted in
    certain bogus uses of constants to no longer be warned about. Leverage
    the md_optimize_expr() hook to adjust when to actually truncate
    expressions to 32 bits - any involvement of binary expressions (which
    would be evaluated in 32 bits only when !BFD64) signals the need for
    doing so. Plain constants (or ones merely subject to unary operators)
    should remain un-truncated - they would be handled as bignums when
    !BFD64, and hence are okay to permit.
    
    To compensate
    - slightly extend optimize_imm() (to be honest I never understood why
      the code being added - or something similar - wasn't there in the
      first place),
    - adjust expectations of the disp-imm-32 testcase (there are now
      warnings, as there should be for any code which won't build [warning-
      free] when !BFD64, and Disp8/Imm8 are no longer used in the warned
      about cases).

Diff:
---
 gas/config/tc-i386-intel.c           |  1 +
 gas/config/tc-i386.c                 | 57 ++++++++++++++++++++++++--
 gas/config/tc-i386.h                 |  6 +++
 gas/testsuite/gas/i386/cst-diag.l    | 43 ++++++++++++++++++++
 gas/testsuite/gas/i386/cst-diag.s    | 79 ++++++++++++++++++++++++++++++++++++
 gas/testsuite/gas/i386/disp-imm-32.d |  7 ++--
 gas/testsuite/gas/i386/disp-imm-32.e |  4 ++
 gas/testsuite/gas/i386/i386.exp      |  1 +
 8 files changed, 192 insertions(+), 6 deletions(-)

diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
index 5a2bf6d865c..f758bc59765 100644
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -633,6 +633,7 @@ i386_intel_operand (char *operand_string, int got_a_float)
   input_line_pointer = buf = xstrdup (operand_string);
 
   intel_syntax = -1;
+  expr_mode = expr_operator_none;
   memset (&exp, 0, sizeof(exp));
   exp_seg = expression (&exp);
   ret = i386_intel_simplify (&exp);
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 9efb1e58447..f9482a0ba4d 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -827,6 +827,14 @@ i386_cpu_flags cpu_arch_isa_flags;
    larger than a byte offset.  */
 static bool no_cond_jump_promotion = false;
 
+/* This will be set from an expression parser hook if there's any
+   applicable operator involved in an expression.  */
+static enum {
+  expr_operator_none,
+  expr_operator_present,
+  expr_large_value,
+} expr_mode;
+
 /* Encode SSE instructions with VEX prefix.  */
 static unsigned int sse2avx;
 
@@ -6016,6 +6024,8 @@ optimize_imm (void)
     }
   else if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0))
     guess_suffix = WORD_MNEM_SUFFIX;
+  else if (flag_code != CODE_64BIT || !(i.prefix[REX_PREFIX] & REX_W))
+    guess_suffix = LONG_MNEM_SUFFIX;
 
   for (op = i.operands; --op >= 0;)
     if (operand_type_check (i.types[op], imm))
@@ -10508,6 +10518,7 @@ x86_cons (expressionS *exp, int size)
 
   intel_syntax = -intel_syntax;
   exp->X_md = 0;
+  expr_mode = expr_operator_none;
 
 #if ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \
       && !defined (LEX_AT)) \
@@ -10567,7 +10578,8 @@ x86_cons (expressionS *exp, int size)
     i386_intel_simplify (exp);
 
   /* If not 64bit, massage value, to account for wraparound when !BFD64.  */
-  if (size == 4 && exp->X_op == O_constant && !object_64bit)
+  if (size <= 4 && expr_mode == expr_operator_present
+      && exp->X_op == O_constant && !object_64bit)
     exp->X_add_number = extend_to_32bit_address (exp->X_add_number);
 
   return got_reloc;
@@ -11626,6 +11638,7 @@ i386_immediate (char *imm_start)
   if (gotfree_input_line)
     input_line_pointer = gotfree_input_line;
 
+  expr_mode = expr_operator_none;
   exp_seg = expression (exp);
 
   /* For .insn immediates there may be a size specifier.  */
@@ -11684,7 +11697,8 @@ i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
 
       /* If not 64bit, sign/zero extend val, to account for wraparound
 	 when !BFD64.  */
-      if (flag_code != CODE_64BIT && !object_64bit)
+      if (expr_mode == expr_operator_present
+	  && flag_code != CODE_64BIT && !object_64bit)
 	exp->X_add_number = extend_to_32bit_address (exp->X_add_number);
     }
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
@@ -11906,6 +11920,7 @@ i386_displacement (char *disp_start, char *disp_end)
   if (gotfree_input_line)
     input_line_pointer = gotfree_input_line;
 
+  expr_mode = expr_operator_none;
   exp_seg = expression (exp);
 
   SKIP_WHITESPACE ();
@@ -11976,7 +11991,8 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
 
 	 If not 64bit, sign/zero extend val, to account for wraparound
 	 when !BFD64.  */
-      if (flag_code != CODE_64BIT && !object_64bit)
+      if (expr_mode == expr_operator_present
+	  && flag_code != CODE_64BIT && !object_64bit)
 	exp->X_add_number = extend_to_32bit_address (exp->X_add_number);
     }
 
@@ -13923,6 +13939,41 @@ md_operand (expressionS *e)
     }
 }
 
+#ifdef BFD64
+/* To maintain consistency with !BFD64 builds of gas record, whether any
+   (binary) operator was involved in an expression.  As expressions are
+   evaluated in only 32 bits when !BFD64, we use this to decide whether to
+   truncate results.  */
+bool i386_record_operator (operatorT op,
+			   const expressionS *left,
+			   const expressionS *right)
+{
+  if (op == O_absent)
+    return false;
+
+  if (!left)
+    {
+      /* Since the expression parser applies unary operators fine to bignum
+	 operands, we don't need to be concerned of respective operands not
+	 fitting in 32 bits.  */
+      if (right->X_op == O_constant && right->X_unsigned
+	  && !fits_in_unsigned_long (right->X_add_number))
+	return false;
+    }
+  /* This isn't entirely right: The pattern can also result when constant
+     expressions are folded (e.g. 0xffffffff + 1).  */
+  else if ((left->X_op == O_constant && left->X_unsigned
+	    && !fits_in_unsigned_long (left->X_add_number))
+	   || (right->X_op == O_constant && right->X_unsigned
+	       && !fits_in_unsigned_long (right->X_add_number)))
+    expr_mode = expr_large_value;
+
+  if (expr_mode != expr_large_value)
+    expr_mode = expr_operator_present;
+
+  return false;
+}
+#endif
 \f
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 const char *md_shortopts = "kVQ:sqnO::";
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 9247cdeab8b..62b82227571 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -188,6 +188,12 @@ extern operatorT i386_operator (const char *name, unsigned int operands, char *)
 extern int i386_need_index_operator (void);
 #define md_need_index_operator i386_need_index_operator
 
+#ifdef BFD64
+extern bool i386_record_operator
+  (operatorT, const expressionS *, const expressionS *);
+#define md_optimize_expr(l, o, r) i386_record_operator (o, l, r)
+#endif
+
 #define md_register_arithmetic 0
 
 extern const struct relax_type md_relax_table[];
diff --git a/gas/testsuite/gas/i386/cst-diag.l b/gas/testsuite/gas/i386/cst-diag.l
new file mode 100644
index 00000000000..0f0eb082746
--- /dev/null
+++ b/gas/testsuite/gas/i386/cst-diag.l
@@ -0,0 +1,43 @@
+.*: Assembler messages:
+.*:3: Warning: .*
+.*:4: Warning: .*
+.*:5: (Error|Warning): .*
+.*:6: (Error|Warning): .*
+.*:8: Warning: .*
+.*:9: Warning: .*
+.*:10: (Error|Warning): .*
+.*:11: (Error|Warning): .*
+.*:13: Warning: .*
+.*:14: Warning: .*
+.*:15: (Error|Warning): .*
+.*:16: (Error|Warning): .*
+.*:18: Warning: .*
+.*:19: (Error|Warning): .*
+.*:20: (Error|Warning): .*
+.*:22: (Error|Warning): .*
+.*:23: (Error|Warning): .*
+.*:24: (Error|Warning): .*
+.*:25: (Error|Warning): .*
+.*:30: Warning: .*
+.*:31: Warning: .*
+.*:35: Warning: .*
+.*:36: Warning: .*
+.*:40: Warning: .*
+.*:41: Warning: .*
+.*:46: Warning: .*
+.*:47: Warning: .*
+.*:48: Warning: .*
+.*:50: Warning: .*
+.*:51: Warning: .*
+.*:52: Warning: .*
+.*:55: Warning: .*
+.*:56: Warning: .*
+.*:57: Warning: .*
+.*:59: Warning: .*
+.*:60: Warning: .*
+.*:61: Warning: .*
+.*:64: Warning: .*
+.*:65: Warning: .*
+.*:66: Warning: .*
+GAS LISTING .*
+#pass
diff --git a/gas/testsuite/gas/i386/cst-diag.s b/gas/testsuite/gas/i386/cst-diag.s
new file mode 100644
index 00000000000..d34ab3b50a2
--- /dev/null
+++ b/gas/testsuite/gas/i386/cst-diag.s
@@ -0,0 +1,79 @@
+	.text
+const:
+	add	$0x101, %cl
+	add	$0x10001, %cx
+	add	$0x100000001, %ecx
+	add	0x100000001, %ecx
+
+	add	$0x100, %cl
+	add	$0x10000, %cx
+	add	$0x100000000, %ecx
+	add	0x100000000, %ecx
+
+	add	$-0x101, %cl
+	add	$-0x10001, %cx
+	add	$-0x100000001, %ecx
+	add	-0x100000001, %ecx
+
+	add	$-0x100, %cl
+	add	$-0x10000, %cx
+	add	$-0x100000000, %ecx
+
+	add	$0xffffffffffffff00, %cl
+	add	$0xffffffffffff0000, %cx
+	add	$0xffffffff00000000, %ecx
+	add	0xffffffff00000000, %ecx
+
+	# The next two might as well not have a disagnostic issued, but if
+	# there is one (as is the case now), then it should be independent
+	# of BFD64.
+	and	$~0xff, %cl
+	and	$~0xffff, %cx
+	and	$~0xffffffff, %ecx
+	and	~0xffffffff, %ecx
+
+	and	$0xff+2, %cl
+	and	$0xffff+2, %cx
+	and	$0xffffffff+2, %ecx
+	and	0xffffffff+2, %ecx
+
+	and	$0xff*2, %cl
+	and	$0xffff*2, %cx
+	and	$0xffffffff*2, %ecx
+	and	0xffffffff*2, %ecx
+
+	.data
+	.byte 0x101
+	.byte -0x100
+	.byte 0xffffffffffffff00
+#	.byte ~0xffffffffffffff00
+	.byte ~0xff
+	.byte 0xff+2
+	.byte 0xff*2
+
+	.p2align 4
+	.word 0x10001
+	.word -0x10000
+	.word 0xffffffffffff0000
+#	.word ~0xffffffffffff0000
+	.word ~0xffff
+	.word 0xffff+2
+	.word 0xffff*2
+
+	.p2align 4
+	.long 0x100000001
+	.long -0x100000000
+	.long 0xffffffff00000000
+#	.long ~0xffffffff00000000
+	.long ~0xffffffff
+#	.long 0xffffffff+2
+#	.long 0xffffffff*2
+
+	.p2align 4
+	.quad 0x100000001
+	.quad -0x100000000
+	.quad 0xffffffff00000000
+#	.quad ~0xffffffff00000000
+	.quad ~0xffffffff
+#	.quad 0xffffffff+2
+#	.quad 0xffffffff*2
diff --git a/gas/testsuite/gas/i386/disp-imm-32.d b/gas/testsuite/gas/i386/disp-imm-32.d
index dc712b96269..aa2e4a07d87 100644
--- a/gas/testsuite/gas/i386/disp-imm-32.d
+++ b/gas/testsuite/gas/i386/disp-imm-32.d
@@ -1,5 +1,6 @@
 #objdump: -dw
 #name: i386 displacements / immediates (32-bit)
+#warning_output: disp-imm-32.e
 
 .*: +file format .*
 
@@ -15,7 +16,7 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	8b 40 ff             	mov    -0x1\(%eax\),%eax
 [ 	]*[a-f0-9]+:	62 f1 7c 48 28 40 ff 	vmovaps -0x40\(%eax\),%zmm0
 [ 	]*[a-f0-9]+:	83 c1 ff             	add    \$0xffffffff,%ecx
-[ 	]*[a-f0-9]+:	8b 40 01             	mov    0x1\(%eax\),%eax
-[ 	]*[a-f0-9]+:	62 f1 7c 48 28 40 01 	vmovaps 0x40\(%eax\),%zmm0
-[ 	]*[a-f0-9]+:	83 c1 01             	add    \$0x1,%ecx
+[ 	]*[a-f0-9]+:	8b (40 01 +|80 01 00 00 00)    	mov    0x1\(%eax\),%eax
+[ 	]*[a-f0-9]+:	62 f1 7c 48 28 (40 01|80 40 00 00 00) 	vmovaps 0x40\(%eax\),%zmm0
+[ 	]*[a-f0-9]+:	(83 c1 01 +|81 c1 01 00 00 00)    	add    \$0x1,%ecx
 #pass
diff --git a/gas/testsuite/gas/i386/disp-imm-32.e b/gas/testsuite/gas/i386/disp-imm-32.e
new file mode 100644
index 00000000000..3da95b426d0
--- /dev/null
+++ b/gas/testsuite/gas/i386/disp-imm-32.e
@@ -0,0 +1,4 @@
+.*: Assembler messages:
+.*:15: Warning: .* shortened to 0x1
+.*:16: Warning: .* shortened to 0x40
+.*:17: Warning: .* shortened to 0x1
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 40e75ac6f88..62796c71551 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -100,6 +100,7 @@ if [gas_32_check] then {
     run_dump_test "suffix-intel"
     run_list_test "suffix-bad"
     run_dump_test "immed32"
+    run_list_test "cst-diag" "-al"
     run_dump_test "equ"
     run_list_test "equ-2" "-al"
     run_list_test "equ-bad"

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-05-19  7:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-19  7:19 [binutils-gdb] x86: further adjust extend-to-32bit-address conditions Jan Beulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).