bugfixes, mainly concerning 32-bit machines

This commit is contained in:
Joel Dice 2008-04-28 16:08:31 -06:00
parent 90ae9a70ee
commit 8738bddcb9
4 changed files with 348 additions and 120 deletions

View File

@ -134,7 +134,7 @@ class Assembler {
public:
virtual ~Client() { }
virtual int acquireTemporary(int r = NoRegister) = 0;
virtual int acquireTemporary() = 0;
virtual void releaseTemporary(int r) = 0;
virtual void save(int r) = 0;
@ -156,11 +156,8 @@ class Assembler {
virtual unsigned argumentRegisterCount() = 0;
virtual int argumentRegister(unsigned index) = 0;
virtual void getTargets(UnaryOperation op, unsigned size,
Register* a) = 0;
virtual void getTargets(BinaryOperation op, unsigned size,
Register* a, Register* b) = 0;
Register* a, Register* b, bool* syncStack) = 0;
virtual void apply(Operation op) = 0;

View File

@ -3875,11 +3875,11 @@ finish(MyThread* t, Context* context)
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"java/nio/ByteBuffer") == 0 and
"java/lang/Class") == 0 and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)),
"checkPut") == 0)
"replace") == 0)
{
asm("int3");
}

View File

@ -1195,13 +1195,15 @@ class MoveEvent: public Event {
nextRead(c, src);
if (dst->reads) {
addSite(c, stack, size, dst, target);
}
if (cost) {
apply(c, type, size, src->source, target);
}
if (dst->reads) {
addSite(c, stack, size, dst, target);
} else {
if (dst->reads == 0) {
removeSite(c, dst, target);
}
}
@ -1263,22 +1265,20 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second)
class CombineEvent: public Event {
public:
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result):
Value* second, Value* result, Assembler::Register* r1,
Assembler::Register* r2):
Event(c), type(type), size(size), first(first), second(second),
result(result)
{
Assembler::Register r1(NoRegister);
Assembler::Register r2(NoRegister);
c->assembler->getTargets(type, size, &r1, &r2);
addRead(c, first, size,
r1.low == NoRegister ?
r1->low == NoRegister ?
constantOrRegisterSite(c) :
static_cast<Site*>(registerSite(c, r1.low, r1.high)));
static_cast<Site*>(registerSite(c, r1->low, r1->high)));
addRead(c, second, size,
r2.low == NoRegister ?
r2->low == NoRegister ?
valueSite(c, result) :
static_cast<Site*>(registerSite(c, r2.low, r2.high)));
static_cast<Site*>(registerSite(c, r2->low, r2->high)));
}
virtual void compile(Context* c) {
@ -1304,16 +1304,28 @@ class CombineEvent: public Event {
Value* result;
};
void
appendStackSync(Context* c);
void
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result)
{
Assembler::Register r1(NoRegister);
Assembler::Register r2(NoRegister);
bool syncStack;
c->assembler->getTargets(type, size, &r1, &r2, &syncStack);
if (syncStack) {
appendStackSync(c);
}
if (DebugAppend) {
fprintf(stderr, "appendCombine\n");
}
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, first, second, result);
CombineEvent(c, type, size, first, second, result, &r1, &r2);
}
class TranslateEvent: public Event {
@ -1949,14 +1961,8 @@ class Client: public Assembler::Client {
public:
Client(Context* c): c(c) { }
virtual int acquireTemporary(int r) {
if (r == NoRegister) {
r = freeRegisterExcept(c, NoRegister, false);
} else {
expect(c, (c->registers[r].refCount == 0
and c->registers[r].value == 0)
or c->registers[r].pushed);
}
virtual int acquireTemporary() {
int r = freeRegisterExcept(c, NoRegister, false);
increment(c, r);
return r;
}

View File

@ -95,6 +95,13 @@ expect(Context* c, bool v)
expect(c->s, v);
}
ResolvedPromise*
resolved(Context* c, int64_t value)
{
return new (c->zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value);
}
class CodePromise: public Promise {
public:
CodePromise(Context* c, unsigned offset): c(c), offset(offset) { }
@ -434,12 +441,12 @@ pushC(Context* c, unsigned size, Assembler::Constant* a)
int64_t v = a->value->value();
if (BytesPerWord == 4 and size == 8) {
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
pushC(c, 4, &ah);
pushC(c, 4, &al);
} else {
@ -536,13 +543,65 @@ popM(Context* c, unsigned size, Assembler::Memory* a)
}
void
negateR(Context* c, unsigned size UNUSED, Assembler::Register* a)
addCarryCR(Context* c, unsigned size, Assembler::Constant* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
assert(c, BytesPerWord == 8 or size == 4);
int64_t v = a->value->value();
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xd0 | b->low);
c->code.append(v);
} else {
abort(c);
}
}
rex(c);
c->code.append(0xf7);
c->code.append(0xd8 | a->low);
void
moveRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b);
void
negateR(Context* c, unsigned size, Assembler::Register* a)
{
if (BytesPerWord == 4 and size == 8) {
Assembler::Register ax(rax);
Assembler::Register dx(rdx);
Assembler::Register ah(a->high);
ResolvedPromise zeroPromise(0);
Assembler::Constant zero(&zeroPromise);
if (a->low != rax) {
c->client->save(rax);
moveRR(c, BytesPerWord, a, &ax);
}
if (a->high != rdx) {
c->client->save(rdx);
moveRR(c, BytesPerWord, &ah, &dx);
}
negateR(c, 4, &ax);
addCarryCR(c, 4, &zero, &dx);
negateR(c, 4, &dx);
if (a->high != rdx) {
moveRR(c, BytesPerWord, &dx, a);
c->client->restore(rdx);
}
if (a->low != rax) {
moveRR(c, BytesPerWord, &ax, a);
c->client->restore(rax);
}
} else {
rex(c);
c->code.append(0xf7);
c->code.append(0xd8 | a->low);
}
}
@ -559,18 +618,31 @@ leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
}
void
moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
moveCR(Context* c, unsigned size, Assembler::Constant* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
if (BytesPerWord == 4 and size == 8) {
int64_t v = a->value->value();
rex(c, 0x48, b->low);
c->code.append(0xb8 | b->low);
if (a->value->resolved()) {
c->code.appendAddress(a->value->value());
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Register bh(b->high);
moveCR(c, 4, &al, b);
moveCR(c, 4, &ah, &bh);
} else {
appendImmediateTask(c, a->value, c->code.length());
c->code.appendAddress(static_cast<uintptr_t>(0));
rex(c, 0x48, b->low);
c->code.append(0xb8 | b->low);
if (a->value->resolved()) {
c->code.appendAddress(a->value->value());
} else {
appendImmediateTask(c, a->value, c->code.length());
c->code.appendAddress(static_cast<uintptr_t>(0));
}
}
}
@ -629,10 +701,25 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
} else {
switch (size) {
case 1:
rex(c);
c->code.append(0x0f);
c->code.append(0xbe);
c->code.append(0xc0 | (b->low << 3) | a->low);
if (BytesPerWord == 4 and a->low > rbx) {
if (b->low > rbx) {
c->client->save(rax);
Assembler::Register ax(rax);
moveRR(c, BytesPerWord, a, &ax);
moveRR(c, 1, &ax, b);
c->client->restore(rax);
} else {
moveRR(c, BytesPerWord, a, b);
moveRR(c, 1, b, b);
}
} else {
rex(c);
c->code.append(0x0f);
c->code.append(0xbe);
c->code.append(0xc0 | (b->low << 3) | a->low);
}
break;
case 2:
@ -674,10 +761,13 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
}
} else {
if (a->low > rbx) {
Assembler::Register ax(c->client->acquireTemporary(rax));
c->client->save(rax);
Assembler::Register ax(rax);
moveRR(c, BytesPerWord, a, &ax);
moveRM(c, 1, &ax, b);
c->client->releaseTemporary(ax.low);
c->client->restore(rax);
} else {
encode(c, 0x88, a->low, b, false);
}
@ -709,15 +799,32 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a,
if (a->low == rax and b->low == rax and b->high == rdx) {
c->code.append(0x99); // cdq
} else {
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
Assembler::Register axdx(rax, rdx);
Assembler::Register dx(rdx);
Assembler::Register bh(b->high);
bool saveAX = a->low != rax and b->low != rax and b->high != rax;
bool saveDX = b->low != rdx and b->high != rdx;
if (saveDX) c->client->save(rdx);
if (saveAX) c->client->save(rax);
if (a->low != rax) {
moveRR(c, 4, a, &axdx);
}
moveRR(c, 4, a, &axdx);
move4To8RR(c, 0, &axdx, &axdx);
moveRR(c, 8, &axdx, b);
c->client->releaseTemporary(axdx.low);
c->client->releaseTemporary(axdx.high);
if (b->low != rax) {
moveRR(c, 4, &axdx, b);
}
if (b->high != rdx) {
moveRR(c, 4, &dx, &bh);
}
if (saveAX) c->client->restore(rax);
if (saveDX) c->client->restore(rdx);
}
}
}
@ -803,15 +910,29 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
if (BytesPerWord == 8) {
encode(c, 0x63, b->low, a, true);
} else {
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
Assembler::Register axdx(rax, rdx);
Assembler::Register dx(rdx);
Assembler::Register bh(b->high);
bool saveAX = b->low != rax and b->high != rax;
bool saveDX = b->low != rdx and b->high != rdx;
if (saveDX) c->client->save(rdx);
if (saveAX) c->client->save(rax);
moveMR(c, 4, a, &axdx);
move4To8RR(c, 0, &axdx, &axdx);
moveRR(c, 8, &axdx, b);
c->client->releaseTemporary(axdx.low);
c->client->releaseTemporary(axdx.high);
if (b->low != rax) {
moveRR(c, 4, &axdx, b);
}
if (b->high != rdx) {
moveRR(c, 4, &dx, &bh);
}
if (saveAX) c->client->restore(rax);
if (saveDX) c->client->restore(rdx);
}
}
@ -867,25 +988,52 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
}
}
void
subtractBorrowCR(Context* c, unsigned size, Assembler::Constant* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4);
int64_t v = a->value->value();
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xd8 | b->low);
c->code.append(v);
} else {
abort(c);
}
}
void
subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
int64_t v = a->value->value();
if (v) {
rex(c);
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xe8 | b->low);
c->code.append(v);
} else if (isInt32(v)) {
c->code.append(0x81);
c->code.append(0xe8 | b->low);
c->code.append4(v);
if (BytesPerWord == 4 and size == 8) {
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Register bh(b->high);
subtractCR(c, 4, &al, b);
subtractBorrowCR(c, 4, &ah, &bh);
} else {
abort(c);
rex(c);
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xe8 | b->low);
c->code.append(v);
} else if (isInt32(v)) {
c->code.append(0x81);
c->code.append(0xe8 | b->low);
c->code.append4(v);
} else {
abort(c);
}
}
}
}
@ -902,14 +1050,31 @@ subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
}
void
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
addCarryRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4);
rex(c);
c->code.append(0x11);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
void
addRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
if (BytesPerWord == 4 and size == 8) {
Assembler::Register ah(a->high);
Assembler::Register bh(b->high);
rex(c);
c->code.append(0x01);
c->code.append(0xc0 | (a->low << 3) | b->low);
addRR(c, 4, a, b);
addCarryRR(c, 4, &ah, &bh);
} else {
rex(c);
c->code.append(0x01);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
}
void
@ -966,16 +1131,21 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
abort(c); // todo: sync stack first
Assembler::Register axdx(rax, rdx);
Assembler::Register dx(rdx);
Assembler::Register bh(b->high);
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
bool saveAX = b->low != rax and b->high != rax;
bool saveDX = b->low != rdx and b->high != rdx;
if (saveDX) c->client->save(rdx);
if (saveAX) c->client->save(rax);
pushR(c, size, a);
pushR(c, size, b);
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(divideLong));
Assembler::Constant address(&addressPromise);
Assembler::Constant address
(resolved(c, reinterpret_cast<intptr_t>(divideLong)));
callC(c, BytesPerWord, &address);
ResolvedPromise offsetPromise(16);
@ -983,24 +1153,29 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register stack(rsp);
addCR(c, BytesPerWord, &offset, &stack);
moveRR(c, size, &axdx, b);
if (b->low != rax) {
moveRR(c, 4, &axdx, b);
}
c->client->releaseTemporary(axdx.low);
c->client->releaseTemporary(axdx.high);
if (b->high != rdx) {
moveRR(c, 4, &dx, &bh);
}
if (saveAX) c->client->restore(rax);
if (saveDX) c->client->restore(rdx);
} else {
Assembler::Register ax(rax);
Assembler::Register divisor(a->low);
if (a->low == rdx) {
divisor.low = c->client->acquireTemporary();
moveRR(c, BytesPerWord, a, &divisor);
moveRR(c, BytesPerWord, a, &divisor);
} else if (b->low != rdx) {
c->client->save(rdx);
}
if (b->low != rax) {
c->client->save(rax);
c->client->acquireTemporary(rax);
moveRR(c, BytesPerWord, b, &ax);
}
@ -1012,7 +1187,6 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
if (b->low != rax) {
moveRR(c, BytesPerWord, &ax, b);
c->client->releaseTemporary(rax);
c->client->restore(rax);
}
@ -1042,16 +1216,21 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
abort(c); // todo: sync stack first
Assembler::Register axdx(rax, rdx);
Assembler::Register dx(rdx);
Assembler::Register bh(b->high);
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
bool saveAX = b->low != rax and b->high != rax;
bool saveDX = b->low != rdx and b->high != rdx;
if (saveDX) c->client->save(rdx);
if (saveAX) c->client->save(rax);
pushR(c, size, a);
pushR(c, size, b);
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(moduloLong));
Assembler::Constant address(&addressPromise);
Assembler::Constant address
(resolved(c, reinterpret_cast<intptr_t>(moduloLong)));
callC(c, BytesPerWord, &address);
ResolvedPromise offsetPromise(16);
@ -1059,10 +1238,16 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register stack(rsp);
addCR(c, BytesPerWord, &offset, &stack);
moveRR(c, size, &axdx, b);
if (b->low != rax) {
moveRR(c, 4, &axdx, b);
}
c->client->releaseTemporary(axdx.low);
c->client->releaseTemporary(axdx.high);
if (b->high != rdx) {
moveRR(c, 4, &dx, &bh);
}
if (saveAX) c->client->restore(rax);
if (saveDX) c->client->restore(rdx);
} else {
Assembler::Register ax(rax);
Assembler::Register dx(rdx);
@ -1077,7 +1262,6 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
if (b->low != rax) {
c->client->save(rax);
c->client->acquireTemporary(rax);
moveRR(c, BytesPerWord, b, &ax);
}
@ -1089,7 +1273,9 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
if (b->low != rdx) {
moveRR(c, BytesPerWord, &dx, b);
c->client->releaseTemporary(rax);
}
if (b->low != rax) {
c->client->restore(rax);
}
@ -1215,10 +1401,25 @@ shift(Context* c, int type, Assembler::Register* a, Assembler::Register* b) {
c->code.append(0xd3);
c->code.append(type | b->low);
} else {
Assembler::Register cx(c->client->acquireTemporary(rcx));
Assembler::Register target(b->low);
if (b->low == rcx) {
target.low = c->client->acquireTemporary();
moveRR(c, BytesPerWord, b, &target);
} else {
c->client->save(rcx);
}
Assembler::Register cx(rcx);
moveRR(c, BytesPerWord, a, &cx);
shift(c, type, &cx, b);
c->client->releaseTemporary(cx.low);
if (b->low == rcx) {
moveRR(c, BytesPerWord, &target, b);
c->client->releaseTemporary(target.low);
} else {
c->client->restore(rcx);
}
}
}
@ -1346,19 +1547,39 @@ compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
}
void
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
compareCM(Context* c, unsigned size, Assembler::Constant* a,
Assembler::Memory* b)
{
assert(c, BytesPerWord == 8 or size == 4);
int64_t v = a->value->value();
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
if (BytesPerWord == 4 and size == 8) {
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
if (isInt8(a->value->value())) {
c->code.append(a->value->value());
} else if (isInt32(a->value->value())) {
c->code.append4(a->value->value());
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
compareCM(c, 4, &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
c->code.append4(2);
compareCM(c, 4, &al, b);
} else {
abort(c);
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);
}
}
}
@ -1557,22 +1778,26 @@ class MyAssembler: public Assembler {
}
}
virtual void getTargets(UnaryOperation /*op*/, unsigned /*size*/,
Register* r)
virtual void getTargets(BinaryOperation op, unsigned size,
Register* a, Register* b, bool* syncStack)
{
// todo
r->low = NoRegister;
r->high = NoRegister;
}
virtual void getTargets(BinaryOperation /*op*/, unsigned /*size*/,
Register* a, Register* b)
{
// todo
a->low = NoRegister;
a->high = NoRegister;
b->low = NoRegister;
b->high = NoRegister;
*syncStack = false;
switch (op) {
case Divide:
case Remainder:
if (BytesPerWord == 4 and size == 8) {
*syncStack = true;
}
break;
default:
break;
}
}
virtual void apply(Operation op) {