diff --git a/makefile b/makefile index 553125d966..d0f9761473 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ MAKEFLAGS = -s name = avian -version = 0.0.1 +version = 0.1 build-arch = "$(shell uname -m)" ifeq ($(build-arch),"Power Macintosh") 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 b012acb37c..5f7ba20a2c 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1834,67 +1834,34 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (&singletonValue(t, aioobThunk(t), 0))); } - if (c->isConstant(index)) { - unsigned i = c->constantValue(index); - switch (instruction) { - case aaload: - frame->pushObject - (c->load - (BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord)))); - break; + switch (instruction) { + case aaload: + frame->pushObject + (c->load + (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); + break; - case faload: - case iaload: - frame->pushInt(c->load(4, c->memory(array, ArrayBody + (i * 4)))); - break; + case faload: + case iaload: + frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); + break; - case baload: - frame->pushInt(c->load(1, c->memory(array, ArrayBody + i))); - break; + case baload: + frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); + break; - case caload: - frame->pushInt(c->loadz(2, c->memory(array, ArrayBody + (i * 2)))); - break; + case caload: + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); + break; - case daload: - case laload: - frame->pushLong(c->load(8, c->memory(array, ArrayBody + (i * 8)))); - break; + case daload: + case laload: + frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); + break; - case saload: - frame->pushInt(c->load(2, c->memory(array, ArrayBody + (i * 2)))); - break; - } - } else { - switch (instruction) { - case aaload: - frame->pushObject - (c->load - (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); - break; - - case faload: - case iaload: - frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); - break; - - case baload: - frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); - break; - - case caload: - frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); - break; - - case daload: - case laload: - frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); - break; - - case saload: - frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); - break; - } + case saload: + frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); + break; } } break; @@ -1923,72 +1890,37 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (&singletonValue(t, aioobThunk(t), 0))); } - if (c->isConstant(index)) { - unsigned i = c->constantValue(index); - switch (instruction) { - case aastore: { - c->call - (c->constant(getThunk(t, setMaybeNullThunk)), - 0, - frame->trace(0, false), - 0, - 4, c->thread(), array, - c->constant(ArrayBody + (i * BytesPerWord)), - value); - } break; + switch (instruction) { + case aastore: { + c->call + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, + frame->trace(0, false), + 0, + 4, c->thread(), array, + c->add(4, c->constant(ArrayBody), + c->shl(4, c->constant(log(BytesPerWord)), index)), + value); + } break; - case fastore: - case iastore: - c->store(4, value, c->memory(array, ArrayBody + (i * 4))); - break; + case fastore: + case iastore: + c->store(4, value, c->memory(array, ArrayBody, index, 4)); + break; - case bastore: - c->store(1, value, c->memory(array, ArrayBody + i)); - break; + case bastore: + c->store(1, value, c->memory(array, ArrayBody, index, 1)); + break; - case castore: - case sastore: - c->store(2, value, c->memory(array, ArrayBody + (i * 2))); - break; + case castore: + case sastore: + c->store(2, value, c->memory(array, ArrayBody, index, 2)); + break; - case dastore: - case lastore: - c->store(8, value, c->memory(array, ArrayBody + (i * 8))); - break; - } - } else { - switch (instruction) { - case aastore: { - c->call - (c->constant(getThunk(t, setMaybeNullThunk)), - 0, - frame->trace(0, false), - 0, - 4, c->thread(), array, - c->add(4, c->constant(ArrayBody), - c->shl(4, c->constant(log(BytesPerWord)), index)), - value); - } break; - - case fastore: - case iastore: - c->store(4, value, c->memory(array, ArrayBody, index, 4)); - break; - - case bastore: - c->store(1, value, c->memory(array, ArrayBody, index, 1)); - break; - - case castore: - case sastore: - c->store(2, value, c->memory(array, ArrayBody, index, 2)); - break; - - case dastore: - case lastore: - c->store(8, value, c->memory(array, ArrayBody, index, 8)); - break; - } + case dastore: + case lastore: + c->store(8, value, c->memory(array, ArrayBody, index, 8)); + break; } } break; @@ -2602,7 +2534,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jle(target); break; } - + compile(t, frame, newIp); if (UNLIKELY(t->exception)) return; } break; @@ -2858,6 +2790,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, assert(t, newIp < codeLength(t, code)); + c->saveStack(); + frame->pushAddress(frame->machineIp(ip)); c->jmp(frame->machineIp(newIp)); @@ -2902,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 53ca697095..bffbf37b0c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -37,6 +37,13 @@ apply(Context* c, UnaryOperation op, unsigned size, Site* a); void apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b); +enum ConstantCompare { + CompareNone, + CompareLess, + CompareGreater, + CompareEqual +}; + class Site { public: Site(): next(0) { } @@ -207,7 +214,8 @@ class Context { machineCode(0), locals(0), localTable(0), - stackReset(false) + stackReset(false), + constantCompare(CompareNone) { for (unsigned i = 0; i < assembler->registerCount(); ++i) { registers[i] = new (zone->allocate(sizeof(Register))) Register(i); @@ -238,6 +246,7 @@ class Context { Local* locals; Local** localTable; bool stackReset; + ConstantCompare constantCompare; }; class PoolPromise: public Promise { @@ -999,7 +1008,7 @@ trySteal(Context* c, Register* r, Stack* stack) unsigned count = 0; Stack* start = 0; for (Stack* s = stack; s and (not s->pushed); s = s->next) { - if (s->value == v) { + if (start == 0 and s->value == v) { start = s; } if (start) { @@ -1595,6 +1604,17 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); } +ConstantSite* +findConstantSite(Context* c, Value* v) +{ + for (Site* s = v->sites; s; s = s->next) { + if (s->type(c) == ConstantOperand) { + return static_cast(s); + } + } + return 0; +} + class CompareEvent: public Event { public: CompareEvent(Context* c, unsigned size, Value* first, Value* second, @@ -1610,7 +1630,25 @@ class CompareEvent: public Event { fprintf(stderr, "CompareEvent.compile\n"); } - apply(c, Compare, size, first->source, second->source); + ConstantSite* firstConstant = findConstantSite(c, first); + ConstantSite* secondConstant = findConstantSite(c, second); + + if (firstConstant and secondConstant) { + int64_t d = firstConstant->value.value->value() + - secondConstant->value.value->value(); + + if (d < 0) { + c->constantCompare = CompareLess; + } else if (d > 0) { + c->constantCompare = CompareGreater; + } else { + c->constantCompare = CompareEqual; + } + } else { + c->constantCompare = CompareNone; + + apply(c, Compare, size, first->source, second->source); + } nextRead(c, first); nextRead(c, second); @@ -1704,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); } } @@ -1786,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); } } @@ -1826,7 +1864,7 @@ class MemoryEvent: public Event { scale(scale), result(result) { addRead(c, base, BytesPerWord, anyRegisterSite(c)); - if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c)); + if (index) addRead(c, index, BytesPerWord, registerOrConstantSite(c)); } virtual void compile(Context* c) { @@ -1835,9 +1873,20 @@ class MemoryEvent: public Event { } int indexRegister; + int displacement = this->displacement; + unsigned scale = this->scale; if (index) { - assert(c, index->source->type(c) == RegisterOperand); - indexRegister = static_cast(index->source)->register_.low; + ConstantSite* constant = findConstantSite(c, index); + + if (constant) { + indexRegister = NoRegister; + displacement += (constant->value.value->value() * scale); + scale = 1; + } else { + assert(c, index->source->type(c) == RegisterOperand); + indexRegister = static_cast + (index->source)->register_.low; + } } else { indexRegister = NoRegister; } @@ -1846,7 +1895,7 @@ class MemoryEvent: public Event { nextRead(c, base); if (index) { - if (BytesPerWord == 8) { + if (BytesPerWord == 8 and indexRegister != NoRegister) { apply(c, Move4To8, 8, index->source, index->source); } @@ -1920,22 +1969,23 @@ popNow(Context* c, Stack* stack, unsigned count, bool ignore) s->pushSite = 0; s->pushed = false; - if (s->value->reads and (not ignore)) { + Value* v = s->value; + if (v->reads and v->sites == 0 and (not ignore)) { ::ignore(c, ignored); - Site* target = targetOrRegister(c, s->value); + Site* target = targetOrRegister(c, v); if (DebugStack) { fprintf(stderr, "pop %p value: %p target: %p\n", s, s->value, target); } - addSite(c, stack, s->size * BytesPerWord, s->value, target); + addSite(c, stack, s->size * BytesPerWord, v, target); apply(c, Pop, BytesPerWord * s->size, target); } else { if (DebugStack) { - fprintf(stderr, "ignore %p value: %p\n", s, s->value); + fprintf(stderr, "ignore %p value: %p\n", s, v); } ignored += s->size; @@ -2005,7 +2055,65 @@ class BranchEvent: public Event { fprintf(stderr, "BranchEvent.compile\n"); } - apply(c, type, BytesPerWord, address->source); + bool jump; + UnaryOperation type = this->type; + if (type != Jump) { + switch (c->constantCompare) { + case CompareLess: + switch (type) { + case JumpIfLess: + case JumpIfLessOrEqual: + case JumpIfNotEqual: + jump = true; + type = Jump; + break; + + default: + jump = false; + } + break; + + case CompareGreater: + switch (type) { + case JumpIfGreater: + case JumpIfGreaterOrEqual: + case JumpIfNotEqual: + jump = true; + type = Jump; + break; + + default: + jump = false; + } + break; + + case CompareEqual: + switch (type) { + case JumpIfEqual: + case JumpIfLessOrEqual: + case JumpIfGreaterOrEqual: + jump = true; + type = Jump; + break; + + default: + jump = false; + } + break; + + case CompareNone: + jump = true; + break; + + default: abort(c); + } + } else { + jump = true; + } + + if (jump) { + apply(c, type, BytesPerWord, address->source); + } nextRead(c, address); } @@ -2203,14 +2311,7 @@ class BoundsCheckEvent: public Event { Assembler* a = c->assembler; - ConstantSite* constant = 0; - for (Site* s = index->sites; s; s = s->next) { - if (s->type(c) == ConstantOperand) { - constant = static_cast(s); - break; - } - } - + ConstantSite* constant = findConstantSite(c, index); CodePromise* nextPromise = codePromise(c, -1); CodePromise* outOfBoundsPromise = 0; @@ -2232,7 +2333,7 @@ class BoundsCheckEvent: public Event { Site* length = memorySite(c, base, lengthOffset); length->acquire(c, 0, 0, 0); - apply(c, Compare, BytesPerWord, index->source, length); + apply(c, Compare, 4, index->source, length); length->release(c); @@ -2641,22 +2742,6 @@ class MyCompiler: public Compiler { return value(&c, s, s); } - virtual bool isConstant(Operand* a) { - for (Site* s = static_cast(a)->sites; s; s = s->next) { - if (s->type(&c) == ConstantOperand) return true; - } - return false; - } - - virtual int64_t constantValue(Operand* a) { - for (Site* s = static_cast(a)->sites; s; s = s->next) { - if (s->type(&c) == ConstantOperand) { - return static_cast(s)->value.value->value(); - } - } - abort(&c); - } - virtual Operand* label() { return value(&c, ::constantSite(&c, static_cast(0))); } @@ -2698,7 +2783,8 @@ class MyCompiler: public Compiler { Value* v = value(&c); c.state->stack = ::stack(&c, v, 1, c.state->stack); c.state->stack->pushed = true; -// v->sites = pushSite(&c, c.state->stack->index); + c.state->stack->pushSite + = v->sites = pushSite(&c, c.state->stack->index); } } @@ -2831,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 6d27a60cc1..621f941019 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -62,9 +62,6 @@ class Compiler { virtual Operand* base() = 0; virtual Operand* thread() = 0; - virtual bool isConstant(Operand* value) = 0; - virtual int64_t constantValue(Operand* value) = 0; - virtual Operand* label() = 0; virtual void mark(Operand* label) = 0; @@ -94,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 8f0e05eab4..0a515f2fba 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -771,6 +771,13 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) } } +void +move4To8CR(Context* c, unsigned, Assembler::Constant* a, + Assembler::Register* b) +{ + moveCR(c, 8, a, b); +} + void move4To8RR(Context* c, unsigned, Assembler::Register* a, Assembler::Register* b) @@ -1144,7 +1151,7 @@ multiplyCR(Context* c, unsigned size, Assembler::Constant* a, c->client->releaseTemporary(tmp.high); } else { int64_t v = a->value->value(); - if (v) { + if (v != 1) { if (isInt32(v)) { if (size == 8) rex(c); if (isInt8(v)) { @@ -1582,48 +1589,22 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, doShift(c, unsignedShiftRightRR, 0xe8, size, a, b); } -void -multiwordCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah, - Assembler::Operand* bl, Assembler::Operand* bh, - BinaryOperationType op) -{ - op(c, BytesPerWord, ah, bh); - - // 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 - - unsigned comparisonOffset = c->code.length(); - c->code.append4(0); - - op(c, BytesPerWord, al, bl); - - int32_t comparisonSize = c->code.length() - comparisonOffset - 4; - c->code.set(comparisonOffset, &comparisonSize, 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); @@ -1635,65 +1616,45 @@ 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); } } void -compareCM(Context* c, unsigned size, Assembler::Constant* a, +compareCM(Context* c, unsigned size UNUSED, 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); } } @@ -1701,77 +1662,192 @@ 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); + 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); +} - int64_t v = b->value->value(); +void +longCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah, + Assembler::Operand* bl, Assembler::Operand* bh, + BinaryOperationType compare, BinaryOperationType move) +{ + ResolvedPromise negativePromise(-1); + Assembler::Constant negative(&negativePromise); - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant bl(&low); + ResolvedPromise zeroPromise(0); + Assembler::Constant zero(&zeroPromise); - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant bh(&high); + ResolvedPromise positivePromise(1); + Assembler::Constant positive(&positivePromise); - multiwordCompare(c, a, &ah, &bl, &bh, CAST2(compareRC)); + if (BytesPerWord == 8) { + compare(c, 8, al, bl); + + 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); + + move(c, 4, &zero, bl); + + 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); + + move(c, 4, &negative, bl); + + 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); + + move(c, 4, &positive, bl); + + 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 { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, b, &tmp); - compareRR(c, size, a, &tmp); - c->client->releaseTemporary(tmp.low); + compare(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); + + compare(c, 4, al, bl); + + 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); + + move(c, 4, &zero, bl); + + 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); + + move(c, 4, &negative, bl); + + 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); + + move(c, 4, &positive, bl); + + 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 +longCompareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, size == 8); + + int64_t v = a->value->value(); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + Assembler::Register bh(b->high); + + longCompare(c, &al, &ah, b, &bh, CAST2(compareCR), CAST2(moveCR)); +} + +void +longCompareRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, size == 8); + + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); + + longCompare(c, a, &ah, b, &bh, CAST2(compareRR), CAST2(moveCR)); +} + void populateTables() { @@ -1826,6 +1902,7 @@ populateTables() BinaryOperations[INDEX2(Move, Address, Memory)] = CAST2(moveAM); BinaryOperations[INDEX2(Move, Memory, Memory)] = CAST2(moveMM); + BinaryOperations[INDEX2(Move4To8, Constant, Register)] = CAST2(move4To8CR); BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); @@ -1874,6 +1951,11 @@ populateTables() BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); + BinaryOperations[INDEX2(LongCompare, Constant, Register)] + = CAST2(longCompareCR); + BinaryOperations[INDEX2(LongCompare, Register, Register)] + = CAST2(longCompareRR); + BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC); BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR); diff --git a/test/Misc.java b/test/Misc.java index 483ba73820..28c8e6c16c 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -95,6 +95,22 @@ public class Misc { } public static void main(String[] args) { + { long foo = 25214903884L; + int radix = 10; + expect(foo > 0); + foo /= radix; + expect(foo > 0); + } + + expect(String.valueOf(25214903884l).equals("25214903884")); + + { boolean p = true; + int[] array = new int[] { 1, 2 }; + expect(array[0] == array[p ? 0 : 1]); + p = false; + expect(array[1] == array[p ? 0 : 1]); + } + expect(roundUp(156, 2) == 156); { Foo foo = new Foo(); @@ -185,6 +201,39 @@ public class Misc { expect(~a == ~5L); } + { long a = -25214903884L; + long b = 2; + expect(a >> b == -25214903884L >> 2); + expect(a >>> b == -25214903884L >>> 2); + expect(a << b == -25214903884L << 2); + expect(a + b == -25214903884L + 2L); + expect(a - b == -25214903884L - 2L); + expect(a * b == -25214903884L * 2L); + expect(a / b == -25214903884L / 2L); + expect(a % b == -25214903884L % 2L); + expect((a & b) == (-25214903884L & 2L)); + expect((a | b) == (-25214903884L | 2L)); + expect((a ^ b) == (-25214903884L ^ 2L)); + expect(-a == 25214903884L); + expect(~a == ~-25214903884L); + + a = 25214903884L; + b = 2; + expect(a >> b == 25214903884L >> 2); + expect(a >>> b == 25214903884L >>> 2); + expect(a << b == 25214903884L << 2); + expect(a + b == 25214903884L + 2L); + expect(a - b == 25214903884L - 2L); + expect(a * b == 25214903884L * 2L); + expect(a / b == 25214903884L / 2L); + expect(a % b == 25214903884L % 2L); + expect((a & b) == (25214903884L & 2L)); + expect((a | b) == (25214903884L | 2L)); + expect((a ^ b) == (25214903884L ^ 2L)); + expect(-a == -25214903884L); + expect(~a == ~25214903884L); + } + byte2 = 0; expect(byte2 == 0);