handle constant array lengths and indexes properly; various bugfixes

This commit is contained in:
Joel Dice 2008-03-13 14:50:56 -06:00
parent 7cd79736c2
commit 406f173982
4 changed files with 349 additions and 124 deletions

View File

@ -948,6 +948,8 @@ class Frame {
(context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord)))
TraceElement(context, target, virtualCall, context->traceLog); TraceElement(context, target, virtualCall, context->traceLog);
fprintf(stderr, "make element %p at ip %d\n", e, ip);
context->eventLog.append(TraceEvent); context->eventLog.append(TraceEvent);
context->eventLog.appendAddress(e); context->eventLog.appendAddress(e);
@ -1573,6 +1575,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
frame->startLogicalIp(ip); frame->startLogicalIp(ip);
if (ip == 0) {
handleEntrance(t, frame);
}
// fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map)); // fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map));
unsigned instruction = codeBody(t, code, ip++); unsigned instruction = codeBody(t, code, ip++);
@ -1591,17 +1597,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
if (CheckArrayBounds) { if (CheckArrayBounds) {
Compiler::Operand* load = c->label(); Compiler::Operand* load = c->label();
Compiler::Operand* throw_ = c->label(); Compiler::Operand* throw_ = 0;
c->cmp(4, c->constant(0), index); if (c->isConstant(index)) {
c->jl(throw_); expect(t, c->constantValue(index) >= 0);
} else {
throw_ = c->label();
c->cmp(4, c->constant(0), index);
c->jl(throw_);
}
c->cmp(BytesPerWord, c->cmp(BytesPerWord,
c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), index,
index); c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)));
c->jl(load); c->jge(load);
c->mark(throw_); if (not c->isConstant(index)) {
c->mark(throw_);
}
c->call c->call
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)), (c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
@ -1614,34 +1627,67 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->mark(load); c->mark(load);
} }
switch (instruction) { if (c->isConstant(index)) {
case aaload: unsigned i = c->constantValue(index);
frame->pushObject switch (instruction) {
(c->load case aaload:
(BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); frame->pushObject
break; (c->load
(BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord))));
break;
case faload: case faload:
case iaload: case iaload:
frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); frame->pushInt(c->load(4, c->memory(array, ArrayBody + (i * 4))));
break; break;
case baload: case baload:
frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); frame->pushInt(c->load(1, c->memory(array, ArrayBody + i)));
break; break;
case caload: case caload:
frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); frame->pushInt(c->loadz(2, c->memory(array, ArrayBody + (i * 2))));
break; break;
case daload: case daload:
case laload: case laload:
frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); frame->pushInt(c->load(8, c->memory(array, ArrayBody + (i * 8))));
break; break;
case saload: case saload:
frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); frame->pushInt(c->load(2, c->memory(array, ArrayBody + (i * 2))));
break; break;
}
} else {
switch (instruction) {
case aaload:
frame->pushObject
(c->load
(BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord)));
break;
case faload:
case iaload:
frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4)));
break;
case baload:
frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1)));
break;
case caload:
frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2)));
break;
case daload:
case laload:
frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8)));
break;
case saload:
frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2)));
break;
}
} }
} break; } break;
@ -1667,17 +1713,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
if (CheckArrayBounds) { if (CheckArrayBounds) {
Compiler::Operand* store = c->label(); Compiler::Operand* store = c->label();
Compiler::Operand* throw_ = c->label(); Compiler::Operand* throw_ = 0;
c->cmp(4, c->constant(0), index); if (c->isConstant(index)) {
c->jl(throw_); expect(t, c->constantValue(index) >= 0);
} else {
throw_ = c->label();
c->cmp(4, c->constant(0), index);
c->jl(throw_);
}
c->cmp(BytesPerWord, c->cmp(BytesPerWord,
c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), index,
index); c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)));
c->jl(store); c->jge(store);
c->mark(throw_); if (not c->isConstant(index)) {
c->mark(throw_);
}
c->call c->call
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)), (c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
@ -1690,38 +1743,74 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->mark(store); c->mark(store);
} }
switch (instruction) { if (c->isConstant(index)) {
case aastore: { unsigned i = c->constantValue(index);
c->call switch (instruction) {
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)), case aastore: {
context->indirection, c->call
0, (c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
frame->trace(0, false), context->indirection,
0, 0,
4, c->thread(), array, frame->trace(0, false),
c->add(4, c->constant(ArrayBody), 0,
c->shl(4, c->constant(log(BytesPerWord)), index)), 4, c->thread(), array,
value); c->constant(ArrayBody + (i * BytesPerWord)),
} break; value);
} break;
case fastore: case fastore:
case iastore: case iastore:
c->store(4, value, c->memory(array, ArrayBody, index, 4)); c->store(4, value, c->memory(array, ArrayBody + (i * 4)));
break; break;
case bastore: case bastore:
c->store(1, value, c->memory(array, ArrayBody, index, 1)); c->store(1, value, c->memory(array, ArrayBody + i));
break; break;
case castore: case castore:
case sastore: case sastore:
c->store(2, value, c->memory(array, ArrayBody, index, 2)); c->store(2, value, c->memory(array, ArrayBody + (i * 2)));
break; break;
case dastore: case dastore:
case lastore: case lastore:
c->store(8, value, c->memory(array, ArrayBody, index, 8)); c->store(8, value, c->memory(array, ArrayBody + (i * 8)));
break; break;
}
} else {
switch (instruction) {
case aastore: {
c->call
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
context->indirection,
0,
frame->trace(0, false),
0,
4, c->thread(), array,
c->add(4, c->constant(ArrayBody),
c->shl(4, c->constant(log(BytesPerWord)), index)),
value);
} break;
case fastore:
case iastore:
c->store(4, value, c->memory(array, ArrayBody, index, 4));
break;
case bastore:
c->store(1, value, c->memory(array, ArrayBody, index, 1));
break;
case castore:
case sastore:
c->store(2, value, c->memory(array, ArrayBody, index, 2));
break;
case dastore:
case lastore:
c->store(8, value, c->memory(array, ArrayBody, index, 8));
break;
}
} }
} break; } break;
@ -1755,21 +1844,26 @@ 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* nonnegative = c->label();
Compiler::Operand* length = frame->popInt(); Compiler::Operand* length = frame->popInt();
c->cmp(4, c->constant(0), length);
c->jge(nonnegative);
c->call if (c->isConstant(length)) {
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)), expect(t, c->constantValue(length) >= 0);
context->indirection, } else{
Compiler::NoReturn, Compiler::Operand* nonnegative = c->label();
frame->trace(0, false),
0,
2, c->thread(), length);
c->mark(nonnegative); c->cmp(4, c->constant(0), length);
c->jge(nonnegative);
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);
}
frame->pushObject frame->pushObject
(c->call (c->call
@ -2924,22 +3018,26 @@ 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* nonnegative = c->label();
Compiler::Operand* length = frame->popInt(); Compiler::Operand* length = frame->popInt();
c->cmp(4, c->constant(0), length); if (c->isConstant(length)) {
c->jge(nonnegative); expect(t, c->constantValue(length) >= 0);
} else{
Compiler::Operand* nonnegative = c->label();
c->call c->cmp(4, c->constant(0), length);
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)), c->jge(nonnegative);
context->indirection,
Compiler::NoReturn,
frame->trace(0, false),
0,
2, c->thread(), length);
c->mark(nonnegative); 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);
}
object (*constructor)(Thread*, uintptr_t, bool); object (*constructor)(Thread*, uintptr_t, bool);
switch (type) { switch (type) {
@ -2985,7 +3083,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
0, 0,
frame->trace(0, false), frame->trace(0, false),
BytesPerWord, BytesPerWord,
2, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)), 3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
length)); length));
} break; } break;
@ -3463,6 +3561,7 @@ finish(MyThread* t, Context* context)
unsigned mapSize = frameMapSizeInWords(t, context->method); unsigned mapSize = frameMapSizeInWords(t, context->method);
for (TraceElement* p = context->traceLog; p; p = p->next) { for (TraceElement* p = context->traceLog; p; p = p->next) {
fprintf(stderr, "make node for %p\n", p);
object node = makeTraceNode object node = makeTraceNode
(t, p->address->value(), 0, context->method, p->target, (t, p->address->value(), 0, context->method, p->target,
p->virtualCall, mapSize, false); p->virtualCall, mapSize, false);
@ -3562,8 +3661,6 @@ compile(MyThread* t, Context* context)
} }
} }
handleEntrance(t, &frame);
compile(t, &frame, 0); compile(t, &frame, 0);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;

