summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-07 10:05:10 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-07 10:05:10 -0700
commit588df78b0dcba0416fa172c6a8b16f712fa3befc (patch)
tree7c0182754f5a39f3994fa49239883b8c48372f15
parentf70fce6cc9a1a55822a2b0fac858c1fd9f6c1731 (diff)
downloadnasm-588df78b0dcba0416fa172c6a8b16f712fa3befc.tar.gz
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>
-rw-r--r--assemble.c22
-rw-r--r--disasm.c1
-rw-r--r--insns.dat2
-rwxr-xr-xinsns.pl4
-rw-r--r--test/immwarn.asm2
5 files changed, 28 insertions, 3 deletions
diff --git a/assemble.c b/assemble.c
index 1ed78bbf..f8b782cc 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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:
diff --git a/disasm.c b/disasm.c
index 46e3cf2f..0ff40fc1 100644
--- a/disasm.c
+++ b/disasm.c
@@ -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;
diff --git a/insns.dat b/insns.dat
index 8da82ed6..1b28d639 100644
--- a/insns.dat
+++ b/insns.dat
@@ -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
diff --git a/insns.pl b/insns.pl
index cb454966..1f723dd5 100755
--- a/insns.pl
+++ b/insns.pl
@@ -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') {
diff --git a/test/immwarn.asm b/test/immwarn.asm
index 90084fbc..8bffbfae 100644
--- a/test/immwarn.asm
+++ b/test/immwarn.asm
@@ -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