mirror of
https://github.com/corda/corda.git
synced 2025-02-02 01:08:09 +00:00
bugfixes, mainly concerning 32-bit machines
This commit is contained in:
parent
90ae9a70ee
commit
8738bddcb9
@ -134,7 +134,7 @@ class Assembler {
|
|||||||
public:
|
public:
|
||||||
virtual ~Client() { }
|
virtual ~Client() { }
|
||||||
|
|
||||||
virtual int acquireTemporary(int r = NoRegister) = 0;
|
virtual int acquireTemporary() = 0;
|
||||||
virtual void releaseTemporary(int r) = 0;
|
virtual void releaseTemporary(int r) = 0;
|
||||||
|
|
||||||
virtual void save(int r) = 0;
|
virtual void save(int r) = 0;
|
||||||
@ -156,11 +156,8 @@ class Assembler {
|
|||||||
virtual unsigned argumentRegisterCount() = 0;
|
virtual unsigned argumentRegisterCount() = 0;
|
||||||
virtual int argumentRegister(unsigned index) = 0;
|
virtual int argumentRegister(unsigned index) = 0;
|
||||||
|
|
||||||
virtual void getTargets(UnaryOperation op, unsigned size,
|
|
||||||
Register* a) = 0;
|
|
||||||
|
|
||||||
virtual void getTargets(BinaryOperation op, unsigned size,
|
virtual void getTargets(BinaryOperation op, unsigned size,
|
||||||
Register* a, Register* b) = 0;
|
Register* a, Register* b, bool* syncStack) = 0;
|
||||||
|
|
||||||
virtual void apply(Operation op) = 0;
|
virtual void apply(Operation op) = 0;
|
||||||
|
|
||||||
|
@ -3875,11 +3875,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)),
|
||||||
"java/nio/ByteBuffer") == 0 and
|
"java/lang/Class") == 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)),
|
||||||
"checkPut") == 0)
|
"replace") == 0)
|
||||||
{
|
{
|
||||||
asm("int3");
|
asm("int3");
|
||||||
}
|
}
|
||||||
|
@ -1195,13 +1195,15 @@ class MoveEvent: public Event {
|
|||||||
|
|
||||||
nextRead(c, src);
|
nextRead(c, src);
|
||||||
|
|
||||||
|
if (dst->reads) {
|
||||||
|
addSite(c, stack, size, dst, target);
|
||||||
|
}
|
||||||
|
|
||||||
if (cost) {
|
if (cost) {
|
||||||
apply(c, type, size, src->source, target);
|
apply(c, type, size, src->source, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst->reads) {
|
if (dst->reads == 0) {
|
||||||
addSite(c, stack, size, dst, target);
|
|
||||||
} else {
|
|
||||||
removeSite(c, dst, target);
|
removeSite(c, dst, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1263,22 +1265,20 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second)
|
|||||||
class CombineEvent: public Event {
|
class CombineEvent: public Event {
|
||||||
public:
|
public:
|
||||||
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
|
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
|
||||||
Value* second, Value* result):
|
Value* second, Value* result, Assembler::Register* r1,
|
||||||
|
Assembler::Register* r2):
|
||||||
Event(c), type(type), size(size), first(first), second(second),
|
Event(c), type(type), size(size), first(first), second(second),
|
||||||
result(result)
|
result(result)
|
||||||
{
|
{
|
||||||
Assembler::Register r1(NoRegister);
|
|
||||||
Assembler::Register r2(NoRegister);
|
|
||||||
c->assembler->getTargets(type, size, &r1, &r2);
|
|
||||||
|
|
||||||
addRead(c, first, size,
|
addRead(c, first, size,
|
||||||
r1.low == NoRegister ?
|
r1->low == NoRegister ?
|
||||||
constantOrRegisterSite(c) :
|
constantOrRegisterSite(c) :
|
||||||
static_cast<Site*>(registerSite(c, r1.low, r1.high)));
|
static_cast<Site*>(registerSite(c, r1->low, r1->high)));
|
||||||
|
|
||||||
addRead(c, second, size,
|
addRead(c, second, size,
|
||||||
r2.low == NoRegister ?
|
r2->low == NoRegister ?
|
||||||
valueSite(c, result) :
|
valueSite(c, result) :
|
||||||
static_cast<Site*>(registerSite(c, r2.low, r2.high)));
|
static_cast<Site*>(registerSite(c, r2->low, r2->high)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
@ -1304,16 +1304,28 @@ class CombineEvent: public Event {
|
|||||||
Value* result;
|
Value* result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendStackSync(Context* c);
|
||||||
|
|
||||||
void
|
void
|
||||||
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
|
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
|
||||||
Value* second, Value* result)
|
Value* second, Value* result)
|
||||||
{
|
{
|
||||||
|
Assembler::Register r1(NoRegister);
|
||||||
|
Assembler::Register r2(NoRegister);
|
||||||
|
bool syncStack;
|
||||||
|
c->assembler->getTargets(type, size, &r1, &r2, &syncStack);
|
||||||
|
|
||||||
|
if (syncStack) {
|
||||||
|
appendStackSync(c);
|
||||||
|
}
|
||||||
|
|
||||||
if (DebugAppend) {
|
if (DebugAppend) {
|
||||||
fprintf(stderr, "appendCombine\n");
|
fprintf(stderr, "appendCombine\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
new (c->zone->allocate(sizeof(CombineEvent)))
|
new (c->zone->allocate(sizeof(CombineEvent)))
|
||||||
CombineEvent(c, type, size, first, second, result);
|
CombineEvent(c, type, size, first, second, result, &r1, &r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TranslateEvent: public Event {
|
class TranslateEvent: public Event {
|
||||||
@ -1949,14 +1961,8 @@ class Client: public Assembler::Client {
|
|||||||
public:
|
public:
|
||||||
Client(Context* c): c(c) { }
|
Client(Context* c): c(c) { }
|
||||||
|
|
||||||
virtual int acquireTemporary(int r) {
|
virtual int acquireTemporary() {
|
||||||
if (r == NoRegister) {
|
int r = freeRegisterExcept(c, NoRegister, false);
|
||||||
r = freeRegisterExcept(c, NoRegister, false);
|
|
||||||
} else {
|
|
||||||
expect(c, (c->registers[r].refCount == 0
|
|
||||||
and c->registers[r].value == 0)
|
|
||||||
or c->registers[r].pushed);
|
|
||||||
}
|
|
||||||
increment(c, r);
|
increment(c, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
409
src/x86.cpp
409
src/x86.cpp
@ -95,6 +95,13 @@ expect(Context* c, bool v)
|
|||||||
expect(c->s, v);
|
expect(c->s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResolvedPromise*
|
||||||
|
resolved(Context* c, int64_t value)
|
||||||
|
{
|
||||||
|
return new (c->zone->allocate(sizeof(ResolvedPromise)))
|
||||||
|
ResolvedPromise(value);
|
||||||
|
}
|
||||||
|
|
||||||
class CodePromise: public Promise {
|
class CodePromise: public Promise {
|
||||||
public:
|
public:
|
||||||
CodePromise(Context* c, unsigned offset): c(c), offset(offset) { }
|
CodePromise(Context* c, unsigned offset): c(c), offset(offset) { }
|
||||||
@ -434,12 +441,12 @@ pushC(Context* c, unsigned size, Assembler::Constant* a)
|
|||||||
int64_t v = a->value->value();
|
int64_t v = a->value->value();
|
||||||
|
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
|
||||||
Assembler::Constant ah(&high);
|
|
||||||
|
|
||||||
ResolvedPromise low(v & 0xFFFFFFFF);
|
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||||
Assembler::Constant al(&low);
|
Assembler::Constant al(&low);
|
||||||
|
|
||||||
|
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||||
|
Assembler::Constant ah(&high);
|
||||||
|
|
||||||
pushC(c, 4, &ah);
|
pushC(c, 4, &ah);
|
||||||
pushC(c, 4, &al);
|
pushC(c, 4, &al);
|
||||||
} else {
|
} else {
|
||||||
@ -536,13 +543,65 @@ popM(Context* c, unsigned size, Assembler::Memory* a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
negateR(Context* c, unsigned size UNUSED, Assembler::Register* a)
|
addCarryCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
|
int64_t v = a->value->value();
|
||||||
|
if (isInt8(v)) {
|
||||||
|
c->code.append(0x83);
|
||||||
|
c->code.append(0xd0 | b->low);
|
||||||
|
c->code.append(v);
|
||||||
|
} else {
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rex(c);
|
void
|
||||||
c->code.append(0xf7);
|
moveRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
c->code.append(0xd8 | a->low);
|
Assembler::Register* b);
|
||||||
|
|
||||||
|
void
|
||||||
|
negateR(Context* c, unsigned size, Assembler::Register* a)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
Assembler::Register ax(rax);
|
||||||
|
Assembler::Register dx(rdx);
|
||||||
|
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
|
||||||
|
ResolvedPromise zeroPromise(0);
|
||||||
|
Assembler::Constant zero(&zeroPromise);
|
||||||
|
|
||||||
|
if (a->low != rax) {
|
||||||
|
c->client->save(rax);
|
||||||
|
moveRR(c, BytesPerWord, a, &ax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->high != rdx) {
|
||||||
|
c->client->save(rdx);
|
||||||
|
moveRR(c, BytesPerWord, &ah, &dx);
|
||||||
|
}
|
||||||
|
|
||||||
|
negateR(c, 4, &ax);
|
||||||
|
addCarryCR(c, 4, &zero, &dx);
|
||||||
|
negateR(c, 4, &dx);
|
||||||
|
|
||||||
|
if (a->high != rdx) {
|
||||||
|
moveRR(c, BytesPerWord, &dx, a);
|
||||||
|
c->client->restore(rdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->low != rax) {
|
||||||
|
moveRR(c, BytesPerWord, &ax, a);
|
||||||
|
c->client->restore(rax);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xd8 | a->low);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -559,18 +618,31 @@ leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
moveCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
int64_t v = a->value->value();
|
||||||
|
|
||||||
rex(c, 0x48, b->low);
|
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||||
c->code.append(0xb8 | b->low);
|
Assembler::Constant ah(&high);
|
||||||
if (a->value->resolved()) {
|
|
||||||
c->code.appendAddress(a->value->value());
|
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||||
|
Assembler::Constant al(&low);
|
||||||
|
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
moveCR(c, 4, &al, b);
|
||||||
|
moveCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
appendImmediateTask(c, a->value, c->code.length());
|
rex(c, 0x48, b->low);
|
||||||
c->code.appendAddress(static_cast<uintptr_t>(0));
|
c->code.append(0xb8 | b->low);
|
||||||
|
if (a->value->resolved()) {
|
||||||
|
c->code.appendAddress(a->value->value());
|
||||||
|
} else {
|
||||||
|
appendImmediateTask(c, a->value, c->code.length());
|
||||||
|
c->code.appendAddress(static_cast<uintptr_t>(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,10 +701,25 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
} else {
|
} else {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
rex(c);
|
if (BytesPerWord == 4 and a->low > rbx) {
|
||||||
c->code.append(0x0f);
|
if (b->low > rbx) {
|
||||||
c->code.append(0xbe);
|
c->client->save(rax);
|
||||||
c->code.append(0xc0 | (b->low << 3) | a->low);
|
|
||||||
|
Assembler::Register ax(rax);
|
||||||
|
moveRR(c, BytesPerWord, a, &ax);
|
||||||
|
moveRR(c, 1, &ax, b);
|
||||||
|
|
||||||
|
c->client->restore(rax);
|
||||||
|
} else {
|
||||||
|
moveRR(c, BytesPerWord, a, b);
|
||||||
|
moveRR(c, 1, b, b);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0xbe);
|
||||||
|
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@ -674,10 +761,13 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (a->low > rbx) {
|
if (a->low > rbx) {
|
||||||
Assembler::Register ax(c->client->acquireTemporary(rax));
|
c->client->save(rax);
|
||||||
|
|
||||||
|
Assembler::Register ax(rax);
|
||||||
moveRR(c, BytesPerWord, a, &ax);
|
moveRR(c, BytesPerWord, a, &ax);
|
||||||
moveRM(c, 1, &ax, b);
|
moveRM(c, 1, &ax, b);
|
||||||
c->client->releaseTemporary(ax.low);
|
|
||||||
|
c->client->restore(rax);
|
||||||
} else {
|
} else {
|
||||||
encode(c, 0x88, a->low, b, false);
|
encode(c, 0x88, a->low, b, false);
|
||||||
}
|
}
|
||||||
@ -709,15 +799,32 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
|||||||
if (a->low == rax and b->low == rax and b->high == rdx) {
|
if (a->low == rax and b->low == rax and b->high == rdx) {
|
||||||
c->code.append(0x99); // cdq
|
c->code.append(0x99); // cdq
|
||||||
} else {
|
} else {
|
||||||
Assembler::Register axdx(c->client->acquireTemporary(rax),
|
Assembler::Register axdx(rax, rdx);
|
||||||
c->client->acquireTemporary(rdx));
|
Assembler::Register dx(rdx);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
bool saveAX = a->low != rax and b->low != rax and b->high != rax;
|
||||||
|
bool saveDX = b->low != rdx and b->high != rdx;
|
||||||
|
|
||||||
|
if (saveDX) c->client->save(rdx);
|
||||||
|
if (saveAX) c->client->save(rax);
|
||||||
|
|
||||||
|
if (a->low != rax) {
|
||||||
|
moveRR(c, 4, a, &axdx);
|
||||||
|
}
|
||||||
|
|
||||||
moveRR(c, 4, a, &axdx);
|
|
||||||
move4To8RR(c, 0, &axdx, &axdx);
|
move4To8RR(c, 0, &axdx, &axdx);
|
||||||
moveRR(c, 8, &axdx, b);
|
|
||||||
|
|
||||||
c->client->releaseTemporary(axdx.low);
|
if (b->low != rax) {
|
||||||
c->client->releaseTemporary(axdx.high);
|
moveRR(c, 4, &axdx, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->high != rdx) {
|
||||||
|
moveRR(c, 4, &dx, &bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAX) c->client->restore(rax);
|
||||||
|
if (saveDX) c->client->restore(rdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -803,15 +910,29 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
|||||||
if (BytesPerWord == 8) {
|
if (BytesPerWord == 8) {
|
||||||
encode(c, 0x63, b->low, a, true);
|
encode(c, 0x63, b->low, a, true);
|
||||||
} else {
|
} else {
|
||||||
Assembler::Register axdx(c->client->acquireTemporary(rax),
|
Assembler::Register axdx(rax, rdx);
|
||||||
c->client->acquireTemporary(rdx));
|
Assembler::Register dx(rdx);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
bool saveAX = b->low != rax and b->high != rax;
|
||||||
|
bool saveDX = b->low != rdx and b->high != rdx;
|
||||||
|
|
||||||
|
if (saveDX) c->client->save(rdx);
|
||||||
|
if (saveAX) c->client->save(rax);
|
||||||
|
|
||||||
moveMR(c, 4, a, &axdx);
|
moveMR(c, 4, a, &axdx);
|
||||||
move4To8RR(c, 0, &axdx, &axdx);
|
move4To8RR(c, 0, &axdx, &axdx);
|
||||||
moveRR(c, 8, &axdx, b);
|
|
||||||
|
|
||||||
c->client->releaseTemporary(axdx.low);
|
if (b->low != rax) {
|
||||||
c->client->releaseTemporary(axdx.high);
|
moveRR(c, 4, &axdx, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->high != rdx) {
|
||||||
|
moveRR(c, 4, &dx, &bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAX) c->client->restore(rax);
|
||||||
|
if (saveDX) c->client->restore(rdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,25 +988,52 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
subtractBorrowCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
|
int64_t v = a->value->value();
|
||||||
|
if (isInt8(v)) {
|
||||||
|
c->code.append(0x83);
|
||||||
|
c->code.append(0xd8 | b->low);
|
||||||
|
c->code.append(v);
|
||||||
|
} else {
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
|
||||||
|
|
||||||
int64_t v = a->value->value();
|
int64_t v = a->value->value();
|
||||||
if (v) {
|
if (v) {
|
||||||
rex(c);
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
if (isInt8(v)) {
|
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||||
c->code.append(0x83);
|
Assembler::Constant ah(&high);
|
||||||
c->code.append(0xe8 | b->low);
|
|
||||||
c->code.append(v);
|
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||||
} else if (isInt32(v)) {
|
Assembler::Constant al(&low);
|
||||||
c->code.append(0x81);
|
|
||||||
c->code.append(0xe8 | b->low);
|
Assembler::Register bh(b->high);
|
||||||
c->code.append4(v);
|
|
||||||
|
subtractCR(c, 4, &al, b);
|
||||||
|
subtractBorrowCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
abort(c);
|
rex(c);
|
||||||
|
if (isInt8(v)) {
|
||||||
|
c->code.append(0x83);
|
||||||
|
c->code.append(0xe8 | b->low);
|
||||||
|
c->code.append(v);
|
||||||
|
} else if (isInt32(v)) {
|
||||||
|
c->code.append(0x81);
|
||||||
|
c->code.append(0xe8 | b->low);
|
||||||
|
c->code.append4(v);
|
||||||
|
} else {
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -902,14 +1050,31 @@ subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
addCarryRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x11);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
addRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
rex(c);
|
addRR(c, 4, a, b);
|
||||||
c->code.append(0x01);
|
addCarryRR(c, 4, &ah, &bh);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
} else {
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x01);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -966,16 +1131,21 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
abort(c); // todo: sync stack first
|
Assembler::Register axdx(rax, rdx);
|
||||||
|
Assembler::Register dx(rdx);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
Assembler::Register axdx(c->client->acquireTemporary(rax),
|
bool saveAX = b->low != rax and b->high != rax;
|
||||||
c->client->acquireTemporary(rdx));
|
bool saveDX = b->low != rdx and b->high != rdx;
|
||||||
|
|
||||||
|
if (saveDX) c->client->save(rdx);
|
||||||
|
if (saveAX) c->client->save(rax);
|
||||||
|
|
||||||
pushR(c, size, a);
|
pushR(c, size, a);
|
||||||
pushR(c, size, b);
|
pushR(c, size, b);
|
||||||
|
|
||||||
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(divideLong));
|
Assembler::Constant address
|
||||||
Assembler::Constant address(&addressPromise);
|
(resolved(c, reinterpret_cast<intptr_t>(divideLong)));
|
||||||
callC(c, BytesPerWord, &address);
|
callC(c, BytesPerWord, &address);
|
||||||
|
|
||||||
ResolvedPromise offsetPromise(16);
|
ResolvedPromise offsetPromise(16);
|
||||||
@ -983,24 +1153,29 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
Assembler::Register stack(rsp);
|
Assembler::Register stack(rsp);
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
addCR(c, BytesPerWord, &offset, &stack);
|
||||||
|
|
||||||
moveRR(c, size, &axdx, b);
|
if (b->low != rax) {
|
||||||
|
moveRR(c, 4, &axdx, b);
|
||||||
|
}
|
||||||
|
|
||||||
c->client->releaseTemporary(axdx.low);
|
if (b->high != rdx) {
|
||||||
c->client->releaseTemporary(axdx.high);
|
moveRR(c, 4, &dx, &bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAX) c->client->restore(rax);
|
||||||
|
if (saveDX) c->client->restore(rdx);
|
||||||
} else {
|
} else {
|
||||||
Assembler::Register ax(rax);
|
Assembler::Register ax(rax);
|
||||||
Assembler::Register divisor(a->low);
|
Assembler::Register divisor(a->low);
|
||||||
|
|
||||||
if (a->low == rdx) {
|
if (a->low == rdx) {
|
||||||
divisor.low = c->client->acquireTemporary();
|
divisor.low = c->client->acquireTemporary();
|
||||||
moveRR(c, BytesPerWord, a, &divisor);
|
moveRR(c, BytesPerWord, a, &divisor);
|
||||||
} else if (b->low != rdx) {
|
} else if (b->low != rdx) {
|
||||||
c->client->save(rdx);
|
c->client->save(rdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b->low != rax) {
|
if (b->low != rax) {
|
||||||
c->client->save(rax);
|
c->client->save(rax);
|
||||||
c->client->acquireTemporary(rax);
|
|
||||||
moveRR(c, BytesPerWord, b, &ax);
|
moveRR(c, BytesPerWord, b, &ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,7 +1187,6 @@ divideRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
|
|
||||||
if (b->low != rax) {
|
if (b->low != rax) {
|
||||||
moveRR(c, BytesPerWord, &ax, b);
|
moveRR(c, BytesPerWord, &ax, b);
|
||||||
c->client->releaseTemporary(rax);
|
|
||||||
c->client->restore(rax);
|
c->client->restore(rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,16 +1216,21 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
abort(c); // todo: sync stack first
|
Assembler::Register axdx(rax, rdx);
|
||||||
|
Assembler::Register dx(rdx);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
Assembler::Register axdx(c->client->acquireTemporary(rax),
|
bool saveAX = b->low != rax and b->high != rax;
|
||||||
c->client->acquireTemporary(rdx));
|
bool saveDX = b->low != rdx and b->high != rdx;
|
||||||
|
|
||||||
|
if (saveDX) c->client->save(rdx);
|
||||||
|
if (saveAX) c->client->save(rax);
|
||||||
|
|
||||||
pushR(c, size, a);
|
pushR(c, size, a);
|
||||||
pushR(c, size, b);
|
pushR(c, size, b);
|
||||||
|
|
||||||
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(moduloLong));
|
Assembler::Constant address
|
||||||
Assembler::Constant address(&addressPromise);
|
(resolved(c, reinterpret_cast<intptr_t>(moduloLong)));
|
||||||
callC(c, BytesPerWord, &address);
|
callC(c, BytesPerWord, &address);
|
||||||
|
|
||||||
ResolvedPromise offsetPromise(16);
|
ResolvedPromise offsetPromise(16);
|
||||||
@ -1059,10 +1238,16 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
Assembler::Register stack(rsp);
|
Assembler::Register stack(rsp);
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
addCR(c, BytesPerWord, &offset, &stack);
|
||||||
|
|
||||||
moveRR(c, size, &axdx, b);
|
if (b->low != rax) {
|
||||||
|
moveRR(c, 4, &axdx, b);
|
||||||
|
}
|
||||||
|
|
||||||
c->client->releaseTemporary(axdx.low);
|
if (b->high != rdx) {
|
||||||
c->client->releaseTemporary(axdx.high);
|
moveRR(c, 4, &dx, &bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAX) c->client->restore(rax);
|
||||||
|
if (saveDX) c->client->restore(rdx);
|
||||||
} else {
|
} else {
|
||||||
Assembler::Register ax(rax);
|
Assembler::Register ax(rax);
|
||||||
Assembler::Register dx(rdx);
|
Assembler::Register dx(rdx);
|
||||||
@ -1077,7 +1262,6 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
|
|
||||||
if (b->low != rax) {
|
if (b->low != rax) {
|
||||||
c->client->save(rax);
|
c->client->save(rax);
|
||||||
c->client->acquireTemporary(rax);
|
|
||||||
moveRR(c, BytesPerWord, b, &ax);
|
moveRR(c, BytesPerWord, b, &ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1089,7 +1273,9 @@ remainderRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
|
|
||||||
if (b->low != rdx) {
|
if (b->low != rdx) {
|
||||||
moveRR(c, BytesPerWord, &dx, b);
|
moveRR(c, BytesPerWord, &dx, b);
|
||||||
c->client->releaseTemporary(rax);
|
}
|
||||||
|
|
||||||
|
if (b->low != rax) {
|
||||||
c->client->restore(rax);
|
c->client->restore(rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1215,10 +1401,25 @@ shift(Context* c, int type, Assembler::Register* a, Assembler::Register* b) {
|
|||||||
c->code.append(0xd3);
|
c->code.append(0xd3);
|
||||||
c->code.append(type | b->low);
|
c->code.append(type | b->low);
|
||||||
} else {
|
} else {
|
||||||
Assembler::Register cx(c->client->acquireTemporary(rcx));
|
Assembler::Register target(b->low);
|
||||||
|
|
||||||
|
if (b->low == rcx) {
|
||||||
|
target.low = c->client->acquireTemporary();
|
||||||
|
moveRR(c, BytesPerWord, b, &target);
|
||||||
|
} else {
|
||||||
|
c->client->save(rcx);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assembler::Register cx(rcx);
|
||||||
moveRR(c, BytesPerWord, a, &cx);
|
moveRR(c, BytesPerWord, a, &cx);
|
||||||
shift(c, type, &cx, b);
|
shift(c, type, &cx, b);
|
||||||
c->client->releaseTemporary(cx.low);
|
|
||||||
|
if (b->low == rcx) {
|
||||||
|
moveRR(c, BytesPerWord, &target, b);
|
||||||
|
c->client->releaseTemporary(target.low);
|
||||||
|
} else {
|
||||||
|
c->client->restore(rcx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,19 +1547,39 @@ compareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
compareCM(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
Assembler::Memory* b)
|
Assembler::Memory* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4);
|
int64_t v = a->value->value();
|
||||||
|
|
||||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||||
|
Assembler::Constant al(&low);
|
||||||
|
|
||||||
if (isInt8(a->value->value())) {
|
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||||
c->code.append(a->value->value());
|
Assembler::Constant ah(&high);
|
||||||
} else if (isInt32(a->value->value())) {
|
|
||||||
c->code.append4(a->value->value());
|
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
|
||||||
|
|
||||||
|
compareCM(c, 4, &ah, &bh);
|
||||||
|
|
||||||
|
// if the high order bits are equal, we compare the low order
|
||||||
|
// bits; otherwise, we jump past that comparison
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0x85); // jne
|
||||||
|
c->code.append4(2);
|
||||||
|
|
||||||
|
compareCM(c, 4, &al, b);
|
||||||
} else {
|
} else {
|
||||||
abort(c);
|
encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true);
|
||||||
|
|
||||||
|
if (isInt8(v)) {
|
||||||
|
c->code.append(v);
|
||||||
|
} else if (isInt32(v)) {
|
||||||
|
c->code.append4(v);
|
||||||
|
} else {
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1557,22 +1778,26 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getTargets(UnaryOperation /*op*/, unsigned /*size*/,
|
virtual void getTargets(BinaryOperation op, unsigned size,
|
||||||
Register* r)
|
Register* a, Register* b, bool* syncStack)
|
||||||
{
|
{
|
||||||
// todo
|
|
||||||
r->low = NoRegister;
|
|
||||||
r->high = NoRegister;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void getTargets(BinaryOperation /*op*/, unsigned /*size*/,
|
|
||||||
Register* a, Register* b)
|
|
||||||
{
|
|
||||||
// todo
|
|
||||||
a->low = NoRegister;
|
a->low = NoRegister;
|
||||||
a->high = NoRegister;
|
a->high = NoRegister;
|
||||||
b->low = NoRegister;
|
b->low = NoRegister;
|
||||||
b->high = NoRegister;
|
b->high = NoRegister;
|
||||||
|
*syncStack = false;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case Divide:
|
||||||
|
case Remainder:
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
*syncStack = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Operation op) {
|
virtual void apply(Operation op) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user