32-bit JIT bugfixes; still broken

This commit is contained in:
Joel Dice 2007-12-19 18:42:12 -07:00
parent fc6beb852b
commit be42c325d8
4 changed files with 178 additions and 59 deletions

View File

@ -28,7 +28,7 @@ src = src
classpath = classpath
test = test
input = $(test-build)/Enums.class
input = $(test-build)/Exceptions.class
build-cxx = g++
build-cc = gcc

View File

@ -19,7 +19,7 @@ vmInvoke:
// %r8 : returnType
mov %rdi,%rbx
// copy memory arguments into place
pushq %rcx
movq $0,%r9
@ -37,7 +37,11 @@ test:
call *%rsi
// pop arguments
addq -16(%rbp),%rsp
mov -16(%rbp),%rcx
sal $3,%rcx
addq %rcx,%rsp
// pop argument stack size
addq $8,%rsp
popq %rbx
@ -77,7 +81,7 @@ vmInvoke:
jmp test
loop:
push (%rdx,%rcx,4)
push (%edx,%ecx,4)
inc %ecx
test:
@ -88,7 +92,9 @@ test:
call *12(%ebp)
// pop arguments
addl 20(%ebp),%esp
mov 20(%ebp),%ecx
sal $2,%ecx
addl %ecx,%esp
// handle return value based on expected type
movl 24(%ebp),%ecx
@ -118,8 +124,8 @@ exit:
vmJump:
movl 4(%esp),%eax
movl 8(%esp),%ebp
movl 12(%esp),%esp
movl 16(%esp),%ebx
movl 12(%esp),%esp
jmp *%eax
#else

View File

@ -18,7 +18,7 @@ vmJump(void* address, void* base, void* stack, void* thread);
namespace {
const bool Verbose = false;
const bool Verbose = true;
const bool DebugTraces = false;
class MyThread: public Thread {
@ -660,7 +660,7 @@ class Frame {
}
Operand* popLong() {
Operand* tmp = c->temporary();
Operand* tmp = c->select8(c->temporary());
popLong(tmp);
return tmp;
}
@ -3000,10 +3000,10 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
if (false and
strcmp(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
"java/lang/reflect/Method") == 0 and
"java/lang/Throwable") == 0 and
strcmp(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, method), 0)),
"invoke") == 0)
"init") == 0)
{
asm("int3");
}

View File

