mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
lots of bugfixes and a few instructions added
This commit is contained in:
parent
011cbe44e3
commit
392a1417e5
@ -157,17 +157,6 @@ class Assembler {
|
||||
virtual void restore(int r) = 0;
|
||||
};
|
||||
|
||||
class Offset {
|
||||
public:
|
||||
virtual ~Offset() { }
|
||||
|
||||
virtual unsigned resolve(unsigned start) = 0;
|
||||
|
||||
virtual bool resolved() = 0;
|
||||
|
||||
virtual unsigned value() = 0;
|
||||
};
|
||||
|
||||
class Block {
|
||||
public:
|
||||
virtual ~Block() { }
|
||||
@ -252,9 +241,9 @@ class Assembler {
|
||||
|
||||
virtual void writeTo(uint8_t* dst) = 0;
|
||||
|
||||
virtual Offset* offset() = 0;
|
||||
virtual Promise* offset() = 0;
|
||||
|
||||
virtual Block* endBlock() = 0;
|
||||
virtual Block* endBlock(bool startNew) = 0;
|
||||
|
||||
virtual unsigned length() = 0;
|
||||
|
||||
|
@ -350,18 +350,22 @@ alignedFrameSizeWithParameters(MyThread* t, object method)
|
||||
int
|
||||
localOffset(MyThread* t, int v, object method)
|
||||
{
|
||||
int parameterFootprint = methodParameterFootprint(t, method) * BytesPerWord;
|
||||
int parameterFootprint = methodParameterFootprint(t, method);
|
||||
int frameSize = alignedFrameSize(t, method);
|
||||
|
||||
v *= BytesPerWord;
|
||||
if (v < parameterFootprint) {
|
||||
return alignedFrameSize(t, method)
|
||||
+ parameterFootprint
|
||||
+ t->arch->frameFooterSize()
|
||||
+ t->arch->frameHeaderSize()
|
||||
- v;
|
||||
} else {
|
||||
return alignedFrameSize(t, method) - t->arch->frameHeaderSize() - v;
|
||||
}
|
||||
int offset = ((v < parameterFootprint) ?
|
||||
(frameSize
|
||||
+ parameterFootprint
|
||||
+ (t->arch->frameFooterSize() * 2)
|
||||
+ t->arch->frameHeaderSize()
|
||||
- v) :
|
||||
(frameSize
|
||||
+ parameterFootprint
|
||||
+ t->arch->frameFooterSize()
|
||||
- v)) * BytesPerWord;
|
||||
|
||||
assert(t, offset >= 0);
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline object*
|
||||
@ -1837,6 +1841,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
|
||||
if (ip == 0) {
|
||||
handleEntrance(t, frame);
|
||||
|
||||
int index = 0;
|
||||
for (MethodSpecIterator it
|
||||
(t, reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodSpec(t, context->method), 0)));
|
||||
it.hasNext();)
|
||||
{
|
||||
switch (*it.next()) {
|
||||
case 'J':
|
||||
case 'D':
|
||||
c->initParameter(2, index);
|
||||
index += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
c->initParameter(1, index);
|
||||
index += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (exceptionHandler) {
|
||||
exceptionHandler = false;
|
||||
|
||||
@ -2599,10 +2623,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
uint8_t index = codeBody(t, code, ip++);
|
||||
int8_t count = codeBody(t, code, ip++);
|
||||
|
||||
Compiler::Operand* a = c->memory
|
||||
(c->stack(), localOffset(t, index, context->method));
|
||||
|
||||
c->storeLocal(4, c->add(4, c->constant(count), a), index);
|
||||
c->storeLocal
|
||||
(4, c->add(4, c->constant(count), c->loadLocal(4, index)), index);
|
||||
} break;
|
||||
|
||||
case iload:
|
||||
@ -3313,10 +3335,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
} break;
|
||||
|
||||
case ret:
|
||||
c->jmp
|
||||
(c->memory
|
||||
(c->stack(), localOffset
|
||||
(t, codeBody(t, code, ip), context->method)));
|
||||
c->jmp(c->loadLocal(BytesPerWord, codeBody(t, code, ip)));
|
||||
return;
|
||||
|
||||
case return_:
|
||||
@ -3398,10 +3417,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
uint16_t index = codeReadInt16(t, code, ip);
|
||||
uint16_t count = codeReadInt16(t, code, ip);
|
||||
|
||||
Compiler::Operand* a = c->memory
|
||||
(c->stack(), localOffset(t, index, context->method));
|
||||
|
||||
c->storeLocal(4, c->add(4, c->constant(count), a), index);
|
||||
c->storeLocal
|
||||
(4, c->add(4, c->constant(count), c->loadLocal(4, index)), index);
|
||||
} break;
|
||||
|
||||
case iload: {
|
||||
@ -3421,10 +3438,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
} break;
|
||||
|
||||
case ret:
|
||||
c->jmp
|
||||
(c->memory
|
||||
(c->stack(), localOffset
|
||||
(t, codeReadInt16(t, code, ip), context->method)));
|
||||
c->jmp(c->loadLocal(BytesPerWord, codeReadInt16(t, code, ip)));
|
||||
return;
|
||||
|
||||
default: abort(t);
|
||||
@ -4960,7 +4974,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
Assembler::Register result(t->arch->returnLow());
|
||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||
|
||||
a->endBlock()->resolve(0, 0);
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext nativeContext(t);
|
||||
@ -4982,7 +4996,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
|
||||
a->apply(Return);
|
||||
|
||||
a->endBlock()->resolve(0, 0);
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext aioobContext(t);
|
||||
@ -5001,7 +5015,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
Assembler::Constant proc(&(aioobContext.promise));
|
||||
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
a->endBlock()->resolve(0, 0);
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
ThunkContext tableContext(t);
|
||||
@ -5013,7 +5027,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
Assembler::Constant proc(&(tableContext.promise));
|
||||
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
a->endBlock()->resolve(0, 0);
|
||||
a->endBlock(false)->resolve(0, 0);
|
||||
}
|
||||
|
||||
p->thunkSize = pad(tableContext.context.assembler->length());
|
||||
|
@ -130,7 +130,7 @@ class LogicalInstruction {
|
||||
LogicalInstruction* immediatePredecessor;
|
||||
Stack* stack;
|
||||
Value** locals;
|
||||
Assembler::Offset* machineOffset;
|
||||
Promise* machineOffset;
|
||||
int index;
|
||||
bool stackSaved;
|
||||
};
|
||||
@ -301,7 +301,7 @@ class CodePromise: public Promise {
|
||||
c(c), offset(0), next(next)
|
||||
{ }
|
||||
|
||||
CodePromise(Context* c, Assembler::Offset* offset):
|
||||
CodePromise(Context* c, Promise* offset):
|
||||
c(c), offset(offset), next(0)
|
||||
{ }
|
||||
|
||||
@ -318,7 +318,7 @@ class CodePromise: public Promise {
|
||||
}
|
||||
|
||||
Context* c;
|
||||
Assembler::Offset* offset;
|
||||
Promise* offset;
|
||||
CodePromise* next;
|
||||
};
|
||||
|
||||
@ -450,18 +450,19 @@ localOffset(Context* c, int v)
|
||||
int parameterFootprint = c->parameterFootprint;
|
||||
int frameSize = alignedFrameSize(c);
|
||||
|
||||
if (v < parameterFootprint) {
|
||||
return (frameSize
|
||||
+ parameterFootprint
|
||||
+ (c->arch->frameFooterSize() * 2)
|
||||
+ c->arch->frameHeaderSize()
|
||||
- v) * BytesPerWord;
|
||||
} else {
|
||||
return (frameSize
|
||||
+ parameterFootprint
|
||||
+ c->arch->frameFooterSize()
|
||||
- v) * BytesPerWord;
|
||||
}
|
||||
int offset = ((v < parameterFootprint) ?
|
||||
(frameSize
|
||||
+ parameterFootprint
|
||||
+ (c->arch->frameFooterSize() * 2)
|
||||
+ c->arch->frameHeaderSize()
|
||||
- v) :
|
||||
(frameSize
|
||||
+ parameterFootprint
|
||||
+ c->arch->frameFooterSize()
|
||||
- v)) * BytesPerWord;
|
||||
|
||||
assert(c, offset >= 0);
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1460,7 +1461,7 @@ codePromise(Context* c, Event* e)
|
||||
}
|
||||
|
||||
CodePromise*
|
||||
codePromise(Context* c, Assembler::Offset* offset)
|
||||
codePromise(Context* c, Promise* offset)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
|
||||
}
|
||||
@ -2194,13 +2195,13 @@ class BoundsCheckEvent: public Event {
|
||||
|
||||
ConstantSite* constant = findConstantSite(c, index);
|
||||
CodePromise* nextPromise = codePromise
|
||||
(c, static_cast<Assembler::Offset*>(0));
|
||||
(c, static_cast<Promise*>(0));
|
||||
CodePromise* outOfBoundsPromise = 0;
|
||||
|
||||
if (constant) {
|
||||
expect(c, constant->value.value->value() >= 0);
|
||||
} else {
|
||||
outOfBoundsPromise = codePromise(c, static_cast<Assembler::Offset*>(0));
|
||||
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
|
||||
|
||||
apply(c, Compare, 4, constantSite(c, resolved(c, 0)), 4, index->source);
|
||||
|
||||
@ -2253,6 +2254,36 @@ appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
|
||||
(c, object, lengthOffset, index, handler);
|
||||
}
|
||||
|
||||
class ParameterEvent: public Event {
|
||||
public:
|
||||
ParameterEvent(Context* c, Value* value, unsigned size, int index):
|
||||
Event(c), value(value), size(size), index(index)
|
||||
{ }
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
if (DebugCompile) {
|
||||
fprintf(stderr, "ParameterEvent.compile\n");
|
||||
}
|
||||
|
||||
addSite(c, stack, locals, size, value, frameSite(c, index));
|
||||
}
|
||||
|
||||
Value* value;
|
||||
unsigned size;
|
||||
int index;
|
||||
};
|
||||
|
||||
void
|
||||
appendParameter(Context* c, Value* value, unsigned size, int index)
|
||||
{
|
||||
if (DebugAppend) {
|
||||
fprintf(stderr, "appendParameter\n");
|
||||
}
|
||||
|
||||
new (c->zone->allocate(sizeof(ParameterEvent))) ParameterEvent
|
||||
(c, value, size, index);
|
||||
}
|
||||
|
||||
// class ClobberLocalEvent: public Event {
|
||||
// public:
|
||||
// ClobberLocalEvent(Context* c, unsigned size, int index):
|
||||
@ -2550,19 +2581,18 @@ compile(Context* c)
|
||||
p->offset = a->offset();
|
||||
}
|
||||
|
||||
if (e->next and e->logicalInstruction->lastEvent == e) {
|
||||
if (e->logicalInstruction->lastEvent == e) {
|
||||
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
||||
if (nextInstruction != e->next->logicalInstruction) {
|
||||
if (e->next == 0 or nextInstruction != e->next->logicalInstruction) {
|
||||
block->nextInstruction = nextInstruction;
|
||||
block->assemblerBlock = a->endBlock();
|
||||
block = ::block(c, e->next);
|
||||
block->assemblerBlock = a->endBlock(e->next != 0);
|
||||
if (e->next) {
|
||||
block = ::block(c, e->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
block->nextInstruction = 0;
|
||||
block->assemblerBlock = a->endBlock();
|
||||
|
||||
block = firstBlock;
|
||||
while (block->nextInstruction) {
|
||||
Block* next = block->nextInstruction->firstEvent->block;
|
||||
@ -2710,6 +2740,7 @@ class MyCompiler: public Compiler {
|
||||
|
||||
c.state->locals = static_cast<Value**>
|
||||
(c.zone->allocate(sizeof(Value*) * localFootprint));
|
||||
|
||||
memset(c.state->locals, 0, sizeof(Value*) * localFootprint);
|
||||
}
|
||||
|
||||
@ -2925,6 +2956,14 @@ class MyCompiler: public Compiler {
|
||||
appendReturn(&c, size, static_cast<Value*>(value));
|
||||
}
|
||||
|
||||
virtual void initParameter(unsigned size, unsigned index) {
|
||||
assert(&c, index < c.parameterFootprint);
|
||||
|
||||
Value* v = value(&c);
|
||||
appendParameter(&c, v, size, index);
|
||||
c.state->locals[index] = v;
|
||||
}
|
||||
|
||||
virtual void storeLocal(unsigned, Operand* src, unsigned index) {
|
||||
assert(&c, index < c.localFootprint);
|
||||
|
||||
|
@ -92,6 +92,7 @@ class Compiler {
|
||||
|
||||
virtual void return_(unsigned size, Operand* value) = 0;
|
||||
|
||||
virtual void initParameter(unsigned size, unsigned index) = 0;
|
||||
virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0;
|
||||
virtual Operand* loadLocal(unsigned size, unsigned index) = 0;
|
||||
|
||||
|
316
src/x86.cpp
316
src/x86.cpp
@ -180,6 +180,35 @@ codePromise(Context* c, unsigned offset)
|
||||
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
|
||||
}
|
||||
|
||||
class Offset: public Promise {
|
||||
public:
|
||||
Offset(Context* c, MyBlock* block, unsigned offset):
|
||||
c(c), block(block), offset(offset)
|
||||
{ }
|
||||
|
||||
virtual bool resolved() {
|
||||
return block->start != static_cast<unsigned>(~0);
|
||||
}
|
||||
|
||||
virtual int64_t value() {
|
||||
assert(c, resolved());
|
||||
|
||||
return block->start + (offset - block->offset)
|
||||
+ padding(block->firstPadding, block->start, block->offset, offset);
|
||||
}
|
||||
|
||||
Context* c;
|
||||
MyBlock* block;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
Promise*
|
||||
offset(Context* c)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(Offset)))
|
||||
Offset(c, c->lastBlock, c->code.length());
|
||||
}
|
||||
|
||||
class Task {
|
||||
public:
|
||||
Task(Task* next): next(next) { }
|
||||
@ -193,7 +222,7 @@ class Task {
|
||||
|
||||
class OffsetTask: public Task {
|
||||
public:
|
||||
OffsetTask(Task* next, Promise* promise, unsigned instructionOffset,
|
||||
OffsetTask(Task* next, Promise* promise, Promise* instructionOffset,
|
||||
unsigned instructionSize):
|
||||
Task(next),
|
||||
promise(promise),
|
||||
@ -202,7 +231,7 @@ class OffsetTask: public Task {
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c) {
|
||||
uint8_t* instruction = c->result + instructionOffset;
|
||||
uint8_t* instruction = c->result + instructionOffset->value();
|
||||
intptr_t v = reinterpret_cast<uint8_t*>(promise->value())
|
||||
- instruction - instructionSize;
|
||||
|
||||
@ -213,12 +242,12 @@ class OffsetTask: public Task {
|
||||
}
|
||||
|
||||
Promise* promise;
|
||||
unsigned instructionOffset;
|
||||
Promise* instructionOffset;
|
||||
unsigned instructionSize;
|
||||
};
|
||||
|
||||
void
|
||||
appendOffsetTask(Context* c, Promise* promise, int instructionOffset,
|
||||
appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset,
|
||||
unsigned instructionSize)
|
||||
{
|
||||
c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask
|
||||
@ -227,7 +256,7 @@ appendOffsetTask(Context* c, Promise* promise, int instructionOffset,
|
||||
|
||||
class ImmediateTask: public Task {
|
||||
public:
|
||||
ImmediateTask(Task* next, Promise* promise, unsigned offset):
|
||||
ImmediateTask(Task* next, Promise* promise, Promise* offset):
|
||||
Task(next),
|
||||
promise(promise),
|
||||
offset(offset)
|
||||
@ -235,15 +264,15 @@ class ImmediateTask: public Task {
|
||||
|
||||
virtual void run(Context* c) {
|
||||
intptr_t v = promise->value();
|
||||
memcpy(c->result + offset, &v, BytesPerWord);
|
||||
memcpy(c->result + offset->value(), &v, BytesPerWord);
|
||||
}
|
||||
|
||||
Promise* promise;
|
||||
unsigned offset;
|
||||
Promise* offset;
|
||||
};
|
||||
|
||||
void
|
||||
appendImmediateTask(Context* c, Promise* promise, unsigned offset)
|
||||
appendImmediateTask(Context* c, Promise* promise, Promise* offset)
|
||||
{
|
||||
c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask
|
||||
(c->tasks, promise, offset);
|
||||
@ -359,7 +388,7 @@ return_(Context* c)
|
||||
void
|
||||
unconditional(Context* c, unsigned jump, Assembler::Constant* a)
|
||||
{
|
||||
appendOffsetTask(c, a->value, c->code.length(), 5);
|
||||
appendOffsetTask(c, a->value, offset(c), 5);
|
||||
|
||||
c->code.append(jump);
|
||||
c->code.append4(0);
|
||||
@ -368,7 +397,7 @@ unconditional(Context* c, unsigned jump, Assembler::Constant* a)
|
||||
void
|
||||
conditional(Context* c, unsigned condition, Assembler::Constant* a)
|
||||
{
|
||||
appendOffsetTask(c, a->value, c->code.length(), 6);
|
||||
appendOffsetTask(c, a->value, offset(c), 6);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(condition);
|
||||
@ -397,7 +426,7 @@ index(TernaryOperation operation,
|
||||
OperandType operand1,
|
||||
OperandType operand2)
|
||||
{
|
||||
return operation
|
||||
return BinaryOperationCount + operation
|
||||
+ ((BinaryOperationCount + TernaryOperationCount) * operand1)
|
||||
+ ((BinaryOperationCount + TernaryOperationCount)
|
||||
* OperandTypeCount * operand2);
|
||||
@ -421,6 +450,62 @@ jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
unconditional(c, 0xe9, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpM(Context* c, unsigned size UNUSED, Assembler::Memory* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
encode(c, 0xff, 4, a, false);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x84, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfNotEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x85, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfGreaterC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x8f, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x8d, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfLessC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x8c, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfLessOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x8e, a);
|
||||
}
|
||||
|
||||
void
|
||||
moveCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
||||
unsigned bSize, Assembler::Register* b);
|
||||
@ -709,7 +794,7 @@ moveCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
||||
if (a->value->resolved()) {
|
||||
c->code.appendAddress(a->value->value());
|
||||
} else {
|
||||
appendImmediateTask(c, a->value, c->code.length());
|
||||
appendImmediateTask(c, a->value, offset(c));
|
||||
c->code.appendAddress(static_cast<uintptr_t>(0));
|
||||
}
|
||||
}
|
||||
@ -754,6 +839,18 @@ moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
compareRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||
unsigned bSize UNUSED, Assembler::Register* b)
|
||||
{
|
||||
assert(c, aSize == bSize);
|
||||
assert(c, BytesPerWord == 8 or aSize == 4);
|
||||
|
||||
if (aSize == 8) rex(c);
|
||||
c->code.append(0x39);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
}
|
||||
|
||||
void
|
||||
addCarryRR(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
@ -839,6 +936,26 @@ addCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
|
||||
unsigned bSize UNUSED, Assembler::Memory* b)
|
||||
{
|
||||
assert(c, aSize == bSize);
|
||||
assert(c, BytesPerWord == 8 or aSize == 4);
|
||||
|
||||
int64_t v = a->value->value();
|
||||
unsigned i = (isInt8(v) ? 0x83 : 0x81);
|
||||
|
||||
encode(c, i, 0, b, true);
|
||||
if (isInt8(v)) {
|
||||
c->code.append(v);
|
||||
} else if (isInt32(v)) {
|
||||
c->code.append4(v);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
@ -987,6 +1104,67 @@ andCR(Context* c, unsigned aSize, Assembler::Constant* a,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
multiplyRR(Context* c, unsigned aSize, Assembler::Register* a,
|
||||
unsigned bSize, Assembler::Register* b)
|
||||
{
|
||||
assert(c, aSize == bSize);
|
||||
|
||||
if (BytesPerWord == 4 and aSize == 8) {
|
||||
assert(c, b->high == rdx);
|
||||
assert(c, b->low != rax);
|
||||
assert(c, a->low != rax);
|
||||
assert(c, a->high != rax);
|
||||
|
||||
c->client->save(rax);
|
||||
|
||||
Assembler::Register axdx(rax, rdx);
|
||||
Assembler::Register ah(a->high);
|
||||
Assembler::Register bh(b->high);
|
||||
|
||||
moveRR(c, 4, b, 4, &axdx);
|
||||
multiplyRR(c, 4, &ah, 4, b);
|
||||
multiplyRR(c, 4, a, 4, &bh);
|
||||
addRR(c, 4, &bh, 4, b);
|
||||
|
||||
// mul a->low,%eax%edx
|
||||
c->code.append(0xf7);
|
||||
c->code.append(0xe0 | a->low);
|
||||
|
||||
addRR(c, 4, b, 4, &bh);
|
||||
moveRR(c, 4, &axdx, 4, b);
|
||||
|
||||
c->client->restore(rax);
|
||||
} else {
|
||||
if (aSize == 8) rex(c);
|
||||
c->code.append(0x0f);
|
||||
c->code.append(0xaf);
|
||||
c->code.append(0xc0 | (b->low << 3) | a->low);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
multiplyMR(Context* c, unsigned aSize, Assembler::Memory* a,
|
||||
unsigned bSize, Assembler::Register* b)
|
||||
{
|
||||
assert(c, aSize == bSize);
|
||||
|
||||
if (BytesPerWord == 4 and aSize == 8) {
|
||||
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||
Assembler::Register tmp(c->client->acquireTemporary(mask),
|
||||
c->client->acquireTemporary(mask));
|
||||
|
||||
moveMR(c, aSize, a, aSize, &tmp);
|
||||
multiplyRR(c, aSize, &tmp, bSize, b);
|
||||
|
||||
c->client->releaseTemporary(tmp.low);
|
||||
c->client->releaseTemporary(tmp.high);
|
||||
} else {
|
||||
if (aSize == 8) rex(c);
|
||||
encode2(c, 0x0faf, b->low, a, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
populateTables(ArchitectureContext* c)
|
||||
{
|
||||
@ -1011,8 +1189,15 @@ populateTables(ArchitectureContext* c)
|
||||
uo[index(LongCall, C)] = CAST1(longCallC);
|
||||
|
||||
uo[index(Jump, R)] = CAST1(jumpR);
|
||||
|
||||
uo[index(Jump, C)] = CAST1(jumpC);
|
||||
uo[index(Jump, M)] = CAST1(jumpM);
|
||||
|
||||
uo[index(JumpIfEqual, C)] = CAST1(jumpIfEqualC);
|
||||
uo[index(JumpIfNotEqual, C)] = CAST1(jumpIfNotEqualC);
|
||||
uo[index(JumpIfGreater, C)] = CAST1(jumpIfGreaterC);
|
||||
uo[index(JumpIfGreaterOrEqual, C)] = CAST1(jumpIfGreaterOrEqualC);
|
||||
uo[index(JumpIfLess, C)] = CAST1(jumpIfLessC);
|
||||
uo[index(JumpIfLessOrEqual, C)] = CAST1(jumpIfLessOrEqualC);
|
||||
|
||||
uo[index(LongJump, C)] = CAST1(longJumpC);
|
||||
|
||||
@ -1023,11 +1208,17 @@ populateTables(ArchitectureContext* c)
|
||||
bo[index(Move, C, M)] = CAST2(moveCM);
|
||||
bo[index(Move, A, M)] = CAST2(moveAM);
|
||||
|
||||
bo[index(Compare, R, R)] = CAST2(compareRR);
|
||||
|
||||
bo[index(Add, C, R)] = CAST2(addCR);
|
||||
bo[index(Add, C, M)] = CAST2(addCM);
|
||||
|
||||
bo[index(Subtract, C, R)] = CAST2(subtractCR);
|
||||
|
||||
bo[index(And, C, R)] = CAST2(andCR);
|
||||
|
||||
bo[index(Multiply, R, R)] = CAST2(multiplyRR);
|
||||
bo[index(Multiply, M, R)] = CAST2(multiplyMR);
|
||||
}
|
||||
|
||||
class MyArchitecture: public Assembler::Architecture {
|
||||
@ -1162,7 +1353,7 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
case Compare:
|
||||
if (BytesPerWord == 8 and aSize != 8) {
|
||||
*aTypeMask = ~(1 << MemoryOperand);
|
||||
*bTypeMask = ~(1 << MemoryOperand);
|
||||
*bTypeMask = ~((1 << MemoryOperand) | (1 << ConstantOperand));
|
||||
} else {
|
||||
*bTypeMask = ~(1 << ConstantOperand);
|
||||
}
|
||||
@ -1190,8 +1381,8 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
}
|
||||
|
||||
virtual void plan
|
||||
(TernaryOperation,
|
||||
unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
||||
(TernaryOperation op,
|
||||
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
||||
unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask,
|
||||
unsigned, uint8_t* cTypeMask, uint64_t* cRegisterMask,
|
||||
bool* thunk)
|
||||
@ -1199,13 +1390,56 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
*aTypeMask = ~0;
|
||||
*aRegisterMask = ~static_cast<uint64_t>(0);
|
||||
|
||||
*bTypeMask = ~0;
|
||||
*bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||
*bRegisterMask = ~static_cast<uint64_t>(0);
|
||||
|
||||
*cTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||
*cRegisterMask = ~static_cast<uint64_t>(0);
|
||||
|
||||
*thunk = false;
|
||||
|
||||
switch (op) {
|
||||
case Multiply:
|
||||
if (BytesPerWord == 4 and aSize == 8) {
|
||||
const uint32_t mask = ~((1 << rax) | (1 << rdx));
|
||||
*aRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||
*bRegisterMask = (static_cast<uint64_t>(1) << (rdx + 32)) | mask;
|
||||
}
|
||||
break;
|
||||
|
||||
case Divide:
|
||||
if (BytesPerWord == 4 and aSize == 8) {
|
||||
*bTypeMask = ~0;
|
||||
*thunk = true;
|
||||
} else {
|
||||
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
||||
*bRegisterMask = 1 << rax;
|
||||
}
|
||||
break;
|
||||
|
||||
case Remainder:
|
||||
if (BytesPerWord == 4 and aSize == 8) {
|
||||
*bTypeMask = ~0;
|
||||
*thunk = true;
|
||||
} else {
|
||||
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
||||
*bRegisterMask = 1 << rax;
|
||||
}
|
||||
break;
|
||||
|
||||
case ShiftLeft:
|
||||
case ShiftRight:
|
||||
case UnsignedShiftRight: {
|
||||
*aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand);
|
||||
*aRegisterMask = (~static_cast<uint64_t>(0) << 32)
|
||||
| (static_cast<uint64_t>(1) << rcx);
|
||||
const uint32_t mask = ~(1 << rcx);
|
||||
*bRegisterMask = (static_cast<uint64_t>(mask) << 32) | mask;
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*cTypeMask = *bTypeMask;
|
||||
*cRegisterMask = *bRegisterMask;
|
||||
}
|
||||
|
||||
virtual void acquire() {
|
||||
@ -1222,33 +1456,6 @@ class MyArchitecture: public Assembler::Architecture {
|
||||
unsigned referenceCount;
|
||||
};
|
||||
|
||||
class MyOffset: public Assembler::Offset {
|
||||
public:
|
||||
MyOffset(Context* c, MyBlock* block, unsigned offset):
|
||||
c(c), block(block), offset(offset)
|
||||
{ }
|
||||
|
||||
virtual unsigned resolve(unsigned start) {
|
||||
block->start = start;
|
||||
return value();
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return block->start != static_cast<unsigned>(~0);
|
||||
}
|
||||
|
||||
virtual unsigned value() {
|
||||
assert(c, resolved());
|
||||
|
||||
return block->start + (offset - block->offset)
|
||||
+ padding(block->firstPadding, block->start, block->offset, offset);
|
||||
}
|
||||
|
||||
Context* c;
|
||||
MyBlock* block;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
class MyAssembler: public Assembler {
|
||||
public:
|
||||
MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch):
|
||||
@ -1370,16 +1577,19 @@ class MyAssembler: public Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
virtual Offset* offset() {
|
||||
return new (c.zone->allocate(sizeof(MyOffset)))
|
||||
MyOffset(&c, c.lastBlock, c.code.length());
|
||||
virtual Promise* offset() {
|
||||
return ::offset(&c);
|
||||
}
|
||||
|
||||
virtual Block* endBlock() {
|
||||
virtual Block* endBlock(bool startNew) {
|
||||
MyBlock* b = c.lastBlock;
|
||||
b->size = c.code.length() - b->offset;
|
||||
c.lastBlock = new (c.zone->allocate(sizeof(MyBlock)))
|
||||
MyBlock(c.code.length());
|
||||
if (startNew) {
|
||||
c.lastBlock = new (c.zone->allocate(sizeof(MyBlock)))
|
||||
MyBlock(c.code.length());
|
||||
} else {
|
||||
c.lastBlock = 0;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user