mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +00:00
various bugfixes and tweaks in new compiler, primarily related to duplicating stack operands
This commit is contained in:
parent
6271f878e8
commit
d654c943f3
@ -733,6 +733,10 @@ class Frame {
|
||||
return r;
|
||||
}
|
||||
|
||||
Compiler::Operand* peekLong(unsigned index) {
|
||||
return c->peek(8, index);
|
||||
}
|
||||
|
||||
Compiler::Operand* popLong() {
|
||||
poppedLong();
|
||||
return popLongQuiet();
|
||||
@ -803,10 +807,7 @@ class Frame {
|
||||
}
|
||||
|
||||
void dup() {
|
||||
Compiler::Operand* s0 = c->pop(BytesPerWord);
|
||||
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, c->peek(BytesPerWord, 0)));
|
||||
|
||||
dupped();
|
||||
}
|
||||
@ -817,7 +818,7 @@ class Frame {
|
||||
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s0));
|
||||
|
||||
duppedX1();
|
||||
}
|
||||
@ -830,7 +831,7 @@ class Frame {
|
||||
|
||||
c->push(BytesPerWord, s0);
|
||||
pushLongQuiet(s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s0));
|
||||
} else {
|
||||
Compiler::Operand* s1 = c->pop(BytesPerWord);
|
||||
Compiler::Operand* s2 = c->pop(BytesPerWord);
|
||||
@ -838,7 +839,7 @@ class Frame {
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, s2);
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s0));
|
||||
}
|
||||
|
||||
duppedX2();
|
||||
@ -846,18 +847,15 @@ class Frame {
|
||||
|
||||
void dup2() {
|
||||
if (get(sp - 1) == Long) {
|
||||
Compiler::Operand* s0 = popLongQuiet();
|
||||
|
||||
pushLongQuiet(s0);
|
||||
pushLongQuiet(s0);
|
||||
pushLongQuiet(c->dup(8, peekLong(0)));
|
||||
} else {
|
||||
Compiler::Operand* s0 = c->pop(BytesPerWord);
|
||||
Compiler::Operand* s1 = c->pop(BytesPerWord);
|
||||
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s1));
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s0));
|
||||
}
|
||||
|
||||
dupped2();
|
||||
@ -870,7 +868,7 @@ class Frame {
|
||||
|
||||
pushLongQuiet(s0);
|
||||
c->push(BytesPerWord, s1);
|
||||
pushLongQuiet(s0);
|
||||
pushLongQuiet(c->dup(8, s0));
|
||||
} else {
|
||||
Compiler::Operand* s0 = c->pop(BytesPerWord);
|
||||
Compiler::Operand* s1 = c->pop(BytesPerWord);
|
||||
@ -879,8 +877,8 @@ class Frame {
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, s2);
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s1));
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s0));
|
||||
}
|
||||
|
||||
dupped2X1();
|
||||
@ -895,7 +893,7 @@ class Frame {
|
||||
|
||||
pushLongQuiet(s0);
|
||||
pushLongQuiet(s1);
|
||||
pushLongQuiet(s0);
|
||||
pushLongQuiet(c->dup(8, s0));
|
||||
} else {
|
||||
Compiler::Operand* s1 = c->pop(BytesPerWord);
|
||||
Compiler::Operand* s2 = c->pop(BytesPerWord);
|
||||
@ -903,7 +901,7 @@ class Frame {
|
||||
pushLongQuiet(s0);
|
||||
c->push(BytesPerWord, s2);
|
||||
c->push(BytesPerWord, s1);
|
||||
pushLongQuiet(s0);
|
||||
pushLongQuiet(c->dup(8, s0));
|
||||
}
|
||||
} else {
|
||||
Compiler::Operand* s0 = c->pop(BytesPerWord);
|
||||
@ -915,8 +913,8 @@ class Frame {
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, s3);
|
||||
c->push(BytesPerWord, s2);
|
||||
c->push(BytesPerWord, s1);
|
||||
c->push(BytesPerWord, s0);
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s1));
|
||||
c->push(BytesPerWord, c->dup(BytesPerWord, s0));
|
||||
}
|
||||
|
||||
dupped2X2();
|
||||
@ -1788,7 +1786,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Compiler::Operand* instance = c->peek(0);
|
||||
Compiler::Operand* instance = c->peek(BytesPerWord, 0);
|
||||
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(checkCast)),
|
||||
@ -2396,7 +2394,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
frame->trace(0, false),
|
||||
BytesPerWord,
|
||||
3, c->thread(), frame->append(target),
|
||||
c->peek(instance)),
|
||||
c->peek(BytesPerWord, instance)),
|
||||
0,
|
||||
0,
|
||||
frame->trace(target, true),
|
||||
@ -2443,7 +2441,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
unsigned offset = ClassVtable + (methodOffset(t, target) * BytesPerWord);
|
||||
|
||||
Compiler::Operand* instance = c->peek(parameterFootprint - 1);
|
||||
Compiler::Operand* instance = c->peek
|
||||
(BytesPerWord, parameterFootprint - 1);
|
||||
|
||||
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
||||
|
||||
@ -3463,14 +3462,13 @@ finish(MyThread* t, Context* context)
|
||||
Compiler* c = context->compiler;
|
||||
|
||||
unsigned codeSize = c->compile();
|
||||
object result = allocateCode(t, codeSize + c->poolSize());
|
||||
object result = allocateCode(t, pad(codeSize) + c->poolSize());
|
||||
PROTECT(t, result);
|
||||
|
||||
uint8_t* start = reinterpret_cast<uint8_t*>(&singletonValue(t, result, 0));
|
||||
|
||||
c->writeTo(start);
|
||||
|
||||
PROTECT(t, result);
|
||||
|
||||
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
||||
|
||||
for (TraceElement* p = context->traceLog; p; p = p->next) {
|
||||
|
472
src/compiler.cpp
472
src/compiler.cpp
@ -22,10 +22,11 @@ class Value {
|
||||
public:
|
||||
virtual ~Value() { }
|
||||
|
||||
virtual bool equals(Value*) { return false; }
|
||||
virtual bool equals(RegisterValue*) { return false; }
|
||||
virtual OperandType type() = 0;
|
||||
|
||||
virtual void preserve(Context*) { }
|
||||
virtual bool equals(Value*) { return false; }
|
||||
|
||||
virtual void preserve(Context*, MyOperand*) { }
|
||||
virtual void acquire(Context*, MyOperand*) { }
|
||||
virtual void release(Context*, MyOperand*) { }
|
||||
|
||||
@ -39,15 +40,24 @@ class Value {
|
||||
class MyOperand: public Compiler::Operand {
|
||||
public:
|
||||
MyOperand(Value* value):
|
||||
event(0), value(value), target(0), size(0), index(0), next(0)
|
||||
event(0), value(value), target(0)
|
||||
{ }
|
||||
|
||||
Event* event;
|
||||
Value* value;
|
||||
Value* target;
|
||||
};
|
||||
|
||||
class Stack {
|
||||
public:
|
||||
Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next):
|
||||
operand(operand), size(size), index(index), next(next)
|
||||
{ }
|
||||
|
||||
MyOperand* operand;
|
||||
unsigned size;
|
||||
unsigned index;
|
||||
MyOperand* next;
|
||||
Stack* next;
|
||||
};
|
||||
|
||||
class State {
|
||||
@ -57,7 +67,7 @@ class State {
|
||||
next(s)
|
||||
{ }
|
||||
|
||||
MyOperand* stack;
|
||||
Stack* stack;
|
||||
State* next;
|
||||
};
|
||||
|
||||
@ -191,7 +201,7 @@ class PoolPromise: public Promise {
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + c->assembler->length() + key);
|
||||
(c->machineCode + pad(c->assembler->length()) + key);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
@ -209,6 +219,8 @@ class CodePromise: public Promise {
|
||||
public:
|
||||
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
|
||||
|
||||
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>(c->machineCode + offset);
|
||||
@ -257,6 +269,8 @@ class ConstantValue: public Value {
|
||||
public:
|
||||
ConstantValue(Promise* value): value(value) { }
|
||||
|
||||
virtual OperandType type() { return Constant; }
|
||||
|
||||
virtual RegisterValue* toRegister(Context* c);
|
||||
|
||||
virtual void asAssemblerOperand(Context*,
|
||||
@ -287,6 +301,8 @@ class AddressValue: public Value {
|
||||
public:
|
||||
AddressValue(Promise* address): address(address) { }
|
||||
|
||||
virtual OperandType type() { return Address; }
|
||||
|
||||
virtual RegisterValue* toRegister(Context* c);
|
||||
|
||||
virtual void asAssemblerOperand(Context*,
|
||||
@ -306,35 +322,43 @@ address(Context* c, Promise* address)
|
||||
return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address);
|
||||
}
|
||||
|
||||
void preserve(Context* c, int reg);
|
||||
void preserve(Context* c, int reg, MyOperand* a);
|
||||
|
||||
class RegisterValue: public Value {
|
||||
public:
|
||||
RegisterValue(int low, int high): register_(low, high) { }
|
||||
|
||||
virtual bool equals(Value* o) { return o->equals(this); }
|
||||
virtual OperandType type() { return Register; }
|
||||
|
||||
virtual bool equals(RegisterValue* o) {
|
||||
return o->register_.low == register_.low
|
||||
and o->register_.high == register_.high;
|
||||
virtual bool equals(Value* o) {
|
||||
return this == o or
|
||||
(o->type() == Register
|
||||
and static_cast<RegisterValue*>(o)->register_.low == register_.low
|
||||
and static_cast<RegisterValue*>(o)->register_.high == register_.high);
|
||||
}
|
||||
|
||||
virtual void preserve(Context* c) {
|
||||
::preserve(c, register_.low);
|
||||
if (register_.high >= 0) ::preserve(c, register_.high);
|
||||
virtual void preserve(Context* c, MyOperand* a) {
|
||||
::preserve(c, register_.low, a);
|
||||
if (register_.high >= 0) ::preserve(c, register_.high, a);
|
||||
}
|
||||
|
||||
virtual void acquire(Context* c, MyOperand* a) {
|
||||
preserve(c);
|
||||
c->registers[register_.low].operand = a;
|
||||
if (register_.high >= 0) c->registers[register_.high].operand = a;
|
||||
if (a != c->registers[register_.low].operand) {
|
||||
fprintf(stderr, "%p acquire %d\n", a, register_.low);
|
||||
|
||||
preserve(c, a);
|
||||
c->registers[register_.low].operand = a;
|
||||
if (register_.high >= 0) c->registers[register_.high].operand = a;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void release(Context* c, MyOperand* a UNUSED) {
|
||||
assert(c, a == c->registers[register_.low].operand);
|
||||
if (a == c->registers[register_.low].operand) {
|
||||
fprintf(stderr, "%p release %d\n", a, register_.low);
|
||||
|
||||
c->registers[register_.low].operand = 0;
|
||||
if (register_.high >= 0) c->registers[register_.high].operand = 0;
|
||||
c->registers[register_.low].operand = 0;
|
||||
if (register_.high >= 0) c->registers[register_.high].operand = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual RegisterValue* toRegister(Context*) {
|
||||
@ -366,6 +390,17 @@ class MemoryValue: public Value {
|
||||
value(base, offset, index, scale, traceHandler)
|
||||
{ }
|
||||
|
||||
virtual OperandType type() { return Memory; }
|
||||
|
||||
virtual bool equals(Value* o) {
|
||||
return this == o or
|
||||
(o->type() == Memory
|
||||
and static_cast<MemoryValue*>(o)->value.base == value.base
|
||||
and static_cast<MemoryValue*>(o)->value.offset == value.offset
|
||||
and static_cast<MemoryValue*>(o)->value.index == value.index
|
||||
and static_cast<MemoryValue*>(o)->value.scale == value.scale);
|
||||
}
|
||||
|
||||
virtual RegisterValue* toRegister(Context* c) {
|
||||
RegisterValue* v = freeRegister(c, BytesPerWord);
|
||||
apply(c, Move, BytesPerWord, this, v);
|
||||
@ -458,7 +493,7 @@ class Event {
|
||||
virtual void compile(Context* c) = 0;
|
||||
|
||||
Event* next;
|
||||
MyOperand* stack;
|
||||
Stack* stack;
|
||||
CodePromise* promises;
|
||||
};
|
||||
|
||||
@ -466,7 +501,10 @@ class ArgumentEvent: public Event {
|
||||
public:
|
||||
ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index):
|
||||
Event(c), size(size), a(a), index(index)
|
||||
{ }
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == a);
|
||||
@ -475,7 +513,7 @@ class ArgumentEvent: public Event {
|
||||
return register_(c, c->assembler->argumentRegister(index));
|
||||
} else {
|
||||
return memory(c, c->assembler->base(),
|
||||
(v->index + c->stackOffset) * BytesPerWord,
|
||||
index + (c->stackOffset * BytesPerWord),
|
||||
NoRegister, 0, 0);
|
||||
}
|
||||
}
|
||||
@ -487,8 +525,12 @@ class ArgumentEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "ArgumentEvent.compile\n");
|
||||
|
||||
if (a->target == 0) a->target = target(c, a);
|
||||
|
||||
a->value->release(c, a);
|
||||
a->target->preserve(c);
|
||||
a->target->preserve(c, a);
|
||||
|
||||
if (not a->target->equals(a->value)) {
|
||||
apply(c, Move, size, a->value, a->target);
|
||||
@ -511,7 +553,12 @@ class ReturnEvent: public Event {
|
||||
public:
|
||||
ReturnEvent(Context* c, unsigned size, MyOperand* a):
|
||||
Event(c), size(size), a(a)
|
||||
{ }
|
||||
{
|
||||
if (a) {
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == a);
|
||||
@ -526,7 +573,11 @@ class ReturnEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "ReturnEvent.compile\n");
|
||||
|
||||
if (a) {
|
||||
if (a->target == 0) a->target = target(c, a);
|
||||
|
||||
a->value->release(c, a);
|
||||
|
||||
if (not a->target->equals(a->value)) {
|
||||
@ -536,6 +587,7 @@ class ReturnEvent: public Event {
|
||||
|
||||
Assembler::Register base(c->assembler->base());
|
||||
Assembler::Register stack(c->assembler->stack());
|
||||
|
||||
c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack);
|
||||
c->assembler->apply(Pop, BytesPerWord, Register, &base);
|
||||
c->assembler->apply(Return);
|
||||
@ -553,15 +605,19 @@ appendReturn(Context* c, unsigned size, MyOperand* value)
|
||||
|
||||
class SyncForCallEvent: public Event {
|
||||
public:
|
||||
SyncForCallEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst):
|
||||
Event(c), size(size), src(src), dst(dst)
|
||||
{ }
|
||||
SyncForCallEvent(Context* c, unsigned size, unsigned index, MyOperand* src,
|
||||
MyOperand* dst):
|
||||
Event(c), size(size), index(index), src(src), dst(dst)
|
||||
{
|
||||
assert(c, src->event == 0);
|
||||
src->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == src);
|
||||
|
||||
return memory(c, c->assembler->base(),
|
||||
(v->index + c->stackOffset) * BytesPerWord,
|
||||
index + (c->stackOffset * BytesPerWord),
|
||||
NoRegister, 0, 0);
|
||||
}
|
||||
|
||||
@ -572,43 +628,68 @@ class SyncForCallEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "SyncForCallEvent.compile\n");
|
||||
|
||||
if (src->target == 0) src->target = target(c, src);
|
||||
|
||||
src->value->release(c, src);
|
||||
|
||||
if (not src->target->equals(src->value)) {
|
||||
if (src->value->type() == Memory and src->target->type() == Memory) {
|
||||
RegisterValue* tmp = freeRegister(c, size);
|
||||
tmp->preserve(c, 0);
|
||||
apply(c, Move, size, src->value, tmp);
|
||||
src->value = tmp;
|
||||
}
|
||||
|
||||
apply(c, Move, size, src->value, src->target);
|
||||
}
|
||||
|
||||
dst->value = src->target;
|
||||
}
|
||||
|
||||
unsigned size;
|
||||
unsigned index;
|
||||
MyOperand* src;
|
||||
MyOperand* dst;
|
||||
};
|
||||
|
||||
void
|
||||
appendSyncForCall(Context* c, unsigned size, MyOperand* src, MyOperand* dst)
|
||||
appendSyncForCall(Context* c, unsigned size, unsigned index, MyOperand* src,
|
||||
MyOperand* dst)
|
||||
{
|
||||
new (c->zone->allocate(sizeof(SyncForCallEvent)))
|
||||
SyncForCallEvent(c, size, src, dst);
|
||||
SyncForCallEvent(c, size, index, src, dst);
|
||||
}
|
||||
|
||||
class SyncForJumpEvent: public Event {
|
||||
public:
|
||||
SyncForJumpEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst):
|
||||
Event(c), size(size), src(src), dst(dst)
|
||||
{ }
|
||||
SyncForJumpEvent(Context* c, unsigned size, unsigned index, MyOperand* src,
|
||||
MyOperand* dst):
|
||||
Event(c), size(size), index(index), src(src), dst(dst)
|
||||
{
|
||||
assert(c, src->event == 0);
|
||||
src->event = this;
|
||||
}
|
||||
|
||||
SyncForJumpEvent(Event* next, unsigned size, MyOperand* src, MyOperand* dst):
|
||||
Event(next), size(size), src(src), dst(dst)
|
||||
{ }
|
||||
SyncForJumpEvent(Context* c, Event* next, unsigned size, unsigned index,
|
||||
MyOperand* src, MyOperand* dst):
|
||||
Event(next), size(size), index(index), src(src), dst(dst)
|
||||
{
|
||||
assert(c, src->event == 0);
|
||||
src->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == src);
|
||||
|
||||
if (BytesPerWord == 4 and v->size == 8) {
|
||||
return register_(c, c->assembler->stackSyncRegister(v->index),
|
||||
c->assembler->stackSyncRegister(v->index + 4));
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
return register_
|
||||
(c, c->assembler->stackSyncRegister(index / BytesPerWord),
|
||||
c->assembler->stackSyncRegister((index / BytesPerWord) + 1));
|
||||
} else {
|
||||
return register_(c, c->assembler->stackSyncRegister(v->index));
|
||||
return register_
|
||||
(c, c->assembler->stackSyncRegister(index / BytesPerWord));
|
||||
}
|
||||
}
|
||||
|
||||
@ -619,6 +700,10 @@ class SyncForJumpEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "SyncForJumpEvent.compile\n");
|
||||
|
||||
if (src->target == 0) src->target = target(c, src);
|
||||
|
||||
src->value->release(c, src);
|
||||
src->target->acquire(c, dst);
|
||||
|
||||
@ -630,15 +715,17 @@ class SyncForJumpEvent: public Event {
|
||||
}
|
||||
|
||||
unsigned size;
|
||||
unsigned index;
|
||||
MyOperand* src;
|
||||
MyOperand* dst;
|
||||
};
|
||||
|
||||
void
|
||||
appendSyncForJump(Context* c, unsigned size, MyOperand* src, MyOperand* dst)
|
||||
appendSyncForJump(Context* c, unsigned size, unsigned index, MyOperand* src,
|
||||
MyOperand* dst)
|
||||
{
|
||||
new (c->zone->allocate(sizeof(SyncForJumpEvent)))
|
||||
SyncForJumpEvent(c, size, src, dst);
|
||||
SyncForJumpEvent(c, size, index, src, dst);
|
||||
}
|
||||
|
||||
class CallEvent: public Event {
|
||||
@ -653,7 +740,10 @@ class CallEvent: public Event {
|
||||
traceHandler(traceHandler),
|
||||
result(result),
|
||||
stackOffset(stackOffset)
|
||||
{ }
|
||||
{
|
||||
assert(c, address->event == 0);
|
||||
address->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == address);
|
||||
@ -672,6 +762,12 @@ class CallEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "CallEvent.compile\n");
|
||||
|
||||
if (indirection and address->target == 0) {
|
||||
address->target = target(c, address);
|
||||
}
|
||||
|
||||
address->value->release(c, address);
|
||||
|
||||
if (result->event) {
|
||||
@ -680,12 +776,14 @@ class CallEvent: public Event {
|
||||
result->value->acquire(c, result);
|
||||
}
|
||||
|
||||
apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()),
|
||||
memory(c, c->assembler->base(), stackOffset * BytesPerWord,
|
||||
NoRegister, 0, 0));
|
||||
if (stackOffset != c->stackOffset) {
|
||||
apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()),
|
||||
memory(c, c->assembler->base(), stackOffset * BytesPerWord,
|
||||
NoRegister, 0, 0));
|
||||
}
|
||||
|
||||
if (indirection) {
|
||||
if (not address->target->equals(address->value)) {
|
||||
if (address->target->equals(address->value)) {
|
||||
apply(c, Move, BytesPerWord, address->value, address->target);
|
||||
}
|
||||
apply(c, Call, BytesPerWord,
|
||||
@ -693,6 +791,12 @@ class CallEvent: public Event {
|
||||
} else {
|
||||
apply(c, Call, BytesPerWord, address->value);
|
||||
}
|
||||
|
||||
if (traceHandler) {
|
||||
traceHandler->handleTrace
|
||||
(new (c->zone->allocate(sizeof(CodePromise)))
|
||||
CodePromise(c, c->assembler->length()));
|
||||
}
|
||||
}
|
||||
|
||||
MyOperand* address;
|
||||
@ -716,7 +820,7 @@ appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags,
|
||||
int
|
||||
freeRegister(Context* c)
|
||||
{
|
||||
for (unsigned i = 0; i < c->assembler->registerCount(); ++i) {
|
||||
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
||||
if ((not c->registers[i].reserved)
|
||||
and c->registers[i].operand == 0)
|
||||
{
|
||||
@ -724,7 +828,7 @@ freeRegister(Context* c)
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < c->assembler->registerCount(); ++i) {
|
||||
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
||||
if (not c->registers[i].reserved) {
|
||||
return i;
|
||||
}
|
||||
@ -748,15 +852,20 @@ class MoveEvent: public Event {
|
||||
MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src,
|
||||
MyOperand* dst):
|
||||
Event(c), type(type), size(size), src(src), dst(dst)
|
||||
{ }
|
||||
{
|
||||
assert(c, src->event == 0);
|
||||
src->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == src);
|
||||
|
||||
if (dst->value) {
|
||||
return dst->value;
|
||||
} else if (dst->event) {
|
||||
return dst->event->target(c, dst);
|
||||
} else {
|
||||
return v->event->target(c, dst);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -767,12 +876,18 @@ class MoveEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "MoveEvent.compile\n");
|
||||
|
||||
if (src->target == 0) src->target = target(c, src);
|
||||
|
||||
if (src->target == 0) {
|
||||
if (dst->value) {
|
||||
src->target = dst->value;
|
||||
} else {
|
||||
src->target = freeRegister(c, size);
|
||||
}
|
||||
src->target = freeRegister(c, size);
|
||||
} else if (src->value->type() == Memory and src->target->type() == Memory)
|
||||
{
|
||||
RegisterValue* tmp = freeRegister(c, size);
|
||||
tmp->preserve(c, 0);
|
||||
apply(c, Move, size, src->value, tmp);
|
||||
src->value = tmp;
|
||||
}
|
||||
|
||||
src->value->release(c, src);
|
||||
@ -797,11 +912,67 @@ appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src,
|
||||
MoveEvent(c, type, size, src, dst);
|
||||
}
|
||||
|
||||
class DupEvent: public Event {
|
||||
public:
|
||||
DupEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst):
|
||||
Event(c), size(size), src(src), dst(dst)
|
||||
{ }
|
||||
|
||||
virtual Value* target(Context* c, MyOperand*) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual void replace(Context* c, MyOperand*, MyOperand*) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "DupEvent.compile\n");
|
||||
|
||||
Value* value = src->value;
|
||||
Value* target = dst->value;
|
||||
|
||||
if (target == 0) {
|
||||
if (dst->event) {
|
||||
target = dst->event->target(c, dst);
|
||||
} else {
|
||||
target = freeRegister(c, size);
|
||||
}
|
||||
} else if (value->type() == Memory and target->type() == Memory) {
|
||||
RegisterValue* tmp = freeRegister(c, size);
|
||||
tmp->preserve(c, 0);
|
||||
apply(c, Move, size, value, tmp);
|
||||
value = tmp;
|
||||
}
|
||||
|
||||
target->acquire(c, dst);
|
||||
|
||||
apply(c, Move, size, value, target);
|
||||
|
||||
dst->value = target;
|
||||
}
|
||||
|
||||
unsigned size;
|
||||
MyOperand* src;
|
||||
MyOperand* dst;
|
||||
};
|
||||
|
||||
void
|
||||
appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst)
|
||||
{
|
||||
new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst);
|
||||
}
|
||||
|
||||
class CompareEvent: public Event {
|
||||
public:
|
||||
CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b):
|
||||
Event(c), size(size), a(a), b(b)
|
||||
{ }
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
assert(c, b->event == 0);
|
||||
b->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == a or v == b);
|
||||
@ -821,6 +992,8 @@ class CompareEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "CompareEvent.compile\n");
|
||||
|
||||
a->value->release(c, a);
|
||||
b->value->release(c, b);
|
||||
|
||||
@ -842,7 +1015,10 @@ class BranchEvent: public Event {
|
||||
public:
|
||||
BranchEvent(Context* c, UnaryOperation type, MyOperand* address):
|
||||
Event(c), type(type), address(address)
|
||||
{ }
|
||||
{
|
||||
assert(c, address->event == 0);
|
||||
address->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == address);
|
||||
@ -857,6 +1033,8 @@ class BranchEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "BranchEvent.compile\n");
|
||||
|
||||
address->value->release(c, address);
|
||||
|
||||
apply(c, type, BytesPerWord, address->value);
|
||||
@ -877,7 +1055,10 @@ class JumpEvent: public Event {
|
||||
JumpEvent(Context* c, MyOperand* address):
|
||||
Event(c),
|
||||
address(address)
|
||||
{ }
|
||||
{
|
||||
assert(c, address->event == 0);
|
||||
address->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == address);
|
||||
@ -891,6 +1072,8 @@ class JumpEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "JumpEvent.compile\n");
|
||||
|
||||
address->value->release(c, address);
|
||||
|
||||
apply(c, Jump, BytesPerWord, address->value);
|
||||
@ -913,12 +1096,17 @@ class CombineEvent: public Event {
|
||||
CombineEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* a,
|
||||
MyOperand* b, MyOperand* result):
|
||||
Event(c), type(type), size(size), a(a), b(b), result(result)
|
||||
{ }
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
assert(c, b->event == 0);
|
||||
b->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
Assembler::Register ar(NoRegister);
|
||||
Assembler::Register br(NoRegister);
|
||||
c->assembler->getTargets(type, v->size, &ar, &br);
|
||||
c->assembler->getTargets(type, size, &ar, &br);
|
||||
|
||||
if (v == a) {
|
||||
if (ar.low == NoRegister) {
|
||||
@ -930,7 +1118,16 @@ class CombineEvent: public Event {
|
||||
assert(c, v == b);
|
||||
|
||||
if (br.low == NoRegister) {
|
||||
return result->event->target(c, result);
|
||||
if (result->event) {
|
||||
Value* v = result->event->target(c, result);
|
||||
if (v->type() == Register) {
|
||||
return v;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return register_(c, br.low, br.high);
|
||||
}
|
||||
@ -949,6 +1146,11 @@ class CombineEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "CombineEvent.compile\n");
|
||||
|
||||
if (a->target == 0) a->target = target(c, a);
|
||||
if (b->target == 0) b->target = target(c, b);
|
||||
|
||||
a->value->release(c, a);
|
||||
b->value->release(c, b);
|
||||
b->value->acquire(c, result);
|
||||
@ -985,13 +1187,16 @@ class TranslateEvent: public Event {
|
||||
TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
|
||||
MyOperand* result):
|
||||
Event(c), type(type), size(size), a(a), result(result)
|
||||
{ }
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == a);
|
||||
|
||||
Assembler::Register r(NoRegister);
|
||||
c->assembler->getTargets(type, v->size, &r);
|
||||
c->assembler->getTargets(type, size, &r);
|
||||
|
||||
if (r.low == NoRegister) {
|
||||
return result->event->target(c, result);
|
||||
@ -1007,9 +1212,16 @@ class TranslateEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
fprintf(stderr, "TranslateEvent.compile\n");
|
||||
|
||||
if (a->target == 0) a->target = target(c, a);
|
||||
|
||||
result->value->acquire(c, result);
|
||||
|
||||
apply(c, type, a->size, a->value);
|
||||
if (a->target and not a->target->equals(a->value)) {
|
||||
apply(c, Move, size, a->value, a->target);
|
||||
}
|
||||
apply(c, type, size, a->value);
|
||||
|
||||
result->value = a->value;
|
||||
}
|
||||
@ -1045,18 +1257,21 @@ AddressValue::toRegister(Context* c)
|
||||
}
|
||||
|
||||
void
|
||||
preserve(Context* c, int reg)
|
||||
preserve(Context* c, int reg, MyOperand* a)
|
||||
{
|
||||
MyOperand* a = c->registers[reg].operand;
|
||||
if (a) {
|
||||
MemoryValue* dst = memory
|
||||
(c, c->assembler->base(), (a->index + c->stackOffset) * BytesPerWord,
|
||||
-1, 0, 0);
|
||||
MyOperand* b = c->registers[reg].operand;
|
||||
if (b and a != b) {
|
||||
fprintf(stderr, "%p preserve %d for %p\n", a, reg, b);
|
||||
|
||||
apply(c, Move, a->size, a->value, dst);
|
||||
abort(c);
|
||||
// MemoryValue* dst = memory
|
||||
// (c, c->assembler->base(), (b->index + c->stackOffset) * BytesPerWord,
|
||||
// -1, 0, 0);
|
||||
|
||||
a->value = dst;
|
||||
c->registers[reg].operand = 0;
|
||||
// apply(c, Move, b->size, b->value, dst);
|
||||
|
||||
// b->value = dst;
|
||||
// c->registers[reg].operand = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1080,52 +1295,59 @@ popState(Context* c)
|
||||
State(c->state->next);
|
||||
}
|
||||
|
||||
Stack*
|
||||
stack(Context* c, MyOperand* operand, unsigned size, unsigned index,
|
||||
Stack* next)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(Stack)))
|
||||
Stack(operand, size, index, next);
|
||||
}
|
||||
|
||||
void
|
||||
push(Context* c, unsigned size, MyOperand* o)
|
||||
{
|
||||
assert(c, o->size == 0 and o->index == 0);
|
||||
assert(c, ceiling(size, BytesPerWord));
|
||||
assert(c, o->event == 0);
|
||||
|
||||
o->next = c->state->stack;
|
||||
o->size = ceiling(size, BytesPerWord);
|
||||
o->index = ceiling(size, BytesPerWord)
|
||||
+ (c->state->stack ? c->state->stack->index : 0);
|
||||
c->state->stack = o;
|
||||
c->state->stack = stack
|
||||
(c, o, ceiling(size, BytesPerWord),
|
||||
ceiling(size, BytesPerWord)
|
||||
+ (c->state->stack ? c->state->stack->index : 0),
|
||||
c->state->stack);
|
||||
}
|
||||
|
||||
MyOperand*
|
||||
pop(Context* c, unsigned size UNUSED)
|
||||
{
|
||||
MyOperand* o = c->state->stack;
|
||||
assert(c, ceiling(size, BytesPerWord) == o->size);
|
||||
Stack* s = c->state->stack;
|
||||
assert(c, ceiling(size, BytesPerWord) == s->size);
|
||||
|
||||
c->state->stack = o->next;
|
||||
return o;
|
||||
c->state->stack = s->next;
|
||||
return s->operand;
|
||||
}
|
||||
|
||||
void
|
||||
syncStack(Context* c, SyncType type)
|
||||
{
|
||||
MyOperand* top = 0;
|
||||
MyOperand* new_ = 0;
|
||||
for (MyOperand* old = c->state->stack; old; old = old->next) {
|
||||
MyOperand* n = operand(c);
|
||||
if (new_) {
|
||||
new_->next = n;
|
||||
Stack* newStack = 0;
|
||||
for (Stack* s = c->state->stack; s; s = s->next) {
|
||||
MyOperand* old = s->operand;
|
||||
MyOperand* new_ = operand(c);
|
||||
Stack* ns = stack(c, new_, s->size, s->index, 0);
|
||||
if (newStack) {
|
||||
newStack->next = ns;
|
||||
} else {
|
||||
top = n;
|
||||
newStack = c->state->stack = ns;
|
||||
}
|
||||
new_ = n;
|
||||
new_->size = old->size;
|
||||
new_->index = old->index;
|
||||
|
||||
if (type == SyncForCall) {
|
||||
appendSyncForCall(c, old->size * BytesPerWord, old, new_);
|
||||
appendSyncForCall
|
||||
(c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_);
|
||||
} else {
|
||||
appendSyncForJump(c, old->size * BytesPerWord, old, new_);
|
||||
appendSyncForJump
|
||||
(c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_);
|
||||
}
|
||||
}
|
||||
|
||||
c->state->stack = top;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1137,13 +1359,9 @@ updateJunctions(Context* c)
|
||||
if (i->predecessor >= 0) {
|
||||
LogicalInstruction* p = c->logicalCode + i->predecessor;
|
||||
|
||||
MyOperand* new_ = 0;
|
||||
for (MyOperand* old = i->firstEvent->stack; old; old = old->next) {
|
||||
MyOperand* n = operand(c);
|
||||
if (new_) new_->next = n;
|
||||
new_ = n;
|
||||
new_->size = old->size;
|
||||
new_->index = old->index;
|
||||
for (Stack* s = c->state->stack; s; s = s->next) {
|
||||
MyOperand* old = s->operand;
|
||||
MyOperand* new_ = operand(c);
|
||||
|
||||
if (old->event) {
|
||||
old->event->replace(c, old, new_);
|
||||
@ -1151,7 +1369,9 @@ updateJunctions(Context* c)
|
||||
|
||||
p->lastEvent = p->lastEvent->next = new
|
||||
(c->zone->allocate(sizeof(SyncForJumpEvent)))
|
||||
SyncForJumpEvent(p->lastEvent->next, old->size, old, new_);
|
||||
SyncForJumpEvent
|
||||
(c, p->lastEvent->next, s->size * BytesPerWord,
|
||||
s->index * BytesPerWord, old, new_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1170,7 +1390,6 @@ compile(Context* c)
|
||||
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
||||
fprintf(stderr, "compile ip %d\n", i);
|
||||
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
|
||||
fprintf(stderr, "compile ip %d event\n", i);
|
||||
e->compile(c);
|
||||
|
||||
if (e == c->logicalCode[i].lastEvent) break;
|
||||
@ -1307,17 +1526,21 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual void popped(unsigned count) {
|
||||
for (int i = count; i >= 0;) {
|
||||
MyOperand* o = c.state->stack;
|
||||
c.state->stack = o->next;
|
||||
count -= o->size;
|
||||
for (unsigned i = count; i > 0;) {
|
||||
Stack* s = c.state->stack;
|
||||
c.state->stack = s->next;
|
||||
i -= s->size;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Operand* peek(unsigned index) {
|
||||
MyOperand* a = c.state->stack;
|
||||
for (; index; --index) a = a->next;
|
||||
return a;
|
||||
virtual Operand* peek(unsigned size, unsigned index) {
|
||||
Stack* s = c.state->stack;
|
||||
for (unsigned i = index; i > 0;) {
|
||||
s = s->next;
|
||||
i -= s->size;
|
||||
}
|
||||
assert(&c, s->size == ceiling(size, BytesPerWord));
|
||||
return s->operand;
|
||||
}
|
||||
|
||||
virtual Operand* call(Operand* address,
|
||||
@ -1347,9 +1570,10 @@ class MyCompiler: public Compiler {
|
||||
|
||||
syncStack(&c, SyncForCall);
|
||||
|
||||
unsigned stackOffset = c.stackOffset + c.state->stack->index
|
||||
+ (footprint > c.assembler->argumentRegisterCount() ?
|
||||
footprint - c.assembler->argumentRegisterCount() : 0);
|
||||
unsigned stackOffset = c.stackOffset
|
||||
+ (c.state->stack ? c.state->stack->index
|
||||
+ (footprint > c.assembler->argumentRegisterCount() ?
|
||||
footprint - c.assembler->argumentRegisterCount() : 0) : 0);
|
||||
|
||||
MyOperand* result = operand(&c);
|
||||
appendCall(&c, static_cast<MyOperand*>(address), indirection, flags,
|
||||
@ -1384,6 +1608,12 @@ class MyCompiler: public Compiler {
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual Operand* dup(unsigned size, Operand* src) {
|
||||
MyOperand* dst = operand(&c);
|
||||
appendDup(&c, size, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual void cmp(unsigned size, Operand* a, Operand* b) {
|
||||
appendCompare(&c, size, static_cast<MyOperand*>(a),
|
||||
static_cast<MyOperand*>(b));
|
||||
@ -1530,7 +1760,7 @@ class MyCompiler: public Compiler {
|
||||
|
||||
int i = 0;
|
||||
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
||||
*reinterpret_cast<intptr_t*>(dst + c.assembler->length() + (i++))
|
||||
*reinterpret_cast<intptr_t*>(dst + pad(c.assembler->length()) + (i++))
|
||||
= n->promise->value();
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class Compiler {
|
||||
virtual Operand* pop(unsigned size) = 0;
|
||||
virtual void pushed(unsigned count) = 0;
|
||||
virtual void popped(unsigned count) = 0;
|
||||
virtual Operand* peek(unsigned index) = 0;
|
||||
virtual Operand* peek(unsigned size, unsigned index) = 0;
|
||||
|
||||
virtual Operand* call(Operand* address,
|
||||
void* indirection,
|
||||
@ -64,6 +64,7 @@ class Compiler {
|
||||
virtual Operand* load(unsigned size, Operand* src) = 0;
|
||||
virtual Operand* loadz(unsigned size, Operand* src) = 0;
|
||||
virtual Operand* load4To8(Operand* src) = 0;
|
||||
virtual Operand* dup(unsigned size, Operand* src) = 0;
|
||||
virtual void cmp(unsigned size, Operand* a, Operand* b) = 0;
|
||||
virtual void jl(Operand* address) = 0;
|
||||
virtual void jg(Operand* address) = 0;
|
||||
|
74
src/x86.cpp
74
src/x86.cpp
@ -121,7 +121,7 @@ class Task {
|
||||
|
||||
class OffsetTask: public Task {
|
||||
public:
|
||||
OffsetTask(Task* next, Promise* promise, int instructionOffset,
|
||||
OffsetTask(Task* next, Promise* promise, unsigned instructionOffset,
|
||||
unsigned instructionSize):
|
||||
Task(next),
|
||||
promise(promise),
|
||||
@ -141,7 +141,7 @@ class OffsetTask: public Task {
|
||||
}
|
||||
|
||||
Promise* promise;
|
||||
int instructionOffset;
|
||||
unsigned instructionOffset;
|
||||
unsigned instructionSize;
|
||||
};
|
||||
|
||||
@ -153,6 +153,30 @@ appendOffsetTask(Context* c, Promise* promise, int instructionOffset,
|
||||
(c->tasks, promise, instructionOffset, instructionSize);
|
||||
}
|
||||
|
||||
class ImmediateTask: public Task {
|
||||
public:
|
||||
ImmediateTask(Task* next, Promise* promise, unsigned offset):
|
||||
Task(next),
|
||||
promise(promise),
|
||||
offset(offset)
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c) {
|
||||
intptr_t v = promise->value();
|
||||
memcpy(c->result + offset, &v, BytesPerWord);
|
||||
}
|
||||
|
||||
Promise* promise;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
void
|
||||
appendImmediateTask(Context* c, Promise* promise, unsigned offset)
|
||||
{
|
||||
c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask
|
||||
(c->tasks, promise, offset);
|
||||
}
|
||||
|
||||
void
|
||||
encode(Context* c, uint8_t* instruction, unsigned length, int a, int b,
|
||||
int32_t displacement, int index, unsigned scale)
|
||||
@ -307,6 +331,18 @@ popR(Context* c, unsigned size, Assembler::Register* a)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
leaRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
||||
{
|
||||
if (BytesPerWord == 8 and size == 4) {
|
||||
encode(c, 0x8d, a->low, b, false);
|
||||
} else {
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
encode(c, 0x8d, a->low, b, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
@ -315,7 +351,12 @@ moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
|
||||
rex(c);
|
||||
c->code.append(0xb8 | b->low);
|
||||
c->code.appendAddress(a->value->value());
|
||||
if (a->value->resolved()) {
|
||||
c->code.appendAddress(a->value->value());
|
||||
} else {
|
||||
appendImmediateTask(c, a->value, c->code.length());
|
||||
c->code.appendAddress(static_cast<uintptr_t>(0));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -393,6 +434,19 @@ moveMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
moveAR(Context* c, unsigned size, Assembler::Address* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
Assembler::Constant constant(a->address);
|
||||
Assembler::Memory memory(b->low, 0, -1, 0);
|
||||
|
||||
moveCR(c, size, &constant, b);
|
||||
moveMR(c, size, &memory, b);
|
||||
}
|
||||
|
||||
void
|
||||
move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
||||
{
|
||||
@ -412,6 +466,15 @@ addRR(Context* c, unsigned size, Assembler::Register* a,
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
}
|
||||
|
||||
void
|
||||
addRM(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Memory* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
encode(c, 0x01, a->low, b, true);
|
||||
}
|
||||
|
||||
void
|
||||
populateTables()
|
||||
{
|
||||
@ -422,13 +485,16 @@ populateTables()
|
||||
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
||||
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
|
||||
|
||||
BinaryOperations[INDEX2(LoadAddress, Register, Memory)] = CAST2(leaRM);
|
||||
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
|
||||
BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM);
|
||||
BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM);
|
||||
BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR);
|
||||
BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR);
|
||||
BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR);
|
||||
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
|
||||
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
||||
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
|
||||
}
|
||||
|
||||
class MyAssembler: public Assembler {
|
||||
@ -442,7 +508,7 @@ class MyAssembler: public Assembler {
|
||||
}
|
||||
|
||||
virtual unsigned registerCount() {
|
||||
return BytesPerWord == 4 ? 8 : 16;
|
||||
return 8;//BytesPerWord == 4 ? 8 : 16;
|
||||
}
|
||||
|
||||
virtual int base() {
|
||||
|
@ -1,67 +1,60 @@
|
||||
public class Misc {
|
||||
// private static int alpha;
|
||||
// private static int beta;
|
||||
// private static byte byte1, byte2, byte3;
|
||||
// private int gamma;
|
||||
private static int alpha;
|
||||
private static int beta;
|
||||
private static byte byte1, byte2, byte3;
|
||||
private int gamma;
|
||||
|
||||
// private String foo(String s) {
|
||||
// return s;
|
||||
// }
|
||||
private String foo(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// public String bar(String s) {
|
||||
// return s;
|
||||
// }
|
||||
public String bar(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// private static String baz(String s) {
|
||||
// return s;
|
||||
// }
|
||||
private static String baz(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// private static void expect(boolean v) {
|
||||
// if (! v) throw new RuntimeException();
|
||||
// }
|
||||
private static void expect(boolean v) {
|
||||
if (! v) throw new RuntimeException();
|
||||
}
|
||||
|
||||
// private synchronized byte sync() {
|
||||
// byte[] array = new byte[123];
|
||||
// return array[42];
|
||||
// }
|
||||
private synchronized byte sync() {
|
||||
byte[] array = new byte[123];
|
||||
return array[42];
|
||||
}
|
||||
|
||||
// private static synchronized byte syncStatic(boolean throw_) {
|
||||
// byte[] array = new byte[123];
|
||||
// if (throw_) {
|
||||
// throw new RuntimeException();
|
||||
// } else {
|
||||
// return array[42];
|
||||
// }
|
||||
// }
|
||||
private static synchronized byte syncStatic(boolean throw_) {
|
||||
byte[] array = new byte[123];
|
||||
if (throw_) {
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
return array[42];
|
||||
}
|
||||
}
|
||||
|
||||
// public static void putInt(int val, byte[] dst, int offset) {
|
||||
// System.out.println("put " + val);
|
||||
// dst[offset] = (byte)((val >> 24) & 0xff);
|
||||
// dst[offset+1] = (byte)((val >> 16) & 0xff);
|
||||
// dst[offset+2] = (byte)((val >> 8) & 0xff);
|
||||
// dst[offset+3] = (byte)((val ) & 0xff);
|
||||
// }
|
||||
public static void putInt(int val, byte[] dst, int offset) {
|
||||
System.out.println("put " + val);
|
||||
dst[offset] = (byte)((val >> 24) & 0xff);
|
||||
dst[offset+1] = (byte)((val >> 16) & 0xff);
|
||||
dst[offset+2] = (byte)((val >> 8) & 0xff);
|
||||
dst[offset+3] = (byte)((val ) & 0xff);
|
||||
}
|
||||
|
||||
// public static void putLong(long val, byte[] dst, int offset) {
|
||||
// putInt((int)(val >> 32), dst, offset);
|
||||
// putInt((int)val, dst, offset + 4);
|
||||
// }
|
||||
public static void putLong(long val, byte[] dst, int offset) {
|
||||
putInt((int)(val >> 32), dst, offset);
|
||||
putInt((int)val, dst, offset + 4);
|
||||
}
|
||||
|
||||
// public String toString() {
|
||||
// return super.toString();
|
||||
// }
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int a = 2;
|
||||
int b = 2;
|
||||
int c = a + b;
|
||||
|
||||
// byte2 = 0;
|
||||
// expect(byte2 == 0);
|
||||
|
||||
// Misc m = new Misc();
|
||||
// m.toString();
|
||||
|
||||
// expect(Long.valueOf(231L) == 231L);
|
||||
|
||||
// long x = 231;
|
||||
@ -97,6 +90,9 @@ public class Misc {
|
||||
// int b = 2;
|
||||
// int c = a + b;
|
||||
|
||||
Misc m = new Misc();
|
||||
// m.toString();
|
||||
|
||||
// String s = "hello";
|
||||
// m.foo(s);
|
||||
// m.bar(s);
|
||||
|
Loading…
Reference in New Issue
Block a user