corda/src/x86.cpp

185 lines
3.2 KiB
C++
Raw Normal View History

2008-02-08 23:18:57 +00:00
#include "assembler.h"
2008-02-09 20:11:37 +00:00
#include "vector.h"
2008-02-08 23:18:57 +00:00
using namespace vm;
namespace {
enum Register {
rax = 0,
rcx = 1,
rdx = 2,
rbx = 3,
rsp = 4,
rbp = 5,
rsi = 6,
rdi = 7,
r8 = 8,
r9 = 9,
r10 = 10,
r11 = 11,
r12 = 12,
r13 = 13,
r14 = 14,
r15 = 15,
};
class Task {
public:
2008-02-09 20:11:37 +00:00
Task(Task* next): next(next) { }
virtual ~Task() { }
2008-02-08 23:18:57 +00:00
virtual void run(uint8_t* code) = 0;
2008-02-09 20:11:37 +00:00
Task* next;
2008-02-08 23:18:57 +00:00
};
class MyAssembler: public Assembler {
public:
2008-02-09 20:11:37 +00:00
MyAssembler(System* s, Allocator* a): s(s), code(s, a, 1024), tasks(0) { }
2008-02-08 23:18:57 +00:00
virtual unsigned registerCount() {
return BytesPerWord == 4 ? 8 : 16;
}
virtual int base() {
return rbp;
}
virtual int stack() {
return rsp;
}
virtual int thread() {
return rbx;
}
virtual int returnLow() {
return rax;
}
virtual int returnHigh() {
return (BytesPerWord == 4 ? rdx : NoRegister);
}
virtual unsigned argumentRegisterCount() {
return (BytesPerWord == 4 ? 0 : 6);
}
virtual int argumentRegister(unsigned index) {
assert(s, BytesPerWord == 8);
switch (index) {
case 0:
return rdi;
case 1:
return rsi;
case 2:
return rdx;
case 3:
return rcx;
case 4:
return r8;
case 5:
return r9;
default:
2008-02-09 20:11:37 +00:00
abort(s);
2008-02-08 23:18:57 +00:00
}
}
virtual int stackSyncRegister(unsigned index) {
switch (index) {
case 0:
return rax;
case 1:
return rcx;
case 2:
return rdx;
case 3:
return rsi;
case 4:
return rdi;
default:
2008-02-09 20:11:37 +00:00
abort(s);
2008-02-08 23:18:57 +00:00
}
}
2008-02-09 20:11:37 +00:00
virtual void getTargets(UnaryOperation /*op*/, unsigned /*size*/,
Register* r)
{
// todo
r->low = NoRegister;
r->high = NoRegister;
}
virtual void getTargets(BinaryOperation /*op*/, unsigned /*size*/,
Register* a, Register* b)
2008-02-08 23:18:57 +00:00
{
// todo
2008-02-09 20:11:37 +00:00
a->low = NoRegister;
a->high = NoRegister;
b->low = NoRegister;
b->high = NoRegister;
2008-02-08 23:18:57 +00:00
}
2008-02-09 20:11:37 +00:00
virtual void apply(Operation /*op*/) {
2008-02-08 23:18:57 +00:00
// todo
abort(s);
}
2008-02-09 20:11:37 +00:00
virtual void apply(UnaryOperation /*op*/, unsigned /*size*/,
OperandType /*type*/, Operand* /*operand*/)
2008-02-08 23:18:57 +00:00
{
// todo
abort(s);
}
2008-02-09 20:11:37 +00:00
virtual void apply(BinaryOperation /*op*/, unsigned /*size*/,
OperandType /*aType*/, Operand* /*a*/,
OperandType /*bType*/, Operand* /*b*/)
2008-02-08 23:18:57 +00:00
{
// todo
abort(s);
}
virtual void writeTo(uint8_t* dst) {
memcpy(dst, code.data, code.length());
for (Task* t = tasks; t; t = t->next) {
t->run(dst);
}
}
2008-02-09 20:11:37 +00:00
virtual unsigned length() {
return code.length();
}
virtual void updateCall(void* returnAddress, void* newTarget) {
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
assert(s, *instruction == 0xE8);
assert(s, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
int32_t v = static_cast<uint8_t*>(newTarget)
- static_cast<uint8_t*>(returnAddress);
memcpy(instruction + 1, &v, 4);
}
2008-02-08 23:18:57 +00:00
System* s;
Vector code;
Task* tasks;
};
} // namespace
namespace vm {
Assembler*
2008-02-09 20:11:37 +00:00
makeAssembler(System* system, Allocator* allocator, Zone* zone)
2008-02-08 23:18:57 +00:00
{
return new (zone->allocate(sizeof(MyAssembler)))
2008-02-09 20:11:37 +00:00
MyAssembler(system, allocator);
2008-02-08 23:18:57 +00:00
}
} // namespace vm