summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-06 23:40:31 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-06 23:40:31 -0700
commitc1377e9a98dd5ca6f7900c048df5d346d1733d05 (patch)
treebb8b66a023c6e2106d2492cbc7ac9ba486ac6d03
parent94cacf8ea9a7c2741f1fef6091d7e5fded7454fe (diff)
downloadnasm-c1377e9a98dd5ca6f7900c048df5d346d1733d05.tar.gz
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.c50
-rw-r--r--disasm.c1
-rw-r--r--insns.dat38
-rwxr-xr-xinsns.pl2
-rw-r--r--test/immwarn.asm7
5 files changed, 73 insertions, 25 deletions
diff --git a/assemble.c b/assemble.c
index d7e9eae7..a7a23c21 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 f3d4d2a3..46e3cf2f 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 e4a0d784..8da82ed6 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 9a8d3ed8..cb454966 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 3fc01c71..4b67676f 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
-