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;
}
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))
intel_syntax = -intel_syntax;
exp->X_md = 0;
+ expr_mode = expr_operator_none;
#if ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \
&& !defined (LEX_AT)) \
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;
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. */
/* 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))
if (gotfree_input_line)
input_line_pointer = gotfree_input_line;
+ expr_mode = expr_operator_none;
exp_seg = expression (exp);
SKIP_WHITESPACE ();
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);
}
}
}
+#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::";
--- /dev/null
+ .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
#objdump: -dw
#name: i386 displacements / immediates (32-bit)
+#warning_output: disp-imm-32.e
.*: +file format .*
[ ]*[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