diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-10-07 10:05:10 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-07 10:05:10 -0700 |
commit | 588df78b0dcba0416fa172c6a8b16f712fa3befc (patch) | |
tree | 7c0182754f5a39f3994fa49239883b8c48372f15 | |
parent | f70fce6cc9a1a55822a2b0fac858c1fd9f6c1731 (diff) | |
download | nasm-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.c | 22 | ||||
-rw-r--r-- | disasm.c | 1 | ||||
-rw-r--r-- | insns.dat | 2 | ||||
-rwxr-xr-x | insns.pl | 4 | ||||
-rw-r--r-- | test/immwarn.asm | 2 |
5 files changed, 28 insertions, 3 deletions
@@ -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: @@ -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; @@ -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 @@ -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 |