mirror of
https://github.com/corda/corda.git
synced 2025-01-23 04:48:09 +00:00
bugfixes
This commit is contained in:
parent
aaaf388652
commit
5391c68efd
@ -946,7 +946,7 @@ class Frame {
|
|||||||
|
|
||||||
void loadLong(unsigned index) {
|
void loadLong(unsigned index) {
|
||||||
assert(t, index < static_cast<unsigned>(localSize() - 1));
|
assert(t, index < static_cast<unsigned>(localSize() - 1));
|
||||||
pushLong(c->loadLocal(8, index + 1));
|
pushLong(c->loadLocal(8, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadObject(unsigned index) {
|
void loadObject(unsigned index) {
|
||||||
@ -960,7 +960,7 @@ class Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void storeLong(unsigned index) {
|
void storeLong(unsigned index) {
|
||||||
c->storeLocal(8, popLong(), index + 1);
|
c->storeLocal(8, popLong(), index);
|
||||||
storedLong(index);
|
storedLong(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1871,7 +1871,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
switch (*it.next()) {
|
switch (*it.next()) {
|
||||||
case 'J':
|
case 'J':
|
||||||
case 'D':
|
case 'D':
|
||||||
c->initLocal(2 * BytesPerWord, index);
|
c->initLocal(8, index);
|
||||||
index += 2;
|
index += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
196
src/compiler.cpp
196
src/compiler.cpp
@ -99,6 +99,8 @@ class Site {
|
|||||||
|
|
||||||
virtual void thaw(Context*) { }
|
virtual void thaw(Context*) { }
|
||||||
|
|
||||||
|
virtual bool usesRegister(Context*, int) { return false; }
|
||||||
|
|
||||||
virtual OperandType type(Context*) = 0;
|
virtual OperandType type(Context*) = 0;
|
||||||
|
|
||||||
virtual Assembler::Operand* asAssemblerOperand(Context*) = 0;
|
virtual Assembler::Operand* asAssemblerOperand(Context*) = 0;
|
||||||
@ -453,6 +455,19 @@ append(Context* c, Cell* first, Cell* second)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cell*
|
||||||
|
reverseDestroy(Cell* cell)
|
||||||
|
{
|
||||||
|
Cell* previous = 0;
|
||||||
|
while (cell) {
|
||||||
|
Cell* next = cell->next;
|
||||||
|
cell->next = previous;
|
||||||
|
previous = cell;
|
||||||
|
cell = next;
|
||||||
|
}
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
class StubReadPair {
|
class StubReadPair {
|
||||||
public:
|
public:
|
||||||
Value* value;
|
Value* value;
|
||||||
@ -521,7 +536,7 @@ class Event {
|
|||||||
next(0), stackBefore(c->stack), localsBefore(c->locals),
|
next(0), stackBefore(c->stack), localsBefore(c->locals),
|
||||||
stackAfter(0), localsAfter(0), promises(0), reads(0),
|
stackAfter(0), localsAfter(0), promises(0), reads(0),
|
||||||
junctionSites(0), savedSites(0), predecessors(0), successors(0),
|
junctionSites(0), savedSites(0), predecessors(0), successors(0),
|
||||||
cleanLink(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
|
visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
|
||||||
readCount(0)
|
readCount(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -544,7 +559,7 @@ class Event {
|
|||||||
Site** savedSites;
|
Site** savedSites;
|
||||||
Link* predecessors;
|
Link* predecessors;
|
||||||
Link* successors;
|
Link* successors;
|
||||||
Link* cleanLink;
|
Cell* visitLinks;
|
||||||
Block* block;
|
Block* block;
|
||||||
LogicalInstruction* logicalInstruction;
|
LogicalInstruction* logicalInstruction;
|
||||||
unsigned readCount;
|
unsigned readCount;
|
||||||
@ -675,8 +690,8 @@ nextRead(Context* c, Event* e, Value* v)
|
|||||||
{
|
{
|
||||||
assert(c, e == v->reads->event);
|
assert(c, e == v->reads->event);
|
||||||
|
|
||||||
fprintf(stderr, "pop read %p from %p next %p event %p (%s)\n",
|
// fprintf(stderr, "pop read %p from %p next %p event %p (%s)\n",
|
||||||
v->reads, v, v->reads->next(c), e, (e ? e->name() : 0));
|
// v->reads, v, v->reads->next(c), e, (e ? e->name() : 0));
|
||||||
|
|
||||||
v->reads = v->reads->next(c);
|
v->reads = v->reads->next(c);
|
||||||
if (not live(v)) {
|
if (not live(v)) {
|
||||||
@ -918,6 +933,11 @@ class RegisterSite: public Site {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool usesRegister(Context* c, int r) {
|
||||||
|
sync(c);
|
||||||
|
return register_.low == r or register_.high == r;
|
||||||
|
}
|
||||||
|
|
||||||
virtual OperandType type(Context*) {
|
virtual OperandType type(Context*) {
|
||||||
return RegisterOperand;
|
return RegisterOperand;
|
||||||
}
|
}
|
||||||
@ -1097,6 +1117,11 @@ class MemorySite: public Site {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool usesRegister(Context* c, int r) {
|
||||||
|
sync(c);
|
||||||
|
return value.base == r or value.index == r;
|
||||||
|
}
|
||||||
|
|
||||||
virtual OperandType type(Context*) {
|
virtual OperandType type(Context*) {
|
||||||
return MemoryOperand;
|
return MemoryOperand;
|
||||||
}
|
}
|
||||||
@ -1499,6 +1524,62 @@ move(Context* c, Stack* stack, Local* locals, unsigned size, Value* value,
|
|||||||
apply(c, Move, size, src, size, dst);
|
apply(c, Move, size, src, size, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
toString(Context* c, Site* sites, char* buffer, unsigned size)
|
||||||
|
{
|
||||||
|
sites->toString(c, buffer, size);
|
||||||
|
if (sites->next) {
|
||||||
|
unsigned length = strlen(buffer);
|
||||||
|
assert(c, length + 2 < size);
|
||||||
|
memcpy(buffer + length, ", ", 2);
|
||||||
|
length += 2;
|
||||||
|
sites->next->toString(c, buffer + length, size - length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
releaseRegister(Context* c, Value* v, unsigned index, unsigned size, int r)
|
||||||
|
{
|
||||||
|
if (v) {
|
||||||
|
Site* source = 0;
|
||||||
|
for (Site** s = &(v->sites); *s;) {
|
||||||
|
if ((*s)->usesRegister(c, r)) {
|
||||||
|
char buffer[256]; (*s)->toString(c, buffer, 256);
|
||||||
|
fprintf(stderr, "%p (%s) in %p at %d uses %d\n", *s, buffer, v, index, r);
|
||||||
|
|
||||||
|
source = *s;
|
||||||
|
*s = (*s)->next;
|
||||||
|
|
||||||
|
source->release(c);
|
||||||
|
} else {
|
||||||
|
char buffer[256]; (*s)->toString(c, buffer, 256);
|
||||||
|
fprintf(stderr, "%p (%s) in %p at %d does not use %d\n", *s, buffer, v, index, r);
|
||||||
|
s = &((*s)->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->sites == 0) {
|
||||||
|
move(c, c->stack, c->locals, size, v, source, frameSite(c, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[256]; toString(c, v->sites, buffer, 256);
|
||||||
|
fprintf(stderr, "%p is left with %s\n", v, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
releaseRegister(Context* c, int r)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
||||||
|
releaseRegister(c, c->locals[i].value, i, c->locals[i].size, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Stack* s = c->stack; s; s = s->next) {
|
||||||
|
releaseRegister(c, s->value, s->index + c->localFootprint,
|
||||||
|
s->size * BytesPerWord, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
trySteal(Context* c, Register* r, Stack* stack, Local* locals)
|
trySteal(Context* c, Register* r, Stack* stack, Local* locals)
|
||||||
{
|
{
|
||||||
@ -1747,9 +1828,9 @@ trySteal(Context* c, FrameResource* r, Stack*, Local*)
|
|||||||
Value* v = r->value;
|
Value* v = r->value;
|
||||||
assert(c, v->reads);
|
assert(c, v->reads);
|
||||||
|
|
||||||
// if (v->sites->next == 0) {
|
if (v->sites->next == 0) {
|
||||||
// return false; // todo
|
return false; // todo
|
||||||
// }
|
}
|
||||||
|
|
||||||
if (DebugFrameIndexes) {
|
if (DebugFrameIndexes) {
|
||||||
int index = r - c->frameResources;
|
int index = r - c->frameResources;
|
||||||
@ -2313,6 +2394,7 @@ class CombineEvent: public Event {
|
|||||||
if (c->arch->condensedAddressing()) {
|
if (c->arch->condensedAddressing()) {
|
||||||
maybePreserve(c, stackBefore, localsBefore, secondSize, second,
|
maybePreserve(c, stackBefore, localsBefore, secondSize, second,
|
||||||
second->source);
|
second->source);
|
||||||
|
removeSite(c, second, second->source);
|
||||||
target = second->source;
|
target = second->source;
|
||||||
} else {
|
} else {
|
||||||
target = resultRead->allocateSite(c);
|
target = resultRead->allocateSite(c);
|
||||||
@ -2326,11 +2408,8 @@ class CombineEvent: public Event {
|
|||||||
nextRead(c, this, first);
|
nextRead(c, this, first);
|
||||||
nextRead(c, this, second);
|
nextRead(c, this, second);
|
||||||
|
|
||||||
if (c->arch->condensedAddressing()) {
|
if (c->arch->condensedAddressing() and live(result)) {
|
||||||
removeSite(c, second, second->source);
|
addSite(c, 0, 0, resultSize, result, target);
|
||||||
if (result->reads) {
|
|
||||||
addSite(c, 0, 0, resultSize, result, second->source);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2440,10 +2519,11 @@ appendCombine(Context* c, TernaryOperation type,
|
|||||||
class TranslateEvent: public Event {
|
class TranslateEvent: public Event {
|
||||||
public:
|
public:
|
||||||
TranslateEvent(Context* c, BinaryOperation type, unsigned size, Value* value,
|
TranslateEvent(Context* c, BinaryOperation type, unsigned size, Value* value,
|
||||||
Value* result, Read* read):
|
Value* result, Read* valueRead, Read* resultRead):
|
||||||
Event(c), type(type), size(size), value(value), result(result)
|
Event(c), type(type), size(size), value(value), result(result),
|
||||||
|
resultRead(resultRead)
|
||||||
{
|
{
|
||||||
addRead(c, this, value, read);
|
addRead(c, this, value, valueRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* name() {
|
virtual const char* name() {
|
||||||
@ -2451,16 +2531,22 @@ class TranslateEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
maybePreserve(c, stackBefore, localsBefore, size, value, value->source);
|
Site* target;
|
||||||
|
if (c->arch->condensedAddressing()) {
|
||||||
|
maybePreserve(c, stackBefore, localsBefore, size, value, value->source);
|
||||||
|
removeSite(c, value, value->source);
|
||||||
|
target = value->source;
|
||||||
|
} else {
|
||||||
|
target = resultRead->allocateSite(c);
|
||||||
|
addSite(c, stackBefore, localsBefore, size, result, target);
|
||||||
|
}
|
||||||
|
|
||||||
Site* target = targetOrRegister(c, result);
|
|
||||||
apply(c, type, size, value->source, size, target);
|
apply(c, type, size, value->source, size, target);
|
||||||
|
|
||||||
nextRead(c, this, value);
|
nextRead(c, this, value);
|
||||||
|
|
||||||
removeSite(c, value, value->source);
|
if (c->arch->condensedAddressing() and live(result)) {
|
||||||
if (live(result)) {
|
addSite(c, 0, 0, size, result, target);
|
||||||
addSite(c, 0, 0, size, result, value->source);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2468,6 +2554,7 @@ class TranslateEvent: public Event {
|
|||||||
unsigned size;
|
unsigned size;
|
||||||
Value* value;
|
Value* value;
|
||||||
Value* result;
|
Value* result;
|
||||||
|
Read* resultRead;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2486,12 +2573,20 @@ appendTranslate(Context* c, BinaryOperation type, unsigned size, Value* value,
|
|||||||
|
|
||||||
assert(c, not thunk); // todo
|
assert(c, not thunk); // todo
|
||||||
|
|
||||||
|
Read* resultRead = read
|
||||||
|
(c, size, resultTypeMask, resultRegisterMask, AnyFrameIndex);
|
||||||
|
Read* firstRead;
|
||||||
|
if (c->arch->condensedAddressing()) {
|
||||||
|
firstRead = resultRead;
|
||||||
|
} else {
|
||||||
|
firstRead = read
|
||||||
|
(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex);
|
||||||
|
}
|
||||||
// todo: respect resultTypeMask and resultRegisterMask
|
// todo: respect resultTypeMask and resultRegisterMask
|
||||||
|
|
||||||
append(c, new (c->zone->allocate(sizeof(TranslateEvent)))
|
append(c, new (c->zone->allocate(sizeof(TranslateEvent)))
|
||||||
TranslateEvent
|
TranslateEvent
|
||||||
(c, type, size, value, result,
|
(c, type, size, value, result, firstRead, resultRead));
|
||||||
read(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemoryEvent: public Event {
|
class MemoryEvent: public Event {
|
||||||
@ -2770,9 +2865,9 @@ skipRead(Context* c, Value* v, StubReadPair* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clean(Context* c, Link* link)
|
visit(Context* c, Link* link)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "clean link from %d to %d\n",
|
fprintf(stderr, "visit link from %d to %d\n",
|
||||||
link->predecessor->logicalInstruction->index,
|
link->predecessor->logicalInstruction->index,
|
||||||
link->successor->logicalInstruction->index);
|
link->successor->logicalInstruction->index);
|
||||||
|
|
||||||
@ -2971,19 +3066,6 @@ propagateJunctionSites(Context* c, Event* e, Site** sites)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
toString(Context* c, Site* sites, char* buffer, unsigned size)
|
|
||||||
{
|
|
||||||
sites->toString(c, buffer, size);
|
|
||||||
if (sites->next) {
|
|
||||||
unsigned length = strlen(buffer);
|
|
||||||
assert(c, length + 2 < size);
|
|
||||||
memcpy(buffer + length, ", ", 2);
|
|
||||||
length += 2;
|
|
||||||
sites->next->toString(c, buffer + length, size - length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Site*
|
Site*
|
||||||
copy(Context* c, Site* s)
|
copy(Context* c, Site* s)
|
||||||
{
|
{
|
||||||
@ -3166,16 +3248,6 @@ setSites(Context* c, Event* e, Site** sites)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: we should be releasing these resources at block ends:
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < c->arch->registerCount(); ++i) {
|
|
||||||
release(c, c->registers[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < c->alignedFrameSize + c->parameterFootprint; ++i) {
|
|
||||||
releaseFrameIndex(c, i, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e->stackBefore) {
|
if (e->stackBefore) {
|
||||||
unsigned i = e->stackBefore->index + c->localFootprint;
|
unsigned i = e->stackBefore->index + c->localFootprint;
|
||||||
for (Stack* stack = e->stackBefore; stack; stack = stack->next) {
|
for (Stack* stack = e->stackBefore; stack; stack = stack->next) {
|
||||||
@ -3314,8 +3386,6 @@ compile(Context* c)
|
|||||||
a->allocateFrame(c->alignedFrameSize);
|
a->allocateFrame(c->alignedFrameSize);
|
||||||
|
|
||||||
for (Event* e = c->firstEvent; e; e = e->next) {
|
for (Event* e = c->firstEvent; e; e = e->next) {
|
||||||
e->block = block;
|
|
||||||
|
|
||||||
if (DebugCompile) {
|
if (DebugCompile) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
" -- compile %s at %d with %d preds %d succs %d stack before "
|
" -- compile %s at %d with %d preds %d succs %d stack before "
|
||||||
@ -3329,12 +3399,17 @@ compile(Context* c)
|
|||||||
e->stackAfter->index + e->stackAfter->size : 0);
|
e->stackAfter->index + e->stackAfter->size : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e->block = block;
|
||||||
|
|
||||||
|
c->stack = e->stackBefore;
|
||||||
|
c->locals = e->localsBefore;
|
||||||
|
|
||||||
if (e->logicalInstruction->machineOffset == 0) {
|
if (e->logicalInstruction->machineOffset == 0) {
|
||||||
e->logicalInstruction->machineOffset = a->offset();
|
e->logicalInstruction->machineOffset = a->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->predecessors) {
|
if (e->predecessors) {
|
||||||
clean(c, lastPredecessor(e->predecessors));
|
visit(c, lastPredecessor(e->predecessors));
|
||||||
|
|
||||||
Event* first = e->predecessors->predecessor;
|
Event* first = e->predecessors->predecessor;
|
||||||
if (e->predecessors->nextPredecessor) {
|
if (e->predecessors->nextPredecessor) {
|
||||||
@ -3366,8 +3441,12 @@ compile(Context* c)
|
|||||||
populateSiteTables(c, e);
|
populateSiteTables(c, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->cleanLink) {
|
if (e->visitLinks) {
|
||||||
clean(c, e->cleanLink);
|
for (Cell* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next)
|
||||||
|
{
|
||||||
|
visit(c, static_cast<Link*>(cell->value));
|
||||||
|
}
|
||||||
|
e->visitLinks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CodePromise* p = e->promises; p; p = p->next) {
|
for (CodePromise* p = e->promises; p; p = p->next) {
|
||||||
@ -3509,9 +3588,12 @@ class Client: public Assembler::Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void save(int r) {
|
virtual void save(int r) {
|
||||||
// todo
|
Register* reg = c->registers[r];
|
||||||
expect(c, c->registers[r]->refCount == 0);
|
if (reg->refCount or reg->value) {
|
||||||
expect(c, c->registers[r]->value == 0);
|
releaseRegister(c, r);
|
||||||
|
}
|
||||||
|
assert(c, reg->refCount == 0);
|
||||||
|
assert(c, reg->value == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void restore(int) {
|
virtual void restore(int) {
|
||||||
@ -3578,7 +3660,7 @@ class MyCompiler: public Compiler {
|
|||||||
(&c, p, e->predecessors, e, p->successors, c.forkState);
|
(&c, p, e->predecessors, e, p->successors, c.forkState);
|
||||||
e->predecessors = link;
|
e->predecessors = link;
|
||||||
p->successors = link;
|
p->successors = link;
|
||||||
c.lastEvent->cleanLink = link;
|
c.lastEvent->visitLinks = cons(&c, link, c.lastEvent->visitLinks);
|
||||||
|
|
||||||
fprintf(stderr, "populate junction reads for %d to %d\n",
|
fprintf(stderr, "populate junction reads for %d to %d\n",
|
||||||
p->logicalInstruction->index, logicalIp);
|
p->logicalInstruction->index, logicalIp);
|
||||||
@ -3797,7 +3879,7 @@ class MyCompiler: public Compiler {
|
|||||||
assert(&c, index < c.localFootprint);
|
assert(&c, index < c.localFootprint);
|
||||||
|
|
||||||
Value* v = value(&c);
|
Value* v = value(&c);
|
||||||
// fprintf(stderr, "init local %p of size %d at %d\n", v, size, index);
|
fprintf(stderr, "init local %p of size %d at %d\n", v, size, index);
|
||||||
appendFrameSite(&c, v, size, index);
|
appendFrameSite(&c, v, size, index);
|
||||||
|
|
||||||
Local* local = c.locals + index;
|
Local* local = c.locals + index;
|
||||||
|
239
src/x86.cpp
239
src/x86.cpp
@ -11,6 +11,9 @@
|
|||||||
#include "assembler.h"
|
#include "assembler.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
|
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
||||||
|
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -596,6 +599,41 @@ popR(Context* c, unsigned size, Assembler::Register* a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
addCarryCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
|
Assembler::Register* b);
|
||||||
|
|
||||||
|
void
|
||||||
|
negateR(Context* c, unsigned size, Assembler::Register* a)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
assert(c, a->low == rax and a->high == rdx);
|
||||||
|
|
||||||
|
ResolvedPromise zeroPromise(0);
|
||||||
|
Assembler::Constant zero(&zeroPromise);
|
||||||
|
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
|
||||||
|
negateR(c, 4, a);
|
||||||
|
addCarryCR(c, 4, &zero, &ah);
|
||||||
|
negateR(c, 4, &ah);
|
||||||
|
} else {
|
||||||
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xd8 | a->low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
negateRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||||
|
unsigned bSize, Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, aSize == bSize);
|
||||||
|
assert(c, a == b);
|
||||||
|
|
||||||
|
negateR(c, aSize, a);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
moveRR(Context* c, unsigned aSize, Assembler::Register* a,
|
moveRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||||
unsigned bSize, Assembler::Register* b)
|
unsigned bSize, Assembler::Register* b)
|
||||||
@ -1240,12 +1278,198 @@ multiplyRR(Context* c, unsigned aSize, Assembler::Register* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
longCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah,
|
||||||
|
Assembler::Operand* bl, Assembler::Operand* bh,
|
||||||
|
BinaryOperationType compare, BinaryOperationType move)
|
||||||
|
{
|
||||||
|
ResolvedPromise negativePromise(-1);
|
||||||
|
Assembler::Constant negative(&negativePromise);
|
||||||
|
|
||||||
|
ResolvedPromise zeroPromise(0);
|
||||||
|
Assembler::Constant zero(&zeroPromise);
|
||||||
|
|
||||||
|
ResolvedPromise positivePromise(1);
|
||||||
|
Assembler::Constant positive(&positivePromise);
|
||||||
|
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
compare(c, 8, al, 8, bl);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x8c); // jl
|
||||||
|
unsigned less = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x8f); // jg
|
||||||
|
unsigned greater = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
move(c, 4, &zero, 4, bl);
|
||||||
|
|
||||||
|
c->code.append(0xe9); // jmp
|
||||||
|
unsigned nextFirst = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
int32_t lessOffset = c->code.length() - less - 4;
|
||||||
|
c->code.set(less, &lessOffset, 4);
|
||||||
|
|
||||||
|
move(c, 4, &negative, 4, bl);
|
||||||
|
|
||||||
|
c->code.append(0xe9); // jmp
|
||||||
|
unsigned nextSecond = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
int32_t greaterOffset = c->code.length() - greater - 4;
|
||||||
|
c->code.set(greater, &greaterOffset, 4);
|
||||||
|
|
||||||
|
move(c, 4, &positive, 4, bl);
|
||||||
|
|
||||||
|
int32_t nextFirstOffset = c->code.length() - nextFirst - 4;
|
||||||
|
c->code.set(nextFirst, &nextFirstOffset, 4);
|
||||||
|
|
||||||
|
int32_t nextSecondOffset = c->code.length() - nextSecond - 4;
|
||||||
|
c->code.set(nextSecond, &nextSecondOffset, 4);
|
||||||
|
} else {
|
||||||
|
compare(c, 4, ah, 4, bh);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x8c); // jl
|
||||||
|
unsigned less = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x8f); // jg
|
||||||
|
unsigned greater = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
compare(c, 4, al, 4, bl);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x82); // ja
|
||||||
|
unsigned above = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x87); // jb
|
||||||
|
unsigned below = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
move(c, 4, &zero, 4, bl);
|
||||||
|
|
||||||
|
c->code.append(0xe9); // jmp
|
||||||
|
unsigned nextFirst = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
int32_t lessOffset = c->code.length() - less - 4;
|
||||||
|
c->code.set(less, &lessOffset, 4);
|
||||||
|
|
||||||
|
int32_t aboveOffset = c->code.length() - above - 4;
|
||||||
|
c->code.set(above, &aboveOffset, 4);
|
||||||
|
|
||||||
|
move(c, 4, &negative, 4, bl);
|
||||||
|
|
||||||
|
c->code.append(0xe9); // jmp
|
||||||
|
unsigned nextSecond = c->code.length();
|
||||||
|
c->code.append4(0);
|
||||||
|
|
||||||
|
int32_t greaterOffset = c->code.length() - greater - 4;
|
||||||
|
c->code.set(greater, &greaterOffset, 4);
|
||||||
|
|
||||||
|
int32_t belowOffset = c->code.length() - below - 4;
|
||||||
|
c->code.set(below, &belowOffset, 4);
|
||||||
|
|
||||||
|
move(c, 4, &positive, 4, bl);
|
||||||
|
|
||||||
|
int32_t nextFirstOffset = c->code.length() - nextFirst - 4;
|
||||||
|
c->code.set(nextFirst, &nextFirstOffset, 4);
|
||||||
|
|
||||||
|
int32_t nextSecondOffset = c->code.length() - nextSecond - 4;
|
||||||
|
c->code.set(nextSecond, &nextSecondOffset, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
divideRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||||
|
unsigned bSize, Assembler::Register* b UNUSED)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or aSize == 4);
|
||||||
|
assert(c, aSize == bSize);
|
||||||
|
|
||||||
|
assert(c, b->low == rax);
|
||||||
|
assert(c, a->low != rdx);
|
||||||
|
|
||||||
|
c->client->save(rdx);
|
||||||
|
|
||||||
|
if (aSize == 8) rex(c);
|
||||||
|
c->code.append(0x99); // cdq
|
||||||
|
if (aSize == 8) rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xf8 | a->low);
|
||||||
|
|
||||||
|
c->client->restore(rdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
remainderRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||||
|
unsigned bSize, Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or aSize == 4);
|
||||||
|
assert(c, aSize == bSize);
|
||||||
|
|
||||||
|
assert(c, b->low == rax);
|
||||||
|
assert(c, a->low != rdx);
|
||||||
|
|
||||||
|
c->client->save(rdx);
|
||||||
|
|
||||||
|
if (aSize == 8) rex(c);
|
||||||
|
c->code.append(0x99); // cdq
|
||||||
|
if (aSize == 8) rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xf8 | a->low);
|
||||||
|
|
||||||
|
Assembler::Register dx(rdx);
|
||||||
|
moveRR(c, BytesPerWord, &dx, BytesPerWord, b);
|
||||||
|
|
||||||
|
c->client->restore(rdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
longCompareCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
|
||||||
|
unsigned bSize UNUSED, Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, aSize == 8);
|
||||||
|
assert(c, bSize == 8);
|
||||||
|
|
||||||
|
int64_t v = a->value->value();
|
||||||
|
|
||||||
|
ResolvedPromise low(v & ~static_cast<uintptr_t>(0));
|
||||||
|
Assembler::Constant al(&low);
|
||||||
|
|
||||||
|
ResolvedPromise high((v >> 32) & ~static_cast<uintptr_t>(0));
|
||||||
|
Assembler::Constant ah(&high);
|
||||||
|
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
longCompare(c, &al, &ah, b, &bh, CAST2(compareCR), CAST2(moveCR));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
longCompareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
|
||||||
|
unsigned bSize UNUSED, Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, aSize == 8);
|
||||||
|
assert(c, bSize == 8);
|
||||||
|
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
longCompare(c, a, &ah, b, &bh, CAST2(compareRR), CAST2(moveCR));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
populateTables(ArchitectureContext* c)
|
populateTables(ArchitectureContext* c)
|
||||||
{
|
{
|
||||||
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
|
||||||
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
|
||||||
|
|
||||||
const OperandType C = ConstantOperand;
|
const OperandType C = ConstantOperand;
|
||||||
const OperandType A = AddressOperand;
|
const OperandType A = AddressOperand;
|
||||||
const OperandType R = RegisterOperand;
|
const OperandType R = RegisterOperand;
|
||||||
@ -1277,6 +1501,8 @@ populateTables(ArchitectureContext* c)
|
|||||||
|
|
||||||
uo[index(LongJump, C)] = CAST1(longJumpC);
|
uo[index(LongJump, C)] = CAST1(longJumpC);
|
||||||
|
|
||||||
|
bo[index(Negate, R, R)] = CAST2(negateRR);
|
||||||
|
|
||||||
bo[index(Move, R, R)] = CAST2(moveRR);
|
bo[index(Move, R, R)] = CAST2(moveRR);
|
||||||
bo[index(Move, C, R)] = CAST2(moveCR);
|
bo[index(Move, C, R)] = CAST2(moveCR);
|
||||||
bo[index(Move, M, R)] = CAST2(moveMR);
|
bo[index(Move, M, R)] = CAST2(moveMR);
|
||||||
@ -1304,6 +1530,13 @@ populateTables(ArchitectureContext* c)
|
|||||||
bo[index(And, C, R)] = CAST2(andCR);
|
bo[index(And, C, R)] = CAST2(andCR);
|
||||||
|
|
||||||
bo[index(Multiply, R, R)] = CAST2(multiplyRR);
|
bo[index(Multiply, R, R)] = CAST2(multiplyRR);
|
||||||
|
|
||||||
|
bo[index(Divide, R, R)] = CAST2(divideRR);
|
||||||
|
|
||||||
|
bo[index(Remainder, R, R)] = CAST2(remainderRR);
|
||||||
|
|
||||||
|
bo[index(LongCompare, C, R)] = CAST2(longCompareCR);
|
||||||
|
bo[index(LongCompare, R, R)] = CAST2(longCompareRR);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyArchitecture: public Assembler::Architecture {
|
class MyArchitecture: public Assembler::Architecture {
|
||||||
|
Loading…
Reference in New Issue
Block a user