mirror of
https://github.com/corda/corda.git
synced 2025-05-31 14:40:52 +00:00
various bugfixes and instructions implemented to get more tests passing
This commit is contained in:
parent
1ba497d90a
commit
f01f4441d9
@ -911,10 +911,6 @@ class Frame {
|
|||||||
return popQuiet(1);
|
return popQuiet(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Compiler::Operand* peekLong(unsigned index) {
|
|
||||||
return c->peek(2, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Compiler::Operand* popLong() {
|
Compiler::Operand* popLong() {
|
||||||
poppedLong();
|
poppedLong();
|
||||||
return popLongQuiet();
|
return popLongQuiet();
|
||||||
@ -1010,7 +1006,7 @@ class Frame {
|
|||||||
|
|
||||||
void dup2() {
|
void dup2() {
|
||||||
if (get(sp - 1) == Long) {
|
if (get(sp - 1) == Long) {
|
||||||
pushLongQuiet(peekLong(0));
|
pushLongQuiet(c->peek(2, 0));
|
||||||
} else {
|
} else {
|
||||||
Compiler::Operand* s0 = popQuiet(1);
|
Compiler::Operand* s0 = popQuiet(1);
|
||||||
Compiler::Operand* s1 = popQuiet(1);
|
Compiler::Operand* s1 = popQuiet(1);
|
||||||
@ -1814,7 +1810,7 @@ void
|
|||||||
saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip)
|
saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||||
{
|
{
|
||||||
Compiler::State* state = initialFrame->c->saveState();
|
Compiler::State* state = initialFrame->c->saveState();
|
||||||
compile(t, initialFrame, ip);
|
compile(t, initialFrame, ip);
|
||||||
initialFrame->c->restoreState(state);
|
initialFrame->c->restoreState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3397,11 +3393,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
c->cmp(4, c->constant(bottom), key);
|
c->cmp(4, c->constant(bottom), key);
|
||||||
c->jl(frame->machineIp(defaultIp));
|
c->jl(frame->machineIp(defaultIp));
|
||||||
|
|
||||||
|
c->save(1, key);
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, defaultIp);
|
saveStateAndCompile(t, frame, defaultIp);
|
||||||
|
|
||||||
c->cmp(4, c->constant(top), key);
|
c->cmp(4, c->constant(top), key);
|
||||||
c->jg(frame->machineIp(defaultIp));
|
c->jg(frame->machineIp(defaultIp));
|
||||||
|
|
||||||
|
c->save(1, key);
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, defaultIp);
|
saveStateAndCompile(t, frame, defaultIp);
|
||||||
|
|
||||||
c->jmp(c->memory(start, 0, c->sub(4, c->constant(bottom), key),
|
c->jmp(c->memory(start, 0, c->sub(4, c->constant(bottom), key),
|
||||||
|
194
src/compiler.cpp
194
src/compiler.cpp
@ -15,13 +15,13 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool DebugAppend = false;
|
const bool DebugAppend = true;
|
||||||
const bool DebugCompile = false;
|
const bool DebugCompile = true;
|
||||||
const bool DebugStack = false;
|
const bool DebugStack = false;
|
||||||
const bool DebugRegisters = false;
|
const bool DebugRegisters = false;
|
||||||
const bool DebugFrameIndexes = false;
|
const bool DebugFrameIndexes = true;
|
||||||
const bool DebugFrame = false;
|
const bool DebugFrame = false;
|
||||||
const bool DebugControl = false;
|
const bool DebugControl = true;
|
||||||
|
|
||||||
const int AnyFrameIndex = -2;
|
const int AnyFrameIndex = -2;
|
||||||
const int NoFrameIndex = -1;
|
const int NoFrameIndex = -1;
|
||||||
@ -127,6 +127,17 @@ class Stack: public Compiler::StackElement {
|
|||||||
Stack* next;
|
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 {
|
class ForkElement {
|
||||||
public:
|
public:
|
||||||
Value* value;
|
Value* value;
|
||||||
@ -136,10 +147,11 @@ class ForkElement {
|
|||||||
|
|
||||||
class ForkState: public Compiler::State {
|
class ForkState: public Compiler::State {
|
||||||
public:
|
public:
|
||||||
ForkState(Stack* stack, Local* locals, Event* predecessor,
|
ForkState(Stack* stack, Local* locals, SavedValue* saved, Event* predecessor,
|
||||||
unsigned logicalIp):
|
unsigned logicalIp):
|
||||||
stack(stack),
|
stack(stack),
|
||||||
locals(locals),
|
locals(locals),
|
||||||
|
saved(saved),
|
||||||
predecessor(predecessor),
|
predecessor(predecessor),
|
||||||
logicalIp(logicalIp),
|
logicalIp(logicalIp),
|
||||||
readCount(0)
|
readCount(0)
|
||||||
@ -147,6 +159,7 @@ class ForkState: public Compiler::State {
|
|||||||
|
|
||||||
Stack* stack;
|
Stack* stack;
|
||||||
Local* locals;
|
Local* locals;
|
||||||
|
SavedValue* saved;
|
||||||
Event* predecessor;
|
Event* predecessor;
|
||||||
unsigned logicalIp;
|
unsigned logicalIp;
|
||||||
unsigned readCount;
|
unsigned readCount;
|
||||||
@ -273,6 +286,7 @@ class Context {
|
|||||||
client(client),
|
client(client),
|
||||||
stack(0),
|
stack(0),
|
||||||
locals(0),
|
locals(0),
|
||||||
|
saved(0),
|
||||||
predecessor(0),
|
predecessor(0),
|
||||||
logicalCode(0),
|
logicalCode(0),
|
||||||
registers
|
registers
|
||||||
@ -312,6 +326,7 @@ class Context {
|
|||||||
Compiler::Client* client;
|
Compiler::Client* client;
|
||||||
Stack* stack;
|
Stack* stack;
|
||||||
Local* locals;
|
Local* locals;
|
||||||
|
SavedValue* saved;
|
||||||
Event* predecessor;
|
Event* predecessor;
|
||||||
LogicalInstruction** logicalCode;
|
LogicalInstruction** logicalCode;
|
||||||
Register** registers;
|
Register** registers;
|
||||||
@ -809,8 +824,8 @@ nextRead(Context* c, Event* e, Value* v)
|
|||||||
{
|
{
|
||||||
assert(c, e == v->reads->event);
|
assert(c, e == v->reads->event);
|
||||||
|
|
||||||
// fprintf(stderr, "pop read %p from %p next %p event %p (%s)\n",
|
fprintf(stderr, "pop read %p from %p next %p event %p (%s)\n",
|
||||||
// v->reads, v, v->reads->next(c), e, (e ? e->name() : 0));
|
v->reads, v, v->reads->next(c), e, (e ? e->name() : 0));
|
||||||
|
|
||||||
v->reads = v->reads->next(c);
|
v->reads = v->reads->next(c);
|
||||||
if (not live(v)) {
|
if (not live(v)) {
|
||||||
@ -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
|
bool
|
||||||
trySteal(Context* c, Site* site, Value* v, unsigned size, Stack* stack,
|
trySteal(Context* c, Site* site, Value* v, unsigned size, Stack* stack,
|
||||||
Local* locals)
|
Local* locals)
|
||||||
{
|
{
|
||||||
if (not hasMoreThanOneSite(v)) {
|
if (not hasMoreThanOneSite(v)) {
|
||||||
Site* saveSite = 0;
|
int index = NoFrameIndex;
|
||||||
for (unsigned li = 0; li < c->localFootprint; ++li) {
|
for (unsigned li = 0; li < c->localFootprint; ++li) {
|
||||||
Local* local = locals + li;
|
Local* local = locals + li;
|
||||||
if (local->value == v) {
|
if (find(v, local->value)) {
|
||||||
saveSite = frameSite(c, frameIndex(c, li, local->footprint));
|
index = frameIndex(c, li, local->footprint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (saveSite == 0) {
|
if (index == NoFrameIndex) {
|
||||||
for (Stack* s = stack; s; s = s->next) {
|
for (Stack* s = stack; s; s = s->next) {
|
||||||
if (s->value == v) {
|
if (find(v, s->value)) {
|
||||||
uint8_t typeMask;
|
uint8_t typeMask;
|
||||||
uint64_t registerMask;
|
uint64_t registerMask;
|
||||||
int frameIndex = AnyFrameIndex;
|
int frameIndex = AnyFrameIndex;
|
||||||
v->reads->intersect(&typeMask, ®isterMask, &frameIndex);
|
live(v)->intersect(&typeMask, ®isterMask, &frameIndex);
|
||||||
|
|
||||||
if (frameIndex >= 0) {
|
if (frameIndex >= 0) {
|
||||||
saveSite = frameSite(c, frameIndex);
|
index = frameIndex;
|
||||||
} else {
|
} else {
|
||||||
saveSite = frameSite
|
index = ::frameIndex
|
||||||
(c, ::frameIndex(c, s->index + c->localFootprint, s->footprint));
|
(c, s->index + c->localFootprint, s->footprint);
|
||||||
}
|
}
|
||||||
break;
|
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);
|
move(c, stack, locals, size, v, site, saveSite);
|
||||||
} else {
|
} else {
|
||||||
if (DebugRegisters) {
|
if (DebugRegisters or DebugFrameIndexes) {
|
||||||
fprintf(stderr, "unable to steal %p from %p\n", site, v);
|
fprintf(stderr, "unable to steal %p from %p\n", site, v);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -2102,7 +2134,7 @@ apply(Context* c, TernaryOperation op,
|
|||||||
void
|
void
|
||||||
addRead(Context* c, Event* e, Value* v, Read* r)
|
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;
|
r->value = v;
|
||||||
if (e) {
|
if (e) {
|
||||||
@ -2113,7 +2145,7 @@ addRead(Context* c, Event* e, Value* v, Read* r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v->lastRead) {
|
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);
|
v->lastRead->append(c, r);
|
||||||
} else {
|
} else {
|
||||||
v->reads = r;
|
v->reads = r;
|
||||||
@ -2192,11 +2224,11 @@ class CallEvent: public Event {
|
|||||||
Read* target;
|
Read* target;
|
||||||
if (index < c->arch->argumentRegisterCount()) {
|
if (index < c->arch->argumentRegisterCount()) {
|
||||||
int r = c->arch->argumentRegister(index);
|
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);
|
target = fixedRegisterRead(c, footprintSizeInBytes(s->footprint), r);
|
||||||
mask &= ~(1 << r);
|
mask &= ~(1 << r);
|
||||||
} else {
|
} 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),
|
target = read(c, footprintSizeInBytes(s->footprint),
|
||||||
1 << MemoryOperand, 0, frameIndex);
|
1 << MemoryOperand, 0, frameIndex);
|
||||||
frameIndex += s->footprint;
|
frameIndex += s->footprint;
|
||||||
@ -2206,7 +2238,7 @@ class CallEvent: public Event {
|
|||||||
s = s->next;
|
s = s->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fprintf(stderr, "address read %p\n", address);
|
fprintf(stderr, "address read %p\n", address);
|
||||||
addRead(c, this, address, read
|
addRead(c, this, address, read
|
||||||
(c, BytesPerWord, ~0, (static_cast<uint64_t>(mask) << 32) | mask,
|
(c, BytesPerWord, ~0, (static_cast<uint64_t>(mask) << 32) | mask,
|
||||||
AnyFrameIndex));
|
AnyFrameIndex));
|
||||||
@ -2214,7 +2246,7 @@ class CallEvent: public Event {
|
|||||||
int footprint = stackArgumentFootprint;
|
int footprint = stackArgumentFootprint;
|
||||||
for (Stack* s = stackBefore; s; s = s->next) {
|
for (Stack* s = stackBefore; s; s = s->next) {
|
||||||
if (footprint > 0) {
|
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
|
addRead(c, this, s->value, read
|
||||||
(c, footprintSizeInBytes(s->footprint),
|
(c, footprintSizeInBytes(s->footprint),
|
||||||
1 << MemoryOperand, 0, frameIndex));
|
1 << MemoryOperand, 0, frameIndex));
|
||||||
@ -2226,7 +2258,7 @@ class CallEvent: public Event {
|
|||||||
s->paddingInWords = index - frameIndex;
|
s->paddingInWords = index - frameIndex;
|
||||||
popIndex = index;
|
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
|
addRead(c, this, s->value, read
|
||||||
(c, footprintSizeInBytes(s->footprint), 1 << MemoryOperand, 0,
|
(c, footprintSizeInBytes(s->footprint), 1 << MemoryOperand, 0,
|
||||||
index));
|
index));
|
||||||
@ -2238,7 +2270,7 @@ class CallEvent: public Event {
|
|||||||
for (unsigned li = 0; li < c->localFootprint; ++li) {
|
for (unsigned li = 0; li < c->localFootprint; ++li) {
|
||||||
Local* local = localsBefore + li;
|
Local* local = localsBefore + li;
|
||||||
if (local->value) {
|
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
|
addRead(c, this, local->value, read
|
||||||
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
|
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
|
||||||
0, ::frameIndex(c, li, local->footprint)));
|
0, ::frameIndex(c, li, local->footprint)));
|
||||||
@ -2505,6 +2537,7 @@ class CompareEvent: public Event {
|
|||||||
} else {
|
} else {
|
||||||
c->constantCompare = CompareNone;
|
c->constantCompare = CompareNone;
|
||||||
|
|
||||||
|
fprintf(stderr, "compare %p and %p\n", first, second);
|
||||||
apply(c, Compare, size, first->source, size, second->source);
|
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);
|
return new (c->zone->allocate(sizeof(Snapshot))) Snapshot(c, value, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack*
|
Snapshot*
|
||||||
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
|
makeSnapshots(Context* c, Value* value, Snapshot* next)
|
||||||
{
|
{
|
||||||
return new (c->zone->allocate(sizeof(Stack)))
|
next = snapshot(c, value, next);
|
||||||
Stack(index, size, value, next);
|
for (Value* p = value->buddy; p != value; p = p->buddy) {
|
||||||
|
next = snapshot(c, p, next);
|
||||||
|
}
|
||||||
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack*
|
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
|
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*
|
Value*
|
||||||
@ -3300,7 +3351,7 @@ resolveJunctionSite(Context* c, Event* e, Value* v,
|
|||||||
if (live(v)) {
|
if (live(v)) {
|
||||||
assert(c, hasSite(v));
|
assert(c, hasSite(v));
|
||||||
|
|
||||||
Read* r = v->reads;
|
Read* r = live(v);
|
||||||
Site* original = e->junctionSites[siteIndex];
|
Site* original = e->junctionSites[siteIndex];
|
||||||
Site* target;
|
Site* target;
|
||||||
|
|
||||||
@ -3411,10 +3462,11 @@ populateSiteTables(Context* c, Event* e)
|
|||||||
if (e->successors->nextSuccessor) {
|
if (e->successors->nextSuccessor) {
|
||||||
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
||||||
FrameIterator::Element el = it.next(c);
|
FrameIterator::Element el = it.next(c);
|
||||||
e->snapshots = snapshot(c, el.value, e->snapshots);
|
e->snapshots = makeSnapshots(c, el.value, e->snapshots);
|
||||||
for (Value* p = el.value->buddy; p != el.value; p = p->buddy) {
|
}
|
||||||
e->snapshots = snapshot(c, p, e->snapshots);
|
|
||||||
}
|
for (SavedValue* sv = e->successors->forkState->saved; sv; sv = sv->next) {
|
||||||
|
e->snapshots = makeSnapshots(c, sv->value, e->snapshots);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DebugControl) {
|
if (DebugControl) {
|
||||||
@ -3563,10 +3615,11 @@ next(Context* c, LogicalInstruction* i)
|
|||||||
class Block {
|
class Block {
|
||||||
public:
|
public:
|
||||||
Block(Event* head):
|
Block(Event* head):
|
||||||
head(head), nextInstruction(0), assemblerBlock(0), start(0)
|
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Event* head;
|
Event* head;
|
||||||
|
Block* nextBlock;
|
||||||
LogicalInstruction* nextInstruction;
|
LogicalInstruction* nextInstruction;
|
||||||
Assembler::Block* assemblerBlock;
|
Assembler::Block* assemblerBlock;
|
||||||
unsigned start;
|
unsigned start;
|
||||||
@ -3676,8 +3729,15 @@ compile(Context* c)
|
|||||||
and (e->logicalInstruction->lastEvent == e
|
and (e->logicalInstruction->lastEvent == e
|
||||||
or e->next->logicalInstruction != nextInstruction)))
|
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->nextInstruction = nextInstruction;
|
||||||
block->assemblerBlock = a->endBlock(e->next != 0);
|
block->assemblerBlock = a->endBlock(e->next != 0);
|
||||||
|
fprintf(stderr, "end block %p at %d\n", block->assemblerBlock, e->logicalInstruction->index);
|
||||||
|
|
||||||
if (e->next) {
|
if (e->next) {
|
||||||
block = ::block(c, e->next);
|
block = ::block(c, e->next);
|
||||||
}
|
}
|
||||||
@ -3685,10 +3745,13 @@ compile(Context* c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
block = firstBlock;
|
block = firstBlock;
|
||||||
while (block->nextInstruction) {
|
while (block->nextBlock or block->nextInstruction) {
|
||||||
Block* next = block->nextInstruction->firstEvent->block;
|
Block* next = block->nextBlock
|
||||||
|
? block->nextBlock
|
||||||
|
: block->nextInstruction->firstEvent->block;
|
||||||
next->start = block->assemblerBlock->resolve
|
next->start = block->assemblerBlock->resolve
|
||||||
(block->start, next->assemblerBlock);
|
(block->start, next->assemblerBlock);
|
||||||
|
fprintf(stderr, "resolve block %p\n", block->assemblerBlock);
|
||||||
block = next;
|
block = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3718,27 +3781,39 @@ restore(Context* c, ForkState* state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addMultiRead(Context* c, Value* v, unsigned size, ForkState* state,
|
addForkElement(Context* c, Value* v, unsigned size, ForkState* state,
|
||||||
unsigned* count)
|
unsigned index)
|
||||||
{
|
{
|
||||||
MultiRead* r = multiRead(c, size);
|
MultiRead* r = multiRead(c, size);
|
||||||
// fprintf(stderr, "add multi read %p to %p\n", r, v);
|
// fprintf(stderr, "add multi read %p to %p\n", r, v);
|
||||||
addRead(c, 0, v, r);
|
addRead(c, 0, v, r);
|
||||||
|
|
||||||
ForkElement* p = state->elements + ((*count)++);
|
ForkElement* p = state->elements + index;
|
||||||
p->value = v;
|
p->value = v;
|
||||||
p->local = v->local;
|
p->local = v->local;
|
||||||
p->read = r;
|
p->read = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
count(SavedValue* sv)
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
while (sv) {
|
||||||
|
++ count;
|
||||||
|
sv = sv->next;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
ForkState*
|
ForkState*
|
||||||
saveState(Context* c)
|
saveState(Context* c)
|
||||||
{
|
{
|
||||||
|
unsigned elementCount = frameFootprint(c, c->stack) + count(c->saved);
|
||||||
|
|
||||||
ForkState* state = new
|
ForkState* state = new
|
||||||
(c->zone->allocate
|
(c->zone->allocate
|
||||||
(sizeof(ForkState)
|
(sizeof(ForkState) + (sizeof(ForkElement) * elementCount)))
|
||||||
+ (sizeof(ForkElement) * frameFootprint(c, c->stack))))
|
ForkState(c->stack, c->locals, c->saved, c->predecessor, c->logicalIp);
|
||||||
ForkState(c->stack, c->locals, c->predecessor, c->logicalIp);
|
|
||||||
|
|
||||||
if (c->predecessor) {
|
if (c->predecessor) {
|
||||||
c->forkState = state;
|
c->forkState = state;
|
||||||
@ -3747,15 +3822,13 @@ saveState(Context* c)
|
|||||||
|
|
||||||
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
|
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
|
||||||
FrameIterator::Element e = it.next(c);
|
FrameIterator::Element e = it.next(c);
|
||||||
|
addForkElement
|
||||||
|
(c, e.value, footprintSizeInBytes(e.footprint), state, count++);
|
||||||
|
}
|
||||||
|
|
||||||
MultiRead* r = multiRead(c, footprintSizeInBytes(e.footprint));
|
for (SavedValue* sv = c->saved; sv; sv = sv->next) {
|
||||||
// fprintf(stderr, "add multi read %p to %p\n", r, e.value);
|
addForkElement
|
||||||
addRead(c, 0, e.value, r);
|
(c, sv->value, footprintSizeInBytes(sv->footprint), state, count++);
|
||||||
|
|
||||||
ForkElement* p = state->elements + (count++);
|
|
||||||
p->value = e.value;
|
|
||||||
p->local = e.value->local;
|
|
||||||
p->read = r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state->readCount = count;
|
state->readCount = count;
|
||||||
@ -3763,6 +3836,8 @@ saveState(Context* c)
|
|||||||
restore(c, state);
|
restore(c, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->saved = 0;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3841,6 +3916,10 @@ class MyCompiler: public Compiler {
|
|||||||
return ::saveState(&c);
|
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) {
|
virtual void restoreState(State* state) {
|
||||||
::restoreState(&c, static_cast<ForkState*>(state));
|
::restoreState(&c, static_cast<ForkState*>(state));
|
||||||
}
|
}
|
||||||
@ -3874,10 +3953,17 @@ class MyCompiler: public Compiler {
|
|||||||
virtual void visitLogicalIp(unsigned logicalIp) {
|
virtual void visitLogicalIp(unsigned logicalIp) {
|
||||||
assert(&c, logicalIp < c.logicalCodeLength);
|
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* e = c.logicalCode[logicalIp]->firstEvent;
|
||||||
|
|
||||||
Event* p = c.predecessor;
|
Event* p = c.predecessor;
|
||||||
if (p) {
|
if (p) {
|
||||||
|
fprintf(stderr, "visit %d pred %d\n", logicalIp,
|
||||||
|
p->logicalInstruction->index);
|
||||||
|
|
||||||
p->stackAfter = c.stack;
|
p->stackAfter = c.stack;
|
||||||
p->localsAfter = c.locals;
|
p->localsAfter = c.locals;
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ class Compiler {
|
|||||||
|
|
||||||
virtual void push(unsigned footprint) = 0;
|
virtual void push(unsigned footprint) = 0;
|
||||||
virtual void push(unsigned footprint, Operand* value) = 0;
|
virtual void push(unsigned footprint, Operand* value) = 0;
|
||||||
|
virtual void save(unsigned footprint, Operand* value) = 0;
|
||||||
virtual Operand* pop(unsigned footprint) = 0;
|
virtual Operand* pop(unsigned footprint) = 0;
|
||||||
virtual void pushed() = 0;
|
virtual void pushed() = 0;
|
||||||
virtual void popped() = 0;
|
virtual void popped() = 0;
|
||||||
|
308
src/x86.cpp
308
src/x86.cpp
@ -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
|
void
|
||||||
multiplyRR(Context* c, unsigned aSize, Assembler::Register* a,
|
multiplyRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||||
unsigned bSize, Assembler::Register* b)
|
unsigned bSize, Assembler::Register* b)
|
||||||
@ -1452,6 +1570,20 @@ remainderRR(Context* c, unsigned aSize, Assembler::Register* a,
|
|||||||
c->client->restore(rdx);
|
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
|
void
|
||||||
longCompareCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
|
longCompareCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
|
||||||
unsigned bSize UNUSED, Assembler::Register* b)
|
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));
|
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
|
void
|
||||||
populateTables(ArchitectureContext* c)
|
populateTables(ArchitectureContext* c)
|
||||||
{
|
{
|
||||||
@ -1547,16 +1838,33 @@ populateTables(ArchitectureContext* c)
|
|||||||
bo[index(Subtract, C, R)] = CAST2(subtractCR);
|
bo[index(Subtract, C, R)] = CAST2(subtractCR);
|
||||||
bo[index(Subtract, R, R)] = CAST2(subtractRR);
|
bo[index(Subtract, R, R)] = CAST2(subtractRR);
|
||||||
|
|
||||||
|
bo[index(And, R, R)] = CAST2(andRR);
|
||||||
bo[index(And, C, R)] = CAST2(andCR);
|
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(Multiply, R, R)] = CAST2(multiplyRR);
|
||||||
|
|
||||||
bo[index(Divide, R, R)] = CAST2(divideRR);
|
bo[index(Divide, R, R)] = CAST2(divideRR);
|
||||||
|
|
||||||
bo[index(Remainder, R, R)] = CAST2(remainderRR);
|
bo[index(Remainder, R, R)] = CAST2(remainderRR);
|
||||||
|
bo[index(Remainder, C, R)] = CAST2(remainderCR);
|
||||||
|
|
||||||
bo[index(LongCompare, C, R)] = CAST2(longCompareCR);
|
bo[index(LongCompare, C, R)] = CAST2(longCompareCR);
|
||||||
bo[index(LongCompare, R, R)] = CAST2(longCompareRR);
|
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 {
|
class MyArchitecture: public Assembler::Architecture {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user