From eabb37e6ebd2ed85c7728e8a006b3d9620410cf3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 12 Jun 2008 10:56:48 -0600 Subject: [PATCH] add lcmp instruction to Compiler and corresponding LongCompare instruction to Assembler, since that's the only efficient way to implement the lcmp bytecode on x86 --- src/assembler.h | 1 + src/compile.cpp | 30 +---- src/compiler.cpp | 11 +- src/compiler.h | 1 + src/x86.cpp | 284 ++++++++++++++++++++++++++++------------------- 5 files changed, 180 insertions(+), 147 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 8369c59064..ca7926965b 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -37,6 +37,7 @@ enum BinaryOperation { MoveZ, Move4To8, Swap, + LongCompare, Compare, Add, Subtract, diff --git a/src/compile.cpp b/src/compile.cpp index 4bd272b352..ec3c1d9235 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2836,38 +2836,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } break; case lcmp: { - Compiler::Operand* next = c->label(); - Compiler::Operand* less = c->label(); - Compiler::Operand* greater = c->label(); - Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - c->cmp(8, a, b); - - c->jl(less); - c->pushState(); - - c->jg(greater); - c->pushState(); - - c->push(4, c->constant(0)); - c->jmp(next); - - c->popState(); - c->mark(less); - - c->push(4, c->constant(-1)); - c->jmp(next); - - c->popState(); - c->mark(greater); - - c->push(4, c->constant(1)); - - c->mark(next); - - frame->pushedInt(); + frame->pushInt(c->load(4, c->lcmp(a, b))); } break; case lconst_0: diff --git a/src/compiler.cpp b/src/compiler.cpp index fddab04ae0..bffbf37b0c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1742,7 +1742,7 @@ class CombineEvent: public Event { removeSite(c, second, second->source); if (result->reads) { - addSite(c, 0, 0, result, second->source); + addSite(c, 0, size, result, second->source); } } @@ -1824,7 +1824,7 @@ class TranslateEvent: public Event { removeSite(c, value, value->source); if (result->reads) { - addSite(c, 0, 0, result, value->source); + addSite(c, 0, size, result, value->source); } } @@ -2917,6 +2917,13 @@ class MyCompiler: public Compiler { return dst; } + virtual Operand* lcmp(Operand* a, Operand* b) { + Value* result = value(&c); + appendCombine(&c, LongCompare, 8, static_cast(a), + static_cast(b), result); + return result; + } + virtual void cmp(unsigned size, Operand* a, Operand* b) { appendCompare(&c, size, static_cast(a), static_cast(b)); diff --git a/src/compiler.h b/src/compiler.h index 89f2aa0a49..621f941019 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -91,6 +91,7 @@ class Compiler { virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; virtual Operand* load4To8(Operand* src) = 0; + virtual Operand* lcmp(Operand* a, Operand* b) = 0; virtual void cmp(unsigned size, Operand* a, Operand* b) = 0; virtual void jl(Operand* address) = 0; virtual void jg(Operand* address) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index dd9a042fac..3e5ec4c17f 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1590,47 +1590,143 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, } void -multiwordCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah, - Assembler::Operand* bl, Assembler::Operand* bh, - BinaryOperationType op) +longCompareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) { - op(c, BytesPerWord, ah, bh); + assert(c, size == 8); - // if the high order bits are equal, we compare the low order - // bits; otherwise, we jump past that comparison - c->code.append(0x0f); - c->code.append(0x85); // jne + int64_t v = a->value->value(); + + ResolvedPromise negativePromise(-1); + Assembler::Constant negative(&negativePromise); - unsigned comparisonOffset = c->code.length(); - c->code.append4(0); + ResolvedPromise zeroPromise(0); + Assembler::Constant zero(&zeroPromise); - op(c, BytesPerWord, al, bl); + ResolvedPromise positivePromise(1); + Assembler::Constant positive(&positivePromise); - int32_t comparisonSize = c->code.length() - comparisonOffset - 4; - c->code.set(comparisonOffset, &comparisonSize, 4); + if (BytesPerWord == 8) { + compareCR(c, 8, a, b); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + unsigned less = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x8f); // jg + unsigned greater = c->code.length(); + c->code.append4(0); + + moveCR(c, 4, &zero, b); + + c->code.append(0xe9); // jmp + unsigned nextFirst = c->code.length(); + c->code.append4(0); + + int32_t lessOffset = c->code.length() - less - 4; + c->code.set(less, &lessOffset, 4); + + moveCR(c, 4, &negative, b); + + c->code.append(0xe9); // jmp + unsigned nextSecond = c->code.length(); + c->code.append4(0); + + int32_t greaterOffset = c->code.length() - greater - 4; + c->code.set(greater, &greaterOffset, 4); + + moveCR(c, 4, &positive, b); + + int32_t nextFirstOffset = c->code.length() - nextFirst - 4; + c->code.set(nextFirst, &nextFirstOffset, 4); + + int32_t nextSecondOffset = c->code.length() - nextSecond - 4; + c->code.set(nextSecond, &nextSecondOffset, 4); + } else { + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + Assembler::Register bh(b->high); + + compareCR(c, 4, &ah, &bh); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + unsigned less = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x8f); // jg + unsigned greater = c->code.length(); + c->code.append4(0); + + compareCR(c, 4, &al, b); + + c->code.append(0x0f); + c->code.append(0x82); // ja + unsigned above = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x87); // jb + unsigned below = c->code.length(); + c->code.append4(0); + + moveCR(c, 4, &zero, b); + + c->code.append(0xe9); // jmp + unsigned nextFirst = c->code.length(); + c->code.append4(0); + + int32_t lessOffset = c->code.length() - less - 4; + c->code.set(less, &lessOffset, 4); + + int32_t aboveOffset = c->code.length() - above - 4; + c->code.set(above, &aboveOffset, 4); + + moveCR(c, 4, &negative, b); + + c->code.append(0xe9); // jmp + unsigned nextSecond = c->code.length(); + c->code.append4(0); + + int32_t greaterOffset = c->code.length() - greater - 4; + c->code.set(greater, &greaterOffset, 4); + + int32_t belowOffset = c->code.length() - below - 4; + c->code.set(below, &belowOffset, 4); + + moveCR(c, 4, &positive, b); + + int32_t nextFirstOffset = c->code.length() - nextFirst - 4; + c->code.set(nextFirst, &nextFirstOffset, 4); + + int32_t nextSecondOffset = c->code.length() - nextSecond - 4; + c->code.set(nextSecond, &nextSecondOffset, 4); + } } void compareRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + assert(c, BytesPerWord == 8 or size == 4); - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRR)); - } else { - if (size == 8) rex(c); - c->code.append(0x39); - c->code.append(0xc0 | (a->low << 3) | b->low); - } + if (size == 8) rex(c); + c->code.append(0x39); + c->code.append(0xc0 | (a->low << 3) | b->low); } void compareAR(Context* c, unsigned size, Assembler::Address* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + assert(c, BytesPerWord == 8 or size == 4); Assembler::Register tmp(c->client->acquireTemporary()); moveAR(c, size, a, &tmp); @@ -1642,36 +1738,26 @@ void compareCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { + assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); - if (BytesPerWord == 4 and size == 8) { - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); - - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); - - Assembler::Register bh(b->high); - - multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCR)); - } else { - if (isInt32(v)) { - if (size == 8) rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xf8 | b->low); - c->code.append(v); - } else { - c->code.append(0x81); - c->code.append(0xf8 | b->low); - c->code.append4(v); - } + if (isInt32(v)) { + if (size == 8) rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf8 | b->low); + c->code.append(v); } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - compareRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + c->code.append(0x81); + c->code.append(0xf8 | b->low); + c->code.append4(v); } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + compareRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } } @@ -1679,28 +1765,18 @@ void compareCM(Context* c, unsigned size, Assembler::Constant* a, Assembler::Memory* b) { + assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); - if (BytesPerWord == 4 and size == 8) { - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); - - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCM)); + if (isInt8(v)) { + c->code.append(v); + } else if (isInt32(v)) { + c->code.append4(v); } else { - encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); - - if (isInt8(v)) { - c->code.append(v); - } else if (isInt32(v)) { - c->code.append4(v); - } else { - abort(c); - } + abort(c); } } @@ -1708,75 +1784,48 @@ void compareRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRM)); - } else { - if (BytesPerWord == 8 and size == 4) { - move4To8RR(c, size, a, a); - } - encode(c, 0x39, a->low, b, true); + assert(c, BytesPerWord == 8 or size == 4); + + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, a, a); } + encode(c, 0x39, a->low, b, true); } void compareMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); - Assembler::Register bh(b->high); - - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMR)); - } else { - if (BytesPerWord == 8 and size == 4) { - move4To8RR(c, size, b, b); - } - encode(c, 0x3b, b->low, a, true); + assert(c, BytesPerWord == 8 or size == 4); + + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, b, b); } + encode(c, 0x3b, b->low, a, true); } void compareMM(Context* c, unsigned size, Assembler::Memory* a, Assembler::Memory* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMM)); - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, size, a, &tmp); - compareRM(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); - } + assert(c, BytesPerWord == 8 or size == 4); + + Assembler::Register tmp(c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + compareRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } void compareRC(Context* c, unsigned size, Assembler::Register* a, Assembler::Constant* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); - - int64_t v = b->value->value(); - - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant bl(&low); - - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant bh(&high); - - multiwordCompare(c, a, &ah, &bl, &bh, CAST2(compareRC)); - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, b, &tmp); - compareRR(c, size, a, &tmp); - c->client->releaseTemporary(tmp.low); - } + assert(c, BytesPerWord == 8 or size == 4); + + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, b, &tmp); + compareRR(c, size, a, &tmp); + c->client->releaseTemporary(tmp.low); } void @@ -1882,6 +1931,9 @@ populateTables() BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); + BinaryOperations[INDEX2(LongCompare, Constant, Register)] + = CAST2(longCompareCR); + BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC); BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR);