bugfixes and new instructions

This commit is contained in:
Joel Dice 2008-03-15 17:54:20 -06:00
parent 420a054fd8
commit 684b402e82
3 changed files with 256 additions and 108 deletions

View File

@ -2589,7 +2589,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
Compiler::Operand* result = c->call Compiler::Operand* result = c->call
(c->memory (c->memory
(c->and_ (c->and_
(4, c->constant(PointerMask), c->memory (BytesPerWord, c->constant(PointerMask), c->memory
(instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1), (instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1),
0, 0,
0, 0,

View File

@ -26,6 +26,8 @@ class Event;
class PushEvent; class PushEvent;
class Stack; class Stack;
void NO_RETURN abort(Context* c);
class Value { class Value {
public: public:
virtual ~Value() { } virtual ~Value() { }
@ -38,26 +40,25 @@ class Value {
virtual void acquire(Context*, Stack*, MyOperand*) { } virtual void acquire(Context*, Stack*, MyOperand*) { }
virtual void release(Context*, MyOperand*) { } virtual void release(Context*, MyOperand*) { }
virtual RegisterValue* toRegister(Context*) = 0; virtual int registerValue(Context* c) { abort(c); }
virtual int64_t constantValue(Context* c) { abort(c); }
virtual void asAssemblerOperand(Context*, virtual void asAssemblerOperand(Context*,
OperandType* type, OperandType* type,
Assembler::Operand** operand) = 0; Assembler::Operand** operand) = 0;
virtual int64_t constantValue(Context*) = 0;
}; };
class MyOperand: public Compiler::Operand { class MyOperand: public Compiler::Operand {
public: public:
MyOperand(Value* value): MyOperand(Value* value):
event(0), value(value), target(0), push(0), pushedValue(0) event(0), value(value), target(0), push(0), pushed(false)
{ } { }
Event* event; Event* event;
Value* value; Value* value;
Value* target; Value* target;
PushEvent* push; PushEvent* push;
StackValue* pushedValue; bool pushed;
}; };
class Stack { class Stack {
@ -283,8 +284,6 @@ class ConstantValue: public Value {
virtual OperandType type(Context*) { return Constant; } virtual OperandType type(Context*) { return Constant; }
virtual RegisterValue* toRegister(Context* c);
virtual void asAssemblerOperand(Context*, virtual void asAssemblerOperand(Context*,
OperandType* type, OperandType* type,
Assembler::Operand** operand) Assembler::Operand** operand)
@ -325,8 +324,6 @@ class AddressValue: public Value {
virtual OperandType type(Context*) { return Address; } virtual OperandType type(Context*) { return Address; }
virtual RegisterValue* toRegister(Context* c);
virtual void asAssemblerOperand(Context*, virtual void asAssemblerOperand(Context*,
OperandType* type, OperandType* type,
Assembler::Operand** operand) Assembler::Operand** operand)
@ -335,10 +332,6 @@ class AddressValue: public Value {
*operand = &address; *operand = &address;
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Assembler::Address address; Assembler::Address address;
}; };
@ -389,8 +382,8 @@ class RegisterValue: public Value {
} }
} }
virtual RegisterValue* toRegister(Context*) { virtual int registerValue(Context*) {
return this; return register_.low;
} }
virtual void asAssemblerOperand(Context*, virtual void asAssemblerOperand(Context*,
@ -401,10 +394,6 @@ class RegisterValue: public Value {
*operand = &register_; *operand = &register_;
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Assembler::Register register_; Assembler::Register register_;
}; };
@ -433,12 +422,6 @@ class MemoryValue: public Value {
and static_cast<MemoryValue*>(o)->value.scale == value.scale); and static_cast<MemoryValue*>(o)->value.scale == value.scale);
} }
virtual RegisterValue* toRegister(Context* c) {
RegisterValue* v = freeRegister(c, BytesPerWord, false);
apply(c, Move, BytesPerWord, this, v);
return v;
}
virtual int base(Context*) { virtual int base(Context*) {
return value.base; return value.base;
} }
@ -457,27 +440,9 @@ class MemoryValue: public Value {
*operand = &value; *operand = &value;
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Assembler::Memory value; Assembler::Memory value;
}; };
MemoryValue*
memory(Context* c, int base, int offset, int index, unsigned scale,
TraceHandler* traceHandler)
{
return new (c->zone->allocate(sizeof(MemoryValue)))
MemoryValue(base, offset, index, scale, traceHandler);
}
int
toRegister(Context* c, MyOperand* a)
{
return a->value->toRegister(c)->register_.low;
}
class AbstractMemoryValue: public MemoryValue { class AbstractMemoryValue: public MemoryValue {
public: public:
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
@ -501,11 +466,11 @@ class AbstractMemoryValue: public MemoryValue {
} }
virtual int base(Context* c) { virtual int base(Context* c) {
return ::toRegister(c, base_); return base_->value->registerValue(c);
} }
virtual int index(Context* c) { virtual int index(Context* c) {
return index_ ? ::toRegister(c, index_) : NoRegister; return index_ ? index_->value->registerValue(c) : NoRegister;
} }
MyOperand* base_; MyOperand* base_;
@ -522,35 +487,32 @@ memory(Context* c, MyOperand* base, int offset, MyOperand* index,
class StackValue: public Value { class StackValue: public Value {
public: public:
StackValue(Stack* stack): stack(stack) { } StackValue(Context* c, Stack* stack):
stack(stack),
value
(c->assembler->base(),
- (c->stackOffset + stack->index + 1) * BytesPerWord,
NoRegister, 0, 0)
{ }
virtual OperandType type(Context* c) { abort(c); } virtual OperandType type(Context*) { return Memory; }
virtual RegisterValue* toRegister(Context* c) { virtual void asAssemblerOperand(Context*,
return MemoryValue OperandType* type,
(c->assembler->base(), (c->stackOffset + stack->index) * BytesPerWord, Assembler::Operand** operand)
NoRegister, 0, 0)
.toRegister(c);
}
virtual void asAssemblerOperand(Context* c,
OperandType*,
Assembler::Operand**)
{ {
abort(c); *type = Memory;
} *operand = &value;
virtual int64_t constantValue(Context* c) {
abort(c);
} }
Stack* stack; Stack* stack;
Assembler::Memory value;
}; };
StackValue* StackValue*
stackValue(Context* c, Stack* stack) stackValue(Context* c, Stack* stack)
{ {
return new (c->zone->allocate(sizeof(StackValue))) StackValue(stack); return new (c->zone->allocate(sizeof(StackValue))) StackValue(c, stack);
} }
class Event { class Event {
@ -691,8 +653,8 @@ class ReturnEvent: public Event {
if (not a->target->equals(c, a->value)) { if (not a->target->equals(c, a->value)) {
apply(c, Move, size, a->value, a->target); apply(c, Move, size, a->value, a->target);
a->value->release(c, a);
} }
a->value->release(c, a);
} }
Assembler::Register base(c->assembler->base()); Assembler::Register base(c->assembler->base());
@ -843,9 +805,19 @@ syncStack(Context* c, Stack* start, unsigned count)
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
Stack* s = segment[i]; Stack* s = segment[i];
apply(c, Push, s->size * BytesPerWord, s->operand->value); if (s->operand->value) {
s->operand->value->release(c, s->operand); apply(c, Push, s->size * BytesPerWord, s->operand->value);
s->operand->pushedValue = stackValue(c, s); s->operand->value->release(c, s->operand);
s->operand->pushed = true;
s->operand->value = stackValue(c, s);
} else {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
c->assembler->apply
(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
s->operand->pushed = true;
s->operand->value = stackValue(c, s);
}
} }
} }
@ -853,7 +825,7 @@ void
syncStack(Context* c, Stack* start) syncStack(Context* c, Stack* start)
{ {
unsigned count = 0; unsigned count = 0;
for (Stack* s = start; s and s->operand->pushedValue == 0; s = s->next) { for (Stack* s = start; s and (not s->operand->pushed); s = s->next) {
++ count; ++ count;
} }
@ -901,8 +873,8 @@ appendPush(Context* c)
class PopEvent: public Event { class PopEvent: public Event {
public: public:
PopEvent(Context* c): PopEvent(Context* c, unsigned count, bool ignore):
Event(c) Event(c), count(count), ignore(ignore)
{ } { }
virtual Value* target(Context* c, MyOperand*) { virtual Value* target(Context* c, MyOperand*) {
@ -916,30 +888,53 @@ class PopEvent: public Event {
virtual void compile(Context* c) { virtual void compile(Context* c) {
fprintf(stderr, "PopEvent.compile\n"); fprintf(stderr, "PopEvent.compile\n");
MyOperand* dst = stack->operand; Stack* s = stack;
if (dst->event and dst->pushedValue) { unsigned ignored = 0;
Value* target = 0; for (unsigned i = count; i;) {
MyOperand* dst = s->operand;
if (dst->pushed) {
if (dst->event and (not ignore)) {
assert(c, ignored == 0);
if (dst->event and dst->event->operandSize(c) == BytesPerWord) { Value* target = 0;
target = dst->event->target(c, dst);
} if (dst->event->operandSize(c) == BytesPerWord) {
if (target == 0) { target = dst->event->target(c, dst);
target = freeRegister(c, BytesPerWord * stack->size, false); }
if (target == 0) {
target = freeRegister(c, BytesPerWord * s->size, false);
}
apply(c, Pop, BytesPerWord * s->size, target);
target->acquire(c, 0, dst);
dst->value = target;
} else {
ignored += s->size;
}
} }
apply(c, Pop, BytesPerWord * stack->size, target); i -= s->size;
s = s->next;
}
target->acquire(c, 0, dst); if (ignored) {
Assembler::Register stack(c->assembler->stack());
dst->value = target; Assembler::Constant offset(resolved(c, ignored * BytesPerWord));
c->assembler->apply
(Add, BytesPerWord, Constant, &offset, Register, &stack);
} }
} }
unsigned count;
bool ignore;
}; };
void void
appendPop(Context* c) appendPop(Context* c, unsigned count, bool ignore)
{ {
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c); new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
} }
bool bool
@ -1221,7 +1216,7 @@ class CombineEvent: public Event {
if (br.low == NoRegister) { if (br.low == NoRegister) {
if (result->event) { if (result->event) {
Value* v = result->event->target(c, result); Value* v = result->event->target(c, result);
if (v->type(c) == Register) { if (v and v->type(c) == Register) {
return v; return v;
} else { } else {
return 0; return 0;
@ -1338,20 +1333,52 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
TranslateEvent(c, type, size, a, result); TranslateEvent(c, type, size, a, result);
} }
RegisterValue* class MemoryEvent: public Event {
ConstantValue::toRegister(Context* c) public:
{ MemoryEvent(Context* c, MyOperand* base, MyOperand* index,
RegisterValue* v = freeRegister(c, BytesPerWord, false); MyOperand* result):
apply(c, Move, BytesPerWord, this, v); Event(c), base(base), index(index), result(result)
return v; {
} setEvent(c, base, this);
if (index) setEvent(c, index, this);
}
RegisterValue* virtual unsigned operandSize(Context*) {
AddressValue::toRegister(Context* c) return BytesPerWord;
}
virtual Value* target(Context* c, MyOperand* v UNUSED) {
assert(c, v == base or v == index);
return 0;
}
virtual void compile(Context* c) {
fprintf(stderr, "MemoryEvent.compile\n");
if (base->value->type(c) != Register) {
base->target = freeRegister(c, BytesPerWord, true);
apply(c, Move, BytesPerWord, base->value, base->target);
base->value->release(c, base);
base->value = base->target;
}
if (index and index->value->type(c) != Register) {
index->target = freeRegister(c, BytesPerWord, true);
apply(c, Move, BytesPerWord, index->value, index->target);
index->value->release(c, index);
index->value = index->target;
}
}
MyOperand* base;
MyOperand* index;
MyOperand* result;
};
void
appendMemory(Context* c, MyOperand* a, MyOperand* b, MyOperand* result)
{ {
RegisterValue* v = freeRegister(c, BytesPerWord, false); new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, a, b, result);
apply(c, Move, BytesPerWord, this, v);
return v;
} }
void void
@ -1363,7 +1390,7 @@ preserve(Context* c, Stack* stack, int reg, MyOperand* a)
unsigned count = 0; unsigned count = 0;
Stack* start = 0; Stack* start = 0;
for (Stack* s = stack; s and s->operand->pushedValue == 0; s = s->next) { for (Stack* s = stack; s and (not s->operand->pushed); s = s->next) {
if (s->operand == b) { if (s->operand == b) {
start = s; start = s;
} }
@ -1429,7 +1456,7 @@ push(Context* c, unsigned size, MyOperand* o)
assert(c, ceiling(size, BytesPerWord)); assert(c, ceiling(size, BytesPerWord));
c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack);
appendPush(c); appendPush(c);
} }
@ -1439,7 +1466,7 @@ pop(Context* c, unsigned size UNUSED)
Stack* s = c->state->stack; Stack* s = c->state->stack;
assert(c, ceiling(size, BytesPerWord) == s->size); assert(c, ceiling(size, BytesPerWord) == s->size);
appendPop(c); appendPop(c, s->size, false);
c->state->stack = s->next; c->state->stack = s->next;
return s->operand; return s->operand;
@ -1499,11 +1526,11 @@ compile(Context* c)
i, count(e->stack)); i, count(e->stack));
e->compile(c); e->compile(c);
if (e == li->lastEvent) break;
for (CodePromise* p = e->promises; p; p = p->next) { for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->length(); p->offset = a->length();
} }
if (e == li->lastEvent) break;
} }
} }
} }
@ -1614,10 +1641,15 @@ class MyCompiler: public Compiler {
unsigned scale = 1, unsigned scale = 1,
TraceHandler* traceHandler = 0) TraceHandler* traceHandler = 0)
{ {
return operand MyOperand* result = operand
(&c, ::memory (&c, ::memory
(&c, static_cast<MyOperand*>(base), displacement, (&c, static_cast<MyOperand*>(base), displacement,
static_cast<MyOperand*>(index), scale, traceHandler)); static_cast<MyOperand*>(index), scale, traceHandler));
appendMemory(&c, static_cast<MyOperand*>(base),
static_cast<MyOperand*>(index), result);
return result;
} }
virtual Operand* stack() { virtual Operand* stack() {
@ -1652,6 +1684,8 @@ class MyCompiler: public Compiler {
} }
virtual void mark(Operand* label) { virtual void mark(Operand* label) {
markStack(&c);
static_cast<ConstantValue*>(static_cast<MyOperand*>(label)->value)->value static_cast<ConstantValue*>(static_cast<MyOperand*>(label)->value)->value
= machineIp(); = machineIp();
} }
@ -1665,11 +1699,18 @@ class MyCompiler: public Compiler {
} }
virtual void pushed(unsigned count) { virtual void pushed(unsigned count) {
for (unsigned i = 0; i < count; ++i) ::push(&c, BytesPerWord, operand(&c)); for (unsigned i = 0; i < count; ++i) {
MyOperand* a = operand(&c);
::push(&c, BytesPerWord, a);
a->value = stackValue(&c, c.state->stack);
a->pushed = true;
}
} }
virtual void popped(unsigned count) { virtual void popped(unsigned count) {
for (unsigned i = count; i > 0;) { appendPop(&c, count, true);
for (unsigned i = count; i;) {
Stack* s = c.state->stack; Stack* s = c.state->stack;
c.state->stack = s->next; c.state->stack = s->next;
i -= s->size; i -= s->size;

View File

@ -426,6 +426,20 @@ pushC(Context* c, unsigned size, Assembler::Constant* a)
} }
} }
void
moveAR(Context*, unsigned, Assembler::Address*, Assembler::Register* b);
void
pushA(Context* c, unsigned size, Assembler::Address* a)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
Assembler::Register tmp(c->client->acquireTemporary());
moveAR(c, size, a, &tmp);
pushR(c, size, &tmp);
c->client->releaseTemporary(tmp.low);
}
void void
pushR(Context* c, unsigned size, Assembler::Register* a) pushR(Context* c, unsigned size, Assembler::Register* a)
{ {
@ -533,8 +547,8 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b) Assembler::Register* b)
{ {
if (BytesPerWord == 4 and size == 8) { if (BytesPerWord == 4 and size == 8) {
Assembler::Register ah(a->low); Assembler::Register ah(a->high);
Assembler::Register bh(b->low); Assembler::Register bh(b->high);
moveRR(c, 4, a, b); moveRR(c, 4, a, b);
moveRR(c, 4, &ah, &bh); moveRR(c, 4, &ah, &bh);
@ -679,6 +693,35 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
encode(c, 0x63, b->low, a, true); encode(c, 0x63, b->low, a, true);
} }
void
moveZMR(Context* c, unsigned size, Assembler::Memory* a,
Assembler::Register* b)
{
switch (size) {
case 2:
encode2(c, 0x0fb7, b->low, a, true);
break;
default: abort(c); // todo
}
}
void
moveZRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
switch (size) {
case 2:
rex(c);
c->code.append(0x0f);
c->code.append(0xb7);
c->code.append(0xc0 | (a->low << 3) | b->low);
break;
default: abort(c); // todo
}
}
void void
addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Register* b) Assembler::Register* b)
@ -725,6 +768,17 @@ subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
} }
} }
void
subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
rex(c);
c->code.append(0x29);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
void void
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
Assembler::Register* b) Assembler::Register* b)
@ -807,6 +861,30 @@ compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
} }
} }
void
compareRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
Assembler::Register ah(a->high);
Assembler::Register bh(b->high);
compareRR(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);
compareRR(c, 4, a, b);
} else {
if (size == 8) rex(c);
c->code.append(0x39);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
}
void void
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Memory* b) Assembler::Memory* b)
@ -824,6 +902,27 @@ compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
} }
} }
void
compareRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
Assembler::Memory* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
encode(c, 0x39, a->low, b, true);
}
void
compareMM(Context* c, unsigned size UNUSED, Assembler::Memory* a,
Assembler::Memory* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
Assembler::Register tmp(c->client->acquireTemporary());
moveMR(c, size, a, &tmp);
compareRM(c, size, &tmp, b);
c->client->releaseTemporary(tmp.low);
}
void void
populateTables() populateTables()
{ {
@ -848,6 +947,7 @@ populateTables()
= CAST1(jumpIfLessOrEqualC); = CAST1(jumpIfLessOrEqualC);
UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC); UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC);
UnaryOperations[INDEX1(Push, Address)] = CAST1(pushA);
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
@ -868,6 +968,9 @@ populateTables()
BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR);
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
BinaryOperations[INDEX2(MoveZ, Memory, Register)] = CAST2(moveZMR);
BinaryOperations[INDEX2(MoveZ, Register, Register)] = CAST2(moveZRR);
BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR);
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
@ -876,9 +979,13 @@ populateTables()
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR);
BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR);
BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR);
BinaryOperations[INDEX2(Compare, Register, Memory)] = CAST2(compareRM);
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
BinaryOperations[INDEX2(Compare, Memory, Memory)] = CAST2(compareMM);
} }
class MyAssembler: public Assembler { class MyAssembler: public Assembler {