mirror of
https://github.com/corda/corda.git
synced 2025-01-22 12:28:11 +00:00
remove operand marshalling from the assembler in favor of doing it in the compiler
This commit is contained in:
parent
7b809efd3f
commit
2e108861da
@ -156,8 +156,12 @@ 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(BinaryOperation op, unsigned size,
|
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
||||||
Register* a, Register* b, bool* syncStack) = 0;
|
uint64_t* registerMask, uintptr_t* procedure);
|
||||||
|
|
||||||
|
virtual void plan(UnaryOperation op, unsigned size, uint8_t* aTypeMask,
|
||||||
|
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
||||||
|
uint64_t* bRegisterMask, uintptr_t* procedure);
|
||||||
|
|
||||||
virtual void apply(Operation op) = 0;
|
virtual void apply(Operation op) = 0;
|
||||||
|
|
||||||
|
703
src/x86.cpp
703
src/x86.cpp
@ -35,12 +35,6 @@ enum {
|
|||||||
r15 = 15,
|
r15 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
int64_t FORCE_ALIGN
|
|
||||||
multiplyLong(int64_t a, int64_t b)
|
|
||||||
{
|
|
||||||
return a * b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t FORCE_ALIGN
|
int64_t FORCE_ALIGN
|
||||||
divideLong(int64_t a, int64_t b)
|
divideLong(int64_t a, int64_t b)
|
||||||
{
|
{
|
||||||
@ -589,106 +583,33 @@ xorRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
void
|
void
|
||||||
swap(Context* c, Assembler::Register* a, Assembler::Register* b)
|
swap(Context* c, Assembler::Register* a, Assembler::Register* b)
|
||||||
{
|
{
|
||||||
|
// todo: use xchg instead
|
||||||
xorRR(c, 4, a, b);
|
xorRR(c, 4, a, b);
|
||||||
xorRR(c, 4, b, b);
|
xorRR(c, 4, b, b);
|
||||||
xorRR(c, 4, a, b);
|
xorRR(c, 4, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
marshal(Context* c, int sl, int sh, int dl, int dh)
|
|
||||||
{
|
|
||||||
Assembler::Register slr(sl);
|
|
||||||
Assembler::Register shr(sh);
|
|
||||||
Assembler::Register dlr(dl);
|
|
||||||
Assembler::Register dhr(dh);
|
|
||||||
|
|
||||||
if (sl == dl or sh == dh) {
|
|
||||||
if (sl != dl) {
|
|
||||||
c->client->save(dl);
|
|
||||||
moveRR(c, BytesPerWord, &slr, &dlr);
|
|
||||||
} else if (sh != dh) {
|
|
||||||
c->client->save(dh);
|
|
||||||
moveRR(c, BytesPerWord, &shr, &dhr);
|
|
||||||
}
|
|
||||||
} else if (sl == dh or sh == dl) {
|
|
||||||
swap(c, &slr, &shr);
|
|
||||||
|
|
||||||
if (sl != dh) {
|
|
||||||
c->client->save(dh);
|
|
||||||
moveRR(c, BytesPerWord, &slr, &dhr);
|
|
||||||
} else if (sh != dl) {
|
|
||||||
c->client->save(dl);
|
|
||||||
moveRR(c, BytesPerWord, &shr, &dlr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c->client->save(dl);
|
|
||||||
moveRR(c, BytesPerWord, &slr, &dlr);
|
|
||||||
|
|
||||||
c->client->save(dh);
|
|
||||||
moveRR(c, BytesPerWord, &shr, &dhr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unmarshal(Context* c, int sl, int sh, int dl, int dh)
|
|
||||||
{
|
|
||||||
Assembler::Register slr(sl);
|
|
||||||
Assembler::Register shr(sh);
|
|
||||||
Assembler::Register dlr(dl);
|
|
||||||
Assembler::Register dhr(dh);
|
|
||||||
|
|
||||||
if (sl == dl or sh == dh) {
|
|
||||||
if (sl != dl) {
|
|
||||||
moveRR(c, BytesPerWord, &slr, &dlr);
|
|
||||||
c->client->restore(sl);
|
|
||||||
} else if (sh != dh) {
|
|
||||||
moveRR(c, BytesPerWord, &shr, &dhr);
|
|
||||||
c->client->restore(sh);
|
|
||||||
}
|
|
||||||
} else if (sl == dh or sh == dl) {
|
|
||||||
if (sl != dh) {
|
|
||||||
moveRR(c, BytesPerWord, &slr, &dhr);
|
|
||||||
c->client->restore(sh);
|
|
||||||
} else if (sh != dl) {
|
|
||||||
moveRR(c, BytesPerWord, &shr, &dlr);
|
|
||||||
c->client->restore(sl);
|
|
||||||
}
|
|
||||||
|
|
||||||
swap(c, &dlr, &dhr);
|
|
||||||
} else {
|
|
||||||
moveRR(c, BytesPerWord, &slr, &dlr);
|
|
||||||
c->client->restore(sl);
|
|
||||||
|
|
||||||
moveRR(c, BytesPerWord, &shr, &dhr);
|
|
||||||
c->client->restore(sh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
negateR(Context* c, unsigned size, Assembler::Register* a)
|
negateR(Context* c, unsigned size, Assembler::Register* a)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
Assembler::Register ax(rax);
|
assert(c, a->low == rax and a->high == rdx);
|
||||||
Assembler::Register dx(rdx);
|
|
||||||
|
|
||||||
ResolvedPromise zeroPromise(0);
|
ResolvedPromise zeroPromise(0);
|
||||||
Assembler::Constant zero(&zeroPromise);
|
Assembler::Constant zero(&zeroPromise);
|
||||||
|
|
||||||
marshal(c, a->low, a->high, rax, rdx);
|
Assembler::Register ah(a->high);
|
||||||
|
|
||||||
negateR(c, 4, &ax);
|
negateR(c, 4, a);
|
||||||
addCarryCR(c, 4, &zero, &dx);
|
addCarryCR(c, 4, &zero, &ah);
|
||||||
negateR(c, 4, &dx);
|
negateR(c, 4, &ah);
|
||||||
|
|
||||||
unmarshal(c, rax, rdx, a->low, a->high);
|
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0xf7);
|
c->code.append(0xf7);
|
||||||
c->code.append(0xd8 | a->low);
|
c->code.append(0xd8 | a->low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
|
leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
|
||||||
{
|
{
|
||||||
@ -785,25 +706,12 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
} else {
|
} else {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
if (BytesPerWord == 4 and a->low > rbx) {
|
assert(c, BytesPerWord == 8 or (a->low <= rbx and b->low <= rbx));
|
||||||
if (b->low > rbx) {
|
|
||||||
c->client->save(rax);
|
|
||||||
|
|
||||||
Assembler::Register ax(rax);
|
rex(c);
|
||||||
moveRR(c, BytesPerWord, a, &ax);
|
c->code.append(0x0f);
|
||||||
moveRR(c, 1, &ax, b);
|
c->code.append(0xbe);
|
||||||
|
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||||
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:
|
||||||
@ -844,17 +752,9 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
|||||||
encode(c, 0x88, a->low, b, false);
|
encode(c, 0x88, a->low, b, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (a->low > rbx) {
|
assert(c, a->low <= rbx);
|
||||||
c->client->save(rax);
|
|
||||||
|
|
||||||
Assembler::Register ax(rax);
|
encode(c, 0x88, a->low, b, false);
|
||||||
moveRR(c, BytesPerWord, a, &ax);
|
|
||||||
moveRM(c, 1, &ax, b);
|
|
||||||
|
|
||||||
c->client->restore(rax);
|
|
||||||
} else {
|
|
||||||
encode(c, 0x88, a->low, b, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -872,31 +772,7 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
move(Context* c, int sl, int sh, int dl, int dh)
|
move4To8RR(Context* c, unsigned, Assembler::Register* a,
|
||||||
{
|
|
||||||
Assembler::Register slr(sl);
|
|
||||||
Assembler::Register shr(sh);
|
|
||||||
Assembler::Register dlr(dl);
|
|
||||||
Assembler::Register dhr(dh);
|
|
||||||
|
|
||||||
if (sl == dh and sh == dl) {
|
|
||||||
swap(c, &slr, &shr);
|
|
||||||
} else {
|
|
||||||
if (sl != dl) {
|
|
||||||
if (sh == dl) {
|
|
||||||
moveRR(c, 4, &shr, &dhr);
|
|
||||||
}
|
|
||||||
moveRR(c, 4, &slr, &dlr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sh != dh and sh != dl) {
|
|
||||||
moveRR(c, 4, &shr, &dhr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 8) {
|
if (BytesPerWord == 8) {
|
||||||
@ -907,26 +783,10 @@ 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(rax, rdx);
|
assert(c, b->low == rax and b->high == rdx);
|
||||||
Assembler::Register dx(rdx);
|
|
||||||
Assembler::Register bh(b->high);
|
|
||||||
|
|
||||||
bool saveAX = a->low != rax and b->low != rax and b->high != rax;
|
moveRR(c, 4, a, b);
|
||||||
bool saveDX = b->low != rdx and b->high != rdx;
|
move4To8RR(c, 0, b, b);
|
||||||
|
|
||||||
if (saveDX) c->client->save(rdx);
|
|
||||||
if (saveAX) c->client->save(rax);
|
|
||||||
|
|
||||||
if (a->low != rax) {
|
|
||||||
moveRR(c, 4, a, &axdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
move4To8RR(c, 0, &axdx, &axdx);
|
|
||||||
|
|
||||||
move(c, rax, rdx, b->low, b->high);
|
|
||||||
|
|
||||||
if (saveAX) c->client->restore(rax);
|
|
||||||
if (saveDX) c->client->restore(rdx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1012,23 +872,10 @@ 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(rax, rdx);
|
assert(c, b->low == rax and b->high == rdx);
|
||||||
Assembler::Register dx(rdx);
|
|
||||||
Assembler::Register bh(b->high);
|
|
||||||
|
|
||||||
bool saveAX = b->low != rax and b->high != rax;
|
moveMR(c, 4, a, b);
|
||||||
bool saveDX = b->low != rdx and b->high != rdx;
|
move4To8RR(c, 0, b, b);
|
||||||
|
|
||||||
if (saveDX) c->client->save(rdx);
|
|
||||||
if (saveAX) c->client->save(rax);
|
|
||||||
|
|
||||||
moveMR(c, 4, a, &axdx);
|
|
||||||
move4To8RR(c, 0, &axdx, &axdx);
|
|
||||||
|
|
||||||
move(c, rax, rdx, b->low, b->high);
|
|
||||||
|
|
||||||
if (saveAX) c->client->restore(rax);
|
|
||||||
if (saveDX) c->client->restore(rdx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1079,7 +926,7 @@ addCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
addCR(c, 4, &al, b);
|
addCR(c, 4, &al, b);
|
||||||
addCarryCR(c, 4, &ah, &bh);
|
addCarryCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x83);
|
c->code.append(0x83);
|
||||||
c->code.append(0xc0 | b->low);
|
c->code.append(0xc0 | b->low);
|
||||||
@ -1129,7 +976,7 @@ subtractCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
subtractCR(c, 4, &al, b);
|
subtractCR(c, 4, &al, b);
|
||||||
subtractBorrowCR(c, 4, &ah, &bh);
|
subtractBorrowCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x83);
|
c->code.append(0x83);
|
||||||
c->code.append(0xe8 | b->low);
|
c->code.append(0xe8 | b->low);
|
||||||
@ -1146,23 +993,23 @@ subtractCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
subtractRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
subtractRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x29);
|
c->code.append(0x29);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addCarryRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
addCarryRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4);
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x11);
|
c->code.append(0x11);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
}
|
}
|
||||||
@ -1178,7 +1025,7 @@ addRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
addRR(c, 4, a, b);
|
addRR(c, 4, a, b);
|
||||||
addCarryRR(c, 4, &ah, &bh);
|
addCarryRR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x01);
|
c->code.append(0x01);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
}
|
}
|
||||||
@ -1198,22 +1045,32 @@ multiplyRR(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) {
|
||||||
pushR(c, size, a);
|
assert(c, b->high == rdx);
|
||||||
pushR(c, size, b);
|
assert(c, b->low != rax);
|
||||||
|
assert(c, a->low != rax);
|
||||||
Assembler::Constant address
|
assert(c, a->high != rax);
|
||||||
(resolved(c, reinterpret_cast<intptr_t>(multiplyLong)));
|
|
||||||
callC(c, BytesPerWord, &address);
|
c->client->save(rax);
|
||||||
|
|
||||||
Assembler::Register axdx(rax, rdx);
|
Assembler::Register axdx(rax, rdx);
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
Assembler::Register bh(b->high);
|
||||||
|
|
||||||
|
moveRR(c, 4, b, &axdx);
|
||||||
|
multiplyRR(c, 4, &ah, b);
|
||||||
|
multiplyRR(c, 4, a, &bh);
|
||||||
|
addRR(c, 4, &bh, b);
|
||||||
|
|
||||||
|
// mul a->low,%eax%edx
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xe8 | a->low);
|
||||||
|
|
||||||
|
addRR(c, 4, b, &bh);
|
||||||
moveRR(c, 4, &axdx, b);
|
moveRR(c, 4, &axdx, b);
|
||||||
|
|
||||||
ResolvedPromise offsetPromise(16);
|
c->client->restore(rax);
|
||||||
Assembler::Constant offset(&offsetPromise);
|
|
||||||
Assembler::Register stack(rsp);
|
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x0f);
|
c->code.append(0x0f);
|
||||||
c->code.append(0xaf);
|
c->code.append(0xaf);
|
||||||
c->code.append(0xc0 | (b->low << 3) | a->low);
|
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||||
@ -1224,26 +1081,23 @@ void
|
|||||||
multiplyCR(Context* c, unsigned size, Assembler::Constant* a,
|
multiplyCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
pushC(c, size, a);
|
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||||
pushR(c, size, b);
|
Assembler::Register tmp(c->client->acquireTemporary(mask),
|
||||||
|
c->client->acquireTemporary(mask));
|
||||||
Assembler::Constant address
|
|
||||||
(resolved(c, reinterpret_cast<intptr_t>(multiplyLong)));
|
|
||||||
callC(c, BytesPerWord, &address);
|
|
||||||
|
|
||||||
Assembler::Register axdx(rax, rdx);
|
moveCR(c, size, a, &tmp);
|
||||||
moveRR(c, 4, &axdx, b);
|
remainderRR(c, size, &tmp, b);
|
||||||
|
|
||||||
ResolvedPromise offsetPromise(16);
|
c->client->releaseTemporary(tmp.low);
|
||||||
Assembler::Constant offset(&offsetPromise);
|
c->client->releaseTemporary(tmp.high);
|
||||||
Assembler::Register stack(rsp);
|
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
|
||||||
} else {
|
} else {
|
||||||
int64_t v = a->value->value();
|
int64_t v = a->value->value();
|
||||||
if (v) {
|
if (v) {
|
||||||
if (isInt32(v)) {
|
if (isInt32(v)) {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x6b);
|
c->code.append(0x6b);
|
||||||
c->code.append(0xc0 | (b->low << 3) | b->low);
|
c->code.append(0xc0 | (b->low << 3) | b->low);
|
||||||
@ -1267,68 +1121,30 @@ void
|
|||||||
divideRR(Context* c, unsigned size, Assembler::Register* a,
|
divideRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
pushR(c, size, a);
|
|
||||||
pushR(c, size, b);
|
assert(c, b->low == rax);
|
||||||
|
assert(c, a->low != rdx);
|
||||||
|
|
||||||
|
c->client->save(rdx);
|
||||||
|
|
||||||
Assembler::Constant address
|
if (size == 8) rex(c);
|
||||||
(resolved(c, reinterpret_cast<intptr_t>(divideLong)));
|
c->code.append(0x99); // cdq
|
||||||
callC(c, BytesPerWord, &address);
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xf8 | a->low);
|
||||||
|
|
||||||
Assembler::Register axdx(rax, rdx);
|
c->client->restore(rdx);
|
||||||
moveRR(c, 4, &axdx, b);
|
|
||||||
|
|
||||||
ResolvedPromise offsetPromise(16);
|
|
||||||
Assembler::Constant offset(&offsetPromise);
|
|
||||||
Assembler::Register stack(rsp);
|
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
|
||||||
} else {
|
|
||||||
Assembler::Register ax(rax);
|
|
||||||
Assembler::Register divisor(a->low);
|
|
||||||
|
|
||||||
if (a->low == rdx or a->low == rax) {
|
|
||||||
divisor.low = c->client->acquireTemporary();
|
|
||||||
moveRR(c, BytesPerWord, a, &divisor);
|
|
||||||
} else if (b->low != rdx) {
|
|
||||||
c->client->save(rdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b->low != rax) {
|
|
||||||
if (a->low != rax) {
|
|
||||||
c->client->save(rax);
|
|
||||||
}
|
|
||||||
moveRR(c, BytesPerWord, b, &ax);
|
|
||||||
}
|
|
||||||
|
|
||||||
rex(c);
|
|
||||||
c->code.append(0x99);
|
|
||||||
rex(c);
|
|
||||||
c->code.append(0xf7);
|
|
||||||
c->code.append(0xf8 | divisor.low);
|
|
||||||
|
|
||||||
if (b->low != rax) {
|
|
||||||
moveRR(c, BytesPerWord, &ax, b);
|
|
||||||
if (a->low != rax) {
|
|
||||||
c->client->restore(rax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a->low == rdx or a->low == rax) {
|
|
||||||
moveRR(c, BytesPerWord, &divisor, a);
|
|
||||||
c->client->releaseTemporary(divisor.low);
|
|
||||||
} else if (b->low != rdx) {
|
|
||||||
c->client->restore(rdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
divideCR(Context* c, unsigned size, Assembler::Constant* a,
|
divideCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
|
|
||||||
Assembler::Register tmp(c->client->acquireTemporary());
|
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||||
|
Assembler::Register tmp(c->client->acquireTemporary(mask));
|
||||||
moveCR(c, size, a, &tmp);
|
moveCR(c, size, a, &tmp);
|
||||||
divideRR(c, size, &tmp, b);
|
divideRR(c, size, &tmp, b);
|
||||||
c->client->releaseTemporary(tmp.low);
|
c->client->releaseTemporary(tmp.low);
|
||||||
@ -1338,88 +1154,36 @@ void
|
|||||||
remainderRR(Context* c, unsigned size, Assembler::Register* a,
|
remainderRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
pushR(c, size, a);
|
|
||||||
pushR(c, size, b);
|
assert(c, b->low == rax);
|
||||||
|
assert(c, a->low != rdx);
|
||||||
|
|
||||||
|
c->client->save(rdx);
|
||||||
|
|
||||||
Assembler::Constant address
|
if (size == 8) rex(c);
|
||||||
(resolved(c, reinterpret_cast<intptr_t>(moduloLong)));
|
c->code.append(0x99); // cdq
|
||||||
callC(c, BytesPerWord, &address);
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0xf7);
|
||||||
|
c->code.append(0xf8 | a->low);
|
||||||
|
|
||||||
Assembler::Register axdx(rax, rdx);
|
Assembler::Register dx(rdx);
|
||||||
moveRR(c, 4, &axdx, b);
|
moveRR(c, BytesPerWord, &dx, b);
|
||||||
|
|
||||||
ResolvedPromise offsetPromise(16);
|
c->client->restore(rdx);
|
||||||
Assembler::Constant offset(&offsetPromise);
|
|
||||||
Assembler::Register stack(rsp);
|
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
|
||||||
} else {
|
|
||||||
Assembler::Register ax(rax);
|
|
||||||
Assembler::Register dx(rdx);
|
|
||||||
Assembler::Register divisor(a->low);
|
|
||||||
|
|
||||||
if (a->low == rdx or a->low == rax) {
|
|
||||||
divisor.low = c->client->acquireTemporary();
|
|
||||||
moveRR(c, BytesPerWord, a, &divisor);
|
|
||||||
} else if (b->low != rdx) {
|
|
||||||
c->client->save(rdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b->low != rax) {
|
|
||||||
if (a->low != rax) {
|
|
||||||
c->client->save(rax);
|
|
||||||
}
|
|
||||||
moveRR(c, BytesPerWord, b, &ax);
|
|
||||||
}
|
|
||||||
|
|
||||||
rex(c);
|
|
||||||
c->code.append(0x99);
|
|
||||||
rex(c);
|
|
||||||
c->code.append(0xf7);
|
|
||||||
c->code.append(0xf8 | divisor.low);
|
|
||||||
|
|
||||||
if (b->low != rdx) {
|
|
||||||
moveRR(c, BytesPerWord, &dx, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b->low != rax and a->low != rax) {
|
|
||||||
c->client->restore(rax);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a->low == rdx or a->low == rax) {
|
|
||||||
moveRR(c, BytesPerWord, &divisor, a);
|
|
||||||
c->client->releaseTemporary(divisor.low);
|
|
||||||
} else if (b->low != rdx) {
|
|
||||||
c->client->restore(rdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
remainderCR(Context* c, unsigned size, Assembler::Constant* a,
|
remainderCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
assert(c, BytesPerWord == 8 or size == 4);
|
||||||
pushC(c, size, a);
|
|
||||||
pushR(c, size, b);
|
|
||||||
|
|
||||||
Assembler::Constant address
|
|
||||||
(resolved(c, reinterpret_cast<intptr_t>(moduloLong)));
|
|
||||||
callC(c, BytesPerWord, &address);
|
|
||||||
|
|
||||||
Assembler::Register axdx(rax, rdx);
|
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||||
moveRR(c, 4, &axdx, b);
|
Assembler::Register tmp(c->client->acquireTemporary(mask));
|
||||||
|
moveCR(c, size, a, &tmp);
|
||||||
ResolvedPromise offsetPromise(16);
|
remainderRR(c, size, &tmp, b);
|
||||||
Assembler::Constant offset(&offsetPromise);
|
c->client->releaseTemporary(tmp.low);
|
||||||
Assembler::Register stack(rsp);
|
|
||||||
addCR(c, BytesPerWord, &offset, &stack);
|
|
||||||
} else {
|
|
||||||
Assembler::Register tmp(c->client->acquireTemporary());
|
|
||||||
moveCR(c, size, a, &tmp);
|
|
||||||
remainderRR(c, size, &tmp, b);
|
|
||||||
c->client->releaseTemporary(tmp.low);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1433,7 +1197,7 @@ andRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
andRR(c, 4, a, b);
|
andRR(c, 4, a, b);
|
||||||
andRR(c, 4, &ah, &bh);
|
andRR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x21);
|
c->code.append(0x21);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
}
|
}
|
||||||
@ -1458,7 +1222,7 @@ andCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
andCR(c, 4, &ah, &bh);
|
andCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
if (isInt32(v)) {
|
if (isInt32(v)) {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x83);
|
c->code.append(0x83);
|
||||||
c->code.append(0xe0 | b->low);
|
c->code.append(0xe0 | b->low);
|
||||||
@ -1497,7 +1261,7 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
|||||||
|
|
||||||
void
|
void
|
||||||
orRR(Context* c, unsigned size, Assembler::Register* a,
|
orRR(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) {
|
||||||
Assembler::Register ah(a->high);
|
Assembler::Register ah(a->high);
|
||||||
@ -1506,7 +1270,7 @@ orRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
orRR(c, 4, a, b);
|
orRR(c, 4, a, b);
|
||||||
orRR(c, 4, &ah, &bh);
|
orRR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x09);
|
c->code.append(0x09);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
}
|
}
|
||||||
@ -1514,7 +1278,7 @@ orRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
|
|
||||||
void
|
void
|
||||||
orCR(Context* c, unsigned size, Assembler::Constant* a,
|
orCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
int64_t v = a->value->value();
|
int64_t v = a->value->value();
|
||||||
if (v) {
|
if (v) {
|
||||||
@ -1531,7 +1295,7 @@ orCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
orCR(c, 4, &ah, &bh);
|
orCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
if (isInt32(v)) {
|
if (isInt32(v)) {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x83);
|
c->code.append(0x83);
|
||||||
c->code.append(0xc8 | b->low);
|
c->code.append(0xc8 | b->low);
|
||||||
@ -1562,7 +1326,7 @@ xorRR(Context* c, unsigned size, Assembler::Register* a,
|
|||||||
xorRR(c, 4, a, b);
|
xorRR(c, 4, a, b);
|
||||||
xorRR(c, 4, &ah, &bh);
|
xorRR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
c->code.append(0x31);
|
c->code.append(0x31);
|
||||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
}
|
}
|
||||||
@ -1587,7 +1351,7 @@ xorCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
xorCR(c, 4, &ah, &bh);
|
xorCR(c, 4, &ah, &bh);
|
||||||
} else {
|
} else {
|
||||||
if (isInt32(v)) {
|
if (isInt32(v)) {
|
||||||
rex(c);
|
if (size == 8) rex(c);
|
||||||
if (isInt8(v)) {
|
if (isInt8(v)) {
|
||||||
c->code.append(0x83);
|
c->code.append(0x83);
|
||||||
c->code.append(0xf0 | b->low);
|
c->code.append(0xf0 | b->low);
|
||||||
@ -1607,38 +1371,6 @@ xorCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
doShift(Context* c, void (*shift)
|
|
||||||
(Context*, unsigned, Assembler::Register*, Assembler::Register*),
|
|
||||||
unsigned size, Assembler::Register* a, Assembler::Register* b)
|
|
||||||
{
|
|
||||||
Assembler::Register target(b->low, b->high);
|
|
||||||
|
|
||||||
if (b->low == rcx) {
|
|
||||||
target.low = c->client->acquireTemporary();
|
|
||||||
moveRR(c, BytesPerWord, b, &target);
|
|
||||||
} else if (b->high == rcx) {
|
|
||||||
target.high = c->client->acquireTemporary();
|
|
||||||
moveRR(c, BytesPerWord, b, &target);
|
|
||||||
} else {
|
|
||||||
c->client->save(rcx);
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembler::Register cx(rcx);
|
|
||||||
moveRR(c, BytesPerWord, a, &cx);
|
|
||||||
shift(c, size, &cx, &target);
|
|
||||||
|
|
||||||
if (b->low == rcx) {
|
|
||||||
moveRR(c, BytesPerWord, &target, b);
|
|
||||||
c->client->releaseTemporary(target.low);
|
|
||||||
} else if (b->high == rcx) {
|
|
||||||
moveRR(c, BytesPerWord, &target, b);
|
|
||||||
c->client->releaseTemporary(target.high);
|
|
||||||
} else {
|
|
||||||
c->client->restore(rcx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
doShift(Context* c, void (*shift)
|
doShift(Context* c, void (*shift)
|
||||||
(Context*, unsigned, Assembler::Register*, Assembler::Register*),
|
(Context*, unsigned, Assembler::Register*, Assembler::Register*),
|
||||||
@ -1676,37 +1408,35 @@ compareCR(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
|
|
||||||
void
|
void
|
||||||
shiftLeftRR(Context* c, unsigned size, Assembler::Register* a,
|
shiftLeftRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (a->low == rcx) {
|
assert(c, a->low == rcx);
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
|
||||||
// shld
|
|
||||||
c->code.append(0x0f);
|
|
||||||
c->code.append(0xa5);
|
|
||||||
c->code.append(0xc0 | (b->low << 3) | b->high);
|
|
||||||
|
|
||||||
// shl
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
c->code.append(0xd3);
|
// shld
|
||||||
c->code.append(0xe0 | b->low);
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0xa5);
|
||||||
|
c->code.append(0xc0 | (b->low << 3) | b->high);
|
||||||
|
|
||||||
ResolvedPromise promise(32);
|
// shl
|
||||||
Assembler::Constant constant(&promise);
|
c->code.append(0xd3);
|
||||||
compareCR(c, 4, &constant, a);
|
c->code.append(0xe0 | b->low);
|
||||||
|
|
||||||
c->code.append(0x0f);
|
ResolvedPromise promise(32);
|
||||||
c->code.append(0x8c); // jl
|
Assembler::Constant constant(&promise);
|
||||||
c->code.append4(2 + 2);
|
compareCR(c, 4, &constant, a);
|
||||||
|
|
||||||
Assembler::Register bh(b->high);
|
c->code.append(0x0f);
|
||||||
moveRR(c, 4, b, &bh); // 2 bytes
|
c->code.append(0x8c); // jl
|
||||||
xorRR(c, 4, b, b); // 2 bytes
|
c->code.append4(2 + 2);
|
||||||
} else {
|
|
||||||
if (size == 8) rex(c);
|
Assembler::Register bh(b->high);
|
||||||
c->code.append(0xd3);
|
moveRR(c, 4, b, &bh); // 2 bytes
|
||||||
c->code.append(0xe0 | b->low);
|
xorRR(c, 4, b, b); // 2 bytes
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
doShift(c, shiftLeftRR, size, a, b);
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0xd3);
|
||||||
|
c->code.append(0xe0 | b->low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1721,39 +1451,37 @@ void
|
|||||||
shiftRightRR(Context* c, unsigned size, Assembler::Register* a,
|
shiftRightRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (a->low == rcx) {
|
assert(c, a->low == rcx);
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
|
||||||
// shrd
|
|
||||||
c->code.append(0x0f);
|
|
||||||
c->code.append(0xad);
|
|
||||||
c->code.append(0xc0 | (b->high << 3) | b->low);
|
|
||||||
|
|
||||||
// sar
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
c->code.append(0xd3);
|
// shrd
|
||||||
c->code.append(0xf8 | b->high);
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0xad);
|
||||||
|
c->code.append(0xc0 | (b->high << 3) | b->low);
|
||||||
|
|
||||||
ResolvedPromise promise(32);
|
// sar
|
||||||
Assembler::Constant constant(&promise);
|
c->code.append(0xd3);
|
||||||
compareCR(c, 4, &constant, a);
|
c->code.append(0xf8 | b->high);
|
||||||
|
|
||||||
c->code.append(0x0f);
|
ResolvedPromise promise(32);
|
||||||
c->code.append(0x8c); // jl
|
Assembler::Constant constant(&promise);
|
||||||
c->code.append4(2 + 3);
|
compareCR(c, 4, &constant, a);
|
||||||
|
|
||||||
Assembler::Register bh(b->high);
|
c->code.append(0x0f);
|
||||||
moveRR(c, 4, &bh, b); // 2 bytes
|
c->code.append(0x8c); // jl
|
||||||
|
c->code.append4(2 + 3);
|
||||||
|
|
||||||
// sar 31,high
|
Assembler::Register bh(b->high);
|
||||||
c->code.append(0xc1);
|
moveRR(c, 4, &bh, b); // 2 bytes
|
||||||
c->code.append(0xf8 | b->high);
|
|
||||||
c->code.append(31);
|
// sar 31,high
|
||||||
} else {
|
c->code.append(0xc1);
|
||||||
if (size == 8) rex(c);
|
c->code.append(0xf8 | b->high);
|
||||||
c->code.append(0xd3);
|
c->code.append(31);
|
||||||
c->code.append(0xf8 | b->low);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
doShift(c, shiftRightRR, size, a, b);
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0xd3);
|
||||||
|
c->code.append(0xf8 | b->low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1768,35 +1496,33 @@ void
|
|||||||
unsignedShiftRightRR(Context* c, unsigned size, Assembler::Register* a,
|
unsignedShiftRightRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Register* b)
|
Assembler::Register* b)
|
||||||
{
|
{
|
||||||
if (a->low == rcx) {
|
assert(c, a->low == rcx);
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
|
||||||
// shld
|
|
||||||
c->code.append(0x0f);
|
|
||||||
c->code.append(0xa5);
|
|
||||||
c->code.append(0xc0 | (b->high << 3) | b->low);
|
|
||||||
|
|
||||||
// shr
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
c->code.append(0xd3);
|
// shld
|
||||||
c->code.append(0xe8 | b->high);
|
c->code.append(0x0f);
|
||||||
|
c->code.append(0xa5);
|
||||||
|
c->code.append(0xc0 | (b->high << 3) | b->low);
|
||||||
|
|
||||||
ResolvedPromise promise(32);
|
// shr
|
||||||
Assembler::Constant constant(&promise);
|
c->code.append(0xd3);
|
||||||
compareCR(c, 4, &constant, a);
|
c->code.append(0xe8 | b->high);
|
||||||
|
|
||||||
c->code.append(0x0f);
|
ResolvedPromise promise(32);
|
||||||
c->code.append(0x8c); // jl
|
Assembler::Constant constant(&promise);
|
||||||
c->code.append4(2 + 2);
|
compareCR(c, 4, &constant, a);
|
||||||
|
|
||||||
Assembler::Register bh(b->high);
|
c->code.append(0x0f);
|
||||||
moveRR(c, 4, &bh, b); // 2 bytes
|
c->code.append(0x8c); // jl
|
||||||
xorRR(c, 4, &bh, &bh); // 2 bytes
|
c->code.append4(2 + 2);
|
||||||
} else {
|
|
||||||
if (size == 8) rex(c);
|
Assembler::Register bh(b->high);
|
||||||
c->code.append(0xd3);
|
moveRR(c, 4, &bh, b); // 2 bytes
|
||||||
c->code.append(0xe8 | b->low);
|
xorRR(c, 4, &bh, &bh); // 2 bytes
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
doShift(c, unsignedShiftRightRR, size, a, b);
|
if (size == 8) rex(c);
|
||||||
|
c->code.append(0xd3);
|
||||||
|
c->code.append(0xe8 | b->low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1914,11 +1640,14 @@ compareCM(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
compareRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
compareRM(Context* c, unsigned size, Assembler::Register* a,
|
||||||
Assembler::Memory* b)
|
Assembler::Memory* b)
|
||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
if (BytesPerWord == 8 and size == 4) {
|
||||||
|
move4To8RR(c, size, a, a);
|
||||||
|
}
|
||||||
encode(c, 0x39, a->low, b, true);
|
encode(c, 0x39, a->low, b, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1928,6 +1657,9 @@ compareMR(Context* c, unsigned size UNUSED, Assembler::Memory* a,
|
|||||||
{
|
{
|
||||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
if (BytesPerWord == 8 and size == 4) {
|
||||||
|
move4To8RR(c, size, b, b);
|
||||||
|
}
|
||||||
encode(c, 0x3b, b->low, a, true);
|
encode(c, 0x3b, b->low, a, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2123,24 +1855,85 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getTargets(BinaryOperation op, unsigned size,
|
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
||||||
Register* a, Register* b, bool* syncStack)
|
uint64_t* registerMask, uintptr_t* procedure)
|
||||||
{
|
{
|
||||||
a->low = NoRegister;
|
if (op == Negate and BytesPerWord == 4 and size == 8) {
|
||||||
a->high = NoRegister;
|
*typeMask = 1 << RegisterOperand;
|
||||||
b->low = NoRegister;
|
*registerMask = (static_cast<uint64_t>(1) << (rdx + 32))
|
||||||
b->high = NoRegister;
|
| (static_cast<uint64_t>(1) << rax);
|
||||||
*syncStack = false;
|
} else {
|
||||||
|
*typeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||||
|
*registerMask = ~static_cast<uint64_t>(0);
|
||||||
|
}
|
||||||
|
*procedure = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void plan(UnaryOperation op, unsigned size, uint8_t* aTypeMask,
|
||||||
|
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
||||||
|
uint64_t* bRegisterMask, uintptr_t* procedure)
|
||||||
|
{
|
||||||
|
*aTypeMask = ~static_cast<uint8_t>(0);
|
||||||
|
*aRegisterMask = ~static_cast<uint64_t>(0);
|
||||||
|
|
||||||
|
*bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||||
|
*bRegisterMask = ~static_cast<uint64_t>(0);
|
||||||
|
|
||||||
|
*procedure = 0;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
case Move:
|
||||||
|
if (BytesPerWord == 4 and size == 1) {
|
||||||
|
const uint32_t mask
|
||||||
|
= (1 << rax) | (1 << rcx) | (1 << rdx) | (1 << rbx);
|
||||||
|
*aRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
|
*bRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Move4To8:
|
||||||
|
if (BytesPerWord == 4) {
|
||||||
|
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||||
|
*aRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
|
*bRegisterMask = (static_cast<uint64_t>(1) << (rdx + 32))
|
||||||
|
| (static_cast<uint64_t>(1) << rax);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Multiply:
|
case Multiply:
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||||
|
*aRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
|
*bRegisterMask = (static_cast<uint64_t>(1) << (rdx + 32)) | mask;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Divide:
|
case Divide:
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
*procedure = reinterpret_cast<uintptr_t>(divideLong);
|
||||||
|
} else {
|
||||||
|
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
||||||
|
*bRegisterMask = 1 << rax;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Remainder:
|
case Remainder:
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
*syncStack = true;
|
*procedure = reinterpret_cast<uintptr_t>(moduloLong);
|
||||||
|
} else {
|
||||||
|
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
||||||
|
*bRegisterMask = 1 << rax;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShiftLeft:
|
||||||
|
case ShiftRight:
|
||||||
|
case UnsignedShiftRight:
|
||||||
|
*aRegisterMask = static_cast<uint64_t>(1) << rcx;
|
||||||
|
const uint32_t mask = ~(1 << rcx);
|
||||||
|
*bRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user