diff --git a/src/assembler.h b/src/assembler.h index 03c2380c2d..248d8272a8 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -333,7 +333,6 @@ class Assembler { virtual void updateCall(UnaryOperation op, void* returnAddress, void* newTarget) = 0; - virtual uintptr_t getConstant(const void* src) = 0; virtual void setConstant(void* dst, uintptr_t constant) = 0; virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; @@ -422,6 +421,8 @@ class Assembler { virtual unsigned length() = 0; + virtual unsigned scratchSize() = 0; + virtual void dispose() = 0; }; diff --git a/src/compile.cpp b/src/compile.cpp index 8dd745defc..c29914f3e0 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5383,6 +5383,7 @@ makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start, return table; } + uint8_t* finish(MyThread* t, Allocator* allocator, Context* context) { diff --git a/src/compiler.cpp b/src/compiler.cpp index b2c1b7ed90..60ec596ce9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -5397,7 +5397,7 @@ compile(Context* c) block = next; } - return block->assemblerBlock->resolve(block->start, 0); + return block->assemblerBlock->resolve(block->start, 0) + a->scratchSize(); } unsigned diff --git a/src/powerpc.cpp b/src/powerpc.cpp index e978310dcf..3f9c8e79af 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -32,6 +32,15 @@ inline int lo16(int64_t i) { return (int)(i & MASK_LO16); } inline int hi16(int64_t i) { return lo16(i >> 16); } inline int lo8(int64_t i) { return (int)(i & MASK_LO8); } inline int hi8(int64_t i) { return lo8(i >> 8); } + +inline int ha16(int32_t i) { + return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; +} + +inline int unha16(int32_t high, int32_t low) { + return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; +} + } namespace isa { @@ -186,13 +195,14 @@ class MyBlock: public Assembler::Block { }; class Task; +class ConstantPoolEntry; class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)), - lastBlock(firstBlock) + lastBlock(firstBlock), constantPool(0), constantPoolCount(0) { } System* s; @@ -203,6 +213,8 @@ class Context { uint8_t* result; MyBlock* firstBlock; MyBlock* lastBlock; + ConstantPoolEntry* constantPool; + unsigned constantPoolCount; }; class Task { @@ -556,15 +568,20 @@ void unsignedShiftRightC(Context* con, unsigned size, Const* a, Reg* b, Reg* t) } void -updateImmediate(System* s, void* dst, int64_t src, unsigned size) +updateImmediate(System* s, void* dst, int32_t src, unsigned size, bool address) { switch (size) { case 4: { int32_t* p = static_cast(dst); int r = (p[1] >> 21) & 31; - p[0] = lis(r, src >> 16); - p[1] = ori(r, r, src); + if (address) { + p[0] = lis(r, ha16(src)); + p[1] |= (src & 0xFFFF); + } else { + p[0] = lis(r, src >> 16); + p[1] = ori(r, r, src); + } } break; default: abort(s); @@ -573,12 +590,13 @@ updateImmediate(System* s, void* dst, int64_t src, unsigned size) class ImmediateListener: public Promise::Listener { public: - ImmediateListener(System* s, void* dst, unsigned size, unsigned offset): - s(s), dst(dst), size(size), offset(offset) + ImmediateListener(System* s, void* dst, unsigned size, unsigned offset, + bool address): + s(s), dst(dst), size(size), offset(offset), address(address) { } virtual bool resolve(int64_t value, void** location) { - updateImmediate(s, dst, value, size); + updateImmediate(s, dst, value, size, address); if (location) *location = static_cast(dst) + offset; return false; } @@ -587,26 +605,28 @@ class ImmediateListener: public Promise::Listener { void* dst; unsigned size; unsigned offset; + bool address; }; class ImmediateTask: public Task { public: ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size, - unsigned promiseOffset): + unsigned promiseOffset, bool address): Task(next), promise(promise), offset(offset), size(size), - promiseOffset(promiseOffset) + promiseOffset(promiseOffset), + address(address) { } virtual void run(Context* c) { if (promise->resolved()) { updateImmediate - (c->s, c->result + offset->value(), promise->value(), size); + (c->s, c->result + offset->value(), promise->value(), size, address); } else { new (promise->listen(sizeof(ImmediateListener))) ImmediateListener - (c->s, c->result + offset->value(), size, promiseOffset); + (c->s, c->result + offset->value(), size, promiseOffset, address); } } @@ -614,14 +634,48 @@ class ImmediateTask: public Task { Promise* offset; unsigned size; unsigned promiseOffset; + bool address; }; void appendImmediateTask(Context* c, Promise* promise, Promise* offset, - unsigned size, unsigned promiseOffset = 0) + unsigned size, unsigned promiseOffset, bool address) { c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask - (c->tasks, promise, offset, size, promiseOffset); + (c->tasks, promise, offset, size, promiseOffset, address); +} + +class ConstantPoolEntry: public Promise { + public: + ConstantPoolEntry(Context* c, Promise* constant): + c(c), constant(constant), next(c->constantPool), address(0) + { + c->constantPool = this; + ++ c->constantPoolCount; + } + + virtual int64_t value() { + assert(c, resolved()); + + return reinterpret_cast(address); + } + + virtual bool resolved() { + return address != 0; + } + + Context* c; + Promise* constant; + ConstantPoolEntry* next; + void* address; + unsigned constantPoolCount; +}; + +ConstantPoolEntry* +appendConstantPoolEntry(Context* c, Promise* constant) +{ + return new (c->zone->allocate(sizeof(ConstantPoolEntry))) + ConstantPoolEntry(c, constant); } void @@ -717,7 +771,7 @@ moveCR2(Context* c, unsigned, Assembler::Constant* src, } } else { appendImmediateTask - (c, src->value, offset(c), BytesPerWord, promiseOffset); + (c, src->value, offset(c), BytesPerWord, promiseOffset, false); issue(c, lis(dst->low, 0)); issue(c, ori(dst->low, dst->low, 0)); } @@ -1252,18 +1306,27 @@ xorC(Context* c, unsigned size, Assembler::Constant* a, } void -moveAR(Context* c, unsigned srcSize, Assembler::Address* src, - unsigned dstSize, Assembler::Register* dst) +moveAR2(Context* c, unsigned srcSize, Assembler::Address* src, + unsigned dstSize, Assembler::Register* dst, unsigned promiseOffset) { assert(c, srcSize == 4 and dstSize == 4); - Assembler::Constant constant(src->address); Assembler::Memory memory(dst->low, 0, -1, 0); - - moveCR(c, srcSize, &constant, dstSize, dst); + + appendImmediateTask + (c, src->address, offset(c), BytesPerWord, promiseOffset, true); + + issue(c, lis(dst->low, 0)); moveMR(c, dstSize, &memory, dstSize, dst); } +void +moveAR(Context* c, unsigned srcSize, Assembler::Address* src, + unsigned dstSize, Assembler::Register* dst) +{ + moveAR2(c, srcSize, src, dstSize, dst, 0); +} + void compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, unsigned bSize UNUSED, Assembler::Register* b) @@ -1596,6 +1659,18 @@ longCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) callR(c, BytesPerWord, &tmp); } +void +alignedLongCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +{ + assert(c, size == BytesPerWord); + + Assembler::Register tmp(c->client->acquireTemporary()); + Assembler::Address address(appendConstantPoolEntry(c, target->value)); + moveAR2(c, BytesPerWord, &address, BytesPerWord, &tmp, 12); + callR(c, BytesPerWord, &tmp); + c->client->releaseTemporary(tmp.low); +} + void longJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) { @@ -1606,6 +1681,18 @@ longJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) jumpR(c, BytesPerWord, &tmp); } +void +alignedLongJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +{ + assert(c, size == BytesPerWord); + + Assembler::Register tmp(c->client->acquireTemporary()); + Assembler::Address address(appendConstantPoolEntry(c, target->value)); + moveAR2(c, BytesPerWord, &address, BytesPerWord, &tmp, 12); + jumpR(c, BytesPerWord, &tmp); + c->client->releaseTemporary(tmp.low); +} + void jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) { @@ -1707,8 +1794,12 @@ populateTables(ArchitectureContext* c) uo[index(c, LongCall, C)] = CAST1(longCallC); + uo[index(c, AlignedLongCall, C)] = CAST1(alignedLongCallC); + uo[index(c, LongJump, C)] = CAST1(longJumpC); + uo[index(c, AlignedLongJump, C)] = CAST1(alignedLongJumpC); + uo[index(c, Jump, R)] = CAST1(jumpR); uo[index(c, Jump, C)] = CAST1(jumpC); @@ -1878,7 +1969,15 @@ class MyArchitecture: public Assembler::Architecture { case LongCall: case LongJump: { updateImmediate(c.s, static_cast(returnAddress) - 12, - reinterpret_cast(newTarget), BytesPerWord); + reinterpret_cast(newTarget), BytesPerWord, + false); + } break; + + case AlignedLongCall: + case AlignedLongJump: { + uint32_t* p = static_cast(returnAddress) - 4; + *reinterpret_cast(unha16(p[0] & 0xFFFF, p[1] & 0xFFFF)) + = newTarget; } break; default: abort(&c); @@ -1889,13 +1988,8 @@ class MyArchitecture: public Assembler::Architecture { return 4; } - virtual uintptr_t getConstant(const void* src) { - const int32_t* p = static_cast(src); - return (p[0] << 16) | (p[1] & 0xFFFF); - } - virtual void setConstant(void* dst, uintptr_t constant) { - updateImmediate(c.s, dst, constant, BytesPerWord); + updateImmediate(c.s, dst, constant, BytesPerWord, false); } virtual unsigned alignFrameSize(unsigned sizeInWords) { @@ -2337,9 +2431,21 @@ class MyAssembler: public Assembler { memcpy(dst + b->start, c.code.data + b->offset, b->size); } + unsigned index = c.code.length(); + assert(&c, index % BytesPerWord == 0); + for (ConstantPoolEntry* e = c.constantPool; e; e = e->next) { + e->address = dst + index; + index += BytesPerWord; + } + for (Task* t = c.tasks; t; t = t->next) { t->run(&c); } + + for (ConstantPoolEntry* e = c.constantPool; e; e = e->next) { + *static_cast(e->address) = e->constant->value(); + fprintf(stderr, "constant %p at %p\n", reinterpret_cast(e->constant->value()), e->address); + } } virtual Promise* offset() { @@ -2362,6 +2468,10 @@ class MyAssembler: public Assembler { return c.code.length(); } + virtual unsigned scratchSize() { + return c.constantPoolCount * BytesPerWord; + } + virtual void dispose() { c.code.dispose(); } diff --git a/src/x86.cpp b/src/x86.cpp index bd207303e0..104a9d06c3 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2791,12 +2791,6 @@ class MyArchitecture: public Assembler::Architecture { } } - virtual uintptr_t getConstant(const void* src) { - uintptr_t v; - memcpy(&v, src, BytesPerWord); - return v; - } - virtual void setConstant(void* dst, uintptr_t constant) { memcpy(dst, &constant, BytesPerWord); } @@ -3493,6 +3487,10 @@ class MyAssembler: public Assembler { return c.code.length(); } + virtual unsigned scratchSize() { + return 0; + } + virtual void dispose() { c.code.dispose(); }