View File

@ -43,6 +43,8 @@ class Value {
virtual void asAssemblerOperand(Context*, virtual void asAssemblerOperand(Context*,
OperandType* type, OperandType* type,
Assembler::Operand** operand) = 0; Assembler::Operand** operand) = 0;
virtual int64_t constantValue(Context*) = 0;
}; };
class MyOperand: public Compiler::Operand { class MyOperand: public Compiler::Operand {
@ -291,6 +293,10 @@ class ConstantValue: public Value {
*operand = &value; *operand = &value;
} }
virtual int64_t constantValue(Context*) {
return value.value->value();
}
Assembler::Constant value; Assembler::Constant value;
}; };
@ -300,11 +306,17 @@ constant(Context* c, Promise* value)
return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value);
} }
ResolvedPromise*
resolved(Context* c, int64_t value)
{
return new (c->zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value);
}
ConstantValue* ConstantValue*
constant(Context* c, int64_t value) constant(Context* c, int64_t value)
{ {
return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise))) return constant(c, resolved(c, value));
ResolvedPromise(value));
} }
class AddressValue: public Value { class AddressValue: public Value {
@ -323,6 +335,10 @@ class AddressValue: public Value {
*operand = &address; *operand = &address;
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Assembler::Address address; Assembler::Address address;
}; };
@ -385,6 +401,10 @@ class RegisterValue: public Value {
*operand = &register_; *operand = &register_;
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Assembler::Register register_; Assembler::Register register_;
}; };
@ -437,6 +457,10 @@ class MemoryValue: public Value {
*operand = &value; *operand = &value;
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Assembler::Memory value; Assembler::Memory value;
}; };
@ -467,7 +491,7 @@ class AbstractMemoryValue: public MemoryValue {
} }
virtual int index(Context* c) { virtual int index(Context* c) {
return index_ ? ::toRegister(c, base_) : NoRegister; return index_ ? ::toRegister(c, index_) : NoRegister;
} }
MyOperand* base_; MyOperand* base_;
@ -502,6 +526,10 @@ class StackValue: public Value {
abort(c); abort(c);
} }
virtual int64_t constantValue(Context* c) {
abort(c);
}
Stack* stack; Stack* stack;
}; };
@ -514,6 +542,8 @@ stackValue(Context* c, Stack* stack)
class Event { class Event {
public: public:
Event(Context* c): next(0), stack(c->state->stack), promises(0) { Event(Context* c): next(0), stack(c->state->stack), promises(0) {
assert(c, c->logicalIp >= 0);
if (c->event) { if (c->event) {
c->event->next = this; c->event->next = this;
} }
@ -538,13 +568,37 @@ class Event {
CodePromise* promises; CodePromise* promises;
}; };
class NullEvent: public Event {
public:
NullEvent(Context* c):
Event(c)
{ }
virtual Value* target(Context*, MyOperand*) {
return 0;
}
virtual void compile(Context*) {
// ignore
}
};
void
setEvent(Context* c, MyOperand* a, Event* e)
{
if (a->event) {
a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c);
} else{
a->event = e;
}
}
class ArgumentEvent: public Event { class ArgumentEvent: public Event {
public: public:
ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index):
Event(c), size(size), a(a), index(index) Event(c), size(size), a(a), index(index)
{ {
assert(c, a->event == 0); setEvent(c, a, this);
a->event = this;
} }
virtual Value* target(Context* c, MyOperand* v UNUSED) { virtual Value* target(Context* c, MyOperand* v UNUSED) {
@ -590,8 +644,7 @@ class ReturnEvent: public Event {
Event(c), size(size), a(a) Event(c), size(size), a(a)
{ {
if (a) { if (a) {
assert(c, a->event == 0); setEvent(c, a, this);
a->event = this;
} }
} }
@ -643,8 +696,7 @@ class CallEvent: public Event {
traceHandler(traceHandler), traceHandler(traceHandler),
result(result) result(result)
{ {
assert(c, address->event == 0); setEvent(c, address, this);
address->event = this;
} }
virtual Value* target(Context* c, MyOperand* v UNUSED) { virtual Value* target(Context* c, MyOperand* v UNUSED) {
@ -855,8 +907,7 @@ class MoveEvent: public Event {
MyOperand* dst): MyOperand* dst):
Event(c), type(type), size(size), src(src), dst(dst) Event(c), type(type), size(size), src(src), dst(dst)
{ {
assert(c, src->event == 0); setEvent(c, src, this);
src->event = this;
} }
virtual Value* target(Context* c, MyOperand* v UNUSED) { virtual Value* target(Context* c, MyOperand* v UNUSED) {
@ -983,10 +1034,8 @@ class CompareEvent: public Event {
CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b):
Event(c), size(size), a(a), b(b) Event(c), size(size), a(a), b(b)
{ {
assert(c, a->event == 0); setEvent(c, a, this);
a->event = this; setEvent(c, b, this);
assert(c, b->event == 0);
b->event = this;
} }
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
@ -1020,8 +1069,7 @@ class BranchEvent: public Event {
BranchEvent(Context* c, UnaryOperation type, MyOperand* address): BranchEvent(Context* c, UnaryOperation type, MyOperand* address):
Event(c), type(type), address(address) Event(c), type(type), address(address)
{ {
assert(c, address->event == 0); setEvent(c, address, this);
address->event = this;
} }
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
@ -1054,8 +1102,7 @@ class JumpEvent: public Event {
Event(c), Event(c),
address(address) address(address)
{ {
assert(c, address->event == 0); setEvent(c, address, this);
address->event = this;
} }
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
@ -1087,10 +1134,8 @@ class CombineEvent: public Event {
MyOperand* b, MyOperand* result): MyOperand* b, MyOperand* result):
Event(c), type(type), size(size), a(a), b(b), result(result) Event(c), type(type), size(size), a(a), b(b), result(result)
{ {
assert(c, a->event == 0); setEvent(c, a, this);
a->event = this; setEvent(c, b, this);
assert(c, b->event == 0);
b->event = this;
} }
virtual Value* target(Context* c, MyOperand* v) { virtual Value* target(Context* c, MyOperand* v) {
@ -1174,8 +1219,7 @@ class TranslateEvent: public Event {
MyOperand* result): MyOperand* result):
Event(c), type(type), size(size), a(a), result(result) Event(c), type(type), size(size), a(a), result(result)
{ {
assert(c, a->event == 0); setEvent(c, a, this);
a->event = this;
} }
virtual Value* target(Context* c, MyOperand* v UNUSED) { virtual Value* target(Context* c, MyOperand* v UNUSED) {
@ -1356,12 +1400,21 @@ compile(Context* c)
a->apply(Push, BytesPerWord, Register, &base); a->apply(Push, BytesPerWord, Register, &base);
a->apply(Move, BytesPerWord, Register, &stack, Register, &base); a->apply(Move, BytesPerWord, Register, &stack, Register, &base);
if (c->stackOffset) {
Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord));
a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
}
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
fprintf(stderr, "compile ip %d\n", i); fprintf(stderr, "compile ip %d\n", i);
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
e->compile(c); e->compile(c);
if (e == c->logicalCode[i].lastEvent) break; if (e == c->logicalCode[i].lastEvent) break;
for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->length();
}
} }
} }
} }
@ -1408,8 +1461,7 @@ class MyCompiler: public Compiler {
} }
virtual Promise* poolAppend(intptr_t value) { virtual Promise* poolAppend(intptr_t value) {
return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise))) return poolAppendPromise(resolved(&c, value));
ResolvedPromise(value));
} }
virtual Promise* poolAppendPromise(Promise* value) { virtual Promise* poolAppendPromise(Promise* value) {
@ -1432,8 +1484,7 @@ class MyCompiler: public Compiler {
} }
virtual Operand* constant(int64_t value) { virtual Operand* constant(int64_t value) {
return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise))) return promiseConstant(resolved(&c, value));
ResolvedPromise(value));
} }
virtual Operand* promiseConstant(Promise* value) { virtual Operand* promiseConstant(Promise* value) {
@ -1468,6 +1519,16 @@ class MyCompiler: public Compiler {
return operand(&c, register_(&c, c.assembler->thread())); return operand(&c, register_(&c, c.assembler->thread()));
} }
virtual bool isConstant(Operand* a) {
return static_cast<MyOperand*>(a)->value
and static_cast<MyOperand*>(a)->value->type(&c) == Constant;
}
virtual int64_t constantValue(Operand* a) {
assert(&c, isConstant(a));
return static_cast<MyOperand*>(a)->value->constantValue(&c);
}
virtual Operand* label() { virtual Operand* label() {
return operand(&c, ::constant(&c, static_cast<Promise*>(0))); return operand(&c, ::constant(&c, static_cast<Promise*>(0)));
} }

View File

@ -51,6 +51,9 @@ class Compiler {
virtual Operand* base() = 0; virtual Operand* base() = 0;
virtual Operand* thread() = 0; virtual Operand* thread() = 0;
virtual bool isConstant(Operand* value) = 0;
virtual int64_t constantValue(Operand* value) = 0;
virtual Operand* label() = 0; virtual Operand* label() = 0;
virtual void mark(Operand* label) = 0; virtual void mark(Operand* label) = 0;

View File

@ -224,6 +224,7 @@ void
encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex) encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex)
{ {
if (b->traceHandler) { if (b->traceHandler) {
fprintf(stderr, "handle trace %p\n", b->traceHandler);
b->traceHandler->handleTrace(codePromise(c, c->code.length())); b->traceHandler->handleTrace(codePromise(c, c->code.length()));
} }
@ -239,6 +240,7 @@ encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b,
bool rex) bool rex)
{ {
if (b->traceHandler) { if (b->traceHandler) {
fprintf(stderr, "handle trace %p\n", b->traceHandler);
b->traceHandler->handleTrace(codePromise(c, c->code.length())); b->traceHandler->handleTrace(codePromise(c, c->code.length()));
} }
@ -331,6 +333,14 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a)
c->code.append(0xe0 | a->low); c->code.append(0xe0 | a->low);
} }
void
jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
{
assert(c, size == BytesPerWord);
conditional(c, 0x8d, a);
}
void void
pushR(Context* c, unsigned size, Assembler::Register* a) pushR(Context* c, unsigned size, Assembler::Register* a)
{ {
@ -552,6 +562,29 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
} }
} }
void
subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Register* b)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
int64_t v = a->value->value();
if (v) {
rex(c);
if (isInt8(v)) {
c->code.append(0x83);
c->code.append(0xe8 | b->low);
c->code.append(v);
} else if (isInt32(v)) {
c->code.append(0x81);
c->code.append(0xe8 | b->low);
c->code.append4(v);
} else {
abort(c);
}
}
}
void void
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
Assembler::Register* b) Assembler::Register* b)
@ -598,7 +631,23 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
{ {
assert(c, BytesPerWord == 8 or size == 4); assert(c, BytesPerWord == 8 or size == 4);
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 4, b, true); encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true);
if (isInt8(a->value->value())) {
c->code.append(a->value->value());
} else if (isInt32(a->value->value())) {
c->code.append4(a->value->value());
} else {
abort(c);
}
}
void
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Memory* b)
{
assert(c, BytesPerWord == 8 or size == 4);
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
if (isInt8(a->value->value())) { if (isInt8(a->value->value())) {
c->code.append(a->value->value()); c->code.append(a->value->value());
} else if (isInt32(a->value->value())) { } else if (isInt32(a->value->value())) {
@ -614,29 +663,44 @@ populateTables()
Operations[Return] = return_; Operations[Return] = return_;
UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC);
UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC);
UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); UnaryOperations[INDEX1(Call, Register)] = CAST1(callR);
UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM); UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM);
UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC);
UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR);
UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)]
= CAST1(jumpIfGreaterOrEqualC);
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
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);
BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM);
BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM);
BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR);
BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR);
BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR);
BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR);
BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR);
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR);
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(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);
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
} }
class MyAssembler: public Assembler { class MyAssembler: public Assembler {