New opcode for 32->64 bit sign-extended immediate with warning

Add a new opcode for 32->64 bit sign-extended immediate, with warning
on the number not matching.

This unfortunately calls for an audit of all the \4[0123] opcodes, if
they should be replaced by \25[4567].  This only replaces one
instruction (MOV reg64,imm32); other instructions need to be
considered.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2008-10-07 10:05:10 -07:00
parent f70fce6cc9
commit 588df78b0d
5 changed files with 28 additions and 3 deletions

View File

@ -56,6 +56,7 @@
* \250..\253 - same as \150..\153, except warn if the 64-bit operand
* is not equal to the truncated and sign-extended 32-bit
* operand; used for 32-bit immediates in 64-bit mode.
* \254..\257 - a signed 32-bit operand to be extended to 64 bits.
* \260..\263 - this instruction uses VEX rather than REX, with the
* V field taken from operand 0..3.
* \270 - this instruction uses VEX rather than REX, with the
@ -953,6 +954,12 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
case 0253:
length += is_sbyte32(opx) ? 1 : 4;
break;
case 0254:
case 0255:
case 0256:
case 0257:
length += 4;
break;
case 0260:
case 0261:
case 0262:
@ -1592,6 +1599,21 @@ static void gencode(int32_t segment, int64_t offset, int bits,
}
break;
case 0254:
case 0255:
case 0256:
case 0257:
data = opx->offset;
if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
(int32_t)data != (int64_t)data) {
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
"signed dword immediate exceeds bounds");
}
out(offset, segment, &data, OUT_ADDRESS, 4,
opx->segment, opx->wrt);
offset += 4;
break;
case 0260:
case 0261:
case 0262:

View File

@ -513,6 +513,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
break;
case4(040):
case4(0254):
opx->offset = getu32(data);
data += 4;
break;

View File

@ -768,7 +768,7 @@ MOV reg8,imm \10\xB0\21 8086,SM
MOV reg16,imm \320\10\xB8\31 8086,SM
MOV reg32,imm \321\10\xB8\41 386,SM
MOV reg64,imm \324\10\xB8\55 X64,SM
MOV reg64,imm32 \324\1\xC7\200\41 X64
MOV reg64,imm32 \324\1\xC7\200\255 X64
MOV rm8,imm \1\xC6\200\21 8086,SM
MOV rm16,imm \320\1\xC7\200\31 8086,SM
MOV rm32,imm \321\1\xC7\200\41 386,SM

View File

@ -658,7 +658,7 @@ sub byte_code_compile($) {
# This allows us to match the AMD documentation and still
# do the right thing.
unshift(@codes, 0160+$oppos{'d'}+($oc0 ? 4 : 0));
} elsif ($op =~ /^(ib\,s|ib|ib\,w|iw|iwd|id|iwdq|rel|rel8|rel16|rel32|iq|seg|ibw|ibd|ibd,s)$/) {
} elsif ($op =~ /^(ib\,s|ib|ibx|ib\,w|iw|iwd|id|idx|iwdq|rel|rel8|rel16|rel32|iq|seg|ibw|ibd|ibd,s)$/) {
if (!defined($oppos{'i'})) {
die "$fname: $line: $op without 'i' operand\n";
}
@ -676,6 +676,8 @@ sub byte_code_compile($) {
push(@codes, 034+$oppos{'i'});
} elsif ($op eq 'id') { # imm32
push(@codes, 040+$oppos{'i'});
} elsif ($op eq 'idx') { # imm32 extended to 64 bits
push(@codes, 0254+$oppos{'i'});
} elsif ($op eq 'iwdq') { # imm16/32/64, depending on opsize
push(@codes, 044+$oppos{'i'});
} elsif ($op eq 'rel8') {

View File

@ -72,7 +72,7 @@
mov rax,7fffffffh
mov rax,80000000h
%if WARN
mov rax,dword 80000000h ; XXX - missing
mov rax,dword 80000000h
%endif
add rcx,0FFFFh
%if WARN