enable Linux PowerPC build

This commit is contained in:
Joel Dice 2011-02-26 12:45:22 -07:00
parent 944e223335
commit 9e1ee7e974
10 changed files with 206 additions and 78 deletions

View File

@ -3,7 +3,11 @@ MAKEFLAGS = -s
name = avian
version = 0.4
build-arch := $(shell uname -m | sed 's/^i.86$$/i386/' | sed 's/^arm.*$$/arm/')
build-arch := $(shell uname -m \
| sed 's/^i.86$$/i386/' \
| sed 's/^arm.*$$/arm/' \
| sed 's/ppc/powerpc/')
ifeq (Power,$(filter Power,$(build-arch)))
build-arch = powerpc
endif

View File

@ -35,6 +35,7 @@
#define EV_CURRENT 1
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define ELFOSABI_SYSV 0
@ -43,6 +44,7 @@
#define EM_386 3
#define EM_X86_64 62
#define EM_ARM 40
#define EM_PPC 20
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
@ -77,7 +79,6 @@
# error
#endif
#define Data ELFDATA2LSB
#define OSABI ELFOSABI_SYSV
namespace {
@ -178,7 +179,7 @@ void
writeObject(const uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* sectionName, unsigned sectionFlags,
unsigned alignment, int machine)
unsigned alignment, int machine, int encoding)
{
const unsigned sectionCount = 5;
const unsigned symbolCount = 2;
@ -222,7 +223,7 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
fileHeader.e_ident[EI_MAG2] = ELFMAG2;
fileHeader.e_ident[EI_MAG3] = ELFMAG3;
fileHeader.e_ident[EI_CLASS] = Class;
fileHeader.e_ident[EI_DATA] = Data;
fileHeader.e_ident[EI_DATA] = encoding;
fileHeader.e_ident[EI_VERSION] = EV_CURRENT;
fileHeader.e_ident[EI_OSABI] = OSABI;
fileHeader.e_ident[EI_ABIVERSION] = 0;
@ -349,12 +350,19 @@ MAKE_NAME(writeElf, BITS_PER_WORD, Object)
bool writable, bool executable)
{
int machine;
int encoding;
if (strcmp(architecture, "x86_64") == 0) {
machine = EM_X86_64;
encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "i386") == 0) {
machine = EM_386;
encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "arm") == 0) {
machine = EM_ARM;
encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "powerpc") == 0) {
machine = EM_PPC;
encoding = ELFDATA2MSB;
} else {
fprintf(stderr, "unsupported architecture: %s\n", architecture);
return false;
@ -376,7 +384,7 @@ MAKE_NAME(writeElf, BITS_PER_WORD, Object)
}
writeObject(data, size, out, startName, endName, sectionName, sectionFlags,
alignment, machine);
alignment, machine, encoding);
return true;
}

View File

