diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-10-06 23:40:31 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-06 23:40:31 -0700 |
commit | c1377e9a98dd5ca6f7900c048df5d346d1733d05 (patch) | |
tree | bb8b66a023c6e2106d2492cbc7ac9ba486ac6d03 | |
parent | 94cacf8ea9a7c2741f1fef6091d7e5fded7454fe (diff) | |
download | nasm-c1377e9a98dd5ca6f7900c048df5d346d1733d05.tar.gz nasm-c1377e9a98dd5ca6f7900c048df5d346d1733d05.tar.bz2 nasm-c1377e9a98dd5ca6f7900c048df5d346d1733d05.zip |
New opcodes to deal with 8-bit immediate sign extended to opsize
New opcodes to deal with 8-bit immediates which are then sign-extended
to the operand size. These allow us to warn appropriately.
Not sure I'm using these in all the proper places; need audit of all
uses of the \14..\17 opcodes.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | assemble.c | 50 | ||||
-rw-r--r-- | disasm.c | 1 | ||||
-rw-r--r-- | insns.dat | 38 | ||||
-rwxr-xr-x | insns.pl | 2 | ||||
-rw-r--r-- | test/immwarn.asm | 7 |
5 files changed, 73 insertions, 25 deletions
@@ -29,13 +29,13 @@ * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit * assembly mode or the operand-size override on the operand * \70..\73 - a long relative operand, from operand 0..3 - * \74..\77 - a word constant, from the _segment_ part of operand 0..3 + * \74..\77 - a word constant, from the _segment_ part of operand 0..3 * \1ab - a ModRM, calculated on EA in operand a, with the spare * field the register value of operand b. * \140..\143 - an immediate word or signed byte for operand 0..3 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3 * is a signed byte rather than a word. Opcode byte follows. - * \150..\153 - an immediate dword or signed byte for operand 0..3 + * \150..\153 - an immediate dword or signed byte for operand 0..3 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3 * is a signed byte rather than a dword. Opcode byte follows. * \160..\163 - this instruction uses DREX rather than REX, with the @@ -70,6 +70,8 @@ * [ww] ww = 3 for W used as REX.W * * + * \274..\277 - a signed byte immediate operand, from operand 0..3, + * which is to be extended to the operand size. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67. * \312 - (disassembler only) marker on LOOP, LOOPxx instructions. @@ -989,6 +991,12 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, ins->vex_m = *codes++; ins->vex_wlp = *codes++; break; + case 0274: + case 0275: + case 0276: + case 0277: + length++; + break; case 0300: case 0301: case 0302: @@ -1625,6 +1633,44 @@ static void gencode(int32_t segment, int64_t offset, int bits, } break; + case 0274: + case 0275: + case 0276: + case 0277: + { + uint64_t uv, um; + int s; + + if (ins->rex & REX_W) + s = 64; + else if (ins->prefixes[PPS_OSIZE] == P_O16) + s = 16; + else if (ins->prefixes[PPS_OSIZE] == P_O32) + s = 32; + else + s = bits; + + um = (uint64_t)2 << (s-1); + uv = opx->offset; + + if (uv > 127 && uv < (uint64_t)-128 && + (uv < um-128 || uv > um-1)) { + errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, + "signed byte value exceeds bounds"); + } + if (opx->segment != NO_SEG) { + data = um; + out(offset, segment, &data, OUT_ADDRESS, 1, + opx->segment, opx->wrt); + } else { + bytes[0] = um; + out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, + NO_SEG); + } + offset += 1; + break; + } + case 0300: case 0301: case 0302: @@ -482,6 +482,7 @@ static int matches(const struct itemplate *t, uint8_t *data, } case4(014): + case4(0274): opx->offset = (int8_t)*data++; opx->segment |= SEG_SIGNED; break; @@ -87,9 +87,9 @@ ADD reg32,mem \321\1\x03\110 386,SM ADD reg32,reg32 \321\1\x03\110 386 ADD reg64,mem \324\1\x03\110 X64,SM ADD reg64,reg64 \324\1\x03\110 X64 -ADD rm16,imm8 \320\1\x83\200\15 8086 -ADD rm32,imm8 \321\1\x83\200\15 386 -ADD rm64,imm8 \324\1\x83\200\15 X64 +ADD rm16,imm8 \320\1\x83\200\275 8086 +ADD rm32,imm8 \321\1\x83\200\275 386 +ADD rm64,imm8 \324\1\x83\200\275 X64 ADD reg_al,imm \1\x04\21 8086,SM ADD reg_ax,imm \320\1\x05\31 8086,SM ADD reg_eax,imm \321\1\x05\41 386,SM @@ -242,9 +242,9 @@ CMP reg32,mem \321\1\x3B\110 386,SM CMP reg32,reg32 \321\1\x3B\110 386 CMP reg64,mem \324\1\x3B\110 X64,SM CMP reg64,reg64 \324\1\x3B\110 X64 -CMP rm16,imm8 \320\1\x83\207\15 8086 -CMP rm32,imm8 \321\1\x83\207\15 386 -CMP rm64,imm8 \324\1\x83\207\15 X64 +CMP rm16,imm8 \320\1\x83\207\275 8086 +CMP rm32,imm8 \321\1\x83\207\275 386 +CMP rm64,imm8 \324\1\x83\207\275 X64 CMP reg_al,imm \1\x3C\21 8086,SM CMP reg_ax,imm \320\1\x3D\31 8086,SM CMP reg_eax,imm \321\1\x3D\41 386,SM @@ -840,9 +840,9 @@ OR reg32,mem \321\1\x0B\110 386,SM OR reg32,reg32 \321\1\x0B\110 386 OR reg64,mem \324\1\x0B\110 X64,SM OR reg64,reg64 \324\1\x0B\110 X64 -OR rm16,imm8 \320\1\x83\201\15 8086 -OR rm32,imm8 \321\1\x83\201\15 386 -OR rm64,imm8 \324\1\x83\201\15 X64 +OR rm16,imm8 \320\1\x83\201\275 8086 +OR rm32,imm8 \321\1\x83\201\275 386 +OR rm64,imm8 \324\1\x83\201\275 X64 OR reg_al,imm \1\x0C\21 8086,SM OR reg_ax,imm \320\1\x0D\31 8086,SM OR reg_eax,imm \321\1\x0D\41 386,SM @@ -973,7 +973,7 @@ PUSH rm64 \323\1\xFF\206 X64 PUSH reg_cs \6 8086,NOLONG PUSH reg_dess \6 8086,NOLONG PUSH reg_fsgs \1\x0F\7 386 -PUSH imm8 \1\x6A\14 186 +PUSH imm8 \1\x6A\274 186 PUSH imm16 \320\144\x68\140 186,AR0,SZ PUSH imm32 \321\154\x68\150 386,NOLONG,AR0,SZ PUSH imm32 \321\154\x68\150 386,NOLONG,SD @@ -1092,9 +1092,9 @@ SBB reg32,mem \321\1\x1B\110 386,SM SBB reg32,reg32 \321\1\x1B\110 386 SBB reg64,mem \324\1\x1B\110 X64,SM SBB reg64,reg64 \324\1\x1B\110 X64 -SBB rm16,imm8 \320\1\x83\203\15 8086 -SBB rm32,imm8 \321\1\x83\203\15 386 -SBB rm64,imm8 \324\1\x83\203\15 X64 +SBB rm16,imm8 \320\1\x83\203\275 8086 +SBB rm32,imm8 \321\1\x83\203\275 386 +SBB rm64,imm8 \324\1\x83\203\275 X64 SBB reg_al,imm \1\x1C\21 8086,SM SBB reg_ax,imm \320\1\x1D\31 8086,SM SBB reg_eax,imm \321\1\x1D\41 386,SM @@ -1205,9 +1205,9 @@ SUB reg32,mem \321\1\x2B\110 386,SM SUB reg32,reg32 \321\1\x2B\110 386 SUB reg64,mem \324\1\x2B\110 X64,SM SUB reg64,reg64 \324\1\x2B\110 X64 -SUB rm16,imm8 \320\1\x83\205\15 8086 -SUB rm32,imm8 \321\1\x83\205\15 386 -SUB rm64,imm8 \324\1\x83\205\15 X64 +SUB rm16,imm8 \320\1\x83\205\275 8086 +SUB rm32,imm8 \321\1\x83\205\275 386 +SUB rm64,imm8 \324\1\x83\205\275 X64 SUB reg_al,imm \1\x2C\21 8086,SM SUB reg_ax,imm \320\1\x2D\31 8086,SM SUB reg_eax,imm \321\1\x2D\41 386,SM @@ -1333,9 +1333,9 @@ XOR reg32,mem \321\1\x33\110 386,SM XOR reg32,reg32 \321\1\x33\110 386 XOR reg64,mem \324\1\x33\110 X64,SM XOR reg64,reg64 \324\1\x33\110 X64 -XOR rm16,imm8 \320\1\x83\206\15 8086 -XOR rm32,imm8 \321\1\x83\206\15 386 -XOR rm64,imm8 \324\1\x83\206\15 X64 +XOR rm16,imm8 \320\1\x83\206\275 8086 +XOR rm32,imm8 \321\1\x83\206\275 386 +XOR rm64,imm8 \324\1\x83\206\275 X64 XOR reg_al,imm \1\x34\21 8086,SM XOR reg_ax,imm \320\1\x35\31 8086,SM XOR reg_eax,imm \321\1\x35\41 386,SM @@ -670,6 +670,8 @@ sub byte_code_compile($) { push(@codes, 024+$oppos{'i'}); } elsif ($op eq 'iw') { # imm16 push(@codes, 030+$oppos{'i'}); + } elsif ($op eq 'ibx') { # imm8 sign-extended to opsize + push(@codes, 0274+$oppos{'i'}); } elsif ($op eq 'iwd') { # imm16 or imm32, depending on opsize push(@codes, 034+$oppos{'i'}); } elsif ($op eq 'id') { # imm32 diff --git a/test/immwarn.asm b/test/immwarn.asm index 3fc01c7..4b67676 100644 --- a/test/immwarn.asm +++ b/test/immwarn.asm @@ -14,14 +14,14 @@ %endif push -1 push 0ffffh - push byte 0FFFFh ; XXX - inappropriate + push byte 0FFFFh add ax,0FFFFh %if WARN add ax,0FFFFFFFFh %endif add ax,-1 - add ax,byte 0FFFFh ; XXX - inappropriate + add ax,byte 0FFFFh %if WARN add ax,byte 0FFFFFFFFh %endif @@ -32,7 +32,7 @@ add cx,0FFFFFFFFh %endif add cx,-1 - add cx,byte 0FFFFh ; XXX - inappropriate + add cx,byte 0FFFFh %if WARN add cx,byte 0FFFFFFFFh %endif @@ -87,4 +87,3 @@ push byte 0ffffffffh %endif push byte -1 - |