@ -305,7 +305,8 @@ RegisterOperand*
register_(Context* c, RegisterReference*, SelectionType = DefaultSelection);
RegisterOperand*
register_(Context* c, Register, SelectionType = DefaultSelection);
register_(Context* c, Register, Register = NoRegister,
SelectionType = DefaultSelection);
MemoryOperand*
memory(Context* c, MyOperand* base, int displacement,
@ -410,14 +411,15 @@ release(Context* c, Register v)
class RegisterReference {
public:
RegisterReference(Register v = NoRegister): value_(v), high_(NoRegister) { }
RegisterReference(Register value = NoRegister, Register high = NoRegister):
value_(value), high_(high), acquireHigh(false)
{ }
void acquireValue(Context* c) {
void acquire(Context* c) {
value_ = ::acquire(c);
}
void acquireHigh(Context* c) {
high_ = ::acquire(c);
if (acquireHigh) {
high_ = ::acquire(c);
}
}
void release(Context* c) {
@ -441,6 +443,7 @@ class RegisterReference {
Register value_;
Register high_;
bool acquireHigh;
};
class RegisterOperand: public MyOperand {
@ -469,10 +472,8 @@ class RegisterOperand: public MyOperand {
if (selection == this->selection) {
return this;
} else {
if (selection == S8Selection and BytesPerWord == 4
and reference->high_ == NoRegister)
{
reference->acquireHigh(c);
if (selection == S8Selection and BytesPerWord == 4) {
reference->acquireHigh = true;
}
return register_(c, reference, selection);
}
@ -656,10 +657,10 @@ register_(Context* c, RegisterReference* r, SelectionType selection)
}
RegisterOperand*
register_(Context* c, Register v, SelectionType selection)
register_(Context* c, Register v, Register h, SelectionType selection)
{
RegisterReference* r = new (c->zone.allocate(sizeof(RegisterReference)))
RegisterReference(v);
RegisterReference(v, h);
return register_(c, r, selection);
}
@ -677,6 +678,16 @@ temporary(Context* c)
return register_(c, acquire(c));
}
RegisterOperand*
temporary(Context* c, SelectionType selection)
{
if (BytesPerWord == 4 and selection == S8Selection) {
return register_(c, acquire(c), acquire(c), selection);
} else {
return register_(c, acquire(c), NoRegister, selection);
}
}
RegisterOperand*
temporary(Context* c, Register v)
{
@ -765,7 +776,7 @@ class AcquireEvent: public Event {
{ }
virtual void run(Context* c) {
operand->reference->acquireValue(c);
operand->reference->acquire(c);
}
RegisterOperand* operand;
@ -1064,7 +1075,9 @@ encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex)
void
RegisterOperand::apply(Context* c, Operation operation)
{
assert(c, selection == DefaultSelection);
assert(c, operation == push
or operation == pop
or selection == DefaultSelection);
switch (operation) {
case call:
@ -1078,11 +1091,43 @@ RegisterOperand::apply(Context* c, Operation operation)
break;
case pop:
c->code.append(0x58 | value(c));
if (selection == DefaultSelection) {
c->code.append(0x58 | value(c));
} else {
switch (selection) {
case S8Selection:
assert(c, selection == S8Selection);
register_(c, high(c))->apply(c, pop);
register_(c, value(c))->apply(c, pop);
break;
default: abort(c);
}
}
break;
case push:
c->code.append(0x50 | value(c));
if (selection == DefaultSelection) {
c->code.append(0x50 | value(c));
} else {
switch (selection) {
case S8Selection:
assert(c, selection == S8Selection);
register_(c, value(c))->apply(c, push);
register_(c, high(c))->apply(c, push);
break;
default: abort(c);
}
}
break;
case neg:
rex(c);
c->code.append(0xf7);
c->code.append(0xd8 | value(c));
break;
default: abort(c);
@ -1093,9 +1138,6 @@ void
RegisterOperand::accept(Context* c, Operation operation,
RegisterOperand* operand)
{
assert(c, selection == DefaultSelection);
assert(c, operation == mov or operand->selection == DefaultSelection);
switch (operation) {
case add:
rex(c);
@ -1104,9 +1146,25 @@ RegisterOperand::accept(Context* c, Operation operation,
break;
case cmp:
rex(c);
c->code.append(0x39);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
if (selection == DefaultSelection) {
rex(c);
c->code.append(0x39);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
} else {
assert(c, selection == S8Selection);
register_(c, high(c))->accept
(c, mov, register_(c, operand->high(c)));
// 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);
register_(c, value(c))->accept
(c, mov, register_(c, operand->value(c)));
}
break;
case mov:
@ -1119,24 +1177,36 @@ RegisterOperand::accept(Context* c, Operation operation,
switch (operand->selection) {
case S1Selection:
c->code.append(0xbe);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break;
case S2Selection:
c->code.append(0xbf);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break;
case Z2Selection:
c->code.append(0xb7);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break;
case S4Selection:
c->code.append(0x89);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break;
case S8Selection:
assert(c, selection == S8Selection);
register_(c, value(c))->accept
(c, mov, register_(c, operand->value(c)));
register_(c, high(c))->accept
(c, mov, register_(c, operand->high(c)));
break;
default: abort(c);
}
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
}
}
break;
@ -1272,7 +1342,7 @@ void
RegisterOperand::accept(Context* c, Operation operation,
MemoryOperand* operand)
{
assert(c, selection == DefaultSelection);
assert(c, operation == mov or selection == DefaultSelection);
assert(c, operation == mov or operand->selection == DefaultSelection);
switch (operation) {
@ -1540,8 +1610,6 @@ MemoryOperand::asRegister(Context* c)
void
MemoryOperand::apply(Context* c, Operation operation)
{
assert(c, operation == push or selection == DefaultSelection);
switch (operation) {
case call:
encode(c, 0xff, 2, this, false);
@ -1552,7 +1620,36 @@ MemoryOperand::apply(Context* c, Operation operation)
break;
case neg:
encode(c, 0xf7, 2, this, true);
if (selection == DefaultSelection) {
encode(c, 0xf7, 2, this, true);
} else {
assert(c, selection == S8Selection);
RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx);
MemoryOperand* low = memory(c, base, displacement, index, scale);
MemoryOperand* high = memory
(c, base, displacement + BytesPerWord, index, scale);
ax->accept(c, mov, low);
dx->accept(c, mov, high);
ax->apply(c, neg);
// adc 0,%rdx
c->code.append(0x83);
c->code.append(0xd0 | rdx);
c->code.append(0);
dx->apply(c, neg);
low->accept(c, mov, ax);
high->accept(c, mov, dx);
ax->release(c);
dx->release(c);
}
break;
case pop:
@ -1563,7 +1660,8 @@ MemoryOperand::apply(Context* c, Operation operation)
if (selection == DefaultSelection) {
encode(c, 0xff, 6, this, false);
} else {
RegisterOperand* tmp = temporary(c);
RegisterOperand* tmp = temporary
(c, selection == S8Selection ? S8Selection : DefaultSelection);
tmp->accept(c, mov, this);
tmp->apply(c, operation);
tmp->release(c);
@ -1578,9 +1676,6 @@ void
MemoryOperand::accept(Context* c, Operation operation,
RegisterOperand* operand)
{
assert(c, operation == mov or selection == DefaultSelection);
assert(c, operand->selection == DefaultSelection);
switch (operation) {
case and_: {
encode(c, 0x21, operand->value(c), this, true);
@ -1591,20 +1686,24 @@ MemoryOperand::accept(Context* c, Operation operation,
} break;
case div: {
RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx);
ax->accept(c, mov, this);
if (selection == DefaultSelection) {
RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx);
ax->accept(c, mov, this);
rex(c);
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | operand->value(c));
rex(c);
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | operand->value(c));
accept(c, mov, ax);
accept(c, mov, ax);
ax->release(c);
dx->release(c);
ax->release(c);
dx->release(c);
} else {
abort(c);
}
} break;
case mov: {
@ -1629,19 +1728,33 @@ MemoryOperand::accept(Context* c, Operation operation,
encode(c, 0x89, operand->value(c), this, false);
break;
case S8Selection:
assert(c, operand->selection == S8Selection);
memory(c, base, displacement, index, scale)->accept
(c, mov, register_(c, operand->value(c)));
memory(c, base, displacement + BytesPerWord, index, scale)->accept
(c, mov, register_(c, operand->high(c)));
break;
default: abort(c);
}
}
} break;
case mul: {
RegisterOperand* tmp = temporary(c);
if (selection == DefaultSelection) {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, this);
tmp->accept(c, mul, operand);
accept(c, mov, tmp);
tmp->accept(c, mov, this);
tmp->accept(c, mul, operand);
accept(c, mov, tmp);
tmp->release(c);
tmp->release(c);
} else {
abort(c);
}
} break;
case or_: {