mirror of
https://github.com/corda/corda.git
synced 2025-02-04 18:22:29 +00:00
Merge branch 'master' of oss.ecovate.com:/var/local/git/avian into powerpc
This commit is contained in:
commit
358f3f801b
2
makefile
2
makefile
@ -1,7 +1,7 @@
|
||||
MAKEFLAGS = -s
|
||||
|
||||
name = avian
|
||||
version = 0.0.1
|
||||
version = 0.1
|
||||
|
||||
build-arch = "$(shell uname -m)"
|
||||
ifeq ($(build-arch),"Power Macintosh")
|
||||
|
@ -37,6 +37,7 @@ enum BinaryOperation {
|
||||
MoveZ,
|
||||
Move4To8,
|
||||
Swap,
|
||||
LongCompare,
|
||||
Compare,
|
||||
Add,
|
||||
Subtract,
|
||||
|
202
src/compile.cpp
202
src/compile.cpp
@ -1834,67 +1834,34 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
(&singletonValue(t, aioobThunk(t), 0)));
|
||||
}
|
||||
|
||||
if (c->isConstant(index)) {
|
||||
unsigned i = c->constantValue(index);
|
||||
switch (instruction) {
|
||||
case aaload:
|
||||
frame->pushObject
|
||||
(c->load
|
||||
(BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord))));
|
||||
break;
|
||||
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 + (i * 4))));
|
||||
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 + i)));
|
||||
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 + (i * 2))));
|
||||
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 + (i * 8))));
|
||||
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 + (i * 2))));
|
||||
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;
|
||||
}
|
||||
case saload:
|
||||
frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1923,72 +1890,37 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
(&singletonValue(t, aioobThunk(t), 0)));
|
||||
}
|
||||
|
||||
if (c->isConstant(index)) {
|
||||
unsigned i = c->constantValue(index);
|
||||
switch (instruction) {
|
||||
case aastore: {
|
||||
c->call
|
||||
(c->constant(getThunk(t, setMaybeNullThunk)),
|
||||
0,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
4, c->thread(), array,
|
||||
c->constant(ArrayBody + (i * BytesPerWord)),
|
||||
value);
|
||||
} break;
|
||||
switch (instruction) {
|
||||
case aastore: {
|
||||
c->call
|
||||
(c->constant(getThunk(t, setMaybeNullThunk)),
|
||||
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 + (i * 4)));
|
||||
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 + i));
|
||||
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 + (i * 2)));
|
||||
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 + (i * 8)));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (instruction) {
|
||||
case aastore: {
|
||||
c->call
|
||||
(c->constant(getThunk(t, setMaybeNullThunk)),
|
||||
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;
|
||||
}
|
||||
case dastore:
|
||||
case lastore:
|
||||
c->store(8, value, c->memory(array, ArrayBody, index, 8));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -2602,7 +2534,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
c->jle(target);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
compile(t, frame, newIp);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
} break;
|
||||
@ -2858,6 +2790,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
|
||||
assert(t, newIp < codeLength(t, code));
|
||||
|
||||
c->saveStack();
|
||||
|
||||
frame->pushAddress(frame->machineIp(ip));
|
||||
c->jmp(frame->machineIp(newIp));
|
||||
|
||||
@ -2902,38 +2836,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
} break;
|
||||
|
||||
case lcmp: {
|
||||
Compiler::Operand* next = c->label();
|
||||
Compiler::Operand* less = c->label();
|
||||
Compiler::Operand* greater = c->label();
|
||||
|
||||
Compiler::Operand* a = frame->popLong();
|
||||
Compiler::Operand* b = frame->popLong();
|
||||
|
||||
c->cmp(8, a, b);
|
||||
|
||||
c->jl(less);
|
||||
c->pushState();
|
||||
|
||||
c->jg(greater);
|
||||
c->pushState();
|
||||
|
||||
c->push(4, c->constant(0));
|
||||
c->jmp(next);
|
||||
|
||||
c->popState();
|
||||
c->mark(less);
|
||||
|
||||
c->push(4, c->constant(-1));
|
||||
c->jmp(next);
|
||||
|
||||
c->popState();
|
||||
c->mark(greater);
|
||||
|
||||
c->push(4, c->constant(1));
|
||||
|
||||
c->mark(next);
|
||||
|
||||
frame->pushedInt();
|
||||
frame->pushInt(c->load(4, c->lcmp(a, b)));
|
||||
} break;
|
||||
|
||||
case lconst_0:
|
||||
|
173
src/compiler.cpp
173
src/compiler.cpp
@ -37,6 +37,13 @@ apply(Context* c, UnaryOperation op, unsigned size, Site* a);
|
||||
void
|
||||
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b);
|
||||
|
||||
enum ConstantCompare {
|
||||
CompareNone,
|
||||
CompareLess,
|
||||
CompareGreater,
|
||||
CompareEqual
|
||||
};
|
||||
|
||||
class Site {
|
||||
public:
|
||||
Site(): next(0) { }
|
||||
@ -207,7 +214,8 @@ class Context {
|
||||
machineCode(0),
|
||||
locals(0),
|
||||
localTable(0),
|
||||
stackReset(false)
|
||||
stackReset(false),
|
||||
constantCompare(CompareNone)
|
||||
{
|
||||
for (unsigned i = 0; i < assembler->registerCount(); ++i) {
|
||||
registers[i] = new (zone->allocate(sizeof(Register))) Register(i);
|
||||
@ -238,6 +246,7 @@ class Context {
|
||||
Local* locals;
|
||||
Local** localTable;
|
||||
bool stackReset;
|
||||
ConstantCompare constantCompare;
|
||||
};
|
||||
|
||||
class PoolPromise: public Promise {
|
||||
@ -999,7 +1008,7 @@ trySteal(Context* c, Register* r, Stack* stack)
|
||||
unsigned count = 0;
|
||||
Stack* start = 0;
|
||||
for (Stack* s = stack; s and (not s->pushed); s = s->next) {
|
||||
if (s->value == v) {
|
||||
if (start == 0 and s->value == v) {
|
||||
start = s;
|
||||
}
|
||||
if (start) {
|
||||
@ -1595,6 +1604,17 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
|
||||
MoveEvent(c, type, size, src, dst, srcTarget, dstTarget);
|
||||
}
|
||||
|
||||
ConstantSite*
|
||||
findConstantSite(Context* c, Value* v)
|
||||
{
|
||||
for (Site* s = v->sites; s; s = s->next) {
|
||||
if (s->type(c) == ConstantOperand) {
|
||||
return static_cast<ConstantSite*>(s);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class CompareEvent: public Event {
|
||||
public:
|
||||
CompareEvent(Context* c, unsigned size, Value* first, Value* second,
|
||||
@ -1610,7 +1630,25 @@ class CompareEvent: public Event {
|
||||
fprintf(stderr, "CompareEvent.compile\n");
|
||||
}
|
||||
|
||||
apply(c, Compare, size, first->source, second->source);
|
||||
ConstantSite* firstConstant = findConstantSite(c, first);
|
||||
ConstantSite* secondConstant = findConstantSite(c, second);
|
||||
|
||||
if (firstConstant and secondConstant) {
|
||||
int64_t d = firstConstant->value.value->value()
|
||||
- secondConstant->value.value->value();
|
||||
|
||||
if (d < 0) {
|
||||
c->constantCompare = CompareLess;
|
||||
} else if (d > 0) {
|
||||
c->constantCompare = CompareGreater;
|
||||
} else {
|
||||
c->constantCompare = CompareEqual;
|
||||
}
|
||||
} else {
|
||||
c->constantCompare = CompareNone;
|
||||
|
||||
apply(c, Compare, size, first->source, second->source);
|
||||
}
|
||||
|
||||
nextRead(c, first);
|
||||
nextRead(c, second);
|
||||
@ -1704,7 +1742,7 @@ class CombineEvent: public Event {
|
||||
|
||||
removeSite(c, second, second->source);
|
||||
if (result->reads) {
|
||||
addSite(c, 0, 0, result, second->source);
|
||||
addSite(c, 0, size, result, second->source);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1786,7 +1824,7 @@ class TranslateEvent: public Event {
|
||||
|
||||
removeSite(c, value, value->source);
|
||||
if (result->reads) {
|
||||
addSite(c, 0, 0, result, value->source);
|
||||
addSite(c, 0, size, result, value->source);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1826,7 +1864,7 @@ class MemoryEvent: public Event {
|
||||
scale(scale), result(result)
|
||||
{
|
||||
addRead(c, base, BytesPerWord, anyRegisterSite(c));
|
||||
if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c));
|
||||
if (index) addRead(c, index, BytesPerWord, registerOrConstantSite(c));
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
@ -1835,9 +1873,20 @@ class MemoryEvent: public Event {
|
||||
}
|
||||
|
||||
int indexRegister;
|
||||
int displacement = this->displacement;
|
||||
unsigned scale = this->scale;
|
||||
if (index) {
|
||||
assert(c, index->source->type(c) == RegisterOperand);
|
||||
indexRegister = static_cast<RegisterSite*>(index->source)->register_.low;
|
||||
ConstantSite* constant = findConstantSite(c, index);
|
||||
|
||||
if (constant) {
|
||||
indexRegister = NoRegister;
|
||||
displacement += (constant->value.value->value() * scale);
|
||||
scale = 1;
|
||||
} else {
|
||||
assert(c, index->source->type(c) == RegisterOperand);
|
||||
indexRegister = static_cast<RegisterSite*>
|
||||
(index->source)->register_.low;
|
||||
}
|
||||
} else {
|
||||
indexRegister = NoRegister;
|
||||
}
|
||||
@ -1846,7 +1895,7 @@ class MemoryEvent: public Event {
|
||||
|
||||
nextRead(c, base);
|
||||
if (index) {
|
||||
if (BytesPerWord == 8) {
|
||||
if (BytesPerWord == 8 and indexRegister != NoRegister) {
|
||||
apply(c, Move4To8, 8, index->source, index->source);
|
||||
}
|
||||
|
||||
@ -1920,22 +1969,23 @@ popNow(Context* c, Stack* stack, unsigned count, bool ignore)
|
||||
s->pushSite = 0;
|
||||
s->pushed = false;
|
||||
|
||||
if (s->value->reads and (not ignore)) {
|
||||
Value* v = s->value;
|
||||
if (v->reads and v->sites == 0 and (not ignore)) {
|
||||
::ignore(c, ignored);
|
||||
|
||||
Site* target = targetOrRegister(c, s->value);
|
||||
Site* target = targetOrRegister(c, v);
|
||||
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop %p value: %p target: %p\n",
|
||||
s, s->value, target);
|
||||
}
|
||||
|
||||
addSite(c, stack, s->size * BytesPerWord, s->value, target);
|
||||
addSite(c, stack, s->size * BytesPerWord, v, target);
|
||||
|
||||
apply(c, Pop, BytesPerWord * s->size, target);
|
||||
} else {
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "ignore %p value: %p\n", s, s->value);
|
||||
fprintf(stderr, "ignore %p value: %p\n", s, v);
|
||||
}
|
||||
|
||||
ignored += s->size;
|
||||
@ -2005,7 +2055,65 @@ class BranchEvent: public Event {
|
||||
fprintf(stderr, "BranchEvent.compile\n");
|
||||
}
|
||||
|
||||
apply(c, type, BytesPerWord, address->source);
|
||||
bool jump;
|
||||
UnaryOperation type = this->type;
|
||||
if (type != Jump) {
|
||||
switch (c->constantCompare) {
|
||||
case CompareLess:
|
||||
switch (type) {
|
||||
case JumpIfLess:
|
||||
case JumpIfLessOrEqual:
|
||||
case JumpIfNotEqual:
|
||||
jump = true;
|
||||
type = Jump;
|
||||
break;
|
||||
|
||||
default:
|
||||
jump = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case CompareGreater:
|
||||
switch (type) {
|
||||
case JumpIfGreater:
|
||||
case JumpIfGreaterOrEqual:
|
||||
case JumpIfNotEqual:
|
||||
jump = true;
|
||||
type = Jump;
|
||||
break;
|
||||
|
||||
default:
|
||||
jump = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case CompareEqual:
|
||||
switch (type) {
|
||||
case JumpIfEqual:
|
||||
case JumpIfLessOrEqual:
|
||||
case JumpIfGreaterOrEqual:
|
||||
jump = true;
|
||||
type = Jump;
|
||||
break;
|
||||
|
||||
default:
|
||||
jump = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case CompareNone:
|
||||
jump = true;
|
||||
break;
|
||||
|
||||
default: abort(c);
|
||||
}
|
||||
} else {
|
||||
jump = true;
|
||||
}
|
||||
|
||||
if (jump) {
|
||||
apply(c, type, BytesPerWord, address->source);
|
||||
}
|
||||
|
||||
nextRead(c, address);
|
||||
}
|
||||
@ -2203,14 +2311,7 @@ class BoundsCheckEvent: public Event {
|
||||
|
||||
Assembler* a = c->assembler;
|
||||
|
||||
ConstantSite* constant = 0;
|
||||
for (Site* s = index->sites; s; s = s->next) {
|
||||
if (s->type(c) == ConstantOperand) {
|
||||
constant = static_cast<ConstantSite*>(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ConstantSite* constant = findConstantSite(c, index);
|
||||
CodePromise* nextPromise = codePromise(c, -1);
|
||||
CodePromise* outOfBoundsPromise = 0;
|
||||
|
||||
@ -2232,7 +2333,7 @@ class BoundsCheckEvent: public Event {
|
||||
Site* length = memorySite(c, base, lengthOffset);
|
||||
length->acquire(c, 0, 0, 0);
|
||||
|
||||
apply(c, Compare, BytesPerWord, index->source, length);
|
||||
apply(c, Compare, 4, index->source, length);
|
||||
|
||||
length->release(c);
|
||||
|
||||
@ -2641,22 +2742,6 @@ class MyCompiler: public Compiler {
|
||||
return value(&c, s, s);
|
||||
}
|
||||
|
||||
virtual bool isConstant(Operand* a) {
|
||||
for (Site* s = static_cast<Value*>(a)->sites; s; s = s->next) {
|
||||
if (s->type(&c) == ConstantOperand) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Operand* a) {
|
||||
for (Site* s = static_cast<Value*>(a)->sites; s; s = s->next) {
|
||||
if (s->type(&c) == ConstantOperand) {
|
||||
return static_cast<ConstantSite*>(s)->value.value->value();
|
||||
}
|
||||
}
|
||||
abort(&c);
|
||||
}
|
||||
|
||||
virtual Operand* label() {
|
||||
return value(&c, ::constantSite(&c, static_cast<Promise*>(0)));
|
||||
}
|
||||
@ -2698,7 +2783,8 @@ class MyCompiler: public Compiler {
|
||||
Value* v = value(&c);
|
||||
c.state->stack = ::stack(&c, v, 1, c.state->stack);
|
||||
c.state->stack->pushed = true;
|
||||
// v->sites = pushSite(&c, c.state->stack->index);
|
||||
c.state->stack->pushSite
|
||||
= v->sites = pushSite(&c, c.state->stack->index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2831,6 +2917,13 @@ class MyCompiler: public Compiler {
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual Operand* lcmp(Operand* a, Operand* b) {
|
||||
Value* result = value(&c);
|
||||
appendCombine(&c, LongCompare, 8, static_cast<Value*>(a),
|
||||
static_cast<Value*>(b), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void cmp(unsigned size, Operand* a, Operand* b) {
|
||||
appendCompare(&c, size, static_cast<Value*>(a),
|
||||
static_cast<Value*>(b));
|
||||
|
@ -62,9 +62,6 @@ class Compiler {
|
||||
virtual Operand* base() = 0;
|
||||
virtual Operand* thread() = 0;
|
||||
|
||||
virtual bool isConstant(Operand* value) = 0;
|
||||
virtual int64_t constantValue(Operand* value) = 0;
|
||||
|
||||
virtual Operand* label() = 0;
|
||||
virtual void mark(Operand* label) = 0;
|
||||
|
||||
@ -94,6 +91,7 @@ class Compiler {
|
||||
virtual Operand* load(unsigned size, Operand* src) = 0;
|
||||
virtual Operand* loadz(unsigned size, Operand* src) = 0;
|
||||
virtual Operand* load4To8(Operand* src) = 0;
|
||||
virtual Operand* lcmp(Operand* a, Operand* b) = 0;
|
||||
virtual void cmp(unsigned size, Operand* a, Operand* b) = 0;
|
||||
virtual void jl(Operand* address) = 0;
|
||||
virtual void jg(Operand* address) = 0;
|
||||
|
322
src/x86.cpp
322
src/x86.cpp
@ -771,6 +771,13 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
move4To8CR(Context* c, unsigned, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
moveCR(c, 8, a, b);
|
||||
}
|
||||
|
||||
void
|
||||
move4To8RR(Context* c, unsigned, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
@ -1144,7 +1151,7 @@ multiplyCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||
c->client->releaseTemporary(tmp.high);
|
||||
} else {
|
||||
int64_t v = a->value->value();
|
||||
if (v) {
|
||||
if (v != 1) {
|
||||
if (isInt32(v)) {
|
||||
if (size == 8) rex(c);
|
||||
if (isInt8(v)) {
|
||||
@ -1582,48 +1589,22 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||
doShift(c, unsignedShiftRightRR, 0xe8, size, a, b);
|
||||
}
|
||||
|
||||
void
|
||||
multiwordCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah,
|
||||
Assembler::Operand* bl, Assembler::Operand* bh,
|
||||
BinaryOperationType op)
|
||||
{
|
||||
op(c, BytesPerWord, ah, bh);
|
||||
|
||||
// if the high order bits are equal, we compare the low order
|
||||
// bits; otherwise, we jump past that comparison
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x85); // jne
|
||||
|
||||
unsigned comparisonOffset = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
op(c, BytesPerWord, al, bl);
|
||||
|
||||
int32_t comparisonSize = c->code.length() - comparisonOffset - 4;
|
||||
c->code.set(comparisonOffset, &comparisonSize, 4);
|
||||
}
|
||||
|
||||
void
|
||||
compareRR(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
Assembler::Register ah(a->high);
|
||||
Assembler::Register bh(b->high);
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRR));
|
||||
} else {
|
||||
if (size == 8) rex(c);
|
||||
c->code.append(0x39);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
}
|
||||
if (size == 8) rex(c);
|
||||
c->code.append(0x39);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
}
|
||||
|
||||
void
|
||||
compareAR(Context* c, unsigned size, Assembler::Address* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveAR(c, size, a, &tmp);
|
||||
@ -1635,65 +1616,45 @@ void
|
||||
compareCR(Context* c, unsigned size, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
int64_t v = a->value->value();
|
||||
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||
Assembler::Constant al(&low);
|
||||
|
||||
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||
Assembler::Constant ah(&high);
|
||||
|
||||
Assembler::Register bh(b->high);
|
||||
|
||||
multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCR));
|
||||
} else {
|
||||
if (isInt32(v)) {
|
||||
if (size == 8) rex(c);
|
||||
if (isInt8(v)) {
|
||||
c->code.append(0x83);
|
||||
c->code.append(0xf8 | b->low);
|
||||
c->code.append(v);
|
||||
} else {
|
||||
c->code.append(0x81);
|
||||
c->code.append(0xf8 | b->low);
|
||||
c->code.append4(v);
|
||||
}
|
||||
if (isInt32(v)) {
|
||||
if (size == 8) rex(c);
|
||||
if (isInt8(v)) {
|
||||
c->code.append(0x83);
|
||||
c->code.append(0xf8 | b->low);
|
||||
c->code.append(v);
|
||||
} else {
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveCR(c, size, a, &tmp);
|
||||
compareRR(c, size, &tmp, b);
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
c->code.append(0x81);
|
||||
c->code.append(0xf8 | b->low);
|
||||
c->code.append4(v);
|
||||
}
|
||||
} else {
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveCR(c, size, a, &tmp);
|
||||
compareRR(c, size, &tmp, b);
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
compareCM(Context* c, unsigned size, Assembler::Constant* a,
|
||||
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Memory* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
int64_t v = a->value->value();
|
||||
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||
Assembler::Constant al(&low);
|
||||
encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true);
|
||||
|
||||
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||
Assembler::Constant ah(&high);
|
||||
|
||||
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
|
||||
|
||||
multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCM));
|
||||
if (isInt8(v)) {
|
||||
c->code.append(v);
|
||||
} else if (isInt32(v)) {
|
||||
c->code.append4(v);
|
||||
} else {
|
||||
encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true);
|
||||
|
||||
if (isInt8(v)) {
|
||||
c->code.append(v);
|
||||
} else if (isInt32(v)) {
|
||||
c->code.append4(v);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1701,77 +1662,192 @@ void
|
||||
compareRM(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Memory* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
Assembler::Register ah(a->high);
|
||||
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
|
||||
|
||||
multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRM));
|
||||
} else {
|
||||
if (BytesPerWord == 8 and size == 4) {
|
||||
move4To8RR(c, size, a, a);
|
||||
}
|
||||
encode(c, 0x39, a->low, b, true);
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
if (BytesPerWord == 8 and size == 4) {
|
||||
move4To8RR(c, size, a, a);
|
||||
}
|
||||
encode(c, 0x39, a->low, b, true);
|
||||
}
|
||||
|
||||
void
|
||||
compareMR(Context* c, unsigned size, Assembler::Memory* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale);
|
||||
Assembler::Register bh(b->high);
|
||||
|
||||
multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMR));
|
||||
} else {
|
||||
if (BytesPerWord == 8 and size == 4) {
|
||||
move4To8RR(c, size, b, b);
|
||||
}
|
||||
encode(c, 0x3b, b->low, a, true);
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
if (BytesPerWord == 8 and size == 4) {
|
||||
move4To8RR(c, size, b, b);
|
||||
}
|
||||
encode(c, 0x3b, b->low, a, true);
|
||||
}
|
||||
|
||||
void
|
||||
compareMM(Context* c, unsigned size, Assembler::Memory* a,
|
||||
Assembler::Memory* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale);
|
||||
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
|
||||
|
||||
multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMM));
|
||||
} else {
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveMR(c, size, a, &tmp);
|
||||
compareRM(c, size, &tmp, b);
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
}
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveMR(c, size, a, &tmp);
|
||||
compareRM(c, size, &tmp, b);
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
}
|
||||
|
||||
void
|
||||
compareRC(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Constant* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
Assembler::Register ah(a->high);
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveCR(c, size, b, &tmp);
|
||||
compareRR(c, size, a, &tmp);
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
}
|
||||
|
||||
int64_t v = b->value->value();
|
||||
void
|
||||
longCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah,
|
||||
Assembler::Operand* bl, Assembler::Operand* bh,
|
||||
BinaryOperationType compare, BinaryOperationType move)
|
||||
{
|
||||
ResolvedPromise negativePromise(-1);
|
||||
Assembler::Constant negative(&negativePromise);
|
||||
|
||||
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||
Assembler::Constant bl(&low);
|
||||
ResolvedPromise zeroPromise(0);
|
||||
Assembler::Constant zero(&zeroPromise);
|
||||
|
||||
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||
Assembler::Constant bh(&high);
|
||||
ResolvedPromise positivePromise(1);
|
||||
Assembler::Constant positive(&positivePromise);
|
||||
|
||||
multiwordCompare(c, a, &ah, &bl, &bh, CAST2(compareRC));
|
||||
if (BytesPerWord == 8) {
|
||||
compare(c, 8, al, bl);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x8c); // jl
|
||||
unsigned less = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x8f); // jg
|
||||
unsigned greater = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
move(c, 4, &zero, bl);
|
||||
|
||||
c->code.append(0xe9); // jmp
|
||||
unsigned nextFirst = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
int32_t lessOffset = c->code.length() - less - 4;
|
||||
c->code.set(less, &lessOffset, 4);
|
||||
|
||||
move(c, 4, &negative, bl);
|
||||
|
||||
c->code.append(0xe9); // jmp
|
||||
unsigned nextSecond = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
int32_t greaterOffset = c->code.length() - greater - 4;
|
||||
c->code.set(greater, &greaterOffset, 4);
|
||||
|
||||
move(c, 4, &positive, bl);
|
||||
|
||||
int32_t nextFirstOffset = c->code.length() - nextFirst - 4;
|
||||
c->code.set(nextFirst, &nextFirstOffset, 4);
|
||||
|
||||
int32_t nextSecondOffset = c->code.length() - nextSecond - 4;
|
||||
c->code.set(nextSecond, &nextSecondOffset, 4);
|
||||
} else {
|
||||
Assembler::Register tmp(c->client->acquireTemporary());
|
||||
moveCR(c, size, b, &tmp);
|
||||
compareRR(c, size, a, &tmp);
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
compare(c, 4, ah, bh);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x8c); // jl
|
||||
unsigned less = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x8f); // jg
|
||||
unsigned greater = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
compare(c, 4, al, bl);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x82); // ja
|
||||
unsigned above = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0x87); // jb
|
||||
unsigned below = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
move(c, 4, &zero, bl);
|
||||
|
||||
c->code.append(0xe9); // jmp
|
||||
unsigned nextFirst = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
int32_t lessOffset = c->code.length() - less - 4;
|
||||
c->code.set(less, &lessOffset, 4);
|
||||
|
||||
int32_t aboveOffset = c->code.length() - above - 4;
|
||||
c->code.set(above, &aboveOffset, 4);
|
||||
|
||||
move(c, 4, &negative, bl);
|
||||
|
||||
c->code.append(0xe9); // jmp
|
||||
unsigned nextSecond = c->code.length();
|
||||
c->code.append4(0);
|
||||
|
||||
int32_t greaterOffset = c->code.length() - greater - 4;
|
||||
c->code.set(greater, &greaterOffset, 4);
|
||||
|
||||
int32_t belowOffset = c->code.length() - below - 4;
|
||||
c->code.set(below, &belowOffset, 4);
|
||||
|
||||
move(c, 4, &positive, bl);
|
||||
|
||||
int32_t nextFirstOffset = c->code.length() - nextFirst - 4;
|
||||
c->code.set(nextFirst, &nextFirstOffset, 4);
|
||||
|
||||
int32_t nextSecondOffset = c->code.length() - nextSecond - 4;
|
||||
c->code.set(nextSecond, &nextSecondOffset, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
longCompareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, size == 8);
|
||||
|
||||
int64_t v = a->value->value();
|
||||
|
||||
ResolvedPromise low(v & 0xFFFFFFFF);
|
||||
Assembler::Constant al(&low);
|
||||
|
||||
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
|
||||
Assembler::Constant ah(&high);
|
||||
|
||||
Assembler::Register bh(b->high);
|
||||
|
||||
longCompare(c, &al, &ah, b, &bh, CAST2(compareCR), CAST2(moveCR));
|
||||
}
|
||||
|
||||
void
|
||||
longCompareRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, size == 8);
|
||||
|
||||
Assembler::Register ah(a->high);
|
||||
Assembler::Register bh(b->high);
|
||||
|
||||
longCompare(c, a, &ah, b, &bh, CAST2(compareRR), CAST2(moveCR));
|
||||
}
|
||||
|
||||
void
|
||||
populateTables()
|
||||
{
|
||||
@ -1826,6 +1902,7 @@ populateTables()
|
||||
BinaryOperations[INDEX2(Move, Address, Memory)] = CAST2(moveAM);
|
||||
BinaryOperations[INDEX2(Move, Memory, Memory)] = CAST2(moveMM);
|
||||
|
||||
BinaryOperations[INDEX2(Move4To8, Constant, Register)] = CAST2(move4To8CR);
|
||||
BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR);
|
||||
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
|
||||
|
||||
@ -1874,6 +1951,11 @@ populateTables()
|
||||
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
||||
BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR);
|
||||
|
||||
BinaryOperations[INDEX2(LongCompare, Constant, Register)]
|
||||
= CAST2(longCompareCR);
|
||||
BinaryOperations[INDEX2(LongCompare, Register, Register)]
|
||||
= CAST2(longCompareRR);
|
||||
|
||||
BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR);
|
||||
BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC);
|
||||
BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR);
|
||||
|
@ -95,6 +95,22 @@ public class Misc {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
{ long foo = 25214903884L;
|
||||
int radix = 10;
|
||||
expect(foo > 0);
|
||||
foo /= radix;
|
||||
expect(foo > 0);
|
||||
}
|
||||
|
||||
expect(String.valueOf(25214903884l).equals("25214903884"));
|
||||
|
||||
{ boolean p = true;
|
||||
int[] array = new int[] { 1, 2 };
|
||||
expect(array[0] == array[p ? 0 : 1]);
|
||||
p = false;
|
||||
expect(array[1] == array[p ? 0 : 1]);
|
||||
}
|
||||
|
||||
expect(roundUp(156, 2) == 156);
|
||||
|
||||
{ Foo foo = new Foo();
|
||||
@ -185,6 +201,39 @@ public class Misc {
|
||||
expect(~a == ~5L);
|
||||
}
|
||||
|
||||
{ long a = -25214903884L;
|
||||
long b = 2;
|
||||
expect(a >> b == -25214903884L >> 2);
|
||||
expect(a >>> b == -25214903884L >>> 2);
|
||||
expect(a << b == -25214903884L << 2);
|
||||
expect(a + b == -25214903884L + 2L);
|
||||
expect(a - b == -25214903884L - 2L);
|
||||
expect(a * b == -25214903884L * 2L);
|
||||
expect(a / b == -25214903884L / 2L);
|
||||
expect(a % b == -25214903884L % 2L);
|
||||
expect((a & b) == (-25214903884L & 2L));
|
||||
expect((a | b) == (-25214903884L | 2L));
|
||||
expect((a ^ b) == (-25214903884L ^ 2L));
|
||||
expect(-a == 25214903884L);
|
||||
expect(~a == ~-25214903884L);
|
||||
|
||||
a = 25214903884L;
|
||||
b = 2;
|
||||
expect(a >> b == 25214903884L >> 2);
|
||||
expect(a >>> b == 25214903884L >>> 2);
|
||||
expect(a << b == 25214903884L << 2);
|
||||
expect(a + b == 25214903884L + 2L);
|
||||
expect(a - b == 25214903884L - 2L);
|
||||
expect(a * b == 25214903884L * 2L);
|
||||
expect(a / b == 25214903884L / 2L);
|
||||
expect(a % b == 25214903884L % 2L);
|
||||
expect((a & b) == (25214903884L & 2L));
|
||||
expect((a | b) == (25214903884L | 2L));
|
||||
expect((a ^ b) == (25214903884L ^ 2L));
|
||||
expect(-a == -25214903884L);
|
||||
expect(~a == ~25214903884L);
|
||||
}
|
||||
|
||||
byte2 = 0;
|
||||
expect(byte2 == 0);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user