mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +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) {
|
||||
if (BytesPerWord == 8) {
|
||||
c->pushed(1);
|
||||
c->push(8);
|
||||
}
|
||||
c->push(8, o);
|
||||
}
|
||||
@ -774,7 +774,7 @@ class Frame {
|
||||
Compiler::Operand* popLongQuiet() {
|
||||
Compiler::Operand* r = c->pop(8);
|
||||
if (BytesPerWord == 8) {
|
||||
c->popped(1);
|
||||
c->pop(8);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -1364,16 +1364,28 @@ longToFloat(int64_t a)
|
||||
}
|
||||
|
||||
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
|
||||
makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool),
|
||||
makeBlankArray(MyThread* t, object (*constructor)(Thread*, uintptr_t, bool),
|
||||
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
|
||||
@ -1478,14 +1490,6 @@ throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index)
|
||||
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
|
||||
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);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Compiler::Operand* length = c->peek(4, 0);
|
||||
|
||||
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();
|
||||
Compiler::Operand* length = frame->popInt();
|
||||
|
||||
frame->pushObject
|
||||
(c->call
|
||||
@ -3197,30 +3178,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case newarray: {
|
||||
uint8_t type = codeBody(t, code, ip++);
|
||||
|
||||
Compiler::Operand* length = c->peek(4, 0);
|
||||
|
||||
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();
|
||||
Compiler::Operand* length = frame->popInt();
|
||||
|
||||
object (*constructor)(Thread*, uintptr_t, bool);
|
||||
switch (type) {
|
||||
@ -3870,11 +3828,11 @@ finish(MyThread* t, Context* context)
|
||||
strcmp
|
||||
(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
||||
"Enums") == 0 and
|
||||
"java/lang/StringBuilder") == 0 and
|
||||
strcmp
|
||||
(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
||||
"main") == 0)
|
||||
"<init>") == 0)
|
||||
{
|
||||
asm("int3");
|
||||
}
|
||||
|
199
src/compiler.cpp
199
src/compiler.cpp
@ -17,8 +17,8 @@ namespace {
|
||||
|
||||
const bool DebugAppend = true;
|
||||
const bool DebugCompile = true;
|
||||
const bool DebugStack = false;
|
||||
const bool DebugRegisters = false;
|
||||
const bool DebugStack = true;
|
||||
const bool DebugRegisters = true;
|
||||
|
||||
class Context;
|
||||
class Value;
|
||||
@ -61,7 +61,7 @@ class Stack {
|
||||
public:
|
||||
Stack(Value* value, unsigned size, unsigned index, Stack* next):
|
||||
value(value), size(size), index(index), next(next), pushEvent(0),
|
||||
pushSite(0), syncSite(0), pushed(false)
|
||||
pushSite(0), pushed(false)
|
||||
{ }
|
||||
|
||||
Value* value;
|
||||
@ -70,7 +70,6 @@ class Stack {
|
||||
Stack* next;
|
||||
PushEvent* pushEvent;
|
||||
Site* pushSite;
|
||||
Site* syncSite;
|
||||
bool pushed;
|
||||
};
|
||||
|
||||
@ -141,8 +140,8 @@ class Read {
|
||||
|
||||
class Value: public Compiler::Operand {
|
||||
public:
|
||||
Value(Site* site):
|
||||
reads(0), lastRead(0), sites(site), source(0), target(site)
|
||||
Value(Site* site, Site* target):
|
||||
reads(0), lastRead(0), sites(site), source(0), target(target)
|
||||
{ }
|
||||
|
||||
Read* reads;
|
||||
@ -330,8 +329,6 @@ class Event {
|
||||
|
||||
virtual ~Event() { }
|
||||
|
||||
virtual void prepare(Context*) { }
|
||||
|
||||
virtual void compile(Context* c) = 0;
|
||||
|
||||
virtual bool isBranch() { return false; };
|
||||
@ -773,6 +770,14 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
|
||||
return site;
|
||||
}
|
||||
|
||||
Site*
|
||||
pushSite(Context* c, unsigned index)
|
||||
{
|
||||
return memorySite
|
||||
(c, c->assembler->base(),
|
||||
- (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1);
|
||||
}
|
||||
|
||||
void
|
||||
pushNow(Context* c, Stack* start, unsigned count)
|
||||
{
|
||||
@ -787,11 +792,12 @@ pushNow(Context* c, Stack* start, unsigned count)
|
||||
assert(c, not s->pushed);
|
||||
|
||||
if (s->value and s->value->sites) {
|
||||
apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites));
|
||||
s->pushSite = memorySite
|
||||
(c, c->assembler->base(),
|
||||
- (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1);
|
||||
Site* source = pick(c, s->value->sites);
|
||||
|
||||
s->pushSite = pushSite(c, s->index);
|
||||
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
|
||||
|
||||
apply(c, Push, s->size * BytesPerWord, source);
|
||||
} else {
|
||||
Assembler::Register stack(c->assembler->stack());
|
||||
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
|
||||
@ -959,7 +965,7 @@ class PushEvent: public Event {
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
if (DebugCompile) {
|
||||
fprintf(stderr, "PushEvent.compile\n");
|
||||
fprintf(stderr, "PushEvent.compile active: %d\n", active);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
@ -1161,17 +1167,17 @@ class MoveEvent: public Event {
|
||||
}
|
||||
|
||||
Site* target;
|
||||
unsigned cost;
|
||||
if (type == Move
|
||||
and size >= BytesPerWord
|
||||
and dst->reads
|
||||
and next == dst->reads->event)
|
||||
{
|
||||
target = src->source;
|
||||
cost = 0;
|
||||
} else {
|
||||
target = targetOrRegister(c, size, dst, this);
|
||||
if (src->source->copyCost(c, target)) {
|
||||
apply(c, type, size, src->source, target);
|
||||
}
|
||||
cost = src->source->copyCost(c, target);
|
||||
}
|
||||
|
||||
nextRead(c, src);
|
||||
@ -1181,6 +1187,10 @@ class MoveEvent: public Event {
|
||||
} else {
|
||||
removeSite(c, dst, target);
|
||||
}
|
||||
|
||||
if (cost) {
|
||||
apply(c, type, size, src->source, target);
|
||||
}
|
||||
}
|
||||
|
||||
BinaryOperation type;
|
||||
@ -1390,16 +1400,6 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
|
||||
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(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(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
|
||||
@ -1419,8 +1419,9 @@ resetStack(Context* c)
|
||||
unsigned i = 0;
|
||||
Stack* p = 0;
|
||||
for (Stack* s = c->state->stack; s; s = s->next) {
|
||||
Stack* n = stack
|
||||
(c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0);
|
||||
Stack* n = stack(c, value(c), s->size, s->index, 0);
|
||||
n->value->sites = n->pushSite = pushSite(c, s->index);
|
||||
n->pushed = true;
|
||||
|
||||
if (p) {
|
||||
p->next = n;
|
||||
@ -1453,9 +1454,9 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore)
|
||||
s, s->value, target);
|
||||
}
|
||||
|
||||
apply(c, Pop, BytesPerWord * s->size, target);
|
||||
|
||||
addSite(c, stack, s->size * BytesPerWord, s->value, target);
|
||||
|
||||
apply(c, Pop, BytesPerWord * s->size, target);
|
||||
} else {
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "ignore %p value: %p\n", s, s->value);
|
||||
@ -1485,31 +1486,21 @@ class StackSyncEvent: public Event {
|
||||
StackSyncEvent(Context* c):
|
||||
Event(c)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (Stack* s = stack; s; s = s->next) {
|
||||
s->syncSite = stackSyncSite(c, i, s->size);
|
||||
addRead(c, s->value, s->size * BytesPerWord, s->syncSite);
|
||||
i += s->size;
|
||||
}
|
||||
if (s->pushEvent) s->pushEvent->active = true;
|
||||
addRead(c, s->value, s->size * BytesPerWord, 0);
|
||||
}
|
||||
}
|
||||
|
||||
StackSyncEvent(Context* c, unsigned sequence, Stack* stack):
|
||||
Event(c, sequence, stack)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (Stack* s = stack; s; s = s->next) {
|
||||
s->syncSite = stackSyncSite(c, i, s->size);
|
||||
insertRead(c, this, sequence, s->value, s->size * BytesPerWord,
|
||||
s->syncSite);
|
||||
if (s->pushEvent) s->pushEvent->active = false;
|
||||
i += s->size;
|
||||
if (s->pushEvent) s->pushEvent->active = true;
|
||||
insertRead(c, this, sequence, s->value, s->size * BytesPerWord, 0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void prepare(Context* c) {
|
||||
popNow(c, this, stack, 0xFFFFFFFF, false);
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
if (DebugCompile) {
|
||||
fprintf(stderr, "StackSyncEvent.compile\n");
|
||||
@ -1520,7 +1511,9 @@ class StackSyncEvent: public Event {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -1642,23 +1635,23 @@ appendPop(Context* c, unsigned count, bool ignore)
|
||||
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
|
||||
}
|
||||
|
||||
void
|
||||
swapRegisters(Context* c, int* ap, int* bp)
|
||||
{
|
||||
Assembler::Register a(*ap);
|
||||
Assembler::Register b(*bp);
|
||||
// void
|
||||
// swapRegisters(Context* c, int* ap, int* bp)
|
||||
// {
|
||||
// Assembler::Register a(*ap);
|
||||
// Assembler::Register b(*bp);
|
||||
|
||||
c->assembler->apply
|
||||
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
||||
c->assembler->apply
|
||||
(Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
|
||||
c->assembler->apply
|
||||
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
||||
// c->assembler->apply
|
||||
// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
||||
// c->assembler->apply
|
||||
// (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
|
||||
// c->assembler->apply
|
||||
// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
|
||||
|
||||
int t = *ap;
|
||||
*ap = *bp;
|
||||
*bp = t;
|
||||
}
|
||||
// int t = *ap;
|
||||
// *ap = *bp;
|
||||
// *bp = t;
|
||||
// }
|
||||
|
||||
Site*
|
||||
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);
|
||||
return target;
|
||||
} 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) {
|
||||
if (s->type(c) == RegisterOperand) {
|
||||
RegisterSite* rs = static_cast<RegisterSite*>(s);
|
||||
// for (Site* s = r->value->sites; s; s = s->next) {
|
||||
// if (s->type(c) == RegisterOperand) {
|
||||
// RegisterSite* rs = static_cast<RegisterSite*>(s);
|
||||
|
||||
RegisterSite* os = static_cast<RegisterSite*>
|
||||
(c->registers[ts->register_.low].site);
|
||||
// RegisterSite* os = static_cast<RegisterSite*>
|
||||
// (c->registers[ts->register_.low].site);
|
||||
|
||||
assert(c, os->register_.low == ts->register_.low);
|
||||
assert(c, os->register_.high == NoRegister);
|
||||
assert(c, ts->register_.high == NoRegister);
|
||||
assert(c, rs->register_.high == NoRegister);
|
||||
// assert(c, os->register_.low == ts->register_.low);
|
||||
// assert(c, os->register_.high == NoRegister);
|
||||
// assert(c, ts->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);
|
||||
@ -1736,7 +1730,7 @@ compile(Context* c)
|
||||
|
||||
for (Event* e = li->firstEvent; e; e = e->next) {
|
||||
if (e->stackReset) {
|
||||
// fprintf(stderr, "stack reset\n");
|
||||
fprintf(stderr, "stack reset\n");
|
||||
for (Stack* s = e->stack; s; s = s->next) {
|
||||
if (s->value->sites) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
// bool
|
||||
// usedExclusively(Context* c, int r)
|
||||
// {
|
||||
// Value* v = c->registers[r].value;
|
||||
// return used(c, r)
|
||||
// and v->pushCount == 0
|
||||
// and v->sites->next == 0;
|
||||
// }
|
||||
bool
|
||||
usedExclusively(Context* c, int r)
|
||||
{
|
||||
Value* v = c->registers[r].value;
|
||||
return used(c, r) and v->sites->next == 0;
|
||||
}
|
||||
|
||||
int
|
||||
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) {
|
||||
// if (i != except
|
||||
// and c->registers[i].refCount == 0
|
||||
// and (not usedExclusively(c, i)))
|
||||
// {
|
||||
// return i;
|
||||
// }
|
||||
// }
|
||||
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
|
||||
if (i != except
|
||||
and c->registers[i].refCount == 0
|
||||
and (not usedExclusively(c, i)))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (allowAcquired) {
|
||||
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
|
||||
@ -2048,15 +2038,18 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
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() {
|
||||
return value(&c, registerSite(&c, c.assembler->base()));
|
||||
Site* s = registerSite(&c, c.assembler->base());
|
||||
return value(&c, s, s);
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -2098,6 +2091,10 @@ class MyCompiler: public Compiler {
|
||||
abort(&c);
|
||||
}
|
||||
|
||||
virtual void push(unsigned size) {
|
||||
::push(&c, size, value(&c));
|
||||
}
|
||||
|
||||
virtual void push(unsigned size, Operand* value) {
|
||||
::push(&c, size, static_cast<Value*>(value));
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ class Compiler {
|
||||
virtual Operand* label() = 0;
|
||||
virtual void mark(Operand* label) = 0;
|
||||
|
||||
virtual void push(unsigned size) = 0;
|
||||
virtual void push(unsigned size, Operand* value) = 0;
|
||||
virtual Operand* pop(unsigned size) = 0;
|
||||
virtual void pushed(unsigned count) = 0;
|
||||
|
85
src/x86.cpp
85
src/x86.cpp
@ -35,6 +35,18 @@ enum {
|
||||
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
|
||||
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
|
||||
leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
|
||||
{
|
||||
@ -575,13 +598,19 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
|
||||
} else {
|
||||
switch (size) {
|
||||
case 1:
|
||||
if (BytesPerWord == 8) {
|
||||
c->code.append(0x0f);
|
||||
}
|
||||
c->code.append(0xbe);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (BytesPerWord == 8) {
|
||||
c->code.append(0x0f);
|
||||
}
|
||||
c->code.append(0xbf);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
@ -863,6 +892,54 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||
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
|
||||
andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
@ -1065,6 +1142,8 @@ populateTables()
|
||||
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
|
||||
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
|
||||
|
||||
UnaryOperations[INDEX1(Negate, Register)] = CAST1(negateR);
|
||||
|
||||
BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR);
|
||||
|
||||
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
|
||||
@ -1086,6 +1165,8 @@ populateTables()
|
||||
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
||||
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, Memory)] = CAST2(andCM);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user