mirror of
https://github.com/corda/corda.git
synced 2025-01-09 14:33:30 +00:00
allow assembler to acquire and release temporary registers; new machine instruction implementations; bugfixes
This commit is contained in:
parent
406f173982
commit
6a9fbc0c17
@ -133,8 +133,18 @@ class Assembler {
|
|||||||
TraceHandler* traceHandler;
|
TraceHandler* traceHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
virtual ~Client() { }
|
||||||
|
|
||||||
|
virtual int acquireTemporary() = 0;
|
||||||
|
virtual void releaseTemporary(int r) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~Assembler() { }
|
virtual ~Assembler() { }
|
||||||
|
|
||||||
|
virtual void setClient(Client* client) = 0;
|
||||||
|
|
||||||
virtual unsigned registerCount() = 0;
|
virtual unsigned registerCount() = 0;
|
||||||
|
|
||||||
virtual int base() = 0;
|
virtual int base() = 0;
|
||||||
|
@ -759,10 +759,11 @@ appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
freeRegister(Context* c)
|
freeRegisterExcept(Context* c, int except)
|
||||||
{
|
{
|
||||||
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
||||||
if ((not c->registers[i].reserved)
|
if (i != except
|
||||||
|
and (not c->registers[i].reserved)
|
||||||
and c->registers[i].operand == 0)
|
and c->registers[i].operand == 0)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
@ -770,7 +771,9 @@ freeRegister(Context* c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
||||||
if (not c->registers[i].reserved) {
|
if (i != except
|
||||||
|
and (not c->registers[i].reserved))
|
||||||
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -778,11 +781,18 @@ freeRegister(Context* c)
|
|||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
freeRegister(Context* c)
|
||||||
|
{
|
||||||
|
return freeRegisterExcept(c, NoRegister);
|
||||||
|
}
|
||||||
|
|
||||||
RegisterValue*
|
RegisterValue*
|
||||||
freeRegister(Context* c, unsigned size)
|
freeRegister(Context* c, unsigned size)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
return register_(c, freeRegister(c), freeRegister(c));
|
int low = freeRegister(c);
|
||||||
|
return register_(c, low, freeRegisterExcept(c, low));
|
||||||
} else {
|
} else {
|
||||||
return register_(c, freeRegister(c));
|
return register_(c, freeRegister(c));
|
||||||
}
|
}
|
||||||
@ -943,14 +953,6 @@ class MoveEvent: public Event {
|
|||||||
{
|
{
|
||||||
dst->value = src->value;
|
dst->value = src->value;
|
||||||
return;
|
return;
|
||||||
} else if ((src->value->type(c) == Address
|
|
||||||
or src->value->type(c) == Memory)
|
|
||||||
and src->target->type(c) == Memory)
|
|
||||||
{
|
|
||||||
RegisterValue* tmp = freeRegister(c, size);
|
|
||||||
tmp->preserve(c, stack, 0);
|
|
||||||
apply(c, Move, size, src->value, tmp);
|
|
||||||
src->value = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src->value->release(c, src);
|
src->value->release(c, src);
|
||||||
@ -1406,11 +1408,14 @@ compile(Context* c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
||||||
|
LogicalInstruction* li = c->logicalCode + i;
|
||||||
|
li->machineOffset = a->length();
|
||||||
|
|
||||||
fprintf(stderr, "compile ip %d\n", i);
|
fprintf(stderr, "compile ip %d\n", i);
|
||||||
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
|
for (Event* e = li->firstEvent; e; e = e->next) {
|
||||||
e->compile(c);
|
e->compile(c);
|
||||||
|
|
||||||
if (e == c->logicalCode[i].lastEvent) break;
|
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();
|
||||||
@ -1419,11 +1424,30 @@ compile(Context* c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Client: public Assembler::Client {
|
||||||
|
public:
|
||||||
|
Client(Context* c): c(c) { }
|
||||||
|
|
||||||
|
virtual int acquireTemporary() {
|
||||||
|
int r = freeRegister(c);
|
||||||
|
c->registers[r].reserved = true;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void releaseTemporary(int r) {
|
||||||
|
c->registers[r].reserved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
|
};
|
||||||
|
|
||||||
class MyCompiler: public Compiler {
|
class MyCompiler: public Compiler {
|
||||||
public:
|
public:
|
||||||
MyCompiler(System* s, Assembler* assembler, Zone* zone):
|
MyCompiler(System* s, Assembler* assembler, Zone* zone):
|
||||||
c(s, assembler, zone)
|
c(s, assembler, zone), client(&c)
|
||||||
{ }
|
{
|
||||||
|
assembler->setClient(&client);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void pushState() {
|
virtual void pushState() {
|
||||||
::pushState(&c);
|
::pushState(&c);
|
||||||
@ -1795,6 +1819,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Context c;
|
Context c;
|
||||||
|
Client client;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
126
src/x86.cpp
126
src/x86.cpp
@ -52,11 +52,12 @@ class Task;
|
|||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
Context(System* s, Allocator* a, Zone* zone):
|
Context(System* s, Allocator* a, Zone* zone):
|
||||||
s(s), zone(zone), code(s, a, 1024), tasks(0), result(0)
|
s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
Zone* zone;
|
Zone* zone;
|
||||||
|
Assembler::Client* client;
|
||||||
Vector code;
|
Vector code;
|
||||||
Task* tasks;
|
Task* tasks;
|
||||||
uint8_t* result;
|
uint8_t* result;
|
||||||
@ -341,6 +342,50 @@ jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
|||||||
conditional(c, 0x8d, a);
|
conditional(c, 0x8d, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||||
|
{
|
||||||
|
assert(c, size == BytesPerWord);
|
||||||
|
|
||||||
|
conditional(c, 0x84, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveCR(Context*, unsigned, Assembler::Constant*, Assembler::Register*);
|
||||||
|
|
||||||
|
void
|
||||||
|
pushR(Context*, unsigned, Assembler::Register*);
|
||||||
|
|
||||||
|
void
|
||||||
|
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);
|
||||||
|
|
||||||
|
pushC(c, 4, &ah);
|
||||||
|
pushC(c, 4, &al);
|
||||||
|
} else {
|
||||||
|
if (isInt8(v)) {
|
||||||
|
c->code.append(0x6a);
|
||||||
|
c->code.append(v);
|
||||||
|
} else if (isInt32(v)) {
|
||||||
|
c->code.append(0x68);
|
||||||
|
c->code.append4(v);
|
||||||
|
} else {
|
||||||
|
Assembler::Register tmp(c->client->acquireTemporary());
|
||||||
|
moveCR(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)
|
||||||
{
|
{
|
||||||
@ -531,6 +576,30 @@ moveAR(Context* c, unsigned size, Assembler::Address* a,
|
|||||||
moveMR(c, size, &memory, b);
|
moveMR(c, size, &memory, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveAM(Context* c, unsigned size, Assembler::Address* a,
|
||||||
|
Assembler::Memory* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
Assembler::Register tmp(c->client->acquireTemporary());
|
||||||
|
moveAR(c, size, a, &tmp);
|
||||||
|
moveRM(c, size, &tmp, b);
|
||||||
|
c->client->releaseTemporary(tmp.low);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveMM(Context* c, unsigned size, 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);
|
||||||
|
moveRM(c, size, &tmp, b);
|
||||||
|
c->client->releaseTemporary(tmp.low);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
||||||
{
|
{
|
||||||
@ -611,17 +680,19 @@ andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4);
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
|
int64_t v = a->value->value();
|
||||||
|
|
||||||
rex(c);
|
rex(c);
|
||||||
if (isInt8(a->value->value())) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x83);
|
c->code.append(0x83);
|
||||||
c->code.append(0xe0 | b->low);
|
c->code.append(0xe0 | b->low);
|
||||||
c->code.append(a->value->value());
|
c->code.append(a->value->value());
|
||||||
} else {
|
} else if (isInt32(v)) {
|
||||||
assert(c, isInt32(a->value->value()));
|
|
||||||
|
|
||||||
c->code.append(0x81);
|
c->code.append(0x81);
|
||||||
c->code.append(0xe0 | b->low);
|
c->code.append(0xe0 | b->low);
|
||||||
c->code.append(a->value->value());
|
c->code.append(v);
|
||||||
|
} else {
|
||||||
|
abort(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,11 +702,35 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4);
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
|
int64_t v = a->value->value();
|
||||||
|
|
||||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true);
|
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true);
|
||||||
if (isInt8(a->value->value())) {
|
if (isInt8(v)) {
|
||||||
c->code.append(a->value->value());
|
c->code.append(v);
|
||||||
} else if (isInt32(a->value->value())) {
|
} else if (isInt32(v)) {
|
||||||
c->code.append4(a->value->value());
|
c->code.append4(v);
|
||||||
|
} else {
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compareCR(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 (size == 8) rex(c);
|
||||||
|
if (isInt8(v)) {
|
||||||
|
c->code.append(0x83);
|
||||||
|
c->code.append(0xf8 | b->low);
|
||||||
|
c->code.append(v);
|
||||||
|
} else if (isInt32(v)) {
|
||||||
|
c->code.append(0x81);
|
||||||
|
c->code.append(0xf8 | b->low);
|
||||||
|
c->code.append4(v);
|
||||||
} else {
|
} else {
|
||||||
abort(c);
|
abort(c);
|
||||||
}
|
}
|
||||||
@ -648,6 +743,7 @@ compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
assert(c, BytesPerWord == 8 or size == 4);
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
|
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
|
||||||
|
|
||||||
if (isInt8(a->value->value())) {
|
if (isInt8(a->value->value())) {
|
||||||
c->code.append(a->value->value());
|
c->code.append(a->value->value());
|
||||||
} else if (isInt32(a->value->value())) {
|
} else if (isInt32(a->value->value())) {
|
||||||
@ -672,7 +768,9 @@ populateTables()
|
|||||||
|
|
||||||
UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)]
|
UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)]
|
||||||
= CAST1(jumpIfGreaterOrEqualC);
|
= CAST1(jumpIfGreaterOrEqualC);
|
||||||
|
UnaryOperations[INDEX1(JumpIfEqual, Constant)] = CAST1(jumpIfEqualC);
|
||||||
|
|
||||||
|
UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC);
|
||||||
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
||||||
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
|
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
|
||||||
|
|
||||||
@ -687,6 +785,8 @@ populateTables()
|
|||||||
BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR);
|
BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR);
|
||||||
BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR);
|
BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR);
|
||||||
BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR);
|
BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR);
|
||||||
|
BinaryOperations[INDEX2(Move, Address, Memory)] = CAST2(moveAM);
|
||||||
|
BinaryOperations[INDEX2(Move, Memory, Memory)] = CAST2(moveMM);
|
||||||
|
|
||||||
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);
|
||||||
@ -700,6 +800,7 @@ populateTables()
|
|||||||
|
|
||||||
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
||||||
|
|
||||||
|
BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR);
|
||||||
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
|
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,6 +814,11 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void setClient(Client* client) {
|
||||||
|
assert(&c, c.client == 0);
|
||||||
|
c.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned registerCount() {
|
virtual unsigned registerCount() {
|
||||||
return 8;//BytesPerWord == 4 ? 8 : 16;
|
return 8;//BytesPerWord == 4 ? 8 : 16;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user