aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2000-02-26 04:00:13 +0000
committerAlan Modra <amodra@gmail.com>2000-02-26 04:00:13 +0000
commit773f551c1d440a64663f9ba9135ab362eabbed2b (patch)
treee81c56e3b91a856e5202de895647f163c6098c59 /gas
parent8d75d12d1b003c59e1500c14fcf4dea559d6380f (diff)
downloadgdb-773f551c1d440a64663f9ba9135ab362eabbed2b.zip
gdb-773f551c1d440a64663f9ba9135ab362eabbed2b.tar.gz
gdb-773f551c1d440a64663f9ba9135ab362eabbed2b.tar.bz2
Catch some more cases where we can represent a 16 bit immediate operand as
8 bit sign extended.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog15
-rw-r--r--gas/config/tc-i386.c82
2 files changed, 82 insertions, 15 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 1bb6e38..38084c1 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,18 @@
+2000-02-26 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * config/tc-i386.c (i386_immediate): Move constant operand sizing
+ from here..
+ (md_assemble): To here, before template operands are matched.
+ Also ensure a constant immediate is sign extended when we know the
+ size is at most 16 bits. This is to catch cases like "add
+ $0xffc0,%ax" where we don't know the size, and thus that the
+ immediate can be represented as Imm8S until after parsing the
+ register operand.
+ (i386_displacement): Similarly sign extend 16 bit constant
+ displacements.
+ (md_assemble): Relax 16-bit jump constant range check to suit sign
+ extended displacements.
+
2000-02-26 Andreas Jaeger <aj@suse.de>
* doc/c-mips.texi (MIPS Opts): Fix typo in last patch.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 3e202b7..d8d641c 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1305,6 +1305,61 @@ md_assemble (line)
i.seg[1] = temp_seg;
}
}
+
+ if (i.imm_operands)
+ {
+ /* Try to ensure constant immediates are represented in the smallest
+ opcode possible. */
+ char guess_suffix = 0;
+ int op;
+
+ if (i.suffix)
+ guess_suffix = i.suffix;
+ else if (i.reg_operands)
+ {
+ /* Figure out a suffix from the last register operand specified.
+ We can't do this properly yet, ie. excluding InOutPortReg,
+ but the following works for instructions with immediates.
+ In any case, we can't set i.suffix yet. */
+ for (op = i.operands; --op >= 0; )
+ if (i.types[op] & Reg)
+ {
+ if (i.types[op] & Reg8)
+ guess_suffix = BYTE_MNEM_SUFFIX;
+ else if (i.types[op] & Reg16)
+ guess_suffix = WORD_MNEM_SUFFIX;
+ break;
+ }
+ }
+ for (op = i.operands; --op >= 0; )
+ if ((i.types[op] & Imm)
+ && i.op[op].imms->X_op == O_constant)
+ {
+ /* If a suffix is given, this operand may be shortened. */
+ switch (guess_suffix)
+ {
+ case WORD_MNEM_SUFFIX:
+ i.types[op] |= Imm16;
+ break;
+ case BYTE_MNEM_SUFFIX:
+ i.types[op] |= Imm16 | Imm8 | Imm8S;
+ break;
+ }
+
+ /* If this operand is at most 16 bits, convert it to a
+ signed 16 bit number before trying to see whether it will
+ fit in an even smaller size. This allows a 16-bit operand
+ such as $0xffe0 to be recognised as within Imm8S range. */
+ if ((i.types[op] & Imm16)
+ && (i.op[op].imms->X_add_number & ~(offsetT)0xffff) == 0)
+ {
+ i.op[op].imms->X_add_number =
+ (((i.op[op].imms->X_add_number & 0xffff) ^ 0x8000) - 0x8000);
+ }
+ i.types[op] |= smallest_imm_type ((long) i.op[op].imms->X_add_number);
+ }
+ }
+
overlap0 = 0;
overlap1 = 0;
overlap2 = 0;
@@ -2200,7 +2255,9 @@ md_assemble (line)
{
long n = (long) i.op[1].imms->X_add_number;
- if (size == 2 && !fits_in_unsigned_word (n))
+ if (size == 2
+ && !fits_in_unsigned_word (n)
+ && !fits_in_signed_word (n))
{
as_bad (_("16-bit jump out of range"));
return;
@@ -2530,20 +2587,7 @@ i386_immediate (imm_start)
int bigimm = Imm32;
if (flag_16bit_code ^ (i.prefix[DATA_PREFIX] != 0))
bigimm = Imm16;
-
- i.types[this_operand] |=
- (bigimm | smallest_imm_type ((long) exp->X_add_number));
-
- /* If a suffix is given, this operand may be shortened. */
- switch (i.suffix)
- {
- case WORD_MNEM_SUFFIX:
- i.types[this_operand] |= Imm16;
- break;
- case BYTE_MNEM_SUFFIX:
- i.types[this_operand] |= Imm16 | Imm8 | Imm8S;
- break;
- }
+ i.types[this_operand] |= bigimm;
}
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
else if (
@@ -2784,6 +2828,14 @@ i386_displacement (disp_start, disp_end)
if (exp->X_op == O_constant)
{
+ if (i.types[this_operand] & Disp16)
+ {
+ /* We know this operand is at most 16 bits, so convert to a
+ signed 16 bit number before trying to see whether it will
+ fit in an even smaller size. */
+ exp->X_add_number =
+ (((exp->X_add_number & 0xffff) ^ 0x8000) - 0x8000);
+ }
if (fits_in_signed_byte (exp->X_add_number))
i.types[this_operand] |= Disp8;
}