@ -73,8 +73,10 @@ writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
success = writeElf64Object
(data, size, out, startName, endName, architecture, alignment,
writable, executable);
} else if (strcmp("i386", architecture) == 0 ||
strcmp("arm", architecture) == 0) {
} else if (strcmp("i386", architecture) == 0
or strcmp("arm", architecture) == 0
or strcmp("powerpc", architecture) == 0)
{
found = true;
success = writeElf32Object
(data, size, out, startName, endName, architecture, alignment,

View File

@ -88,7 +88,7 @@ alias(void* p, unsigned offset)
# define ARCH_x86_32
# elif defined __x86_64__
# define ARCH_x86_64
# elif defined __POWERPC__
# elif (defined __POWERPC__) || (defined __powerpc__)
# define ARCH_powerpc
# elif defined __arm__
# define ARCH_arm

View File

@ -13,16 +13,21 @@
.text
#define BYTES_PER_WORD 4
#define LINKAGE_AREA 6
#define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA
#define LOCAL(x) L##x
#ifdef __APPLE__
# define GLOBAL(x) _##x
# define LOCAL(x) L##x
# define LINKAGE_AREA 6
# define RETURN_ADDRESS_OFFSET 8
#else
# define GLOBAL(x) x
# define GLOBAL(x) x
# define LOCAL(x) .L##x
# define LINKAGE_AREA 2
# define RETURN_ADDRESS_OFFSET 4
# include "powerpc-regs.S"
#endif
#define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA
#define THREAD_STACK 2148
#define THREAD_CONTINUATION 2156
@ -42,7 +47,7 @@
GLOBAL(vmInvoke):
// save return address
mflr r0
stw r0,8(r1)
stw r0,RETURN_ADDRESS_OFFSET(r1)
// r3: thread
// r4: function
@ -53,12 +58,10 @@ GLOBAL(vmInvoke):
// r9: temporary
// save return type
stw r8,44(r1)
// allocate stack space, adding room for callee-saved registers
// allocate stack space, adding room for callee-saved registers and
// return type
subfic r9,r7,-80
stwux r1,r1,r9
stwux r1,r1,r9
// save callee-saved registers
add r9,r7,r1
@ -83,6 +86,9 @@ GLOBAL(vmInvoke):
stw r30,68(r9)
stw r31,72(r9)
// save return type
stw r8,74(r9)
// we use r13 to hold the thread pointer, by convention
mr r13,r3
@ -213,11 +219,11 @@ LOCAL(vmInvoke_exit):
lwz r31,72(r9)
// handle return value based on expected type
lwz r8,44(r1)
lwz r8,74(r9)
LOCAL(vmInvoke_return):
// load return address
lwz r0,8(r1)
lwz r0,RETURN_ADDRESS_OFFSET(r1)
mtlr r0
// return

View File

@ -2171,9 +2171,9 @@ class MemorySite: public Site {
}
virtual Site* makeNextWord(Context* c, unsigned index) {
// todo: endianness?
return memorySite
(c, base, offset + (index == 1 ? BytesPerWord : -BytesPerWord),
(c, base, offset + ((index == 1) xor c->arch->bigEndian()
? BytesPerWord : -BytesPerWord),
this->index, scale);
}
@ -2184,12 +2184,11 @@ class MemorySite: public Site {
}
virtual SiteMask nextWordMask(Context* c, unsigned index) {
// todo: endianness?
int frameIndex;
if (base == c->arch->stack()) {
assert(c, this->index == NoRegister);
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
+ (index == 1 ? 1 : -1);
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
} else {
frameIndex = NoFrameIndex;
}

64
src/powerpc-regs.S Normal file
View File

@ -0,0 +1,64 @@
#define r0 0
#define r1 1
#define r2 2
#define r3 3
#define r4 4
#define r5 5
#define r6 6
#define r7 7
#define r8 8
#define r9 9
#define r10 10
#define r11 11
#define r12 12
#define r13 13
#define r14 14
#define r15 15
#define r16 16
#define r17 17
#define r18 18
#define r19 19
#define r20 20
#define r21 21
#define r22 22
#define r23 23
#define r24 24
#define r25 25
#define r26 26
#define r27 27
#define r28 28
#define r29 29
#define r30 30
#define r31 31
#define f0 0
#define f1 1
#define f2 2
#define f3 3
#define f4 4
#define f5 5
#define f6 6
#define f7 7
#define f8 8
#define f9 9
#define f10 10
#define f11 11
#define f12 12
#define f13 13
#define f14 14
#define f15 15
#define f16 16
#define f17 17
#define f18 18
#define f19 19
#define f20 20
#define f21 21
#define f22 22
#define f23 23
#define f24 24
#define f25 25
#define f26 26
#define f27 27
#define f28 28
#define f29 29
#define f30 30
#define f31 31

View File

@ -13,22 +13,28 @@
.text
#define BYTES_PER_WORD 4
#define LINKAGE_AREA 6
#define GPR_COUNT 8
#define MEMORY_BASE BYTES_PER_WORD * (LINKAGE_AREA + GPR_COUNT)
#define LOCAL(x) L##x
#ifdef __APPLE__
# define GLOBAL(x) _##x
# define LOCAL(x) L##x
# define LINKAGE_AREA 6
# define MEMORY_BASE BYTES_PER_WORD * (LINKAGE_AREA + GPR_COUNT)
# define RETURN_ADDRESS_OFFSET 8
#else
# define GLOBAL(x) x
# define GLOBAL(x) x
# define LOCAL(x) .L##x
# define LINKAGE_AREA 2
# define MEMORY_BASE BYTES_PER_WORD * LINKAGE_AREA
# define RETURN_ADDRESS_OFFSET 4
# include "powerpc-regs.S"
#endif
.globl GLOBAL(vmNativeCall)
GLOBAL(vmNativeCall):
// save return address
mflr r0
stw r0,8(r1)
stw r0,RETURN_ADDRESS_OFFSET(r1)
// r3 aka r13: function
// r4 : stackTotal
@ -42,17 +48,26 @@ GLOBAL(vmNativeCall):
// r16 : temporary
// r17 : temporary
// r18 : temporary
// save registers used for local variables
stw r13,24(r1)
stw r14,28(r1)
stw r15,32(r1)
stw r16,36(r1)
stw r17,40(r1)
stw r18,44(r1)
// allocate stack space
stwux r1,r1,r4
// allocate stack space, adding room for callee-saved registers and
// scratch space for copying a FP return value into GPRs
subfic r10,r4,-48
stwux r1,r1,r10
// save callee-saved registers used for local variables
add r10,r4,r1
// save registers used for local variables
stw r13,0(r10)
stw r14,4(r10)
stw r15,8(r10)
stw r16,12(r10)
stw r17,16(r10)
stw r18,20(r10)
stw r19,24(r10)
// remember where we saved the local variables
mr r19,r10
// save our argument registers so we can clobber them
mr r13,r3
@ -84,12 +99,14 @@ LOCAL(test):
lfd f6,40(r8)
lfd f7,48(r8)
lfd f8,56(r8)
#ifdef __APPLE__
lfd f9,64(r8)
lfd f10,72(r8)
lfd f11,80(r8)
lfd f12,88(r8)
lfd f13,96(r8)
#endif
LOCAL(gpr):
// do we need to load the general-purpose registers?
cmpwi r7,0
@ -128,25 +145,26 @@ LOCAL(float):
LOCAL(copy):
// move floating point return value to GPRs via memory
stfd f1,8(r1)
lwz r3,8(r1)
lwz r4,12(r1)
stfd f1,32(r19)
lwz r3,32(r19)
lwz r4,36(r19)
b LOCAL(exit)
LOCAL(exit):
// restore callee-saved registers used for local variables
lwz r13,0(r19)
lwz r14,4(r19)
lwz r15,8(r19)
lwz r16,12(r19)
lwz r17,16(r19)
lwz r18,20(r19)
lwz r19,24(r19)
// restore stack pointer
lwz r1,0(r1)
// restore registers used for local variables
lwz r13,24(r1)
lwz r14,28(r1)
lwz r15,32(r1)
lwz r16,36(r1)
lwz r17,40(r1)
lwz r18,44(r1)
// load return address
lwz r0,8(r1)
lwz r0,RETURN_ADDRESS_OFFSET(r1)
mtlr r0
// return
@ -171,7 +189,7 @@ GLOBAL(vmRun):
// r5: checkpoint
mflr r0
stw r0,8(r1)
stw r0,RETURN_ADDRESS_OFFSET(r1)
stwu r1,-(MEMORY_BASE+88)(r1)
@ -226,6 +244,6 @@ GLOBAL(vmRun_returnAddress):
lwz r31,MEMORY_BASE+72(r1)
lwz r1,0(r1)
lwz r0,8(r1)
lwz r0,RETURN_ADDRESS_OFFSET(r1)
mtlr r0
blr

View File

@ -162,7 +162,15 @@ carry16(intptr_t v)
return static_cast<int16_t>(v) < 0 ? 1 : 0;
}
#ifdef __APPLE__
const unsigned FrameFooterSize = 6;
const unsigned ReturnAddressOffset = 2;
const unsigned AlignArguments = false;
#else
const unsigned FrameFooterSize = 2;
const unsigned ReturnAddressOffset = 1;
const unsigned AlignArguments = true;
#endif
const unsigned StackAlignmentInBytes = 16;
const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord;
@ -1777,7 +1785,7 @@ nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size,
// todo: check for and handle tail calls
}
*ip = static_cast<void**>(*stack)[offset + 2];
*ip = static_cast<void**>(*stack)[offset + ReturnAddressOffset];
*stack = static_cast<void**>(*stack) + offset;
}
@ -1940,7 +1948,7 @@ class MyArchitecture: public Assembler::Architecture {
}
virtual bool argumentAlignment() {
return false;
return AlignArguments;
}
virtual unsigned argumentRegisterCount() {
@ -2023,7 +2031,7 @@ class MyArchitecture: public Assembler::Architecture {
}
virtual void* frameIp(void* stack) {
return stack ? static_cast<void**>(stack)[2] : 0;
return stack ? static_cast<void**>(stack)[ReturnAddressOffset] : 0;
}
virtual unsigned frameHeaderSize() {
@ -2039,7 +2047,7 @@ class MyArchitecture: public Assembler::Architecture {
}
virtual int returnAddressOffset() {
return 8 / BytesPerWord;
return ReturnAddressOffset;
}
virtual int framePointerOffset() {
@ -2261,7 +2269,7 @@ class MyAssembler: public Assembler {
Register returnAddress(0);
emit(&c, mflr(returnAddress.low));
Memory returnAddressDst(StackRegister, 8);
Memory returnAddressDst(StackRegister, ReturnAddressOffset * BytesPerWord);
moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst);
Register stack(StackRegister);
@ -2314,7 +2322,7 @@ class MyAssembler: public Assembler {
Register returnAddress(0);
emit(&c, mflr(returnAddress.low));
Memory returnAddressDst(StackRegister, 8);
Memory returnAddressDst(StackRegister, ReturnAddressOffset * BytesPerWord);
moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst);
Register stack(StackRegister);
@ -2337,7 +2345,7 @@ class MyAssembler: public Assembler {
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack);
Register returnAddress(0);
Memory returnAddressSrc(StackRegister, 8);
Memory returnAddressSrc(StackRegister, ReturnAddressOffset * BytesPerWord);
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress);
emit(&c, mtlr(returnAddress.low));
@ -2351,7 +2359,8 @@ class MyAssembler: public Assembler {
if (TailCalls) {
if (offset) {
Register tmp(0);
Memory returnAddressSrc(StackRegister, 8 + (footprint * BytesPerWord));
Memory returnAddressSrc
(StackRegister, (ReturnAddressOffset + footprint) * BytesPerWord);
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &tmp);
emit(&c, mtlr(tmp.low));
@ -2366,7 +2375,8 @@ class MyAssembler: public Assembler {
assert(&c, offset > 0);
Register ras(returnAddressSurrogate);
Memory dst(StackRegister, 8 + (offset * BytesPerWord));
Memory dst
(StackRegister, (ReturnAddressOffset + offset) * BytesPerWord);
moveRM(&c, BytesPerWord, &ras, BytesPerWord, &dst);
}

View File

@ -14,8 +14,6 @@
#include "types.h"
#include "common.h"
#define VA_LIST(x) (&(x))
#ifdef __APPLE__
# include "mach/mach_types.h"
# include "mach/ppc/thread_act.h"
@ -45,9 +43,17 @@
# define LINK_REGISTER(context) \
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
#else
# error "non-Apple PowerPC-based platforms not yet supported"
#endif
#define VA_LIST(x) (&(x))
#else // not __APPLE__
# define IP_REGISTER(context) (context->uc_mcontext.regs->gpr[32])
# define STACK_REGISTER(context) (context->uc_mcontext.regs->gpr[1])
# define THREAD_REGISTER(context) (context->uc_mcontext.regs->gpr[13])
# define LINK_REGISTER(context) (context->uc_mcontext.regs->gpr[36])
#define VA_LIST(x) (x)
#endif // not __APPLE__
extern "C" uint64_t
vmNativeCall(void* function, unsigned stackTotal, void* memoryTable,
@ -150,13 +156,22 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned argumentCount, unsigned argumentsSize,
unsigned returnType)
{
#ifdef __APPLE__
# define SKIP(var, count) var += count;
# define ALIGN(var)
const unsigned LinkageArea = 24;
const unsigned FprCount = 13;
#else
# define SKIP(var, count)
# define ALIGN(var) if (var & 1) ++var;
const unsigned LinkageArea = 8;
const unsigned FprCount = 8;
#endif
const unsigned GprCount = 8;
uintptr_t gprTable[GprCount];
unsigned gprIndex = 0;
const unsigned FprCount = 13;
uint64_t fprTable[FprCount];
unsigned fprIndex = 0;
@ -172,8 +187,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
double d = bitsToFloat(arguments[ai]);
memcpy(fprTable + fprIndex, &d, 8);
++ fprIndex;
++ gprIndex;
++ stackSkip;
SKIP(gprIndex, 1);
SKIP(stackSkip, 1);
} else {
stack[stackIndex++] = arguments[ai];
}
@ -184,9 +199,10 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
if (fprIndex + (8 / BytesPerWord) <= FprCount) {
memcpy(fprTable + fprIndex, arguments + ai, 8);
++ fprIndex;
gprIndex += 8 / BytesPerWord;
stackSkip += 8 / BytesPerWord;
SKIP(gprIndex, 8 / BytesPerWord);
SKIP(stackSkip, 8 / BytesPerWord);
} else {
ALIGN(stackIndex);
memcpy(stack + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
}
@ -195,10 +211,12 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
case INT64_TYPE: {
if (gprIndex + (8 / BytesPerWord) <= GprCount) {
ALIGN(gprIndex);
memcpy(gprTable + gprIndex, arguments + ai, 8);
gprIndex += 8 / BytesPerWord;
stackSkip += 8 / BytesPerWord;
SKIP(stackSkip, 8 / BytesPerWord);
} else {
ALIGN(stackIndex);
memcpy(stack + stackIndex, arguments + ai, 8);
stackIndex += 8 / BytesPerWord;
}
@ -208,7 +226,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
default: {
if (gprIndex < GprCount) {
gprTable[gprIndex++] = arguments[ai];
++ stackSkip;
SKIP(stackSkip, 1);
} else {
stack[stackIndex++] = arguments[ai];
}
@ -219,8 +237,7 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
return vmNativeCall
(function,
- ((((1 + stackSkip + stackIndex) * BytesPerWord) + LinkageArea + 15)
& -16),
(((1 + stackSkip + stackIndex) * BytesPerWord) + LinkageArea + 15) & -16,
stack, stackIndex * BytesPerWord,
(gprIndex ? gprTable : 0),
(fprIndex ? fprTable : 0), returnType);