use stack instead of registers to save data across jumps and branches; bugfixes

This commit is contained in:
Joel Dice 2008-04-26 14:56:03 -06:00
parent 571bffde09
commit d5137a7cdf
4 changed files with 204 additions and 167 deletions

View File

@ -751,7 +751,7 @@ class Frame {
void pushLongQuiet(Compiler::Operand* o) { void pushLongQuiet(Compiler::Operand* o) {
if (BytesPerWord == 8) { if (BytesPerWord == 8) {
c->pushed(1); c->push(8);
} }
c->push(8, o); c->push(8, o);
} }
@ -774,7 +774,7 @@ class Frame {
Compiler::Operand* popLongQuiet() { Compiler::Operand* popLongQuiet() {
Compiler::Operand* r = c->pop(8); Compiler::Operand* r = c->pop(8);
if (BytesPerWord == 8) { if (BytesPerWord == 8) {
c->popped(1); c->pop(8);
} }
return r; return r;
} }
@ -1364,16 +1364,28 @@ longToFloat(int64_t a)
} }
object FORCE_ALIGN object FORCE_ALIGN
makeBlankObjectArray(Thread* t, object class_, int32_t length) makeBlankObjectArray(MyThread* t, object class_, int32_t length)
{ {
return makeObjectArray(t, class_, length, true); if (length >= 0) {
return makeObjectArray(t, class_, length, true);
} else {
object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message);
unwind(t);
}
} }
object FORCE_ALIGN object FORCE_ALIGN
makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool), makeBlankArray(MyThread* t, object (*constructor)(Thread*, uintptr_t, bool),
int32_t length) int32_t length)
{ {
return constructor(t, length, true); if (length >= 0) {
return constructor(t, length, true);
} else {
object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message);
unwind(t);
}
} }
uintptr_t uintptr_t
@ -1478,14 +1490,6 @@ throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index)
unwind(t); unwind(t);
} }
void NO_RETURN FORCE_ALIGN
throwNegativeArraySize(MyThread* t, int32_t length)
{
object message = makeString(t, "%d", length);
t->exception = makeArrayIndexOutOfBoundsException(t, message);
unwind(t);
}
void NO_RETURN FORCE_ALIGN void NO_RETURN FORCE_ALIGN
throw_(MyThread* t, object o) throw_(MyThread* t, object o)
{ {
@ -2008,30 +2012,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object class_ = resolveClassInPool(t, codePool(t, code), index - 1); object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
Compiler::Operand* length = c->peek(4, 0); Compiler::Operand* length = frame->popInt();
if (c->isConstant(length)) {
expect(t, c->constantValue(length) >= 0);
} else{
Compiler::Operand* nonnegative = c->label();
c->cmp(4, c->constant(0), length);
c->jge(nonnegative);
length = c->peek(4, 0);
c->call
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
context->indirection,
Compiler::NoReturn,
frame->trace(0, false),
0,
2, c->thread(), length);
c->mark(nonnegative);
}
length = frame->popInt();
frame->pushObject frame->pushObject
(c->call (c->call
@ -3197,30 +3178,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case newarray: { case newarray: {
uint8_t type = codeBody(t, code, ip++); uint8_t type = codeBody(t, code, ip++);
Compiler::Operand* length = c->peek(4, 0); Compiler::Operand* length = frame->popInt();
if (c->isConstant(length)) {
expect(t, c->constantValue(length) >= 0);
} else{
Compiler::Operand* nonnegative = c->label();
c->cmp(4, c->constant(0), length);
c->jge(nonnegative);
length = c->peek(4, 0);
c->call
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
context->indirection,
Compiler::NoReturn,
frame->trace(0, false),
0,
2, c->thread(), length);
c->mark(nonnegative);
}
length = frame->popInt();
object (*constructor)(Thread*, uintptr_t, bool); object (*constructor)(Thread*, uintptr_t, bool);
switch (type) { switch (type) {
@ -3870,11 +3828,11 @@ finish(MyThread* t, Context* context)
strcmp strcmp
(reinterpret_cast<const char*> (reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"Enums") == 0 and "java/lang/StringBuilder") == 0 and
strcmp strcmp
(reinterpret_cast<const char*> (reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)), (&byteArrayBody(t, methodName(t, context->method), 0)),
"main") == 0) "<init>") == 0)
{ {
asm("int3"); asm("int3");
} }

View File

@ -17,8 +17,8 @@ namespace {
const bool DebugAppend = true; const bool DebugAppend = true;
const bool DebugCompile = true; const bool DebugCompile = true;
const bool DebugStack = false; const bool DebugStack = true;
const bool DebugRegisters = false; const bool DebugRegisters = true;
class Context; class Context;
class Value; class Value;
@ -61,7 +61,7 @@ class Stack {
public: public:
Stack(Value* value, unsigned size, unsigned index, Stack* next): Stack(Value* value, unsigned size, unsigned index, Stack* next):
value(value), size(size), index(index), next(next), pushEvent(0), value(value), size(size), index(index), next(next), pushEvent(0),
pushSite(0), syncSite(0), pushed(false) pushSite(0), pushed(false)
{ } { }
Value* value; Value* value;
@ -70,7 +70,6 @@ class Stack {
Stack* next; Stack* next;
PushEvent* pushEvent; PushEvent* pushEvent;
Site* pushSite; Site* pushSite;
Site* syncSite;
bool pushed; bool pushed;
}; };
@ -141,8 +140,8 @@ class Read {
class Value: public Compiler::Operand { class Value: public Compiler::Operand {
public: public:
Value(Site* site): Value(Site* site, Site* target):
reads(0), lastRead(0), sites(site), source(0), target(site) reads(0), lastRead(0), sites(site), source(0), target(target)
{ } { }
Read* reads; Read* reads;
@ -330,8 +329,6 @@ class Event {
virtual ~Event() { } virtual ~Event() { }
virtual void prepare(Context*) { }
virtual void compile(Context* c) = 0; virtual void compile(Context* c) = 0;
virtual bool isBranch() { return false; }; virtual bool isBranch() { return false; };
@ -773,6 +770,14 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
return site; return site;
} }
Site*
pushSite(Context* c, unsigned index)
{
return memorySite
(c, c->assembler->base(),
- (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1);
}
void void
pushNow(Context* c, Stack* start, unsigned count) pushNow(Context* c, Stack* start, unsigned count)
{ {
@ -787,11 +792,12 @@ pushNow(Context* c, Stack* start, unsigned count)
assert(c, not s->pushed); assert(c, not s->pushed);
if (s->value and s->value->sites) { if (s->value and s->value->sites) {
apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); Site* source = pick(c, s->value->sites);
s->pushSite = memorySite
(c, c->assembler->base(), s->pushSite = pushSite(c, s->index);
- (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1);
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
apply(c, Push, s->size * BytesPerWord, source);
} else { } else {
Assembler::Register stack(c->assembler->stack()); Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
@ -959,7 +965,7 @@ class PushEvent: public Event {
virtual void compile(Context* c) { virtual void compile(Context* c) {
if (DebugCompile) { if (DebugCompile) {
fprintf(stderr, "PushEvent.compile\n"); fprintf(stderr, "PushEvent.compile active: %d\n", active);
} }
if (active) { if (active) {
@ -1161,17 +1167,17 @@ class MoveEvent: public Event {
} }
Site* target; Site* target;
unsigned cost;
if (type == Move if (type == Move
and size >= BytesPerWord and size >= BytesPerWord
and dst->reads and dst->reads
and next == dst->reads->event) and next == dst->reads->event)
{ {
target = src->source; target = src->source;
cost = 0;
} else { } else {
target = targetOrRegister(c, size, dst, this); target = targetOrRegister(c, size, dst, this);
if (src->source->copyCost(c, target)) { cost = src->source->copyCost(c, target);
apply(c, type, size, src->source, target);
}
} }
nextRead(c, src); nextRead(c, src);
@ -1181,6 +1187,10 @@ class MoveEvent: public Event {
} else { } else {
removeSite(c, dst, target); removeSite(c, dst, target);
} }
if (cost) {
apply(c, type, size, src->source, target);
}
} }
BinaryOperation type; BinaryOperation type;
@ -1390,16 +1400,6 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
MemoryEvent(c, base, displacement, index, scale, result); MemoryEvent(c, base, displacement, index, scale, result);
} }
Site*
stackSyncSite(Context* c, unsigned index, unsigned size)
{
assert(c, index + size <= c->freeRegisterCount);
return registerSite
(c, c->freeRegisters[index],
size == 2 ? c->freeRegisters[index + 1] : NoRegister);
}
Stack* Stack*
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
{ {
@ -1408,9 +1408,9 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
} }
Value* Value*
value(Context* c, Site* site = 0) value(Context* c, Site* site = 0, Site* target = 0)
{ {
return new (c->zone->allocate(sizeof(Value))) Value(site); return new (c->zone->allocate(sizeof(Value))) Value(site, target);
} }
void void
@ -1419,8 +1419,9 @@ resetStack(Context* c)
unsigned i = 0; unsigned i = 0;
Stack* p = 0; Stack* p = 0;
for (Stack* s = c->state->stack; s; s = s->next) { for (Stack* s = c->state->stack; s; s = s->next) {
Stack* n = stack Stack* n = stack(c, value(c), s->size, s->index, 0);
(c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0); n->value->sites = n->pushSite = pushSite(c, s->index);
n->pushed = true;
if (p) { if (p) {
p->next = n; p->next = n;
@ -1453,9 +1454,9 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore)
s, s->value, target); s, s->value, target);
} }
apply(c, Pop, BytesPerWord * s->size, target);
addSite(c, stack, s->size * BytesPerWord, s->value, target); addSite(c, stack, s->size * BytesPerWord, s->value, target);
apply(c, Pop, BytesPerWord * s->size, target);
} else { } else {
if (DebugStack) { if (DebugStack) {
fprintf(stderr, "ignore %p value: %p\n", s, s->value); fprintf(stderr, "ignore %p value: %p\n", s, s->value);
@ -1485,31 +1486,21 @@ class StackSyncEvent: public Event {
StackSyncEvent(Context* c): StackSyncEvent(Context* c):
Event(c) Event(c)
{ {
unsigned i = 0;
for (Stack* s = stack; s; s = s->next) { for (Stack* s = stack; s; s = s->next) {
s->syncSite = stackSyncSite(c, i, s->size); if (s->pushEvent) s->pushEvent->active = true;
addRead(c, s->value, s->size * BytesPerWord, s->syncSite); addRead(c, s->value, s->size * BytesPerWord, 0);
i += s->size; }
}
} }
StackSyncEvent(Context* c, unsigned sequence, Stack* stack): StackSyncEvent(Context* c, unsigned sequence, Stack* stack):
Event(c, sequence, stack) Event(c, sequence, stack)
{ {
unsigned i = 0;
for (Stack* s = stack; s; s = s->next) { for (Stack* s = stack; s; s = s->next) {
s->syncSite = stackSyncSite(c, i, s->size); if (s->pushEvent) s->pushEvent->active = true;
insertRead(c, this, sequence, s->value, s->size * BytesPerWord, insertRead(c, this, sequence, s->value, s->size * BytesPerWord, 0);
s->syncSite);
if (s->pushEvent) s->pushEvent->active = false;
i += s->size;
} }
} }
virtual void prepare(Context* c) {
popNow(c, this, stack, 0xFFFFFFFF, false);
}
virtual void compile(Context* c) { virtual void compile(Context* c) {
if (DebugCompile) { if (DebugCompile) {
fprintf(stderr, "StackSyncEvent.compile\n"); fprintf(stderr, "StackSyncEvent.compile\n");
@ -1520,7 +1511,9 @@ class StackSyncEvent: public Event {
} }
for (Stack* s = stack; s; s = s->next) { for (Stack* s = stack; s; s = s->next) {
addSite(c, 0, s->size * BytesPerWord, s->value, s->syncSite); if (s->pushSite) {
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
}
} }
for (Read* r = reads; r; r = r->eventNext) { for (Read* r = reads; r; r = r->eventNext) {
@ -1642,23 +1635,23 @@ appendPop(Context* c, unsigned count, bool ignore)
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
} }
void // void
swapRegisters(Context* c, int* ap, int* bp) // swapRegisters(Context* c, int* ap, int* bp)
{ // {
Assembler::Register a(*ap); // Assembler::Register a(*ap);
Assembler::Register b(*bp); // Assembler::Register b(*bp);
c->assembler->apply // c->assembler->apply
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); // (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
c->assembler->apply // c->assembler->apply
(Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); // (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
c->assembler->apply // c->assembler->apply
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); // (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
int t = *ap; // int t = *ap;
*ap = *bp; // *ap = *bp;
*bp = t; // *bp = t;
} // }
Site* Site*
readSource(Context* c, Stack* stack, Read* r, Event* e) readSource(Context* c, Stack* stack, Read* r, Event* e)
@ -1674,29 +1667,30 @@ readSource(Context* c, Stack* stack, Read* r, Event* e)
apply(c, Move, r->size, site, target); apply(c, Move, r->size, site, target);
return target; return target;
} else { } else {
// this is a filthy hack, but I think the core idea is right: abort(c);
// // this is a filthy hack, but I think the core idea is right:
assert(c, target->type(c) == RegisterOperand); // assert(c, target->type(c) == RegisterOperand);
RegisterSite* ts = static_cast<RegisterSite*>(target); // RegisterSite* ts = static_cast<RegisterSite*>(target);
for (Site* s = r->value->sites; s; s = s->next) { // for (Site* s = r->value->sites; s; s = s->next) {
if (s->type(c) == RegisterOperand) { // if (s->type(c) == RegisterOperand) {
RegisterSite* rs = static_cast<RegisterSite*>(s); // RegisterSite* rs = static_cast<RegisterSite*>(s);
RegisterSite* os = static_cast<RegisterSite*> // RegisterSite* os = static_cast<RegisterSite*>
(c->registers[ts->register_.low].site); // (c->registers[ts->register_.low].site);
assert(c, os->register_.low == ts->register_.low); // assert(c, os->register_.low == ts->register_.low);
assert(c, os->register_.high == NoRegister); // assert(c, os->register_.high == NoRegister);
assert(c, ts->register_.high == NoRegister); // assert(c, ts->register_.high == NoRegister);
assert(c, rs->register_.high == NoRegister); // assert(c, rs->register_.high == NoRegister);
swapRegisters(c, &(os->register_.low), &(rs->register_.low)); // swapRegisters(c, &(os->register_.low), &(rs->register_.low));
return rs; // return rs;
} // }
} // }
} }
abort(c); abort(c);
@ -1736,7 +1730,7 @@ compile(Context* c)
for (Event* e = li->firstEvent; e; e = e->next) { for (Event* e = li->firstEvent; e; e = e->next) {
if (e->stackReset) { if (e->stackReset) {
// fprintf(stderr, "stack reset\n"); fprintf(stderr, "stack reset\n");
for (Stack* s = e->stack; s; s = s->next) { for (Stack* s = e->stack; s; s = s->next) {
if (s->value->sites) { if (s->value->sites) {
assert(c, s->value->sites->next == 0); assert(c, s->value->sites->next == 0);
@ -1748,8 +1742,6 @@ compile(Context* c)
} }
} }
e->prepare(c);
for (Read* r = e->reads; r; r = r->eventNext) { for (Read* r = e->reads; r; r = r->eventNext) {
r->value->source = readSource(c, e->stack, r, e); r->value->source = readSource(c, e->stack, r, e);
} }
@ -1852,14 +1844,12 @@ used(Context* c, int r)
return v and findSite(c, v, c->registers[r].site); return v and findSite(c, v, c->registers[r].site);
} }
// bool bool
// usedExclusively(Context* c, int r) usedExclusively(Context* c, int r)
// { {
// Value* v = c->registers[r].value; Value* v = c->registers[r].value;
// return used(c, r) return used(c, r) and v->sites->next == 0;
// and v->pushCount == 0 }
// and v->sites->next == 0;
// }
int int
freeRegisterExcept(Context* c, int except, bool allowAcquired) freeRegisterExcept(Context* c, int except, bool allowAcquired)
@ -1873,14 +1863,14 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired)
} }
} }
// for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
// if (i != except if (i != except
// and c->registers[i].refCount == 0 and c->registers[i].refCount == 0
// and (not usedExclusively(c, i))) and (not usedExclusively(c, i)))
// { {
// return i; return i;
// } }
// } }
if (allowAcquired) { if (allowAcquired) {
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
@ -2048,15 +2038,18 @@ class MyCompiler: public Compiler {
} }
virtual Operand* stack() { virtual Operand* stack() {
return value(&c, registerSite(&c, c.assembler->stack())); Site* s = registerSite(&c, c.assembler->stack());
return value(&c, s, s);
} }
virtual Operand* base() { virtual Operand* base() {
return value(&c, registerSite(&c, c.assembler->base())); Site* s = registerSite(&c, c.assembler->base());
return value(&c, s, s);
} }
virtual Operand* thread() { virtual Operand* thread() {
return value(&c, registerSite(&c, c.assembler->thread())); Site* s = registerSite(&c, c.assembler->thread());
return value(&c, s, s);
} }
virtual bool isConstant(Operand* a) { virtual bool isConstant(Operand* a) {
@ -2098,6 +2091,10 @@ class MyCompiler: public Compiler {
abort(&c); abort(&c);
} }
virtual void push(unsigned size) {
::push(&c, size, value(&c));
}
virtual void push(unsigned size, Operand* value) { virtual void push(unsigned size, Operand* value) {
::push(&c, size, static_cast<Value*>(value)); ::push(&c, size, static_cast<Value*>(value));
} }

View File

@ -57,6 +57,7 @@ class Compiler {
virtual Operand* label() = 0; virtual Operand* label() = 0;
virtual void mark(Operand* label) = 0; virtual void mark(Operand* label) = 0;
virtual void push(unsigned size) = 0;
virtual void push(unsigned size, Operand* value) = 0; virtual void push(unsigned size, Operand* value) = 0;
virtual Operand* pop(unsigned size) = 0; virtual Operand* pop(unsigned size) = 0;
virtual void pushed(unsigned count) = 0; virtual void pushed(unsigned count) = 0;

View File

@ -35,6 +35,18 @@ enum {
r15 = 15, r15 = 15,
}; };
int64_t FORCE_ALIGN
divideLong(int64_t a, int64_t b)
{
return a / b;
}
int64_t FORCE_ALIGN
moduloLong(int64_t a, int64_t b)
{
return a % b;
}
inline bool inline bool
isInt8(intptr_t v) isInt8(intptr_t v)
{ {
@ -523,6 +535,17 @@ popM(Context* c, unsigned size, Assembler::Memory* a)
} }
} }
void
negateR(Context* c, unsigned size, Assembler::Register* a)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
rex(c);
c->code.append(0xf7);
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)
{ {
@ -575,13 +598,19 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
} else { } else {
switch (size) { switch (size) {
case 1: case 1:
if (BytesPerWord == 8) {
c->code.append(0x0f);
}
c->code.append(0xbe); c->code.append(0xbe);
c->code.append(0xc0 | (a->low << 3) | b->low); c->code.append(0xc0 | (b->low << 3) | a->low);
break; break;
case 2: case 2:
if (BytesPerWord == 8) {
c->code.append(0x0f);
}
c->code.append(0xbf); c->code.append(0xbf);
c->code.append(0xc0 | (a->low << 3) | b->low); c->code.append(0xc0 | (b->low << 3) | a->low);
break; break;
case 8: case 8:
@ -863,6 +892,54 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
encode(c, 0x01, a->low, b, true); encode(c, 0x01, a->low, b, true);
} }
void
divideRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
pushR(c, size, a);
pushR(c, size, b);
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(divideLong));
Assembler::Constant address(&addressPromise);
callC(c, BytesPerWord, &address);
ResolvedPromise offsetPromise(16);
Assembler::Constant offset(&offsetPromise);
Assembler::Register stack(rsp);
addCR(c, BytesPerWord, &offset, &stack);
moveRR(c, size, &axdx, b);
c->client->releaseTemporary(axdx.low);
c->client->releaseTemporary(axdx.high);
} else {
Assembler::Register ax(rax);
Assembler::Register dx(c->client->acquireTemporary(rdx));
if (b->low != rax) {
c->client->acquireTemporary(ax.low);
moveRR(c, BytesPerWord, b, &ax);
}
rex(c);
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | a->low);
if (b->low != rax) {
moveRR(c, BytesPerWord, &ax, b);
c->client->releaseTemporary(ax.low);
}
c->client->releaseTemporary(dx.low);
}
}
void void
andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Register* b) Assembler::Register* b)
@ -1065,6 +1142,8 @@ populateTables()
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
UnaryOperations[INDEX1(Negate, Register)] = CAST1(negateR);
BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR);
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
@ -1086,6 +1165,8 @@ populateTables()
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR);
BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR);
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);