mirror of
https://github.com/corda/corda.git
synced 2025-01-08 14:03:06 +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;
|
||||
};
|
||||
|
||||
class Client {
|
||||
public:
|
||||
virtual ~Client() { }
|
||||
|
||||
virtual int acquireTemporary() = 0;
|
||||
virtual void releaseTemporary(int r) = 0;
|
||||
};
|
||||
|
||||
virtual ~Assembler() { }
|
||||
|
||||
virtual void setClient(Client* client) = 0;
|
||||
|
||||
virtual unsigned registerCount() = 0;
|
||||
|
||||
virtual int base() = 0;
|
||||
|
@ -759,10 +759,11 @@ appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags,
|
||||
}
|
||||
|
||||
int
|
||||
freeRegister(Context* c)
|
||||
freeRegisterExcept(Context* c, int except)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return i;
|
||||
@ -770,7 +771,9 @@ freeRegister(Context* c)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -778,11 +781,18 @@ freeRegister(Context* c)
|
||||
abort(c);
|
||||
}
|
||||
|
||||
inline int
|
||||
freeRegister(Context* c)
|
||||
{
|
||||
return freeRegisterExcept(c, NoRegister);
|
||||
}
|
||||
|
||||
RegisterValue*
|
||||
freeRegister(Context* c, unsigned size)
|
||||
{
|
||||
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 {
|
||||
return register_(c, freeRegister(c));
|
||||
}
|
||||
@ -943,14 +953,6 @@ class MoveEvent: public Event {
|
||||
{
|
||||
dst->value = src->value;
|
||||
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);
|
||||
@ -1406,11 +1408,14 @@ compile(Context* c)
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
||||
LogicalInstruction* li = c->logicalCode + i;
|
||||
li->machineOffset = a->length();
|
||||
|
||||
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);
|
||||
|
||||
if (e == c->logicalCode[i].lastEvent) break;
|
||||
if (e == li->lastEvent) break;
|
||||
|
||||
for (CodePromise* p = e->promises; p; p = p->next) {
|
||||
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 {
|
||||
public:
|
||||
MyCompiler(System* s, Assembler* assembler, Zone* zone):
|
||||
c(s, assembler, zone)
|
||||
{ }
|
||||
c(s, assembler, zone), client(&c)
|
||||
{
|
||||
assembler->setClient(&client);
|
||||
}
|
||||
|
||||
virtual void pushState() {
|
||||
::pushState(&c);
|
||||
@ -1795,6 +1819,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
Context c;
|
||||
Client client;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
130
src/x86.cpp
130
src/x86.cpp
@ -52,11 +52,12 @@ class Task;
|
||||
class Context {
|
||||
public:
|
||||
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;
|
||||
Zone* zone;
|
||||
Assembler::Client* client;
|
||||
Vector code;
|
||||
Task* tasks;
|
||||
uint8_t* result;
|
||||
@ -341,6 +342,50 @@ jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* 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
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
||||
{
|
||||
@ -564,7 +633,7 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
|
||||
void
|
||||
subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
@ -587,7 +656,7 @@ subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
|
||||
void
|
||||
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
@ -611,17 +680,19 @@ andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
int64_t v = a->value->value();
|
||||
|
||||
rex(c);
|
||||
if (isInt8(a->value->value())) {
|
||||
if (isInt8(v)) {
|
||||
c->code.append(0x83);
|
||||
c->code.append(0xe0 | b->low);
|
||||
c->code.append(a->value->value());
|
||||
} else {
|
||||
assert(c, isInt32(a->value->value()));
|
||||
|
||||
} else if (isInt32(v)) {
|
||||
c->code.append(0x81);
|
||||
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);
|
||||
|
||||
int64_t v = a->value->value();
|
||||
|
||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true);
|
||||
if (isInt8(a->value->value())) {
|
||||
c->code.append(a->value->value());
|
||||
} else if (isInt32(a->value->value())) {
|
||||
c->code.append4(a->value->value());
|
||||
if (isInt8(v)) {
|
||||
c->code.append(v);
|
||||
} else if (isInt32(v)) {
|
||||
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 {
|
||||
abort(c);
|
||||
}
|
||||
@ -648,6 +743,7 @@ compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
|
||||
|
||||
if (isInt8(a->value->value())) {
|
||||
c->code.append(a->value->value());
|
||||
} else if (isInt32(a->value->value())) {
|
||||
@ -672,7 +768,9 @@ populateTables()
|
||||
|
||||
UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)]
|
||||
= CAST1(jumpIfGreaterOrEqualC);
|
||||
UnaryOperations[INDEX1(JumpIfEqual, Constant)] = CAST1(jumpIfEqualC);
|
||||
|
||||
UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC);
|
||||
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
||||
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
|
||||
|
||||
@ -687,6 +785,8 @@ populateTables()
|
||||
BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR);
|
||||
BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR);
|
||||
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, Memory, Register)] = CAST2(move4To8MR);
|
||||
@ -700,6 +800,7 @@ populateTables()
|
||||
|
||||
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
||||
|
||||
BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR);
|
||||
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() {
|
||||
return 8;//BytesPerWord == 4 ? 8 : 16;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user