2009-03-15 18:02:36 +00:00
|
|
|
/* Copyright (c) 2008-2009, Avian Contributors
|
2008-06-25 20:53:48 +00:00
|
|
|
|
|
|
|
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. */
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
#ifndef ASSEMBLER_H
|
|
|
|
#define ASSEMBLER_H
|
|
|
|
|
|
|
|
#include "system.h"
|
|
|
|
#include "zone.h"
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
|
|
|
enum Operation {
|
2009-03-03 03:18:15 +00:00
|
|
|
Return,
|
|
|
|
LoadBarrier,
|
|
|
|
StoreStoreBarrier,
|
|
|
|
StoreLoadBarrier
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
|
|
|
|
2009-03-03 03:18:15 +00:00
|
|
|
const unsigned OperationCount = StoreLoadBarrier + 1;
|
2008-02-12 00:20:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
enum UnaryOperation {
|
2008-02-17 22:29:04 +00:00
|
|
|
Call,
|
2008-06-02 13:49:09 +00:00
|
|
|
LongCall,
|
2008-02-17 22:29:04 +00:00
|
|
|
AlignedCall,
|
|
|
|
Jump,
|
2008-06-02 13:49:09 +00:00
|
|
|
LongJump,
|
2009-04-08 00:55:43 +00:00
|
|
|
AlignedJump,
|
2008-02-11 17:21:41 +00:00
|
|
|
JumpIfLess,
|
|
|
|
JumpIfGreater,
|
|
|
|
JumpIfLessOrEqual,
|
|
|
|
JumpIfGreaterOrEqual,
|
|
|
|
JumpIfEqual,
|
2008-08-19 23:38:37 +00:00
|
|
|
JumpIfNotEqual
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
|
|
|
|
2008-08-19 23:38:37 +00:00
|
|
|
const unsigned UnaryOperationCount = JumpIfNotEqual + 1;
|
2008-02-12 00:20:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
enum BinaryOperation {
|
2008-02-12 02:06:12 +00:00
|
|
|
Move,
|
|
|
|
MoveZ,
|
2008-08-19 23:38:37 +00:00
|
|
|
Compare,
|
|
|
|
Negate
|
2008-08-16 17:45:36 +00:00
|
|
|
};
|
|
|
|
|
2008-08-19 23:38:37 +00:00
|
|
|
const unsigned BinaryOperationCount = Negate + 1;
|
2008-08-16 17:45:36 +00:00
|
|
|
|
|
|
|
enum TernaryOperation {
|
2008-06-12 16:56:48 +00:00
|
|
|
LongCompare,
|
2008-02-11 17:21:41 +00:00
|
|
|
Add,
|
|
|
|
Subtract,
|
|
|
|
Multiply,
|
|
|
|
Divide,
|
|
|
|
Remainder,
|
|
|
|
ShiftLeft,
|
|
|
|
ShiftRight,
|
|
|
|
UnsignedShiftRight,
|
|
|
|
And,
|
|
|
|
Or,
|
|
|
|
Xor
|
|
|
|
};
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
const unsigned TernaryOperationCount = Xor + 1;
|
2008-02-12 00:20:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
enum OperandType {
|
2008-04-17 02:55:38 +00:00
|
|
|
ConstantOperand,
|
|
|
|
AddressOperand,
|
|
|
|
RegisterOperand,
|
2008-04-18 03:47:42 +00:00
|
|
|
MemoryOperand
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
const unsigned OperandTypeCount = MemoryOperand + 1;
|
2008-02-12 00:20:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
const int NoRegister = -1;
|
|
|
|
|
|
|
|
class Promise {
|
|
|
|
public:
|
2008-11-27 20:59:40 +00:00
|
|
|
class Listener {
|
|
|
|
public:
|
2009-03-11 01:08:16 +00:00
|
|
|
virtual bool resolve(int64_t value, void** location) = 0;
|
2008-12-02 02:38:00 +00:00
|
|
|
|
|
|
|
Listener* next;
|
2008-11-27 20:59:40 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int64_t value() = 0;
|
|
|
|
virtual bool resolved() = 0;
|
2008-11-27 20:59:40 +00:00
|
|
|
virtual Listener* listen(unsigned) { return 0; }
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ResolvedPromise: public Promise {
|
|
|
|
public:
|
|
|
|
ResolvedPromise(int64_t value): value_(value) { }
|
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
return value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t value_;
|
|
|
|
};
|
|
|
|
|
2009-02-01 23:10:56 +00:00
|
|
|
class ShiftMaskPromise: public Promise {
|
|
|
|
public:
|
|
|
|
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
|
|
|
|
base(base), shift(shift), mask(mask)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
return (base->value() >> shift) & mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return base->resolved();
|
|
|
|
}
|
|
|
|
|
|
|
|
Promise* base;
|
|
|
|
unsigned shift;
|
|
|
|
int64_t mask;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CombinedPromise: public Promise {
|
|
|
|
public:
|
|
|
|
CombinedPromise(Promise* low, Promise* high):
|
|
|
|
low(low), high(high)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
return low->value() | (high->value() << 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return low->resolved() and high->resolved();
|
|
|
|
}
|
|
|
|
|
|
|
|
Promise* low;
|
|
|
|
Promise* high;
|
|
|
|
};
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
class ListenPromise: public Promise {
|
2008-11-23 23:58:01 +00:00
|
|
|
public:
|
2008-11-27 20:59:40 +00:00
|
|
|
ListenPromise(System* s, Allocator* allocator):
|
|
|
|
s(s), allocator(allocator), listener(0)
|
|
|
|
{ }
|
2008-11-23 23:58:01 +00:00
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
virtual Listener* listen(unsigned sizeInBytes) {
|
2008-12-02 02:38:00 +00:00
|
|
|
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
|
|
|
l->next = listener;
|
|
|
|
listener = l;
|
|
|
|
return l;
|
2008-11-23 23:58:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
2008-11-27 20:59:40 +00:00
|
|
|
Allocator* allocator;
|
|
|
|
Listener* listener;
|
2008-12-02 16:45:20 +00:00
|
|
|
Promise* promise;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DelayedPromise: public ListenPromise {
|
|
|
|
public:
|
|
|
|
DelayedPromise(System* s, Allocator* allocator, Promise* basis,
|
|
|
|
DelayedPromise* next):
|
|
|
|
ListenPromise(s, allocator), basis(basis), next(next)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Listener* listen(unsigned sizeInBytes) {
|
|
|
|
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
|
|
|
|
l->next = listener;
|
|
|
|
listener = l;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
Promise* basis;
|
|
|
|
DelayedPromise* next;
|
2008-11-23 23:58:01 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Assembler {
|
|
|
|
public:
|
|
|
|
class Operand { };
|
|
|
|
|
|
|
|
class Constant: public Operand {
|
|
|
|
public:
|
|
|
|
Constant(Promise* value): value(value) { }
|
|
|
|
|
|
|
|
Promise* value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Address: public Operand {
|
|
|
|
public:
|
|
|
|
Address(Promise* address): address(address) { }
|
|
|
|
|
|
|
|
Promise* address;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Register: public Operand {
|
|
|
|
public:
|
|
|
|
Register(int low, int high = NoRegister): low(low), high(high) { }
|
|
|
|
|
|
|
|
int low;
|
|
|
|
int high;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Memory: public Operand {
|
|
|
|
public:
|
2008-04-13 19:48:20 +00:00
|
|
|
Memory(int base, int offset, int index = NoRegister, unsigned scale = 0):
|
|
|
|
base(base), offset(offset), index(index), scale(scale)
|
2008-02-11 17:21:41 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
int base;
|
|
|
|
int offset;
|
|
|
|
int index;
|
|
|
|
unsigned scale;
|
|
|
|
};
|
|
|
|
|
2008-03-13 23:43:11 +00:00
|
|
|
class Client {
|
|
|
|
public:
|
2008-05-06 21:13:02 +00:00
|
|
|
virtual int acquireTemporary
|
|
|
|
(uint32_t mask = ~static_cast<uint32_t>(0)) = 0;
|
2008-03-13 23:43:11 +00:00
|
|
|
virtual void releaseTemporary(int r) = 0;
|
2008-04-27 20:15:18 +00:00
|
|
|
|
|
|
|
virtual void save(int r) = 0;
|
2008-03-13 23:43:11 +00:00
|
|
|
};
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
class Block {
|
|
|
|
public:
|
|
|
|
virtual unsigned resolve(unsigned start, Block* next) = 0;
|
|
|
|
};
|
|
|
|
|
2008-08-17 19:32:40 +00:00
|
|
|
class Architecture {
|
|
|
|
public:
|
|
|
|
virtual unsigned registerCount() = 0;
|
2008-03-13 23:43:11 +00:00
|
|
|
|
2008-08-17 19:32:40 +00:00
|
|
|
virtual int stack() = 0;
|
|
|
|
virtual int thread() = 0;
|
2009-02-28 21:20:43 +00:00
|
|
|
virtual int returnLow() = 0;
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual int returnHigh() = 0;
|
2009-05-03 20:57:11 +00:00
|
|
|
virtual int virtualCallTarget() = 0;
|
2009-04-19 22:36:11 +00:00
|
|
|
virtual int virtualCallIndex() = 0;
|
2008-08-23 18:04:36 +00:00
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
virtual bool condensedAddressing() = 0;
|
|
|
|
|
2009-03-01 19:28:17 +00:00
|
|
|
virtual bool bigEndian() = 0;
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual bool reserved(int register_) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2009-04-25 17:49:56 +00:00
|
|
|
virtual unsigned frameFootprint(unsigned footprint) = 0;
|
2009-02-26 03:49:42 +00:00
|
|
|
virtual unsigned argumentFootprint(unsigned footprint) = 0;
|
2008-08-17 19:32:40 +00:00
|
|
|
virtual unsigned argumentRegisterCount() = 0;
|
|
|
|
virtual int argumentRegister(unsigned index) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2009-04-25 17:49:56 +00:00
|
|
|
virtual unsigned stackAlignmentInWords() = 0;
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
virtual bool matchCall(void* returnAddress, void* target) = 0;
|
|
|
|
|
2009-02-09 23:22:01 +00:00
|
|
|
virtual void updateCall(UnaryOperation op, bool assertAlignment,
|
|
|
|
void* returnAddress, void* newTarget) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2009-03-10 00:52:09 +00:00
|
|
|
virtual uintptr_t getConstant(const void* src) = 0;
|
|
|
|
virtual void setConstant(void* dst, uintptr_t constant) = 0;
|
|
|
|
|
2008-08-17 19:32:40 +00:00
|
|
|
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
|
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
virtual void* frameIp(void* stack) = 0;
|
|
|
|
virtual unsigned frameHeaderSize() = 0;
|
2008-11-08 22:36:38 +00:00
|
|
|
virtual unsigned frameReturnAddressSize() = 0;
|
2008-08-18 15:23:01 +00:00
|
|
|
virtual unsigned frameFooterSize() = 0;
|
2009-04-22 01:39:25 +00:00
|
|
|
virtual int returnAddressOffset() = 0;
|
|
|
|
virtual int framePointerOffset() = 0;
|
2008-08-18 15:23:01 +00:00
|
|
|
virtual void nextFrame(void** stack, void** base) = 0;
|
2008-08-17 19:32:40 +00:00
|
|
|
|
|
|
|
virtual void plan
|
|
|
|
(UnaryOperation op,
|
|
|
|
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
|
|
|
bool* thunk) = 0;
|
|
|
|
|
|
|
|
virtual void plan
|
|
|
|
(BinaryOperation op,
|
|
|
|
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
|
|
|
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
|
|
|
|
bool* thunk) = 0;
|
|
|
|
|
|
|
|
virtual void plan
|
|
|
|
(TernaryOperation op,
|
|
|
|
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
|
|
|
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
|
|
|
|
unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask,
|
|
|
|
bool* thunk) = 0;
|
2008-08-16 18:46:14 +00:00
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
virtual void acquire() = 0;
|
|
|
|
virtual void release() = 0;
|
2008-08-17 19:32:40 +00:00
|
|
|
};
|
2008-07-05 20:21:13 +00:00
|
|
|
|
2008-08-17 19:32:40 +00:00
|
|
|
virtual void setClient(Client* client) = 0;
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual Architecture* arch() = 0;
|
|
|
|
|
2008-09-05 15:00:38 +00:00
|
|
|
virtual void saveFrame(unsigned stackOffset, unsigned baseOffset) = 0;
|
|
|
|
virtual void pushFrame(unsigned argumentCount, ...) = 0;
|
|
|
|
virtual void allocateFrame(unsigned footprint) = 0;
|
|
|
|
virtual void popFrame() = 0;
|
2009-04-19 22:36:11 +00:00
|
|
|
virtual void popFrameForTailCall(unsigned footprint, int offset,
|
|
|
|
int returnAddressSurrogate,
|
|
|
|
int framePointerSurrogate) = 0;
|
|
|
|
virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint)
|
|
|
|
= 0;
|
2009-04-25 17:49:56 +00:00
|
|
|
virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread)
|
|
|
|
= 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
virtual void apply(Operation op) = 0;
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
virtual void apply(UnaryOperation op,
|
|
|
|
unsigned aSize, OperandType aType, Operand* aOperand) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
virtual void apply(BinaryOperation op,
|
|
|
|
unsigned aSize, OperandType aType, Operand* aOperand,
|
|
|
|
unsigned bSize, OperandType bType, Operand* bOperand) = 0;
|
|
|
|
|
|
|
|
virtual void apply(TernaryOperation op,
|
|
|
|
unsigned aSize, OperandType aType, Operand* aOperand,
|
|
|
|
unsigned bSize, OperandType bType, Operand* bOperand,
|
|
|
|
unsigned cSize, OperandType cType, Operand* cOperand) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
virtual void writeTo(uint8_t* dst) = 0;
|
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
virtual Promise* offset() = 0;
|
2008-08-30 20:12:27 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
virtual Block* endBlock(bool startNew) = 0;
|
2008-08-30 20:12:27 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual unsigned length() = 0;
|
|
|
|
|
|
|
|
virtual void dispose() = 0;
|
|
|
|
};
|
|
|
|
|
2008-08-17 19:32:40 +00:00
|
|
|
Assembler::Architecture*
|
|
|
|
makeArchitecture(System* system);
|
|
|
|
|
2008-08-19 23:38:37 +00:00
|
|
|
Assembler*
|
|
|
|
makeAssembler(System* system, Allocator* allocator, Zone* zone,
|
|
|
|
Assembler::Architecture* architecture);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
} // namespace vm
|
|
|
|
|
|
|
|
#endif//ASSEMBLER_H
|