From b361e1b637156290dbcf5195a45a3e8af6b14759 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 26 Dec 2007 09:56:14 -0700 Subject: [PATCH] refactor JIT code to make operand size an explicit part of each applicable instruction --- makefile | 2 +- src/compile.cpp | 517 +++++++++++-------- src/compiler.cpp | 1257 +++++++++++++++++++++++----------------------- src/compiler.h | 70 ++- 4 files changed, 992 insertions(+), 854 deletions(-) diff --git a/makefile b/makefile index 4791b502cc..f911fe1c58 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,7 @@ src = src classpath = classpath test = test -input = $(test-build)/Misc.class +input = $(test-build)/Reflection.class build-cxx = g++ build-cc = gcc diff --git a/src/compile.cpp b/src/compile.cpp index 4fb297e538..add8438339 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -268,6 +268,76 @@ class TraceElement { uint8_t map[0]; }; +inline Stack* +push(Compiler* c, Stack* s, Operand* v) +{ + if (BytesPerWord == 8) { + return c->push8(s, v); + } else { + return c->push4(s, v); + } +} + +inline Stack* +pop(Compiler* c, Stack* s, Operand* v) +{ + if (BytesPerWord == 8) { + return c->pop8(s, v); + } else { + return c->pop4(s, v); + } +} + +inline void +mov(Compiler* c, Operand* src, Operand* dst) +{ + if (BytesPerWord == 8) { + c->mov8(src, dst); + } else { + c->mov4(src, dst); + } +} + +inline Operand* +result(Compiler* c) +{ + if (BytesPerWord == 8) { + return c->result8(); + } else { + return c->result4(); + } +} + +inline void +returnW(Compiler* c, Operand* v) +{ + if (BytesPerWord == 8) { + c->return8(v); + } else { + c->return4(v); + } +} + +inline void +cmp(Compiler* c, Operand* src, Operand* dst) +{ + if (BytesPerWord == 8) { + c->cmp8(src, dst); + } else { + c->cmp4(src, dst); + } +} + +inline void +and_(Compiler* c, Operand* src, Operand* dst) +{ + if (BytesPerWord == 8) { + c->and8(src, dst); + } else { + c->and4(src, dst); + } +} + class Frame { public: class MyProtector: public Thread::Protector { @@ -600,13 +670,46 @@ class Frame { this->ip = ip; } + void topIntToLong() { + dup(); + if (BytesPerWord == 4) { + c->mov4To8(c->stack(stack, 0), c->stack(stack, 0)); + } + } + + void topLongToInt() { + mov(c, c->stack(stack, 0), c->stack(stack, 1)); + stack = c->pop(stack, 1); + poppedInt(); + } + void pushInt(Operand* o) { - stack = c->push(stack, o); + stack = push(c, stack, o); + pushedInt(); + } + + void pushInt1(Operand* o) { + stack = c->push1(stack, o); + pushedInt(); + } + + void pushInt2(Operand* o) { + stack = c->push2(stack, o); + pushedInt(); + } + + void pushInt2z(Operand* o) { + stack = c->push2z(stack, o); + pushedInt(); + } + + void pushInt4(Operand* o) { + stack = c->push4(stack, o); pushedInt(); } void pushObject(Operand* o) { - stack = c->push(stack, o); + stack = push(c, stack, o); pushedObject(); } @@ -619,10 +722,10 @@ class Frame { if (BytesPerWord == 8) { stack = c->push(stack, 1); } - stack = c->push(stack, o); + stack = c->push8(stack, o); pushedInt(); - pushedInt(); + pushedInt(); } void pop(unsigned count) { @@ -653,13 +756,13 @@ class Frame { } Operand* popInt() { - Operand* tmp = c->select4(c->temporary()); + Operand* tmp = c->temporary(); popInt(tmp); return tmp; } Operand* popLong() { - Operand* tmp = c->select8(c->temporary()); + Operand* tmp = c->temporary(); popLong(tmp); return tmp; } @@ -671,12 +774,12 @@ class Frame { } void popInt(Operand* o) { - stack = c->pop(stack, o); + stack = ::pop(c, stack, o); poppedInt(); } void popLong(Operand* o) { - stack = c->pop(stack, o); + stack = c->pop8(stack, o); if (BytesPerWord == 8) { stack = c->pop(stack, 1); } @@ -686,7 +789,7 @@ class Frame { } void popObject(Operand* o) { - stack = c->pop(stack, o); + stack = ::pop(c, stack, o); poppedObject(); } @@ -694,7 +797,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->select4(c->memory(c->base(), localOffset(t, index, method)))); + pushInt(c->memory(c->base(), localOffset(t, index, method))); } void loadLong(unsigned index) { @@ -704,8 +807,7 @@ 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 + 1, method)))); + pushLong(c->memory(c->base(), localOffset(t, index + 1, method))); } void loadObject(unsigned index) { @@ -721,8 +823,7 @@ class Frame { } void storeLong(unsigned index) { - popLong - (c->select8(c->memory(c->base(), localOffset(t, index + 1, method)))); + popLong(c->memory(c->base(), localOffset(t, index + 1, method))); storedInt(index); storedInt(index + 1); } @@ -736,56 +837,56 @@ class Frame { assert(t, index < codeMaxLocals(t, methodCode(t, method))); assert(t, index < parameterFootprint(t, method) or getBit(map, index - parameterFootprint(t, method)) == 0); - c->add(c->constant(count), - c->memory(c->base(), localOffset(t, index, method))); + c->add4(c->constant(count), + c->memory(c->base(), localOffset(t, index, method))); } void dup() { - stack = c->push(stack, c->stack(stack, 0)); + stack = push(c, stack, c->stack(stack, 0)); dupped(); } void dupX1() { - stack = c->push(stack, c->stack(stack, 0)); - c->mov(c->stack(stack, 2), c->stack(stack, 1)); - c->mov(c->stack(stack, 0), c->stack(stack, 2)); + stack = push(c, stack, c->stack(stack, 0)); + mov(c, c->stack(stack, 2), c->stack(stack, 1)); + mov(c, c->stack(stack, 0), c->stack(stack, 2)); duppedX1(); } void dupX2() { - stack = c->push(stack, c->stack(stack, 0)); - c->mov(c->stack(stack, 2), c->stack(stack, 1)); - c->mov(c->stack(stack, 3), c->stack(stack, 2)); - c->mov(c->stack(stack, 0), c->stack(stack, 3)); + stack = push(c, stack, c->stack(stack, 0)); + mov(c, c->stack(stack, 2), c->stack(stack, 1)); + mov(c, c->stack(stack, 3), c->stack(stack, 2)); + mov(c, c->stack(stack, 0), c->stack(stack, 3)); duppedX2(); } void dup2() { - stack = c->push(stack, c->stack(stack, 0)); - stack = c->push(stack, c->stack(stack, 1)); + stack = push(c, stack, c->stack(stack, 0)); + stack = push(c, stack, c->stack(stack, 1)); dupped2(); } void dup2X1() { - stack = c->push(stack, c->stack(stack, 1)); - stack = c->push(stack, c->stack(stack, 1)); - c->mov(c->stack(stack, 4), c->stack(stack, 2)); - c->mov(c->stack(stack, 1), c->stack(stack, 4)); - c->mov(c->stack(stack, 0), c->stack(stack, 3)); + stack = push(c, stack, c->stack(stack, 1)); + stack = push(c, stack, c->stack(stack, 1)); + mov(c, c->stack(stack, 4), c->stack(stack, 2)); + mov(c, c->stack(stack, 1), c->stack(stack, 4)); + mov(c, c->stack(stack, 0), c->stack(stack, 3)); dupped2X1(); } void dup2X2() { - stack = c->push(stack, c->stack(stack, 1)); - stack = c->push(stack, c->stack(stack, 1)); - c->mov(c->stack(stack, 5), c->stack(stack, 3)); - c->mov(c->stack(stack, 4), c->stack(stack, 2)); - c->mov(c->stack(stack, 1), c->stack(stack, 5)); - c->mov(c->stack(stack, 0), c->stack(stack, 4)); + stack = push(c, stack, c->stack(stack, 1)); + stack = push(c, stack, c->stack(stack, 1)); + mov(c, c->stack(stack, 5), c->stack(stack, 3)); + mov(c, c->stack(stack, 4), c->stack(stack, 2)); + mov(c, c->stack(stack, 1), c->stack(stack, 5)); + mov(c, c->stack(stack, 0), c->stack(stack, 4)); dupped2X2(); } @@ -795,9 +896,9 @@ class Frame { Operand* s1 = c->stack(stack, 1); Operand* tmp = c->temporary(); - c->mov(s0, tmp); - c->mov(s1, s0); - c->mov(tmp, s1); + mov(c, s0, tmp); + mov(c, s1, s0); + mov(c, tmp, s1); c->release(tmp); @@ -1192,7 +1293,7 @@ checkCast(MyThread* t, object class_, object o) void pushReturnValue(MyThread* t, Frame* frame, unsigned code) { - Operand* result = frame->c->result(); + Compiler* c = frame->c; switch (code) { case ByteField: @@ -1200,18 +1301,24 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code) case CharField: case ShortField: case FloatField: - case IntField: - frame->pushInt(frame->c->select4(result)); - break; + case IntField: { + Operand* result = c->result4(); + frame->pushInt(result); + c->release(result); + } break; - case ObjectField: + case ObjectField: { + Operand* result = ::result(c); frame->pushObject(result); - break; + c->release(result); + } break; case LongField: - case DoubleField: - frame->pushLong(frame->c->select8(result)); - break; + case DoubleField: { + Operand* result = c->result8(); + frame->pushLong(result); + c->release(result); + } break; case VoidField: break; @@ -1219,8 +1326,6 @@ pushReturnValue(MyThread* t, Frame* frame, unsigned code) default: abort(t); } - - frame->c->release(result); } void @@ -1278,10 +1383,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* index = frame->popInt(); Operand* array = frame->popObject(); - c->cmp(c->constant(0), index); + c->cmp4(c->constant(0), index); c->jl(outOfBounds); - c->cmp(c->memory(array, ArrayLength), index); + c->cmp4(c->memory(array, ArrayLength), index); c->jge(outOfBounds); switch (instruction) { @@ -1291,24 +1396,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case faload: case iaload: - frame->pushInt(c->select4(c->memory(array, ArrayBody, index, 4))); + frame->pushInt4(c->memory(array, ArrayBody, index, 4)); break; case baload: - frame->pushInt(c->select1(c->memory(array, ArrayBody, index, 1))); + frame->pushInt1(c->memory(array, ArrayBody, index, 1)); break; case caload: - frame->pushInt(c->select2z(c->memory(array, ArrayBody, index, 2))); + frame->pushInt2z(c->memory(array, ArrayBody, index, 2)); break; case daload: case laload: - frame->pushLong(c->select8(c->memory(array, ArrayBody, index, 8))); + frame->pushLong(c->memory(array, ArrayBody, index, 8)); break; case saload: - frame->pushInt(c->select2(c->memory(array, ArrayBody, index, 2))); + frame->pushInt2(c->memory(array, ArrayBody, index, 2)); break; } @@ -1346,16 +1451,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* index = frame->popInt(); Operand* array = frame->popObject(); - c->cmp(c->constant(0), index); + c->cmp4(c->constant(0), index); c->jl(outOfBounds); - c->cmp(c->memory(array, BytesPerWord), index); + c->cmp4(c->memory(array, BytesPerWord), index); c->jge(outOfBounds); switch (instruction) { case aastore: { - c->shl(c->constant(log(BytesPerWord)), index); - c->add(c->constant(ArrayBody), index); + c->shl4(c->constant(log(BytesPerWord)), index); + c->add4(c->constant(ArrayBody), index); Promise* returnAddress = c->directCall (c->constant(reinterpret_cast(set)), @@ -1366,21 +1471,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case fastore: case iastore: - c->mov(c->select4(value), c->memory(array, ArrayBody, index, 4)); + c->mov4(value, c->memory(array, ArrayBody, index, 4)); break; case bastore: - c->mov(c->select1(value), c->memory(array, ArrayBody, index, 1)); + c->mov1(value, c->memory(array, ArrayBody, index, 1)); break; case castore: case sastore: - c->mov(c->select2(value), c->memory(array, ArrayBody, index, 2)); + c->mov2(value, c->memory(array, ArrayBody, index, 2)); break; case dastore: case lastore: - c->mov(c->select8(value), c->memory(array, ArrayBody, index, 8)); + c->mov8(value, c->memory(array, ArrayBody, index, 8)); break; } @@ -1429,7 +1534,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* nonnegative = c->label(); Operand* length = frame->popInt(); - c->cmp(c->constant(0), length); + c->cmp4(c->constant(0), length); c->jge(nonnegative); compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType); @@ -1440,7 +1545,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(makeBlankObjectArray)), 3, c->thread(), frame->append(class_), length); - Operand* result = c->result(); + Operand* result = ::result(c); c->release(length); @@ -1452,13 +1557,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case areturn: { Operand* result = frame->popObject(); - c->return_(result); + returnW(c, result); c->release(result); } return; case arraylength: { Operand* array = frame->popObject(); - frame->pushInt(c->memory(array, ArrayLength)); + frame->pushInt4(c->memory(array, ArrayLength)); c->release(array); } break; @@ -1518,10 +1623,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(doubleToFloat)), 1, a); + (c->constant(reinterpret_cast(doubleToFloat)), 2, 0, a); c->release(a); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1530,10 +1635,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(doubleToInt)), 1, a); + (c->constant(reinterpret_cast(doubleToInt)), 2, 0, a); c->release(a); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1542,10 +1647,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(doubleToLong)), 1, a); + (c->constant(reinterpret_cast(doubleToLong)), 2, 0, a); c->release(a); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1555,11 +1660,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(addDouble)), 2, a, b); + (c->constant(reinterpret_cast(addDouble)), 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1569,11 +1674,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(compareDoublesG)), 2, a, b); + (c->constant(reinterpret_cast(compareDoublesG)), + 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1583,21 +1689,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(compareDoublesL)), 2, a, b); + (c->constant(reinterpret_cast(compareDoublesL)), + 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; case dconst_0: - frame->pushLong(c->select8(c->constant(doubleToBits(0.0)))); + frame->pushLong(c->constant(doubleToBits(0.0))); break; case dconst_1: - frame->pushLong(c->select8(c->constant(doubleToBits(1.0)))); + frame->pushLong(c->constant(doubleToBits(1.0))); break; case ddiv: { @@ -1605,11 +1712,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(divideDouble)), 2, a, b); + (c->constant(reinterpret_cast(divideDouble)), + 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1619,11 +1727,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(multiplyDouble)), 2, a, b); + (c->constant(reinterpret_cast(multiplyDouble)), + 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1632,10 +1741,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(negateDouble)), 1, a); + (c->constant(reinterpret_cast(negateDouble)), 2, 0, a); c->release(a); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1645,11 +1754,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(moduloDouble)), 2, a, b); + (c->constant(reinterpret_cast(moduloDouble)), 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1659,11 +1768,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); c->directCall - (c->constant(reinterpret_cast(subtractDouble)), 2, a, b); + (c->constant(reinterpret_cast(subtractDouble)), + 4, 0, a, 0, b); c->release(a); c->release(b); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1699,7 +1809,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(floatToDouble)), 1, a); c->release(a); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1711,7 +1821,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(floatToInt)), 1, a); c->release(a); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1723,7 +1833,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(floatToLong)), 1, a); c->release(a); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); } break; @@ -1737,7 +1847,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1751,7 +1861,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1765,7 +1875,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1791,7 +1901,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1805,20 +1915,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; case fneg: { - Operand* a = frame->popLong(); + Operand* a = frame->popInt(); c->directCall (c->constant(reinterpret_cast(negateFloat)), 1, a); c->release(a); - Operand* result = c->select8(c->result()); - frame->pushLong(result); + Operand* result = c->result4(); + frame->pushInt(result); c->release(result); } break; @@ -1831,7 +1941,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1845,7 +1955,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(a); c->release(b); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); } break; @@ -1873,30 +1983,25 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - frame->pushInt - (c->select1(c->memory(table, fieldOffset(t, field)))); + frame->pushInt1(c->memory(table, fieldOffset(t, field))); break; case CharField: - frame->pushInt - (c->select2z(c->memory(table, fieldOffset(t, field)))); + frame->pushInt2z(c->memory(table, fieldOffset(t, field))); break; case ShortField: - frame->pushInt - (c->select2(c->memory(table, fieldOffset(t, field)))); + frame->pushInt2(c->memory(table, fieldOffset(t, field))); break; case FloatField: case IntField: - frame->pushInt - (c->select4(c->memory(table, fieldOffset(t, field)))); + frame->pushInt4(c->memory(table, fieldOffset(t, field))); break; case DoubleField: case LongField: - frame->pushLong - (c->select8(c->memory(table, fieldOffset(t, field)))); + frame->pushLong(c->memory(table, fieldOffset(t, field))); break; case ObjectField: @@ -1930,12 +2035,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case i2b: { Operand* top = frame->topInt(); - c->mov(c->select1(top), top); + c->mov1ToW(top, top); } break; case i2c: { Operand* top = frame->topInt(); - c->mov(c->select2z(top), top); + c->mov2zToW(top, top); } break; case i2d: { @@ -1944,7 +2049,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->directCall (c->constant(reinterpret_cast(intToDouble)), 1, a); - Operand* result = c->select8(c->result()); + Operand* result = c->result8(); frame->pushLong(result); c->release(result); c->release(a); @@ -1956,32 +2061,30 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->directCall (c->constant(reinterpret_cast(intToFloat)), 1, a); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); c->release(a); } break; case i2l: { - Operand* a = frame->popInt(); - frame->pushLong(c->select8From4(a)); - c->release(a); + frame->topIntToLong(); } break; case i2s: { Operand* top = frame->topInt(); - c->mov(c->select2(top), top); + c->mov2ToW(top, top); } break; case iadd: { Operand* a = frame->popInt(); - c->add(a, frame->topInt()); + c->add4(a, frame->topInt()); c->release(a); } break; case iand: { Operand* a = frame->popInt(); - c->and_(a, frame->topInt()); + c->and4(a, frame->topInt()); c->release(a); } break; @@ -2015,7 +2118,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case idiv: { Operand* a = frame->popInt(); - c->div(a, frame->topInt()); + c->div4(a, frame->topInt()); c->release(a); } break; @@ -2026,7 +2129,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popObject(); Operand* b = frame->popObject(); - c->cmp(a, b); + cmp(c, a, b); c->release(a); c->release(b); @@ -2052,7 +2155,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popInt(); Operand* b = frame->popInt(); - c->cmp(a, b); + c->cmp4(a, b); c->release(a); c->release(b); @@ -2092,7 +2195,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) assert(t, newIp < codeLength(t, code)); Operand* a = frame->popInt(); - c->cmp(c->constant(0), a); + c->cmp4(c->constant(0), a); c->release(a); Operand* target = frame->machineIp(newIp); @@ -2127,7 +2230,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) assert(t, newIp < codeLength(t, code)); Operand* a = frame->popObject(); - c->cmp(c->constant(0), a); + cmp(c, c->constant(0), a); c->release(a); Operand* target = frame->machineIp(newIp); @@ -2175,7 +2278,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case imul: { Operand* a = frame->popInt(); - c->mul(a, frame->topInt()); + c->mul4(a, frame->topInt()); c->release(a); } break; @@ -2193,7 +2296,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(instanceOf)), 3, c->thread(), classOperand, instance); - Operand* result = c->select4(c->result()); + Operand* result = c->result4(); frame->pushInt(result); c->release(result); c->release(instance); @@ -2216,7 +2319,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 3, c->thread(), frame->append(target), c->stack(frame->stack, instance)); - Operand* result = c->result(); + Operand* result = ::result(c); c->call(result); c->release(result); @@ -2270,8 +2373,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* instance = c->stack(frame->stack, parameterFootprint - 1); Operand* class_ = c->temporary(); - c->mov(c->memory(instance), class_); - c->and_(c->constant(PointerMask), class_); + mov(c, c->memory(instance), class_); + and_(c, c->constant(PointerMask), class_); c->call(c->memory(class_, offset)); @@ -2286,32 +2389,32 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ior: { Operand* a = frame->popInt(); - c->or_(a, frame->topInt()); + c->or4(a, frame->topInt()); c->release(a); } break; case irem: { Operand* a = frame->popInt(); - c->rem(a, frame->topInt()); + c->rem4(a, frame->topInt()); c->release(a); } break; case ireturn: case freturn: { Operand* a = frame->popInt(); - c->return_(a); + c->return4(a); c->release(a); } return; case ishl: { Operand* a = frame->popInt(); - c->shl(a, frame->topInt()); + c->shl4(a, frame->topInt()); c->release(a); } break; case ishr: { Operand* a = frame->popInt(); - c->shr(a, frame->topInt()); + c->shr4(a, frame->topInt()); c->release(a); } break; @@ -2342,19 +2445,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case isub: { Operand* a = frame->popInt(); - c->sub(a, frame->topInt()); + c->sub4(a, frame->topInt()); c->release(a); } break; case iushr: { Operand* a = frame->popInt(); - c->ushr(a, frame->topInt()); + c->ushr4(a, frame->topInt()); c->release(a); } break; case ixor: { Operand* a = frame->popInt(); - c->xor_(a, frame->topInt()); + c->xor4(a, frame->topInt()); c->release(a); } break; @@ -2365,14 +2468,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) abort(t); case l2i: { - Operand* a = frame->popLong(); - frame->pushInt(c->select4(a)); - c->release(a); + frame->topLongToInt(); } break; case ladd: { Operand* a = frame->popLong(); - c->add(a, frame->topLong()); + c->add8(a, frame->topLong()); c->release(a); } break; @@ -2385,22 +2486,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* b = frame->popLong(); Operand* result = c->temporary(); - c->cmp(a, b); + c->cmp8(a, b); c->release(a); c->release(b); c->jl(less); c->jg(greater); - c->mov(c->constant(0), result); + c->mov4(c->constant(0), result); c->jmp(next); c->mark(less); - c->mov(c->constant(-1), result); + c->mov4(c->constant(-1), result); c->jmp(next); c->mark(greater); - c->mov(c->constant(1), result); + c->mov4(c->constant(1), result); c->mark(next); frame->pushInt(result); @@ -2409,11 +2510,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case lconst_0: - frame->pushLong(c->select8(c->constant(0))); + frame->pushLong(c->constant(0)); break; case lconst_1: - frame->pushLong(c->select8(c->constant(1))); + frame->pushLong(c->constant(1)); break; case ldc: @@ -2452,12 +2553,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint64_t v; memcpy(&v, &singletonValue(t, pool, index - 1), 8); - frame->pushLong(c->select8(c->constant(v))); + frame->pushLong(c->constant(v)); } break; case ldiv_: { Operand* a = frame->popLong(); - c->div(a, frame->topLong()); + c->div8(a, frame->topLong()); c->release(a); } break; @@ -2488,12 +2589,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lmul: { Operand* a = frame->popLong(); - c->mul(a, frame->topLong()); + c->mul8(a, frame->topLong()); c->release(a); } break; case lneg: - c->neg(frame->topLong()); + c->neg8(frame->topLong()); break; case lookupswitch: { @@ -2533,7 +2634,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(lookUpAddress)), 4, key, start, c->constant(pairCount), default_); - Operand* result = c->result(); + Operand* result = ::result(c); c->jmp(result); c->release(result); @@ -2550,32 +2651,32 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lor: { Operand* a = frame->popLong(); - c->or_(a, frame->topLong()); + c->or8(a, frame->topLong()); c->release(a); } break; case lrem: { Operand* a = frame->popLong(); - c->rem(a, frame->topLong()); + c->rem8(a, frame->topLong()); c->release(a); } break; case lreturn: case dreturn: { Operand* a = frame->popLong(); - c->return_(a); + c->return8(a); c->release(a); } return; case lshl: { Operand* a = frame->popLong(); - c->shl(a, frame->topLong()); + c->shl8(a, frame->topLong()); c->release(a); } break; case lshr: { Operand* a = frame->popLong(); - c->shr(a, frame->topLong()); + c->shr8(a, frame->topLong()); c->release(a); } break; @@ -2606,19 +2707,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lsub: { Operand* a = frame->popLong(); - c->sub(a, frame->topLong()); + c->sub8(a, frame->topLong()); c->release(a); } break; case lushr: { Operand* a = frame->popLong(); - c->ushr(a, frame->topLong()); + c->ushr8(a, frame->topLong()); c->release(a); } break; case lxor: { Operand* a = frame->popLong(); - c->xor_(a, frame->topLong()); + c->xor8(a, frame->topLong()); c->release(a); } break; @@ -2655,7 +2756,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 4, c->thread(), frame->append(class_), c->stack(), c->constant(dimensions)); - Operand* result = c->result(); + Operand* result = ::result(c); frame->trace(returnAddress, 0, false); @@ -2687,7 +2788,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->trace(returnAddress, 0, false); - Operand* result = c->result(); + Operand* result = ::result(c); frame->pushObject(result); c->release(result); } break; @@ -2698,7 +2799,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* nonnegative = c->label(); Operand* size = frame->popInt(); - c->cmp(c->constant(0), size); + c->cmp4(c->constant(0), size); c->jge(nonnegative); @@ -2748,7 +2849,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 3, c->thread(), c->constant(reinterpret_cast(constructor)), size); - Operand* result = c->result(); + Operand* result = ::result(c); c->release(size); @@ -2820,22 +2921,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) switch (fieldCode(t, field)) { case ByteField: case BooleanField: - c->mov(c->select1(value), c->memory(table, fieldOffset(t, field))); + c->mov1(value, c->memory(table, fieldOffset(t, field))); break; case CharField: case ShortField: - c->mov(c->select2(value), c->memory(table, fieldOffset(t, field))); + c->mov2(value, c->memory(table, fieldOffset(t, field))); break; case FloatField: case IntField: - c->mov(c->select4(value), c->memory(table, fieldOffset(t, field))); + c->mov4(value, c->memory(table, fieldOffset(t, field))); break; case DoubleField: case LongField: - c->mov(c->select8(value), c->memory(table, fieldOffset(t, field))); + c->mov8(value, c->memory(table, fieldOffset(t, field))); break; case ObjectField: @@ -2898,13 +2999,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* defaultCase = c->label(); - c->cmp(c->constant(bottom), key); + c->cmp4(c->constant(bottom), key); c->jl(defaultCase); - c->cmp(c->constant(top), key); + c->cmp4(c->constant(top), key); c->jg(defaultCase); - c->sub(c->constant(bottom), key); + c->sub4(c->constant(bottom), key); c->jmp(c->memory(start, 0, key, BytesPerWord)); c->mark(defaultCase); @@ -2965,9 +3066,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } } +void +logCompile(const void* code, unsigned size, const char* class_, + const char* name) +{ + if (Verbose) { + fprintf(stderr, "%s.%s from %p to %p\n", + class_, name, code, static_cast(code) + size); + } +} + object finish(MyThread* t, Compiler* c, object method, Vector* objectPool, - Vector* traceLog) + Vector* traceLog, const char* name) { PROTECT(t, method); @@ -3070,33 +3181,37 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, } if (Verbose) { - fprintf(stderr, "%s.%s from %p to %p\n", - &byteArrayBody(t, className(t, methodClass(t, method)), 0), - &byteArrayBody(t, methodName(t, method), 0), - start, - start + c->codeSize()); + logCompile(start, c->codeSize(), + reinterpret_cast + (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), + reinterpret_cast + (&byteArrayBody(t, methodName(t, method), 0))); } // for debugging: if (false and strcmp(reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), - "java/lang/Math") == 0 and + "java/lang/Long") == 0 and strcmp(reinterpret_cast (&byteArrayBody(t, methodName(t, method), 0)), - "max") == 0) + "valueOf") == 0) { asm("int3"); } + } else { + if (Verbose) { + logCompile(start, c->codeSize(), 0, name); + } } return result; } object -finish(MyThread* t, Compiler* c) +finish(MyThread* t, Compiler* c, const char* name) { - return finish(t, c, 0, 0, 0); + return finish(t, c, 0, 0, 0, name); } object @@ -3139,7 +3254,7 @@ compile(MyThread* t, Compiler* c, object method) } } - return finish(t, c, method, &objectPool, &traceLog); + return finish(t, c, method, &objectPool, &traceLog, 0); } void @@ -3449,32 +3564,32 @@ visitStack(MyThread* t, Heap::Visitor* v) object 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))); + mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); + mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); c->directCall (c->constant(reinterpret_cast(compileMethod)), 1, c->thread()); - Operand* result = c->result(); + Operand* result = ::result(c); c->jmp(result); c->release(result); - return finish(t, c); + return finish(t, c, "default"); } object compileNative(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))); + mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); + mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); c->directCall (c->constant(reinterpret_cast(invokeNative)), 1, c->thread()); c->ret(); - return finish(t, c); + return finish(t, c, "native"); } class ArgumentList { @@ -3935,8 +4050,8 @@ processor(MyThread* t) Compiler* c = makeCompiler(t->m->system, 0); - c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t))); - c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); + mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); + mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); c->jmp(c->indirectTarget()); @@ -3944,6 +4059,10 @@ processor(MyThread* t) (t->m->system->allocate(c->codeSize())); c->writeTo(p->indirectCaller); + if (Verbose) { + logCompile(p->indirectCaller, c->codeSize(), 0, "indirect caller"); + } + c->dispose(); } } diff --git a/src/compiler.cpp b/src/compiler.cpp index a685b0431d..2238310ca9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -26,21 +26,10 @@ enum Register { r15 = 15, }; -enum SelectionType { - Select1, - Select2, - Select2z, - Select4, - Select8, - Select8From4 -}; - const bool Verbose = false; const unsigned RegisterCount = BytesPerWord * 2; const unsigned GprParameterCount = 6; -const SelectionType DefaultSelection -= (BytesPerWord == 8 ? Select8 : Select4); class Context; class MyOperand; @@ -53,19 +42,6 @@ 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) { @@ -322,32 +298,44 @@ AddressOperand* address(Context* c, MyPromise* p); ImmediateOperand* -immediate(Context* c, int64_t v, SelectionType = DefaultSelection); +immediate(Context* c, int64_t v); AbsoluteOperand* absolute(Context* c, MyPromise* v); RegisterOperand* -register_(Context* c, RegisterReference*, SelectionType = DefaultSelection); +register_(Context* c, RegisterReference*); RegisterOperand* -register_(Context* c, Register = NoRegister, Register = NoRegister, - SelectionType = DefaultSelection); +register_(Context* c, Register = NoRegister, Register = NoRegister); MemoryOperand* memory(Context* c, MyOperand* base, int displacement, - MyOperand* index, unsigned scale, SelectionType = DefaultSelection); + MyOperand* index, unsigned scale); class MyOperand: public Operand { public: enum Operation { - push, - pop, + push1, + push2, + push2z, + push4, + push8, + pop4, + pop8, call, alignedCall, ret, - mov, - cmp, + mov1, + mov2, + mov4, + mov8, + mov1ToW, + mov2ToW, + mov2zToW, + mov4To8, + cmp4, + cmp8, jl, jg, jle, @@ -355,32 +343,47 @@ class MyOperand: public Operand { je, jne, jmp, - add, + add4, + add8, + sub4, + sub8, + mul4, + mul8, + div4, + div8, + rem4, + rem8, + shl4, + shl8, + shr4, + shr8, + ushr4, + ushr8, + and4, + and8, + or4, + or8, + xor4, + xor8, + neg4, + neg8, addc, - sub, - subb, - mul, - div, - rem, - shl, - shr, - ushr, - and_, - or_, - xor_, - neg + subb }; + static const Operation push = (BytesPerWord == 8 ? push8 : push4); + static const Operation pop = (BytesPerWord == 8 ? pop8 : pop4); + static const Operation mov = (BytesPerWord == 8 ? mov8 : mov4); + static const Operation cmp = (BytesPerWord == 8 ? cmp8 : cmp4); + static const Operation add = (BytesPerWord == 8 ? add8 : add4); + static const Operation sub = (BytesPerWord == 8 ? sub8 : sub4); + static const Operation mul = (BytesPerWord == 8 ? mul8 : mul4); + static const Operation neg = (BytesPerWord == 8 ? neg8 : neg4); + virtual ~MyOperand() { } - virtual unsigned footprint(Context*) { - return BytesPerWord; - } - virtual Register asRegister(Context* c) { abort(c); } - virtual MyOperand* select(Context* c, SelectionType) { abort(c); } - virtual RegisterNode* dependencies(Context*, RegisterNode* next) { return next; } @@ -501,8 +504,8 @@ class RegisterReference { class RegisterOperand: public MyOperand { public: - RegisterOperand(RegisterReference* reference, SelectionType selection): - reference(reference), selection(selection) + RegisterOperand(RegisterReference* reference): + reference(reference) { } Register value(Context* c) { @@ -513,22 +516,10 @@ class RegisterOperand: public MyOperand { return reference->high(c); } - virtual unsigned footprint(Context*) { - return ::footprint(selection); - } - virtual Register asRegister(Context* c) { return value(c); } - virtual MyOperand* select(Context* c, SelectionType selection) { - if (selection == this->selection) { - return this; - } else { - return register_(c, reference, selection); - } - } - virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { return new (c->zone.allocate(sizeof(RegisterNode))) RegisterNode(value(c), next); @@ -551,23 +542,14 @@ class RegisterOperand: public MyOperand { virtual void accept(Context*, Operation, MemoryOperand*); RegisterReference* reference; - SelectionType selection; }; class ImmediateOperand: public MyOperand { public: - ImmediateOperand(int64_t value, SelectionType selection): - value(value), selection(selection) + ImmediateOperand(int64_t value): + value(value) { } - virtual unsigned footprint(Context*) { - return ::footprint(selection); - } - - virtual MyOperand* select(Context* c, SelectionType selection) { - return immediate(c, value, selection); - } - virtual void apply(Context* c, Operation operation); virtual void apply(Context* c, Operation operation, MyOperand* operand) { @@ -581,7 +563,6 @@ class ImmediateOperand: public MyOperand { virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); } int64_t value; - SelectionType selection; }; class AddressOperand: public MyOperand { @@ -634,24 +615,15 @@ class AbsoluteOperand: public MyOperand { class MemoryOperand: public MyOperand { public: MemoryOperand(MyOperand* base, int displacement, MyOperand* index, - unsigned scale, SelectionType selection): + unsigned scale): base(base), displacement(displacement), index(index), - scale(scale), - selection(selection) + scale(scale) { } - virtual unsigned footprint(Context*) { - return ::footprint(selection); - } - virtual Register asRegister(Context*); - virtual MyOperand* select(Context* c, SelectionType selection) { - return memory(c, base, displacement, index, scale, selection); - } - virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { next = base->dependencies(c, next); if (index) { @@ -677,7 +649,6 @@ class MemoryOperand: public MyOperand { int displacement; MyOperand* index; unsigned scale; - SelectionType selection; }; AddressOperand* @@ -687,10 +658,10 @@ address(Context* c, MyPromise* p) } ImmediateOperand* -immediate(Context* c, int64_t v, SelectionType selection) +immediate(Context* c, int64_t v) { return new (c->zone.allocate(sizeof(ImmediateOperand))) - ImmediateOperand(v, selection); + ImmediateOperand(v); } AbsoluteOperand* @@ -700,26 +671,26 @@ absolute(Context* c, MyPromise* v) } RegisterOperand* -register_(Context* c, RegisterReference* r, SelectionType selection) +register_(Context* c, RegisterReference* r) { return new (c->zone.allocate(sizeof(RegisterOperand))) - RegisterOperand(r, selection); + RegisterOperand(r); } RegisterOperand* -register_(Context* c, Register v, Register h, SelectionType selection) +register_(Context* c, Register v, Register h) { RegisterReference* r = new (c->zone.allocate(sizeof(RegisterReference))) RegisterReference(v, h); - return register_(c, r, selection); + return register_(c, r); } MemoryOperand* memory(Context* c, MyOperand* base, int displacement, - MyOperand* index, unsigned scale, SelectionType selection) + MyOperand* index, unsigned scale) { return new (c->zone.allocate(sizeof(MemoryOperand))) - MemoryOperand(base, displacement, index, scale, selection); + MemoryOperand(base, displacement, index, scale); } RegisterOperand* @@ -728,16 +699,6 @@ temporary(Context* c) return register_(c, acquire(c)); } -RegisterOperand* -temporary(Context* c, SelectionType selection) -{ - if (BytesPerWord == 4 and selection == Select8) { - return register_(c, acquire(c), acquire(c), selection); - } else { - return register_(c, acquire(c), NoRegister, selection); - } -} - RegisterOperand* temporary(Context* c, Register v) { @@ -937,14 +898,18 @@ class ArgumentEvent: public Event { m->destination = gpRegister(c, i); m->dependencies = arguments[i]->dependencies(c, 0); } else { - arguments[i]->apply(c, MyOperand::push); + arguments[i]->apply(c, MyOperand::push8); } } push(c, moveTable, size); } else { for (int i = count - 1; i >= 0; --i) { - arguments[i]->apply(c, MyOperand::push); + if (i > 0 and arguments[i - 1] == 0) { + arguments[i]->apply(c, MyOperand::push8); + } else { + arguments[i]->apply(c, MyOperand::push4); + } } } } @@ -1036,11 +1001,11 @@ pushed(Context* c, MyStack* stack) } MyStack* -push(Context* c, MyStack* stack, MyOperand* v) +push(Context* c, MyStack* stack, MyOperand::Operation operation, MyOperand* v) { - appendOperation(c, MyOperand::push, v); + appendOperation(c, operation, v); - if ((v->footprint(c) / BytesPerWord) == 2) { + if (BytesPerWord == 4 and operation == MyOperand::push8) { stack = pushed(c, stack); } return pushed(c, stack); @@ -1066,11 +1031,11 @@ pop(Context* c, MyStack* stack, int count) } MyStack* -pop(Context* c, MyStack* stack, MyOperand* dst) +pop(Context* c, MyStack* stack, MyOperand::Operation operation, MyOperand* dst) { - appendOperation(c, MyOperand::pop, dst); + appendOperation(c, operation, dst); - if (dst->footprint(c) / BytesPerWord == 2) { + if (BytesPerWord == 4 and operation == MyOperand::pop8) { stack = stack->next; } @@ -1081,27 +1046,38 @@ pop(Context* c, MyStack* stack, MyOperand* dst) return stack->next; } -unsigned +void pushArguments(Context* c, unsigned count, va_list list) { MyOperand** arguments = static_cast (c->zone.allocate(count * BytesPerWord)); - unsigned footprint = 0; + + unsigned index = 0; for (unsigned i = 0; i < count; ++i) { - arguments[i] = va_arg(list, MyOperand*); - footprint += pad(arguments[i]->footprint(c)); + if (BytesPerWord == 8) { + arguments[index] = va_arg(list, MyOperand*); + if (arguments[index]) { + ++ index; + } + } else { + arguments[index++] = va_arg(list, MyOperand*); + } } - appendArgumentEvent(c, arguments, count); + appendArgumentEvent(c, arguments, index); +} +unsigned +argumentFootprint(unsigned count) +{ if (BytesPerWord == 8) { - if (footprint > GprParameterCount * BytesPerWord) { - return footprint - GprParameterCount * BytesPerWord; + if (count > GprParameterCount) { + return (count - GprParameterCount) * BytesPerWord; } else { return 0; } } else { - return footprint; + return count * BytesPerWord; } } @@ -1113,17 +1089,6 @@ 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) @@ -1170,15 +1135,6 @@ 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) { @@ -1196,70 +1152,33 @@ RegisterOperand::apply(Context* c, Operation operation) { 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 or selection == Select4) { - c->code.append(0x58 | value(c)); - } else { - assert(c, selection == Select8); - + case pop4: + case pop8: + if (BytesPerWord == 4 and operation == pop8) { register_(c, value(c))->apply(c, pop); register_(c, high(c))->apply(c, pop); - } - break; - - case push: - if (selection == DefaultSelection or selection == Select4) - { - 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: { - if (BytesPerWord == 8) { - RegisterOperand* fullSize = register_ - (c, reference, DefaultSelection); - fullSize->accept(c, mov, this); - fullSize->apply(c, operation); - } else { - 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); - } + c->code.append(0x58 | value(c)); } break; - case neg: - rex(c, selection); - c->code.append(0xf7); - c->code.append(0xd8 | value(c)); + case push4: + case push8: + if (BytesPerWord == 4 and operation == push8) { + register_(c, high(c))->apply(c, push); + register_(c, value(c))->apply(c, push); + } else { + c->code.append(0x50 | value(c)); + } break; default: abort(c); @@ -1272,25 +1191,14 @@ RegisterOperand::accept(Context* c, Operation operation, { switch (operation) { case add: - assert(c, selection == operand->selection); - - rex(c, operand->selection); + rex(c); c->code.append(0x01); c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); break; - case cmp: - 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, operand->selection == Select8); - + case cmp4: + case cmp8: + if (BytesPerWord == 4 and operation == cmp8) { register_(c, high(c))->accept (c, cmp, register_(c, operand->high(c))); @@ -1302,57 +1210,55 @@ RegisterOperand::accept(Context* c, Operation operation, register_(c, value(c))->accept (c, cmp, register_(c, operand->value(c))); + } else { + rex(c); + c->code.append(0x39); + c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); } break; - case mov: - if (value(c) != operand->value(c) or selection != operand->selection) { - 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 Select1: - c->code.append(0xbe); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case Select2: - c->code.append(0xbf); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case Select2z: - c->code.append(0xb7); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case Select4: - case Select8From4: - rex(c); - c->code.append(0x63); - c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); - break; - - case Select8: - register_(c, value(c))->accept - (c, mov, register_(c, operand->value(c))); - - register_(c, high(c))->accept - (c, mov, register_(c, operand->high(c))); - break; - - default: abort(c); - } - } + case mov4: + case mov8: + if (BytesPerWord == 4 and operation == mov8) { + register_(c, value(c))->accept + (c, mov, register_(c, operand->value(c))); + + register_(c, high(c))->accept + (c, mov, register_(c, operand->high(c))); + } else if (value(c) != operand->value(c)) { + rex(c); + c->code.append(0x89); + c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); } break; - case mul: - rex(c, selection); + case mov1ToW: + c->code.append(0xbe); + c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); + break; + + case mov2ToW: + c->code.append(0xbf); + c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); + break; + + case mov2zToW: + c->code.append(0xb7); + c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); + break; + + case mov4To8: + assert(c, BytesPerWord == 8); + rex(c); + c->code.append(0x63); + c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); + break; + + case mul4: + case mul8: + assert(c, BytesPerWord == 8 or operation == mul4); // todo + + rex(c); c->code.append(0x0f); c->code.append(0xaf); c->code.append(0xc0 | (value(c) << 3) | operand->value(c)); @@ -1366,12 +1272,13 @@ void RegisterOperand::accept(Context* c, Operation operation, ImmediateOperand* operand) { - assert(c, operand->selection == DefaultSelection); - switch (operation) { - case add: { + case add4: + case add8: + assert(c, BytesPerWord == 8 or operation == add4); // todo + if (operand->value) { - rex(c, selection); + rex(c); if (isInt8(operand->value)) { c->code.append(0x83); c->code.append(0xc0 | value(c)); @@ -1384,7 +1291,7 @@ RegisterOperand::accept(Context* c, Operation operation, abort(c); } } - } break; + break; case addc: if (isInt8(operand->value)) { @@ -1396,8 +1303,11 @@ RegisterOperand::accept(Context* c, Operation operation, } break; - case and_: { - rex(c, selection); + case and4: + case and8: + assert(c, BytesPerWord == 8 or operation == and4); // todo + + rex(c); if (isInt8(operand->value)) { c->code.append(0x83); c->code.append(0xe0 | value(c)); @@ -1409,26 +1319,34 @@ RegisterOperand::accept(Context* c, Operation operation, c->code.append(0xe0 | value(c)); c->code.append(operand->value); } - } break; + break; - case cmp: { + case cmp4: + case cmp8: { assert(c, isInt8(operand->value)); // todo + assert(c, BytesPerWord == 8 or operation == cmp4); // todo - rex(c, selection); + rex(c); c->code.append(0x83); c->code.append(0xf8 | value(c)); c->code.append(operand->value); } break; - case mov: { + case mov4: + case mov8: { + assert(c, BytesPerWord == 8 or operation == mov4); // todo + rex(c); c->code.append(0xb8 | value(c)); c->code.appendAddress(operand->value); } break; - case shl: { + case shl4: + case shl8: { + assert(c, BytesPerWord == 8 or operation == shl4); // todo + if (operand->value) { - rex(c, selection); + rex(c); if (operand->value == 1) { c->code.append(0xd1); c->code.append(0xe0 | value(c)); @@ -1442,9 +1360,12 @@ RegisterOperand::accept(Context* c, Operation operation, } } break; - case sub: { + case sub4: + case sub8: { + assert(c, BytesPerWord == 8 or operation == sub4); // todo + if (operand->value) { - rex(c, selection); + rex(c); if (isInt8(operand->value)) { c->code.append(0x83); c->code.append(0xe8 | value(c)); @@ -1477,8 +1398,6 @@ void RegisterOperand::accept(Context* c, Operation operation, AddressOperand* operand) { - assert(c, selection == DefaultSelection); - switch (operation) { case mov: { accept(c, operation, ::value(c, operand)); @@ -1493,65 +1412,49 @@ RegisterOperand::accept(Context* c, Operation operation, MemoryOperand* operand) { switch (operation) { - case cmp: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x3b, value(c), operand, operand->selection); - } else { - abort(c); - } - } break; + case cmp4: + case cmp8: + assert(c, BytesPerWord == 8 or operation == cmp4); // todo - case mov: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { + encode(c, 0x3b, value(c), operand, true); + break; + + case mov4: + case mov8: + if (BytesPerWord == 4 and operation == mov8) { + register_(c, value(c))->accept + (c, mov, memory + (c, operand->base, operand->displacement, + operand->index, operand->scale)); + + register_(c, high(c))->accept + (c, mov, memory + (c, operand->base, operand->displacement + BytesPerWord, + operand->index, operand->scale)); + } else if (BytesPerWord == 8 and operation == mov4) { + encode(c, 0x63, value(c), operand, true); + } else { encode(c, 0x8b, value(c), operand, true); - } else { - switch (operand->selection) { - case Select1: - encode2(c, 0x0fbe, value(c), operand, true); - break; - - case Select2: - encode2(c, 0x0fbf, value(c), operand, true); - break; - - case Select2z: - encode2(c, 0x0fb7, value(c), operand, true); - break; - - case Select4: - encode(c, 0x63, value(c), operand, true); - break; - - case Select8: - register_(c, value(c))->accept - (c, mov, memory - (c, operand->base, operand->displacement, - operand->index, operand->scale)); - - register_(c, high(c))->accept - (c, mov, memory - (c, operand->base, operand->displacement + BytesPerWord, - operand->index, operand->scale)); - break; - - default: abort(c); - } } - } break; + break; - case mul: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode2(c, 0x0faf, value(c), operand, operand->selection); - } else { - abort(c); - } - } break; + case mov1ToW: + encode2(c, 0x0fbe, value(c), operand, true); + break; + + case mov2ToW: + encode2(c, 0x0fbf, value(c), operand, true); + break; + + case mov2zToW: + encode2(c, 0x0fb7, value(c), operand, true); + break; + + case mov4To8: + assert(c, BytesPerWord == 8); // todo + + encode(c, 0x63, value(c), operand, true); + break; default: abort(c); } @@ -1572,14 +1475,20 @@ RegisterOperand::accept(Context* c, Operation operation, AbsoluteOperand* operand) { switch (operation) { - case cmp: { + case cmp4: + case cmp8: { + assert(c, BytesPerWord == 8 or operation == cmp4); // todo + RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, ::value(c, operand)); accept(c, cmp, memory(c, tmp, 0, 0, 1)); tmp->release(c); } break; - case mov: { + case mov4: + case mov8: { + assert(c, BytesPerWord == 8 or operation == mov4); // todo + accept(c, mov, ::value(c, operand)); accept(c, mov, memory(c, this, 0, 0, 1)); } break; @@ -1671,7 +1580,10 @@ AddressOperand::apply(Context* c, Operation operation) conditional(c, 0x8e, this); break; - case push: { + case push4: + case push8: { + assert(c, BytesPerWord == 8 or operation == push4); // todo + RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, this); tmp->apply(c, push); @@ -1706,14 +1618,16 @@ ImmediateOperand::apply(Context* c, Operation 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; - case push: { - if (selection == DefaultSelection) { + case push4: + case push8: + if (BytesPerWord == 4 and operation == push8) { + immediate(c, (value >> 32) & 0xFFFFFFFF)->apply(c, push); + immediate(c, (value ) & 0xFFFFFFFF)->apply(c, push); + } else { if (isInt8(value)) { c->code.append(0x6a); c->code.append(value); @@ -1726,13 +1640,8 @@ ImmediateOperand::apply(Context* c, Operation operation) tmp->apply(c, push); tmp->release(c); } - } else { - assert(c, selection == Select8); - - immediate(c, (value >> 32) & 0xFFFFFFFF)->apply(c, push); - immediate(c, (value ) & 0xFFFFFFFF)->apply(c, push); } - } break; + break; default: abort(c); } @@ -1785,23 +1694,16 @@ 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, selection); - } else { - assert(c, selection == Select8); - + case neg4: + case neg8: + if (BytesPerWord == 4 and operation == neg8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -1821,48 +1723,68 @@ MemoryOperand::apply(Context* c, Operation operation) ax->release(c); dx->release(c); + } else { + encode(c, 0xf7, 2, this, true); } break; - case pop: - if (selection == DefaultSelection) { - encode(c, 0x8f, 0, this, false); - } else { - assert(c, selection == Select8); - + case pop4: + case pop8: + if (BytesPerWord == 4 and operation == pop8) { 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); + } else if (BytesPerWord == 8 and operation == pop4) { + abort(c); + } else { + encode(c, 0x8f, 0, this, false); } break; - case push: - if (selection == DefaultSelection) { - encode(c, 0xff, 6, this, false); + case push4: + case push8: + if (BytesPerWord == 4 and operation == push8) { + MemoryOperand* low = memory(c, base, displacement, index, scale); + MemoryOperand* high = memory + (c, base, displacement + BytesPerWord, index, scale); + + high->apply(c, push); + low->apply(c, push); + } else if (BytesPerWord == 8 and operation == push4) { + RegisterOperand* tmp = temporary(c); + tmp->accept(c, mov4, this); + tmp->apply(c, operation); + tmp->release(c); } else { - switch (selection) { - case Select8: { - MemoryOperand* low = memory(c, base, displacement, index, scale); - MemoryOperand* high = memory - (c, base, displacement + BytesPerWord, index, scale); - - high->apply(c, push); - low->apply(c, push); - } break; - - default: { - RegisterOperand* tmp = temporary - (c, selection == Select8 ? Select8 : DefaultSelection); - tmp->accept(c, mov, this); - tmp->apply(c, operation); - tmp->release(c); - } break; - } + encode(c, 0xff, 6, this, false); } break; + + case push1: + case push2: + case push2z: { + RegisterOperand* tmp = temporary(c); + switch (operation) { + case push1: + tmp->accept(c, mov1ToW, this); + break; + + case push2: + tmp->accept(c, mov2ToW, this); + break; + + case push2z: + tmp->accept(c, mov2zToW, this); + break; + + default: abort(c); + } + tmp->apply(c, push); + tmp->release(c); + } break; default: abort(c); } @@ -1873,24 +1795,16 @@ MemoryOperand::accept(Context* c, Operation operation, RegisterOperand* operand) { switch (operation) { - case and_: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x21, operand->value(c), this, operand->selection); - } else { - abort(c); - } - } break; + case and4: + case and8: + assert(c, BytesPerWord == 8 or operation == and4); // todo - case add: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x01, operand->value(c), this, operand->selection); - } else { - assert(c, operand->selection == Select8); + encode(c, 0x21, operand->value(c), this, true); + break; + case add4: + case add8: + if (BytesPerWord == 4 and operation == add8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -1903,30 +1817,31 @@ MemoryOperand::accept(Context* c, Operation operation, ax->release(c); dx->release(c); - } - } break; - - case addc: - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x11, operand->value(c), this, operand->selection); } else { - abort(c); + encode(c, 0x01, operand->value(c), this, true); } break; - case div: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { + case addc: + encode(c, 0x11, operand->value(c), this, true); + break; + + case div4: + case div8: + if (BytesPerWord == 4 and operation == div8) { + operand->apply(c, push8); + memory(c, base, displacement, index, scale)->apply(c, push8); + immediate(c, reinterpret_cast(divideLong))->apply(c, call); + register_(c, rsp)->accept(c, add, immediate(c, 16)); + accept(c, mov8, register_(c, rax, rdx)); + } else { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); ax->accept(c, mov, this); - rex(c, operand->selection); + rex(c); c->code.append(0x99); - rex(c, operand->selection); + rex(c); c->code.append(0xf7); c->code.append(0xf8 | operand->value(c)); @@ -1934,77 +1849,55 @@ MemoryOperand::accept(Context* c, Operation operation, ax->release(c); dx->release(c); - } else { - assert(c, operand->selection == Select8); - - operand->apply(c, push); - memory(c, base, displacement, index, scale, Select8)->apply(c, push); - immediate(c, reinterpret_cast(divideLong))->apply(c, call); - register_(c, rsp)->accept(c, add, immediate(c, 16)); - accept(c, mov, register_(c, rax, rdx, Select8)); } - } break; + break; - case mov: { - if (operand->selection == DefaultSelection) { - encode(c, 0x89, operand->value(c), this, true); + case mov4: + case mov8: + if (BytesPerWord == 4 and operation == mov8) { + memory(c, base, displacement, index, scale)->accept + (c, mov, register_(c, operand->value(c))); + + memory(c, base, displacement + BytesPerWord, index, scale)->accept + (c, mov, register_(c, operand->high(c))); + } else if (BytesPerWord == 8 and operation == mov4) { + encode(c, 0x89, operand->value(c), this, false); } else { - 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); - } - } - break; + encode(c, 0x89, operand->value(c), this, true); + } + break; - case Select2: - case Select2z: - c->code.append(0x66); - encode(c, 0x89, operand->value(c), this, false); - break; - - case Select4: - encode(c, 0x89, operand->value(c), this, false); - break; - - case Select8: - memory(c, base, displacement, index, scale)->accept - (c, mov, register_(c, operand->value(c))); - - memory(c, base, displacement + BytesPerWord, index, scale)->accept - (c, mov, register_(c, operand->high(c))); - break; - - default: abort(c); + case mov1: + 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, mov1, register_(c, rax)); + ax->release(c); + } else { + encode(c, 0x88, operand->value(c), this, false); } } - } break; + break; - case mul: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - RegisterOperand* tmp = temporary(c); + case mov2: + c->code.append(0x66); + encode(c, 0x89, operand->value(c), this, false); + break; - tmp->accept(c, mov, this); - tmp->accept(c, mul, operand); - accept(c, mov, tmp); - - tmp->release(c); - } else { - assert(c, operand->selection == Select8); + case mov4To8: + assert(c, BytesPerWord == 8); + encode(c, 0x89, operand->value(c), this, false); + break; + case mul4: + case mul8: + if (BytesPerWord == 4 and operation == mul8) { RegisterOperand* tmp = temporary(c, rcx); RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -2035,23 +1928,33 @@ MemoryOperand::accept(Context* c, Operation operation, tmp->release(c); ax->release(c); dx->release(c); - } - } break; - - case or_: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x09, operand->value(c), this, operand->selection); } else { - abort(c); - } - } break; + RegisterOperand* tmp = temporary(c); - case rem: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { + tmp->accept(c, mov, this); + tmp->accept(c, mul, operand); + accept(c, mov, tmp); + + tmp->release(c); + } + break; + + case or4: + case or8: + assert(c, BytesPerWord == 8 or operation == or4); // todo + + encode(c, 0x09, operand->value(c), this, true); + break; + + case rem4: + case rem8: + if (BytesPerWord == 4 and operation == rem8) { + operand->apply(c, push8); + memory(c, base, displacement, index, scale)->apply(c, push8); + immediate(c, reinterpret_cast(moduloLong))->apply(c, call); + register_(c, rsp)->accept(c, add, immediate(c, 16)); + accept(c, mov8, register_(c, rax, rdx)); + } else { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); ax->accept(c, mov, this); @@ -2066,64 +1969,42 @@ MemoryOperand::accept(Context* c, Operation operation, ax->release(c); dx->release(c); - } else { - assert(c, operand->selection == Select8); - - operand->apply(c, push); - memory(c, base, displacement, index, scale, Select8)->apply(c, push); - immediate(c, reinterpret_cast(moduloLong))->apply(c, call); - register_(c, rsp)->accept(c, add, immediate(c, 16)); - accept(c, mov, register_(c, rax, rdx, Select8)); } + break; + + case shl4: + case shl8: { + assert(c, BytesPerWord == 8 or operation == shl4); // todo + + RegisterOperand* cx = temporary(c, rcx); + cx->accept(c, mov, operand); + encode(c, 0xd3, 4, this, true); + cx->release(c); } break; - case shl: { - 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); - } + case shr4: + case shr8: { + assert(c, BytesPerWord == 8 or operation == shr4); // todo + + RegisterOperand* cx = temporary(c, rcx); + cx->accept(c, mov, operand); + encode(c, 0xd3, 5, this, true); + cx->release(c); } break; - case shr: { - 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); - } + case ushr4: + case ushr8: { + assert(c, BytesPerWord == 8 or operation == ushr4); // todo + + RegisterOperand* cx = temporary(c, rcx); + cx->accept(c, mov, operand); + encode(c, 0xd3, 7, this, true); + cx->release(c); } break; - case ushr: { - 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 (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x29, operand->value(c), this, operand->selection); - } else { - assert(c, operand->selection == Select8); - + case sub4: + case sub8: + if (BytesPerWord == 4 and operation == sub8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -2136,27 +2017,20 @@ MemoryOperand::accept(Context* c, Operation operation, ax->release(c); dx->release(c); - } - } break; - - case subb: - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x19, operand->value(c), this, operand->selection); } else { - abort(c); + encode(c, 0x29, operand->value(c), this, true); } break; - case xor_: { - if (operand->selection == DefaultSelection - or operand->selection == Select4) - { - encode(c, 0x31, operand->value(c), this, operand->selection); - } else { - abort(c); - } + case subb: + encode(c, 0x19, operand->value(c), this, true); + break; + + case xor4: + case xor8: { + assert(c, BytesPerWord == 8 or operation == xor4); // todo + + encode(c, 0x31, operand->value(c), this, true); } break; default: abort(c); @@ -2167,11 +2041,11 @@ void MemoryOperand::accept(Context* c, Operation operation, ImmediateOperand* operand) { - assert(c, selection == DefaultSelection); - assert(c, operand->selection == DefaultSelection); - switch (operation) { - case add: { + case add4: + case add8: { + assert(c, BytesPerWord == 8 or operation == add4); // todo + unsigned i = (isInt8(operand->value) ? 0x83 : 0x81); encode(c, i, 0, this, true); @@ -2184,8 +2058,10 @@ MemoryOperand::accept(Context* c, Operation operation, } } break; - case mov: { + case mov4: + case mov8: { assert(c, isInt32(operand->value)); // todo + assert(c, BytesPerWord == 8 or operation == mov4); // todo encode(c, 0xc7, 0, this, true); c->code.append4(operand->value); @@ -2211,12 +2087,26 @@ void MemoryOperand::accept(Context* c, Operation operation, MemoryOperand* operand) { - RegisterOperand* tmp = temporary(c); - - tmp->accept(c, mov, operand); - accept(c, operation, tmp); - - tmp->release(c); + switch (operation) { + case mov1ToW: + case mov2ToW: + case mov2zToW: { + RegisterOperand* tmp = temporary(c); + tmp->accept(c, operation, operand); + accept(c, mov, tmp); + tmp->release(c); + } break; + + case mov8: + case and4: { + RegisterOperand* tmp = temporary(c); + tmp->accept(c, mov, operand); + accept(c, operation, tmp); + tmp->release(c); + } break; + + default: abort(c); + } } int @@ -2335,7 +2225,9 @@ class MyCompiler: public Compiler { } virtual Stack* push(Stack* s, unsigned count) { - sub(immediate(&c, count * BytesPerWord), register_(&c, rsp)); + appendOperation + (&c, MyOperand::sub, immediate(&c, count * BytesPerWord), + register_(&c, rsp)); return pushed(s, count); } @@ -2349,8 +2241,29 @@ class MyCompiler: public Compiler { return stack; } - virtual Stack* push(Stack* s, Operand* v) { - return ::push(&c, static_cast(s), static_cast(v)); + virtual Stack* push1(Stack* s, Operand* v) { + return ::push(&c, static_cast(s), MyOperand::push1, + static_cast(v)); + } + + virtual Stack* push2(Stack* s, Operand* v) { + return ::push(&c, static_cast(s), MyOperand::push2, + static_cast(v)); + } + + virtual Stack* push2z(Stack* s, Operand* v) { + return ::push(&c, static_cast(s), MyOperand::push2z, + static_cast(v)); + } + + virtual Stack* push4(Stack* s, Operand* v) { + return ::push(&c, static_cast(s), MyOperand::push4, + static_cast(v)); + } + + virtual Stack* push8(Stack* s, Operand* v) { + return ::push(&c, static_cast(s), MyOperand::push8, + static_cast(v)); } virtual Operand* stack(Stack* s, unsigned index) { @@ -2368,8 +2281,14 @@ class MyCompiler: public Compiler { return ::pop(&c, static_cast(s), count); } - virtual Stack* pop(Stack* s, Operand* dst) { - return ::pop(&c, static_cast(s), static_cast(dst)); + virtual Stack* pop4(Stack* s, Operand* dst) { + return ::pop(&c, static_cast(s), MyOperand::pop4, + static_cast(dst)); + } + + virtual Stack* pop8(Stack* s, Operand* dst) { + return ::pop(&c, static_cast(s), MyOperand::pop8, + static_cast(dst)); } virtual Operand* stack() { @@ -2411,14 +2330,16 @@ class MyCompiler: public Compiler { (Operand* address, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); - unsigned footprint = pushArguments(&c, argumentCount, a); + pushArguments(&c, argumentCount, a); va_end(a); - mov(address, register_(&c, rax)); + appendOperation(&c, MyOperand::mov, address, register_(&c, rax)); call(immediate(&c, c.indirectCaller)); Promise* p = machineIp(); - add(immediate(&c, footprint), register_(&c, rsp)); + appendOperation + (&c, MyOperand::add, immediate(&c, argumentFootprint(argumentCount)), + register_(&c, rsp)); return p; } @@ -2429,7 +2350,7 @@ class MyCompiler: public Compiler { pushArguments(&c, argumentCount, a); va_end(a); - mov(address, register_(&c, rax)); + appendOperation(&c, MyOperand::mov, address, register_(&c, rax)); call(immediate(&c, c.indirectCaller)); } @@ -2438,28 +2359,50 @@ class MyCompiler: public Compiler { (Operand* address, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); - unsigned footprint = pushArguments(&c, argumentCount, a); + pushArguments(&c, argumentCount, a); va_end(a); call(address); Promise* p = machineIp(); - add(immediate(&c, footprint), register_(&c, rsp)); + appendOperation + (&c, MyOperand::add, immediate(&c, argumentFootprint(argumentCount)), + register_(&c, rsp)); return p; } - virtual Operand* result() { - RegisterOperand* r = register_(&c, rax, rdx); + virtual Operand* result4() { + RegisterOperand* r = register_(&c, rax); appendAcquire(&c, r); return r; } - virtual void return_(Operand* v) { - mov(v, register_(&c, rax, rdx)); + virtual Operand* result8() { + if (BytesPerWord == 8) { + return result4(); + } else { + RegisterOperand* r = register_(&c, rax, rdx); + appendAcquire(&c, r); + return r; + } + } + + virtual void return4(Operand* v) { + appendOperation(&c, MyOperand::mov, v, register_(&c, rax)); epilogue(); ret(); } + virtual void return8(Operand* v) { + if (BytesPerWord == 8) { + return4(v); + } else { + appendOperation(&c, MyOperand::mov, v, register_(&c, rax, rdx)); + epilogue(); + ret(); + } + } + virtual void call(Operand* v) { appendOperation(&c, MyOperand::call, v); } @@ -2472,12 +2415,44 @@ class MyCompiler: public Compiler { appendOperation(&c, MyOperand::ret); } - virtual void mov(Operand* src, Operand* dst) { - appendOperation(&c, MyOperand::mov, src, dst); + virtual void mov1(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov1, src, dst); } - virtual void cmp(Operand* subtrahend, Operand* minuend) { - appendOperation(&c, MyOperand::cmp, subtrahend, minuend); + virtual void mov2(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov2, src, dst); + } + + virtual void mov4(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov4, src, dst); + } + + virtual void mov8(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov8, src, dst); + } + + virtual void mov1ToW(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov1ToW, src, dst); + } + + virtual void mov2ToW(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov2ToW, src, dst); + } + + virtual void mov2zToW(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov2zToW, src, dst); + } + + virtual void mov4To8(Operand* src, Operand* dst) { + appendOperation(&c, MyOperand::mov4To8, src, dst); + } + + virtual void cmp4(Operand* subtrahend, Operand* minuend) { + appendOperation(&c, MyOperand::cmp4, subtrahend, minuend); + } + + virtual void cmp8(Operand* subtrahend, Operand* minuend) { + appendOperation(&c, MyOperand::cmp8, subtrahend, minuend); } virtual void jl(Operand* v) { @@ -2508,52 +2483,100 @@ class MyCompiler: public Compiler { appendOperation(&c, MyOperand::jmp, v); } - virtual void add(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::add, v, dst); + virtual void add4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::add4, v, dst); } - virtual void sub(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::sub, v, dst); + virtual void add8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::add8, v, dst); } - virtual void mul(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::mul, v, dst); + virtual void sub4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::sub4, v, dst); } - virtual void div(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::div, v, dst); + virtual void sub8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::sub8, v, dst); } - virtual void rem(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::rem, v, dst); + virtual void mul4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::mul4, v, dst); } - virtual void shl(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::shl, v, dst); + virtual void mul8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::mul8, v, dst); } - virtual void shr(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::shr, v, dst); + virtual void div4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::div4, v, dst); } - virtual void ushr(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::ushr, v, dst); + virtual void div8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::div8, v, dst); } - virtual void and_(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::and_, v, dst); + virtual void rem4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::rem4, v, dst); } - virtual void or_(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::or_, v, dst); + virtual void rem8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::rem8, v, dst); } - virtual void xor_(Operand* v, Operand* dst) { - appendOperation(&c, MyOperand::xor_, v, dst); + virtual void shl4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::shl4, v, dst); } - virtual void neg(Operand* v) { - appendOperation(&c, MyOperand::neg, v); + virtual void shl8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::shl8, v, dst); + } + + virtual void shr4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::shr4, v, dst); + } + + virtual void shr8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::shr8, v, dst); + } + + virtual void ushr4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::ushr4, v, dst); + } + + virtual void ushr8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::ushr8, v, dst); + } + + virtual void and4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::and4, v, dst); + } + + virtual void and8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::and8, v, dst); + } + + virtual void or4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::or4, v, dst); + } + + virtual void or8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::or8, v, dst); + } + + virtual void xor4(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::xor4, v, dst); + } + + virtual void xor8(Operand* v, Operand* dst) { + appendOperation(&c, MyOperand::xor8, v, dst); + } + + virtual void neg4(Operand* v) { + appendOperation(&c, MyOperand::neg4, v); + } + + virtual void neg8(Operand* v) { + appendOperation(&c, MyOperand::neg8, v); } virtual Operand* memory(Operand* base, int displacement, @@ -2563,30 +2586,6 @@ class MyCompiler: public Compiler { static_cast(index), scale); } - virtual Operand* select1(Operand* v) { - return static_cast(v)->select(&c, Select1); - } - - virtual Operand* select2(Operand* v) { - return static_cast(v)->select(&c, Select2); - } - - virtual Operand* select2z(Operand* v) { - return static_cast(v)->select(&c, Select2z); - } - - virtual Operand* select4(Operand* v) { - return static_cast(v)->select(&c, Select4); - } - - virtual Operand* select8(Operand* v) { - return static_cast(v)->select(&c, Select8); - } - - virtual Operand* select8From4(Operand* v) { - return static_cast(v)->select(&c, Select8From4); - } - virtual void prologue() { appendOperation(&c, MyOperand::push, register_(&c, rbp)); appendOperation diff --git a/src/compiler.h b/src/compiler.h index ba7be6dad1..1343674e97 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -34,19 +34,13 @@ class Compiler { virtual Operand* memory(Operand* base, int displacement = 0, Operand* index = 0, unsigned scale = 1) = 0; - 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* select8From4(Operand*) = 0; - virtual Operand* stack() = 0; virtual Operand* base() = 0; virtual Operand* thread() = 0; virtual Operand* indirectTarget() = 0; virtual Operand* temporary() = 0; - virtual Operand* result() = 0; + virtual Operand* result4() = 0; + virtual Operand* result8() = 0; virtual void release(Operand*) = 0; virtual Operand* label() = 0; @@ -61,18 +55,32 @@ class Compiler { virtual void call(Operand*) = 0; virtual void alignedCall(Operand*) = 0; - virtual void return_(Operand*) = 0; + virtual void return4(Operand*) = 0; + virtual void return8(Operand*) = 0; virtual void ret() = 0; virtual Stack* push(Stack*, unsigned count) = 0; virtual Stack* pushed(Stack*, unsigned count) = 0; - virtual Stack* push(Stack*, Operand*) = 0; virtual Stack* pop(Stack*, unsigned count) = 0; - virtual Stack* pop(Stack*, Operand*) = 0; virtual Operand* stack(Stack*, unsigned) = 0; - virtual void mov(Operand* src, Operand* dst) = 0; - virtual void cmp(Operand* subtrahend, Operand* minuend) = 0; + virtual Stack* push1(Stack*, Operand*) = 0; + virtual Stack* push2(Stack*, Operand*) = 0; + virtual Stack* push2z(Stack*, Operand*) = 0; + virtual Stack* push4(Stack*, Operand*) = 0; + virtual Stack* push8(Stack*, Operand*) = 0; + virtual Stack* pop4(Stack*, Operand*) = 0; + virtual Stack* pop8(Stack*, Operand*) = 0; + virtual void mov1(Operand* src, Operand* dst) = 0; + virtual void mov2(Operand* src, Operand* dst) = 0; + virtual void mov4(Operand* src, Operand* dst) = 0; + virtual void mov8(Operand* src, Operand* dst) = 0; + virtual void mov1ToW(Operand* src, Operand* dst) = 0; + virtual void mov2ToW(Operand* src, Operand* dst) = 0; + virtual void mov2zToW(Operand* src, Operand* dst) = 0; + virtual void mov4To8(Operand* src, Operand* dst) = 0; + virtual void cmp4(Operand* subtrahend, Operand* minuend) = 0; + virtual void cmp8(Operand* subtrahend, Operand* minuend) = 0; virtual void jl(Operand*) = 0; virtual void jg(Operand*) = 0; virtual void jle(Operand*) = 0; @@ -80,18 +88,30 @@ class Compiler { virtual void je(Operand*) = 0; virtual void jne(Operand*) = 0; virtual void jmp(Operand*) = 0; - virtual void add(Operand* v, Operand* dst) = 0; - virtual void sub(Operand* v, Operand* dst) = 0; - virtual void mul(Operand* v, Operand* dst) = 0; - virtual void div(Operand* v, Operand* dst) = 0; - virtual void rem(Operand* v, Operand* dst) = 0; - virtual void shl(Operand* v, Operand* dst) = 0; - virtual void shr(Operand* v, Operand* dst) = 0; - virtual void ushr(Operand* v, Operand* dst) = 0; - virtual void and_(Operand* v, Operand* dst) = 0; - virtual void or_(Operand* v, Operand* dst) = 0; - virtual void xor_(Operand* v, Operand* dst) = 0; - virtual void neg(Operand*) = 0; + virtual void add4(Operand* v, Operand* dst) = 0; + virtual void add8(Operand* v, Operand* dst) = 0; + virtual void sub4(Operand* v, Operand* dst) = 0; + virtual void sub8(Operand* v, Operand* dst) = 0; + virtual void mul4(Operand* v, Operand* dst) = 0; + virtual void mul8(Operand* v, Operand* dst) = 0; + virtual void div4(Operand* v, Operand* dst) = 0; + virtual void div8(Operand* v, Operand* dst) = 0; + virtual void rem4(Operand* v, Operand* dst) = 0; + virtual void rem8(Operand* v, Operand* dst) = 0; + virtual void shl4(Operand* v, Operand* dst) = 0; + virtual void shl8(Operand* v, Operand* dst) = 0; + virtual void shr4(Operand* v, Operand* dst) = 0; + virtual void shr8(Operand* v, Operand* dst) = 0; + virtual void ushr4(Operand* v, Operand* dst) = 0; + virtual void ushr8(Operand* v, Operand* dst) = 0; + virtual void and4(Operand* v, Operand* dst) = 0; + virtual void and8(Operand* v, Operand* dst) = 0; + virtual void or4(Operand* v, Operand* dst) = 0; + virtual void or8(Operand* v, Operand* dst) = 0; + virtual void xor4(Operand* v, Operand* dst) = 0; + virtual void xor8(Operand* v, Operand* dst) = 0; + virtual void neg4(Operand*) = 0; + virtual void neg8(Operand*) = 0; virtual void prologue() = 0; virtual void reserve(unsigned size) = 0;