Skip to content

Commit 588e15c

Browse files
epertosoCommit bot
authored andcommitted
[ia32] Fixes a bug in cmpw.
The opcodes for 'cmpw r/m16, r16' and 'cmpw r16, r/m16' were swapped, causing a few issues when less than/greater than comparison were performed. Adds a regression test. BUG=621926 Committed: https://crrev.com/efa7095e3e360fbadbe909d831ac11b268ca26b0 Review-Url: https://codereview.chromium.org/2103713003 Cr-Original-Commit-Position: refs/heads/master@{#37339} Cr-Commit-Position: refs/heads/master@{#37345}
1 parent 05638b9 commit 588e15c

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

src/ia32/assembler-ia32.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -852,14 +852,14 @@ void Assembler::cmpw(const Operand& op, Immediate imm16) {
852852
void Assembler::cmpw(Register reg, const Operand& op) {
853853
EnsureSpace ensure_space(this);
854854
EMIT(0x66);
855-
EMIT(0x39);
855+
EMIT(0x3B);
856856
emit_operand(reg, op);
857857
}
858858

859859
void Assembler::cmpw(const Operand& op, Register reg) {
860860
EnsureSpace ensure_space(this);
861861
EMIT(0x66);
862-
EMIT(0x3B);
862+
EMIT(0x39);
863863
emit_operand(reg, op);
864864
}
865865

src/ia32/disasm-ia32.cc

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,11 +1622,19 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
16221622
while (*data == 0x66) data++;
16231623
if (*data == 0xf && data[1] == 0x1f) {
16241624
AppendToBuffer("nop"); // 0x66 prefix
1625-
} else if (*data == 0x90) {
1626-
AppendToBuffer("nop"); // 0x66 prefix
1627-
} else if (*data == 0x8B) {
1625+
} else if (*data == 0x39) {
16281626
data++;
1629-
data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1627+
data += PrintOperands("cmpw", OPER_REG_OP_ORDER, data);
1628+
} else if (*data == 0x3B) {
1629+
data++;
1630+
data += PrintOperands("cmpw", REG_OPER_OP_ORDER, data);
1631+
} else if (*data == 0x81) {
1632+
data++;
1633+
AppendToBuffer("cmpw ");
1634+
data += PrintRightOperand(data);
1635+
int imm = *reinterpret_cast<int16_t*>(data);
1636+
AppendToBuffer(",0x%x", imm);
1637+
data += 2;
16301638
} else if (*data == 0x87) {
16311639
data++;
16321640
int mod, regop, rm;
@@ -1640,6 +1648,11 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
16401648
AppendToBuffer("mov_w ");
16411649
data += PrintRightOperand(data);
16421650
AppendToBuffer(",%s", NameOfCPURegister(regop));
1651+
} else if (*data == 0x8B) {
1652+
data++;
1653+
data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1654+
} else if (*data == 0x90) {
1655+
AppendToBuffer("nop"); // 0x66 prefix
16431656
} else if (*data == 0xC7) {
16441657
data++;
16451658
AppendToBuffer("%s ", "mov_w");

test/cctest/test-assembler-ia32.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,4 +1497,45 @@ TEST(AssemblerIa32JumpTables2) {
14971497
}
14981498
}
14991499

1500+
TEST(Regress621926) {
1501+
// Bug description:
1502+
// The opcodes for cmpw r/m16, r16 and cmpw r16, r/m16 were swapped.
1503+
// This was causing non-commutative comparisons to produce the wrong result.
1504+
CcTest::InitializeVM();
1505+
Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1506+
HandleScope scope(isolate);
1507+
Assembler assm(isolate, nullptr, 0);
1508+
1509+
int16_t a = 42;
1510+
1511+
Label fail;
1512+
__ push(ebx);
1513+
__ mov(ebx, Immediate(reinterpret_cast<intptr_t>(&a)));
1514+
__ mov(eax, Immediate(41));
1515+
__ cmpw(eax, Operand(ebx));
1516+
__ j(above_equal, &fail);
1517+
__ cmpw(Operand(ebx), eax);
1518+
__ j(below_equal, &fail);
1519+
__ mov(eax, 1);
1520+
__ pop(ebx);
1521+
__ ret(0);
1522+
__ bind(&fail);
1523+
__ mov(eax, 0);
1524+
__ pop(ebx);
1525+
__ ret(0);
1526+
1527+
CodeDesc desc;
1528+
assm.GetCode(&desc);
1529+
Handle<Code> code = isolate->factory()->NewCode(
1530+
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1531+
1532+
#ifdef OBJECT_PRINT
1533+
OFStream os(stdout);
1534+
code->Print(os);
1535+
#endif
1536+
1537+
F0 f = FUNCTION_CAST<F0>(code->entry());
1538+
CHECK_EQ(f(), 1);
1539+
}
1540+
15001541
#undef __

0 commit comments

Comments
 (0)