mirror of
https://github.com/corda/corda.git
synced 2025-01-08 14:03:06 +00:00
use stack instead of registers to save data across jumps and branches; bugfixes
This commit is contained in:
parent
571bffde09
commit
d5137a7cdf
@ -751,7 +751,7 @@ class Frame {
|
|||||||
|
|
||||||
void pushLongQuiet(Compiler::Operand* o) {
|
void pushLongQuiet(Compiler::Operand* o) {
|
||||||
if (BytesPerWord == 8) {
|
if (BytesPerWord == 8) {
|
||||||
c->pushed(1);
|
c->push(8);
|
||||||
}
|
}
|
||||||
c->push(8, o);
|
c->push(8, o);
|
||||||
}
|
}
|
||||||
@ -774,7 +774,7 @@ class Frame {
|
|||||||
Compiler::Operand* popLongQuiet() {
|
Compiler::Operand* popLongQuiet() {
|
||||||
Compiler::Operand* r = c->pop(8);
|
Compiler::Operand* r = c->pop(8);
|
||||||
if (BytesPerWord == 8) {
|
if (BytesPerWord == 8) {
|
||||||
c->popped(1);
|
c->pop(8);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1364,16 +1364,28 @@ longToFloat(int64_t a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object FORCE_ALIGN
|
object FORCE_ALIGN
|
||||||
makeBlankObjectArray(Thread* t, object class_, int32_t length)
|
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
|
||||||
{
|
{
|
||||||
return makeObjectArray(t, class_, length, true);
|
if (length >= 0) {
|
||||||
|
return makeObjectArray(t, class_, length, true);
|
||||||
|
} else {
|
||||||
|
object message = makeString(t, "%d", length);
|
||||||
|
t->exception = makeNegativeArraySizeException(t, message);
|
||||||
|
unwind(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object FORCE_ALIGN
|
object FORCE_ALIGN
|
||||||
makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool),
|
makeBlankArray(MyThread* t, object (*constructor)(Thread*, uintptr_t, bool),
|
||||||
int32_t length)
|
int32_t length)
|
||||||
{
|
{
|
||||||
return constructor(t, length, true);
|
if (length >= 0) {
|
||||||
|
return constructor(t, length, true);
|
||||||
|
} else {
|
||||||
|
object message = makeString(t, "%d", length);
|
||||||
|
t->exception = makeNegativeArraySizeException(t, message);
|
||||||
|
unwind(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t
|
uintptr_t
|
||||||
@ -1478,14 +1490,6 @@ throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index)
|
|||||||
unwind(t);
|
unwind(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NO_RETURN FORCE_ALIGN
|
|
||||||
throwNegativeArraySize(MyThread* t, int32_t length)
|
|
||||||
{
|
|
||||||
object message = makeString(t, "%d", length);
|
|
||||||
t->exception = makeArrayIndexOutOfBoundsException(t, message);
|
|
||||||
unwind(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NO_RETURN FORCE_ALIGN
|
void NO_RETURN FORCE_ALIGN
|
||||||
throw_(MyThread* t, object o)
|
throw_(MyThread* t, object o)
|
||||||
{
|
{
|
||||||
@ -2008,30 +2012,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(t->exception)) return;
|
if (UNLIKELY(t->exception)) return;
|
||||||
|
|
||||||
Compiler::Operand* length = c->peek(4, 0);
|
Compiler::Operand* length = frame->popInt();
|
||||||
|
|
||||||
if (c->isConstant(length)) {
|
|
||||||
expect(t, c->constantValue(length) >= 0);
|
|
||||||
} else{
|
|
||||||
Compiler::Operand* nonnegative = c->label();
|
|
||||||
|
|
||||||
c->cmp(4, c->constant(0), length);
|
|
||||||
c->jge(nonnegative);
|
|
||||||
|
|
||||||
length = c->peek(4, 0);
|
|
||||||
|
|
||||||
c->call
|
|
||||||
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
|
|
||||||
context->indirection,
|
|
||||||
Compiler::NoReturn,
|
|
||||||
frame->trace(0, false),
|
|
||||||
0,
|
|
||||||
2, c->thread(), length);
|
|
||||||
|
|
||||||
c->mark(nonnegative);
|
|
||||||
}
|
|
||||||
|
|
||||||
length = frame->popInt();
|
|
||||||
|
|
||||||
frame->pushObject
|
frame->pushObject
|
||||||
(c->call
|
(c->call
|
||||||
@ -3197,30 +3178,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
case newarray: {
|
case newarray: {
|
||||||
uint8_t type = codeBody(t, code, ip++);
|
uint8_t type = codeBody(t, code, ip++);
|
||||||
|
|
||||||
Compiler::Operand* length = c->peek(4, 0);
|
Compiler::Operand* length = frame->popInt();
|
||||||
|
|
||||||
if (c->isConstant(length)) {
|
|
||||||
expect(t, c->constantValue(length) >= 0);
|
|
||||||
} else{
|
|
||||||
Compiler::Operand* nonnegative = c->label();
|
|
||||||
|
|
||||||
c->cmp(4, c->constant(0), length);
|
|
||||||
c->jge(nonnegative);
|
|
||||||
|
|
||||||
length = c->peek(4, 0);
|
|
||||||
|
|
||||||
c->call
|
|
||||||
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
|
|
||||||
context->indirection,
|
|
||||||
Compiler::NoReturn,
|
|
||||||
frame->trace(0, false),
|
|
||||||
0,
|
|
||||||
2, c->thread(), length);
|
|
||||||
|
|
||||||
c->mark(nonnegative);
|
|
||||||
}
|
|
||||||
|
|
||||||
length = frame->popInt();
|
|
||||||
|
|
||||||
object (*constructor)(Thread*, uintptr_t, bool);
|
object (*constructor)(Thread*, uintptr_t, bool);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -3870,11 +3828,11 @@ finish(MyThread* t, Context* context)
|
|||||||
strcmp
|
strcmp
|
||||||
(reinterpret_cast<const char*>
|
(reinterpret_cast<const char*>
|
||||||
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
||||||
"Enums") == 0 and
|
"java/lang/StringBuilder") == 0 and
|
||||||
strcmp
|
strcmp
|
||||||
(reinterpret_cast<const char*>
|
(reinterpret_cast<const char*>
|
||||||
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
||||||
"main") == 0)
|
"<init>") == 0)
|
||||||
{
|
{
|
||||||
asm("int3");
|
asm("int3");
|
||||||
}
|
}
|
||||||
|
199
src/compiler.cpp
199
src/compiler.cpp
@ -17,8 +17,8 @@ namespace {
|
|||||||
|
|
||||||
const bool DebugAppend = true;
|
const bool DebugAppend = true;
|
||||||
const bool DebugCompile = true;
|
const bool DebugCompile = true;
|
||||||
const bool DebugStack = false;
|
const bool DebugStack = true;
|
||||||
const bool DebugRegisters = false;
|
const bool DebugRegisters = true;
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
class Value;
|
class Value;
|
||||||
@ -61,7 +61,7 @@ class Stack {
|
|||||||
public:
|
public:
|
||||||
Stack(Value* value, unsigned size, unsigned index, Stack* next):
|
Stack(Value* value, unsigned size, unsigned index, Stack* next):
|
||||||
value(value), size(size), index(index), next(next), pushEvent(0),
|
value(value), size(size), index(index), next(next), pushEvent(0),
|
||||||
pushSite(0), syncSite(0), pushed(false)
|
pushSite(0), pushed(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Value* value;
|
Value* value;
|
||||||
@ -70,7 +70,6 @@ class Stack {
|
|||||||
Stack* next;
|
Stack* next;
|
||||||
PushEvent* pushEvent;
|
PushEvent* pushEvent;
|
||||||
Site* pushSite;
|
Site* pushSite;
|
||||||
Site* syncSite;
|
|
||||||
bool pushed;
|
bool pushed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -141,8 +140,8 @@ class Read {
|
|||||||
|
|
||||||
class Value: public Compiler::Operand {
|
class Value: public Compiler::Operand {
|
||||||
public:
|
public:
|
||||||
Value(Site* site):
|
Value(Site* site, Site* target):
|
||||||
reads(0), lastRead(0), sites(site), source(0), target(site)
|
reads(0), lastRead(0), sites(site), source(0), target(target)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Read* reads;
|
Read* reads;
|
||||||
@ -330,8 +329,6 @@ class Event {
|
|||||||
|
|
||||||
virtual ~Event() { }
|
virtual ~Event() { }
|
||||||
|
|
||||||
virtual void prepare(Context*) { }
|
|
||||||
|
|
||||||
virtual void compile(Context* c) = 0;
|
virtual void compile(Context* c) = 0;
|
||||||
|
|
||||||
virtual bool isBranch() { return false; };
|
virtual bool isBranch() { return false; };
|
||||||
@ -773,6 +770,14 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
|
|||||||
return site;
|
return site;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Site*
|
||||||
|
pushSite(Context* c, unsigned index)
|
||||||
|
{
|
||||||
|
return memorySite
|
||||||
|
(c, c->assembler->base(),
|
||||||
|
- (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pushNow(Context* c, Stack* start, unsigned count)
|
pushNow(Context* c, Stack* start, unsigned count)
|
||||||
{
|
{
|
||||||
@ -787,11 +792,12 @@ pushNow(Context* c, Stack* start, unsigned count)
|
|||||||
assert(c, not s->pushed);
|
assert(c, not s->pushed);
|
||||||
|
|
||||||
if (s->value and s->value->sites) {
|
if (s->value and s->value->sites) {
|
||||||
apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites));
|
Site* source = pick(c, s->value->sites);
|
||||||
s->pushSite = memorySite
|
|
||||||
(c, c->assembler->base(),
|
s->pushSite = pushSite(c, s->index);
|
||||||
- (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1);
|
|
||||||
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
|
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
|
||||||
|
|
||||||
|
apply(c, Push, s->size * BytesPerWord, source);
|
||||||
} else {
|
} else {
|
||||||
Assembler::Register stack(c->assembler->stack());
|
Assembler::Register stack(c->assembler->stack());
|
||||||
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
|
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
|
||||||
@ -959,7 +965,7 @@ class PushEvent: public Event {
|
|||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
if (DebugCompile) {
|
if (DebugCompile) {
|
||||||
fprintf(stderr, "PushEvent.compile\n");
|
fprintf(stderr, "PushEvent.compile active: %d\n", active);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
@ -1161,17 +1167,17 @@ class MoveEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Site* target;
|
Site* target;
|
||||||
|
unsigned cost;
|
||||||
if (type == Move
|
if (type == Move
|
||||||
and size >= BytesPerWord
|
and size >= BytesPerWord
|
||||||
and dst->reads
|
and dst->reads
|
||||||
and next == dst->reads->event)
|
and next == dst->reads->event)
|
||||||
{
|
{
|
||||||
target = src->source;
|
target = src->source;
|
||||||
|
cost = 0;
|
||||||
} else {
|
} else {
|
||||||
target = targetOrRegister(c, size, dst, this);
|
target = targetOrRegister(c, size, dst, this);
|
||||||
if (src->source->copyCost(c, target)) {
|
cost = src->source->copyCost(c, target);
|
||||||
apply(c, type, size, src->source, target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nextRead(c, src);
|
nextRead(c, src);
|
||||||
@ -1181,6 +1187,10 @@ class MoveEvent: public Event {
|
|||||||
} else {
|
} else {
|
||||||
removeSite(c, dst, target);
|
removeSite(c, dst, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cost) {
|
||||||
|
apply(c, type, size, src->source, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryOperation type;
|
BinaryOperation type;
|
||||||
@ -1390,16 +1400,6 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
|
|||||||
MemoryEvent(c, base, displacement, index, scale, result);
|
MemoryEvent(c, base, displacement, index, scale, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Site*
|
|
||||||
stackSyncSite(Context* c, unsigned index, unsigned size)
|
|
||||||
{
|
|
||||||
assert(c, index + size <= c->freeRegisterCount);
|
|
||||||
|
|
||||||
return registerSite
|
|
||||||
(c, c->freeRegisters[index],
|
|
||||||
size == 2 ? c->freeRegisters[index + 1] : NoRegister);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack*
|
Stack*
|
||||||
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
|
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
|
||||||
{
|
{
|
||||||
@ -1408,9 +1408,9 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value*
|
Value*
|
||||||
value(Context* c, Site* site = 0)
|
value(Context* c, Site* site = 0, Site* target = 0)
|
||||||
{
|
{
|
||||||
return new (c->zone->allocate(sizeof(Value))) Value(site);
|
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1419,8 +1419,9 @@ resetStack(Context* c)
|
|||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
Stack* p = 0;
|
Stack* p = 0;
|
||||||
for (Stack* s = c->state->stack; s; s = s->next) {
|
for (Stack* s = c->state->stack; s; s = s->next) {
|
||||||
Stack* n = stack
|
Stack* n = stack(c, value(c), s->size, s->index, 0);
|
||||||
(c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0);
|
n->value->sites = n->pushSite = pushSite(c, s->index);
|
||||||
|
n->pushed = true;
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
p->next = n;
|
p->next = n;
|
||||||
@ -1453,9 +1454,9 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore)
|
|||||||
s, s->value, target);
|
s, s->value, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(c, Pop, BytesPerWord * s->size, target);
|
|
||||||
|
|
||||||
addSite(c, stack, s->size * BytesPerWord, s->value, target);
|
addSite(c, stack, s->size * BytesPerWord, s->value, target);
|
||||||
|
|
||||||
|
apply(c, Pop, BytesPerWord * s->size, target);
|
||||||
} else {
|
} else {
|
||||||
if (DebugStack) {
|
if (DebugStack) {
|
||||||
fprintf(stderr, "ignore %p value: %p\n", s, s->value);
|
fprintf(stderr, "ignore %p value: %p\n", s, s->value);
|
||||||
@ -1485,31 +1486,21 @@ class StackSyncEvent: public Event {
|
|||||||
StackSyncEvent(Context* c):
|
StackSyncEvent(Context* c):
|
||||||
Event(c)
|
Event(c)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
|
||||||
for (Stack* s = stack; s; s = s->next) {
|
for (Stack* s = stack; s; s = s->next) {
|
||||||
s->syncSite = stackSyncSite(c, i, s->size);
|
if (s->pushEvent) s->pushEvent->active = true;
|
||||||
addRead(c, s->value, s->size * BytesPerWord, s->syncSite);
|
addRead(c, s->value, s->size * BytesPerWord, 0);
|
||||||
i += s->size;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StackSyncEvent(Context* c, unsigned sequence, Stack* stack):
|
StackSyncEvent(Context* c, unsigned sequence, Stack* stack):
|
||||||
Event(c, sequence, stack)
|
Event(c, sequence, stack)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
|
||||||
for (Stack* s = stack; s; s = s->next) {
|
for (Stack* s = stack; s; s = s->next) {
|
||||||
s->syncSite = stackSyncSite(c, i, s->size);
|
if (s->pushEvent) s->pushEvent->active = true;
|
||||||
insertRead(c, this, sequence, s->value, s->size * BytesPerWord,
|
insertRead(c, this, sequence, s->value, s->size * BytesPerWord, 0);
|
||||||
s->syncSite);
|
|
||||||
if (s->pushEvent) s->pushEvent->active = false;
|
|
||||||
i += s->size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void prepare(Context* c) {
|
|
||||||
popNow(c, this, stack, 0xFFFFFFFF, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
if (DebugCompile) {
|
if (DebugCompile) {
|
||||||
fprintf(stderr, "StackSyncEvent.compile\n");
|
fprintf(stderr, "StackSyncEvent.compile\n");
|
||||||
@ -1520,7 +1511,9 @@ class StackSyncEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Stack* s = stack; s; s = s->next) {
|
for (Stack* s = stack; s; s = s->next) {
|
||||||
addSite(c, 0, s->size * BytesPerWord, s->value, s->syncSite);
|
if (s->pushSite) {
|
||||||
|
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Read* r = reads; r; r = r->eventNext) {
|
for (Read* r = reads; r; r = r->eventNext) {
|
||||||
@ -1642,23 +1635,23 @@ appendPop(Context* c, unsigned count, bool ignore)
|
|||||||
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
|
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// void
|
||||||
swapRegisters(Context* c, int* ap, int* bp)
|
// swapRegisters(Context* c, int* ap, int* bp)
|
||||||
{
|
// {
|
||||||
Assembler::Register a(*ap);
|
// Assembler::Register a(*ap);
|
||||||
Assembler::Register b(*bp);
|
// Assembler::Register b(*bp);
|
||||||
|
|
||||||
c->assembler->apply
|
// c->assembler->apply
|
||||||
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
||||||
c->assembler->apply
|
// c->assembler->apply
|
||||||
(Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
|
// (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
|
||||||
c->assembler->apply
|
// c->assembler->apply
|
||||||
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
||||||
|
|
||||||
int t = *ap;
|
// int t = *ap;
|
||||||
*ap = *bp;
|
// *ap = *bp;
|
||||||
*bp = t;
|
// *bp = t;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Site*
|
Site*
|
||||||
readSource(Context* c, Stack* stack, Read* r, Event* e)
|
readSource(Context* c, Stack* stack, Read* r, Event* e)
|
||||||
@ -1674,29 +1667,30 @@ readSource(Context* c, Stack* stack, Read* r, Event* e)
|
|||||||
apply(c, Move, r->size, site, target);
|
apply(c, Move, r->size, site, target);
|
||||||
return target;
|
return target;
|
||||||
} else {
|
} else {
|
||||||
// this is a filthy hack, but I think the core idea is right:
|
abort(c);
|
||||||
|
// // this is a filthy hack, but I think the core idea is right:
|
||||||
|
|
||||||
assert(c, target->type(c) == RegisterOperand);
|
// assert(c, target->type(c) == RegisterOperand);
|
||||||
|
|
||||||
RegisterSite* ts = static_cast<RegisterSite*>(target);
|
// RegisterSite* ts = static_cast<RegisterSite*>(target);
|
||||||
|
|
||||||
for (Site* s = r->value->sites; s; s = s->next) {
|
// for (Site* s = r->value->sites; s; s = s->next) {
|
||||||
if (s->type(c) == RegisterOperand) {
|
// if (s->type(c) == RegisterOperand) {
|
||||||
RegisterSite* rs = static_cast<RegisterSite*>(s);
|
// RegisterSite* rs = static_cast<RegisterSite*>(s);
|
||||||
|
|
||||||
RegisterSite* os = static_cast<RegisterSite*>
|
// RegisterSite* os = static_cast<RegisterSite*>
|
||||||
(c->registers[ts->register_.low].site);
|
// (c->registers[ts->register_.low].site);
|
||||||
|
|
||||||
assert(c, os->register_.low == ts->register_.low);
|
// assert(c, os->register_.low == ts->register_.low);
|
||||||
assert(c, os->register_.high == NoRegister);
|
// assert(c, os->register_.high == NoRegister);
|
||||||
assert(c, ts->register_.high == NoRegister);
|
// assert(c, ts->register_.high == NoRegister);
|
||||||
assert(c, rs->register_.high == NoRegister);
|
// assert(c, rs->register_.high == NoRegister);
|
||||||
|
|
||||||
swapRegisters(c, &(os->register_.low), &(rs->register_.low));
|
// swapRegisters(c, &(os->register_.low), &(rs->register_.low));
|
||||||
|
|
||||||
return rs;
|
// return rs;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
abort(c);
|
abort(c);
|
||||||
@ -1736,7 +1730,7 @@ compile(Context* c)
|
|||||||
|
|
||||||
for (Event* e = li->firstEvent; e; e = e->next) {
|
for (Event* e = li->firstEvent; e; e = e->next) {
|
||||||
if (e->stackReset) {
|
if (e->stackReset) {
|
||||||
// fprintf(stderr, "stack reset\n");
|
fprintf(stderr, "stack reset\n");
|
||||||
for (Stack* s = e->stack; s; s = s->next) {
|
for (Stack* s = e->stack; s; s = s->next) {
|
||||||
if (s->value->sites) {
|
if (s->value->sites) {
|
||||||
assert(c, s->value->sites->next == 0);
|
assert(c, s->value->sites->next == 0);
|
||||||
@ -1748,8 +1742,6 @@ compile(Context* c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e->prepare(c);
|
|
||||||
|
|
||||||
for (Read* r = e->reads; r; r = r->eventNext) {
|
for (Read* r = e->reads; r; r = r->eventNext) {
|
||||||
r->value->source = readSource(c, e->stack, r, e);
|
r->value->source = readSource(c, e->stack, r, e);
|
||||||
}
|
}
|
||||||
@ -1852,14 +1844,12 @@ used(Context* c, int r)
|
|||||||
return v and findSite(c, v, c->registers[r].site);
|
return v and findSite(c, v, c->registers[r].site);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool
|
bool
|
||||||
// usedExclusively(Context* c, int r)
|
usedExclusively(Context* c, int r)
|
||||||
// {
|
{
|
||||||
// Value* v = c->registers[r].value;
|
Value* v = c->registers[r].value;
|
||||||
// return used(c, r)
|
return used(c, r) and v->sites->next == 0;
|
||||||
// and v->pushCount == 0
|
}
|
||||||
// and v->sites->next == 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
int
|
int
|
||||||
freeRegisterExcept(Context* c, int except, bool allowAcquired)
|
freeRegisterExcept(Context* c, int except, bool allowAcquired)
|
||||||
@ -1873,14 +1863,14 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
|
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
|
||||||
// if (i != except
|
if (i != except
|
||||||
// and c->registers[i].refCount == 0
|
and c->registers[i].refCount == 0
|
||||||
// and (not usedExclusively(c, i)))
|
and (not usedExclusively(c, i)))
|
||||||
// {
|
{
|
||||||
// return i;
|
return i;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (allowAcquired) {
|
if (allowAcquired) {
|
||||||
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
|
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
|
||||||
@ -2048,15 +2038,18 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* stack() {
|
virtual Operand* stack() {
|
||||||
return value(&c, registerSite(&c, c.assembler->stack()));
|
Site* s = registerSite(&c, c.assembler->stack());
|
||||||
|
return value(&c, s, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* base() {
|
virtual Operand* base() {
|
||||||
return value(&c, registerSite(&c, c.assembler->base()));
|
Site* s = registerSite(&c, c.assembler->base());
|
||||||
|
return value(&c, s, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* thread() {
|
virtual Operand* thread() {
|
||||||
return value(&c, registerSite(&c, c.assembler->thread()));
|
Site* s = registerSite(&c, c.assembler->thread());
|
||||||
|
return value(&c, s, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isConstant(Operand* a) {
|
virtual bool isConstant(Operand* a) {
|
||||||
@ -2098,6 +2091,10 @@ class MyCompiler: public Compiler {
|
|||||||
abort(&c);
|
abort(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void push(unsigned size) {
|
||||||
|
::push(&c, size, value(&c));
|
||||||
|
}
|
||||||
|
|
||||||
virtual void push(unsigned size, Operand* value) {
|
virtual void push(unsigned size, Operand* value) {
|
||||||
::push(&c, size, static_cast<Value*>(value));
|
::push(&c, size, static_cast<Value*>(value));
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ class Compiler {
|
|||||||
virtual Operand* label() = 0;
|
virtual Operand* label() = 0;
|
||||||
virtual void mark(Operand* label) = 0;
|
virtual void mark(Operand* label) = 0;
|
||||||
|
|
||||||
|
virtual void push(unsigned size) = 0;
|
||||||
virtual void push(unsigned size, Operand* value) = 0;
|
virtual void push(unsigned size, Operand* value) = 0;
|
||||||
virtual Operand* pop(unsigned size) = 0;
|
virtual Operand* pop(unsigned size) = 0;
|
||||||
virtual void pushed(unsigned count) = 0;
|
virtual void pushed(unsigned count) = 0;
|
||||||
|
85
src/x86.cpp
85
src/x86.cpp
@ -35,6 +35,18 @@ enum {
|
|||||||
r15 = 15,
|
r15 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int64_t FORCE_ALIGN
|
||||||
|
divideLong(int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
return a / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t FORCE_ALIGN
|
||||||
|
moduloLong(int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
return a % b;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
isInt8(intptr_t v)
|
isInt8(intptr_t v)
|
||||||
{
|
{
|
||||||
@ -523,6 +535,17 @@ popM(Context* c, unsigned size, Assembler::Memory* a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
negateR(Context* c, unsigned size, Assembler::Register* a)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xd8 | a->low);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
|
leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
|
||||||
{
|
{
|
||||||
@ -575,13 +598,19 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
} else {
|
} else {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
c->code.append(0x0f);
|
||||||
|
}
|
||||||
c->code.append(0xbe);
|
c->code.append(0xbe);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
c->code.append(0x0f);
|
||||||
|
}
|
||||||
c->code.append(0xbf);
|
c->code.append(0xbf);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
@ -863,6 +892,54 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
|||||||
encode(c, 0x01, a->low, b, true);
|
encode(c, 0x01, a->low, b, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
divideRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
Assembler::Register axdx(c->client->acquireTemporary(rax),
|
||||||
|
c->client->acquireTemporary(rdx));
|
||||||
|
|
||||||
|
pushR(c, size, a);
|
||||||
|
pushR(c, size, b);
|
||||||
|
|
||||||
|
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(divideLong));
|
||||||
|
Assembler::Constant address(&addressPromise);
|
||||||
|
callC(c, BytesPerWord, &address);
|
||||||
|
|
||||||
|
ResolvedPromise offsetPromise(16);
|
||||||
|
Assembler::Constant offset(&offsetPromise);
|
||||||
|
Assembler::Register stack(rsp);
|
||||||
|
addCR(c, BytesPerWord, &offset, &stack);
|
||||||
|
|
||||||
|
moveRR(c, size, &axdx, b);
|
||||||
|
|
||||||
|
c->client->releaseTemporary(axdx.low);
|
||||||
|
c->client->releaseTemporary(axdx.high);
|
||||||
|
} else {
|
||||||
|
Assembler::Register ax(rax);
|
||||||
|
Assembler::Register dx(c->client->acquireTemporary(rdx));
|
||||||
|
|
||||||
|
if (b->low != rax) {
|
||||||
|
c->client->acquireTemporary(ax.low);
|
||||||
|
moveRR(c, BytesPerWord, b, &ax);
|
||||||
|
}
|
||||||
|
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x99);
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xf8 | a->low);
|
||||||
|
|
||||||
|
if (b->low != rax) {
|
||||||
|
moveRR(c, BytesPerWord, &ax, b);
|
||||||
|
c->client->releaseTemporary(ax.low);
|
||||||
|
}
|
||||||
|
|
||||||
|
c->client->releaseTemporary(dx.low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
@ -1065,6 +1142,8 @@ populateTables()
|
|||||||
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
|
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
|
||||||
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
|
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
|
||||||
|
|
||||||
|
UnaryOperations[INDEX1(Negate, Register)] = CAST1(negateR);
|
||||||
|
|
||||||
BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR);
|
BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR);
|
||||||
|
|
||||||
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
|
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
|
||||||
@ -1086,6 +1165,8 @@ populateTables()
|
|||||||
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);
|
||||||
|
|
||||||
|
BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR);
|
||||||
|
|
||||||
BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR);
|
BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR);
|
||||||
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);
|
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user