mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
snapshot
This commit is contained in:
parent
23197da679
commit
609a1a9633
@ -38,22 +38,11 @@ enum UnaryOperation {
|
|||||||
Jump,
|
Jump,
|
||||||
LongJump,
|
LongJump,
|
||||||
AlignedJump,
|
AlignedJump,
|
||||||
JumpIfLess,
|
|
||||||
JumpIfGreater,
|
NoUnaryOperation = -1
|
||||||
JumpIfLessOrEqual,
|
|
||||||
JumpIfGreaterOrEqual,
|
|
||||||
JumpIfEqual,
|
|
||||||
JumpIfNotEqual,
|
|
||||||
JumpIfFloatUnordered,
|
|
||||||
JumpIfFloatLess,
|
|
||||||
JumpIfFloatGreater,
|
|
||||||
JumpIfFloatLessOrEqual,
|
|
||||||
JumpIfFloatGreaterOrEqual,
|
|
||||||
JumpIfFloatEqual,
|
|
||||||
JumpIfFloatNotEqual,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned UnaryOperationCount = JumpIfNotEqual + 1;
|
const unsigned UnaryOperationCount = AlignedJump + 1;
|
||||||
|
|
||||||
enum BinaryOperation {
|
enum BinaryOperation {
|
||||||
Move,
|
Move,
|
||||||
@ -62,15 +51,11 @@ enum BinaryOperation {
|
|||||||
MoveZ,
|
MoveZ,
|
||||||
Compare,
|
Compare,
|
||||||
Negate,
|
Negate,
|
||||||
|
|
||||||
//extensions:
|
|
||||||
FloatNegate,
|
FloatNegate,
|
||||||
FloatCompare,
|
FloatCompare,
|
||||||
Float2Float,
|
Float2Float,
|
||||||
Float2Int,
|
Float2Int,
|
||||||
Int2Float,
|
Int2Float,
|
||||||
|
|
||||||
//intrinsic functions:
|
|
||||||
FloatSqrt,
|
FloatSqrt,
|
||||||
FloatAbs,
|
FloatAbs,
|
||||||
Abs,
|
Abs,
|
||||||
@ -81,7 +66,6 @@ enum BinaryOperation {
|
|||||||
const unsigned BinaryOperationCount = Abs + 1;
|
const unsigned BinaryOperationCount = Abs + 1;
|
||||||
|
|
||||||
enum TernaryOperation {
|
enum TernaryOperation {
|
||||||
LongCompare,
|
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
Multiply,
|
Multiply,
|
||||||
@ -93,22 +77,35 @@ enum TernaryOperation {
|
|||||||
And,
|
And,
|
||||||
Or,
|
Or,
|
||||||
Xor,
|
Xor,
|
||||||
|
|
||||||
//extensions:
|
|
||||||
FloatAdd,
|
FloatAdd,
|
||||||
FloatSubtract,
|
FloatSubtract,
|
||||||
FloatMultiply,
|
FloatMultiply,
|
||||||
FloatDivide,
|
FloatDivide,
|
||||||
FloatRemainder,
|
FloatRemainder,
|
||||||
|
|
||||||
//intrinsic functions:
|
|
||||||
FloatMax,
|
FloatMax,
|
||||||
FloatMin,
|
FloatMin,
|
||||||
|
JumpIfLess,
|
||||||
|
JumpIfGreater,
|
||||||
|
JumpIfLessOrEqual,
|
||||||
|
JumpIfGreaterOrEqual,
|
||||||
|
JumpIfEqual,
|
||||||
|
JumpIfNotEqual,
|
||||||
|
JumpIfFloatEqual,
|
||||||
|
JumpIfFloatNotEqual,
|
||||||
|
JumpIfFloatLess,
|
||||||
|
JumpIfFloatGreater,
|
||||||
|
JumpIfFloatLessOrEqual,
|
||||||
|
JumpIfFloatGreaterOrEqual,
|
||||||
|
JumpIfFloatLessOrUnordered,
|
||||||
|
JumpIfFloatGreaterOrUnordered,
|
||||||
|
JumpIfFloatLessOrEqualOrUnordered,
|
||||||
|
JumpIfFloatGreaterOrEqualOrUnordered,
|
||||||
|
|
||||||
NoTernaryOperation = -1
|
NoTernaryOperation = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned TernaryOperationCount = FloatMin + 1;
|
const unsigned TernaryOperationCount
|
||||||
|
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
|
||||||
|
|
||||||
enum OperandType {
|
enum OperandType {
|
||||||
ConstantOperand,
|
ConstantOperand,
|
||||||
@ -315,8 +312,6 @@ class Assembler {
|
|||||||
|
|
||||||
virtual unsigned registerSize(ValueType type) = 0;
|
virtual unsigned registerSize(ValueType type) = 0;
|
||||||
|
|
||||||
virtual bool supportsFloatCompare(unsigned size) = 0;
|
|
||||||
|
|
||||||
virtual bool alwaysCondensed(BinaryOperation op) = 0;
|
virtual bool alwaysCondensed(BinaryOperation op) = 0;
|
||||||
virtual bool alwaysCondensed(TernaryOperation op) = 0;
|
virtual bool alwaysCondensed(TernaryOperation op) = 0;
|
||||||
|
|
||||||
|
250
src/compile.cpp
250
src/compile.cpp
@ -1971,6 +1971,18 @@ compareFloatsL(uint32_t bi, uint32_t ai)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
compareLongs(uint64_t b, uint64_t a)
|
||||||
|
{
|
||||||
|
if (a < b) {
|
||||||
|
return -1;
|
||||||
|
} else if (a > b) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
addDouble(uint64_t b, uint64_t a)
|
addDouble(uint64_t b, uint64_t a)
|
||||||
{
|
{
|
||||||
@ -2677,17 +2689,111 @@ saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isCJump(unsigned instruction)
|
integerBranch(Frame* frame, object code, unsigned& ip, unsigned size,
|
||||||
|
Compiler::Operand* a, Compiler::Operand* b)
|
||||||
{
|
{
|
||||||
switch(instruction) {
|
if (ip + 3 > codeLength(t, code)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler* c = frame->c;
|
||||||
|
unsigned instruction = codeBody(t, code, ip++);
|
||||||
|
uint32_t offset = codeReadInt16(t, code, ip);
|
||||||
|
uint32_t newIp = (ip - 3) + offset;
|
||||||
|
assert(t, newIp < codeLength(t, code));
|
||||||
|
|
||||||
|
Compiler::Operand* target = frame->machineIp(newIp);
|
||||||
|
|
||||||
|
switch (instruction) {
|
||||||
case ifeq:
|
case ifeq:
|
||||||
case ifne:
|
c->jumpIfEqual(size, a, b, target);
|
||||||
case ifgt:
|
|
||||||
case ifge:
|
|
||||||
case iflt:
|
|
||||||
case ifle:
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case ifne:
|
||||||
|
c->jumpIfNotEqual(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifgt:
|
||||||
|
c->jumpIfGreater(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifge:
|
||||||
|
c->jumpIfGreaterOrEqual(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case iflt:
|
||||||
|
c->jumpIfLessOrUnordered(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifle:
|
||||||
|
c->jumpIfLessOrEqualOrUnordered(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
ip -= 3;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
floatBranch(Frame* frame, object code, unsigned& ip, unsigned size,
|
||||||
|
bool lessIfUnordered, Compiler::Operand* a, Compiler::Operand* b)
|
||||||
|
{
|
||||||
|
if (ip + 3 > codeLength(t, code)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler* c = frame->c;
|
||||||
|
unsigned instruction = codeBody(t, code, ip++);
|
||||||
|
uint32_t offset = codeReadInt16(t, code, ip);
|
||||||
|
uint32_t newIp = (ip - 3) + offset;
|
||||||
|
assert(t, newIp < codeLength(t, code));
|
||||||
|
|
||||||
|
Compiler::Operand* target = frame->machineIp(newIp);
|
||||||
|
|
||||||
|
switch (instruction) {
|
||||||
|
case ifeq:
|
||||||
|
c->jumpIfFloatEqual(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifne:
|
||||||
|
c->jumpIfFloatNotEqual(size, a, b, target);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifgt:
|
||||||
|
if (lessIfUnordered) {
|
||||||
|
c->jumpIfFloatGreater(size, a, b, target);
|
||||||
|
} else {
|
||||||
|
c->jumpIfFloatGreaterOrUnordered(size, a, b, target);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifge:
|
||||||
|
if (lessIfUnordered) {
|
||||||
|
c->jumpIfFloatGreaterOrEqual(size, a, b, target);
|
||||||
|
} else {
|
||||||
|
c->jumpIfFloatGreaterOrEqualOrUnordered(size, a, b, target);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case iflt:
|
||||||
|
if (lessIfUnordered) {
|
||||||
|
c->jumpIfFloatLessOrUnordered(size, a, b, target);
|
||||||
|
} else {
|
||||||
|
c->jumpIfFloatLess(size, a, b, target);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ifle:
|
||||||
|
if (lessIfUnordered) {
|
||||||
|
c->jumpIfFloatLessOrEqualOrUnordered(size, a, b, target);
|
||||||
|
} else {
|
||||||
|
c->jumpIfFloatLessOrEqual(size, a, b, target);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ip -= 3;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2706,8 +2812,6 @@ 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] ++) {
|
||||||
// we've already visited this part of the code
|
// we've already visited this part of the code
|
||||||
@ -2733,9 +2837,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
1, c->register_(t->arch->thread()));
|
1, c->register_(t->arch->thread()));
|
||||||
}
|
}
|
||||||
|
|
||||||
++ lastFcmpl;
|
|
||||||
++ lastFcmpg;
|
|
||||||
|
|
||||||
// fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map));
|
// fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map));
|
||||||
|
|
||||||
unsigned instruction = codeBody(t, code, ip++);
|
unsigned instruction = codeBody(t, code, ip++);
|
||||||
@ -3043,10 +3144,7 @@ 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();
|
||||||
|
|
||||||
if(t->arch->supportsFloatCompare(8) and isCJump(codeBody(t, code, ip))) {
|
if (not floatBranch(frame, ip, 8, false, a, b)) {
|
||||||
c->fcmp(8, a, b);
|
|
||||||
lastFcmpg = 0;
|
|
||||||
} else {
|
|
||||||
frame->pushInt
|
frame->pushInt
|
||||||
(c->call
|
(c->call
|
||||||
(c->constant
|
(c->constant
|
||||||
@ -3061,10 +3159,7 @@ 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();
|
||||||
|
|
||||||
if(t->arch->supportsFloatCompare(8) and isCJump(codeBody(t, code, ip))) {
|
if (not floatBranch(frame, ip, 8, true, a, b)) {
|
||||||
c->fcmp(8, a, b);
|
|
||||||
lastFcmpl = 0;
|
|
||||||
} else {
|
|
||||||
frame->pushInt
|
frame->pushInt
|
||||||
(c->call
|
(c->call
|
||||||
(c->constant
|
(c->constant
|
||||||
@ -3162,10 +3257,7 @@ 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();
|
||||||
|
|
||||||
if(t->arch->supportsFloatCompare(4) and isCJump(codeBody(t, code, ip))) {
|
if (not floatBranch(frame, ip, 4, false, a, b)) {
|
||||||
c->fcmp(4, a, b);
|
|
||||||
lastFcmpg = 0;
|
|
||||||
} else {
|
|
||||||
frame->pushInt
|
frame->pushInt
|
||||||
(c->call
|
(c->call
|
||||||
(c->constant
|
(c->constant
|
||||||
@ -3178,10 +3270,7 @@ 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();
|
||||||
|
|
||||||
if(t->arch->supportsFloatCompare(4) and isCJump(codeBody(t, code, ip))) {
|
if (not floatBranch(frame, ip, 4, true, a, b)) {
|
||||||
c->fcmp(4, a, b);
|
|
||||||
lastFcmpl = 0;
|
|
||||||
} else {
|
|
||||||
frame->pushInt
|
frame->pushInt
|
||||||
(c->call
|
(c->call
|
||||||
(c->constant
|
(c->constant
|
||||||
@ -3473,11 +3562,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
Compiler::Operand* b = frame->popObject();
|
Compiler::Operand* b = frame->popObject();
|
||||||
Compiler::Operand* target = frame->machineIp(newIp);
|
Compiler::Operand* target = frame->machineIp(newIp);
|
||||||
|
|
||||||
c->cmp(BytesPerWord, a, b);
|
|
||||||
if (instruction == if_acmpeq) {
|
if (instruction == if_acmpeq) {
|
||||||
c->je(target);
|
c->jumpIfEqual(BytesPerWord, a, btarget);
|
||||||
} else {
|
} else {
|
||||||
c->jne(target);
|
c->jumpIfNotEqual(BytesPerWord, a, btarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, newIp);
|
saveStateAndCompile(t, frame, newIp);
|
||||||
@ -3498,26 +3586,27 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
Compiler::Operand* b = frame->popInt();
|
Compiler::Operand* b = frame->popInt();
|
||||||
Compiler::Operand* target = frame->machineIp(newIp);
|
Compiler::Operand* target = frame->machineIp(newIp);
|
||||||
|
|
||||||
c->cmp(4, a, b);
|
|
||||||
switch (instruction) {
|
switch (instruction) {
|
||||||
case if_icmpeq:
|
case if_icmpeq:
|
||||||
c->je(target);
|
c->jumpIfEqual(4, a, b, target);
|
||||||
break;
|
break;
|
||||||
case if_icmpne:
|
case if_icmpne:
|
||||||
c->jne(target);
|
c->jumpIfNotEqual(4, a, b, target);
|
||||||
break;
|
break;
|
||||||
case if_icmpgt:
|
case if_icmpgt:
|
||||||
c->jg(target);
|
c->jumpIfGreater(4, a, b, target);
|
||||||
break;
|
break;
|
||||||
case if_icmpge:
|
case if_icmpge:
|
||||||
c->jge(target);
|
c->jumpIfGreaterOrEqual(4, a, b, target);
|
||||||
break;
|
break;
|
||||||
case if_icmplt:
|
case if_icmplt:
|
||||||
c->jl(target);
|
c->jumpIfLess(4, a, b, target);
|
||||||
break;
|
break;
|
||||||
case if_icmple:
|
case if_icmple:
|
||||||
c->jle(target);
|
c->jumpIfLessOrEqual(4, a, b, target);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, newIp);
|
saveStateAndCompile(t, frame, newIp);
|
||||||
@ -3537,67 +3626,30 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
Compiler::Operand* target = frame->machineIp(newIp);
|
Compiler::Operand* target = frame->machineIp(newIp);
|
||||||
Compiler::Operand* cont = frame->machineIp(ip);
|
Compiler::Operand* cont = frame->machineIp(ip);
|
||||||
|
|
||||||
if (lastFcmpl != 1 and lastFcmpg != 1) {
|
Compiler::Operand* a = c->constant(0, Compiler::IntegerType);
|
||||||
Compiler::Operand* a = frame->popInt();
|
Compiler::Operand* b = frame->popInt();
|
||||||
c->cmp(4, c->constant(0, Compiler::IntegerType), a);
|
|
||||||
}
|
|
||||||
switch (instruction) {
|
switch (instruction) {
|
||||||
case ifeq:
|
case ifeq:
|
||||||
if (lastFcmpl == 1 or lastFcmpg == 1) {
|
c->jumpIfEqual(4, a, b, target);
|
||||||
c->fjuo(cont);
|
|
||||||
c->fje(target);
|
|
||||||
} else {
|
|
||||||
c->je(target);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ifne:
|
case ifne:
|
||||||
if (lastFcmpl == 1 or lastFcmpg == 1) {
|
c->jumpIfNotEqual(4, a, b, target);
|
||||||
c->fjuo(cont);
|
|
||||||
c->fjne(target);
|
|
||||||
} else {
|
|
||||||
c->jne(target);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ifgt:
|
case ifgt:
|
||||||
if (lastFcmpl == 1) {
|
c->jumpIfGreater(4, a, b, target);
|
||||||
c->fjuo(cont);
|
|
||||||
c->fjg(target);
|
|
||||||
} else if (lastFcmpg == 1) {
|
|
||||||
c->fjg(target);
|
|
||||||
} else {
|
|
||||||
c->jg(target);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ifge:
|
case ifge:
|
||||||
if (lastFcmpl == 1) {
|
c->jumpIfGreaterOrEqual(4, a, b, target);
|
||||||
c->fjuo(cont);
|
|
||||||
c->fjge(target);
|
|
||||||
} else if (lastFcmpg == 1) {
|
|
||||||
c->fjge(target);
|
|
||||||
} else {
|
|
||||||
c->jge(target);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case iflt:
|
case iflt:
|
||||||
if (lastFcmpg == 1) {
|
c->jumpIfLess(4, a, b, target);
|
||||||
c->fjuo(cont);
|
|
||||||
c->fjl(target);
|
|
||||||
} else if (lastFcmpl == 1) {
|
|
||||||
c->fjl(target);
|
|
||||||
} else {
|
|
||||||
c->jl(target);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ifle:
|
case ifle:
|
||||||
if(lastFcmpg == 1) {
|
c->jumpIfLessOrEqual(4, a, b, target);
|
||||||
c->fjuo(cont);
|
|
||||||
c->fjle(target);
|
|
||||||
} else if (lastFcmpl == 1) {
|
|
||||||
c->fjle(target);
|
|
||||||
} else {
|
|
||||||
c->jle(target);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, newIp);
|
saveStateAndCompile(t, frame, newIp);
|
||||||
@ -3610,14 +3662,14 @@ 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->popObject();
|
Compiler::Operand* a = c->constant(0, Compiler::ObjectType);
|
||||||
|
Compiler::Operand* b = frame->popObject();
|
||||||
Compiler::Operand* target = frame->machineIp(newIp);
|
Compiler::Operand* target = frame->machineIp(newIp);
|
||||||
|
|
||||||
c->cmp(BytesPerWord, c->constant(0, Compiler::ObjectType), a);
|
|
||||||
if (instruction == ifnull) {
|
if (instruction == ifnull) {
|
||||||
c->je(target);
|
c->jumpIfEqual(BytesPerWord, a, btarget);
|
||||||
} else {
|
} else {
|
||||||
c->jne(target);
|
c->jumpIfNotEqual(BytesPerWord, a, btarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, newIp);
|
saveStateAndCompile(t, frame, newIp);
|
||||||
@ -3971,7 +4023,15 @@ 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->pushInt(c->lcmp(a, b));
|
if (not integerBranch(frame, ip, 8, a, b)) {
|
||||||
|
frame->pushInt
|
||||||
|
(c->call
|
||||||
|
(c->constant
|
||||||
|
(getThunk(t, compareLongsThunk), Compiler::AddressType),
|
||||||
|
0, 0, 4, Compiler::IntegerType, 4,
|
||||||
|
static_cast<Compiler::Operand*>(0), a,
|
||||||
|
static_cast<Compiler::Operand*>(0), b));
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case lconst_0:
|
case lconst_0:
|
||||||
@ -4522,15 +4582,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
Compiler::Operand* key = frame->popInt();
|
Compiler::Operand* key = frame->popInt();
|
||||||
|
|
||||||
c->cmp(4, c->constant(bottom, Compiler::IntegerType), key);
|
c->jumpIfLess(4, c->constant(bottom, Compiler::IntegerType), key,
|
||||||
c->jl(frame->machineIp(defaultIp));
|
frame->machineIp(defaultIp));
|
||||||
|
|
||||||
c->save(1, key);
|
c->save(1, key);
|
||||||
|
|
||||||
saveStateAndCompile(t, frame, defaultIp);
|
saveStateAndCompile(t, frame, defaultIp);
|
||||||
|
|
||||||
c->cmp(4, c->constant(top, Compiler::IntegerType), key);
|
c->jumpIfGreater(4, c->constant(top, Compiler::IntegerType), key,
|
||||||
c->jg(frame->machineIp(defaultIp));
|
frame->machineIp(defaultIp));
|
||||||
|
|
||||||
c->save(1, key);
|
c->save(1, key);
|
||||||
|
|
||||||
|
505
src/compiler.cpp
505
src/compiler.cpp
@ -66,13 +66,6 @@ apply(Context* c, TernaryOperation op,
|
|||||||
unsigned s2Size, Site* s2Low, Site* s2High,
|
unsigned s2Size, Site* s2Low, Site* s2High,
|
||||||
unsigned s3Size, Site* s3Low, Site* s3High);
|
unsigned s3Size, Site* s3Low, Site* s3High);
|
||||||
|
|
||||||
enum ConstantCompare {
|
|
||||||
CompareNone,
|
|
||||||
CompareLess,
|
|
||||||
CompareGreater,
|
|
||||||
CompareEqual
|
|
||||||
};
|
|
||||||
|
|
||||||
class Cell {
|
class Cell {
|
||||||
public:
|
public:
|
||||||
Cell(Cell* next, void* value): next(next), value(value) { }
|
Cell(Cell* next, void* value): next(next), value(value) { }
|
||||||
@ -385,8 +378,7 @@ class Context {
|
|||||||
localFootprint(0),
|
localFootprint(0),
|
||||||
machineCodeSize(0),
|
machineCodeSize(0),
|
||||||
alignedFrameSize(0),
|
alignedFrameSize(0),
|
||||||
availableGeneralRegisterCount(generalRegisterLimit - generalRegisterStart),
|
availableGeneralRegisterCount(generalRegisterLimit - generalRegisterStart)
|
||||||
constantCompare(CompareNone)
|
|
||||||
{
|
{
|
||||||
for (unsigned i = generalRegisterStart; i < generalRegisterLimit; ++i) {
|
for (unsigned i = generalRegisterStart; i < generalRegisterLimit; ++i) {
|
||||||
new (registerResources + i) RegisterResource(arch->reserved(i));
|
new (registerResources + i) RegisterResource(arch->reserved(i));
|
||||||
@ -433,7 +425,6 @@ class Context {
|
|||||||
unsigned machineCodeSize;
|
unsigned machineCodeSize;
|
||||||
unsigned alignedFrameSize;
|
unsigned alignedFrameSize;
|
||||||
unsigned availableGeneralRegisterCount;
|
unsigned availableGeneralRegisterCount;
|
||||||
ConstantCompare constantCompare;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
@ -3459,82 +3450,6 @@ findConstantSite(Context* c, Value* v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompareEvent: public Event {
|
|
||||||
public:
|
|
||||||
CompareEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
|
|
||||||
Value* second, const SiteMask& firstMask,
|
|
||||||
const SiteMask& secondMask):
|
|
||||||
Event(c), type(type), size(size), first(first), second(second)
|
|
||||||
{
|
|
||||||
assert(c, type != FloatCompare or
|
|
||||||
(first->type == ValueFloat and first->type == ValueFloat));
|
|
||||||
|
|
||||||
addReads(c, this, first, size, firstMask, firstMask);
|
|
||||||
addReads(c, this, second, size, secondMask, secondMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* name() {
|
|
||||||
return "CompareEvent";
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
|
||||||
ConstantSite* firstConstant = findConstantSite(c, first);
|
|
||||||
ConstantSite* secondConstant = findConstantSite(c, second);
|
|
||||||
|
|
||||||
if (firstConstant and secondConstant) {
|
|
||||||
int64_t d = firstConstant->value->value()
|
|
||||||
- secondConstant->value->value();
|
|
||||||
|
|
||||||
if (d < 0) {
|
|
||||||
c->constantCompare = CompareLess;
|
|
||||||
} else if (d > 0) {
|
|
||||||
c->constantCompare = CompareGreater;
|
|
||||||
} else {
|
|
||||||
c->constantCompare = CompareEqual;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c->constantCompare = CompareNone;
|
|
||||||
|
|
||||||
apply(c, type, size, first->source, first->source,
|
|
||||||
size, second->source, second->source);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Read* r = reads; r; r = r->eventNext) {
|
|
||||||
popRead(c, this, r->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BinaryOperation type;
|
|
||||||
unsigned size;
|
|
||||||
Value* first;
|
|
||||||
Value* second;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
appendCompare(Context* c, BinaryOperation op, unsigned size, Value* first,
|
|
||||||
Value* second)
|
|
||||||
{
|
|
||||||
bool thunk;
|
|
||||||
uint8_t firstTypeMask;
|
|
||||||
uint64_t firstRegisterMask;
|
|
||||||
uint8_t secondTypeMask;
|
|
||||||
uint64_t secondRegisterMask;
|
|
||||||
|
|
||||||
c->arch->planSource
|
|
||||||
(op, size, &firstTypeMask, &firstRegisterMask, size, &thunk);
|
|
||||||
|
|
||||||
assert(c, not thunk); // todo
|
|
||||||
|
|
||||||
c->arch->planDestination
|
|
||||||
(op, size, 0, 0, size, &secondTypeMask, &secondRegisterMask);
|
|
||||||
|
|
||||||
append(c, new (c->zone->allocate(sizeof(CompareEvent)))
|
|
||||||
CompareEvent
|
|
||||||
(c, op, size, first, second,
|
|
||||||
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
|
||||||
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
preserve(Context* c, Value* v, Site* s, Read* r)
|
preserve(Context* c, Value* v, Site* s, Read* r)
|
||||||
{
|
{
|
||||||
@ -3576,12 +3491,6 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Site*
|
|
||||||
source(Value* v, Site* site)
|
|
||||||
{
|
|
||||||
return v ? v->source : site;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
freezeSource(Context* c, unsigned size, Value* v)
|
freezeSource(Context* c, unsigned size, Value* v)
|
||||||
{
|
{
|
||||||
@ -3674,8 +3583,8 @@ class CombineEvent: public Event {
|
|||||||
|
|
||||||
// fprintf(stderr, "combine %p and %p into %p\n", first, second, result);
|
// fprintf(stderr, "combine %p and %p into %p\n", first, second, result);
|
||||||
apply(c, type,
|
apply(c, type,
|
||||||
firstSize, first->source, source(first->next, first->source),
|
firstSize, first->source, first->next->source),
|
||||||
secondSize, second->source, source(second->next, second->source),
|
secondSize, second->source, second->next->source),
|
||||||
resultSize, low, high);
|
resultSize, low, high);
|
||||||
|
|
||||||
thawSource(c, firstSize, first);
|
thawSource(c, firstSize, first);
|
||||||
@ -4095,8 +4004,7 @@ class TranslateEvent: public Event {
|
|||||||
? getTarget(c, value->next, result->next, resultHighMask)
|
? getTarget(c, value->next, result->next, resultHighMask)
|
||||||
: low);
|
: low);
|
||||||
|
|
||||||
apply(c, type,
|
apply(c, type, valueSize, value->source, value->next->source),
|
||||||
valueSize, value->source, source(value->next, value->source),
|
|
||||||
resultSize, low, high);
|
resultSize, low, high);
|
||||||
|
|
||||||
for (Read* r = reads; r; r = r->eventNext) {
|
for (Read* r = reads; r; r = r->eventNext) {
|
||||||
@ -4264,20 +4172,96 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
|
|||||||
MemoryEvent(c, base, displacement, index, scale, result));
|
MemoryEvent(c, base, displacement, index, scale, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
asFloat(unsigned size, int64_t v)
|
||||||
|
{
|
||||||
|
if (size == 4) {
|
||||||
|
return bitsToFloat(v);
|
||||||
|
} else {
|
||||||
|
return bitsToDouble(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
unordered(double a, double b)
|
||||||
|
{
|
||||||
|
return not (a >= b or a < b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
shouldJump(TernaryOperation type, unsigned size, int64_t a, int64_t b)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case JumpIfEqual:
|
||||||
|
return a == b;
|
||||||
|
|
||||||
|
case JumpIfNotEqual:
|
||||||
|
return a != b;
|
||||||
|
|
||||||
|
case JumpIfLess:
|
||||||
|
return a < b;
|
||||||
|
|
||||||
|
case JumpIfGreater:
|
||||||
|
return a > b;
|
||||||
|
|
||||||
|
case JumpIfLessOrEqual:
|
||||||
|
return a <= b;
|
||||||
|
|
||||||
|
case JumpIfGreaterOrEqual:
|
||||||
|
return a >= b;
|
||||||
|
|
||||||
|
case JumpIfFloatEqual:
|
||||||
|
return asFloat(size, a) == asFloat(size, b);
|
||||||
|
|
||||||
|
case JumpIfFloatNotEqual:
|
||||||
|
return asFloat(size, a) != asFloat(size, b);
|
||||||
|
|
||||||
|
case JumpIfFloatLess:
|
||||||
|
return asFloat(size, a) < asFloat(size, b);
|
||||||
|
|
||||||
|
case JumpIfFloatGreater:
|
||||||
|
return asFloat(size, a) > asFloat(size, b);
|
||||||
|
|
||||||
|
case JumpIfFloatLessOrEqual:
|
||||||
|
return asFloat(size, a) <= asFloat(size, b);
|
||||||
|
|
||||||
|
case JumpIfFloatGreaterOrEqual:
|
||||||
|
return asFloat(size, a) >= asFloat(size, b);
|
||||||
|
|
||||||
|
case JumpIfFloatLessOrUnordered:
|
||||||
|
return asFloat(size, a) < asFloat(size, b)
|
||||||
|
or unordered(asFloat(size, a), asFloat(size, b));
|
||||||
|
|
||||||
|
case JumpIfFloatGreaterOrUnordered:
|
||||||
|
return asFloat(size, a) > asFloat(size, b)
|
||||||
|
or unordered(asFloat(size, a), asFloat(size, b));
|
||||||
|
|
||||||
|
case JumpIfFloatLessOrEqualOrUnordered:
|
||||||
|
return asFloat(size, a) <= asFloat(size, b)
|
||||||
|
or unordered(asFloat(size, a), asFloat(size, b));
|
||||||
|
|
||||||
|
case JumpIfFloatGreaterOrEqualOrUnordered:
|
||||||
|
return asFloat(size, a) >= asFloat(size, b)
|
||||||
|
or unordered(asFloat(size, a), asFloat(size, b));
|
||||||
|
|
||||||
|
default:
|
||||||
|
jump = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class BranchEvent: public Event {
|
class BranchEvent: public Event {
|
||||||
public:
|
public:
|
||||||
BranchEvent(Context* c, UnaryOperation type, Value* address, bool exit):
|
BranchEvent(Context* c, TernaryOperation type, unsigned size,
|
||||||
Event(c), type(type), address(address), exit(exit)
|
Value* first, Value* second, Value* address, bool exit,
|
||||||
|
const SiteMask& firstLowMask,
|
||||||
|
const SiteMask& firstHighMask,
|
||||||
|
const SiteMask& secondLowMask,
|
||||||
|
const SiteMask& secondHighMask):
|
||||||
|
Event(c), type(type), size(size), first(first), second(second),
|
||||||
|
address(address), exit(exit)
|
||||||
{
|
{
|
||||||
bool thunk;
|
addReads(c, this, first, firstSize, firstLowMask, firstHighMask);
|
||||||
uint8_t typeMask;
|
addReads(c, this, second, secondSize, secondLowMask, secondHighMask);
|
||||||
uint64_t registerMask;
|
|
||||||
|
|
||||||
c->arch->plan(type, BytesPerWord, &typeMask, ®isterMask, &thunk);
|
|
||||||
|
|
||||||
assert(c, not thunk);
|
|
||||||
|
|
||||||
addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* name() {
|
virtual const char* name() {
|
||||||
@ -4285,67 +4269,27 @@ class BranchEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
bool jump;
|
ConstantSite* firstConstant = findConstantSite(c, first);
|
||||||
UnaryOperation type = this->type;
|
ConstantSite* secondConstant = findConstantSite(c, second);
|
||||||
if (type != Jump) {
|
|
||||||
switch (c->constantCompare) {
|
|
||||||
case CompareLess:
|
|
||||||
switch (type) {
|
|
||||||
case JumpIfLess:
|
|
||||||
case JumpIfLessOrEqual:
|
|
||||||
case JumpIfNotEqual:
|
|
||||||
jump = true;
|
|
||||||
type = Jump;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if (not unreachable(this)) {
|
||||||
jump = false;
|
if (firstConstant and secondConstant) {
|
||||||
|
if (shouldJump(type, firstConstant->value->value(),
|
||||||
|
secondConstant->value->value())
|
||||||
|
and reachable)
|
||||||
|
{
|
||||||
|
apply(c, Jump, BytesPerWord, address->source, address->source);
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
apply(c, type, size, first->source, first->next->source,
|
||||||
case CompareGreater:
|
size, second->source, second->next->sourcem
|
||||||
switch (type) {
|
BytesPerWord, address->source, address->source);
|
||||||
case JumpIfGreater:
|
|
||||||
case JumpIfGreaterOrEqual:
|
|
||||||
case JumpIfNotEqual:
|
|
||||||
jump = true;
|
|
||||||
type = Jump;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
jump = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CompareEqual:
|
|
||||||
switch (type) {
|
|
||||||
case JumpIfEqual:
|
|
||||||
case JumpIfLessOrEqual:
|
|
||||||
case JumpIfGreaterOrEqual:
|
|
||||||
jump = true;
|
|
||||||
type = Jump;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
jump = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CompareNone:
|
|
||||||
jump = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: abort(c);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
jump = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jump and not unreachable(this)) {
|
for (Read* r = reads; r; r = r->eventNext) {
|
||||||
apply(c, type, BytesPerWord, address->source, address->source);
|
popRead(c, this, r->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
popRead(c, this, address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isBranch() { return true; }
|
virtual bool isBranch() { return true; }
|
||||||
@ -4355,10 +4299,57 @@ class BranchEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UnaryOperation type;
|
UnaryOperation type;
|
||||||
|
unsigned size;
|
||||||
|
Value* first;
|
||||||
|
Value* second;
|
||||||
Value* address;
|
Value* address;
|
||||||
bool exit;
|
bool exit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first,
|
||||||
|
Value* second, Value* address, bool exit = false)
|
||||||
|
{
|
||||||
|
bool thunk;
|
||||||
|
uint8_t firstTypeMask;
|
||||||
|
uint64_t firstRegisterMask;
|
||||||
|
uint8_t secondTypeMask;
|
||||||
|
uint64_t secondRegisterMask;
|
||||||
|
|
||||||
|
c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask,
|
||||||
|
size, &secondTypeMask, &secondRegisterMask,
|
||||||
|
resultSize, &thunk);
|
||||||
|
|
||||||
|
if (thunk) {
|
||||||
|
Stack* oldStack = c->stack;
|
||||||
|
|
||||||
|
local::push(c, ceiling(size, BytesPerWord), second, false);
|
||||||
|
local::push(c, ceiling(size, BytesPerWord), first, false);
|
||||||
|
|
||||||
|
Stack* argumentStack = c->stack;
|
||||||
|
c->stack = oldStack;
|
||||||
|
|
||||||
|
Value* result = value(&c, ValueGeneral);
|
||||||
|
appendCall
|
||||||
|
(c, value
|
||||||
|
(c, ValueGeneral, constantSite(c, c->client->getThunk(type, size, 4))),
|
||||||
|
0, 0, result, resultSize, argumentStack,
|
||||||
|
ceiling(size, BytesPerWord) * 2, 0);
|
||||||
|
|
||||||
|
appendBranch(c, JumpIfEqual, 4, value(c, ValueGeneral, constantSite(c, 0)),
|
||||||
|
result, address);
|
||||||
|
} else {
|
||||||
|
append
|
||||||
|
(c, new (c->zone->allocate(sizeof(BranchEvent)))
|
||||||
|
BranchEvent
|
||||||
|
(c, type, size, first, second, address, exit,
|
||||||
|
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
||||||
|
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
|
||||||
|
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
|
||||||
|
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
appendBranch(Context* c, UnaryOperation type, Value* address,
|
appendBranch(Context* c, UnaryOperation type, Value* address,
|
||||||
bool exit = false)
|
bool exit = false)
|
||||||
@ -4396,11 +4387,10 @@ class BoundsCheckEvent: public Event {
|
|||||||
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
|
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
|
||||||
|
|
||||||
Site* zero = constantSite(c, resolved(c, 0));
|
Site* zero = constantSite(c, resolved(c, 0));
|
||||||
apply(c, Compare, 4, zero, zero, 4, index->source, index->source);
|
|
||||||
|
|
||||||
Assembler::Constant outOfBoundsConstant(outOfBoundsPromise);
|
Assembler::Constant outOfBoundsConstant(outOfBoundsPromise);
|
||||||
a->apply
|
a->apply
|
||||||
(JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant);
|
(JumpIfLess, 4, zero, zero, 4, index->source, index->source,
|
||||||
|
BytesPerWord, ConstantOperand, &outOfBoundsConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(c, object->source->type(c) == RegisterOperand);
|
assert(c, object->source->type(c) == RegisterOperand);
|
||||||
@ -4408,10 +4398,9 @@ class BoundsCheckEvent: public Event {
|
|||||||
lengthOffset, NoRegister, 1);
|
lengthOffset, NoRegister, 1);
|
||||||
length.acquired = true;
|
length.acquired = true;
|
||||||
|
|
||||||
apply(c, Compare, 4, index->source, index->source, 4, &length, &length);
|
|
||||||
|
|
||||||
Assembler::Constant nextConstant(nextPromise);
|
Assembler::Constant nextConstant(nextPromise);
|
||||||
a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant);
|
a->apply(JumpIfGreater, 4, index->source, index->source, 4, &length,
|
||||||
|
&length, BytesPerWord, ConstantOperand, &nextConstant);
|
||||||
|
|
||||||
if (constant == 0) {
|
if (constant == 0) {
|
||||||
outOfBoundsPromise->offset = a->offset();
|
outOfBoundsPromise->offset = a->offset();
|
||||||
@ -5953,88 +5942,176 @@ class MyCompiler: public Compiler {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* lcmp(Operand* a, Operand* b) {
|
virtual void jumpIfEqual(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
||||||
and static_cast<Value*>(b)->type == ValueGeneral);
|
and static_cast<Value*>(b)->type == ValueGeneral);
|
||||||
Value* result = value(&c, ValueGeneral);
|
|
||||||
appendCombine(&c, LongCompare, 8, static_cast<Value*>(a),
|
appendBranch(&c, JumpIfEqual, size, static_cast<Value*>(a),
|
||||||
8, static_cast<Value*>(b), 8, result);
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void cmp(unsigned size, Operand* a, Operand* b) {
|
virtual void jumpIfNotEqual(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
||||||
and static_cast<Value*>(b)->type == ValueGeneral);
|
and static_cast<Value*>(b)->type == ValueGeneral);
|
||||||
appendCompare(&c, Compare, size, static_cast<Value*>(a),
|
|
||||||
static_cast<Value*>(b));
|
appendBranch(&c, JumpIfNotEqual, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void fcmp(unsigned size, Operand* a, Operand* b) {
|
virtual void jumpIfLess(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
||||||
|
and static_cast<Value*>(b)->type == ValueGeneral);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfLess, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void jumpIfGreater(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
||||||
|
and static_cast<Value*>(b)->type == ValueGeneral);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfGreater, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void jumpIfLessOrEqual(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
||||||
|
and static_cast<Value*>(b)->type == ValueGeneral);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfLessOrEqual, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void jumpIfGreaterOrEqual(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueGeneral
|
||||||
|
and static_cast<Value*>(b)->type == ValueGeneral);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfGreaterOrEqual, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void jumpIfFloatEqual(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
and static_cast<Value*>(b)->type == ValueFloat);
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
appendCompare(&c, FloatCompare, size, static_cast<Value*>(a),
|
|
||||||
static_cast<Value*>(b));
|
appendBranch(&c, JumpIfFloatEqual, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void jumpIfFloatNotEqual(unsigned size, Operand* a, Operand* b,
|
||||||
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
virtual void jl(Operand* address) {
|
appendBranch(&c, JumpIfFloatNotEqual, size, static_cast<Value*>(a),
|
||||||
appendBranch(&c, JumpIfLess, static_cast<Value*>(address));
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void jg(Operand* address) {
|
virtual void jumpIfFloatLess(unsigned size, Operand* a, Operand* b,
|
||||||
appendBranch(&c, JumpIfGreater, static_cast<Value*>(address));
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatLess, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void jle(Operand* address) {
|
virtual void jumpIfFloatGreater(unsigned size, Operand* a, Operand* b,
|
||||||
appendBranch(&c, JumpIfLessOrEqual, static_cast<Value*>(address));
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatGreater, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void jge(Operand* address) {
|
virtual void jumpIfFloatLessOrEqual(unsigned size, Operand* a, Operand* b,
|
||||||
appendBranch(&c, JumpIfGreaterOrEqual, static_cast<Value*>(address));
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatLessOrEqual, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void je(Operand* address) {
|
virtual void jumpIfFloatGreaterOrEqual(unsigned size, Operand* a, Operand* b,
|
||||||
appendBranch(&c, JumpIfEqual, static_cast<Value*>(address));
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatGreaterOrEqual, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void jne(Operand* address) {
|
virtual void jumpIfFloatLessOrUnordered(unsigned size, Operand* a,
|
||||||
appendBranch(&c, JumpIfNotEqual, static_cast<Value*>(address));
|
Operand* b, Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatLessOrUnordered, size, static_cast<Value*>(a),
|
||||||
|
static_cast<Value*>(b), static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void fjl(Operand* address) {
|
virtual void jumpIfFloatGreaterOrUnordered(unsigned size, Operand* a,
|
||||||
appendBranch(&c, JumpIfFloatLess, static_cast<Value*>(address));
|
Operand* b, Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatGreaterOrUnordered, size,
|
||||||
|
static_cast<Value*>(a), static_cast<Value*>(b),
|
||||||
|
static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void fjg(Operand* address) {
|
virtual void jumpIfFloatLessOrEqualOrUnordered(unsigned size, Operand* a,
|
||||||
appendBranch(&c, JumpIfFloatGreater, static_cast<Value*>(address));
|
Operand* b, Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
|
appendBranch(&c, JumpIfFloatLessOrEqualOrUnordered, size,
|
||||||
|
static_cast<Value*>(a), static_cast<Value*>(b),
|
||||||
|
static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void fjle(Operand* address) {
|
virtual void jumpIfFloatGreaterOrEqualOrUnordered(unsigned size, Operand* a,
|
||||||
appendBranch(&c, JumpIfFloatLessOrEqual, static_cast<Value*>(address));
|
Operand* b,
|
||||||
}
|
Operand* address)
|
||||||
|
{
|
||||||
|
assert(&c, static_cast<Value*>(a)->type == ValueFloat
|
||||||
|
and static_cast<Value*>(b)->type == ValueFloat);
|
||||||
|
|
||||||
virtual void fjge(Operand* address) {
|
appendBranch(&c, JumpIfFloatGreaterOrEqualOrUnordered, size,
|
||||||
appendBranch(&c, JumpIfFloatGreaterOrEqual, static_cast<Value*>(address));
|
static_cast<Value*>(a), static_cast<Value*>(b),
|
||||||
}
|
static_cast<Value*>(address));
|
||||||
|
|
||||||
virtual void fje(Operand* address) {
|
|
||||||
appendBranch(&c, JumpIfFloatEqual, static_cast<Value*>(address));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void fjne(Operand* address) {
|
|
||||||
appendBranch(&c, JumpIfFloatNotEqual, static_cast<Value*>(address));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void fjuo(Operand* address) {
|
|
||||||
appendBranch(&c, JumpIfFloatUnordered, static_cast<Value*>(address));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void jmp(Operand* address) {
|
virtual void jmp(Operand* address) {
|
||||||
appendBranch(&c, Jump, static_cast<Value*>(address));
|
appendBranch(&c, Jump, 0, 0, 0, static_cast<Value*>(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void exit(Operand* address) {
|
virtual void exit(Operand* address) {
|
||||||
appendBranch(&c, Jump, static_cast<Value*>(address), true);
|
appendBranch(&c, Jump, 0, 0, 0, static_cast<Value*>(address), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
|
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
|
||||||
|
@ -120,22 +120,41 @@ class Compiler {
|
|||||||
unsigned dstSize) = 0;
|
unsigned dstSize) = 0;
|
||||||
virtual Operand* loadz(unsigned size, unsigned srcSelectSize, Operand* src,
|
virtual Operand* loadz(unsigned size, unsigned srcSelectSize, Operand* src,
|
||||||
unsigned dstSize) = 0;
|
unsigned dstSize) = 0;
|
||||||
virtual Operand* lcmp(Operand* a, Operand* b) = 0;
|
|
||||||
virtual void cmp(unsigned size, Operand* a, Operand* b) = 0;
|
virtual void jumpIfEqual
|
||||||
virtual void fcmp(unsigned size, Operand* a, Operand* b) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
virtual void jl(Operand* address) = 0;
|
virtual void jumpIfNotEqual
|
||||||
virtual void jg(Operand* address) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
virtual void jle(Operand* address) = 0;
|
virtual void jumpIfLess
|
||||||
virtual void jge(Operand* address) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
virtual void je(Operand* address) = 0;
|
virtual void jumpIfGreater
|
||||||
virtual void jne(Operand* address) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
virtual void fjl(Operand* address) = 0;
|
virtual void jumpIfLessOrEqual
|
||||||
virtual void fjg(Operand* address) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
virtual void fjle(Operand* address) = 0;
|
virtual void jumpIfGreaterOrEqual
|
||||||
virtual void fjge(Operand* address) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
virtual void fje(Operand* address) = 0;
|
|
||||||
virtual void fjne(Operand* address) = 0;
|
virtual void jumpIfFloatEqual
|
||||||
virtual void fjuo(Operand* address) = 0;
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatNotEqual
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatLess
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatGreater
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatLessOrEqual
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatGreaterOrEqual
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatLessOrUnordered
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatGreaterOrUnordered
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatLessOrEqualOrUnordered
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
virtual void jumpIfFloatGreaterOrEqualOrUnordered
|
||||||
|
(unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
||||||
|
|
||||||
virtual void jmp(Operand* address) = 0;
|
virtual void jmp(Operand* address) = 0;
|
||||||
virtual void exit(Operand* address) = 0;
|
virtual void exit(Operand* address) = 0;
|
||||||
virtual Operand* add(unsigned size, Operand* a, Operand* b) = 0;
|
virtual Operand* add(unsigned size, Operand* a, Operand* b) = 0;
|
||||||
|
@ -1847,10 +1847,6 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
return NoTernaryOperation;
|
return NoTernaryOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool supportsFloatCompare(unsigned) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool alwaysCondensed(BinaryOperation) {
|
virtual bool alwaysCondensed(BinaryOperation) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ THUNK(compareDoublesG)
|
|||||||
THUNK(compareDoublesL)
|
THUNK(compareDoublesL)
|
||||||
THUNK(compareFloatsG)
|
THUNK(compareFloatsG)
|
||||||
THUNK(compareFloatsL)
|
THUNK(compareFloatsL)
|
||||||
|
THUNK(compareLongs)
|
||||||
THUNK(addDouble)
|
THUNK(addDouble)
|
||||||
THUNK(subtractDouble)
|
THUNK(subtractDouble)
|
||||||
THUNK(multiplyDouble)
|
THUNK(multiplyDouble)
|
||||||
|
@ -2713,10 +2713,6 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool supportsFloatCompare(unsigned) {
|
|
||||||
return supportsSSE();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool alwaysCondensed(BinaryOperation op)
|
virtual bool alwaysCondensed(BinaryOperation op)
|
||||||
{
|
{
|
||||||
switch(op) {
|
switch(op) {
|
||||||
|
Loading…
Reference in New Issue
Block a user