mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
bugfixes
This commit is contained in:
parent
aaaf388652
commit
5391c68efd
@ -946,7 +946,7 @@ class Frame {
|
||||
|
||||
void loadLong(unsigned index) {
|
||||
assert(t, index < static_cast<unsigned>(localSize() - 1));
|
||||
pushLong(c->loadLocal(8, index + 1));
|
||||
pushLong(c->loadLocal(8, index));
|
||||
}
|
||||
|
||||
void loadObject(unsigned index) {
|
||||
@ -960,7 +960,7 @@ class Frame {
|
||||
}
|
||||
|
||||
void storeLong(unsigned index) {
|
||||
c->storeLocal(8, popLong(), index + 1);
|
||||
c->storeLocal(8, popLong(), index);
|
||||
storedLong(index);
|
||||
}
|
||||
|
||||
@ -1871,7 +1871,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
switch (*it.next()) {
|
||||
case 'J':
|
||||
case 'D':
|
||||
c->initLocal(2 * BytesPerWord, index);
|
||||
c->initLocal(8, index);
|
||||
index += 2;
|
||||
break;
|
||||
|
||||
|
196
src/compiler.cpp
196
src/compiler.cpp
@ -99,6 +99,8 @@ class Site {
|
||||
|
||||
virtual void thaw(Context*) { }
|
||||
|
||||
virtual bool usesRegister(Context*, int) { return false; }
|
||||
|
||||
virtual OperandType type(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 {
|
||||
public:
|
||||
Value* value;
|
||||
@ -521,7 +536,7 @@ class Event {
|
||||
next(0), stackBefore(c->stack), localsBefore(c->locals),
|
||||
stackAfter(0), localsAfter(0), promises(0), reads(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)
|
||||
{ }
|
||||
|
||||
@ -544,7 +559,7 @@ class Event {
|
||||
Site** savedSites;
|
||||
Link* predecessors;
|
||||
Link* successors;
|
||||
Link* cleanLink;
|
||||
Cell* visitLinks;
|
||||
Block* block;
|
||||
LogicalInstruction* logicalInstruction;
|
||||
unsigned readCount;
|
||||
@ -675,8 +690,8 @@ nextRead(Context* c, Event* e, Value* v)
|
||||
{
|
||||
assert(c, e == v->reads->event);
|
||||
|
||||
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));
|
||||
// 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->reads->next(c);
|
||||
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*) {
|
||||
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*) {
|
||||
return MemoryOperand;
|
||||
}
|
||||
@ -1499,6 +1524,62 @@ move(Context* c, Stack* stack, Local* locals, unsigned size, Value* value,
|
||||
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
|
||||
trySteal(Context* c, Register* r, Stack* stack, Local* locals)
|
||||
{
|
||||
@ -1747,9 +1828,9 @@ trySteal(Context* c, FrameResource* r, Stack*, Local*)
|
||||
Value* v = r->value;
|
||||
assert(c, v->reads);
|
||||
|
||||
// if (v->sites->next == 0) {
|
||||
// return false; // todo
|
||||
// }
|
||||
if (v->sites->next == 0) {
|
||||
return false; // todo
|
||||
}
|
||||
|
||||
if (DebugFrameIndexes) {
|
||||
int index = r - c->frameResources;
|
||||
@ -2313,6 +2394,7 @@ class CombineEvent: public Event {
|
||||
if (c->arch->condensedAddressing()) {
|
||||
maybePreserve(c, stackBefore, localsBefore, secondSize, second,
|
||||
second->source);
|
||||
removeSite(c, second, second->source);
|
||||
target = second->source;
|
||||
} else {
|
||||
target = resultRead->allocateSite(c);
|
||||
@ -2326,11 +2408,8 @@ class CombineEvent: public Event {
|
||||
nextRead(c, this, first);
|
||||
nextRead(c, this, second);
|
||||
|
||||
if (c->arch->condensedAddressing()) {
|
||||
removeSite(c, second, second->source);
|
||||
if (result->reads) {
|
||||
addSite(c, 0, 0, resultSize, result, second->source);
|
||||
}
|
||||
if (c->arch->condensedAddressing() and live(result)) {
|
||||
addSite(c, 0, 0, resultSize, result, target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2440,10 +2519,11 @@ appendCombine(Context* c, TernaryOperation type,
|
||||
class TranslateEvent: public Event {
|
||||
public:
|
||||
TranslateEvent(Context* c, BinaryOperation type, unsigned size, Value* value,
|
||||
Value* result, Read* read):
|
||||
Event(c), type(type), size(size), value(value), result(result)
|
||||
Value* result, Read* valueRead, Read* resultRead):
|
||||
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() {
|
||||
@ -2451,16 +2531,22 @@ class TranslateEvent: public Event {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
nextRead(c, this, value);
|
||||
|
||||
removeSite(c, value, value->source);
|
||||
if (live(result)) {
|
||||
addSite(c, 0, 0, size, result, value->source);
|
||||
if (c->arch->condensedAddressing() and live(result)) {
|
||||
addSite(c, 0, 0, size, result, target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2468,6 +2554,7 @@ class TranslateEvent: public Event {
|
||||
unsigned size;
|
||||
Value* value;
|
||||
Value* result;
|
||||
Read* resultRead;
|
||||
};
|
||||
|
||||
void
|
||||
@ -2486,12 +2573,20 @@ appendTranslate(Context* c, BinaryOperation type, unsigned size, Value* value,
|
||||
|
||||
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
|
||||
|
||||
append(c, new (c->zone->allocate(sizeof(TranslateEvent)))
|
||||
TranslateEvent
|
||||
(c, type, size, value, result,
|
||||
read(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex)));
|
||||
(c, type, size, value, result, firstRead, resultRead));
|
||||
}
|
||||
|
||||
class MemoryEvent: public Event {
|
||||
@ -2770,9 +2865,9 @@ skipRead(Context* c, Value* v, StubReadPair* p)
|
||||
}
|
||||
|
||||
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->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*
|
||||
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) {
|
||||
unsigned i = e->stackBefore->index + c->localFootprint;
|
||||
for (Stack* stack = e->stackBefore; stack; stack = stack->next) {
|
||||
@ -3314,8 +3386,6 @@ compile(Context* c)
|
||||
a->allocateFrame(c->alignedFrameSize);
|
||||
|
||||
for (Event* e = c->firstEvent; e; e = e->next) {
|
||||
e->block = block;
|
||||
|
||||
if (DebugCompile) {
|
||||
fprintf(stderr,
|
||||
" -- 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->block = block;
|
||||
|
||||
c->stack = e->stackBefore;
|
||||
c->locals = e->localsBefore;
|
||||
|
||||
if (e->logicalInstruction->machineOffset == 0) {
|
||||
e->logicalInstruction->machineOffset = a->offset();
|
||||
}
|
||||
|
||||
if (e->predecessors) {
|
||||
clean(c, lastPredecessor(e->predecessors));
|
||||
visit(c, lastPredecessor(e->predecessors));
|
||||
|
||||
Event* first = e->predecessors->predecessor;
|
||||
if (e->predecessors->nextPredecessor) {
|
||||
@ -3366,8 +3441,12 @@ compile(Context* c)
|
||||
populateSiteTables(c, e);
|
||||
}
|
||||
|
||||
if (e->cleanLink) {
|
||||
clean(c, e->cleanLink);
|
||||
if (e->visitLinks) {
|
||||
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) {
|
||||
@ -3509,9 +3588,12 @@ class Client: public Assembler::Client {
|
||||
}
|
||||
|
||||
virtual void save(int r) {
|
||||
// todo
|
||||
expect(c, c->registers[r]->refCount == 0);
|
||||
expect(c, c->registers[r]->value == 0);
|
||||
Register* reg = c->registers[r];
|
||||
if (reg->refCount or reg->value) {
|
||||
releaseRegister(c, r);
|
||||
}
|
||||
assert(c, reg->refCount == 0);
|
||||
assert(c, reg->value == 0);
|
||||
}
|
||||
|
||||
virtual void restore(int) {
|
||||
@ -3578,7 +3660,7 @@ class MyCompiler: public Compiler {
|
||||
(&c, p, e->predecessors, e, p->successors, c.forkState);
|
||||
e->predecessors = 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",
|
||||
p->logicalInstruction->index, logicalIp);
|
||||
@ -3797,7 +3879,7 @@ class MyCompiler: public Compiler {
|
||||
assert(&c, index < c.localFootprint);
|
||||
|
||||
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);
|
||||
|
||||
Local* local = c.locals + index;
|
||||
|
239
src/x86.cpp
239
src/x86.cpp
@ -11,6 +11,9 @@
|
||||
#include "assembler.h"
|
||||
#include "vector.h"
|
||||
|
||||
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
||||
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
||||
|
||||
using namespace vm;
|
||||
|
||||
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
|
||||
moveRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||
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
|
||||
populateTables(ArchitectureContext* c)
|
||||
{
|
||||
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
||||
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
||||
|
||||
const OperandType C = ConstantOperand;
|
||||
const OperandType A = AddressOperand;
|
||||
const OperandType R = RegisterOperand;
|
||||
@ -1277,6 +1501,8 @@ populateTables(ArchitectureContext* c)
|
||||
|
||||
uo[index(LongJump, C)] = CAST1(longJumpC);
|
||||
|
||||
bo[index(Negate, R, R)] = CAST2(negateRR);
|
||||
|
||||
bo[index(Move, R, R)] = CAST2(moveRR);
|
||||
bo[index(Move, C, R)] = CAST2(moveCR);
|
||||
bo[index(Move, M, R)] = CAST2(moveMR);
|
||||
@ -1304,6 +1530,13 @@ populateTables(ArchitectureContext* c)
|
||||
bo[index(And, C, R)] = CAST2(andCR);
|
||||
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user