summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-04-04 13:34:53 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-04-04 13:34:53 -0700
commit32cd4c2a62f34815dbc9c13e1e6640bb096d05b5 (patch)
treeb102f98dbf7c28e18f114f944c006ab7499a2904
parent5a7976c925e494bfd0db806c5f5724157236b4e3 (diff)
downloadnasm-32cd4c2a62f34815dbc9c13e1e6640bb096d05b5.tar.gz
Correctly identify SBYTE in the optimizer
Correctly identify SBYTE in the optimizer, *HOWEVER*, this change will cause nuisance warnings to be issued; that will have to be fixed.
-rw-r--r--assemble.c193
-rw-r--r--insns.dat97
-rw-r--r--insns.h4
-rw-r--r--nasm.h8
-rw-r--r--parser.c13
5 files changed, 200 insertions, 115 deletions
diff --git a/assemble.c b/assemble.c
index 681af699..60fe369e 100644
--- a/assemble.c
+++ b/assemble.c
@@ -37,7 +37,7 @@
* is a signed byte rather than a word. Opcode byte follows.
* \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 word. Opcode byte follows.
+ * is a signed byte rather than a dword. Opcode byte follows.
* \160..\163 - this instruction uses DREX rather than REX, with the
* OC0 field set to 0, and the dest field taken from
* operand 0..3.
@@ -50,6 +50,9 @@
* \171 - placement of DREX suffix in the absence of an EA
* \2ab - a ModRM, calculated on EA in operand a, with the spare
* field equal to digit b.
+ * \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.
* \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.
@@ -159,7 +162,8 @@ static void warn_overflow(int size, int64_t data)
int64_t lim = ((int64_t)1 << (size*8))-1;
if (data < ~lim || data > lim)
- errfunc(ERR_WARNING | ERR_WARN_NOV, "%s data exceeds bounds", size_name(size));
+ errfunc(ERR_WARNING | ERR_WARN_NOV,
+ "%s data exceeds bounds", size_name(size));
}
}
/*
@@ -756,25 +760,55 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
return -1; /* didn't match any instruction */
}
-/* check that opn[op] is a signed byte of size 16 or 32,
- and return the signed value*/
-static int is_sbyte(insn * ins, int op, int size)
+static bool possible_sbyte(insn * ins, int op)
{
- int32_t v;
- int ret;
-
- ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
+ return !(ins->forw_ref && ins->oprs[op].opflags) &&
optimizing >= 0 &&
!(ins->oprs[op].type & STRICT) &&
ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
+}
+
+/* check that opn[op] is a signed byte of size 16 or 32 */
+static bool is_sbyte16(insn * ins, int op)
+{
+ int16_t v;
+
+ if (!possible_sbyte(ins, op))
+ return false;
v = ins->oprs[op].offset;
- if (size == 16)
- v = (int16_t)v; /* sign extend if 16 bits */
+ return v >= -128 && v <= 127;
+}
- return ret && v >= -128L && v <= 127L;
+static bool is_sbyte32(insn * ins, int op)
+{
+ int32_t v;
+
+ if (!possible_sbyte(ins, op))
+ return false;
+
+ v = ins->oprs[op].offset;
+ return v >= -128 && v <= 127;
}
+/* check that opn[op] is a signed byte of size 32; warn if this is not
+ the original value when extended to 64 bits */
+static bool is_sbyte64(insn * ins, int op)
+{
+ int64_t v64;
+ int32_t v32;
+
+ /* dead in the water on forward reference or External */
+ if (!possible_sbyte(ins, op))
+ return false;
+
+ v64 = ins->oprs[op].offset;
+ v32 = (int32_t)v64;
+
+ warn_overflow(32, v64);
+
+ return v32 >= -128 && v32 <= 127;
+}
static int64_t calcsize(int32_t segment, int64_t offset, int bits,
insn * ins, const char *codes)
{
@@ -902,7 +936,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
case 0141:
case 0142:
case 0143:
- length += is_sbyte(ins, c & 3, 16) ? 1 : 2;
+ length += is_sbyte16(ins, c & 3) ? 1 : 2;
break;
case 0144:
case 0145:
@@ -915,7 +949,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
case 0151:
case 0152:
case 0153:
- length += is_sbyte(ins, c & 3, 32) ? 1 : 4;
+ length += is_sbyte32(ins, c & 3) ? 1 : 4;
break;
case 0154:
case 0155:
@@ -945,6 +979,12 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
break;
case 0171:
break;
+ case 0250:
+ case 0251:
+ case 0252:
+ case 0253:
+ length += is_sbyte64(ins, c & 3) ? 1 : 4;
+ break;
case 0300:
case 0301:
case 0302:
@@ -1174,6 +1214,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
case 015:
case 016:
case 017:
+ /* XXX: warns for legitimate optimizer actions */
if (opx->offset < -128 || opx->offset > 127) {
errfunc(ERR_WARNING | ERR_WARN_NOV,
"signed byte value exceeds bounds");
@@ -1383,7 +1424,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
case 0142:
case 0143:
data = opx->offset;
- if (is_sbyte(ins, c & 3, 16)) {
+ if (is_sbyte16(ins, c & 3)) {
bytes[0] = data;
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
NO_SEG);
@@ -1404,7 +1445,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
case 0147:
EMIT_REX();
bytes[0] = *codes++;
- if (is_sbyte(ins, c & 3, 16))
+ if (is_sbyte16(ins, c & 3))
bytes[0] |= 2; /* s-bit */
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
offset++;
@@ -1415,7 +1456,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
case 0152:
case 0153:
data = opx->offset;
- if (is_sbyte(ins, c & 3, 32)) {
+ if (is_sbyte32(ins, c & 3)) {
bytes[0] = data;
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
NO_SEG);
@@ -1433,7 +1474,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
case 0157:
EMIT_REX();
bytes[0] = *codes++;
- if (is_sbyte(ins, c & 3, 32))
+ if (is_sbyte32(ins, c & 3))
bytes[0] |= 2; /* s-bit */
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
offset++;
@@ -1466,6 +1507,24 @@ static void gencode(int32_t segment, int64_t offset, int bits,
offset++;
break;
+ case 0250:
+ case 0251:
+ case 0252:
+ case 0253:
+ data = opx->offset;
+ /* is_sbyte32() is right here, we have already warned */
+ if (is_sbyte32(ins, c & 3)) {
+ bytes[0] = data;
+ out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
+ NO_SEG);
+ offset++;
+ } else {
+ out(offset, segment, &data, OUT_ADDRESS, 4,
+ opx->segment, opx->wrt);
+ offset += 4;
+ }
+ break;
+
case 0300:
case 0301:
case 0302:
@@ -1744,47 +1803,13 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
return 0;
/*
- * Check that the operand flags all match up
- */
- for (i = 0; i < itemp->operands; i++) {
- if (itemp->opd[i] & SAME_AS) {
- int j = itemp->opd[i] & ~SAME_AS;
- if (instruction->oprs[i].type != instruction->oprs[j].type ||
- instruction->oprs[i].basereg != instruction->oprs[j].basereg)
- return 0;
- } else if (itemp->opd[i] & ~instruction->oprs[i].type ||
- ((itemp->opd[i] & SIZE_MASK) &&
- ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
- if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
- (instruction->oprs[i].type & SIZE_MASK))
- return 0;
- else
- return 1;
- }
- }
-
- /*
- * Check operand sizes
+ * Process size flags
*/
if (itemp->flags & IF_ARMASK) {
memset(size, 0, sizeof size);
- switch (itemp->flags & IF_ARMASK) {
- case IF_AR0:
- i = 0;
- break;
- case IF_AR1:
- i = 1;
- break;
- case IF_AR2:
- i = 2;
- break;
- case IF_AR3:
- i = 3;
- break;
- default:
- break; /* Shouldn't happen */
- }
+ i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
+
switch (itemp->flags & IF_SMASK) {
case IF_SB:
size[i] = BITS8;
@@ -1801,6 +1826,19 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
case IF_SO:
size[i] = BITS128;
break;
+ case IF_SZ:
+ switch (bits) {
+ case 16:
+ size[i] = BITS16;
+ break;
+ case 32:
+ size[i] = BITS32;
+ break;
+ case 64:
+ size[i] = BITS64;
+ break;
+ }
+ break;
default:
break;
}
@@ -1809,23 +1847,31 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
switch (itemp->flags & IF_SMASK) {
case IF_SB:
asize = BITS8;
- oprs = itemp->operands;
break;
case IF_SW:
asize = BITS16;
- oprs = itemp->operands;
break;
case IF_SD:
asize = BITS32;
- oprs = itemp->operands;
break;
case IF_SQ:
asize = BITS64;
- oprs = itemp->operands;
break;
case IF_SO:
asize = BITS128;
- oprs = itemp->operands;
+ break;
+ case IF_SZ:
+ switch (bits) {
+ case 16:
+ asize = BITS16;
+ break;
+ case 32:
+ asize = BITS32;
+ break;
+ case 64:
+ asize = BITS64;
+ break;
+ }
break;
default:
break;
@@ -1834,6 +1880,33 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
size[i] = asize;
}
+ /*
+ * Check that the operand flags all match up
+ */
+ for (i = 0; i < itemp->operands; i++) {
+ int32_t type = instruction->oprs[i].type;
+ if (!(type & SIZE_MASK))
+ type |= size[i];
+
+ if (itemp->opd[i] & SAME_AS) {
+ int j = itemp->opd[i] & ~SAME_AS;
+ if (type != instruction->oprs[j].type ||
+ instruction->oprs[i].basereg != instruction->oprs[j].basereg)
+ return 0;
+ } else if (itemp->opd[i] & ~type ||
+ ((itemp->opd[i] & SIZE_MASK) &&
+ ((itemp->opd[i] ^ type) & SIZE_MASK))) {
+ if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
+ (type & SIZE_MASK))
+ return 0;
+ else
+ return 1;
+ }
+ }
+
+ /*
+ * Check operand sizes
+ */
if (itemp->flags & (IF_SM | IF_SM2)) {
oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
asize = 0;
diff --git a/insns.dat b/insns.dat
index 457315e1..23027035 100644
--- a/insns.dat
+++ b/insns.dat
@@ -59,16 +59,16 @@ ADC rm16,imm8 \320\1\x83\202\15 8086
ADC rm32,imm8 \321\1\x83\202\15 386
ADC rm64,imm8 \324\1\x83\202\15 X64
ADC reg_al,imm \1\x14\21 8086,SM
-ADC reg_ax,sbyte \320\1\x83\202\15 8086,SM,ND
+ADC reg_ax,sbyte16 \320\1\x83\202\15 8086,SM,ND
ADC reg_ax,imm \320\1\x15\31 8086,SM
-ADC reg_eax,sbyte \321\1\x83\202\15 386,SM,ND
+ADC reg_eax,sbyte32 \321\1\x83\202\15 386,SM,ND
ADC reg_eax,imm \321\1\x15\41 386,SM
-ADC reg_rax,sbyte \324\1\x83\202\15 X64,SM,ND
+ADC reg_rax,sbyte64 \324\1\x83\202\15 X64,SM,ND
ADC reg_rax,imm \324\1\x15\41 X64,SM
ADC rm8,imm \1\x80\202\21 8086,SM
ADC rm16,imm \320\145\x81\202\141 8086,SM
ADC rm32,imm \321\155\x81\202\151 386,SM
-ADC rm64,imm \324\155\x81\202\151 X64,SM
+ADC rm64,imm \324\155\x81\202\251 X64,SM
ADC mem,imm8 \1\x80\202\21 8086,SM
ADC mem,imm16 \320\145\x81\202\141 8086,SM
ADC mem,imm32 \321\155\x81\202\151 386,SM
@@ -92,16 +92,16 @@ 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 reg_al,imm \1\x04\21 8086,SM
-ADD reg_ax,sbyte \320\1\x83\200\15 8086,SM,ND
+ADD reg_ax,sbyte16 \320\1\x83\200\15 8086,SM,ND
ADD reg_ax,imm \320\1\x05\31 8086,SM
-ADD reg_eax,sbyte \321\1\x83\200\15 386,SM,ND
+ADD reg_eax,sbyte32 \321\1\x83\200\15 386,SM,ND
ADD reg_eax,imm \321\1\x05\41 386,SM
-ADD reg_rax,sbyte \324\1\x83\200\15 X64,SM,ND
+ADD reg_rax,sbyte64 \324\1\x83\200\15 X64,SM,ND
ADD reg_rax,imm \324\1\x05\41 X64,SM
ADD rm8,imm \1\x80\200\21 8086,SM
ADD rm16,imm \320\145\x81\200\141 8086,SM
ADD rm32,imm \321\155\x81\200\151 386,SM
-ADD rm64,imm \324\155\x81\200\151 X64,SM
+ADD rm64,imm \324\155\x81\200\251 X64,SM
ADD mem,imm8 \1\x80\200\21 8086,SM
ADD mem,imm16 \320\145\x81\200\141 8086,SM
ADD mem,imm32 \321\155\x81\200\151 386,SM
@@ -125,16 +125,16 @@ AND rm16,imm8 \320\1\x83\204\15 8086
AND rm32,imm8 \321\1\x83\204\15 386
AND rm64,imm8 \324\1\x83\204\15 X64
AND reg_al,imm \1\x24\21 8086,SM
-AND reg_ax,sbyte \320\1\x83\204\15 8086,SM,ND
+AND reg_ax,sbyte16 \320\1\x83\204\15 8086,SM,ND
AND reg_ax,imm \320\1\x25\31 8086,SM
-AND reg_eax,sbyte \321\1\x83\204\15 386,SM,ND
+AND reg_eax,sbyte32 \321\1\x83\204\15 386,SM,ND
AND reg_eax,imm \321\1\x25\41 386,SM
-AND reg_rax,sbyte \324\1\x83\204\15 X64,SM,ND
+AND reg_rax,sbyte64 \324\1\x83\204\15 X64,SM,ND
AND reg_rax,imm \324\1\x25\41 X64,SM
AND rm8,imm \1\x80\204\21 8086,SM
AND rm16,imm \320\145\x81\204\141 8086,SM
AND rm32,imm \321\155\x81\204\151 386,SM
-AND rm64,imm \324\155\x81\204\151 X64,SM
+AND rm64,imm \324\155\x81\204\251 X64,SM
AND mem,imm8 \1\x80\204\21 8086,SM
AND mem,imm16 \320\145\x81\204\141 8086,SM
AND mem,imm32 \321\155\x81\204\151 386,SM
@@ -251,16 +251,16 @@ 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 reg_al,imm \1\x3C\21 8086,SM
-CMP reg_ax,sbyte \320\1\x83\207\15 8086,SM,ND
+CMP reg_ax,sbyte16 \320\1\x83\207\15 8086,SM,ND
CMP reg_ax,imm \320\1\x3D\31 8086,SM
-CMP reg_eax,sbyte \321\1\x83\207\15 386,SM,ND
+CMP reg_eax,sbyte32 \321\1\x83\207\15 386,SM,ND
CMP reg_eax,imm \321\1\x3D\41 386,SM
-CMP reg_rax,sbyte \324\1\x83\207\15 X64,SM,ND
+CMP reg_rax,sbyte64 \324\1\x83\207\15 X64,SM,ND
CMP reg_rax,imm \324\1\x3D\41 X64,SM
CMP rm8,imm \1\x80\207\21 8086,SM
CMP rm16,imm \320\145\x81\207\141 8086,SM
CMP rm32,imm \321\155\x81\207\151 386,SM
-CMP rm64,imm \324\155\x81\207\151 X64,SM
+CMP rm64,imm \324\155\x81\207\251 X64,SM
CMP mem,imm8 \1\x80\207\21 8086,SM
CMP mem,imm16 \320\145\x81\207\141 8086,SM
CMP mem,imm32 \321\155\x81\207\151 386,SM
@@ -546,40 +546,40 @@ IMUL reg32,reg32 \321\2\x0F\xAF\110 386
IMUL reg64,mem \324\2\x0F\xAF\110 X64,SM
IMUL reg64,reg64 \324\2\x0F\xAF\110 X64
IMUL reg16,mem,imm8 \320\1\x6B\110\16 186,SM
-IMUL reg16,mem,sbyte \320\1\x6B\110\16 186,SM,ND
+IMUL reg16,mem,sbyte16 \320\1\x6B\110\16 186,SM,ND
IMUL reg16,mem,imm16 \320\1\x69\110\32 186,SM
IMUL reg16,mem,imm \320\146\x69\110\142 186,SM,ND
IMUL reg16,reg16,imm8 \320\1\x6B\110\16 186
-IMUL reg16,reg16,sbyte \320\1\x6B\110\16 186,SM,ND
+IMUL reg16,reg16,sbyte32 \320\1\x6B\110\16 186,SM,ND
IMUL reg16,reg16,imm16 \320\1\x69\110\32 186
IMUL reg16,reg16,imm \320\146\x69\110\142 186,SM,ND
IMUL reg32,mem,imm8 \321\1\x6B\110\16 386,SM
-IMUL reg32,mem,sbyte \321\1\x6B\110\16 386,SM,ND
+IMUL reg32,mem,sbyte64 \321\1\x6B\110\16 386,SM,ND
IMUL reg32,mem,imm32 \321\1\x69\110\42 386,SM
IMUL reg32,mem,imm \321\156\x69\110\152 386,SM,ND
IMUL reg32,reg32,imm8 \321\1\x6B\110\16 386
-IMUL reg32,reg32,sbyte \321\1\x6B\110\16 386,SM,ND
+IMUL reg32,reg32,sbyte16 \321\1\x6B\110\16 386,SM,ND
IMUL reg32,reg32,imm32 \321\1\x69\110\42 386
IMUL reg32,reg32,imm \321\156\x69\110\152 386,SM,ND
IMUL reg64,mem,imm8 \324\1\x6B\110\16 X64,SM
-IMUL reg64,mem,sbyte \324\1\x6B\110\16 X64,SM,ND
+IMUL reg64,mem,sbyte32 \324\1\x6B\110\16 X64,SM,ND
IMUL reg64,mem,imm32 \324\1\x69\110\42 X64,SM
-IMUL reg64,mem,imm \324\156\x69\110\152 X64,SM,ND
+IMUL reg64,mem,imm \324\156\x69\110\252 X64,SM,ND
IMUL reg64,reg64,imm8 \324\1\x6B\110\16 X64
-IMUL reg64,reg64,sbyte \324\1\x6B\110\16 X64,SM,ND
+IMUL reg64,reg64,sbyte64 \324\1\x6B\110\16 X64,SM,ND
IMUL reg64,reg64,imm32 \324\1\x69\110\42 X64
-IMUL reg64,reg64,imm \324\156\x69\110\152 X64,SM,ND
+IMUL reg64,reg64,imm \324\156\x69\110\252 X64,SM,ND
IMUL reg16,imm8 \320\1\x6B\100\15 186
-IMUL reg16,sbyte \320\1\x6B\100\15 186,SM,ND
+IMUL reg16,sbyte16 \320\1\x6B\100\15 186,SM,ND
IMUL reg16,imm16 \320\1\x69\100\31 186
IMUL reg16,imm \320\145\x69\100\141 186,SM,ND
IMUL reg32,imm8 \321\1\x6B\100\15 386
-IMUL reg32,sbyte \321\1\x6B\100\15 386,SM,ND
+IMUL reg32,sbyte32 \321\1\x6B\100\15 386,SM,ND
IMUL reg32,imm32 \321\1\x69\100\41 386
IMUL reg32,imm \321\155\x69\100\151 386,SM,ND
-IMUL reg64,sbyte \324\1\x6B\100\15 X64,SM,ND
+IMUL reg64,sbyte64 \324\1\x6B\100\15 X64,SM,ND
IMUL reg64,imm32 \324\1\x69\100\41 X64
-IMUL reg64,imm \324\155\x69\100\151 X64,SM,ND
+IMUL reg64,imm \324\155\x69\100\251 X64,SM,ND
IN reg_al,imm \1\xE4\25 8086,SB
IN reg_ax,imm \320\1\xE5\25 8086,SB
IN reg_eax,imm \321\1\xE5\25 386,SB
@@ -849,16 +849,16 @@ 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 reg_al,imm \1\x0C\21 8086,SM
-OR reg_ax,sbyte \320\1\x83\201\15 8086,SM,ND
+OR reg_ax,sbyte16 \320\1\x83\201\15 8086,SM,ND
OR reg_ax,imm \320\1\x0D\31 8086,SM
-OR reg_eax,sbyte \321\1\x83\201\15 386,SM,ND
+OR reg_eax,sbyte32 \321\1\x83\201\15 386,SM,ND
OR reg_eax,imm \321\1\x0D\41 386,SM
-OR reg_rax,sbyte \324\1\x83\201\15 X64,SM,ND
+OR reg_rax,sbyte64 \324\1\x83\201\15 X64,SM,ND
OR reg_rax,imm \324\1\x0D\41 X64,SM
OR rm8,imm \1\x80\201\21 8086,SM
OR rm16,imm \320\145\x81\201\141 8086,SM
OR rm32,imm \321\155\x81\201\151 386,SM
-OR rm64,imm \324\155\x81\201\151 X64,SM
+OR rm64,imm \324\155\x81\201\251 X64,SM
OR mem,imm8 \1\x80\201\21 8086,SM
OR mem,imm16 \320\145\x81\201\141 8086,SM
OR mem,imm32 \321\155\x81\201\151 386,SM
@@ -982,11 +982,10 @@ 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 sbyte \1\x6A\14 186,ND
-PUSH imm16 \320\144\x68\140 186
-PUSH imm32 \321\154\x68\150 386,NOLONG
-PUSH imm64 \321\154\x68\150 X64
-PUSH imm \1\x68\34 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
+PUSH imm64 \323\154\x68\250 X64,AR0,SZ
PUSHA void \322\1\x60 186,NOLONG
PUSHAD void \321\1\x60 386,NOLONG
PUSHAW void \320\1\x60 186,NOLONG
@@ -1105,16 +1104,16 @@ 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 reg_al,imm \1\x1C\21 8086,SM
-SBB reg_ax,sbyte \320\1\x83\203\15 8086,SM,ND
+SBB reg_ax,sbyte16 \320\1\x83\203\15 8086,SM,ND
SBB reg_ax,imm \320\1\x1D\31 8086,SM
-SBB reg_eax,sbyte \321\1\x83\203\15 386,SM,ND
+SBB reg_eax,sbyte32 \321\1\x83\203\15 386,SM,ND
SBB reg_eax,imm \321\1\x1D\41 386,SM
-SBB reg_rax,sbyte \324\1\x83\203\15 X64,SM,ND
+SBB reg_rax,sbyte64 \324\1\x83\203\15 X64,SM,ND
SBB reg_rax,imm \324\1\x1D\41 X64,SM
SBB rm8,imm \1\x80\203\21 8086,SM
SBB rm16,imm \320\145\x81\203\141 8086,SM
SBB rm32,imm \321\155\x81\203\151 386,SM
-SBB rm64,imm \324\155\x81\203\151 X64,SM
+SBB rm64,imm \324\155\x81\203\251 X64,SM
SBB mem,imm8 \1\x80\203\21 8086,SM
SBB mem,imm16 \320\145\x81\203\141 8086,SM
SBB mem,imm32 \321\155\x81\203\151 386,SM
@@ -1219,16 +1218,16 @@ 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 reg_al,imm \1\x2C\21 8086,SM
-SUB reg_ax,sbyte \320\1\x83\205\15 8086,SM,ND
+SUB reg_ax,sbyte16 \320\1\x83\205\15 8086,SM,ND
SUB reg_ax,imm \320\1\x2D\31 8086,SM
-SUB reg_eax,sbyte \321\1\x83\205\15 386,SM,ND
+SUB reg_eax,sbyte32 \321\1\x83\205\15 386,SM,ND
SUB reg_eax,imm \321\1\x2D\41 386,SM
-SUB reg_rax,sbyte \324\1\x83\205\15 X64,SM,ND
+SUB reg_rax,sbyte64 \324\1\x83\205\15 X64,SM,ND
SUB reg_rax,imm \324\1\x2D\41 X64,SM
SUB rm8,imm \1\x80\205\21 8086,SM
SUB rm16,imm \320\145\x81\205\141 8086,SM
SUB rm32,imm \321\155\x81\205\151 386,SM
-SUB rm64,imm \324\155\x81\205\151 X64,SM
+SUB rm64,imm \324\155\x81\205\251 X64,SM
SUB mem,imm8 \1\x80\205\21 8086,SM
SUB mem,imm16 \320\145\x81\205\141 8086,SM
SUB mem,imm32 \321\155\x81\205\151 386,SM
@@ -1348,16 +1347,16 @@ 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 reg_al,imm \1\x34\21 8086,SM
-XOR reg_ax,sbyte \320\1\x83\206\15 8086,SM,ND
+XOR reg_ax,sbyte16 \320\1\x83\206\15 8086,SM,ND
XOR reg_ax,imm \320\1\x35\31 8086,SM
-XOR reg_eax,sbyte \321\1\x83\206\15 386,SM,ND
+XOR reg_eax,sbyte32 \321\1\x83\206\15 386,SM,ND
XOR reg_eax,imm \321\1\x35\41 386,SM
-XOR reg_rax,sbyte \324\1\x83\206\15 X64,SM,ND
+XOR reg_rax,sbyte64 \324\1\x83\206\15 X64,SM,ND
XOR reg_rax,imm \324\1\x35\41 X64,SM
XOR rm8,imm \1\x80\206\21 8086,SM
XOR rm16,imm \320\145\x81\206\141 8086,SM
XOR rm32,imm \321\155\x81\206\151 386,SM
-XOR rm64,imm \324\155\x81\206\151 X64,SM
+XOR rm64,imm \324\155\x81\206\251 X64,SM
XOR mem,imm8 \1\x80\206\21 8086,SM
XOR mem,imm16 \320\145\x81\206\141 8086,SM
XOR mem,imm32 \321\155\x81\206\151 386,SM
diff --git a/insns.h b/insns.h
index 3fefa457..49cc1851 100644
--- a/insns.h
+++ b/insns.h
@@ -72,12 +72,14 @@ extern const struct disasm_index itable[256];
#define IF_SD 0x0000000CUL /* unsized operands can't be non-dword */
#define IF_SQ 0x00000010UL /* unsized operands can't be non-qword */
#define IF_SO 0x00000014UL /* unsized operands can't be non-oword */
+#define IF_SZ 0x00000018UL /* unsized operands must match the bitsize */
#define IF_SMASK 0x0000001CUL /* mask for unsized argument size */
#define IF_AR0 0x00000020UL /* SB, SW, SD applies to argument 0 */
#define IF_AR1 0x00000040UL /* SB, SW, SD applies to argument 1 */
#define IF_AR2 0x00000060UL /* SB, SW, SD applies to argument 2 */
-#define IF_AR3 0x00000080UL /* SB, SW, SD applies to argument 2 */
+#define IF_AR3 0x00000080UL /* SB, SW, SD applies to argument 3 */
#define IF_ARMASK 0x000000E0UL /* mask for unsized argument spec */
+#define IF_ARSHFT 5 /* LSB in IF_ARMASK */
#define IF_PRIV 0x00000100UL /* it's a privileged instruction */
#define IF_SMM 0x00000200UL /* it's only valid in SMM */
#define IF_PROT 0x00000400UL /* it's protected mode only */
diff --git a/nasm.h b/nasm.h
index b2c1e93c..2591b1ce 100644
--- a/nasm.h
+++ b/nasm.h
@@ -428,7 +428,9 @@ enum {
*
* With IMMEDIATE:
* 16: UNITY (1)
- * 17: BYTENESS (-128..127)
+ * 17: BYTENESS16 (-128..127)
+ * 18: BYTENESS32 (-128..127)
+ * 19: BYTENESS64 (-128..127)
*
* Bits 20-26: register classes
* 20: REG_CDT (CRx, DRx, TRx)
@@ -539,7 +541,9 @@ typedef uint32_t opflags_t;
/* special type of immediate operand */
#define UNITY 0x00012000U /* for shift/rotate instructions */
-#define SBYTE 0x00022000U /* for op r16/32,immediate instrs. */
+#define SBYTE16 0x00022000U /* for op r16,immediate instrs. */
+#define SBYTE32 0x00042000U /* for op r32,immediate instrs. */
+#define SBYTE64 0x00082000U /* for op r64,immediate instrs. */
/* special flags */
#define SAME_AS 0x40000000U
diff --git a/parser.c b/parser.c
index 5983af54..9172fb1c 100644
--- a/parser.c
+++ b/parser.c
@@ -797,9 +797,16 @@ restart_parse:
result->oprs[operand].type |= UNITY;
if (optimizing >= 0 &&
!(result->oprs[operand].type & STRICT)) {
- if (reloc_value(value) >= -128 &&
- reloc_value(value) <= 127)
- result->oprs[operand].type |= SBYTE;
+ int64_t v64 = reloc_value(value);
+ int32_t v32 = (int32_t)v64;
+ int16_t v16 = (int16_t)v32;
+
+ if (v64 >= -128 && v64 <= 127)
+ result->oprs[operand].type |= SBYTE64;
+ if (v32 >= -128 && v32 <= 127)
+ result->oprs[operand].type |= SBYTE32;
+ if (v16 >= -128 && v16 <= 127)
+ result->oprs[operand].type |= SBYTE16;
}
}
} else { /* it's a register */