From c1377e9a98dd5ca6f7900c048df5d346d1733d05 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 6 Oct 2008 23:40:31 -0700 Subject: [PATCH] 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 --- assemble.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- disasm.c | 1 + insns.dat | 38 +++++++++++++++++++------------------- insns.pl | 2 ++ test/immwarn.asm | 7 +++---- 5 files changed, 73 insertions(+), 25 deletions(-) diff --git a/assemble.c b/assemble.c index d7e9eae..a7a23c2 100644 --- a/assemble.c +++ b/assemble.c @@ -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: diff --git a/disasm.c b/disasm.c index f3d4d2a..46e3cf2 100644 --- a/disasm.c +++ b/disasm.c @@ -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; diff --git a/insns.dat b/insns.dat index e4a0d78..8da82ed 100644 --- a/insns.dat +++ b/insns.dat @@ -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 diff --git a/insns.pl b/insns.pl index 9a8d3ed..cb45496 100755 --- a/insns.pl +++ b/insns.pl @@ -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 - -- 2.7.4