mirror of
https://github.com/corda/corda.git
synced 2025-06-19 07:38:22 +00:00
handle long conditional immediate branches properly on PowerPC
Due to encoding limitations, the immediate operand of conditional branches can be no more than 32KB forward or backward. Since the JIT-compiled form of some methods can be larger than 32KB, and we also do conditional jumps to code outside the current method in some cases, we must work around this limitation. The strategy of this commit is to provide inline, intermediate jump tables where necessary. A given conditional branch whose target is too far for a direct jump will instead point to an unconditional branch in the nearest jump table which points to the actual target. Unconditional immediate branches are also limited on PowerPC, but this limit is 32MB, which is not an impediment in practice. If it does become a problem, we'll need to encode such branches using multiple instructions.
This commit is contained in:
23
src/arm.cpp
23
src/arm.cpp
@ -670,7 +670,9 @@ padding(MyBlock* b, unsigned offset)
|
||||
unsigned total = 0;
|
||||
for (PoolEvent* e = b->poolEventHead; e; e = e->next) {
|
||||
if (e->offset <= offset) {
|
||||
total += BytesPerWord;
|
||||
if (b->next) {
|
||||
total += BytesPerWord;
|
||||
}
|
||||
for (PoolOffset* o = e->poolOffsetHead; o; o = o->next) {
|
||||
total += BytesPerWord;
|
||||
}
|
||||
@ -2333,9 +2335,12 @@ class MyAssembler: public Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void writeTo(uint8_t* dst) {
|
||||
virtual void setDestination(uint8_t* dst) {
|
||||
c.result = dst;
|
||||
|
||||
}
|
||||
|
||||
virtual void write() {
|
||||
uint8_t* dst = c.result;
|
||||
unsigned dstOffset = 0;
|
||||
for (MyBlock* b = c.firstBlock; b; b = b->next) {
|
||||
if (DebugPool) {
|
||||
@ -2356,10 +2361,12 @@ class MyAssembler: public Assembler {
|
||||
o, o->offset, b);
|
||||
}
|
||||
|
||||
poolSize += BytesPerWord;
|
||||
|
||||
unsigned entry = dstOffset + poolSize;
|
||||
|
||||
if (b->next) {
|
||||
entry += BytesPerWord;
|
||||
}
|
||||
|
||||
o->entry->address = dst + entry;
|
||||
|
||||
unsigned instruction = o->block->start
|
||||
@ -2370,9 +2377,13 @@ class MyAssembler: public Assembler {
|
||||
|
||||
int32_t* p = reinterpret_cast<int32_t*>(dst + instruction);
|
||||
*p = (v & PoolOffsetMask) | ((~PoolOffsetMask) & *p);
|
||||
|
||||
poolSize += BytesPerWord;
|
||||
}
|
||||
|
||||
write4(dst + dstOffset, ::b((poolSize + BytesPerWord - 8) >> 2));
|
||||
if (b->next) {
|
||||
write4(dst + dstOffset, ::b((poolSize + BytesPerWord - 8) >> 2));
|
||||
}
|
||||
|
||||
dstOffset += poolSize + BytesPerWord;
|
||||
}
|
||||
|
Reference in New Issue
Block a user