fix 64-bit arithmetic support on x86-32

This commit is contained in:
Joel Dice
2007-12-22 17:00:35 -07:00
parent 0dfdcd87d9
commit f116225933
5 changed files with 632 additions and 377 deletions

View File

@ -482,16 +482,3 @@ Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e, jclass, jdouble val,
e->ReleaseByteArrayElements(buffer, buf, 0); e->ReleaseByteArrayElements(buffer, buf, 0);
return count; 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);
}

View File

@ -38,16 +38,11 @@ public final class Long extends Number implements Comparable<Long> {
return String.valueOf(value); 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) { public static String toString(long v, int radix) {
if (radix < 1 || radix > 36) { if (radix < 1 || radix > 36) {
throw new IllegalArgumentException("radix " + radix + " not in [1,36]"); throw new IllegalArgumentException("radix " + radix + " not in [1,36]");
} }
printLong(v);
if (v == 0) { if (v == 0) {
return "0"; return "0";
} }
@ -58,13 +53,10 @@ public final class Long extends Number implements Comparable<Long> {
int size = (negative ? 1 : 0); int size = (negative ? 1 : 0);
for (long n = v; n > 0; n /= radix) ++size; for (long n = v; n > 0; n /= radix) ++size;
printInt(size);
char[] array = new char[size]; char[] array = new char[size];
int i = array.length - 1; int i = array.length - 1;
for (long n = v; n > 0; n /= radix) { for (long n = v; n > 0; n /= radix) {
printLong(n);
long digit = n % radix; long digit = n % radix;
if (digit >= 0 && digit <= 9) { if (digit >= 0 && digit <= 9) {
array[i] = (char) ('0' + digit); array[i] = (char) ('0' + digit);

View File

@ -18,7 +18,7 @@ vmJump(void* address, void* base, void* stack, void* thread);
namespace { namespace {
const bool Verbose = true; const bool Verbose = false;
const bool DebugTraces = false; const bool DebugTraces = false;
class MyThread: public Thread { class MyThread: public Thread {
@ -643,7 +643,7 @@ class Frame {
assert(t, sp - 2 >= localSize(t, method)); assert(t, sp - 2 >= localSize(t, method));
assert(t, getBit(map, sp - 1) == 0); assert(t, getBit(map, sp - 1) == 0);
assert(t, getBit(map, sp - 2) == 0); assert(t, getBit(map, sp - 2) == 0);
return c->stack(stack, 1); return c->stack(stack, 0);
} }
Operand* topObject() { Operand* topObject() {
@ -695,8 +695,7 @@ class Frame {
assert(t, index < codeMaxLocals(t, methodCode(t, method))); assert(t, index < codeMaxLocals(t, methodCode(t, method)));
assert(t, index < parameterFootprint(t, method) assert(t, index < parameterFootprint(t, method)
or getBit(map, index - parameterFootprint(t, method)) == 0); or getBit(map, index - parameterFootprint(t, method)) == 0);
pushInt pushInt(c->select4(c->memory(c->base(), localOffset(t, index, method))));
(c->signExtend4(c->memory(c->base(), localOffset(t, index, method))));
} }
void loadLong(unsigned index) { void loadLong(unsigned index) {
@ -706,7 +705,11 @@ class Frame {
or getBit(map, index - parameterFootprint(t, method)) == 0); or getBit(map, index - parameterFootprint(t, method)) == 0);
assert(t, index < parameterFootprint(t, method) assert(t, index < parameterFootprint(t, method)
or getBit(map, index + 1 - parameterFootprint(t, method)) == 0); 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) { void loadObject(unsigned index) {
@ -722,7 +725,11 @@ class Frame {
} }
void storeLong(unsigned index) { 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);
storedInt(index + 1); storedInt(index + 1);
} }
@ -1180,10 +1187,18 @@ compileThrowNew(MyThread* t, Frame* frame, Machine::Type type)
frame->trace(); 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 void
pushReturnValue(MyThread* t, Frame* frame, unsigned code) pushReturnValue(MyThread* t, Frame* frame, unsigned code)
{ {
Object* result = c->result(); Operand* result = frame->c->result();
switch (code) { switch (code) {
case ByteField: case ByteField:
@ -1192,7 +1207,7 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code)
case ShortField: case ShortField:
case FloatField: case FloatField:
case IntField: case IntField:
frame->pushInt(c->signExtend4(result)); frame->pushInt(frame->c->select4(result));
break; break;
case ObjectField: case ObjectField:
@ -1201,7 +1216,7 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code)
case LongField: case LongField:
case DoubleField: case DoubleField:
frame->pushLong(c->select8(result)); frame->pushLong(frame->c->select8(result));
break; break;
case VoidField: case VoidField:
@ -1211,13 +1226,13 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code)
abort(t); abort(t);
} }
c->release(c); frame->c->release(result);
} }
void void
compileDirectInvoke(MyThread* t, Frame* frame, object target) compileDirectInvoke(MyThread* t, Frame* frame, object target)
{ {
Operand* result = frame->c->alignedCall frame->c->alignedCall
(frame->c->constant (frame->c->constant
(reinterpret_cast<intptr_t> (reinterpret_cast<intptr_t>
(&singletonBody(t, methodCompiled(t, target), 0)))); (&singletonBody(t, methodCompiled(t, target), 0))));
@ -1226,7 +1241,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target)
frame->pop(methodParameterFootprint(t, target)); frame->pop(methodParameterFootprint(t, target));
pushReturnValue(t, frame, methodReturnCode(t, target), result); pushReturnValue(t, frame, methodReturnCode(t, target));
} }
void void
@ -1280,15 +1295,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case faload: case faload:
case iaload: case iaload:
frame->pushInt(c->signExtend4(c->memory(array, ArrayBody, index, 4))); frame->pushInt(c->select4(c->memory(array, ArrayBody, index, 4)));
break; break;
case baload: case baload:
frame->pushInt(c->signExtend1(c->memory(array, ArrayBody, index, 1))); frame->pushInt(c->select1(c->memory(array, ArrayBody, index, 1)));
break; break;
case caload: case caload:
frame->pushInt(c->zeroExtend2(c->memory(array, ArrayBody, index, 2))); frame->pushInt(c->select2z(c->memory(array, ArrayBody, index, 2)));
break; break;
case daload: case daload:
@ -1297,7 +1312,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
break; break;
case saload: case saload:
frame->pushInt(c->signExtend2(c->memory(array, ArrayBody, index, 2))); frame->pushInt(c->select2(c->memory(array, ArrayBody, index, 2)));
break; break;
} }
@ -1425,15 +1440,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->mark(nonnegative); c->mark(nonnegative);
Operand* r = c->indirectCall c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeBlankObjectArray)), (c->constant(reinterpret_cast<intptr_t>(makeBlankObjectArray)),
3, c->thread(), frame->append(class_), length); 3, c->thread(), frame->append(class_), length);
Operand* result = c->result();
c->release(length); c->release(length);
frame->trace(); frame->trace();
frame->pushObject(r); frame->pushObject(result);
c->release(result);
} break; } break;
case areturn: { case areturn: {
@ -1489,68 +1507,63 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
object class_ = resolveClassInPool(t, codePool(t, code), index - 1); object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
Operand* next = c->label();
Operand* instance = frame->topObject(); 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_); Operand* classOperand = frame->append(class_);
c->mov(c->memory(tmp), tmp); c->indirectCall
c->and_(c->constant(PointerMask), tmp); (c->constant(reinterpret_cast<intptr_t>(checkCast)),
3, c->thread(), classOperand, instance);
c->cmp(classOperand, tmp); frame->trace();
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);
} break; } break;
case d2f: { case d2f: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(doubleToFloat)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(doubleToFloat)), 1, a);
Operand* result = c->select4(c->result());
frame->pushInt(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case d2i: { case d2i: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(doubleToInt)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(doubleToInt)), 1, a);
Operand* result = c->select4(c->result());
frame->pushInt(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case d2l: { case d2l: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(doubleToLong)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(doubleToLong)), 1, a);
Operand* result = c->select8(c->result());
frame->pushLong(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case dadd: { case dadd: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(addDouble)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1558,9 +1571,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case dcmpg: { case dcmpg: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(compareDoublesG)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1568,9 +1585,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case dcmpl: { case dcmpl: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(compareDoublesL)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1586,9 +1607,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case ddiv: { case ddiv: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(divideDouble)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1596,27 +1621,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case dmul: { case dmul: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(multiplyDouble)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
case dneg: { case dneg: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(negateDouble)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(negateDouble)), 1, a);
Operand* result = c->select8(c->result());
frame->pushLong(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case vm::drem: { case vm::drem: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(moduloDouble)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1624,9 +1661,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case dsub: { case dsub: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
Operand* b = frame->popLong(); Operand* b = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(subtractDouble)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1657,34 +1698,50 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case f2d: { case f2d: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(floatToDouble)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(floatToDouble)), 1, a);
Operand* result = c->select8(c->result());
frame->pushLong(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case f2i: { case f2i: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(floatToInt)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(floatToInt)), 1, a);
Operand* result = c->select4(c->result());
frame->pushInt(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case f2l: { case f2l: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(floatToLong)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(floatToLong)), 1, a);
Operand* result = c->select8(c->result());
frame->pushLong(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case fadd: { case fadd: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(addFloat)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1692,9 +1749,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case fcmpg: { case fcmpg: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(compareFloatsG)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1702,9 +1763,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case fcmpl: { case fcmpl: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(compareFloatsL)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1724,9 +1789,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case fdiv: { case fdiv: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(divideFloat)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1734,27 +1803,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case fmul: { case fmul: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(multiplyFloat)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
case fneg: { case fneg: {
Operand* a = frame->popLong(); Operand* a = frame->popLong();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(negateFloat)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(negateFloat)), 1, a);
Operand* result = c->select8(c->result());
frame->pushLong(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case vm::frem: { case vm::frem: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(moduloFloat)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1762,9 +1843,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case fsub: { case fsub: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
Operand* b = frame->popInt(); Operand* b = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(subtractFloat)), 2, a, b)); (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(a);
c->release(b); c->release(b);
} break; } break;
@ -1793,23 +1878,23 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case ByteField: case ByteField:
case BooleanField: case BooleanField:
frame->pushInt frame->pushInt
(c->signExtend1(c->memory(table, fieldOffset(t, field)))); (c->select1(c->memory(table, fieldOffset(t, field))));
break; break;
case CharField: case CharField:
frame->pushInt frame->pushInt
(c->zeroExtend2(c->memory(table, fieldOffset(t, field)))); (c->select2z(c->memory(table, fieldOffset(t, field))));
break; break;
case ShortField: case ShortField:
frame->pushInt frame->pushInt
(c->signExtend2(c->memory(table, fieldOffset(t, field)))); (c->select2(c->memory(table, fieldOffset(t, field))));
break; break;
case FloatField: case FloatField:
case IntField: case IntField:
frame->pushInt frame->pushInt
(c->signExtend4(c->memory(table, fieldOffset(t, field)))); (c->select4(c->memory(table, fieldOffset(t, field))));
break; break;
case DoubleField: case DoubleField:
@ -1849,39 +1934,47 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case i2b: { case i2b: {
Operand* top = frame->topInt(); Operand* top = frame->topInt();
c->mov(c->signExtend1(top), top); c->mov(c->select1(top), top);
} break; } break;
case i2c: { case i2c: {
Operand* top = frame->topInt(); Operand* top = frame->topInt();
c->mov(c->zeroExtend2(top), top); c->mov(c->select2z(top), top);
} break; } break;
case i2d: { case i2d: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
frame->pushLong
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(intToDouble)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(intToDouble)), 1, a);
Operand* result = c->select8(c->result());
frame->pushLong(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case i2f: { case i2f: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
frame->pushInt
(c->directCall c->directCall
(c->constant(reinterpret_cast<intptr_t>(intToFloat)), 1, a)); (c->constant(reinterpret_cast<intptr_t>(intToFloat)), 1, a);
Operand* result = c->select4(c->result());
frame->pushInt(result);
c->release(result);
c->release(a); c->release(a);
} break; } break;
case i2l: { case i2l: {
Operand* a = frame->popInt(); Operand* a = frame->popInt();
frame->pushLong(c->signExtend4(a)); frame->pushLong(c->select8From4(a));
c->release(a); c->release(a);
} break; } break;
case i2s: { case i2s: {
Operand* top = frame->topInt(); Operand* top = frame->topInt();
c->mov(c->signExtend2(top), top); c->mov(c->select2(top), top);
} break; } break;
case iadd: { case iadd: {
@ -2096,50 +2189,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
object class_ = resolveClassInPool(t, codePool(t, code), index - 1); object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
Operand* call = c->label();
Operand* next = c->label();
Operand* zero = c->label();
Operand* instance = frame->popObject(); 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_); Operand* classOperand = frame->append(class_);
c->mov(c->memory(tmp), tmp); c->directCall
c->and_(c->constant(PointerMask), tmp); (c->constant(reinterpret_cast<intptr_t>(instanceOf)),
3, c->thread(), classOperand, instance);
c->cmp(classOperand, tmp); Operand* result = c->select4(c->result());
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);
frame->pushInt(result); frame->pushInt(result);
c->release(result); c->release(result);
c->release(instance);
} break; } break;
case invokeinterface: { case invokeinterface: {
@ -2153,18 +2214,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
unsigned instance = parameterFootprint - 1; unsigned instance = parameterFootprint - 1;
Operand* result = c->call c->directCall
(c->directCall
(c->constant (c->constant
(reinterpret_cast<intptr_t>(findInterfaceMethodFromInstance)), (reinterpret_cast<intptr_t>(findInterfaceMethodFromInstance)),
3, c->thread(), frame->append(target), 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->trace(target, true);
frame->pop(parameterFootprint); frame->pop(parameterFootprint);
pushReturnValue(t, frame, methodReturnCode(t, target), result); pushReturnValue(t, frame, methodReturnCode(t, target));
} break; } break;
case invokespecial: { case invokespecial: {
@ -2213,7 +2277,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->mov(c->memory(instance), class_); c->mov(c->memory(instance), class_);
c->and_(c->constant(PointerMask), 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); frame->trace(target, true);
@ -2221,7 +2285,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
frame->pop(parameterFootprint); frame->pop(parameterFootprint);
pushReturnValue(t, frame, methodReturnCode(t, target), result); pushReturnValue(t, frame, methodReturnCode(t, target));
} break; } break;
case ior: { case ior: {
@ -2349,11 +2413,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
} break; } break;
case lconst_0: case lconst_0:
frame->pushLong(c->constant(0)); frame->pushLong(c->select8(c->constant(0)));
break; break;
case lconst_1: case lconst_1:
frame->pushLong(c->constant(1)); frame->pushLong(c->select8(c->constant(1)));
break; break;
case ldc: case ldc:
@ -2392,7 +2456,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
uint64_t v; uint64_t v;
memcpy(&v, &singletonValue(t, pool, index - 1), 8); memcpy(&v, &singletonValue(t, pool, index - 1), 8);
frame->pushLong(c->constant(v)); frame->pushLong(c->select8(c->constant(v)));
} break; } break;
case ldiv_: { case ldiv_: {
@ -2469,10 +2533,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
} }
assert(t, start); assert(t, start);
c->jmp c->directCall
(c->directCall (c->constant(reinterpret_cast<intptr_t>(lookUpAddress)),
(c->constant(reinterpret_cast<intptr_t>(lookUpAddress)), 4, key, start, c->constant(pairCount), default_);
4, key, start, c->constant(pairCount), default_));
Operand* result = c->result();
c->jmp(result);
c->release(result);
c->release(key); c->release(key);
@ -2587,15 +2654,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
PROTECT(t, class_); PROTECT(t, class_);
Operand* result = c->indirectCall c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeMultidimensionalArray)), (c->constant(reinterpret_cast<intptr_t>(makeMultidimensionalArray)),
4, c->thread(), frame->append(class_), c->stack(), 4, c->thread(), frame->append(class_), c->stack(),
c->constant(dimensions)); c->constant(dimensions));
Operand* result = c->result();
frame->trace(); frame->trace();
frame->pop(dimensions); frame->pop(dimensions);
frame->pushObject(result); frame->pushObject(result);
c->release(result);
} break; } break;
case new_: { case new_: {
@ -2608,20 +2678,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
initClass(t, class_); initClass(t, class_);
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
Operand* result;
if (classVmFlags(t, class_) & WeakReferenceFlag) { if (classVmFlags(t, class_) & WeakReferenceFlag) {
result = c->indirectCall c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeNewWeakReference)), (c->constant(reinterpret_cast<intptr_t>(makeNewWeakReference)),
2, c->thread(), frame->append(class_)); 2, c->thread(), frame->append(class_));
} else { } else {
result = c->indirectCall c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeNew)), (c->constant(reinterpret_cast<intptr_t>(makeNew)),
2, c->thread(), frame->append(class_)); 2, c->thread(), frame->append(class_));
} }
Operand* result = c->result();
frame->trace(); frame->trace();
frame->pushObject(result); frame->pushObject(result);
c->release(result);
} break; } break;
case newarray: { case newarray: {
@ -2675,16 +2747,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
default: abort(t); default: abort(t);
} }
Operand* result = c->indirectCall c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)), (c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)), 3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
size); size);
Operand* result = c->result();
c->release(size); c->release(size);
frame->trace(); frame->trace();
frame->pushObject(result); frame->pushObject(result);
c->release(result);
} break; } break;
case nop: break; case nop: break;
@ -3007,13 +3082,13 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
} }
// for debugging: // for debugging:
if (//false and if (false and
strcmp(reinterpret_cast<const char*> strcmp(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, method)), 0)), (&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
"java/lang/Long") == 0 and "java/lang/String") == 0 and
strcmp(reinterpret_cast<const char*> strcmp(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, method), 0)), (&byteArrayBody(t, methodName(t, method), 0)),
"toString") == 0) "getBytes") == 0)
{ {
asm("int3"); asm("int3");
} }
@ -3182,7 +3257,11 @@ invokeNative2(MyThread* t, object method)
case INT64_TYPE: case INT64_TYPE:
case DOUBLE_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); argOffset += (8 / BytesPerWord);
sp -= 2; sp -= 2;
} break; } 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->base(), c->memory(c->thread(), difference(&(t->base), t)));
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), 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)), (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); return finish(t, c);
} }

