added floating point support, instrinsics support

This commit is contained in:
Josh warner 2009-08-06 10:01:57 -06:00
parent c3a389429e
commit 7483fa154d

View File

@ -27,7 +27,7 @@ vmCall();
namespace { namespace {
const bool DebugCompile = false; const bool DebugCompile = true;
const bool DebugNatives = false; const bool DebugNatives = false;
const bool DebugCallTable = false; const bool DebugCallTable = false;
const bool DebugMethodTree = false; const bool DebugMethodTree = false;
@ -562,20 +562,86 @@ class Context {
virtual intptr_t getThunk(UnaryOperation, unsigned) { virtual intptr_t getThunk(UnaryOperation, unsigned) {
abort(t); abort(t);
} }
virtual intptr_t getThunk(BinaryOperation op, unsigned size, unsigned resultSize) {
switch(op) {
case FloatNegate:
if (size == 4) {
return ::getThunk(t, negateFloatThunk);
} else {
return ::getThunk(t, negateDoubleThunk);
}
case Float2Float:
if (size == 4 && resultSize == 8) {
return ::getThunk(t, floatToDoubleThunk);
} else if(size == 8 && resultSize == 4) {
return ::getThunk(t, doubleToFloatThunk);
}
case Float2Int:
if (size == 4 && resultSize == 4) {
return ::getThunk(t, floatToIntThunk);
} else if(size == 4 && resultSize == 8) {
return ::getThunk(t, floatToLongThunk);
} else if(size == 8 && resultSize == 4) {
return ::getThunk(t, doubleToIntThunk);
} else if(size == 8 && resultSize == 8) {
return ::getThunk(t, doubleToLongThunk);
}
case Int2Float:
if (size == 4 && resultSize == 4) {
return ::getThunk(t, intToFloatThunk);
} else if(size == 4 && resultSize == 8) {
return ::getThunk(t, intToDoubleThunk);
} else if(size == 8 && resultSize == 4) {
return ::getThunk(t, longToFloatThunk);
} else if(size == 8 && resultSize == 8) {
return ::getThunk(t, longToDoubleThunk);
}
default: break;
}
abort(t);
}
virtual intptr_t getThunk(TernaryOperation op, unsigned size) { virtual intptr_t getThunk(TernaryOperation op, unsigned size UNUSED, unsigned resultSize) {
switch (op) { switch (op) {
case Divide: case Divide:
if (size == 8) { if (resultSize == 8) {
return ::getThunk(t, divideLongThunk); return ::getThunk(t, divideLongThunk);
} }
break; break;
case Remainder: case Remainder:
if (size == 8) { if (resultSize == 8) {
return ::getThunk(t, moduloLongThunk); return ::getThunk(t, moduloLongThunk);
} }
break; break;
case FloatAdd:
if(resultSize == 4) {
return ::getThunk(t, addFloatThunk);
} else {
return ::getThunk(t, addDoubleThunk);
}
case FloatSubtract:
if(resultSize == 4) {
return ::getThunk(t, subtractFloatThunk);
} else {
return ::getThunk(t, subtractDoubleThunk);
}
case FloatMultiply:
if(resultSize == 4) {
return ::getThunk(t, multiplyFloatThunk);
} else {
return ::getThunk(t, multiplyDoubleThunk);
}
case FloatDivide:
if(resultSize == 4) {
return ::getThunk(t, divideFloatThunk);
} else {
return ::getThunk(t, divideDoubleThunk);
}
default: break; default: break;
} }
@ -1008,7 +1074,7 @@ class Frame {
poppedLong(); poppedLong();
return popLongQuiet(); return popLongQuiet();
} }
Compiler::Operand* popObject() { Compiler::Operand* popObject() {
poppedObject(); poppedObject();
return popQuiet(1); return popQuiet(1);
@ -2071,6 +2137,22 @@ saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip)
initialFrame->c->restoreState(state); initialFrame->c->restoreState(state);
} }
bool
isCJump(unsigned instruction)
{
switch(instruction) {
case ifeq:
case ifne:
case ifgt:
case ifge:
case iflt:
case ifle:
return true;
default:
return false;
}
}
void void
compile(MyThread* t, Frame* initialFrame, unsigned ip, compile(MyThread* t, Frame* initialFrame, unsigned ip,
int exceptionHandlerStart) int exceptionHandlerStart)
@ -2084,6 +2166,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object code = methodCode(t, context->method); object code = methodCode(t, context->method);
PROTECT(t, code); PROTECT(t, code);
int lastFcmpl = 1, lastFcmpg = 1;
while (ip < codeLength(t, code)) { while (ip < codeLength(t, code)) {
if (context->visitTable[ip] ++) { if (context->visitTable[ip] ++) {
@ -2108,6 +2192,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
0, 0,
1, c->thread()); 1, c->thread());
} }
++ lastFcmpl;
++ lastFcmpg;
// fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map)); // fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map));
@ -2341,63 +2428,56 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
} break; } break;
case d2f: { case d2f: {
frame->pushInt frame->pushInt(c->f2f(8, 4, frame->popLong()));
(c->call
(c->constant(getThunk(t, doubleToFloatThunk)),
0, 0, 4, 2,
static_cast<Compiler::Operand*>(0), frame->popLong()));
} break; } break;
case d2i: { case d2i: {
frame->pushInt frame->pushInt(c->f2i(8, 4, frame->popLong()));
(c->call
(c->constant(getThunk(t, doubleToIntThunk)),
0, 0, 4, 2,
static_cast<Compiler::Operand*>(0), frame->popLong()));
} break; } break;
case d2l: { case d2l: {
frame->pushLong frame->pushLong(c->f2i(8, 8, frame->popLong()));
(c->call
(c->constant(getThunk(t, doubleToLongThunk)),
0, 0, 8, 2,
static_cast<Compiler::Operand*>(0), frame->popLong()));
} break; } break;
case dadd: { case dadd: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushLong frame->pushLong(c->fadd(8, a, b));
(c->call
(c->constant(getThunk(t, addDoubleThunk)),
0, 0, 8, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
} break; } break;
case dcmpg: { case dcmpg: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushInt if(t->arch->supportsFloatCompare(8) && isCJump(codeBody(t, code, ip))) {
(c->call c->fcmp(8, a, b);
(c->constant(getThunk(t, compareDoublesGThunk)), lastFcmpg = 0;
0, 0, 4, 4, } else {
static_cast<Compiler::Operand*>(0), a, frame->pushInt
static_cast<Compiler::Operand*>(0), b)); (c->call
(c->constant(getThunk(t, compareDoublesGThunk)),
0, 0, 4, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
}
} break; } break;
case dcmpl: { case dcmpl: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushInt if(t->arch->supportsFloatCompare(8) && isCJump(codeBody(t, code, ip))) {
(c->call c->fcmp(8, a, b);
(c->constant(getThunk(t, compareDoublesLThunk)), lastFcmpl = 0;
0, 0, 4, 4, } else {
static_cast<Compiler::Operand*>(0), a, frame->pushInt
static_cast<Compiler::Operand*>(0), b)); (c->call
(c->constant(getThunk(t, compareDoublesLThunk)),
0, 0, 4, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
}
} break; } break;
case dconst_0: case dconst_0:
@ -2412,56 +2492,32 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushLong frame->pushLong(c->fdiv(8, a, b));
(c->call
(c->constant(getThunk(t, divideDoubleThunk)),
0, 0, 8, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
} break; } break;
case dmul: { case dmul: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushLong frame->pushLong(c->fmul(8, a, b));
(c->call
(c->constant(getThunk(t, multiplyDoubleThunk)),
0, 0, 8, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
} break; } break;
case dneg: { case dneg: {
frame->pushLong frame->pushLong(c->fneg(8, frame->popLong()));
(c->call
(c->constant(getThunk(t, negateDoubleThunk)),
0, 0, 8, 2,
static_cast<Compiler::Operand*>(0), frame->popLong()));
} break; } break;
case vm::drem: { case vm::drem: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushLong frame->pushLong(c->frem(8, a, b));
(c->call
(c->constant(getThunk(t, moduloDoubleThunk)),
0, 0, 8, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
} break; } break;
case dsub: { case dsub: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
frame->pushLong frame->pushLong(c->fsub(8, a, b));
(c->call
(c->constant(getThunk(t, subtractDoubleThunk)),
0, 0, 8, 4,
static_cast<Compiler::Operand*>(0), a,
static_cast<Compiler::Operand*>(0), b));
} break; } break;
case dup: case dup:
@ -2489,54 +2545,52 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
break; break;
case f2d: { case f2d: {
frame->pushLong frame->pushLong(c->f2f(4, 8, frame->popInt()));
(c->call
(c->constant(getThunk(t, floatToDoubleThunk)),
0, 0, 8, 1, frame->popInt()));
} break; } break;
case f2i: { case f2i: {
frame->pushInt frame->pushInt(c->f2i(4, 4, frame->popInt()));
(c->call
(c->constant(getThunk(t, floatToIntThunk)),
0, 0, 4, 1, frame->popInt()));
} break; } break;
case f2l: { case f2l: {
frame->pushLong frame->pushLong(c->f2i(4, 8, frame->popInt()));
(c->call
(c->constant(getThunk(t, floatToLongThunk)),
0, 0, 8, 1, frame->popInt()));
} break; } break;
case fadd: { case fadd: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt frame->pushInt(c->fadd(4, a, b));
(c->call
(c->constant(getThunk(t, addFloatThunk)),
0, 0, 4, 2, a, b));
} break; } break;
case fcmpg: { case fcmpg: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt if(t->arch->supportsFloatCompare(4) && isCJump(codeBody(t, code, ip))) {
(c->call c->fcmp(4, a, b);
(c->constant(getThunk(t, compareFloatsGThunk)), lastFcmpg = 0;
0, 0, 4, 2, a, b)); } else {
frame->pushInt
(c->call
(c->constant(getThunk(t, compareFloatsGThunk)),
0, 0, 4, 2, a, b));
}
} break; } break;
case fcmpl: { case fcmpl: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt if(t->arch->supportsFloatCompare(4) && isCJump(codeBody(t, code, ip))) {
(c->call c->fcmp(4, a, b);
(c->constant(getThunk(t, compareFloatsLThunk)), lastFcmpl = 0;
0, 0, 4, 2, a, b)); } else {
frame->pushInt
(c->call
(c->constant(getThunk(t, compareFloatsLThunk)),
0, 0, 4, 2, a, b));
}
} break; } break;
case fconst_0: case fconst_0:
@ -2555,47 +2609,32 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt frame->pushInt(c->fdiv(4, a, b));
(c->call
(c->constant(getThunk(t, divideFloatThunk)),
0, 0, 4, 2, a, b));
} break; } break;
case fmul: { case fmul: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt frame->pushInt(c->fmul(4, a, b));
(c->call
(c->constant(getThunk(t, multiplyFloatThunk)),
0, 0, 4, 2, a, b));
} break; } break;
case fneg: { case fneg: {
frame->pushInt frame->pushInt(c->fneg(4, frame->popInt()));
(c->call
(c->constant(getThunk(t, negateFloatThunk)),
0, 0, 4, 1, frame->popInt()));
} break; } break;
case vm::frem: { case vm::frem: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt frame->pushInt(c->frem(4, a, b));
(c->call
(c->constant(getThunk(t, moduloFloatThunk)),
0, 0, 4, 2, a, b));
} break; } break;
case fsub: { case fsub: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
frame->pushInt frame->pushInt(c->fsub(4, a, b));
(c->call
(c->constant(getThunk(t, subtractFloatThunk)),
0, 0, 4, 2, a, b));
} break; } break;
case getfield: case getfield:
@ -2731,17 +2770,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
} break; } break;
case i2d: { case i2d: {
frame->pushLong frame->pushLong(c->i2f(4, 8, frame->popInt()));
(c->call
(c->constant(getThunk(t, intToDoubleThunk)),
0, 0, 8, 1, frame->popInt()));
} break; } break;
case i2f: { case i2f: {
frame->pushInt frame->pushInt(c->i2f(4, 4, frame->popInt()));
(c->call
(c->constant(getThunk(t, intToFloatThunk)),
0, 0, 4, 1, frame->popInt()));
} break; } break;
case i2l: case i2l:
@ -2869,27 +2902,48 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
uint32_t newIp = (ip - 3) + offset; uint32_t newIp = (ip - 3) + offset;
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
Compiler::Operand* a = frame->popInt();
Compiler::Operand* target = frame->machineIp(newIp); Compiler::Operand* target = frame->machineIp(newIp);
Compiler::Operand* cont = frame->machineIp(ip);
c->cmp(4, c->constant(0), a); if(lastFcmpl != 1 && lastFcmpg != 1) {
Compiler::Operand* a = frame->popInt();
c->cmp(4, c->constant(0), a);
}
switch (instruction) { switch (instruction) {
case ifeq: case ifeq:
if(lastFcmpl == 1 || lastFcmpg == 1) {
c->juo(cont);
}
c->je(target); c->je(target);
break; break;
case ifne: case ifne:
if(lastFcmpl == 1 || lastFcmpg == 1) {
c->juo(cont);
}
c->jne(target); c->jne(target);
break; break;
case ifgt: case ifgt:
if(lastFcmpl == 1) {
c->juo(cont);
}
c->jg(target); c->jg(target);
break; break;
case ifge: case ifge:
if(lastFcmpl == 1) {
c->juo(cont);
}
c->jge(target); c->jge(target);
break; break;
case iflt: case iflt:
if(lastFcmpg == 1) {
c->juo(cont);
}
c->jl(target); c->jl(target);
break; break;
case ifle: case ifle:
if(lastFcmpg == 1) {
c->juo(cont);
}
c->jle(target); c->jle(target);
break; break;
} }
@ -3033,8 +3087,40 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
assert(t, methodFlags(t, target) & ACC_STATIC); assert(t, methodFlags(t, target) & ACC_STATIC);
int params = methodParameterCount(t, target);
compileDirectInvoke(t, frame, target); if(params == 1) {//TODO: Get number of method params
BinaryOperation op = t->arch->hasBinaryIntrinsic(t, target);
if(op != NoBinaryOperation) {
printf("Could use binary intrinsic %i.\n", op);
int opSize = methodParameterFootprint(t, target) * BytesPerWord;
int resSize = resultSize(t, methodReturnCode(t, target));
Compiler::Operand* param;
if(opSize == 4) {
param = frame->popInt();
} else {
param = frame->popLong();
}
if(resSize == 4) {
frame->pushInt(c->operation(op, opSize, resSize, param));
} else {
frame->pushLong(c->operation(op, opSize, resSize, param));
}
} else {
compileDirectInvoke(t, frame, target);
}
} else if(params == 2) { //TODO: Get number of method params
TernaryOperation op = t->arch->hasTernaryIntrinsic(t, target);
if(op != NoTernaryOperation) {
printf("Could use ternary intrinsic %i.\n", op);
//int aSize, bSize;
//int resSize = resultSize(t, methodReturnCode(t, target));
compileDirectInvoke(t, frame, target); //TODO: use intrinsic
} else {
compileDirectInvoke(t, frame, target);
}
} else {
compileDirectInvoke(t, frame, target);
}
} break; } break;
case invokevirtual: { case invokevirtual: {
@ -3187,19 +3273,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
} break; } break;
case l2d: { case l2d: {
frame->pushLong frame->pushLong(c->i2f(8, 8, frame->popLong()));
(c->call
(c->constant(getThunk(t, longToDoubleThunk)),
0, 0, 8, 2,
static_cast<Compiler::Operand*>(0), frame->popLong()));
} break; } break;
case l2f: { case l2f: {
frame->pushInt frame->pushInt(c->i2f(8, 4, frame->popLong()));
(c->call
(c->constant(getThunk(t, longToFloatThunk)),
0, 0, 4, 2,
static_cast<Compiler::Operand*>(0), frame->popLong()));
} break; } break;
case l2i: case l2i:
@ -4095,7 +4173,6 @@ clearBit(MyThread* t, object map, unsigned count, unsigned size, unsigned i,
intArrayBody(t, map, count + (index / 32)) intArrayBody(t, map, count + (index / 32))
&= ~(static_cast<int32_t>(1) << (index % 32)); &= ~(static_cast<int32_t>(1) << (index % 32));
} }
uint8_t* uint8_t*
finish(MyThread* t, Allocator* allocator, Context* context) finish(MyThread* t, Allocator* allocator, Context* context)
{ {
@ -4260,6 +4337,7 @@ finish(MyThread* t, Allocator* allocator, Context* context)
"printStackTrace") == 0) "printStackTrace") == 0)
{ {
trap(); trap();
printf("Address: %p\n", ::vmAddressFromLine(t, (object)(context->method), 1176));
} }
syncInstructionCache(start, codeSize); syncInstructionCache(start, codeSize);