mirror of
https://github.com/corda/corda.git
synced 2025-01-22 12:28:11 +00:00
further break out powerpc assembler
This commit is contained in:
parent
73dda9c26e
commit
900b447e27
File diff suppressed because it is too large
Load Diff
242
src/codegen/powerpc/fixup.cpp
Normal file
242
src/codegen/powerpc/fixup.cpp
Normal 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
|
@ -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
|
||||
|
111
src/codegen/powerpc/multimethod.cpp
Normal file
111
src/codegen/powerpc/multimethod.cpp
Normal 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
|
60
src/codegen/powerpc/multimethod.h
Normal file
60
src/codegen/powerpc/multimethod.h
Normal 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
|
1097
src/codegen/powerpc/operations.cpp
Normal file
1097
src/codegen/powerpc/operations.cpp
Normal file
File diff suppressed because it is too large
Load Diff
197
src/codegen/powerpc/operations.h
Normal file
197
src/codegen/powerpc/operations.h
Normal 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
|
23
src/codegen/powerpc/registers.h
Normal file
23
src/codegen/powerpc/registers.h
Normal 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
|
Loading…
Reference in New Issue
Block a user