got a simple arithmetic test working

This commit is contained in:
Joel Dice 2008-09-07 14:12:11 -06:00
parent 9971eaa92a
commit af9758a6d3
4 changed files with 230 additions and 66 deletions

View File

@ -168,6 +168,13 @@ class Assembler {
virtual unsigned value() = 0;
};
class Block {
public:
virtual ~Block() { }
virtual unsigned resolve(unsigned start, Block* next) = 0;
};
class Architecture {
public:
virtual ~Architecture() { }
@ -179,6 +186,8 @@ class Assembler {
virtual int returnLow() = 0;
virtual int returnHigh() = 0;
virtual bool condensedAddressing() = 0;
virtual bool reserved(int register_) = 0;
virtual unsigned argumentRegisterCount() = 0;
@ -245,7 +254,7 @@ class Assembler {
virtual Offset* offset() = 0;
virtual void endBlock() = 0;
virtual Block* endBlock() = 0;
virtual unsigned length() = 0;

View File

@ -27,7 +27,7 @@ vmCall();
namespace {
const bool Verbose = false;
const bool Verbose = true;
const bool DebugNatives = false;
const bool DebugCallTable = false;
const bool DebugMethodTree = false;
@ -3832,11 +3832,11 @@ finish(MyThread* t, Context* context)
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"java/lang/String") == 0 and
"Simple") == 0 and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)),
"compareTo") == 0)
"main") == 0)
{
asm("int3");
}
@ -4959,6 +4959,8 @@ compileThunks(MyThread* t, MyProcessor* p)
Assembler::Register result(t->arch->returnLow());
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
a->endBlock()->resolve(0, 0);
}
ThunkContext nativeContext(t);
@ -4979,6 +4981,8 @@ compileThunks(MyThread* t, MyProcessor* p)
a->popFrame();
a->apply(Return);
a->endBlock()->resolve(0, 0);
}
ThunkContext aioobContext(t);
@ -4996,6 +5000,8 @@ compileThunks(MyThread* t, MyProcessor* p)
Assembler::Constant proc(&(aioobContext.promise));
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
a->endBlock()->resolve(0, 0);
}
ThunkContext tableContext(t);
@ -5006,6 +5012,8 @@ compileThunks(MyThread* t, MyProcessor* p)
Assembler::Constant proc(&(tableContext.promise));
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
a->endBlock()->resolve(0, 0);
}
p->thunkSize = pad(tableContext.context.assembler->length());

View File

