further break out powerpc assembler

This commit is contained in:
Joshua Warner 2013-02-23 18:08:34 -07:00
parent 73dda9c26e
commit 900b447e27
8 changed files with 1862 additions and 1605 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,242 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "context.h"
#include "block.h"
#include "fixup.h"
#include "encode.h"
namespace avian {
namespace codegen {
namespace powerpc {
using namespace isa;
unsigned padding(MyBlock*, unsigned);
inline int ha16(int32_t i);
bool bounded(int right, int left, int32_t v) {
return ((v << left) >> left) == v and ((v >> right) << right) == v;
}
OffsetPromise::OffsetPromise(Context* c, MyBlock* block, unsigned offset):
c(c), block(block), offset(offset)
{ }
bool OffsetPromise::resolved() {
return block->resolved;
}
int64_t OffsetPromise::value() {
assert(c, resolved());
unsigned o = offset - block->offset;
return block->start + padding(block, o) + o;
}
Promise* offsetPromise(Context* c) {
return new(c->zone) OffsetPromise(c, c->lastBlock, c->code.length());
}
void* updateOffset(vm::System* s, uint8_t* instruction, bool conditional, int64_t value,
void* jumpAddress)
{
int32_t v = reinterpret_cast<uint8_t*>(value) - instruction;
int32_t mask;
if (conditional) {
if (not bounded(2, 16, v)) {
*static_cast<uint32_t*>(jumpAddress) = isa::b(0);
updateOffset(s, static_cast<uint8_t*>(jumpAddress), false, value, 0);
v = static_cast<uint8_t*>(jumpAddress) - instruction;
expect(s, bounded(2, 16, v));
}
mask = 0xFFFC;
} else {
expect(s, bounded(2, 6, v));
mask = 0x3FFFFFC;
}
int32_t* p = reinterpret_cast<int32_t*>(instruction);
*p = vm::targetV4((v & mask) | ((~mask) & vm::targetV4(*p)));
return instruction + 4;
}
OffsetListener::OffsetListener(vm::System* s, uint8_t* instruction, bool conditional,
void* jumpAddress):
s(s),
instruction(instruction),
jumpAddress(jumpAddress),
conditional(conditional)
{ }
bool OffsetListener::resolve(int64_t value, void** location) {
void* p = updateOffset(s, instruction, conditional, value, jumpAddress);
if (location) *location = p;
return false;
}
OffsetTask::OffsetTask(Task* next, Promise* promise, Promise* instructionOffset,
bool conditional):
Task(next),
promise(promise),
instructionOffset(instructionOffset),
jumpAddress(0),
conditional(conditional)
{ }
void OffsetTask::run(Context* c) {
if (promise->resolved()) {
updateOffset
(c->s, c->result + instructionOffset->value(), conditional,
promise->value(), jumpAddress);
} else {
new (promise->listen(sizeof(OffsetListener)))
OffsetListener(c->s, c->result + instructionOffset->value(),
conditional, jumpAddress);
}
}
JumpOffset::JumpOffset(MyBlock* block, OffsetTask* task, unsigned offset):
block(block), task(task), next(0), offset(offset)
{ }
JumpEvent::JumpEvent(JumpOffset* jumpOffsetHead, JumpOffset* jumpOffsetTail,
unsigned offset):
jumpOffsetHead(jumpOffsetHead), jumpOffsetTail(jumpOffsetTail), next(0),
offset(offset)
{ }
void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset,
bool conditional)
{
OffsetTask* task = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, conditional);
c->tasks = task;
if (conditional) {
JumpOffset* offset =
new(c->zone) JumpOffset(c->lastBlock, task, c->code.length() - c->lastBlock->offset);
if (c->lastBlock->jumpOffsetTail) {
c->lastBlock->jumpOffsetTail->next = offset;
} else {
c->lastBlock->jumpOffsetHead = offset;
}
c->lastBlock->jumpOffsetTail = offset;
}
}
void appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head,
JumpOffset* tail)
{
JumpEvent* e = new(c->zone) JumpEvent
(head, tail, offset);
if (b->jumpEventTail) {
b->jumpEventTail->next = e;
} else {
b->jumpEventHead = e;
}
b->jumpEventTail = e;
}
ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) {
return new (c->zone) ShiftMaskPromise(base, shift, mask);
}
void
updateImmediate(vm::System* s, void* dst, int32_t src, unsigned size, bool address)
{
switch (size) {
case 4: {
int32_t* p = static_cast<int32_t*>(dst);
int r = (vm::targetV4(p[1]) >> 21) & 31;
if (address) {
p[0] = vm::targetV4(lis(r, ha16(src)));
p[1] |= vm::targetV4(src & 0xFFFF);
} else {
p[0] = vm::targetV4(lis(r, src >> 16));
p[1] = vm::targetV4(ori(r, r, src));
}
} break;
default: abort(s);
}
}
ImmediateListener::ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset,
bool address):
s(s), dst(dst), size(size), offset(offset), address(address)
{ }
bool ImmediateListener::resolve(int64_t value, void** location) {
updateImmediate(s, dst, value, size, address);
if (location) *location = static_cast<uint8_t*>(dst) + offset;
return false;
}
ImmediateTask::ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size,
unsigned promiseOffset, bool address):
Task(next),
promise(promise),
offset(offset),
size(size),
promiseOffset(promiseOffset),
address(address)
{ }
void ImmediateTask::run(Context* c) {
if (promise->resolved()) {
updateImmediate
(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, address);
}
}
void
appendImmediateTask(Context* c, Promise* promise, Promise* offset,
unsigned size, unsigned promiseOffset, bool address)
{
c->tasks = new(c->zone) ImmediateTask(c->tasks, promise, offset, size, promiseOffset, address);
}
ConstantPoolEntry::ConstantPoolEntry(Context* c, Promise* constant):
c(c), constant(constant), next(c->constantPool), address(0)
{
c->constantPool = this;
++ c->constantPoolCount;
}
int64_t ConstantPoolEntry::value() {
assert(c, resolved());
return reinterpret_cast<intptr_t>(address);
}
bool ConstantPoolEntry::resolved() {
return address != 0;
}
ConstantPoolEntry* appendConstantPoolEntry(Context* c, Promise* constant) {
return new (c->zone) ConstantPoolEntry(c, constant);
}
} // namespace powerpc
} // namespace codegen
} // namespace avian

