various bugfixes and instructions implemented to get more tests passing

This commit is contained in:
Joel Dice 2008-11-06 17:39:38 -07:00
parent 1ba497d90a
commit f01f4441d9
4 changed files with 455 additions and 60 deletions

View File

@ -911,10 +911,6 @@ class Frame {
return popQuiet(1);
}
Compiler::Operand* peekLong(unsigned index) {
return c->peek(2, index);
}
Compiler::Operand* popLong() {
poppedLong();
return popLongQuiet();
@ -1010,7 +1006,7 @@ class Frame {
void dup2() {
if (get(sp - 1) == Long) {
pushLongQuiet(peekLong(0));
pushLongQuiet(c->peek(2, 0));
} else {
Compiler::Operand* s0 = popQuiet(1);
Compiler::Operand* s1 = popQuiet(1);
@ -1814,7 +1810,7 @@ void
saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip)
{
Compiler::State* state = initialFrame->c->saveState();
compile(t, initialFrame, ip);
compile(t, initialFrame, ip);
initialFrame->c->restoreState(state);
}
@ -3397,11 +3393,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
c->cmp(4, c->constant(bottom), key);
c->jl(frame->machineIp(defaultIp));
c->save(1, key);
saveStateAndCompile(t, frame, defaultIp);
c->cmp(4, c->constant(top), key);
c->jg(frame->machineIp(defaultIp));
c->save(1, key);
saveStateAndCompile(t, frame, defaultIp);
c->jmp(c->memory(start, 0, c->sub(4, c->constant(bottom), key),

View File

@ -15,13 +15,13 @@ using namespace vm;
namespace {
const bool DebugAppend = false;
const bool DebugCompile = false;
const bool DebugAppend = true;
const bool DebugCompile = true;
const bool DebugStack = false;
const bool DebugRegisters = false;
const bool DebugFrameIndexes = false;
const bool DebugFrameIndexes = true;
const bool DebugFrame = false;
const bool DebugControl = false;
const bool DebugControl = true;
const int AnyFrameIndex = -2;
const int NoFrameIndex = -1;
@ -127,6 +127,17 @@ class Stack: public Compiler::StackElement {
Stack* next;
};
class SavedValue {
public:
SavedValue(unsigned footprint, Value* value, SavedValue* next):
footprint(footprint), value(value), next(next)
{ }
unsigned footprint;
Value* value;
SavedValue* next;
};
class ForkElement {
public:
Value* value;
@ -136,10 +147,11 @@ class ForkElement {
class ForkState: public Compiler::State {
public:
ForkState(Stack* stack, Local* locals, Event* predecessor,
ForkState(Stack* stack, Local* locals, SavedValue* saved, Event* predecessor,
unsigned logicalIp):
stack(stack),
locals(locals),
saved(saved),
predecessor(predecessor),
logicalIp(logicalIp),
readCount(0)
@ -147,6 +159,7 @@ class ForkState: public Compiler::State {
Stack* stack;
Local* locals;
SavedValue* saved;
Event* predecessor;
unsigned logicalIp;
unsigned readCount;
@ -273,6 +286,7 @@ class Context {
client(client),
stack(0),
locals(0),
saved(0),
predecessor(0),
logicalCode(0),
registers
@ -312,6 +326,7 @@ class Context {
Compiler::Client* client;
Stack* stack;
Local* locals;
SavedValue* saved;
Event* predecessor;
LogicalInstruction** logicalCode;
Register** registers;
@ -809,8 +824,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)) {
@ -1729,43 +1744,60 @@ releaseRegister(Context* c, int r)
}
}
bool
find(Value* needle, Value* haystack)
{
if (haystack) {
if (needle == haystack) return true;
for (Value* p = haystack->buddy; p != haystack; p = p->buddy) {
if (needle == p) return true;
}
}
return false;
}
bool
trySteal(Context* c, Site* site, Value* v, unsigned size, Stack* stack,
Local* locals)
{
if (not hasMoreThanOneSite(v)) {
Site* saveSite = 0;
int index = NoFrameIndex;
for (unsigned li = 0; li < c->localFootprint; ++li) {
Local* local = locals + li;
if (local->value == v) {
saveSite = frameSite(c, frameIndex(c, li, local->footprint));
if (find(v, local->value)) {
index = frameIndex(c, li, local->footprint);
break;
}
}
if (saveSite == 0) {
if (index == NoFrameIndex) {
for (Stack* s = stack; s; s = s->next) {
if (s->value == v) {
if (find(v, s->value)) {
uint8_t typeMask;
uint64_t registerMask;
int frameIndex = AnyFrameIndex;
v->reads->intersect(&typeMask, &registerMask, &frameIndex);
live(v)->intersect(&typeMask, &registerMask, &frameIndex);
if (frameIndex >= 0) {
saveSite = frameSite(c, frameIndex);
index = frameIndex;
} else {
saveSite = frameSite
(c, ::frameIndex(c, s->index + c->localFootprint, s->footprint));
index = ::frameIndex
(c, s->index + c->localFootprint, s->footprint);
}
break;
}
}
}
if (saveSite) {
if (index != NoFrameIndex
and (not site->match(c, 1 << MemoryOperand, 0, index)))
{
Site* saveSite = frameSite(c, index);
move(c, stack, locals, size, v, site, saveSite);
} else {
if (DebugRegisters) {
if (DebugRegisters or DebugFrameIndexes) {
fprintf(stderr, "unable to steal %p from %p\n", site, v);
}
return false;
@ -2102,7 +2134,7 @@ apply(Context* c, TernaryOperation op,
void
addRead(Context* c, Event* e, Value* v, Read* r)
{
// fprintf(stderr, "add read %p to %p last %p event %p (%s)\n", r, v, v->lastRead, e, (e ? e->name() : 0));
fprintf(stderr, "add read %p to %p last %p event %p (%s)\n", r, v, v->lastRead, e, (e ? e->name() : 0));
r->value = v;
if (e) {
@ -2113,7 +2145,7 @@ addRead(Context* c, Event* e, Value* v, Read* r)
}
if (v->lastRead) {
//fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
v->lastRead->append(c, r);
} else {
v->reads = r;
@ -2192,11 +2224,11 @@ class CallEvent: public Event {
Read* target;
if (index < c->arch->argumentRegisterCount()) {
int r = c->arch->argumentRegister(index);
// fprintf(stderr, "reg %d arg read %p\n", r, s->value);
fprintf(stderr, "reg %d arg read %p\n", r, s->value);
target = fixedRegisterRead(c, footprintSizeInBytes(s->footprint), r);
mask &= ~(1 << r);
} else {
// fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value);
fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value);
target = read(c, footprintSizeInBytes(s->footprint),
1 << MemoryOperand, 0, frameIndex);
frameIndex += s->footprint;
@ -2206,7 +2238,7 @@ class CallEvent: public Event {
s = s->next;
}
// fprintf(stderr, "address read %p\n", address);
fprintf(stderr, "address read %p\n", address);
addRead(c, this, address, read
(c, BytesPerWord, ~0, (static_cast<uint64_t>(mask) << 32) | mask,
AnyFrameIndex));
@ -2214,7 +2246,7 @@ class CallEvent: public Event {
int footprint = stackArgumentFootprint;
for (Stack* s = stackBefore; s; s = s->next) {
if (footprint > 0) {
// fprintf(stderr, "stack arg read %p of footprint %d at %d of %d\n", s->value, s->footprint, frameIndex, c->alignedFrameSize + c->parameterFootprint);
fprintf(stderr, "stack arg read %p of footprint %d at %d of %d\n", s->value, s->footprint, frameIndex, c->alignedFrameSize + c->parameterFootprint);
addRead(c, this, s->value, read
(c, footprintSizeInBytes(s->footprint),
1 << MemoryOperand, 0, frameIndex));
@ -2226,7 +2258,7 @@ class CallEvent: public Event {
s->paddingInWords = index - frameIndex;
popIndex = index;
}
// fprintf(stderr, "stack save read %p of footprint %d at %d of %d\n", s->value, s->footprint, index, c->alignedFrameSize + c->parameterFootprint);
fprintf(stderr, "stack save read %p of footprint %d at %d of %d\n", s->value, s->footprint, index, c->alignedFrameSize + c->parameterFootprint);
addRead(c, this, s->value, read
(c, footprintSizeInBytes(s->footprint), 1 << MemoryOperand, 0,
index));
@ -2238,7 +2270,7 @@ class CallEvent: public Event {
for (unsigned li = 0; li < c->localFootprint; ++li) {
Local* local = localsBefore + li;
if (local->value) {
// fprintf(stderr, "local save read %p of footprint %d at %d of %d\n", local->value, local->footprint, ::frameIndex(c, li, local->footprint), c->alignedFrameSize + c->parameterFootprint);
fprintf(stderr, "local save read %p of footprint %d at %d of %d\n", local->value, local->footprint, ::frameIndex(c, li, local->footprint), c->alignedFrameSize + c->parameterFootprint);
addRead(c, this, local->value, read
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
0, ::frameIndex(c, li, local->footprint)));
@ -2505,6 +2537,7 @@ class CompareEvent: public Event {
} else {
c->constantCompare = CompareNone;
fprintf(stderr, "compare %p and %p\n", first, second);
apply(c, Compare, size, first->source, size, second->source);
}
@ -2663,18 +2696,36 @@ snapshot(Context* c, Value* value, Snapshot* next)
return new (c->zone->allocate(sizeof(Snapshot))) Snapshot(c, value, next);
}
Stack*
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
Snapshot*
makeSnapshots(Context* c, Value* value, Snapshot* next)
{
return new (c->zone->allocate(sizeof(Stack)))
Stack(index, size, value, next);
next = snapshot(c, value, next);
for (Value* p = value->buddy; p != value; p = p->buddy) {
next = snapshot(c, p, next);
}
return next;
}
Stack*
stack(Context* c, Value* value, unsigned size, Stack* next)
stack(Context* c, Value* value, unsigned footprint, unsigned index,
Stack* next)
{
return new (c->zone->allocate(sizeof(Stack)))
Stack(index, footprint, value, next);
}
Stack*
stack(Context* c, Value* value, unsigned footprint, Stack* next)
{
return stack
(c, value, size, (next ? next->index + next->footprint : 0), next);
(c, value, footprint, (next ? next->index + next->footprint : 0), next);
}
SavedValue*
savedValue(Context* c, Value* value, unsigned footprint, SavedValue* next)
{
return new (c->zone->allocate(sizeof(SavedValue)))
SavedValue(footprint, value, next);
}
Value*
@ -3300,7 +3351,7 @@ resolveJunctionSite(Context* c, Event* e, Value* v,
if (live(v)) {
assert(c, hasSite(v));
Read* r = v->reads;
Read* r = live(v);
Site* original = e->junctionSites[siteIndex];
Site* target;
@ -3411,10 +3462,11 @@ populateSiteTables(Context* c, Event* e)
if (e->successors->nextSuccessor) {
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
FrameIterator::Element el = it.next(c);
e->snapshots = snapshot(c, el.value, e->snapshots);
for (Value* p = el.value->buddy; p != el.value; p = p->buddy) {
e->snapshots = snapshot(c, p, e->snapshots);
}
e->snapshots = makeSnapshots(c, el.value, e->snapshots);
}
for (SavedValue* sv = e->successors->forkState->saved; sv; sv = sv->next) {
e->snapshots = makeSnapshots(c, sv->value, e->snapshots);
}
if (DebugControl) {
@ -3563,10 +3615,11 @@ next(Context* c, LogicalInstruction* i)
class Block {
public:
Block(Event* head):
head(head), nextInstruction(0), assemblerBlock(0), start(0)
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
{ }
Event* head;
Block* nextBlock;
LogicalInstruction* nextInstruction;
Assembler::Block* assemblerBlock;
unsigned start;
@ -3676,8 +3729,15 @@ compile(Context* c)
and (e->logicalInstruction->lastEvent == e
or e->next->logicalInstruction != nextInstruction)))
{
Block* b = e->logicalInstruction->firstEvent->block;
if (b != block) {
while (b->nextBlock) b = b->nextBlock;
b->nextBlock = block;
}
block->nextInstruction = nextInstruction;
block->assemblerBlock = a->endBlock(e->next != 0);
fprintf(stderr, "end block %p at %d\n", block->assemblerBlock, e->logicalInstruction->index);
if (e->next) {
block = ::block(c, e->next);
}
@ -3685,10 +3745,13 @@ compile(Context* c)
}
block = firstBlock;
while (block->nextInstruction) {
Block* next = block->nextInstruction->firstEvent->block;
while (block->nextBlock or block->nextInstruction) {
Block* next = block->nextBlock
? block->nextBlock
: block->nextInstruction->firstEvent->block;
next->start = block->assemblerBlock->resolve
(block->start, next->assemblerBlock);
fprintf(stderr, "resolve block %p\n", block->assemblerBlock);
block = next;
}
@ -3718,27 +3781,39 @@ restore(Context* c, ForkState* state)
}
void
addMultiRead(Context* c, Value* v, unsigned size, ForkState* state,
unsigned* count)
addForkElement(Context* c, Value* v, unsigned size, ForkState* state,
unsigned index)
{
MultiRead* r = multiRead(c, size);
// fprintf(stderr, "add multi read %p to %p\n", r, v);
addRead(c, 0, v, r);
ForkElement* p = state->elements + ((*count)++);
ForkElement* p = state->elements + index;
p->value = v;
p->local = v->local;
p->read = r;
}
unsigned
count(SavedValue* sv)
{
unsigned count = 0;
while (sv) {
++ count;
sv = sv->next;
}
return count;
}
ForkState*
saveState(Context* c)
{
unsigned elementCount = frameFootprint(c, c->stack) + count(c->saved);
ForkState* state = new
(c->zone->allocate
(sizeof(ForkState)
+ (sizeof(ForkElement) * frameFootprint(c, c->stack))))
ForkState(c->stack, c->locals, c->predecessor, c->logicalIp);
(sizeof(ForkState) + (sizeof(ForkElement) * elementCount)))
ForkState(c->stack, c->locals, c->saved, c->predecessor, c->logicalIp);
if (c->predecessor) {
c->forkState = state;
@ -3747,15 +3822,13 @@ saveState(Context* c)
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
addForkElement
(c, e.value, footprintSizeInBytes(e.footprint), state, count++);
}
MultiRead* r = multiRead(c, footprintSizeInBytes(e.footprint));
// fprintf(stderr, "add multi read %p to %p\n", r, e.value);
addRead(c, 0, e.value, r);
ForkElement* p = state->elements + (count++);
p->value = e.value;
p->local = e.value->local;
p->read = r;
for (SavedValue* sv = c->saved; sv; sv = sv->next) {
addForkElement
(c, sv->value, footprintSizeInBytes(sv->footprint), state, count++);
}
state->readCount = count;
@ -3763,6 +3836,8 @@ saveState(Context* c)
restore(c, state);
}
c->saved = 0;
return state;
}
@ -3841,6 +3916,10 @@ class MyCompiler: public Compiler {
return ::saveState(&c);
}
virtual void save(unsigned footprint, Operand* value) {
c.saved = savedValue(&c, static_cast<Value*>(value), footprint, c.saved);
}
virtual void restoreState(State* state) {
::restoreState(&c, static_cast<ForkState*>(state));
}
@ -3874,10 +3953,17 @@ class MyCompiler: public Compiler {
virtual void visitLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
if (c.logicalIp >= 0 and c.logicalCode[c.logicalIp]->lastEvent == 0) {
appendDummy(&c);
}
Event* e = c.logicalCode[logicalIp]->firstEvent;
Event* p = c.predecessor;
if (p) {
fprintf(stderr, "visit %d pred %d\n", logicalIp,
p->logicalInstruction->index);
p->stackAfter = c.stack;
p->localsAfter = c.locals;

View File

@ -65,6 +65,7 @@ class Compiler {
virtual void push(unsigned footprint) = 0;
virtual void push(unsigned footprint, Operand* value) = 0;
virtual void save(unsigned footprint, Operand* value) = 0;
virtual Operand* pop(unsigned footprint) = 0;
virtual void pushed() = 0;
virtual void popped() = 0;

View File

@ -1257,6 +1257,124 @@ andCR(Context* c, unsigned aSize, Assembler::Constant* a,
}
}
void
orRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize UNUSED, Assembler::Register* b)
{
assert(c, aSize == bSize);
if (BytesPerWord == 4 and aSize == 8) {
Assembler::Register ah(a->high);
Assembler::Register bh(b->high);
orRR(c, 4, a, 4, b);
orRR(c, 4, &ah, 4, &bh);
} else {
if (aSize == 8) rex(c);
c->code.append(0x09);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
}
void
orCR(Context* c, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, aSize == bSize);
int64_t v = a->value->value();
if (v) {
if (BytesPerWord == 4 and aSize == 8) {
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Register bh(b->high);
orCR(c, 4, &al, 4, b);
orCR(c, 4, &ah, 4, &bh);
} else {
if (isInt32(v)) {
if (aSize == 8) rex(c);
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xc8 | b->low);
c->code.append(v);
} else {
c->code.append(0x81);
c->code.append(0xc8 | b->low);
c->code.append4(v);
}
} else {
Assembler::Register tmp(c->client->acquireTemporary());
moveCR(c, aSize, a, aSize, &tmp);
orRR(c, aSize, &tmp, bSize, b);
c->client->releaseTemporary(tmp.low);
}
}
}
}
void
xorRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize UNUSED, Assembler::Register* b)
{
if (BytesPerWord == 4 and aSize == 8) {
Assembler::Register ah(a->high);
Assembler::Register bh(b->high);
xorRR(c, 4, a, 4, b);
xorRR(c, 4, &ah, 4, &bh);
} else {
if (aSize == 8) rex(c);
c->code.append(0x31);
c->code.append(0xc0 | (a->low << 3) | b->low);
}
}
void
xorCR(Context* c, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, aSize == bSize);
int64_t v = a->value->value();
if (v) {
if (BytesPerWord == 4 and aSize == 8) {
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Register bh(b->high);
xorCR(c, 4, &al, 4, b);
xorCR(c, 4, &ah, 4, &bh);
} else {
if (isInt32(v)) {
if (aSize == 8) rex(c);
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xf0 | b->low);
c->code.append(v);
} else {
c->code.append(0x81);
c->code.append(0xf0 | b->low);
c->code.append4(v);
}
} else {
Assembler::Register tmp(c->client->acquireTemporary());
moveCR(c, aSize, a, aSize, &tmp);
xorRR(c, aSize, &tmp, bSize, b);
c->client->releaseTemporary(tmp.low);
}
}
}
}
void
multiplyRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize, Assembler::Register* b)
@ -1452,6 +1570,20 @@ remainderRR(Context* c, unsigned aSize, Assembler::Register* a,
c->client->restore(rdx);
}
void
remainderCR(Context* c, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or aSize == 4);
assert(c, aSize == bSize);
const uint32_t mask = ~((1 << rax) | (1 << rdx));
Assembler::Register tmp(c->client->acquireTemporary(mask));
moveCR(c, aSize, a, aSize, &tmp);
remainderRR(c, aSize, &tmp, bSize, b);
c->client->releaseTemporary(tmp.low);
}
void
longCompareCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
unsigned bSize UNUSED, Assembler::Register* b)
@ -1485,6 +1617,165 @@ longCompareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a,
longCompare(c, a, &ah, b, &bh, CAST2(compareRR), CAST2(moveCR));
}
void
doShift(Context* c, void (*shift)
(Context*, unsigned, Assembler::Register*, unsigned,
Assembler::Register*),
int type, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
int64_t v = a->value->value();
if (BytesPerWord == 4 and bSize == 8) {
c->client->save(rcx);
Assembler::Register cx(rcx);
moveCR(c, 4, a, 4, &cx);
shift(c, aSize, &cx, bSize, b);
c->client->restore(rcx);
} else {
if (bSize == 8) rex(c);
if (v == 1) {
c->code.append(0xd1);
c->code.append(type | b->low);
} else if (isInt8(v)) {
c->code.append(0xc1);
c->code.append(type | b->low);
c->code.append(v);
} else {
abort(c);
}
}
}
void
shiftLeftRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, a->low == rcx);
if (BytesPerWord == 4 and bSize == 8) {
// shld
c->code.append(0x0f);
c->code.append(0xa5);
c->code.append(0xc0 | (b->low << 3) | b->high);
// shl
c->code.append(0xd3);
c->code.append(0xe0 | b->low);
ResolvedPromise promise(32);
Assembler::Constant constant(&promise);
compareCR(c, aSize, &constant, aSize, a);
c->code.append(0x0f);
c->code.append(0x8c); // jl
c->code.append4(2 + 2);
Assembler::Register bh(b->high);
moveRR(c, 4, b, 4, &bh); // 2 bytes
xorRR(c, 4, b, 4, b); // 2 bytes
} else {
if (bSize == 8) rex(c);
c->code.append(0xd3);
c->code.append(0xe0 | b->low);
}
}
void
shiftLeftCR(Context* c, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
doShift(c, shiftLeftRR, 0xe0, aSize, a, bSize, b);
}
void
shiftRightRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, a->low == rcx);
if (BytesPerWord == 4 and bSize == 8) {
// shrd
c->code.append(0x0f);
c->code.append(0xad);
c->code.append(0xc0 | (b->high << 3) | b->low);
// sar
c->code.append(0xd3);
c->code.append(0xf8 | b->high);
ResolvedPromise promise(32);
Assembler::Constant constant(&promise);
compareCR(c, aSize, &constant, aSize, a);
c->code.append(0x0f);
c->code.append(0x8c); // jl
c->code.append4(2 + 3);
Assembler::Register bh(b->high);
moveRR(c, 4, &bh, 4, b); // 2 bytes
// sar 31,high
c->code.append(0xc1);
c->code.append(0xf8 | b->high);
c->code.append(31);
} else {
if (bSize == 8) rex(c);
c->code.append(0xd3);
c->code.append(0xf8 | b->low);
}
}
void
shiftRightCR(Context* c, unsigned aSize, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
doShift(c, shiftRightRR, 0xf8, aSize, a, bSize, b);
}
void
unsignedShiftRightRR(Context* c, unsigned aSize, Assembler::Register* a,
unsigned bSize, Assembler::Register* b)
{
assert(c, a->low == rcx);
if (BytesPerWord == 4 and bSize == 8) {
// shrd
c->code.append(0x0f);
c->code.append(0xad);
c->code.append(0xc0 | (b->high << 3) | b->low);
// shr
c->code.append(0xd3);
c->code.append(0xe8 | b->high);
ResolvedPromise promise(32);
Assembler::Constant constant(&promise);
compareCR(c, aSize, &constant, aSize, a);
c->code.append(0x0f);
c->code.append(0x8c); // jl
c->code.append4(2 + 2);
Assembler::Register bh(b->high);
moveRR(c, 4, &bh, 4, b); // 2 bytes
xorRR(c, 4, &bh, 4, &bh); // 2 bytes
} else {
if (bSize == 8) rex(c);
c->code.append(0xd3);
c->code.append(0xe8 | b->low);
}
}
void
unsignedShiftRightCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
unsigned bSize, Assembler::Register* b)
{
doShift(c, unsignedShiftRightRR, 0xe8, aSize, a, bSize, b);
}
void
populateTables(ArchitectureContext* c)
{
@ -1547,16 +1838,33 @@ populateTables(ArchitectureContext* c)
bo[index(Subtract, C, R)] = CAST2(subtractCR);
bo[index(Subtract, R, R)] = CAST2(subtractRR);
bo[index(And, R, R)] = CAST2(andRR);
bo[index(And, C, R)] = CAST2(andCR);
bo[index(Or, R, R)] = CAST2(orRR);
bo[index(Or, C, R)] = CAST2(orCR);
bo[index(Xor, R, R)] = CAST2(xorRR);
bo[index(Xor, C, R)] = CAST2(xorCR);
bo[index(Multiply, R, R)] = CAST2(multiplyRR);
bo[index(Divide, R, R)] = CAST2(divideRR);
bo[index(Remainder, R, R)] = CAST2(remainderRR);
bo[index(Remainder, C, R)] = CAST2(remainderCR);
bo[index(LongCompare, C, R)] = CAST2(longCompareCR);
bo[index(LongCompare, R, R)] = CAST2(longCompareRR);
bo[index(ShiftLeft, R, R)] = CAST2(shiftLeftRR);
bo[index(ShiftLeft, C, R)] = CAST2(shiftLeftCR);
bo[index(ShiftRight, R, R)] = CAST2(shiftRightRR);
bo[index(ShiftRight, C, R)] = CAST2(shiftRightCR);
bo[index(UnsignedShiftRight, R, R)] = CAST2(unsignedShiftRightRR);
bo[index(UnsignedShiftRight, C, R)] = CAST2(unsignedShiftRightCR);
}
class MyArchitecture: public Assembler::Architecture {