@ -15,8 +15,8 @@ using namespace vm;
namespace {
const bool DebugAppend = false;
const bool DebugCompile = false;
const bool DebugAppend = true;
const bool DebugCompile = true;
const bool DebugStack = false;
const bool DebugRegisters = false;
@ -120,9 +120,10 @@ class State {
class LogicalInstruction {
public:
LogicalInstruction() {
memset(this, 0, sizeof(LogicalInstruction));
}
LogicalInstruction(int index):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(0), locals(0),
machineOffset(0), index(index), stackSaved(false)
{ }
Event* firstEvent;
Event* lastEvent;
@ -321,6 +322,17 @@ class CodePromise: public Promise {
CodePromise* next;
};
unsigned
machineOffset(Context* c, int logicalIp)
{
for (unsigned n = logicalIp; n < c->logicalCodeLength; ++n) {
LogicalInstruction* i = c->logicalCode[n];
if (i and i->machineOffset) return i->machineOffset->value();
}
abort(c);
}
class IpPromise: public Promise {
public:
IpPromise(Context* c, int logicalIp):
@ -331,7 +343,7 @@ class IpPromise: public Promise {
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + c->logicalCode[logicalIp]->machineOffset->value());
(c->machineCode + machineOffset(c, logicalIp));
}
abort(c);
@ -365,6 +377,12 @@ expect(Context* c, bool v)
expect(c->system, v);
}
Cell*
cons(Context* c, void* value, Cell* next)
{
return new (c->zone->allocate(sizeof(Cell))) Cell(next, value);
}
class Event {
public:
Event(Context* c):
@ -377,6 +395,8 @@ class Event {
if (c->lastEvent) {
c->lastEvent->next = this;
predecessors = cons(c, c->lastEvent, 0);
c->lastEvent->successors = cons(c, this, c->lastEvent->successors);
} else {
c->firstEvent = this;
}
@ -1367,6 +1387,7 @@ insertRead(Context*, Event* event, int sequence, Value* v, Read* r)
{
r->value = v;
r->event = event;
r->eventNext = event->reads;
event->reads = r;
++ event->readCount;
@ -1791,10 +1812,12 @@ class CombineEvent: public Event {
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result,
Read* firstRead, Read* secondRead):
Read* firstRead,
Read* secondRead,
Read* resultRead):
Event(c), type(type), firstSize(firstSize), first(first),
secondSize(secondSize), second(second), resultSize(resultSize),
result(result)
result(result), resultRead(resultRead)
{
addRead(c, first, firstRead);
addRead(c, second, secondRead);
@ -1805,18 +1828,20 @@ class CombineEvent: public Event {
fprintf(stderr, "CombineEvent.compile\n");
}
maybePreserve(c, stack, locals, secondSize, second, second->source);
Site* target;
if (c->arch->condensedAddressing()) {
maybePreserve(c, stack, locals, secondSize, second, second->source);
target = second->source;
} else {
target = resultRead->allocateSite(c);
addSite(c, stack, locals, resultSize, result, target);
}
Site* target = targetOrRegister(c, result);
apply(c, type, firstSize, first->source, secondSize, second->source,
resultSize, target);
nextRead(c, first);
nextRead(c, second);
if (live(result)) {
addSite(c, 0, 0, resultSize, result, target);
}
}
TernaryOperation type;
@ -1826,6 +1851,7 @@ class CombineEvent: public Event {
Value* second;
unsigned resultSize;
Value* result;
Read* resultRead;
};
Value*
@ -1902,7 +1928,15 @@ appendCombine(Context* c, TernaryOperation type,
fprintf(stderr, "appendCombine\n");
}
// todo: respect resultTypeMask and resultRegisterMask
Read* resultRead = read
(c, resultSize, resultTypeMask, resultRegisterMask, AnyFrameIndex);
Read* secondRead;
if (c->arch->condensedAddressing()) {
secondRead = resultRead;
} else {
secondRead = read
(c, secondSize, secondTypeMask, secondRegisterMask, AnyFrameIndex);
}
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent
@ -1911,7 +1945,8 @@ appendCombine(Context* c, TernaryOperation type,
secondSize, second,
resultSize, result,
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex),
read(c, secondSize, secondTypeMask, secondRegisterMask, AnyFrameIndex));
secondRead,
resultRead);
}
}
@ -2331,7 +2366,7 @@ propagateJunctionSites(Context* c, Event* e, Site** sites)
unsigned
frameFootprint(Context* c, Stack* s)
{
return c->localFootprint + s->index + s->size;
return c->localFootprint + (s ? (s->index + s->size) : 0);
}
void
@ -2448,7 +2483,7 @@ next(Context* c, LogicalInstruction* i)
{
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
i = c->logicalCode[n];
if (i) return i;
if (i and i->firstEvent) return i;
}
return 0;
}
@ -2456,12 +2491,12 @@ next(Context* c, LogicalInstruction* i)
class Block {
public:
Block(Event* head):
head(head), nextInstruction(0), offset(0), start(0)
head(head), nextInstruction(0), assemblerBlock(0), start(0)
{ }
Event* head;
LogicalInstruction* nextInstruction;
Assembler::Offset* offset;
Assembler::Block* assemblerBlock;
unsigned start;
};
@ -2490,11 +2525,13 @@ compile(Context* c)
e->logicalInstruction->machineOffset = a->offset();
}
Event* predecessor = static_cast<Event*>(e->predecessors->value);
if (e->predecessors->next) {
setSites(c, e, predecessor->junctionSites);
} else if (predecessor->successors->next) {
setSites(c, e, predecessor->savedSites);
if (e->predecessors) {
Event* predecessor = static_cast<Event*>(e->predecessors->value);
if (e->predecessors->next) {
setSites(c, e, predecessor->junctionSites);
} else if (predecessor->successors->next) {
setSites(c, e, predecessor->savedSites);
}
}
populateSources(c, e);
@ -2514,28 +2551,25 @@ compile(Context* c)
if (e->next and e->logicalInstruction->lastEvent == e) {
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
if (nextInstruction != e->next->logicalInstruction) {
a->endBlock();
block->nextInstruction = nextInstruction;
block->offset = a->offset();
block->assemblerBlock = a->endBlock();
block = ::block(c, e->next);
}
}
}
a->endBlock();
block->nextInstruction = 0;
block->offset = a->offset();
block->assemblerBlock = a->endBlock();
block = firstBlock;
while (block->nextInstruction) {
Block* next = block->nextInstruction->firstEvent->block;
next->start = block->offset->resolve(block->start);
next->start = block->assemblerBlock->resolve
(block->start, next->assemblerBlock);
block = next;
}
return block->offset->resolve(block->start);
return block->assemblerBlock->resolve(block->start, 0);
}
unsigned
@ -2599,8 +2633,11 @@ visit(Context* c, unsigned logicalIp)
{
assert(c, logicalIp < c->logicalCodeLength);
c->logicalCode[logicalIp] = new
(c->zone->allocate(sizeof(LogicalInstruction))) LogicalInstruction;
if (c->logicalCode[logicalIp] == 0) {
c->logicalCode[logicalIp] = new
(c->zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(logicalIp);
}
}
class Client: public Assembler::Client {

View File

@ -34,6 +34,8 @@ enum {
r15 = 15,
};
const unsigned FrameHeaderSize = 2;
inline bool
isInt8(intptr_t v)
{
@ -48,19 +50,28 @@ isInt32(intptr_t v)
class Task;
class Block {
class MyBlock: public Assembler::Block {
public:
Block(unsigned offset): offset(offset), start(~0) { }
MyBlock(unsigned offset): offset(offset), start(~0), size(0), next(0) { }
virtual unsigned resolve(unsigned start, Assembler::Block* next) {
this->start = start;
this->next = static_cast<MyBlock*>(next);
return start + size;
}
unsigned offset;
unsigned start;
unsigned size;
MyBlock* next;
};
class Context {
public:
Context(System* s, Allocator* a, Zone* zone):
s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0),
block(0)
firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)),
lastBlock(firstBlock)
{ }
System* s;
@ -69,7 +80,8 @@ class Context {
Vector code;
Task* tasks;
uint8_t* result;
Block* block;
MyBlock* firstBlock;
MyBlock* lastBlock;
};
typedef void (*OperationType)(Context*);
@ -623,11 +635,95 @@ moveCR(Context* c, unsigned aSize, Assembler::Constant* a,
}
void
subtractBorrowCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
unsigned bSize UNUSED, Assembler::Register* b)
addCarryRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4);
if (size == 8) rex(c);
c->code.append(0x11);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
void
addRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize UNUSED, Assembler::Register* b)
{
assert(c, aSize == bSize);
assert(c, BytesPerWord == 8 or aSize == 4);
if (BytesPerWord == 4 and aSize == 8) {
Assembler::Register ah(a->high);
Assembler::Register bh(b->high);
addRR(c, 4, a, 4, b);
addCarryRR(c, 4, &ah, &bh);
} else {
if (aSize == 8) rex(c);
c->code.append(0x01);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
}
void
addCarryCR(Context* c, unsigned size UNUSED, 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(0xd0 | b->low);
c->code.append(v);
} else {
abort(c);
}
}
void
addCR(Context* c, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, aSize == bSize);
int64_t v = a->value->value();
if (v) {
if (BytesPerWord == 4 and aSize == 8) {
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Register bh(b->high);
addCR(c, 4, &al, 4, b);
addCarryCR(c, 4, &ah, &bh);
} else {
if (aSize == 8) rex(c);
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xc0 | b->low);
c->code.append(v);
} else if (isInt32(v)) {
c->code.append(0x81);
c->code.append(0xc0 | b->low);
c->code.append4(v);
} else {
Assembler::Register tmp(c->client->acquireTemporary());
moveCR(c, aSize, a, aSize, &tmp);
addRR(c, aSize, &tmp, bSize, b);
c->client->releaseTemporary(tmp.low);
}
}
}
}
void
subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4);
int64_t v = a->value->value();
if (isInt8(v)) {
@ -661,7 +757,7 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a,
Assembler::Register bh(b->high);
subtractCR(c, 4, &al, 4, b);
subtractBorrowCR(c, 4, &ah, 4, &bh);
subtractBorrowCR(c, 4, &ah, &bh);
} else {
if (aSize == 8) rex(c);
if (isInt8(v)) {
@ -683,13 +779,12 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a,
}
void
subtractBorrowRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
unsigned bSize UNUSED, Assembler::Register* b)
subtractBorrowRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
assert(c, aSize == bSize);
assert(c, BytesPerWord == 8 or aSize == 4);
assert(c, BytesPerWord == 8 or size == 4);
if (aSize == 8) rex(c);
if (size == 8) rex(c);
c->code.append(0x19);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
@ -705,7 +800,7 @@ subtractRR(Context* c, unsigned aSize, Assembler::Register* a,
Assembler::Register bh(b->high);
subtractRR(c, 4, a, 4, b);
subtractBorrowRR(c, 4, &ah, 4, &bh);
subtractBorrowRR(c, 4, &ah, &bh);
} else {
if (aSize == 8) rex(c);
c->code.append(0x29);
@ -741,9 +836,12 @@ populateTables(ArchitectureContext* c)
uo[index(LongJump, C)] = CAST1(longJumpC);
bo[index(Move, R, R)] = CAST2(moveRR);
bo[index(Move, C, R)] = CAST2(moveCR);
bo[index(Move, M, R)] = CAST2(moveMR);
bo[index(Move, R, M)] = CAST2(moveRM);
bo[index(Add, C, R)] = CAST2(addCR);
bo[index(Subtract, C, R)] = CAST2(subtractCR);
}
@ -769,6 +867,10 @@ class MyArchitecture: public Assembler::Architecture {
return rax;
}
virtual bool condensedAddressing() {
return true;
}
virtual bool reserved(int register_) {
switch (register_) {
case rbp:
@ -822,7 +924,8 @@ class MyArchitecture: public Assembler::Architecture {
virtual unsigned alignFrameSize(unsigned sizeInWords) {
const unsigned alignment = 16 / BytesPerWord;
return (ceiling(sizeInWords + 2, alignment) * alignment);
return (ceiling(sizeInWords + FrameHeaderSize, alignment) * alignment)
- FrameHeaderSize;
}
virtual void* frameIp(void* stack) {
@ -830,7 +933,7 @@ class MyArchitecture: public Assembler::Architecture {
}
virtual unsigned frameHeaderSize() {
return 2;
return FrameHeaderSize;
}
virtual unsigned frameFooterSize() {
@ -936,7 +1039,7 @@ class MyArchitecture: public Assembler::Architecture {
class MyOffset: public Assembler::Offset {
public:
MyOffset(Context* c, Block* block, unsigned offset):
MyOffset(Context* c, MyBlock* block, unsigned offset):
c(c), block(block), offset(offset)
{ }
@ -955,7 +1058,7 @@ class MyOffset: public Assembler::Offset {
}
Context* c;
Block* block;
MyBlock* block;
unsigned offset;
};
@ -1002,14 +1105,15 @@ class MyAssembler: public Assembler {
}
va_end(a);
allocateFrame(footprint);
allocateFrame(arch_->alignFrameSize(footprint));
unsigned offset = 0;
for (unsigned i = 0; i < argumentCount; ++i) {
Memory dst(rsp, footprint);
Memory dst(rsp, offset * BytesPerWord);
apply(Move,
arguments[i].size, arguments[i].type, arguments[i].operand,
pad(arguments[i].size), MemoryOperand, &dst);
footprint -= ceiling(arguments[i].size, BytesPerWord);
offset += ceiling(arguments[i].size, BytesPerWord);
}
}
@ -1021,8 +1125,7 @@ class MyAssembler: public Assembler {
apply(Move, BytesPerWord, RegisterOperand, &stack,
BytesPerWord, RegisterOperand, &base);
Constant footprintConstant
(resolved(&c, arch_->alignFrameSize(footprint) * BytesPerWord));
Constant footprintConstant(resolved(&c, footprint * BytesPerWord));
apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant,
BytesPerWord, RegisterOperand, &stack,
BytesPerWord, RegisterOperand, &stack);
@ -1070,7 +1173,10 @@ class MyAssembler: public Assembler {
virtual void writeTo(uint8_t* dst) {
c.result = dst;
memcpy(dst, c.code.data, c.code.length());
for (MyBlock* b = c.firstBlock; b; b = b->next) {
memcpy(dst + b->start, c.code.data + b->offset, b->size);
}
for (Task* t = c.tasks; t; t = t->next) {
t->run(&c);
@ -1079,11 +1185,15 @@ class MyAssembler: public Assembler {
virtual Offset* offset() {
return new (c.zone->allocate(sizeof(MyOffset)))
MyOffset(&c, c.block, c.code.length());
MyOffset(&c, c.lastBlock, c.code.length());
}
virtual void endBlock() {
c.block = new (c.zone->allocate(sizeof(Block))) Block(c.code.length());
virtual Block* endBlock() {
MyBlock* b = c.lastBlock;
b->size = c.code.length() - b->offset;
c.lastBlock = new (c.zone->allocate(sizeof(MyBlock)))
MyBlock(c.code.length());
return b;
}
virtual unsigned length() {