View File

@ -25,6 +25,134 @@ class Task {
Task* next;
};
class OffsetPromise: public Promise {
public:
OffsetPromise(Context* c, MyBlock* block, unsigned offset);
virtual bool resolved();
virtual int64_t value();
Context* c;
MyBlock* block;
unsigned offset;
};
Promise* offsetPromise(Context* c);
void*
updateOffset(vm::System* s, uint8_t* instruction, bool conditional, int64_t value,
void* jumpAddress);
class OffsetListener: public Promise::Listener {
public:
OffsetListener(vm::System* s, uint8_t* instruction, bool conditional,
void* jumpAddress);
virtual bool resolve(int64_t value, void** location);
vm::System* s;
uint8_t* instruction;
void* jumpAddress;
bool conditional;
};
class OffsetTask: public Task {
public:
OffsetTask(Task* next, Promise* promise, Promise* instructionOffset,
bool conditional);
virtual void run(Context* c);
Promise* promise;
Promise* instructionOffset;
void* jumpAddress;
bool conditional;
};
class JumpOffset {
public:
JumpOffset(MyBlock* block, OffsetTask* task, unsigned offset);
MyBlock* block;
OffsetTask* task;
JumpOffset* next;
unsigned offset;
};
class JumpEvent {
public:
JumpEvent(JumpOffset* jumpOffsetHead, JumpOffset* jumpOffsetTail,
unsigned offset);
JumpOffset* jumpOffsetHead;
JumpOffset* jumpOffsetTail;
JumpEvent* next;
unsigned offset;
};
void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset,
bool conditional);
void appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head,
JumpOffset* tail);
ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
void updateImmediate(vm::System* s, void* dst, int32_t src, unsigned size, bool address);
class ImmediateListener: public Promise::Listener {
public:
ImmediateListener(vm::System* s, void* dst, unsigned size, unsigned offset,
bool address);
virtual bool resolve(int64_t value, void** location);
vm::System* s;
void* dst;
unsigned size;
unsigned offset;
bool address;
};
class ImmediateTask: public Task {
public:
ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size,
unsigned promiseOffset, bool address);
virtual void run(Context* c);
Promise* promise;
Promise* offset;
unsigned size;
unsigned promiseOffset;
bool address;
};
void
appendImmediateTask(Context* c, Promise* promise, Promise* offset,
unsigned size, unsigned promiseOffset, bool address);
class ConstantPoolEntry: public Promise {
public:
ConstantPoolEntry(Context* c, Promise* constant);
virtual int64_t value();
virtual bool resolved();
Context* c;
Promise* constant;
ConstantPoolEntry* next;
void* address;
};
ConstantPoolEntry* appendConstantPoolEntry(Context* c, Promise* constant);
inline int ha16(int32_t i) {
return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff;
}
} // namespace powerpc
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,111 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "context.h"
#include "block.h"
#include "common.h"
#include "operations.h"
#include "multimethod.h"
namespace avian {
namespace codegen {
namespace powerpc {
void populateTables(ArchitectureContext* c) {
const lir::OperandType C = lir::ConstantOperand;
const lir::OperandType A = lir::AddressOperand;
const lir::OperandType R = lir::RegisterOperand;
const lir::OperandType M = lir::MemoryOperand;
OperationType* zo = c->operations;
UnaryOperationType* uo = c->unaryOperations;
BinaryOperationType* bo = c->binaryOperations;
TernaryOperationType* to = c->ternaryOperations;
BranchOperationType* bro = c->branchOperations;
zo[lir::Return] = return_;
zo[lir::LoadBarrier] = memoryBarrier;
zo[lir::StoreStoreBarrier] = memoryBarrier;
zo[lir::StoreLoadBarrier] = memoryBarrier;
zo[lir::Trap] = trap;
uo[index(c, lir::LongCall, C)] = CAST1(longCallC);
uo[index(c, lir::AlignedLongCall, C)] = CAST1(alignedLongCallC);
uo[index(c, lir::LongJump, C)] = CAST1(longJumpC);
uo[index(c, lir::AlignedLongJump, C)] = CAST1(alignedLongJumpC);
uo[index(c, lir::Jump, R)] = CAST1(jumpR);
uo[index(c, lir::Jump, C)] = CAST1(jumpC);
uo[index(c, lir::AlignedJump, R)] = CAST1(jumpR);
uo[index(c, lir::AlignedJump, C)] = CAST1(jumpC);
uo[index(c, lir::Call, C)] = CAST1(callC);
uo[index(c, lir::Call, R)] = CAST1(callR);
uo[index(c, lir::AlignedCall, C)] = CAST1(callC);
uo[index(c, lir::AlignedCall, R)] = CAST1(callR);
bo[index(c, lir::Move, R, R)] = CAST2(moveRR);
bo[index(c, lir::Move, C, R)] = CAST2(moveCR);
bo[index(c, lir::Move, C, M)] = CAST2(moveCM);
bo[index(c, lir::Move, M, R)] = CAST2(moveMR);
bo[index(c, lir::Move, R, M)] = CAST2(moveRM);
bo[index(c, lir::Move, A, R)] = CAST2(moveAR);
bo[index(c, lir::MoveZ, R, R)] = CAST2(moveZRR);
bo[index(c, lir::MoveZ, M, R)] = CAST2(moveZMR);
bo[index(c, lir::MoveZ, C, R)] = CAST2(moveCR);
bo[index(c, lir::Negate, R, R)] = CAST2(negateRR);
to[index(c, lir::Add, R)] = CAST3(addR);
to[index(c, lir::Add, C)] = CAST3(addC);
to[index(c, lir::Subtract, R)] = CAST3(subR);
to[index(c, lir::Subtract, C)] = CAST3(subC);
to[index(c, lir::Multiply, R)] = CAST3(multiplyR);
to[index(c, lir::Divide, R)] = CAST3(divideR);
to[index(c, lir::Remainder, R)] = CAST3(remainderR);
to[index(c, lir::ShiftLeft, R)] = CAST3(shiftLeftR);
to[index(c, lir::ShiftLeft, C)] = CAST3(shiftLeftC);
to[index(c, lir::ShiftRight, R)] = CAST3(shiftRightR);
to[index(c, lir::ShiftRight, C)] = CAST3(shiftRightC);
to[index(c, lir::UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR);
to[index(c, lir::UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC);
to[index(c, lir::And, C)] = CAST3(andC);
to[index(c, lir::And, R)] = CAST3(andR);
to[index(c, lir::Or, C)] = CAST3(orC);
to[index(c, lir::Or, R)] = CAST3(orR);
to[index(c, lir::Xor, C)] = CAST3(xorC);
to[index(c, lir::Xor, R)] = CAST3(xorR);
bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR);
bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR);
bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM);
bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM);
}
} // namespace powerpc
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,60 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_MULTIMETHOD_H
#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_MULTIMETHOD_H
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
#define CAST3(x) reinterpret_cast<TernaryOperationType>(x)
#define CAST_BRANCH(x) reinterpret_cast<BranchOperationType>(x)
namespace avian {
namespace codegen {
namespace powerpc {
inline unsigned index(ArchitectureContext*, lir::UnaryOperation operation, lir::OperandType operand)
{
return operation + (lir::UnaryOperationCount * operand);
}
inline unsigned index(ArchitectureContext*,
lir::BinaryOperation operation,
lir::OperandType operand1,
lir::OperandType operand2)
{
return operation
+ (lir::BinaryOperationCount * operand1)
+ (lir::BinaryOperationCount * lir::OperandTypeCount * operand2);
}
inline unsigned index(ArchitectureContext* c UNUSED,
lir::TernaryOperation operation,
lir::OperandType operand1)
{
assert(c, not isBranch(operation));
return operation + (lir::NonBranchTernaryOperationCount * operand1);
}
inline unsigned branchIndex(ArchitectureContext* c UNUSED, lir::OperandType operand1,
lir::OperandType operand2)
{
return operand1 + (lir::OperandTypeCount * operand2);
}
void populateTables(ArchitectureContext* c);
} // namespace powerpc
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_MULTIMETHOD_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_OPERATIONS_H
#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_OPERATIONS_H
#include "context.h"
namespace avian {
namespace codegen {
namespace powerpc {
inline void emit(Context* con, int code) { con->code.append4(vm::targetV4(code)); }
inline int newTemp(Context* con) { return con->client->acquireTemporary(); }
inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); }
inline int64_t getValue(lir::Constant* c) { return c->value->value(); }
void andC(Context* c, unsigned size, lir::Constant* a,
lir::Register* b, lir::Register* dst);
void shiftLeftR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
void moveRR(Context* c, unsigned srcSize, lir::Register* src,
unsigned dstSize, lir::Register* dst);
void shiftLeftC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t);
void shiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
void shiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t);
void unsignedShiftRightR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
void unsignedShiftRightC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t);
void jumpR(Context* c, unsigned size UNUSED, lir::Register* target);
void swapRR(Context* c, unsigned aSize, lir::Register* a,
unsigned bSize, lir::Register* b);
void moveRR(Context* c, unsigned srcSize, lir::Register* src,
unsigned dstSize, lir::Register* dst);
void moveZRR(Context* c, unsigned srcSize, lir::Register* src,
unsigned, lir::Register* dst);
void moveCR2(Context* c, unsigned, lir::Constant* src,
unsigned dstSize, lir::Register* dst, unsigned promiseOffset);
void moveCR(Context* c, unsigned srcSize, lir::Constant* src,
unsigned dstSize, lir::Register* dst);
void addR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
void addC(Context* con, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t);
void subR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
void subC(Context* c, unsigned size, lir::Constant* a, lir::Register* b, lir::Register* t);
void multiplyR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
void divideR(Context* con, unsigned size UNUSED, lir::Register* a, lir::Register* b, lir::Register* t);
void remainderR(Context* con, unsigned size, lir::Register* a, lir::Register* b, lir::Register* t);
int
normalize(Context* c, int offset, int index, unsigned scale,
bool* preserveIndex, bool* release);
void store(Context* c, unsigned size, lir::Register* src,
int base, int offset, int index, unsigned scale, bool preserveIndex);
void moveRM(Context* c, unsigned srcSize, lir::Register* src,
unsigned dstSize UNUSED, lir::Memory* dst);
void moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, lir::Register* src,
unsigned dstSize UNUSED, lir::Memory* dst);
void load(Context* c, unsigned srcSize, int base, int offset, int index,
unsigned scale, unsigned dstSize, lir::Register* dst,
bool preserveIndex, bool signExtend);
void moveMR(Context* c, unsigned srcSize, lir::Memory* src,
unsigned dstSize, lir::Register* dst);
void moveZMR(Context* c, unsigned srcSize, lir::Memory* src,
unsigned dstSize, lir::Register* dst);
void andR(Context* c, unsigned size, lir::Register* a,
lir::Register* b, lir::Register* dst);
void andC(Context* c, unsigned size, lir::Constant* a,
lir::Register* b, lir::Register* dst);
void orR(Context* c, unsigned size, lir::Register* a,
lir::Register* b, lir::Register* dst);
void orC(Context* c, unsigned size, lir::Constant* a,
lir::Register* b, lir::Register* dst);
void xorR(Context* c, unsigned size, lir::Register* a,
lir::Register* b, lir::Register* dst);
void xorC(Context* c, unsigned size, lir::Constant* a,
lir::Register* b, lir::Register* dst);
void moveAR2(Context* c, unsigned srcSize UNUSED, lir::Address* src,
unsigned dstSize, lir::Register* dst, unsigned promiseOffset);
void moveAR(Context* c, unsigned srcSize, lir::Address* src,
unsigned dstSize, lir::Register* dst);
void compareRR(Context* c, unsigned aSize UNUSED, lir::Register* a,
unsigned bSize UNUSED, lir::Register* b);
void compareCR(Context* c, unsigned aSize, lir::Constant* a,
unsigned bSize, lir::Register* b);
void compareCM(Context* c, unsigned aSize, lir::Constant* a,
unsigned bSize, lir::Memory* b);
void compareRM(Context* c, unsigned aSize, lir::Register* a,
unsigned bSize, lir::Memory* b);
void compareUnsignedRR(Context* c, unsigned aSize UNUSED, lir::Register* a,
unsigned bSize UNUSED, lir::Register* b);
void compareUnsignedCR(Context* c, unsigned aSize, lir::Constant* a,
unsigned bSize, lir::Register* b);
int32_t branch(Context* c, lir::TernaryOperation op);
void conditional(Context* c, int32_t branch, lir::Constant* target);
void branch(Context* c, lir::TernaryOperation op, lir::Constant* target);
void branchLong(Context* c, lir::TernaryOperation op, lir::Operand* al,
lir::Operand* ah, lir::Operand* bl,
lir::Operand* bh, lir::Constant* target,
BinaryOperationType compareSigned,
BinaryOperationType compareUnsigned);
void branchRR(Context* c, lir::TernaryOperation op, unsigned size,
lir::Register* a, lir::Register* b,
lir::Constant* target);
void branchCR(Context* c, lir::TernaryOperation op, unsigned size,
lir::Constant* a, lir::Register* b,
lir::Constant* target);
void branchRM(Context* c, lir::TernaryOperation op, unsigned size,
lir::Register* a, lir::Memory* b,
lir::Constant* target);
void branchCM(Context* c, lir::TernaryOperation op, unsigned size,
lir::Constant* a, lir::Memory* b,
lir::Constant* target);
void moveCM(Context* c, unsigned srcSize, lir::Constant* src,
unsigned dstSize, lir::Memory* dst);
void negateRR(Context* c, unsigned srcSize, lir::Register* src,
unsigned dstSize UNUSED, lir::Register* dst);
void callR(Context* c, unsigned size UNUSED, lir::Register* target);
void callC(Context* c, unsigned size UNUSED, lir::Constant* target);
void longCallC(Context* c, unsigned size UNUSED, lir::Constant* target);
void alignedLongCallC(Context* c, unsigned size UNUSED, lir::Constant* target);
void longJumpC(Context* c, unsigned size UNUSED, lir::Constant* target);
void alignedLongJumpC(Context* c, unsigned size UNUSED, lir::Constant* target);
void jumpC(Context* c, unsigned size UNUSED, lir::Constant* target);
void return_(Context* c);
void trap(Context* c);
void memoryBarrier(Context* c);
} // namespace powerpc
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_OPERATIONS_H

View File

@ -0,0 +1,23 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_ASSEMBLER_POWERPC_REGISTERS_H
#define AVIAN_CODEGEN_ASSEMBLER_POWERPC_REGISTERS_H
namespace avian {
namespace codegen {
namespace powerpc {
} // namespace powerpc
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_ASSEMBLER_POWERPC_REGISTERS_H