+2021-06-15 Jan Beulich <jbeulich@suse.com>
+
+ * config/tc-i386.c (optimize_disp): Generalize disp32 part of
+ the BFD64-only logic to also apply to non-64-bit code.
+ (i386_finalize_displacement): Use extend_to_32bit_address for
+ non-64-bit code. Drop now redundant O_constant checks.
+ * testsuite/gas/i386/disp-imm-32.s,
+ testsuite/gas/i386/disp-imm-32.d: New.
+ * testsuite/gas/i386/i386.exp: Run new test.
+
2021-06-15 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (offset_in_range): Replace uses of
}
#ifdef BFD64
- if (flag_code == CODE_64BIT)
+ /* Optimize 64-bit displacement to 32-bit for 64-bit BFD. */
+ if ((i.types[op].bitfield.disp32
+ || (flag_code == CODE_64BIT
+ && want_disp32 (current_templates->start)))
+ && fits_in_unsigned_long (op_disp))
{
- /* Optimize 64-bit displacement to 32-bit for 64-bit BFD. */
- if ((i.types[op].bitfield.disp32
- || want_disp32 (current_templates->start))
- && fits_in_unsigned_long (op_disp))
- {
- /* If this operand is at most 32 bits, convert
- to a signed 32 bit number and don't use 64bit
- displacement. */
- op_disp = (op_disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31);
- i.types[op].bitfield.disp64 = 0;
- i.types[op].bitfield.disp32 = 1;
- }
+ /* If this operand is at most 32 bits, convert
+ to a signed 32 bit number and don't use 64bit
+ displacement. */
+ op_disp = (op_disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31);
+ i.types[op].bitfield.disp64 = 0;
+ i.types[op].bitfield.disp32 = 1;
+ }
- if (fits_in_signed_long (op_disp))
- {
- i.types[op].bitfield.disp64 = 0;
- i.types[op].bitfield.disp32s = 1;
- }
+ if (flag_code == CODE_64BIT && fits_in_signed_long (op_disp))
+ {
+ i.types[op].bitfield.disp64 = 0;
+ i.types[op].bitfield.disp32s = 1;
}
#endif
if ((i.types[op].bitfield.disp32
ret = 0;
}
+ else if (exp->X_op == O_constant)
+ {
+ /* Sizing gets taken care of by optimize_disp().
+
+ If not 64bit, sign/zero extend val, to account for wraparound
+ when !BFD64. */
+ if (flag_code != CODE_64BIT)
+ exp->X_add_number = extend_to_32bit_address (exp->X_add_number);
+ }
+
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
- else if (exp->X_op != O_constant
- && OUTPUT_FLAVOR == bfd_target_aout_flavour
+ else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
&& exp_seg != absolute_section
&& exp_seg != text_section
&& exp_seg != data_section
}
#endif
- if (current_templates->start->opcode_modifier.jump == JUMP_BYTE
- /* Constants get taken care of by optimize_disp(). */
- && exp->X_op != O_constant)
+ else if (current_templates->start->opcode_modifier.jump == JUMP_BYTE)
i.types[this_operand].bitfield.disp8 = 1;
/* Check if this is a displacement only operand. */
--- /dev/null
+#objdump: -dw
+#name: i386 displacements / immediates (32-bit)
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <disp_imm>:
+[ ]*[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 00 mov \(%eax\),%eax
+[ ]*[a-f0-9]+: 62 f1 7c 48 28 00 vmovaps \(%eax\),%zmm0
+[ ]*[a-f0-9]+: 83 c1 00 add \$0x0,%ecx
+[ ]*[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
+#pass
--- /dev/null
+ .text
+disp_imm:
+ mov -0xffffffff(%eax), %eax
+ vmovaps -0xffffffc0(%eax), %zmm0
+ add $-0xffffffff, %ecx
+
+ mov -0xffffffff-1(%eax), %eax
+ vmovaps -0xffffffc0-0x40(%eax), %zmm0
+ add $-0xffffffff-1, %ecx
+
+ mov -0xffffffff-2(%eax), %eax
+ vmovaps -0xffffffc0-0x80(%eax), %zmm0
+ add $-0xffffffff-2, %ecx
+
+ mov -0x1ffffffff(%eax), %eax
+ vmovaps -0x1ffffffc0(%eax), %zmm0
+ add $-0x1ffffffff, %ecx