@@ -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 AT
/* 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, cha
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
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);
}
@@ -13928,6 +13944,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
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
const char *md_shortopts = "kVQ:sqnO::";
@@ -633,6 +633,7 @@ i386_intel_operand (char *operand_string
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);
@@ -188,6 +188,12 @@ extern operatorT i386_operator (const ch
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[];
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,4 @@
+.*: Assembler messages:
+.*:15: Warning: .* shortened to 0x1
+.*:16: Warning: .* shortened to 0x40
+.*:17: Warning: .* shortened to 0x1
@@ -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"