mirror of
https://github.com/corda/corda.git
synced 2025-03-18 01:55:19 +00:00
fix 64-bit arithmetic support on x86-32
This commit is contained in:
parent
0dfdcd87d9
commit
f116225933
@ -482,16 +482,3 @@ Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e, jclass, jdouble val,
|
||||
e->ReleaseByteArrayElements(buffer, buf, 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_lang_Long_printLong(JNIEnv*, jclass, jlong v)
|
||||
{
|
||||
fprintf(stderr, "DEBUG: %lld\n", v);
|
||||
}
|
||||
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_lang_Long_printInt(JNIEnv*, jclass, jint v)
|
||||
{
|
||||
fprintf(stderr, "DEBUG: %d\n", v);
|
||||
}
|
||||
|
@ -38,16 +38,11 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
private static native void printLong(long v);
|
||||
private static native void printInt(long v);
|
||||
|
||||
public static String toString(long v, int radix) {
|
||||
if (radix < 1 || radix > 36) {
|
||||
throw new IllegalArgumentException("radix " + radix + " not in [1,36]");
|
||||
}
|
||||
|
||||
printLong(v);
|
||||
|
||||
if (v == 0) {
|
||||
return "0";
|
||||
}
|
||||
@ -58,13 +53,10 @@ public final class Long extends Number implements Comparable<Long> {
|
||||
int size = (negative ? 1 : 0);
|
||||
for (long n = v; n > 0; n /= radix) ++size;
|
||||
|
||||
printInt(size);
|
||||
|
||||
char[] array = new char[size];
|
||||
|
||||
int i = array.length - 1;
|
||||
for (long n = v; n > 0; n /= radix) {
|
||||
printLong(n);
|
||||
long digit = n % radix;
|
||||
if (digit >= 0 && digit <= 9) {
|
||||
array[i] = (char) ('0' + digit);
|
||||
|
452
src/compile.cpp
452
src/compile.cpp
@ -18,7 +18,7 @@ vmJump(void* address, void* base, void* stack, void* thread);
|
||||
|
||||
namespace {
|
||||
|
||||
const bool Verbose = true;
|
||||
const bool Verbose = false;
|
||||
const bool DebugTraces = false;
|
||||
|
||||
class MyThread: public Thread {
|
||||
@ -643,7 +643,7 @@ class Frame {
|
||||
assert(t, sp - 2 >= localSize(t, method));
|
||||
assert(t, getBit(map, sp - 1) == 0);
|
||||
assert(t, getBit(map, sp - 2) == 0);
|
||||
return c->stack(stack, 1);
|
||||
return c->stack(stack, 0);
|
||||
}
|
||||
|
||||
Operand* topObject() {
|
||||
@ -695,8 +695,7 @@ class Frame {
|
||||
assert(t, index < codeMaxLocals(t, methodCode(t, method)));
|
||||
assert(t, index < parameterFootprint(t, method)
|
||||
or getBit(map, index - parameterFootprint(t, method)) == 0);
|
||||
pushInt
|
||||
(c->signExtend4(c->memory(c->base(), localOffset(t, index, method))));
|
||||
pushInt(c->select4(c->memory(c->base(), localOffset(t, index, method))));
|
||||
}
|
||||
|
||||
void loadLong(unsigned index) {
|
||||
@ -706,7 +705,11 @@ class Frame {
|
||||
or getBit(map, index - parameterFootprint(t, method)) == 0);
|
||||
assert(t, index < parameterFootprint(t, method)
|
||||
or getBit(map, index + 1 - parameterFootprint(t, method)) == 0);
|
||||
pushLong(c->select8(c->memory(c->base(), localOffset(t, index, method))));
|
||||
pushLong
|
||||
(c->select8
|
||||
(c->memory
|
||||
(c->base(),
|
||||
localOffset(t, index + (4 / BytesPerWord), method))));
|
||||
}
|
||||
|
||||
void loadObject(unsigned index) {
|
||||
@ -722,7 +725,11 @@ class Frame {
|
||||
}
|
||||
|
||||
void storeLong(unsigned index) {
|
||||
popLong(c->select8(c->memory(c->base(), localOffset(t, index, method))));
|
||||
popLong
|
||||
(c->select8
|
||||
(c->memory
|
||||
(c->base(),
|
||||
localOffset(t, index + (4 / BytesPerWord), method))));
|
||||
storedInt(index);
|
||||
storedInt(index + 1);
|
||||
}
|
||||
@ -1180,10 +1187,18 @@ compileThrowNew(MyThread* t, Frame* frame, Machine::Type type)
|
||||
frame->trace();
|
||||
}
|
||||
|
||||
void
|
||||
checkCast(MyThread* t, object class_, object o)
|
||||
{
|
||||
if (UNLIKELY(o and not isAssignableFrom(t, class_, objectClass(t, o)))) {
|
||||
throwNew(t, arrayBody(t, t->m->types, Machine::ClassCastExceptionType));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pushReturnValue(MyThread* t, Frame* frame, unsigned code)
|
||||
{
|
||||
Object* result = c->result();
|
||||
Operand* result = frame->c->result();
|
||||
|
||||
switch (code) {
|
||||
case ByteField:
|
||||
@ -1192,7 +1207,7 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code)
|
||||
case ShortField:
|
||||
case FloatField:
|
||||
case IntField:
|
||||
frame->pushInt(c->signExtend4(result));
|
||||
frame->pushInt(frame->c->select4(result));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
@ -1201,7 +1216,7 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code)
|
||||
|
||||
case LongField:
|
||||
case DoubleField:
|
||||
frame->pushLong(c->select8(result));
|
||||
frame->pushLong(frame->c->select8(result));
|
||||
break;
|
||||
|
||||
case VoidField:
|
||||
@ -1211,13 +1226,13 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code)
|
||||
abort(t);
|
||||
}
|
||||
|
||||
c->release(c);
|
||||
frame->c->release(result);
|
||||
}
|
||||
|
||||
void
|
||||
compileDirectInvoke(MyThread* t, Frame* frame, object target)
|
||||
{
|
||||
Operand* result = frame->c->alignedCall
|
||||
frame->c->alignedCall
|
||||
(frame->c->constant
|
||||
(reinterpret_cast<intptr_t>
|
||||
(&singletonBody(t, methodCompiled(t, target), 0))));
|
||||
@ -1226,7 +1241,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target)
|
||||
|
||||
frame->pop(methodParameterFootprint(t, target));
|
||||
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1280,15 +1295,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
case faload:
|
||||
case iaload:
|
||||
frame->pushInt(c->signExtend4(c->memory(array, ArrayBody, index, 4)));
|
||||
frame->pushInt(c->select4(c->memory(array, ArrayBody, index, 4)));
|
||||
break;
|
||||
|
||||
case baload:
|
||||
frame->pushInt(c->signExtend1(c->memory(array, ArrayBody, index, 1)));
|
||||
frame->pushInt(c->select1(c->memory(array, ArrayBody, index, 1)));
|
||||
break;
|
||||
|
||||
case caload:
|
||||
frame->pushInt(c->zeroExtend2(c->memory(array, ArrayBody, index, 2)));
|
||||
frame->pushInt(c->select2z(c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
|
||||
case daload:
|
||||
@ -1297,7 +1312,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
break;
|
||||
|
||||
case saload:
|
||||
frame->pushInt(c->signExtend2(c->memory(array, ArrayBody, index, 2)));
|
||||
frame->pushInt(c->select2(c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1425,15 +1440,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
c->mark(nonnegative);
|
||||
|
||||
Operand* r = c->indirectCall
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(makeBlankObjectArray)),
|
||||
3, c->thread(), frame->append(class_), length);
|
||||
|
||||
Operand* result = c->result();
|
||||
|
||||
c->release(length);
|
||||
|
||||
frame->trace();
|
||||
|
||||
frame->pushObject(r);
|
||||
frame->pushObject(result);
|
||||
c->release(result);
|
||||
} break;
|
||||
|
||||
case areturn: {
|
||||
@ -1489,68 +1507,63 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* next = c->label();
|
||||
|
||||
Operand* instance = frame->topObject();
|
||||
Operand* tmp = c->temporary();
|
||||
|
||||
c->mov(instance, tmp);
|
||||
|
||||
c->cmp(c->constant(0), tmp);
|
||||
c->je(next);
|
||||
|
||||
Operand* classOperand = frame->append(class_);
|
||||
|
||||
c->mov(c->memory(tmp), tmp);
|
||||
c->and_(c->constant(PointerMask), tmp);
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(checkCast)),
|
||||
3, c->thread(), classOperand, instance);
|
||||
|
||||
c->cmp(classOperand, tmp);
|
||||
c->je(next);
|
||||
|
||||
Operand* result = c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(isAssignableFrom)),
|
||||
3, c->thread(), classOperand, tmp);
|
||||
|
||||
c->release(tmp);
|
||||
|
||||
c->cmp(c->constant(0), result);
|
||||
c->jne(next);
|
||||
|
||||
compileThrowNew(t, frame, Machine::ClassCastExceptionType);
|
||||
|
||||
c->mark(next);
|
||||
frame->trace();
|
||||
} break;
|
||||
|
||||
case d2f: {
|
||||
Operand* a = frame->popLong();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(doubleToFloat)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(doubleToFloat)), 1, a);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case d2i: {
|
||||
Operand* a = frame->popLong();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(doubleToInt)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(doubleToInt)), 1, a);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case d2l: {
|
||||
Operand* a = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(doubleToLong)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(doubleToLong)), 1, a);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case dadd: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(addDouble)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(addDouble)), 2, a, b);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1558,9 +1571,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case dcmpg: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareDoublesG)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareDoublesG)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1568,9 +1585,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case dcmpl: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareDoublesL)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareDoublesL)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1586,9 +1607,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case ddiv: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(divideDouble)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(divideDouble)), 2, a, b);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1596,27 +1621,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case dmul: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(multiplyDouble)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(multiplyDouble)), 2, a, b);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
|
||||
case dneg: {
|
||||
Operand* a = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(negateDouble)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(negateDouble)), 1, a);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case vm::drem: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(moduloDouble)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(moduloDouble)), 2, a, b);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1624,9 +1661,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case dsub: {
|
||||
Operand* a = frame->popLong();
|
||||
Operand* b = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(subtractDouble)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(subtractDouble)), 2, a, b);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1657,34 +1698,50 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
case f2d: {
|
||||
Operand* a = frame->popInt();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(floatToDouble)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(floatToDouble)), 1, a);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case f2i: {
|
||||
Operand* a = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(floatToInt)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(floatToInt)), 1, a);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case f2l: {
|
||||
Operand* a = frame->popInt();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(floatToLong)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(floatToLong)), 1, a);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case fadd: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(addFloat)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(addFloat)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1692,9 +1749,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case fcmpg: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareFloatsG)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareFloatsG)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1702,9 +1763,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case fcmpl: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareFloatsL)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compareFloatsL)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1724,9 +1789,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case fdiv: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(divideFloat)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(divideFloat)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1734,27 +1803,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case fmul: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(multiplyFloat)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(multiplyFloat)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
|
||||
case fneg: {
|
||||
Operand* a = frame->popLong();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(negateFloat)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(negateFloat)), 1, a);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case vm::frem: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(moduloFloat)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(moduloFloat)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1762,9 +1843,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case fsub: {
|
||||
Operand* a = frame->popInt();
|
||||
Operand* b = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(subtractFloat)), 2, a, b));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(subtractFloat)), 2, a, b);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
c->release(b);
|
||||
} break;
|
||||
@ -1793,23 +1878,23 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
frame->pushInt
|
||||
(c->signExtend1(c->memory(table, fieldOffset(t, field))));
|
||||
(c->select1(c->memory(table, fieldOffset(t, field))));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
frame->pushInt
|
||||
(c->zeroExtend2(c->memory(table, fieldOffset(t, field))));
|
||||
(c->select2z(c->memory(table, fieldOffset(t, field))));
|
||||
break;
|
||||
|
||||
case ShortField:
|
||||
frame->pushInt
|
||||
(c->signExtend2(c->memory(table, fieldOffset(t, field))));
|
||||
(c->select2(c->memory(table, fieldOffset(t, field))));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
case IntField:
|
||||
frame->pushInt
|
||||
(c->signExtend4(c->memory(table, fieldOffset(t, field))));
|
||||
(c->select4(c->memory(table, fieldOffset(t, field))));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
@ -1849,39 +1934,47 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
case i2b: {
|
||||
Operand* top = frame->topInt();
|
||||
c->mov(c->signExtend1(top), top);
|
||||
c->mov(c->select1(top), top);
|
||||
} break;
|
||||
|
||||
case i2c: {
|
||||
Operand* top = frame->topInt();
|
||||
c->mov(c->zeroExtend2(top), top);
|
||||
c->mov(c->select2z(top), top);
|
||||
} break;
|
||||
|
||||
case i2d: {
|
||||
Operand* a = frame->popInt();
|
||||
frame->pushLong
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(intToDouble)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(intToDouble)), 1, a);
|
||||
|
||||
Operand* result = c->select8(c->result());
|
||||
frame->pushLong(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case i2f: {
|
||||
Operand* a = frame->popInt();
|
||||
frame->pushInt
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(intToFloat)), 1, a));
|
||||
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(intToFloat)), 1, a);
|
||||
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
c->release(result);
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case i2l: {
|
||||
Operand* a = frame->popInt();
|
||||
frame->pushLong(c->signExtend4(a));
|
||||
frame->pushLong(c->select8From4(a));
|
||||
c->release(a);
|
||||
} break;
|
||||
|
||||
case i2s: {
|
||||
Operand* top = frame->topInt();
|
||||
c->mov(c->signExtend2(top), top);
|
||||
c->mov(c->select2(top), top);
|
||||
} break;
|
||||
|
||||
case iadd: {
|
||||
@ -2096,50 +2189,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* call = c->label();
|
||||
Operand* next = c->label();
|
||||
Operand* zero = c->label();
|
||||
|
||||
Operand* instance = frame->popObject();
|
||||
Operand* tmp = c->temporary();
|
||||
Operand* result = c->temporary();
|
||||
|
||||
c->mov(instance, tmp);
|
||||
|
||||
c->cmp(c->constant(0), tmp);
|
||||
c->je(zero);
|
||||
|
||||
Operand* classOperand = frame->append(class_);
|
||||
|
||||
c->mov(c->memory(tmp), tmp);
|
||||
c->and_(c->constant(PointerMask), tmp);
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(instanceOf)),
|
||||
3, c->thread(), classOperand, instance);
|
||||
|
||||
c->cmp(classOperand, tmp);
|
||||
c->jne(call);
|
||||
|
||||
c->mov(c->constant(1), result);
|
||||
c->jmp(next);
|
||||
|
||||
c->mark(call);
|
||||
|
||||
c->mov
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(isAssignableFrom)),
|
||||
3, c->thread(), classOperand, tmp), result);
|
||||
|
||||
c->release(tmp);
|
||||
c->release(instance);
|
||||
|
||||
c->jmp(next);
|
||||
|
||||
c->mark(zero);
|
||||
|
||||
c->mov(c->constant(0), result);
|
||||
|
||||
c->mark(next);
|
||||
Operand* result = c->select4(c->result());
|
||||
frame->pushInt(result);
|
||||
|
||||
c->release(result);
|
||||
c->release(instance);
|
||||
} break;
|
||||
|
||||
case invokeinterface: {
|
||||
@ -2153,18 +2214,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
unsigned instance = parameterFootprint - 1;
|
||||
|
||||
Operand* result = c->call
|
||||
(c->directCall
|
||||
c->directCall
|
||||
(c->constant
|
||||
(reinterpret_cast<intptr_t>(findInterfaceMethodFromInstance)),
|
||||
3, c->thread(), frame->append(target),
|
||||
c->stack(frame->stack, instance)));
|
||||
c->stack(frame->stack, instance));
|
||||
|
||||
Operand* result = c->result();
|
||||
c->call(result);
|
||||
c->release(result);
|
||||
|
||||
frame->trace(target, true);
|
||||
|
||||
frame->pop(parameterFootprint);
|
||||
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target));
|
||||
} break;
|
||||
|
||||
case invokespecial: {
|
||||
@ -2213,7 +2277,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->mov(c->memory(instance), class_);
|
||||
c->and_(c->constant(PointerMask), class_);
|
||||
|
||||
Operand* result = c->call(c->memory(class_, offset));
|
||||
c->call(c->memory(class_, offset));
|
||||
|
||||
frame->trace(target, true);
|
||||
|
||||
@ -2221,7 +2285,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
frame->pop(parameterFootprint);
|
||||
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target));
|
||||
} break;
|
||||
|
||||
case ior: {
|
||||
@ -2349,11 +2413,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
} break;
|
||||
|
||||
case lconst_0:
|
||||
frame->pushLong(c->constant(0));
|
||||
frame->pushLong(c->select8(c->constant(0)));
|
||||
break;
|
||||
|
||||
case lconst_1:
|
||||
frame->pushLong(c->constant(1));
|
||||
frame->pushLong(c->select8(c->constant(1)));
|
||||
break;
|
||||
|
||||
case ldc:
|
||||
@ -2392,7 +2456,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
uint64_t v;
|
||||
memcpy(&v, &singletonValue(t, pool, index - 1), 8);
|
||||
frame->pushLong(c->constant(v));
|
||||
frame->pushLong(c->select8(c->constant(v)));
|
||||
} break;
|
||||
|
||||
case ldiv_: {
|
||||
@ -2469,10 +2533,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
}
|
||||
assert(t, start);
|
||||
|
||||
c->jmp
|
||||
(c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(lookUpAddress)),
|
||||
4, key, start, c->constant(pairCount), default_));
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(lookUpAddress)),
|
||||
4, key, start, c->constant(pairCount), default_);
|
||||
|
||||
Operand* result = c->result();
|
||||
c->jmp(result);
|
||||
c->release(result);
|
||||
|
||||
c->release(key);
|
||||
|
||||
@ -2587,15 +2654,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
PROTECT(t, class_);
|
||||
|
||||
Operand* result = c->indirectCall
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(makeMultidimensionalArray)),
|
||||
4, c->thread(), frame->append(class_), c->stack(),
|
||||
c->constant(dimensions));
|
||||
|
||||
Operand* result = c->result();
|
||||
|
||||
frame->trace();
|
||||
|
||||
frame->pop(dimensions);
|
||||
frame->pushObject(result);
|
||||
c->release(result);
|
||||
} break;
|
||||
|
||||
case new_: {
|
||||
@ -2608,20 +2678,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
initClass(t, class_);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Operand* result;
|
||||
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
||||
result = c->indirectCall
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(makeNewWeakReference)),
|
||||
2, c->thread(), frame->append(class_));
|
||||
} else {
|
||||
result = c->indirectCall
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(makeNew)),
|
||||
2, c->thread(), frame->append(class_));
|
||||
}
|
||||
|
||||
Operand* result = c->result();
|
||||
|
||||
frame->trace();
|
||||
|
||||
frame->pushObject(result);
|
||||
c->release(result);
|
||||
} break;
|
||||
|
||||
case newarray: {
|
||||
@ -2675,16 +2747,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
default: abort(t);
|
||||
}
|
||||
|
||||
Operand* result = c->indirectCall
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
|
||||
3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
|
||||
size);
|
||||
|
||||
Operand* result = c->result();
|
||||
|
||||
c->release(size);
|
||||
|
||||
frame->trace();
|
||||
|
||||
frame->pushObject(result);
|
||||
c->release(result);
|
||||
} break;
|
||||
|
||||
case nop: break;
|
||||
@ -3007,13 +3082,13 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
||||
}
|
||||
|
||||
// for debugging:
|
||||
if (//false and
|
||||
if (false and
|
||||
strcmp(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
|
||||
"java/lang/Long") == 0 and
|
||||
"java/lang/String") == 0 and
|
||||
strcmp(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodName(t, method), 0)),
|
||||
"toString") == 0)
|
||||
"getBytes") == 0)
|
||||
{
|
||||
asm("int3");
|
||||
}
|
||||
@ -3182,7 +3257,11 @@ invokeNative2(MyThread* t, object method)
|
||||
|
||||
case INT64_TYPE:
|
||||
case DOUBLE_TYPE: {
|
||||
memcpy(args + argOffset, sp, 8);
|
||||
if (BytesPerWord == 8) {
|
||||
memcpy(args + argOffset, sp, 8);
|
||||
} else {
|
||||
memcpy(args + argOffset, sp - 1, 8);
|
||||
}
|
||||
argOffset += (8 / BytesPerWord);
|
||||
sp -= 2;
|
||||
} break;
|
||||
@ -3363,10 +3442,13 @@ compileDefault(MyThread* t, Compiler* c)
|
||||
c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t)));
|
||||
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t)));
|
||||
|
||||
c->jmp
|
||||
(c->directCall
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(compileMethod)),
|
||||
1, c->thread()));
|
||||
1, c->thread());
|
||||
|
||||
Operand* result = c->result();
|
||||
c->jmp(result);
|
||||
c->release(result);
|
||||
|
||||
return finish(t, c);
|
||||
}
|
||||
|
529
src/compiler.cpp
529
src/compiler.cpp
@ -29,12 +29,10 @@ enum Register {
|
||||
enum SelectionType {
|
||||
Select1,
|
||||
Select2,
|
||||
Select2z,
|
||||
Select4,
|
||||
Select8,
|
||||
SignExtend1,
|
||||
SignExtend2,
|
||||
ZeroExtend2,
|
||||
SignExtend4
|
||||
Select8From4
|
||||
};
|
||||
|
||||
const bool Verbose = false;
|
||||
@ -42,7 +40,7 @@ const bool Verbose = false;
|
||||
const unsigned RegisterCount = BytesPerWord * 2;
|
||||
const unsigned GprParameterCount = 6;
|
||||
const SelectionType DefaultSelection
|
||||
= (BytesPerWord == 8 ? S8Selection : S4Selection);
|
||||
= (BytesPerWord == 8 ? Select8 : Select4);
|
||||
|
||||
class Context;
|
||||
class MyOperand;
|
||||
@ -55,6 +53,19 @@ class CodePromise;
|
||||
class MyPromise;
|
||||
class RegisterReference;
|
||||
|
||||
inline unsigned
|
||||
footprint(SelectionType selection)
|
||||
{
|
||||
switch (selection) {
|
||||
case Select8:
|
||||
case Select8From4:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
return BytesPerWord;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
divideLong(int64_t a, int64_t b)
|
||||
{
|
||||
@ -320,7 +331,7 @@ RegisterOperand*
|
||||
register_(Context* c, RegisterReference*, SelectionType = DefaultSelection);
|
||||
|
||||
RegisterOperand*
|
||||
register_(Context* c, Register, Register = NoRegister,
|
||||
register_(Context* c, Register = NoRegister, Register = NoRegister,
|
||||
SelectionType = DefaultSelection);
|
||||
|
||||
MemoryOperand*
|
||||
@ -429,38 +440,63 @@ release(Context* c, Register v)
|
||||
class RegisterReference {
|
||||
public:
|
||||
RegisterReference(Register value = NoRegister, Register high = NoRegister):
|
||||
value_(value), high_(high), acquireHigh(false)
|
||||
value_(value), defaultValue(value), high_(high), defaultHigh(high),
|
||||
acquired(true)
|
||||
{ }
|
||||
|
||||
void acquire(Context* c) {
|
||||
value_ = ::acquire(c);
|
||||
if (acquireHigh) {
|
||||
high_ = ::acquire(c);
|
||||
if (defaultValue != NoRegister) {
|
||||
::acquire(c, defaultValue);
|
||||
}
|
||||
|
||||
if (defaultHigh != NoRegister) {
|
||||
::acquire(c, defaultHigh);
|
||||
}
|
||||
|
||||
value_ = defaultValue;
|
||||
high_ = defaultHigh;
|
||||
|
||||
acquired = true;
|
||||
}
|
||||
|
||||
void release(Context* c) {
|
||||
::release(c, value_);
|
||||
value_ = NoRegister;
|
||||
assert(c, acquired);
|
||||
|
||||
if (value_ != NoRegister) {
|
||||
::release(c, value_);
|
||||
}
|
||||
|
||||
if (high_ != NoRegister) {
|
||||
::release(c, high_);
|
||||
}
|
||||
|
||||
value_ = NoRegister;
|
||||
high_ = NoRegister;
|
||||
|
||||
acquired = false;
|
||||
}
|
||||
|
||||
Register value(Context* c UNUSED) {
|
||||
assert(c, value_ != NoRegister);
|
||||
Register value(Context* c) {
|
||||
assert(c, acquired);
|
||||
if (value_ == NoRegister) {
|
||||
value_ = ::acquire(c);
|
||||
}
|
||||
return value_;
|
||||
}
|
||||
|
||||
Register high(Context* c UNUSED) {
|
||||
assert(c, high_ != NoRegister);
|
||||
Register high(Context* c) {
|
||||
assert(c, acquired);
|
||||
if (high_ == NoRegister) {
|
||||
high_ = ::acquire(c);
|
||||
}
|
||||
return high_;
|
||||
}
|
||||
|
||||
Register value_;
|
||||
Register defaultValue;
|
||||
Register high_;
|
||||
bool acquireHigh;
|
||||
Register defaultHigh;
|
||||
bool acquired;
|
||||
};
|
||||
|
||||
class RegisterOperand: public MyOperand {
|
||||
@ -478,7 +514,7 @@ class RegisterOperand: public MyOperand {
|
||||
}
|
||||
|
||||
virtual unsigned footprint(Context*) {
|
||||
return (selection == S8Selection ? 8 : BytesPerWord);
|
||||
return ::footprint(selection);
|
||||
}
|
||||
|
||||
virtual Register asRegister(Context* c) {
|
||||
@ -489,9 +525,6 @@ class RegisterOperand: public MyOperand {
|
||||
if (selection == this->selection) {
|
||||
return this;
|
||||
} else {
|
||||
if (selection == S8Selection and BytesPerWord == 4) {
|
||||
reference->acquireHigh = true;
|
||||
}
|
||||
return register_(c, reference, selection);
|
||||
}
|
||||
}
|
||||
@ -528,7 +561,7 @@ class ImmediateOperand: public MyOperand {
|
||||
{ }
|
||||
|
||||
virtual unsigned footprint(Context*) {
|
||||
return (selection == S8Selection ? 8 : BytesPerWord);
|
||||
return ::footprint(selection);
|
||||
}
|
||||
|
||||
virtual MyOperand* select(Context* c, SelectionType selection) {
|
||||
@ -610,7 +643,7 @@ class MemoryOperand: public MyOperand {
|
||||
{ }
|
||||
|
||||
virtual unsigned footprint(Context*) {
|
||||
return (selection == S8Selection ? 8 : BytesPerWord);
|
||||
return ::footprint(selection);
|
||||
}
|
||||
|
||||
virtual Register asRegister(Context*);
|
||||
@ -698,7 +731,7 @@ temporary(Context* c)
|
||||
RegisterOperand*
|
||||
temporary(Context* c, SelectionType selection)
|
||||
{
|
||||
if (BytesPerWord == 4 and selection == S8Selection) {
|
||||
if (BytesPerWord == 4 and selection == Select8) {
|
||||
return register_(c, acquire(c), acquire(c), selection);
|
||||
} else {
|
||||
return register_(c, acquire(c), NoRegister, selection);
|
||||
@ -712,6 +745,14 @@ temporary(Context* c, Register v)
|
||||
return register_(c, v);
|
||||
}
|
||||
|
||||
RegisterOperand*
|
||||
temporary(Context* c, Register v, Register h)
|
||||
{
|
||||
acquire(c, v);
|
||||
acquire(c, h);
|
||||
return register_(c, v, h);
|
||||
}
|
||||
|
||||
Segment*
|
||||
currentSegment(Context* c)
|
||||
{
|
||||
@ -793,6 +834,9 @@ class AcquireEvent: public Event {
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "acquire register\n");
|
||||
}
|
||||
operand->reference->acquire(c);
|
||||
}
|
||||
|
||||
@ -807,6 +851,9 @@ class ReleaseEvent: public Event {
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "release register\n");
|
||||
}
|
||||
operand->release(c);
|
||||
}
|
||||
|
||||
@ -954,18 +1001,38 @@ appendArgumentEvent(Context* c, MyOperand** arguments, unsigned count)
|
||||
ArgumentEvent(arguments, count, s->event);
|
||||
}
|
||||
|
||||
MyStack*
|
||||
pushed(Context* c, MyStack* stack, unsigned footprint)
|
||||
void
|
||||
logStack(Context* c, MyStack* stack)
|
||||
{
|
||||
int index = (stack ?
|
||||
stack->index + (stack->value->footprint(c) / BytesPerWord) :
|
||||
0);
|
||||
fprintf(stderr, "ip %3d: ", currentSegment(c)->logicalIp);
|
||||
|
||||
if (stack) {
|
||||
fprintf(stderr, " %d",
|
||||
static_cast<MemoryOperand*>(stack->value)->displacement);
|
||||
}
|
||||
|
||||
for (MyStack* s = stack; s; s = s->next) {
|
||||
fprintf(stderr, "*");
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
MyStack*
|
||||
pushed(Context* c, MyStack* stack)
|
||||
{
|
||||
int index = (stack ? stack->index + 1 : 0);
|
||||
|
||||
MyOperand* value = memory
|
||||
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1,
|
||||
footprint == (BytesPerWord * 2) ? S8Selection : DefaultSelection);
|
||||
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1);
|
||||
|
||||
return new (c->zone.allocate(sizeof(MyStack))) MyStack(value, index, stack);
|
||||
stack = new (c->zone.allocate(sizeof(MyStack))) MyStack(value, index, stack);
|
||||
|
||||
if (Verbose) {
|
||||
logStack(c, stack);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
MyStack*
|
||||
@ -973,7 +1040,10 @@ push(Context* c, MyStack* stack, MyOperand* v)
|
||||
{
|
||||
appendOperation(c, MyOperand::push, v);
|
||||
|
||||
return pushed(c, stack, v->footprint(c));
|
||||
if ((v->footprint(c) / BytesPerWord) == 2) {
|
||||
stack = pushed(c, stack);
|
||||
}
|
||||
return pushed(c, stack);
|
||||
}
|
||||
|
||||
MyStack*
|
||||
@ -983,11 +1053,15 @@ pop(Context* c, MyStack* stack, int count)
|
||||
(c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp));
|
||||
|
||||
while (count) {
|
||||
count -= (stack->value->footprint(c) / BytesPerWord);
|
||||
-- count;
|
||||
assert(c, count >= 0);
|
||||
stack = stack->next;
|
||||
}
|
||||
|
||||
if (Verbose) {
|
||||
logStack(c, stack);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
@ -996,6 +1070,14 @@ pop(Context* c, MyStack* stack, MyOperand* dst)
|
||||
{
|
||||
appendOperation(c, MyOperand::pop, dst);
|
||||
|
||||
if (dst->footprint(c) / BytesPerWord == 2) {
|
||||
stack = stack->next;
|
||||
}
|
||||
|
||||
if (Verbose) {
|
||||
logStack(c, stack->next);
|
||||
}
|
||||
|
||||
return stack->next;
|
||||
}
|
||||
|
||||
@ -1031,6 +1113,17 @@ rex(Context* c)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rex(Context* c, SelectionType selection)
|
||||
{
|
||||
if (selection == Select8) {
|
||||
assert(c, BytesPerWord == 8);
|
||||
rex(c);
|
||||
} else {
|
||||
assert(c, selection == Select4);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
encode(Context* c, uint8_t* instruction, unsigned length, int a, Register b,
|
||||
int32_t displacement, int index, unsigned scale)
|
||||
@ -1077,6 +1170,15 @@ encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex)
|
||||
encode(c, &instruction, 1, a, r, b->displacement, index, b->scale);
|
||||
}
|
||||
|
||||
void
|
||||
encode(Context* c, uint8_t instruction, int a, MemoryOperand* b,
|
||||
SelectionType selection)
|
||||
{
|
||||
assert(c, selection == DefaultSelection or selection == Select4);
|
||||
|
||||
encode(c, instruction, a, b, selection == DefaultSelection);
|
||||
}
|
||||
|
||||
void
|
||||
encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex)
|
||||
{
|
||||
@ -1092,51 +1194,64 @@ encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex)
|
||||
void
|
||||
RegisterOperand::apply(Context* c, Operation operation)
|
||||
{
|
||||
assert(c, operation == push
|
||||
or operation == pop
|
||||
or selection == DefaultSelection);
|
||||
|
||||
switch (operation) {
|
||||
case call:
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
c->code.append(0xff);
|
||||
c->code.append(0xd0 | value(c));
|
||||
break;
|
||||
|
||||
case jmp:
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
c->code.append(0xff);
|
||||
c->code.append(0xe0 | value(c));
|
||||
break;
|
||||
|
||||
case pop:
|
||||
if (selection == DefaultSelection) {
|
||||
if (selection == DefaultSelection or selection == Select4) {
|
||||
c->code.append(0x58 | value(c));
|
||||
} else {
|
||||
switch (selection) {
|
||||
case S8Selection:
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, selection == Select8);
|
||||
|
||||
register_(c, value(c))->apply(c, pop);
|
||||
register_(c, high(c))->apply(c, pop);
|
||||
register_(c, value(c))->apply(c, pop);
|
||||
register_(c, high(c))->apply(c, pop);
|
||||
}
|
||||
break;
|
||||
|
||||
case push:
|
||||
if (selection == DefaultSelection or selection == Select4
|
||||
or (BytesPerWord == 8 and selection == Select8From4))
|
||||
{
|
||||
c->code.append(0x50 | value(c));
|
||||
} else {
|
||||
switch (selection) {
|
||||
case Select8:
|
||||
register_(c, high(c))->apply(c, push);
|
||||
register_(c, value(c))->apply(c, push);
|
||||
break;
|
||||
|
||||
case Select8From4: {
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
|
||||
ax->accept(c, mov, register_(c, value(c)));
|
||||
c->code.append(0x99); // cdq
|
||||
dx->apply(c, push);
|
||||
ax->apply(c, push);
|
||||
|
||||
ax->release(c);
|
||||
dx->release(c);
|
||||
} break;
|
||||
|
||||
default: abort(c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case push:
|
||||
if (selection == DefaultSelection or selection == S4Selection) {
|
||||
c->code.append(0x50 | value(c));
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
|
||||
register_(c, high(c))->apply(c, push);
|
||||
register_(c, value(c))->apply(c, push);
|
||||
}
|
||||
break;
|
||||
|
||||
case neg:
|
||||
rex(c);
|
||||
rex(c, selection);
|
||||
c->code.append(0xf7);
|
||||
c->code.append(0xd8 | value(c));
|
||||
break;
|
||||
@ -1151,21 +1266,27 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
{
|
||||
switch (operation) {
|
||||
case add:
|
||||
rex(c);
|
||||
assert(c, selection == operand->selection);
|
||||
|
||||
rex(c, operand->selection);
|
||||
c->code.append(0x01);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
break;
|
||||
|
||||
case cmp:
|
||||
if (selection == DefaultSelection) {
|
||||
rex(c);
|
||||
assert(c, selection == operand->selection);
|
||||
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
rex(c, operand->selection);
|
||||
c->code.append(0x39);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, operand->selection == Select8);
|
||||
|
||||
register_(c, high(c))->accept
|
||||
(c, mov, register_(c, operand->high(c)));
|
||||
(c, cmp, register_(c, operand->high(c)));
|
||||
|
||||
// if the high order bits are equal, we compare the low order
|
||||
// bits; otherwise, we jump past that comparison
|
||||
@ -1174,41 +1295,41 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
c->code.append4(2);
|
||||
|
||||
register_(c, value(c))->accept
|
||||
(c, mov, register_(c, operand->value(c)));
|
||||
(c, cmp, register_(c, operand->value(c)));
|
||||
}
|
||||
break;
|
||||
|
||||
case mov:
|
||||
if (value(c) != operand->value(c) or selection != operand->selection) {
|
||||
if (operand->selection == DefaultSelection) {
|
||||
rex(c);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
rex(c, selection);
|
||||
c->code.append(0x89);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
} else {
|
||||
switch (operand->selection) {
|
||||
case S1Selection:
|
||||
case Select1:
|
||||
c->code.append(0xbe);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
break;
|
||||
|
||||
case S2Selection:
|
||||
case Select2:
|
||||
c->code.append(0xbf);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
break;
|
||||
|
||||
case Z2Selection:
|
||||
case Select2z:
|
||||
c->code.append(0xb7);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
break;
|
||||
|
||||
case S4Selection:
|
||||
case Select4:
|
||||
c->code.append(0x89);
|
||||
c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
|
||||
break;
|
||||
|
||||
case S8Selection:
|
||||
assert(c, selection == S8Selection);
|
||||
|
||||
case Select8:
|
||||
register_(c, value(c))->accept
|
||||
(c, mov, register_(c, operand->value(c)));
|
||||
|
||||
@ -1223,7 +1344,9 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
break;
|
||||
|
||||
case mul:
|
||||
rex(c);
|
||||
assert(c, selection == operand->selection);
|
||||
|
||||
rex(c, selection);
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0xaf);
|
||||
c->code.append(0xc0 | (value(c) << 3) | operand->value(c));
|
||||
@ -1349,6 +1472,8 @@ void
|
||||
RegisterOperand::accept(Context* c, Operation operation,
|
||||
AddressOperand* operand)
|
||||
{
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
switch (operation) {
|
||||
case mov: {
|
||||
accept(c, operation, ::value(c, operand));
|
||||
@ -1362,38 +1487,43 @@ void
|
||||
RegisterOperand::accept(Context* c, Operation operation,
|
||||
MemoryOperand* operand)
|
||||
{
|
||||
assert(c, operation == mov or selection == DefaultSelection);
|
||||
assert(c, operation == mov or operand->selection == DefaultSelection);
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
switch (operation) {
|
||||
case cmp: {
|
||||
encode(c, 0x3b, value(c), operand, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x3b, value(c), operand, operand->selection);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mov: {
|
||||
if (operand->selection == DefaultSelection) {
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x8b, value(c), operand, true);
|
||||
} else {
|
||||
switch (operand->selection) {
|
||||
case S1Selection:
|
||||
case Select1:
|
||||
encode2(c, 0x0fbe, value(c), operand, true);
|
||||
break;
|
||||
|
||||
case S2Selection:
|
||||
case Select2:
|
||||
encode2(c, 0x0fbf, value(c), operand, true);
|
||||
break;
|
||||
|
||||
case Z2Selection:
|
||||
case Select2z:
|
||||
encode2(c, 0x0fb7, value(c), operand, true);
|
||||
break;
|
||||
|
||||
case S4Selection:
|
||||
case Select4:
|
||||
encode(c, 0x63, value(c), operand, true);
|
||||
break;
|
||||
|
||||
case S8Selection:
|
||||
assert(c, selection == S8Selection);
|
||||
|
||||
case Select8:
|
||||
register_(c, value(c))->accept
|
||||
(c, mov, memory
|
||||
(c, operand->base, operand->displacement,
|
||||
@ -1551,12 +1681,12 @@ AddressOperand::asRegister(Context* c)
|
||||
void
|
||||
ImmediateOperand::apply(Context* c, Operation operation)
|
||||
{
|
||||
assert(c, operation == push or selection == DefaultSelection);
|
||||
|
||||
switch (operation) {
|
||||
case alignedCall:
|
||||
case call:
|
||||
case jmp:
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
address(c, new (c->zone.allocate(sizeof(ResolvedPromise)))
|
||||
ResolvedPromise(value))->apply(c, operation);
|
||||
break;
|
||||
@ -1576,7 +1706,7 @@ ImmediateOperand::apply(Context* c, Operation operation)
|
||||
tmp->release(c);
|
||||
}
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, selection == Select8);
|
||||
|
||||
immediate(c, (value >> 32) & 0xFFFFFFFF)->apply(c, push);
|
||||
immediate(c, (value ) & 0xFFFFFFFF)->apply(c, push);
|
||||
@ -1634,18 +1764,22 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
{
|
||||
switch (operation) {
|
||||
case call:
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
encode(c, 0xff, 2, this, false);
|
||||
break;
|
||||
|
||||
case jmp:
|
||||
assert(c, selection == DefaultSelection);
|
||||
|
||||
encode(c, 0xff, 4, this, false);
|
||||
break;
|
||||
|
||||
case neg:
|
||||
if (selection == DefaultSelection) {
|
||||
encode(c, 0xf7, 2, this, true);
|
||||
encode(c, 0xf7, 2, this, selection);
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, selection == Select8);
|
||||
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
@ -1670,7 +1804,18 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
break;
|
||||
|
||||
case pop:
|
||||
encode(c, 0x8f, 0, this, false);
|
||||
if (selection == DefaultSelection) {
|
||||
encode(c, 0x8f, 0, this, false);
|
||||
} else {
|
||||
assert(c, selection == Select8);
|
||||
|
||||
MemoryOperand* low = memory(c, base, displacement, index, scale);
|
||||
MemoryOperand* high = memory
|
||||
(c, base, displacement + BytesPerWord, index, scale);
|
||||
|
||||
low->apply(c, pop);
|
||||
high->apply(c, pop);
|
||||
}
|
||||
break;
|
||||
|
||||
case push:
|
||||
@ -1678,7 +1823,7 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
encode(c, 0xff, 6, this, false);
|
||||
} else {
|
||||
switch (selection) {
|
||||
case S8Selection: {
|
||||
case Select8: {
|
||||
MemoryOperand* low = memory(c, base, displacement, index, scale);
|
||||
MemoryOperand* high = memory
|
||||
(c, base, displacement + BytesPerWord, index, scale);
|
||||
@ -1689,7 +1834,7 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
|
||||
default: {
|
||||
RegisterOperand* tmp = temporary
|
||||
(c, selection == S8Selection ? S8Selection : DefaultSelection);
|
||||
(c, selection == Select8 ? Select8 : DefaultSelection);
|
||||
tmp->accept(c, mov, this);
|
||||
tmp->apply(c, operation);
|
||||
tmp->release(c);
|
||||
@ -1708,14 +1853,22 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
{
|
||||
switch (operation) {
|
||||
case and_: {
|
||||
encode(c, 0x21, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x21, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
case add: {
|
||||
if (selection == DefaultSelection) {
|
||||
encode(c, 0x01, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x01, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, operand->selection == Select8);
|
||||
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
@ -1733,22 +1886,26 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
} break;
|
||||
|
||||
case addc:
|
||||
if (operand->selection == DefaultSelection) {
|
||||
encode(c, 0x11, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x11, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case div: {
|
||||
if (selection == DefaultSelection) {
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
ax->accept(c, mov, this);
|
||||
|
||||
rex(c);
|
||||
rex(c, operand->selection);
|
||||
c->code.append(0x99);
|
||||
rex(c);
|
||||
rex(c, operand->selection);
|
||||
c->code.append(0xf7);
|
||||
c->code.append(0xf8 | operand->value(c));
|
||||
|
||||
@ -1757,40 +1914,52 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
ax->release(c);
|
||||
dx->release(c);
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, operand->selection == Select8);
|
||||
|
||||
operand->apply(c, push);
|
||||
apply(c, push);
|
||||
memory(c, base, displacement, index, scale, Select8)->apply(c, push);
|
||||
immediate(c, reinterpret_cast<intptr_t>(divideLong))->apply(c, call);
|
||||
accept(c, mov, register_(c, rax, rdx, S8Selection));
|
||||
register_(c, rsp)->accept(c, add, immediate(c, 16));
|
||||
accept(c, mov, register_(c, rax, rdx, Select8));
|
||||
}
|
||||
} break;
|
||||
|
||||
case mov: {
|
||||
if (selection == DefaultSelection) {
|
||||
encode(c, 0x89, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x89, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
switch (selection) {
|
||||
case S1Selection:
|
||||
if (operand->value(c) > rbx) {
|
||||
c->code.append(0x40);
|
||||
switch (operand->selection) {
|
||||
case Select1:
|
||||
if (BytesPerWord == 8) {
|
||||
if (operand->value(c) > rbx) {
|
||||
c->code.append(0x40);
|
||||
}
|
||||
encode(c, 0x88, operand->value(c), this, false);
|
||||
} else {
|
||||
if (operand->value(c) > rbx) {
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
ax->accept(c, mov, register_(c, operand->value(c)));
|
||||
accept(c, mov, register_(c, rax, NoRegister, Select1));
|
||||
ax->release(c);
|
||||
} else {
|
||||
encode(c, 0x88, operand->value(c), this, false);
|
||||
}
|
||||
}
|
||||
encode(c, 0x88, operand->value(c), this, false);
|
||||
break;
|
||||
|
||||
case S2Selection:
|
||||
case Z2Selection:
|
||||
case Select2:
|
||||
case Select2z:
|
||||
c->code.append(0x66);
|
||||
encode(c, 0x89, operand->value(c), this, false);
|
||||
break;
|
||||
|
||||
case S4Selection:
|
||||
case Select4:
|
||||
encode(c, 0x89, operand->value(c), this, false);
|
||||
break;
|
||||
|
||||
case S8Selection:
|
||||
assert(c, operand->selection == S8Selection);
|
||||
|
||||
case Select8:
|
||||
memory(c, base, displacement, index, scale)->accept
|
||||
(c, mov, register_(c, operand->value(c)));
|
||||
|
||||
@ -1804,7 +1973,9 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
} break;
|
||||
|
||||
case mul: {
|
||||
if (selection == DefaultSelection) {
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
|
||||
tmp->accept(c, mov, this);
|
||||
@ -1813,6 +1984,8 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
|
||||
tmp->release(c);
|
||||
} else {
|
||||
assert(c, operand->selection == Select8);
|
||||
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
@ -1843,11 +2016,19 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
} break;
|
||||
|
||||
case or_: {
|
||||
encode(c, 0x09, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x09, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
case rem: {
|
||||
if (selection == DefaultSelection) {
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
ax->accept(c, mov, this);
|
||||
@ -1863,41 +2044,62 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
ax->release(c);
|
||||
dx->release(c);
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, operand->selection == Select8);
|
||||
|
||||
operand->apply(c, push);
|
||||
apply(c, push);
|
||||
memory(c, base, displacement, index, scale, Select8)->apply(c, push);
|
||||
immediate(c, reinterpret_cast<intptr_t>(moduloLong))->apply(c, call);
|
||||
accept(c, mov, register_(c, rax, rdx, S8Selection));
|
||||
register_(c, rsp)->accept(c, add, immediate(c, 16));
|
||||
accept(c, mov, register_(c, rax, rdx, Select8));
|
||||
}
|
||||
} break;
|
||||
|
||||
case shl: {
|
||||
RegisterOperand* cx = temporary(c, rcx);
|
||||
cx->accept(c, mov, operand);
|
||||
encode(c, 0xd3, 4, this, true);
|
||||
cx->release(c);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
RegisterOperand* cx = temporary(c, rcx);
|
||||
cx->accept(c, mov, operand);
|
||||
encode(c, 0xd3, 4, this, operand->selection);
|
||||
cx->release(c);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
case shr: {
|
||||
RegisterOperand* cx = temporary(c, rcx);
|
||||
cx->accept(c, mov, operand);
|
||||
encode(c, 0xd3, 5, this, true);
|
||||
cx->release(c);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
RegisterOperand* cx = temporary(c, rcx);
|
||||
cx->accept(c, mov, operand);
|
||||
encode(c, 0xd3, 5, this, operand->selection);
|
||||
cx->release(c);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
case ushr: {
|
||||
RegisterOperand* cx = temporary(c, rcx);
|
||||
cx->accept(c, mov, operand);
|
||||
encode(c, 0xd3, 7, this, true);
|
||||
cx->release(c);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
RegisterOperand* cx = temporary(c, rcx);
|
||||
cx->accept(c, mov, operand);
|
||||
encode(c, 0xd3, 7, this, operand->selection);
|
||||
cx->release(c);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
case sub: {
|
||||
if (selection == DefaultSelection) {
|
||||
encode(c, 0x29, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x29, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
assert(c, selection == S8Selection);
|
||||
assert(c, operand->selection == Select8);
|
||||
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
@ -1915,15 +2117,23 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
} break;
|
||||
|
||||
case subb:
|
||||
if (operand->selection == DefaultSelection) {
|
||||
encode(c, 0x19, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x19, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case xor_: {
|
||||
encode(c, 0x31, operand->value(c), this, true);
|
||||
if (operand->selection == DefaultSelection
|
||||
or operand->selection == Select4)
|
||||
{
|
||||
encode(c, 0x31, operand->value(c), this, operand->selection);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
} break;
|
||||
|
||||
default: abort(c);
|
||||
@ -2111,7 +2321,7 @@ class MyCompiler: public Compiler {
|
||||
MyStack* stack = static_cast<MyStack*>(s);
|
||||
while (count) {
|
||||
-- count;
|
||||
stack = ::pushed(&c, stack, BytesPerWord);
|
||||
stack = ::pushed(&c, stack);
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
@ -2122,17 +2332,10 @@ class MyCompiler: public Compiler {
|
||||
|
||||
virtual Operand* stack(Stack* s, unsigned index) {
|
||||
MyStack* stack = static_cast<MyStack*>(s);
|
||||
unsigned i = 0;
|
||||
|
||||
if (stack->value->footprint(&c) / BytesPerWord == 2) {
|
||||
++ i;
|
||||
}
|
||||
|
||||
for (; i < index; ++i) {
|
||||
while (index) {
|
||||
-- index;
|
||||
stack = stack->next;
|
||||
if (stack->value->footprint(&c) / BytesPerWord == 2) {
|
||||
++ i;
|
||||
}
|
||||
}
|
||||
|
||||
return stack->value;
|
||||
@ -2163,7 +2366,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Operand* temporary() {
|
||||
RegisterOperand* r = register_(&c, NoRegister);
|
||||
RegisterOperand* r = register_(&c);
|
||||
appendAcquire(&c, r);
|
||||
return r;
|
||||
}
|
||||
@ -2219,7 +2422,9 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Operand* result() {
|
||||
return ::temporary(&c, rax, rdx);
|
||||
RegisterOperand* r = register_(&c, rax, rdx);
|
||||
appendAcquire(&c, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual void return_(Operand* v) {
|
||||
@ -2339,6 +2544,10 @@ class MyCompiler: public Compiler {
|
||||
return static_cast<MyOperand*>(v)->select(&c, Select2);
|
||||
}
|
||||
|
||||
virtual Operand* select2z(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, Select2z);
|
||||
}
|
||||
|
||||
virtual Operand* select4(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, Select4);
|
||||
}
|
||||
@ -2347,20 +2556,8 @@ class MyCompiler: public Compiler {
|
||||
return static_cast<MyOperand*>(v)->select(&c, Select8);
|
||||
}
|
||||
|
||||
virtual Operand* signExtend1(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, SignExtend1);
|
||||
}
|
||||
|
||||
virtual Operand* signExtend2(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, SignExtend2);
|
||||
}
|
||||
|
||||
virtual Operand* zeroExtend2(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, ZeroExtend2);
|
||||
}
|
||||
|
||||
virtual Operand* signExtend4(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, SignExtend4);
|
||||
virtual Operand* select8From4(Operand* v) {
|
||||
return static_cast<MyOperand*>(v)->select(&c, Select8From4);
|
||||
}
|
||||
|
||||
virtual void prologue() {
|
||||
|
@ -36,13 +36,10 @@ class Compiler {
|
||||
|
||||
virtual Operand* select1(Operand*) = 0;
|
||||
virtual Operand* select2(Operand*) = 0;
|
||||
virtual Operand* select2z(Operand*) = 0;
|
||||
virtual Operand* select4(Operand*) = 0;
|
||||
virtual Operand* select8(Operand*) = 0;
|
||||
|
||||
virtual Operand* signExtend1(Operand*) = 0;
|
||||
virtual Operand* signExtend2(Operand*) = 0;
|
||||
virtual Operand* zeroExtend2(Operand*) = 0;
|
||||
virtual Operand* signExtend4(Operand*) = 0;
|
||||
virtual Operand* select8From4(Operand*) = 0;
|
||||
|
||||
virtual Operand* stack() = 0;
|
||||
virtual Operand* base() = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user