View File

@ -29,12 +29,10 @@ enum Register {
enum SelectionType { enum SelectionType {
Select1, Select1,
Select2, Select2,
Select2z,
Select4, Select4,
Select8, Select8,
SignExtend1, Select8From4
SignExtend2,
ZeroExtend2,
SignExtend4
}; };
const bool Verbose = false; const bool Verbose = false;
@ -42,7 +40,7 @@ const bool Verbose = false;
const unsigned RegisterCount = BytesPerWord * 2; const unsigned RegisterCount = BytesPerWord * 2;
const unsigned GprParameterCount = 6; const unsigned GprParameterCount = 6;
const SelectionType DefaultSelection const SelectionType DefaultSelection
= (BytesPerWord == 8 ? S8Selection : S4Selection); = (BytesPerWord == 8 ? Select8 : Select4);
class Context; class Context;
class MyOperand; class MyOperand;
@ -55,6 +53,19 @@ class CodePromise;
class MyPromise; class MyPromise;
class RegisterReference; class RegisterReference;
inline unsigned
footprint(SelectionType selection)
{
switch (selection) {
case Select8:
case Select8From4:
return 8;
default:
return BytesPerWord;
}
}
int64_t int64_t
divideLong(int64_t a, int64_t b) divideLong(int64_t a, int64_t b)
{ {
@ -320,7 +331,7 @@ RegisterOperand*
register_(Context* c, RegisterReference*, SelectionType = DefaultSelection); register_(Context* c, RegisterReference*, SelectionType = DefaultSelection);
RegisterOperand* RegisterOperand*
register_(Context* c, Register, Register = NoRegister, register_(Context* c, Register = NoRegister, Register = NoRegister,
SelectionType = DefaultSelection); SelectionType = DefaultSelection);
MemoryOperand* MemoryOperand*
@ -429,38 +440,63 @@ release(Context* c, Register v)
class RegisterReference { class RegisterReference {
public: public:
RegisterReference(Register value = NoRegister, Register high = NoRegister): 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) { void acquire(Context* c) {
value_ = ::acquire(c); if (defaultValue != NoRegister) {
if (acquireHigh) { ::acquire(c, defaultValue);
high_ = ::acquire(c);
} }
if (defaultHigh != NoRegister) {
::acquire(c, defaultHigh);
}
value_ = defaultValue;
high_ = defaultHigh;
acquired = true;
} }
void release(Context* c) { void release(Context* c) {
::release(c, value_); assert(c, acquired);
value_ = NoRegister;
if (value_ != NoRegister) {
::release(c, value_);
}
if (high_ != NoRegister) { if (high_ != NoRegister) {
::release(c, high_); ::release(c, high_);
} }
value_ = NoRegister;
high_ = NoRegister;
acquired = false;
} }
Register value(Context* c UNUSED) { Register value(Context* c) {
assert(c, value_ != NoRegister); assert(c, acquired);
if (value_ == NoRegister) {
value_ = ::acquire(c);
}
return value_; return value_;
} }
Register high(Context* c UNUSED) { Register high(Context* c) {
assert(c, high_ != NoRegister); assert(c, acquired);
if (high_ == NoRegister) {
high_ = ::acquire(c);
}
return high_; return high_;
} }
Register value_; Register value_;
Register defaultValue;
Register high_; Register high_;
bool acquireHigh; Register defaultHigh;
bool acquired;
}; };
class RegisterOperand: public MyOperand { class RegisterOperand: public MyOperand {
@ -478,7 +514,7 @@ class RegisterOperand: public MyOperand {
} }
virtual unsigned footprint(Context*) { virtual unsigned footprint(Context*) {
return (selection == S8Selection ? 8 : BytesPerWord); return ::footprint(selection);
} }
virtual Register asRegister(Context* c) { virtual Register asRegister(Context* c) {
@ -489,9 +525,6 @@ class RegisterOperand: public MyOperand {
if (selection == this->selection) { if (selection == this->selection) {
return this; return this;
} else { } else {
if (selection == S8Selection and BytesPerWord == 4) {
reference->acquireHigh = true;
}
return register_(c, reference, selection); return register_(c, reference, selection);
} }
} }
@ -528,7 +561,7 @@ class ImmediateOperand: public MyOperand {
{ } { }
virtual unsigned footprint(Context*) { virtual unsigned footprint(Context*) {
return (selection == S8Selection ? 8 : BytesPerWord); return ::footprint(selection);
} }
virtual MyOperand* select(Context* c, SelectionType selection) { virtual MyOperand* select(Context* c, SelectionType selection) {
@ -610,7 +643,7 @@ class MemoryOperand: public MyOperand {
{ } { }
virtual unsigned footprint(Context*) { virtual unsigned footprint(Context*) {
return (selection == S8Selection ? 8 : BytesPerWord); return ::footprint(selection);
} }
virtual Register asRegister(Context*); virtual Register asRegister(Context*);
@ -698,7 +731,7 @@ temporary(Context* c)
RegisterOperand* RegisterOperand*
temporary(Context* c, SelectionType selection) 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); return register_(c, acquire(c), acquire(c), selection);
} else { } else {
return register_(c, acquire(c), NoRegister, selection); return register_(c, acquire(c), NoRegister, selection);
@ -712,6 +745,14 @@ temporary(Context* c, Register v)
return register_(c, 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* Segment*
currentSegment(Context* c) currentSegment(Context* c)
{ {
@ -793,6 +834,9 @@ class AcquireEvent: public Event {
{ } { }
virtual void run(Context* c) { virtual void run(Context* c) {
if (Verbose) {
fprintf(stderr, "acquire register\n");
}
operand->reference->acquire(c); operand->reference->acquire(c);
} }
@ -807,6 +851,9 @@ class ReleaseEvent: public Event {
{ } { }
virtual void run(Context* c) { virtual void run(Context* c) {
if (Verbose) {
fprintf(stderr, "release register\n");
}
operand->release(c); operand->release(c);
} }
@ -954,18 +1001,38 @@ appendArgumentEvent(Context* c, MyOperand** arguments, unsigned count)
ArgumentEvent(arguments, count, s->event); ArgumentEvent(arguments, count, s->event);
} }
MyStack* void
pushed(Context* c, MyStack* stack, unsigned footprint) logStack(Context* c, MyStack* stack)
{ {
int index = (stack ? fprintf(stderr, "ip %3d: ", currentSegment(c)->logicalIp);
stack->index + (stack->value->footprint(c) / BytesPerWord) :
0); 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 MyOperand* value = memory
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1, (c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1);
footprint == (BytesPerWord * 2) ? S8Selection : DefaultSelection);
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* MyStack*
@ -973,7 +1040,10 @@ push(Context* c, MyStack* stack, MyOperand* v)
{ {
appendOperation(c, MyOperand::push, 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* MyStack*
@ -983,11 +1053,15 @@ pop(Context* c, MyStack* stack, int count)
(c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp)); (c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp));
while (count) { while (count) {
count -= (stack->value->footprint(c) / BytesPerWord); -- count;
assert(c, count >= 0); assert(c, count >= 0);
stack = stack->next; stack = stack->next;
} }
if (Verbose) {
logStack(c, stack);
}
return stack; return stack;
} }
@ -996,6 +1070,14 @@ pop(Context* c, MyStack* stack, MyOperand* dst)
{ {
appendOperation(c, MyOperand::pop, dst); appendOperation(c, MyOperand::pop, dst);
if (dst->footprint(c) / BytesPerWord == 2) {
stack = stack->next;
}
if (Verbose) {
logStack(c, stack->next);
}
return 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 void
encode(Context* c, uint8_t* instruction, unsigned length, int a, Register b, encode(Context* c, uint8_t* instruction, unsigned length, int a, Register b,
int32_t displacement, int index, unsigned scale) 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); 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 void
encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex) 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 void
RegisterOperand::apply(Context* c, Operation operation) RegisterOperand::apply(Context* c, Operation operation)
{ {
assert(c, operation == push
or operation == pop
or selection == DefaultSelection);
switch (operation) { switch (operation) {
case call: case call:
assert(c, selection == DefaultSelection);
c->code.append(0xff); c->code.append(0xff);
c->code.append(0xd0 | value(c)); c->code.append(0xd0 | value(c));
break; break;
case jmp: case jmp:
assert(c, selection == DefaultSelection);
c->code.append(0xff); c->code.append(0xff);
c->code.append(0xe0 | value(c)); c->code.append(0xe0 | value(c));
break; break;
case pop: case pop:
if (selection == DefaultSelection) { if (selection == DefaultSelection or selection == Select4) {
c->code.append(0x58 | value(c)); c->code.append(0x58 | value(c));
} else { } else {
switch (selection) { assert(c, selection == Select8);
case S8Selection:
assert(c, selection == S8Selection);
register_(c, value(c))->apply(c, pop); register_(c, value(c))->apply(c, pop);
register_(c, high(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; 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); default: abort(c);
} }
} }
break; 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: case neg:
rex(c); rex(c, selection);
c->code.append(0xf7); c->code.append(0xf7);
c->code.append(0xd8 | value(c)); c->code.append(0xd8 | value(c));
break; break;
@ -1151,21 +1266,27 @@ RegisterOperand::accept(Context* c, Operation operation,
{ {
switch (operation) { switch (operation) {
case add: case add:
rex(c); assert(c, selection == operand->selection);
rex(c, operand->selection);
c->code.append(0x01); c->code.append(0x01);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case cmp: case cmp:
if (selection == DefaultSelection) { assert(c, selection == operand->selection);
rex(c);
if (operand->selection == DefaultSelection
or operand->selection == Select4)
{
rex(c, operand->selection);
c->code.append(0x39); c->code.append(0x39);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
} else { } else {
assert(c, selection == S8Selection); assert(c, operand->selection == Select8);
register_(c, high(c))->accept 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 // if the high order bits are equal, we compare the low order
// bits; otherwise, we jump past that comparison // bits; otherwise, we jump past that comparison
@ -1174,41 +1295,41 @@ RegisterOperand::accept(Context* c, Operation operation,
c->code.append4(2); c->code.append4(2);
register_(c, value(c))->accept register_(c, value(c))->accept
(c, mov, register_(c, operand->value(c))); (c, cmp, register_(c, operand->value(c)));
} }
break; break;
case mov: case mov:
if (value(c) != operand->value(c) or selection != operand->selection) { if (value(c) != operand->value(c) or selection != operand->selection) {
if (operand->selection == DefaultSelection) { if (operand->selection == DefaultSelection
rex(c); or operand->selection == Select4)
{
rex(c, selection);
c->code.append(0x89); c->code.append(0x89);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
} else { } else {
switch (operand->selection) { switch (operand->selection) {
case S1Selection: case Select1:
c->code.append(0xbe); c->code.append(0xbe);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case S2Selection: case Select2:
c->code.append(0xbf); c->code.append(0xbf);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case Z2Selection: case Select2z:
c->code.append(0xb7); c->code.append(0xb7);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case S4Selection: case Select4:
c->code.append(0x89); c->code.append(0x89);
c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); c->code.append(0xc0 | (operand->value(c) << 3) | value(c));
break; break;
case S8Selection: case Select8:
assert(c, selection == S8Selection);
register_(c, value(c))->accept register_(c, value(c))->accept
(c, mov, register_(c, operand->value(c))); (c, mov, register_(c, operand->value(c)));
@ -1223,7 +1344,9 @@ RegisterOperand::accept(Context* c, Operation operation,
break; break;
case mul: case mul:
rex(c); assert(c, selection == operand->selection);
rex(c, selection);
c->code.append(0x0f); c->code.append(0x0f);
c->code.append(0xaf); c->code.append(0xaf);
c->code.append(0xc0 | (value(c) << 3) | operand->value(c)); c->code.append(0xc0 | (value(c) << 3) | operand->value(c));
@ -1349,6 +1472,8 @@ void
RegisterOperand::accept(Context* c, Operation operation, RegisterOperand::accept(Context* c, Operation operation,
AddressOperand* operand) AddressOperand* operand)
{ {
assert(c, selection == DefaultSelection);
switch (operation) { switch (operation) {
case mov: { case mov: {
accept(c, operation, ::value(c, operand)); accept(c, operation, ::value(c, operand));
@ -1362,38 +1487,43 @@ void
RegisterOperand::accept(Context* c, Operation operation, RegisterOperand::accept(Context* c, Operation operation,
MemoryOperand* operand) MemoryOperand* operand)
{ {
assert(c, operation == mov or selection == DefaultSelection); assert(c, selection == DefaultSelection);
assert(c, operation == mov or operand->selection == DefaultSelection);
switch (operation) { switch (operation) {
case cmp: { 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; } break;
case mov: { case mov: {
if (operand->selection == DefaultSelection) { if (operand->selection == DefaultSelection
or operand->selection == Select4)
{
encode(c, 0x8b, value(c), operand, true); encode(c, 0x8b, value(c), operand, true);
} else { } else {
switch (operand->selection) { switch (operand->selection) {
case S1Selection: case Select1:
encode2(c, 0x0fbe, value(c), operand, true); encode2(c, 0x0fbe, value(c), operand, true);
break; break;
case S2Selection: case Select2:
encode2(c, 0x0fbf, value(c), operand, true); encode2(c, 0x0fbf, value(c), operand, true);
break; break;
case Z2Selection: case Select2z:
encode2(c, 0x0fb7, value(c), operand, true); encode2(c, 0x0fb7, value(c), operand, true);
break; break;
case S4Selection: case Select4:
encode(c, 0x63, value(c), operand, true); encode(c, 0x63, value(c), operand, true);
break; break;
case S8Selection: case Select8:
assert(c, selection == S8Selection);
register_(c, value(c))->accept register_(c, value(c))->accept
(c, mov, memory (c, mov, memory
(c, operand->base, operand->displacement, (c, operand->base, operand->displacement,
@ -1551,12 +1681,12 @@ AddressOperand::asRegister(Context* c)
void void
ImmediateOperand::apply(Context* c, Operation operation) ImmediateOperand::apply(Context* c, Operation operation)
{ {
assert(c, operation == push or selection == DefaultSelection);
switch (operation) { switch (operation) {
case alignedCall: case alignedCall:
case call: case call:
case jmp: case jmp:
assert(c, selection == DefaultSelection);
address(c, new (c->zone.allocate(sizeof(ResolvedPromise))) address(c, new (c->zone.allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value))->apply(c, operation); ResolvedPromise(value))->apply(c, operation);
break; break;
@ -1576,7 +1706,7 @@ ImmediateOperand::apply(Context* c, Operation operation)
tmp->release(c); tmp->release(c);
} }
} else { } else {
assert(c, selection == S8Selection); assert(c, selection == Select8);
immediate(c, (value >> 32) & 0xFFFFFFFF)->apply(c, push); immediate(c, (value >> 32) & 0xFFFFFFFF)->apply(c, push);
immediate(c, (value ) & 0xFFFFFFFF)->apply(c, push); immediate(c, (value ) & 0xFFFFFFFF)->apply(c, push);
@ -1634,18 +1764,22 @@ MemoryOperand::apply(Context* c, Operation operation)
{ {
switch (operation) { switch (operation) {
case call: case call:
assert(c, selection == DefaultSelection);
encode(c, 0xff, 2, this, false); encode(c, 0xff, 2, this, false);
break; break;
case jmp: case jmp:
assert(c, selection == DefaultSelection);
encode(c, 0xff, 4, this, false); encode(c, 0xff, 4, this, false);
break; break;
case neg: case neg:
if (selection == DefaultSelection) { if (selection == DefaultSelection) {
encode(c, 0xf7, 2, this, true); encode(c, 0xf7, 2, this, selection);
} else { } else {
assert(c, selection == S8Selection); assert(c, selection == Select8);
RegisterOperand* ax = temporary(c, rax); RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* dx = temporary(c, rdx);
@ -1670,7 +1804,18 @@ MemoryOperand::apply(Context* c, Operation operation)
break; break;
case pop: 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; break;
case push: case push:
@ -1678,7 +1823,7 @@ MemoryOperand::apply(Context* c, Operation operation)
encode(c, 0xff, 6, this, false); encode(c, 0xff, 6, this, false);
} else { } else {
switch (selection) { switch (selection) {
case S8Selection: { case Select8: {
MemoryOperand* low = memory(c, base, displacement, index, scale); MemoryOperand* low = memory(c, base, displacement, index, scale);
MemoryOperand* high = memory MemoryOperand* high = memory
(c, base, displacement + BytesPerWord, index, scale); (c, base, displacement + BytesPerWord, index, scale);
@ -1689,7 +1834,7 @@ MemoryOperand::apply(Context* c, Operation operation)
default: { default: {
RegisterOperand* tmp = temporary RegisterOperand* tmp = temporary
(c, selection == S8Selection ? S8Selection : DefaultSelection); (c, selection == Select8 ? Select8 : DefaultSelection);
tmp->accept(c, mov, this); tmp->accept(c, mov, this);
tmp->apply(c, operation); tmp->apply(c, operation);
tmp->release(c); tmp->release(c);
@ -1708,14 +1853,22 @@ MemoryOperand::accept(Context* c, Operation operation,
{ {
switch (operation) { switch (operation) {
case and_: { 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; } break;
case add: { case add: {
if (selection == DefaultSelection) { if (operand->selection == DefaultSelection
encode(c, 0x01, operand->value(c), this, true); or operand->selection == Select4)
{
encode(c, 0x01, operand->value(c), this, operand->selection);
} else { } else {
assert(c, selection == S8Selection); assert(c, operand->selection == Select8);
RegisterOperand* ax = temporary(c, rax); RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* dx = temporary(c, rdx);
@ -1733,22 +1886,26 @@ MemoryOperand::accept(Context* c, Operation operation,
} break; } break;
case addc: case addc:
if (operand->selection == DefaultSelection) { if (operand->selection == DefaultSelection
encode(c, 0x11, operand->value(c), this, true); or operand->selection == Select4)
{
encode(c, 0x11, operand->value(c), this, operand->selection);
} else { } else {
abort(c); abort(c);
} }
break; break;
case div: { case div: {
if (selection == DefaultSelection) { if (operand->selection == DefaultSelection
or operand->selection == Select4)
{
RegisterOperand* ax = temporary(c, rax); RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* dx = temporary(c, rdx);
ax->accept(c, mov, this); ax->accept(c, mov, this);
rex(c); rex(c, operand->selection);
c->code.append(0x99); c->code.append(0x99);
rex(c); rex(c, operand->selection);
c->code.append(0xf7); c->code.append(0xf7);
c->code.append(0xf8 | operand->value(c)); c->code.append(0xf8 | operand->value(c));
@ -1757,40 +1914,52 @@ MemoryOperand::accept(Context* c, Operation operation,
ax->release(c); ax->release(c);
dx->release(c); dx->release(c);
} else { } else {
assert(c, selection == S8Selection); assert(c, operand->selection == Select8);
operand->apply(c, push); 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); 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; } break;
case mov: { case mov: {
if (selection == DefaultSelection) { if (operand->selection == DefaultSelection
encode(c, 0x89, operand->value(c), this, true); or operand->selection == Select4)
{
encode(c, 0x89, operand->value(c), this, operand->selection);
} else { } else {
switch (selection) { switch (operand->selection) {
case S1Selection: case Select1:
if (operand->value(c) > rbx) { if (BytesPerWord == 8) {
c->code.append(0x40); 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; break;
case S2Selection: case Select2:
case Z2Selection: case Select2z:
c->code.append(0x66); c->code.append(0x66);
encode(c, 0x89, operand->value(c), this, false); encode(c, 0x89, operand->value(c), this, false);
break; break;
case S4Selection: case Select4:
encode(c, 0x89, operand->value(c), this, false); encode(c, 0x89, operand->value(c), this, false);
break; break;
case S8Selection: case Select8:
assert(c, operand->selection == S8Selection);
memory(c, base, displacement, index, scale)->accept memory(c, base, displacement, index, scale)->accept
(c, mov, register_(c, operand->value(c))); (c, mov, register_(c, operand->value(c)));
@ -1804,7 +1973,9 @@ MemoryOperand::accept(Context* c, Operation operation,
} break; } break;
case mul: { case mul: {
if (selection == DefaultSelection) { if (operand->selection == DefaultSelection
or operand->selection == Select4)
{
RegisterOperand* tmp = temporary(c); RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, this); tmp->accept(c, mov, this);
@ -1813,6 +1984,8 @@ MemoryOperand::accept(Context* c, Operation operation,
tmp->release(c); tmp->release(c);
} else { } else {
assert(c, operand->selection == Select8);
RegisterOperand* tmp = temporary(c); RegisterOperand* tmp = temporary(c);
RegisterOperand* ax = temporary(c, rax); RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* dx = temporary(c, rdx);
@ -1843,11 +2016,19 @@ MemoryOperand::accept(Context* c, Operation operation,
} break; } break;
case or_: { 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; } break;
case rem: { case rem: {
if (selection == DefaultSelection) { if (operand->selection == DefaultSelection
or operand->selection == Select4)
{
RegisterOperand* ax = temporary(c, rax); RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* dx = temporary(c, rdx);
ax->accept(c, mov, this); ax->accept(c, mov, this);
@ -1863,41 +2044,62 @@ MemoryOperand::accept(Context* c, Operation operation,
ax->release(c); ax->release(c);
dx->release(c); dx->release(c);
} else { } else {
assert(c, selection == S8Selection); assert(c, operand->selection == Select8);
operand->apply(c, push); 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); 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; } break;
case shl: { case shl: {
RegisterOperand* cx = temporary(c, rcx); if (operand->selection == DefaultSelection
cx->accept(c, mov, operand); or operand->selection == Select4)
encode(c, 0xd3, 4, this, true); {
cx->release(c); RegisterOperand* cx = temporary(c, rcx);
cx->accept(c, mov, operand);
encode(c, 0xd3, 4, this, operand->selection);
cx->release(c);
} else {
abort(c);
}
} break; } break;
case shr: { case shr: {
RegisterOperand* cx = temporary(c, rcx); if (operand->selection == DefaultSelection
cx->accept(c, mov, operand); or operand->selection == Select4)
encode(c, 0xd3, 5, this, true); {
cx->release(c); RegisterOperand* cx = temporary(c, rcx);
cx->accept(c, mov, operand);
encode(c, 0xd3, 5, this, operand->selection);
cx->release(c);
} else {
abort(c);
}
} break; } break;
case ushr: { case ushr: {
RegisterOperand* cx = temporary(c, rcx); if (operand->selection == DefaultSelection
cx->accept(c, mov, operand); or operand->selection == Select4)
encode(c, 0xd3, 7, this, true); {
cx->release(c); RegisterOperand* cx = temporary(c, rcx);
cx->accept(c, mov, operand);
encode(c, 0xd3, 7, this, operand->selection);
cx->release(c);
} else {
abort(c);
}
} break; } break;
case sub: { case sub: {
if (selection == DefaultSelection) { if (operand->selection == DefaultSelection
encode(c, 0x29, operand->value(c), this, true); or operand->selection == Select4)
{
encode(c, 0x29, operand->value(c), this, operand->selection);
} else { } else {
assert(c, selection == S8Selection); assert(c, operand->selection == Select8);
RegisterOperand* ax = temporary(c, rax); RegisterOperand* ax = temporary(c, rax);
RegisterOperand* dx = temporary(c, rdx); RegisterOperand* dx = temporary(c, rdx);
@ -1915,15 +2117,23 @@ MemoryOperand::accept(Context* c, Operation operation,
} break; } break;
case subb: case subb:
if (operand->selection == DefaultSelection) { if (operand->selection == DefaultSelection
encode(c, 0x19, operand->value(c), this, true); or operand->selection == Select4)
{
encode(c, 0x19, operand->value(c), this, operand->selection);
} else { } else {
abort(c); abort(c);
} }
break; break;
case xor_: { 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; } break;
default: abort(c); default: abort(c);
@ -2111,7 +2321,7 @@ class MyCompiler: public Compiler {
MyStack* stack = static_cast<MyStack*>(s); MyStack* stack = static_cast<MyStack*>(s);
while (count) { while (count) {
-- count; -- count;
stack = ::pushed(&c, stack, BytesPerWord); stack = ::pushed(&c, stack);
} }
return stack; return stack;
} }
@ -2122,17 +2332,10 @@ class MyCompiler: public Compiler {
virtual Operand* stack(Stack* s, unsigned index) { virtual Operand* stack(Stack* s, unsigned index) {
MyStack* stack = static_cast<MyStack*>(s); MyStack* stack = static_cast<MyStack*>(s);
unsigned i = 0;
if (stack->value->footprint(&c) / BytesPerWord == 2) { while (index) {
++ i; -- index;
}
for (; i < index; ++i) {
stack = stack->next; stack = stack->next;
if (stack->value->footprint(&c) / BytesPerWord == 2) {
++ i;
}
} }
return stack->value; return stack->value;
@ -2163,7 +2366,7 @@ class MyCompiler: public Compiler {
} }
virtual Operand* temporary() { virtual Operand* temporary() {
RegisterOperand* r = register_(&c, NoRegister); RegisterOperand* r = register_(&c);
appendAcquire(&c, r); appendAcquire(&c, r);
return r; return r;
} }
@ -2219,7 +2422,9 @@ class MyCompiler: public Compiler {
} }
virtual Operand* result() { virtual Operand* result() {
return ::temporary(&c, rax, rdx); RegisterOperand* r = register_(&c, rax, rdx);
appendAcquire(&c, r);
return r;
} }
virtual void return_(Operand* v) { virtual void return_(Operand* v) {
@ -2339,6 +2544,10 @@ class MyCompiler: public Compiler {
return static_cast<MyOperand*>(v)->select(&c, Select2); 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) { virtual Operand* select4(Operand* v) {
return static_cast<MyOperand*>(v)->select(&c, Select4); return static_cast<MyOperand*>(v)->select(&c, Select4);
} }
@ -2347,20 +2556,8 @@ class MyCompiler: public Compiler {
return static_cast<MyOperand*>(v)->select(&c, Select8); return static_cast<MyOperand*>(v)->select(&c, Select8);
} }
virtual Operand* signExtend1(Operand* v) { virtual Operand* select8From4(Operand* v) {
return static_cast<MyOperand*>(v)->select(&c, SignExtend1); return static_cast<MyOperand*>(v)->select(&c, Select8From4);
}
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 void prologue() { virtual void prologue() {

View File

@ -36,13 +36,10 @@ class Compiler {
virtual Operand* select1(Operand*) = 0; virtual Operand* select1(Operand*) = 0;
virtual Operand* select2(Operand*) = 0; virtual Operand* select2(Operand*) = 0;
virtual Operand* select2z(Operand*) = 0;
virtual Operand* select4(Operand*) = 0; virtual Operand* select4(Operand*) = 0;
virtual Operand* select8(Operand*) = 0; virtual Operand* select8(Operand*) = 0;
virtual Operand* select8From4(Operand*) = 0;
virtual Operand* signExtend1(Operand*) = 0;
virtual Operand* signExtend2(Operand*) = 0;
virtual Operand* zeroExtend2(Operand*) = 0;
virtual Operand* signExtend4(Operand*) = 0;
virtual Operand* stack() = 0; virtual Operand* stack() = 0;
virtual Operand* base() = 0; virtual Operand* base() = 0;