mirror of
https://github.com/corda/corda.git
synced 2025-06-03 08:00:57 +00:00
got a simple arithmetic test working
This commit is contained in:
parent
9971eaa92a
commit
af9758a6d3
@ -168,6 +168,13 @@ class Assembler {
|
|||||||
virtual unsigned value() = 0;
|
virtual unsigned value() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Block {
|
||||||
|
public:
|
||||||
|
virtual ~Block() { }
|
||||||
|
|
||||||
|
virtual unsigned resolve(unsigned start, Block* next) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class Architecture {
|
class Architecture {
|
||||||
public:
|
public:
|
||||||
virtual ~Architecture() { }
|
virtual ~Architecture() { }
|
||||||
@ -179,6 +186,8 @@ class Assembler {
|
|||||||
virtual int returnLow() = 0;
|
virtual int returnLow() = 0;
|
||||||
virtual int returnHigh() = 0;
|
virtual int returnHigh() = 0;
|
||||||
|
|
||||||
|
virtual bool condensedAddressing() = 0;
|
||||||
|
|
||||||
virtual bool reserved(int register_) = 0;
|
virtual bool reserved(int register_) = 0;
|
||||||
|
|
||||||
virtual unsigned argumentRegisterCount() = 0;
|
virtual unsigned argumentRegisterCount() = 0;
|
||||||
@ -245,7 +254,7 @@ class Assembler {
|
|||||||
|
|
||||||
virtual Offset* offset() = 0;
|
virtual Offset* offset() = 0;
|
||||||
|
|
||||||
virtual void endBlock() = 0;
|
virtual Block* endBlock() = 0;
|
||||||
|
|
||||||
virtual unsigned length() = 0;
|
virtual unsigned length() = 0;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ vmCall();
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool Verbose = false;
|
const bool Verbose = true;
|
||||||
const bool DebugNatives = false;
|
const bool DebugNatives = false;
|
||||||
const bool DebugCallTable = false;
|
const bool DebugCallTable = false;
|
||||||
const bool DebugMethodTree = false;
|
const bool DebugMethodTree = false;
|
||||||
@ -3832,11 +3832,11 @@ finish(MyThread* t, Context* context)
|
|||||||
strcmp
|
strcmp
|
||||||
(reinterpret_cast<const char*>
|
(reinterpret_cast<const char*>
|
||||||
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
||||||
"java/lang/String") == 0 and
|
"Simple") == 0 and
|
||||||
strcmp
|
strcmp
|
||||||
(reinterpret_cast<const char*>
|
(reinterpret_cast<const char*>
|
||||||
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
||||||
"compareTo") == 0)
|
"main") == 0)
|
||||||
{
|
{
|
||||||
asm("int3");
|
asm("int3");
|
||||||
}
|
}
|
||||||
@ -4959,6 +4959,8 @@ compileThunks(MyThread* t, MyProcessor* p)
|
|||||||
|
|
||||||
Assembler::Register result(t->arch->returnLow());
|
Assembler::Register result(t->arch->returnLow());
|
||||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||||
|
|
||||||
|
a->endBlock()->resolve(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext nativeContext(t);
|
ThunkContext nativeContext(t);
|
||||||
@ -4979,6 +4981,8 @@ compileThunks(MyThread* t, MyProcessor* p)
|
|||||||
a->popFrame();
|
a->popFrame();
|
||||||
|
|
||||||
a->apply(Return);
|
a->apply(Return);
|
||||||
|
|
||||||
|
a->endBlock()->resolve(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext aioobContext(t);
|
ThunkContext aioobContext(t);
|
||||||
@ -4996,6 +5000,8 @@ compileThunks(MyThread* t, MyProcessor* p)
|
|||||||
|
|
||||||
Assembler::Constant proc(&(aioobContext.promise));
|
Assembler::Constant proc(&(aioobContext.promise));
|
||||||
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
||||||
|
|
||||||
|
a->endBlock()->resolve(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThunkContext tableContext(t);
|
ThunkContext tableContext(t);
|
||||||
@ -5006,6 +5012,8 @@ compileThunks(MyThread* t, MyProcessor* p)
|
|||||||
|
|
||||||
Assembler::Constant proc(&(tableContext.promise));
|
Assembler::Constant proc(&(tableContext.promise));
|
||||||
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
||||||
|
|
||||||
|
a->endBlock()->resolve(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
p->thunkSize = pad(tableContext.context.assembler->length());
|
p->thunkSize = pad(tableContext.context.assembler->length());
|
||||||
|
@ -15,8 +15,8 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool DebugAppend = false;
|
const bool DebugAppend = true;
|
||||||
const bool DebugCompile = false;
|
const bool DebugCompile = true;
|
||||||
const bool DebugStack = false;
|
const bool DebugStack = false;
|
||||||
const bool DebugRegisters = false;
|
const bool DebugRegisters = false;
|
||||||
|
|
||||||
@ -120,9 +120,10 @@ class State {
|
|||||||
|
|
||||||
class LogicalInstruction {
|
class LogicalInstruction {
|
||||||
public:
|
public:
|
||||||
LogicalInstruction() {
|
LogicalInstruction(int index):
|
||||||
memset(this, 0, sizeof(LogicalInstruction));
|
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(0), locals(0),
|
||||||
}
|
machineOffset(0), index(index), stackSaved(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
Event* firstEvent;
|
Event* firstEvent;
|
||||||
Event* lastEvent;
|
Event* lastEvent;
|
||||||
@ -321,6 +322,17 @@ class CodePromise: public Promise {
|
|||||||
CodePromise* next;
|
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 {
|
class IpPromise: public Promise {
|
||||||
public:
|
public:
|
||||||
IpPromise(Context* c, int logicalIp):
|
IpPromise(Context* c, int logicalIp):
|
||||||
@ -331,7 +343,7 @@ class IpPromise: public Promise {
|
|||||||
virtual int64_t value() {
|
virtual int64_t value() {
|
||||||
if (resolved()) {
|
if (resolved()) {
|
||||||
return reinterpret_cast<intptr_t>
|
return reinterpret_cast<intptr_t>
|
||||||
(c->machineCode + c->logicalCode[logicalIp]->machineOffset->value());
|
(c->machineCode + machineOffset(c, logicalIp));
|
||||||
}
|
}
|
||||||
|
|
||||||
abort(c);
|
abort(c);
|
||||||
@ -365,6 +377,12 @@ expect(Context* c, bool v)
|
|||||||
expect(c->system, 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 {
|
class Event {
|
||||||
public:
|
public:
|
||||||
Event(Context* c):
|
Event(Context* c):
|
||||||
@ -377,6 +395,8 @@ class Event {
|
|||||||
|
|
||||||
if (c->lastEvent) {
|
if (c->lastEvent) {
|
||||||
c->lastEvent->next = this;
|
c->lastEvent->next = this;
|
||||||
|
predecessors = cons(c, c->lastEvent, 0);
|
||||||
|
c->lastEvent->successors = cons(c, this, c->lastEvent->successors);
|
||||||
} else {
|
} else {
|
||||||
c->firstEvent = this;
|
c->firstEvent = this;
|
||||||
}
|
}
|
||||||
@ -1367,6 +1387,7 @@ insertRead(Context*, Event* event, int sequence, Value* v, Read* r)
|
|||||||
{
|
{
|
||||||
r->value = v;
|
r->value = v;
|
||||||
r->event = event;
|
r->event = event;
|
||||||
|
r->eventNext = event->reads;
|
||||||
event->reads = r;
|
event->reads = r;
|
||||||
++ event->readCount;
|
++ event->readCount;
|
||||||
|
|
||||||
@ -1791,10 +1812,12 @@ class CombineEvent: public Event {
|
|||||||
unsigned firstSize, Value* first,
|
unsigned firstSize, Value* first,
|
||||||
unsigned secondSize, Value* second,
|
unsigned secondSize, Value* second,
|
||||||
unsigned resultSize, Value* result,
|
unsigned resultSize, Value* result,
|
||||||
Read* firstRead, Read* secondRead):
|
Read* firstRead,
|
||||||
|
Read* secondRead,
|
||||||
|
Read* resultRead):
|
||||||
Event(c), type(type), firstSize(firstSize), first(first),
|
Event(c), type(type), firstSize(firstSize), first(first),
|
||||||
secondSize(secondSize), second(second), resultSize(resultSize),
|
secondSize(secondSize), second(second), resultSize(resultSize),
|
||||||
result(result)
|
result(result), resultRead(resultRead)
|
||||||
{
|
{
|
||||||
addRead(c, first, firstRead);
|
addRead(c, first, firstRead);
|
||||||
addRead(c, second, secondRead);
|
addRead(c, second, secondRead);
|
||||||
@ -1805,18 +1828,20 @@ class CombineEvent: public Event {
|
|||||||
fprintf(stderr, "CombineEvent.compile\n");
|
fprintf(stderr, "CombineEvent.compile\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Site* target;
|
||||||
|
if (c->arch->condensedAddressing()) {
|
||||||
maybePreserve(c, stack, locals, secondSize, second, second->source);
|
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,
|
apply(c, type, firstSize, first->source, secondSize, second->source,
|
||||||
resultSize, target);
|
resultSize, target);
|
||||||
|
|
||||||
nextRead(c, first);
|
nextRead(c, first);
|
||||||
nextRead(c, second);
|
nextRead(c, second);
|
||||||
|
|
||||||
if (live(result)) {
|
|
||||||
addSite(c, 0, 0, resultSize, result, target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TernaryOperation type;
|
TernaryOperation type;
|
||||||
@ -1826,6 +1851,7 @@ class CombineEvent: public Event {
|
|||||||
Value* second;
|
Value* second;
|
||||||
unsigned resultSize;
|
unsigned resultSize;
|
||||||
Value* result;
|
Value* result;
|
||||||
|
Read* resultRead;
|
||||||
};
|
};
|
||||||
|
|
||||||
Value*
|
Value*
|
||||||
@ -1902,7 +1928,15 @@ appendCombine(Context* c, TernaryOperation type,
|
|||||||
fprintf(stderr, "appendCombine\n");
|
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)))
|
new (c->zone->allocate(sizeof(CombineEvent)))
|
||||||
CombineEvent
|
CombineEvent
|
||||||
@ -1911,7 +1945,8 @@ appendCombine(Context* c, TernaryOperation type,
|
|||||||
secondSize, second,
|
secondSize, second,
|
||||||
resultSize, result,
|
resultSize, result,
|
||||||
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
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
|
unsigned
|
||||||
frameFootprint(Context* c, Stack* s)
|
frameFootprint(Context* c, Stack* s)
|
||||||
{
|
{
|
||||||
return c->localFootprint + s->index + s->size;
|
return c->localFootprint + (s ? (s->index + s->size) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2448,7 +2483,7 @@ next(Context* c, LogicalInstruction* i)
|
|||||||
{
|
{
|
||||||
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
|
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
|
||||||
i = c->logicalCode[n];
|
i = c->logicalCode[n];
|
||||||
if (i) return i;
|
if (i and i->firstEvent) return i;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2456,12 +2491,12 @@ next(Context* c, LogicalInstruction* i)
|
|||||||
class Block {
|
class Block {
|
||||||
public:
|
public:
|
||||||
Block(Event* head):
|
Block(Event* head):
|
||||||
head(head), nextInstruction(0), offset(0), start(0)
|
head(head), nextInstruction(0), assemblerBlock(0), start(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Event* head;
|
Event* head;
|
||||||
LogicalInstruction* nextInstruction;
|
LogicalInstruction* nextInstruction;
|
||||||
Assembler::Offset* offset;
|
Assembler::Block* assemblerBlock;
|
||||||
unsigned start;
|
unsigned start;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2490,12 +2525,14 @@ compile(Context* c)
|
|||||||
e->logicalInstruction->machineOffset = a->offset();
|
e->logicalInstruction->machineOffset = a->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->predecessors) {
|
||||||
Event* predecessor = static_cast<Event*>(e->predecessors->value);
|
Event* predecessor = static_cast<Event*>(e->predecessors->value);
|
||||||
if (e->predecessors->next) {
|
if (e->predecessors->next) {
|
||||||
setSites(c, e, predecessor->junctionSites);
|
setSites(c, e, predecessor->junctionSites);
|
||||||
} else if (predecessor->successors->next) {
|
} else if (predecessor->successors->next) {
|
||||||
setSites(c, e, predecessor->savedSites);
|
setSites(c, e, predecessor->savedSites);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
populateSources(c, e);
|
populateSources(c, e);
|
||||||
|
|
||||||
@ -2514,28 +2551,25 @@ compile(Context* c)
|
|||||||
if (e->next and e->logicalInstruction->lastEvent == e) {
|
if (e->next and e->logicalInstruction->lastEvent == e) {
|
||||||
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
||||||
if (nextInstruction != e->next->logicalInstruction) {
|
if (nextInstruction != e->next->logicalInstruction) {
|
||||||
a->endBlock();
|
|
||||||
|
|
||||||
block->nextInstruction = nextInstruction;
|
block->nextInstruction = nextInstruction;
|
||||||
block->offset = a->offset();
|
block->assemblerBlock = a->endBlock();
|
||||||
block = ::block(c, e->next);
|
block = ::block(c, e->next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a->endBlock();
|
|
||||||
|
|
||||||
block->nextInstruction = 0;
|
block->nextInstruction = 0;
|
||||||
block->offset = a->offset();
|
block->assemblerBlock = a->endBlock();
|
||||||
|
|
||||||
block = firstBlock;
|
block = firstBlock;
|
||||||
while (block->nextInstruction) {
|
while (block->nextInstruction) {
|
||||||
Block* next = block->nextInstruction->firstEvent->block;
|
Block* next = block->nextInstruction->firstEvent->block;
|
||||||
next->start = block->offset->resolve(block->start);
|
next->start = block->assemblerBlock->resolve
|
||||||
|
(block->start, next->assemblerBlock);
|
||||||
block = next;
|
block = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block->offset->resolve(block->start);
|
return block->assemblerBlock->resolve(block->start, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
@ -2599,8 +2633,11 @@ visit(Context* c, unsigned logicalIp)
|
|||||||
{
|
{
|
||||||
assert(c, logicalIp < c->logicalCodeLength);
|
assert(c, logicalIp < c->logicalCodeLength);
|
||||||
|
|
||||||
|
if (c->logicalCode[logicalIp] == 0) {
|
||||||
c->logicalCode[logicalIp] = new
|
c->logicalCode[logicalIp] = new
|
||||||
(c->zone->allocate(sizeof(LogicalInstruction))) LogicalInstruction;
|
(c->zone->allocate(sizeof(LogicalInstruction)))
|
||||||
|
LogicalInstruction(logicalIp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Client: public Assembler::Client {
|
class Client: public Assembler::Client {
|
||||||
|
162
src/x86.cpp
162
src/x86.cpp
@ -34,6 +34,8 @@ enum {
|
|||||||
r15 = 15,
|
r15 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unsigned FrameHeaderSize = 2;
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
isInt8(intptr_t v)
|
isInt8(intptr_t v)
|
||||||
{
|
{
|
||||||
@ -48,19 +50,28 @@ isInt32(intptr_t v)
|
|||||||
|
|
||||||
class Task;
|
class Task;
|
||||||
|
|
||||||
class Block {
|
class MyBlock: public Assembler::Block {
|
||||||
public:
|
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 offset;
|
||||||
unsigned start;
|
unsigned start;
|
||||||
|
unsigned size;
|
||||||
|
MyBlock* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
Context(System* s, Allocator* a, Zone* zone):
|
Context(System* s, Allocator* a, Zone* zone):
|
||||||
s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0),
|
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;
|
System* s;
|
||||||
@ -69,7 +80,8 @@ class Context {
|
|||||||
Vector code;
|
Vector code;
|
||||||
Task* tasks;
|
Task* tasks;
|
||||||
uint8_t* result;
|
uint8_t* result;
|
||||||
Block* block;
|
MyBlock* firstBlock;
|
||||||
|
MyBlock* lastBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*OperationType)(Context*);
|
typedef void (*OperationType)(Context*);
|
||||||
@ -623,11 +635,95 @@ moveCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
subtractBorrowCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
|
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)
|
unsigned bSize UNUSED, Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, aSize == bSize);
|
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();
|
int64_t v = a->value->value();
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
@ -661,7 +757,7 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
|||||||
Assembler::Register bh(b->high);
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
subtractCR(c, 4, &al, 4, b);
|
subtractCR(c, 4, &al, 4, b);
|
||||||
subtractBorrowCR(c, 4, &ah, 4, &bh);
|
subtractBorrowCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
if (aSize == 8) rex(c);
|
if (aSize == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
@ -683,13 +779,12 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
subtractBorrowRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
|
subtractBorrowRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
unsigned bSize UNUSED, Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, aSize == bSize);
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
assert(c, BytesPerWord == 8 or aSize == 4);
|
|
||||||
|
|
||||||
if (aSize == 8) rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x19);
|
c->code.append(0x19);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
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);
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
subtractRR(c, 4, a, 4, b);
|
subtractRR(c, 4, a, 4, b);
|
||||||
subtractBorrowRR(c, 4, &ah, 4, &bh);
|
subtractBorrowRR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
if (aSize == 8) rex(c);
|
if (aSize == 8) rex(c);
|
||||||
c->code.append(0x29);
|
c->code.append(0x29);
|
||||||
@ -741,9 +836,12 @@ populateTables(ArchitectureContext* c)
|
|||||||
uo[index(LongJump, C)] = CAST1(longJumpC);
|
uo[index(LongJump, C)] = CAST1(longJumpC);
|
||||||
|
|
||||||
bo[index(Move, R, R)] = CAST2(moveRR);
|
bo[index(Move, R, R)] = CAST2(moveRR);
|
||||||
|
bo[index(Move, C, R)] = CAST2(moveCR);
|
||||||
bo[index(Move, M, R)] = CAST2(moveMR);
|
bo[index(Move, M, R)] = CAST2(moveMR);
|
||||||
bo[index(Move, R, M)] = CAST2(moveRM);
|
bo[index(Move, R, M)] = CAST2(moveRM);
|
||||||
|
|
||||||
|
bo[index(Add, C, R)] = CAST2(addCR);
|
||||||
|
|
||||||
bo[index(Subtract, C, R)] = CAST2(subtractCR);
|
bo[index(Subtract, C, R)] = CAST2(subtractCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,6 +867,10 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
return rax;
|
return rax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool condensedAddressing() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool reserved(int register_) {
|
virtual bool reserved(int register_) {
|
||||||
switch (register_) {
|
switch (register_) {
|
||||||
case rbp:
|
case rbp:
|
||||||
@ -822,7 +924,8 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
||||||
const unsigned alignment = 16 / BytesPerWord;
|
const unsigned alignment = 16 / BytesPerWord;
|
||||||
return (ceiling(sizeInWords + 2, alignment) * alignment);
|
return (ceiling(sizeInWords + FrameHeaderSize, alignment) * alignment)
|
||||||
|
- FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* frameIp(void* stack) {
|
virtual void* frameIp(void* stack) {
|
||||||
@ -830,7 +933,7 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameHeaderSize() {
|
virtual unsigned frameHeaderSize() {
|
||||||
return 2;
|
return FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameFooterSize() {
|
virtual unsigned frameFooterSize() {
|
||||||
@ -936,7 +1039,7 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
|
|
||||||
class MyOffset: public Assembler::Offset {
|
class MyOffset: public Assembler::Offset {
|
||||||
public:
|
public:
|
||||||
MyOffset(Context* c, Block* block, unsigned offset):
|
MyOffset(Context* c, MyBlock* block, unsigned offset):
|
||||||
c(c), block(block), offset(offset)
|
c(c), block(block), offset(offset)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -955,7 +1058,7 @@ class MyOffset: public Assembler::Offset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
Block* block;
|
MyBlock* block;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1002,14 +1105,15 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
allocateFrame(footprint);
|
allocateFrame(arch_->alignFrameSize(footprint));
|
||||||
|
|
||||||
|
unsigned offset = 0;
|
||||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||||
Memory dst(rsp, footprint);
|
Memory dst(rsp, offset * BytesPerWord);
|
||||||
apply(Move,
|
apply(Move,
|
||||||
arguments[i].size, arguments[i].type, arguments[i].operand,
|
arguments[i].size, arguments[i].type, arguments[i].operand,
|
||||||
pad(arguments[i].size), MemoryOperand, &dst);
|
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,
|
apply(Move, BytesPerWord, RegisterOperand, &stack,
|
||||||
BytesPerWord, RegisterOperand, &base);
|
BytesPerWord, RegisterOperand, &base);
|
||||||
|
|
||||||
Constant footprintConstant
|
Constant footprintConstant(resolved(&c, footprint * BytesPerWord));
|
||||||
(resolved(&c, arch_->alignFrameSize(footprint) * BytesPerWord));
|
|
||||||
apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant,
|
apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant,
|
||||||
BytesPerWord, RegisterOperand, &stack,
|
BytesPerWord, RegisterOperand, &stack,
|
||||||
BytesPerWord, RegisterOperand, &stack);
|
BytesPerWord, RegisterOperand, &stack);
|
||||||
@ -1070,7 +1173,10 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
virtual void writeTo(uint8_t* dst) {
|
virtual void writeTo(uint8_t* dst) {
|
||||||
c.result = 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) {
|
for (Task* t = c.tasks; t; t = t->next) {
|
||||||
t->run(&c);
|
t->run(&c);
|
||||||
@ -1079,11 +1185,15 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
virtual Offset* offset() {
|
virtual Offset* offset() {
|
||||||
return new (c.zone->allocate(sizeof(MyOffset)))
|
return new (c.zone->allocate(sizeof(MyOffset)))
|
||||||
MyOffset(&c, c.block, c.code.length());
|
MyOffset(&c, c.lastBlock, c.code.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void endBlock() {
|
virtual Block* endBlock() {
|
||||||
c.block = new (c.zone->allocate(sizeof(Block))) Block(c.code.length());
|
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() {
|
virtual unsigned length() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user