mirror of
https://github.com/corda/corda.git
synced 2025-03-12 15:34:58 +00:00
bugfixes and new instructions
This commit is contained in:
parent
420a054fd8
commit
684b402e82
@ -2589,7 +2589,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
|||||||
Compiler::Operand* result = c->call
|
Compiler::Operand* result = c->call
|
||||||
(c->memory
|
(c->memory
|
||||||
(c->and_
|
(c->and_
|
||||||
(4, c->constant(PointerMask), c->memory
|
(BytesPerWord, c->constant(PointerMask), c->memory
|
||||||
(instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1),
|
(instance, 0, 0, 1, frame->trace(0, false))), offset, 0, 1),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
251
src/compiler.cpp
251
src/compiler.cpp
@ -26,6 +26,8 @@ class Event;
|
|||||||
class PushEvent;
|
class PushEvent;
|
||||||
class Stack;
|
class Stack;
|
||||||
|
|
||||||
|
void NO_RETURN abort(Context* c);
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
virtual ~Value() { }
|
virtual ~Value() { }
|
||||||
@ -38,26 +40,25 @@ class Value {
|
|||||||
virtual void acquire(Context*, Stack*, MyOperand*) { }
|
virtual void acquire(Context*, Stack*, MyOperand*) { }
|
||||||
virtual void release(Context*, MyOperand*) { }
|
virtual void release(Context*, MyOperand*) { }
|
||||||
|
|
||||||
virtual RegisterValue* toRegister(Context*) = 0;
|
virtual int registerValue(Context* c) { abort(c); }
|
||||||
|
virtual int64_t constantValue(Context* c) { abort(c); }
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context*,
|
virtual void asAssemblerOperand(Context*,
|
||||||
OperandType* type,
|
OperandType* type,
|
||||||
Assembler::Operand** operand) = 0;
|
Assembler::Operand** operand) = 0;
|
||||||
|
|
||||||
virtual int64_t constantValue(Context*) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyOperand: public Compiler::Operand {
|
class MyOperand: public Compiler::Operand {
|
||||||
public:
|
public:
|
||||||
MyOperand(Value* value):
|
MyOperand(Value* value):
|
||||||
event(0), value(value), target(0), push(0), pushedValue(0)
|
event(0), value(value), target(0), push(0), pushed(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Event* event;
|
Event* event;
|
||||||
Value* value;
|
Value* value;
|
||||||
Value* target;
|
Value* target;
|
||||||
PushEvent* push;
|
PushEvent* push;
|
||||||
StackValue* pushedValue;
|
bool pushed;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Stack {
|
class Stack {
|
||||||
@ -283,8 +284,6 @@ class ConstantValue: public Value {
|
|||||||
|
|
||||||
virtual OperandType type(Context*) { return Constant; }
|
virtual OperandType type(Context*) { return Constant; }
|
||||||
|
|
||||||
virtual RegisterValue* toRegister(Context* c);
|
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context*,
|
virtual void asAssemblerOperand(Context*,
|
||||||
OperandType* type,
|
OperandType* type,
|
||||||
Assembler::Operand** operand)
|
Assembler::Operand** operand)
|
||||||
@ -325,8 +324,6 @@ class AddressValue: public Value {
|
|||||||
|
|
||||||
virtual OperandType type(Context*) { return Address; }
|
virtual OperandType type(Context*) { return Address; }
|
||||||
|
|
||||||
virtual RegisterValue* toRegister(Context* c);
|
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context*,
|
virtual void asAssemblerOperand(Context*,
|
||||||
OperandType* type,
|
OperandType* type,
|
||||||
Assembler::Operand** operand)
|
Assembler::Operand** operand)
|
||||||
@ -335,10 +332,6 @@ class AddressValue: public Value {
|
|||||||
*operand = &address;
|
*operand = &address;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int64_t constantValue(Context* c) {
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembler::Address address;
|
Assembler::Address address;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -389,8 +382,8 @@ class RegisterValue: public Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual RegisterValue* toRegister(Context*) {
|
virtual int registerValue(Context*) {
|
||||||
return this;
|
return register_.low;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context*,
|
virtual void asAssemblerOperand(Context*,
|
||||||
@ -401,10 +394,6 @@ class RegisterValue: public Value {
|
|||||||
*operand = ®ister_;
|
*operand = ®ister_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int64_t constantValue(Context* c) {
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembler::Register register_;
|
Assembler::Register register_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -433,12 +422,6 @@ class MemoryValue: public Value {
|
|||||||
and static_cast<MemoryValue*>(o)->value.scale == value.scale);
|
and static_cast<MemoryValue*>(o)->value.scale == value.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual RegisterValue* toRegister(Context* c) {
|
|
||||||
RegisterValue* v = freeRegister(c, BytesPerWord, false);
|
|
||||||
apply(c, Move, BytesPerWord, this, v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int base(Context*) {
|
virtual int base(Context*) {
|
||||||
return value.base;
|
return value.base;
|
||||||
}
|
}
|
||||||
@ -457,27 +440,9 @@ class MemoryValue: public Value {
|
|||||||
*operand = &value;
|
*operand = &value;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int64_t constantValue(Context* c) {
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembler::Memory value;
|
Assembler::Memory value;
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryValue*
|
|
||||||
memory(Context* c, int base, int offset, int index, unsigned scale,
|
|
||||||
TraceHandler* traceHandler)
|
|
||||||
{
|
|
||||||
return new (c->zone->allocate(sizeof(MemoryValue)))
|
|
||||||
MemoryValue(base, offset, index, scale, traceHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
toRegister(Context* c, MyOperand* a)
|
|
||||||
{
|
|
||||||
return a->value->toRegister(c)->register_.low;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AbstractMemoryValue: public MemoryValue {
|
class AbstractMemoryValue: public MemoryValue {
|
||||||
public:
|
public:
|
||||||
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
|
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
|
||||||
@ -501,11 +466,11 @@ class AbstractMemoryValue: public MemoryValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual int base(Context* c) {
|
virtual int base(Context* c) {
|
||||||
return ::toRegister(c, base_);
|
return base_->value->registerValue(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int index(Context* c) {
|
virtual int index(Context* c) {
|
||||||
return index_ ? ::toRegister(c, index_) : NoRegister;
|
return index_ ? index_->value->registerValue(c) : NoRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
MyOperand* base_;
|
MyOperand* base_;
|
||||||
@ -522,35 +487,32 @@ memory(Context* c, MyOperand* base, int offset, MyOperand* index,
|
|||||||
|
|
||||||
class StackValue: public Value {
|
class StackValue: public Value {
|
||||||
public:
|
public:
|
||||||
StackValue(Stack* stack): stack(stack) { }
|
StackValue(Context* c, Stack* stack):
|
||||||
|
stack(stack),
|
||||||
|
value
|
||||||
|
(c->assembler->base(),
|
||||||
|
- (c->stackOffset + stack->index + 1) * BytesPerWord,
|
||||||
|
NoRegister, 0, 0)
|
||||||
|
{ }
|
||||||
|
|
||||||
virtual OperandType type(Context* c) { abort(c); }
|
virtual OperandType type(Context*) { return Memory; }
|
||||||
|
|
||||||
virtual RegisterValue* toRegister(Context* c) {
|
virtual void asAssemblerOperand(Context*,
|
||||||
return MemoryValue
|
OperandType* type,
|
||||||
(c->assembler->base(), (c->stackOffset + stack->index) * BytesPerWord,
|
Assembler::Operand** operand)
|
||||||
NoRegister, 0, 0)
|
|
||||||
.toRegister(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void asAssemblerOperand(Context* c,
|
|
||||||
OperandType*,
|
|
||||||
Assembler::Operand**)
|
|
||||||
{
|
{
|
||||||
abort(c);
|
*type = Memory;
|
||||||
}
|
*operand = &value;
|
||||||
|
|
||||||
virtual int64_t constantValue(Context* c) {
|
|
||||||
abort(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack* stack;
|
Stack* stack;
|
||||||
|
Assembler::Memory value;
|
||||||
};
|
};
|
||||||
|
|
||||||
StackValue*
|
StackValue*
|
||||||
stackValue(Context* c, Stack* stack)
|
stackValue(Context* c, Stack* stack)
|
||||||
{
|
{
|
||||||
return new (c->zone->allocate(sizeof(StackValue))) StackValue(stack);
|
return new (c->zone->allocate(sizeof(StackValue))) StackValue(c, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Event {
|
class Event {
|
||||||
@ -691,8 +653,8 @@ class ReturnEvent: public Event {
|
|||||||
|
|
||||||
if (not a->target->equals(c, a->value)) {
|
if (not a->target->equals(c, a->value)) {
|
||||||
apply(c, Move, size, a->value, a->target);
|
apply(c, Move, size, a->value, a->target);
|
||||||
a->value->release(c, a);
|
|
||||||
}
|
}
|
||||||
|
a->value->release(c, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assembler::Register base(c->assembler->base());
|
Assembler::Register base(c->assembler->base());
|
||||||
@ -843,9 +805,19 @@ syncStack(Context* c, Stack* start, unsigned count)
|
|||||||
|
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
Stack* s = segment[i];
|
Stack* s = segment[i];
|
||||||
apply(c, Push, s->size * BytesPerWord, s->operand->value);
|
if (s->operand->value) {
|
||||||
s->operand->value->release(c, s->operand);
|
apply(c, Push, s->size * BytesPerWord, s->operand->value);
|
||||||
s->operand->pushedValue = stackValue(c, s);
|
s->operand->value->release(c, s->operand);
|
||||||
|
s->operand->pushed = true;
|
||||||
|
s->operand->value = stackValue(c, s);
|
||||||
|
} else {
|
||||||
|
Assembler::Register stack(c->assembler->stack());
|
||||||
|
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
|
||||||
|
c->assembler->apply
|
||||||
|
(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
|
||||||
|
s->operand->pushed = true;
|
||||||
|
s->operand->value = stackValue(c, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,7 +825,7 @@ void
|
|||||||
syncStack(Context* c, Stack* start)
|
syncStack(Context* c, Stack* start)
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
for (Stack* s = start; s and s->operand->pushedValue == 0; s = s->next) {
|
for (Stack* s = start; s and (not s->operand->pushed); s = s->next) {
|
||||||
++ count;
|
++ count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -901,8 +873,8 @@ appendPush(Context* c)
|
|||||||
|
|
||||||
class PopEvent: public Event {
|
class PopEvent: public Event {
|
||||||
public:
|
public:
|
||||||
PopEvent(Context* c):
|
PopEvent(Context* c, unsigned count, bool ignore):
|
||||||
Event(c)
|
Event(c), count(count), ignore(ignore)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual Value* target(Context* c, MyOperand*) {
|
virtual Value* target(Context* c, MyOperand*) {
|
||||||
@ -916,30 +888,53 @@ class PopEvent: public Event {
|
|||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
fprintf(stderr, "PopEvent.compile\n");
|
fprintf(stderr, "PopEvent.compile\n");
|
||||||
|
|
||||||
MyOperand* dst = stack->operand;
|
Stack* s = stack;
|
||||||
if (dst->event and dst->pushedValue) {
|
unsigned ignored = 0;
|
||||||
Value* target = 0;
|
for (unsigned i = count; i;) {
|
||||||
|
MyOperand* dst = s->operand;
|
||||||
|
if (dst->pushed) {
|
||||||
|
if (dst->event and (not ignore)) {
|
||||||
|
assert(c, ignored == 0);
|
||||||
|
|
||||||
if (dst->event and dst->event->operandSize(c) == BytesPerWord) {
|
Value* target = 0;
|
||||||
target = dst->event->target(c, dst);
|
|
||||||
}
|
if (dst->event->operandSize(c) == BytesPerWord) {
|
||||||
if (target == 0) {
|
target = dst->event->target(c, dst);
|
||||||
target = freeRegister(c, BytesPerWord * stack->size, false);
|
}
|
||||||
|
if (target == 0) {
|
||||||
|
target = freeRegister(c, BytesPerWord * s->size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(c, Pop, BytesPerWord * s->size, target);
|
||||||
|
|
||||||
|
target->acquire(c, 0, dst);
|
||||||
|
|
||||||
|
dst->value = target;
|
||||||
|
} else {
|
||||||
|
ignored += s->size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(c, Pop, BytesPerWord * stack->size, target);
|
i -= s->size;
|
||||||
|
s = s->next;
|
||||||
|
}
|
||||||
|
|
||||||
target->acquire(c, 0, dst);
|
if (ignored) {
|
||||||
|
Assembler::Register stack(c->assembler->stack());
|
||||||
dst->value = target;
|
Assembler::Constant offset(resolved(c, ignored * BytesPerWord));
|
||||||
|
c->assembler->apply
|
||||||
|
(Add, BytesPerWord, Constant, &offset, Register, &stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned count;
|
||||||
|
bool ignore;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
appendPop(Context* c)
|
appendPop(Context* c, unsigned count, bool ignore)
|
||||||
{
|
{
|
||||||
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c);
|
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1221,7 +1216,7 @@ class CombineEvent: public Event {
|
|||||||
if (br.low == NoRegister) {
|
if (br.low == NoRegister) {
|
||||||
if (result->event) {
|
if (result->event) {
|
||||||
Value* v = result->event->target(c, result);
|
Value* v = result->event->target(c, result);
|
||||||
if (v->type(c) == Register) {
|
if (v and v->type(c) == Register) {
|
||||||
return v;
|
return v;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@ -1338,20 +1333,52 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
|
|||||||
TranslateEvent(c, type, size, a, result);
|
TranslateEvent(c, type, size, a, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterValue*
|
class MemoryEvent: public Event {
|
||||||
ConstantValue::toRegister(Context* c)
|
public:
|
||||||
{
|
MemoryEvent(Context* c, MyOperand* base, MyOperand* index,
|
||||||
RegisterValue* v = freeRegister(c, BytesPerWord, false);
|
MyOperand* result):
|
||||||
apply(c, Move, BytesPerWord, this, v);
|
Event(c), base(base), index(index), result(result)
|
||||||
return v;
|
{
|
||||||
}
|
setEvent(c, base, this);
|
||||||
|
if (index) setEvent(c, index, this);
|
||||||
|
}
|
||||||
|
|
||||||
RegisterValue*
|
virtual unsigned operandSize(Context*) {
|
||||||
AddressValue::toRegister(Context* c)
|
return BytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
||||||
|
assert(c, v == base or v == index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void compile(Context* c) {
|
||||||
|
fprintf(stderr, "MemoryEvent.compile\n");
|
||||||
|
|
||||||
|
if (base->value->type(c) != Register) {
|
||||||
|
base->target = freeRegister(c, BytesPerWord, true);
|
||||||
|
apply(c, Move, BytesPerWord, base->value, base->target);
|
||||||
|
base->value->release(c, base);
|
||||||
|
base->value = base->target;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index and index->value->type(c) != Register) {
|
||||||
|
index->target = freeRegister(c, BytesPerWord, true);
|
||||||
|
apply(c, Move, BytesPerWord, index->value, index->target);
|
||||||
|
index->value->release(c, index);
|
||||||
|
index->value = index->target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyOperand* base;
|
||||||
|
MyOperand* index;
|
||||||
|
MyOperand* result;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendMemory(Context* c, MyOperand* a, MyOperand* b, MyOperand* result)
|
||||||
{
|
{
|
||||||
RegisterValue* v = freeRegister(c, BytesPerWord, false);
|
new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, a, b, result);
|
||||||
apply(c, Move, BytesPerWord, this, v);
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1363,7 +1390,7 @@ preserve(Context* c, Stack* stack, int reg, MyOperand* a)
|
|||||||
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
Stack* start = 0;
|
Stack* start = 0;
|
||||||
for (Stack* s = stack; s and s->operand->pushedValue == 0; s = s->next) {
|
for (Stack* s = stack; s and (not s->operand->pushed); s = s->next) {
|
||||||
if (s->operand == b) {
|
if (s->operand == b) {
|
||||||
start = s;
|
start = s;
|
||||||
}
|
}
|
||||||
@ -1429,7 +1456,7 @@ push(Context* c, unsigned size, MyOperand* o)
|
|||||||
assert(c, ceiling(size, BytesPerWord));
|
assert(c, ceiling(size, BytesPerWord));
|
||||||
|
|
||||||
c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack);
|
c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack);
|
||||||
|
|
||||||
appendPush(c);
|
appendPush(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1439,7 +1466,7 @@ pop(Context* c, unsigned size UNUSED)
|
|||||||
Stack* s = c->state->stack;
|
Stack* s = c->state->stack;
|
||||||
assert(c, ceiling(size, BytesPerWord) == s->size);
|
assert(c, ceiling(size, BytesPerWord) == s->size);
|
||||||
|
|
||||||
appendPop(c);
|
appendPop(c, s->size, false);
|
||||||
|
|
||||||
c->state->stack = s->next;
|
c->state->stack = s->next;
|
||||||
return s->operand;
|
return s->operand;
|
||||||
@ -1499,11 +1526,11 @@ compile(Context* c)
|
|||||||
i, count(e->stack));
|
i, count(e->stack));
|
||||||
e->compile(c);
|
e->compile(c);
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e == li->lastEvent) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1614,10 +1641,15 @@ class MyCompiler: public Compiler {
|
|||||||
unsigned scale = 1,
|
unsigned scale = 1,
|
||||||
TraceHandler* traceHandler = 0)
|
TraceHandler* traceHandler = 0)
|
||||||
{
|
{
|
||||||
return operand
|
MyOperand* result = operand
|
||||||
(&c, ::memory
|
(&c, ::memory
|
||||||
(&c, static_cast<MyOperand*>(base), displacement,
|
(&c, static_cast<MyOperand*>(base), displacement,
|
||||||
static_cast<MyOperand*>(index), scale, traceHandler));
|
static_cast<MyOperand*>(index), scale, traceHandler));
|
||||||
|
|
||||||
|
appendMemory(&c, static_cast<MyOperand*>(base),
|
||||||
|
static_cast<MyOperand*>(index), result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* stack() {
|
virtual Operand* stack() {
|
||||||
@ -1652,6 +1684,8 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void mark(Operand* label) {
|
virtual void mark(Operand* label) {
|
||||||
|
markStack(&c);
|
||||||
|
|
||||||
static_cast<ConstantValue*>(static_cast<MyOperand*>(label)->value)->value
|
static_cast<ConstantValue*>(static_cast<MyOperand*>(label)->value)->value
|
||||||
= machineIp();
|
= machineIp();
|
||||||
}
|
}
|
||||||
@ -1665,11 +1699,18 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void pushed(unsigned count) {
|
virtual void pushed(unsigned count) {
|
||||||
for (unsigned i = 0; i < count; ++i) ::push(&c, BytesPerWord, operand(&c));
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
|
MyOperand* a = operand(&c);
|
||||||
|
::push(&c, BytesPerWord, a);
|
||||||
|
a->value = stackValue(&c, c.state->stack);
|
||||||
|
a->pushed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popped(unsigned count) {
|
virtual void popped(unsigned count) {
|
||||||
for (unsigned i = count; i > 0;) {
|
appendPop(&c, count, true);
|
||||||
|
|
||||||
|
for (unsigned i = count; i;) {
|
||||||
Stack* s = c.state->stack;
|
Stack* s = c.state->stack;
|
||||||
c.state->stack = s->next;
|
c.state->stack = s->next;
|
||||||
i -= s->size;
|
i -= s->size;
|
||||||
|
111
src/x86.cpp
111
src/x86.cpp
@ -426,6 +426,20 @@ pushC(Context* c, unsigned size, Assembler::Constant* a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveAR(Context*, unsigned, Assembler::Address*, Assembler::Register* b);
|
||||||
|
|
||||||
|
void
|
||||||
|
pushA(Context* c, unsigned size, Assembler::Address* a)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
Assembler::Register tmp(c->client->acquireTemporary());
|
||||||
|
moveAR(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)
|
||||||
{
|
{
|
||||||
@ -533,8 +547,8 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
Assembler::Register ah(a->low);
|
Assembler::Register ah(a->high);
|
||||||
Assembler::Register bh(b->low);
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
moveRR(c, 4, a, b);
|
moveRR(c, 4, a, b);
|
||||||
moveRR(c, 4, &ah, &bh);
|
moveRR(c, 4, &ah, &bh);
|
||||||
@ -679,6 +693,35 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
|||||||
encode(c, 0x63, b->low, a, true);
|
encode(c, 0x63, b->low, a, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveZMR(Context* c, unsigned size, Assembler::Memory* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 2:
|
||||||
|
encode2(c, 0x0fb7, b->low, a, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: abort(c); // todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveZRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 2:
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0xb7);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: abort(c); // todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
@ -725,6 +768,17 @@ subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x29);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
@ -807,6 +861,30 @@ compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compareRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
compareRR(c, 4, &ah, &bh);
|
||||||
|
|
||||||
|
// if the high order bits are equal, we compare the low order
|
||||||
|
// bits; otherwise, we jump past that comparison
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x85); // jne
|
||||||
|
c->code.append4(2);
|
||||||
|
|
||||||
|
compareRR(c, 4, a, b);
|
||||||
|
} else {
|
||||||
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0x39);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||||
Assembler::Memory* b)
|
Assembler::Memory* b)
|
||||||
@ -824,6 +902,27 @@ compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compareRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||||
|
Assembler::Memory* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
encode(c, 0x39, a->low, b, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compareMM(Context* c, unsigned size UNUSED, 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);
|
||||||
|
compareRM(c, size, &tmp, b);
|
||||||
|
c->client->releaseTemporary(tmp.low);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
populateTables()
|
populateTables()
|
||||||
{
|
{
|
||||||
@ -848,6 +947,7 @@ populateTables()
|
|||||||
= CAST1(jumpIfLessOrEqualC);
|
= CAST1(jumpIfLessOrEqualC);
|
||||||
|
|
||||||
UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC);
|
UnaryOperations[INDEX1(Push, Constant)] = CAST1(pushC);
|
||||||
|
UnaryOperations[INDEX1(Push, Address)] = CAST1(pushA);
|
||||||
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
||||||
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
|
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
|
||||||
|
|
||||||
@ -868,6 +968,9 @@ populateTables()
|
|||||||
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);
|
||||||
|
|
||||||
|
BinaryOperations[INDEX2(MoveZ, Memory, Register)] = CAST2(moveZMR);
|
||||||
|
BinaryOperations[INDEX2(MoveZ, Register, Register)] = CAST2(moveZRR);
|
||||||
|
|
||||||
BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR);
|
BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR);
|
||||||
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
||||||
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
|
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
|
||||||
@ -876,9 +979,13 @@ populateTables()
|
|||||||
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);
|
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);
|
||||||
|
|
||||||
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
||||||
|
BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR);
|
||||||
|
|
||||||
BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR);
|
BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR);
|
||||||
|
BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR);
|
||||||
|
BinaryOperations[INDEX2(Compare, Register, Memory)] = CAST2(compareRM);
|
||||||
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
|
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
|
||||||
|
BinaryOperations[INDEX2(Compare, Memory, Memory)] = CAST2(compareMM);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyAssembler: public Assembler {
|
class MyAssembler: public Assembler {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user