mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +00:00
more work on new compiler; addition now works
This commit is contained in:
parent
5b2f351f01
commit
b9fa7179d9
@ -10,6 +10,8 @@ enum Operation {
|
|||||||
Return
|
Return
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unsigned OperationCount = Return + 1;
|
||||||
|
|
||||||
enum UnaryOperation {
|
enum UnaryOperation {
|
||||||
Call,
|
Call,
|
||||||
Push,
|
Push,
|
||||||
@ -23,19 +25,18 @@ enum UnaryOperation {
|
|||||||
Negate
|
Negate
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unsigned UnaryOperationCount = Negate + 1;
|
||||||
|
|
||||||
enum BinaryOperation {
|
enum BinaryOperation {
|
||||||
LoadAddress,
|
LoadAddress,
|
||||||
Move,
|
Move1,
|
||||||
Store1,
|
Move2,
|
||||||
Store2,
|
Move4,
|
||||||
Store4,
|
Move8,
|
||||||
Store8,
|
Move1ToW,
|
||||||
Load1,
|
Move2ToW,
|
||||||
Load2,
|
Move2zToW,
|
||||||
Load2z,
|
Move4To8,
|
||||||
Load4,
|
|
||||||
Load8,
|
|
||||||
Load4To8,
|
|
||||||
Compare,
|
Compare,
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
@ -50,6 +51,10 @@ enum BinaryOperation {
|
|||||||
Xor
|
Xor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BinaryOperation Move = (BytesPerWord == 8 ? Move8 : Move4);
|
||||||
|
|
||||||
|
const unsigned BinaryOperationCount = Xor + 1;
|
||||||
|
|
||||||
enum OperandType {
|
enum OperandType {
|
||||||
Constant,
|
Constant,
|
||||||
Address,
|
Address,
|
||||||
@ -57,6 +62,8 @@ enum OperandType {
|
|||||||
Memory
|
Memory
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unsigned OperandTypeCount = Memory + 1;
|
||||||
|
|
||||||
const int NoRegister = -1;
|
const int NoRegister = -1;
|
||||||
const int AnyRegister = -2;
|
const int AnyRegister = -2;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "assembler.h"
|
#include "assembler.h"
|
||||||
#include "compiler2.h"
|
#include "compiler.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
@ -17,7 +17,7 @@ vmCall();
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool Verbose = false;
|
const bool Verbose = true;
|
||||||
const bool DebugNatives = false;
|
const bool DebugNatives = false;
|
||||||
const bool DebugTraces = false;
|
const bool DebugTraces = false;
|
||||||
const bool DebugFrameMaps = false;
|
const bool DebugFrameMaps = false;
|
||||||
@ -403,7 +403,7 @@ class Context {
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
~Context() {
|
~Context() {
|
||||||
compiler->dispose();
|
if (compiler) compiler->dispose();
|
||||||
assembler->dispose();
|
assembler->dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3414,7 +3414,9 @@ finish(MyThread* t, Assembler* a, const char* name)
|
|||||||
|
|
||||||
a->writeTo(start);
|
a->writeTo(start);
|
||||||
|
|
||||||
logCompile(start, a->length(), 0, name, 0);
|
if (Verbose) {
|
||||||
|
logCompile(start, a->length(), 0, name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "compiler2.h"
|
#include "compiler.h"
|
||||||
#include "assembler.h"
|
#include "assembler.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
@ -527,11 +527,14 @@ class ReturnEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
a->value->release(c, a);
|
if (a) {
|
||||||
|
a->value->release(c, a);
|
||||||
|
|
||||||
if (not a->target->equals(a->value)) {
|
if (not a->target->equals(a->value)) {
|
||||||
apply(c, Move, a->size, a->value, a->target);
|
apply(c, Move, a->size, a->value, a->target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c->assembler->apply(Return);
|
c->assembler->apply(Return);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,7 +746,11 @@ class MoveEvent: public Event {
|
|||||||
virtual Value* target(Context* c, MyOperand* v) {
|
virtual Value* target(Context* c, MyOperand* v) {
|
||||||
assert(c, v == src);
|
assert(c, v == src);
|
||||||
|
|
||||||
return v->event->target(c, dst);
|
if (dst->value) {
|
||||||
|
return dst->value;
|
||||||
|
} else {
|
||||||
|
return v->event->target(c, dst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
|
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
|
||||||
@ -754,7 +761,11 @@ class MoveEvent: public Event {
|
|||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
if (src->target == 0) {
|
if (src->target == 0) {
|
||||||
src->target = freeRegister(c, src->size);
|
if (dst->value) {
|
||||||
|
src->target = dst->value;
|
||||||
|
} else {
|
||||||
|
src->target = freeRegister(c, src->size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
src->value->release(c, src);
|
src->value->release(c, src);
|
||||||
@ -1127,8 +1138,14 @@ updateJunctions(Context* c)
|
|||||||
void
|
void
|
||||||
compile(Context* c)
|
compile(Context* c)
|
||||||
{
|
{
|
||||||
for (Event* e = c->logicalCode[0].firstEvent; e; e = e->next) {
|
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
||||||
e->compile(c);
|
fprintf(stderr, "compile ip %d\n", i);
|
||||||
|
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
|
||||||
|
fprintf(stderr, "compile ip %d event\n", i);
|
||||||
|
e->compile(c);
|
||||||
|
|
||||||
|
if (e == c->logicalCode[i].lastEvent) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1320,22 +1337,22 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void store1(Operand* src, Operand* dst) {
|
virtual void store1(Operand* src, Operand* dst) {
|
||||||
appendMove(&c, Store1, static_cast<MyOperand*>(src),
|
appendMove(&c, Move1, static_cast<MyOperand*>(src),
|
||||||
static_cast<MyOperand*>(dst));
|
static_cast<MyOperand*>(dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void store2(Operand* src, Operand* dst) {
|
virtual void store2(Operand* src, Operand* dst) {
|
||||||
appendMove(&c, Store2, static_cast<MyOperand*>(src),
|
appendMove(&c, Move2, static_cast<MyOperand*>(src),
|
||||||
static_cast<MyOperand*>(dst));
|
static_cast<MyOperand*>(dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void store4(Operand* src, Operand* dst) {
|
virtual void store4(Operand* src, Operand* dst) {
|
||||||
appendMove(&c, Store4, static_cast<MyOperand*>(src),
|
appendMove(&c, Move4, static_cast<MyOperand*>(src),
|
||||||
static_cast<MyOperand*>(dst));
|
static_cast<MyOperand*>(dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void store8(Operand* src, Operand* dst) {
|
virtual void store8(Operand* src, Operand* dst) {
|
||||||
appendMove(&c, Store8, static_cast<MyOperand*>(src),
|
appendMove(&c, Move8, static_cast<MyOperand*>(src),
|
||||||
static_cast<MyOperand*>(dst));
|
static_cast<MyOperand*>(dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1347,37 +1364,39 @@ class MyCompiler: public Compiler {
|
|||||||
|
|
||||||
virtual Operand* load1(Operand* src) {
|
virtual Operand* load1(Operand* src) {
|
||||||
MyOperand* dst = operand(&c, BytesPerWord);
|
MyOperand* dst = operand(&c, BytesPerWord);
|
||||||
appendMove(&c, Load1, static_cast<MyOperand*>(src), dst);
|
appendMove(&c, Move1ToW, static_cast<MyOperand*>(src), dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* load2(Operand* src) {
|
virtual Operand* load2(Operand* src) {
|
||||||
MyOperand* dst = operand(&c, BytesPerWord);
|
MyOperand* dst = operand(&c, BytesPerWord);
|
||||||
appendMove(&c, Load2, static_cast<MyOperand*>(src), dst);
|
appendMove(&c, Move2ToW, static_cast<MyOperand*>(src), dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* load2z(Operand* src) {
|
virtual Operand* load2z(Operand* src) {
|
||||||
MyOperand* dst = operand(&c, BytesPerWord);
|
MyOperand* dst = operand(&c, BytesPerWord);
|
||||||
appendMove(&c, Load2z, static_cast<MyOperand*>(src), dst);
|
appendMove(&c, Move2zToW, static_cast<MyOperand*>(src), dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* load4(Operand* src) {
|
virtual Operand* load4(Operand* src) {
|
||||||
MyOperand* dst = operand(&c, BytesPerWord);
|
if (BytesPerWord == 4) {
|
||||||
appendMove(&c, Load4, static_cast<MyOperand*>(src), dst);
|
return load(src);
|
||||||
return dst;
|
} else {
|
||||||
|
return load4To8(src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* load8(Operand* src) {
|
virtual Operand* load8(Operand* src) {
|
||||||
MyOperand* dst = operand(&c, 8);
|
MyOperand* dst = operand(&c, 8);
|
||||||
appendMove(&c, Load8, static_cast<MyOperand*>(src), dst);
|
appendMove(&c, Move8, static_cast<MyOperand*>(src), dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* load4To8(Operand* src) {
|
virtual Operand* load4To8(Operand* src) {
|
||||||
MyOperand* dst = operand(&c, 8);
|
MyOperand* dst = operand(&c, 8);
|
||||||
appendMove(&c, Load4To8, static_cast<MyOperand*>(src), dst);
|
appendMove(&c, Move4To8, static_cast<MyOperand*>(src), dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
400
src/x86.cpp
400
src/x86.cpp
@ -3,9 +3,20 @@
|
|||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
|
#define INDEX1(a, b) ((a) + (BinaryOperationCount * (b)))
|
||||||
|
|
||||||
|
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
||||||
|
|
||||||
|
#define INDEX2(a, b, c) \
|
||||||
|
((a) \
|
||||||
|
+ (BinaryOperationCount * (b)) \
|
||||||
|
+ (BinaryOperationCount * OperandTypeCount * (c)))
|
||||||
|
|
||||||
|
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum Register {
|
enum {
|
||||||
rax = 0,
|
rax = 0,
|
||||||
rcx = 1,
|
rcx = 1,
|
||||||
rdx = 2,
|
rdx = 2,
|
||||||
@ -24,20 +35,355 @@ enum Register {
|
|||||||
r15 = 15,
|
r15 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
isInt8(intptr_t v)
|
||||||
|
{
|
||||||
|
return v == static_cast<int8_t>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
isInt32(intptr_t v)
|
||||||
|
{
|
||||||
|
return v == static_cast<int32_t>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Task;
|
||||||
|
|
||||||
|
class Context {
|
||||||
|
public:
|
||||||
|
Context(System* s, Allocator* a, Zone* zone):
|
||||||
|
s(s), zone(zone), code(s, a, 1024), tasks(0), result(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
System* s;
|
||||||
|
Zone* zone;
|
||||||
|
Vector code;
|
||||||
|
Task* tasks;
|
||||||
|
uint8_t* result;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void NO_RETURN
|
||||||
|
abort(Context* c)
|
||||||
|
{
|
||||||
|
abort(c->s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
inline void
|
||||||
|
assert(Context* c, bool v)
|
||||||
|
{
|
||||||
|
assert(c->s, v);
|
||||||
|
}
|
||||||
|
#endif // not NDEBUG
|
||||||
|
|
||||||
|
inline void
|
||||||
|
expect(Context* c, bool v)
|
||||||
|
{
|
||||||
|
expect(c->s, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CodePromise: public Promise {
|
||||||
|
public:
|
||||||
|
CodePromise(Context* c, unsigned offset): c(c), offset(offset) { }
|
||||||
|
|
||||||
|
virtual int64_t value() {
|
||||||
|
if (resolved()) {
|
||||||
|
return reinterpret_cast<intptr_t>(c->result + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool resolved() {
|
||||||
|
return c->result != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
|
unsigned offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodePromise*
|
||||||
|
codePromise(Context* c, unsigned offset)
|
||||||
|
{
|
||||||
|
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
|
||||||
|
}
|
||||||
|
|
||||||
class Task {
|
class Task {
|
||||||
public:
|
public:
|
||||||
Task(Task* next): next(next) { }
|
Task(Task* next): next(next) { }
|
||||||
|
|
||||||
virtual ~Task() { }
|
virtual ~Task() { }
|
||||||
|
|
||||||
virtual void run(uint8_t* code) = 0;
|
virtual void run(Context* c) = 0;
|
||||||
|
|
||||||
Task* next;
|
Task* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OffsetTask: public Task {
|
||||||
|
public:
|
||||||
|
OffsetTask(Task* next, Promise* promise, int instructionOffset,
|
||||||
|
unsigned instructionSize):
|
||||||
|
Task(next),
|
||||||
|
promise(promise),
|
||||||
|
instructionOffset(instructionOffset),
|
||||||
|
instructionSize(instructionSize)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void run(Context* c) {
|
||||||
|
uint8_t* instruction = c->result + instructionOffset;
|
||||||
|
intptr_t v = reinterpret_cast<uint8_t*>(promise->value())
|
||||||
|
- instruction - instructionSize;
|
||||||
|
|
||||||
|
expect(c, isInt32(v));
|
||||||
|
|
||||||
|
int32_t v4 = v;
|
||||||
|
memcpy(instruction + instructionSize - 4, &v4, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise* promise;
|
||||||
|
int instructionOffset;
|
||||||
|
unsigned instructionSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendOffsetTask(Context* c, Promise* promise, int instructionOffset,
|
||||||
|
unsigned instructionSize)
|
||||||
|
{
|
||||||
|
c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask
|
||||||
|
(c->tasks, promise, instructionOffset, instructionSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encode(Context* c, uint8_t* instruction, unsigned length, int a, int b,
|
||||||
|
int32_t displacement, int index, unsigned scale)
|
||||||
|
{
|
||||||
|
c->code.append(instruction, length);
|
||||||
|
|
||||||
|
uint8_t width;
|
||||||
|
if (displacement == 0 and b != rbp) {
|
||||||
|
width = 0;
|
||||||
|
} else if (isInt8(displacement)) {
|
||||||
|
width = 0x40;
|
||||||
|
} else {
|
||||||
|
width = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
c->code.append(width | (a << 3) | b);
|
||||||
|
if (b == rsp) {
|
||||||
|
c->code.append(0x24);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(c, b != rsp);
|
||||||
|
c->code.append(width | (a << 3) | 4);
|
||||||
|
c->code.append((log(scale) << 6) | (index << 3) | b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displacement == 0 and b != rbp) {
|
||||||
|
// do nothing
|
||||||
|
} else if (isInt8(displacement)) {
|
||||||
|
c->code.append(displacement);
|
||||||
|
} else {
|
||||||
|
c->code.append4(displacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rex(Context* c)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
c->code.append(0x48);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex)
|
||||||
|
{
|
||||||
|
if (b->traceHandler) {
|
||||||
|
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rex) {
|
||||||
|
::rex(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
encode(c, &instruction, 1, a, b->base, b->offset, b->index, b->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b,
|
||||||
|
bool rex)
|
||||||
|
{
|
||||||
|
if (b->traceHandler) {
|
||||||
|
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rex) {
|
||||||
|
::rex(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t i[2] = { instruction >> 8, instruction & 0xff };
|
||||||
|
encode(c, i, 2, a, b->base, b->offset, b->index, b->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*OperationType)(Context*);
|
||||||
|
OperationType
|
||||||
|
Operations[OperationCount];
|
||||||
|
|
||||||
|
typedef void (*UnaryOperationType)(Context*, unsigned, Assembler::Operand*);
|
||||||
|
UnaryOperationType
|
||||||
|
UnaryOperations[UnaryOperationCount * OperandTypeCount];
|
||||||
|
|
||||||
|
typedef void (*BinaryOperationType)
|
||||||
|
(Context*, unsigned, Assembler::Operand*, Assembler::Operand*);
|
||||||
|
BinaryOperationType
|
||||||
|
BinaryOperations[BinaryOperationCount * OperandTypeCount * OperandTypeCount];
|
||||||
|
|
||||||
|
void
|
||||||
|
return_(Context* c)
|
||||||
|
{
|
||||||
|
c->code.append(0xc3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unconditional(Context* c, unsigned jump, Assembler::Constant* a)
|
||||||
|
{
|
||||||
|
appendOffsetTask(c, a->value, c->code.length(), 5);
|
||||||
|
|
||||||
|
c->code.append(jump);
|
||||||
|
c->code.append4(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
conditional(Context* c, unsigned condition, Assembler::Constant* a)
|
||||||
|
{
|
||||||
|
appendOffsetTask(c, a->value, c->code.length(), 6);
|
||||||
|
|
||||||
|
c->code.append(0x0f);
|
||||||
|
c->code.append(condition);
|
||||||
|
c->code.append4(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
callC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||||
|
{
|
||||||
|
assert(c, size == BytesPerWord);
|
||||||
|
|
||||||
|
unconditional(c, 0xe8, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a)
|
||||||
|
{
|
||||||
|
assert(c, size == BytesPerWord);
|
||||||
|
|
||||||
|
c->code.append(0xff);
|
||||||
|
c->code.append(0xd0 | a->low);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0xb8 | b->low);
|
||||||
|
c->code.appendAddress(a->value->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||||
|
Assembler::Memory* b)
|
||||||
|
{
|
||||||
|
assert(c, isInt32(a->value->value())); // todo
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
encode(c, 0xc7, 0, b, true);
|
||||||
|
c->code.append4(a->value->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
moveRM(c, 4, a, b);
|
||||||
|
|
||||||
|
Assembler::Register ah(a->high);
|
||||||
|
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
|
||||||
|
moveRM(c, 4, &ah, &bh);
|
||||||
|
} else if (BytesPerWord == 8 and size == 4) {
|
||||||
|
encode(c, 0x89, a->low, b, false);
|
||||||
|
} else {
|
||||||
|
encode(c, 0x89, a->low, b, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
moveRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
moveRR(c, 4, a, b);
|
||||||
|
|
||||||
|
Assembler::Register ah(a->low);
|
||||||
|
Assembler::Register bh(b->low);
|
||||||
|
moveRR(c, 4, &ah, &bh);
|
||||||
|
} else {
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x89);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8); // todo
|
||||||
|
|
||||||
|
encode(c, 0x63, b->low, a, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
addRR(Context* c, unsigned size, Assembler::Register* a,
|
||||||
|
Assembler::Register* b)
|
||||||
|
{
|
||||||
|
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||||
|
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x01);
|
||||||
|
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
populateTables()
|
||||||
|
{
|
||||||
|
Operations[Return] = return_;
|
||||||
|
|
||||||
|
UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC);
|
||||||
|
UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR);
|
||||||
|
|
||||||
|
BinaryOperations[INDEX2(Move4, Constant, Register)] = CAST2(moveCR);
|
||||||
|
BinaryOperations[INDEX2(Move8, Constant, Register)] = CAST2(moveCR);
|
||||||
|
BinaryOperations[INDEX2(Move4, Constant, Memory)] = CAST2(moveCM);
|
||||||
|
BinaryOperations[INDEX2(Move8, Constant, Memory)] = CAST2(moveCM);
|
||||||
|
BinaryOperations[INDEX2(Move4, Register, Memory)] = CAST2(moveRM);
|
||||||
|
BinaryOperations[INDEX2(Move8, Register, Memory)] = CAST2(moveRM);
|
||||||
|
BinaryOperations[INDEX2(Move4, Register, Register)] = CAST2(moveRR);
|
||||||
|
BinaryOperations[INDEX2(Move8, Register, Register)] = CAST2(moveRR);
|
||||||
|
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
|
||||||
|
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
||||||
|
}
|
||||||
|
|
||||||
class MyAssembler: public Assembler {
|
class MyAssembler: public Assembler {
|
||||||
public:
|
public:
|
||||||
MyAssembler(System* s, Allocator* a): s(s), code(s, a, 1024), tasks(0) { }
|
MyAssembler(System* s, Allocator* a, Zone* zone): c(s, a, zone) {
|
||||||
|
static bool populated = false;
|
||||||
|
if (not populated) {
|
||||||
|
populated = true;
|
||||||
|
populateTables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual unsigned registerCount() {
|
virtual unsigned registerCount() {
|
||||||
return BytesPerWord == 4 ? 8 : 16;
|
return BytesPerWord == 4 ? 8 : 16;
|
||||||
@ -68,7 +414,7 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual int argumentRegister(unsigned index) {
|
virtual int argumentRegister(unsigned index) {
|
||||||
assert(s, BytesPerWord == 8);
|
assert(&c, BytesPerWord == 8);
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -84,7 +430,7 @@ class MyAssembler: public Assembler {
|
|||||||
case 5:
|
case 5:
|
||||||
return r9;
|
return r9;
|
||||||
default:
|
default:
|
||||||
abort(s);
|
abort(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +447,7 @@ class MyAssembler: public Assembler {
|
|||||||
case 4:
|
case 4:
|
||||||
return rdi;
|
return rdi;
|
||||||
default:
|
default:
|
||||||
abort(s);
|
abort(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,42 +469,40 @@ class MyAssembler: public Assembler {
|
|||||||
b->high = NoRegister;
|
b->high = NoRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Operation /*op*/) {
|
virtual void apply(Operation op) {
|
||||||
// todo
|
Operations[op](&c);
|
||||||
abort(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(UnaryOperation /*op*/, unsigned /*size*/,
|
virtual void apply(UnaryOperation op, unsigned size,
|
||||||
OperandType /*type*/, Operand* /*operand*/)
|
OperandType type, Operand* operand)
|
||||||
{
|
{
|
||||||
// todo
|
UnaryOperations[INDEX1(op, type)](&c, size, operand);
|
||||||
abort(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(BinaryOperation /*op*/, unsigned /*size*/,
|
virtual void apply(BinaryOperation op, unsigned size,
|
||||||
OperandType /*aType*/, Operand* /*a*/,
|
OperandType aType, Operand* a,
|
||||||
OperandType /*bType*/, Operand* /*b*/)
|
OperandType bType, Operand* b)
|
||||||
{
|
{
|
||||||
// todo
|
BinaryOperations[INDEX2(op, aType, bType)](&c, size, a, b);
|
||||||
abort(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void writeTo(uint8_t* dst) {
|
virtual void writeTo(uint8_t* dst) {
|
||||||
memcpy(dst, code.data, code.length());
|
c.result = dst;
|
||||||
|
memcpy(dst, c.code.data, c.code.length());
|
||||||
|
|
||||||
for (Task* t = tasks; t; t = t->next) {
|
for (Task* t = c.tasks; t; t = t->next) {
|
||||||
t->run(dst);
|
t->run(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned length() {
|
virtual unsigned length() {
|
||||||
return code.length();
|
return c.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateCall(void* returnAddress, void* newTarget) {
|
virtual void updateCall(void* returnAddress, void* newTarget) {
|
||||||
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
||||||
assert(s, *instruction == 0xE8);
|
assert(&c, *instruction == 0xE8);
|
||||||
assert(s, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
||||||
|
|
||||||
int32_t v = static_cast<uint8_t*>(newTarget)
|
int32_t v = static_cast<uint8_t*>(newTarget)
|
||||||
- static_cast<uint8_t*>(returnAddress);
|
- static_cast<uint8_t*>(returnAddress);
|
||||||
@ -166,12 +510,10 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
code.dispose();
|
c.code.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
Context c;
|
||||||
Vector code;
|
|
||||||
Task* tasks;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -182,7 +524,7 @@ Assembler*
|
|||||||
makeAssembler(System* system, Allocator* allocator, Zone* zone)
|
makeAssembler(System* system, Allocator* allocator, Zone* zone)
|
||||||
{
|
{
|
||||||
return new (zone->allocate(sizeof(MyAssembler)))
|
return new (zone->allocate(sizeof(MyAssembler)))
|
||||||
MyAssembler(system, allocator);
|
MyAssembler(system, allocator, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
202
test/Misc.java
202
test/Misc.java
@ -1,120 +1,124 @@
|
|||||||
public class Misc {
|
public class Misc {
|
||||||
private static int alpha;
|
// private static int alpha;
|
||||||
private static int beta;
|
// private static int beta;
|
||||||
private static byte byte1, byte2, byte3;
|
// private static byte byte1, byte2, byte3;
|
||||||
private int gamma;
|
// private int gamma;
|
||||||
|
|
||||||
private String foo(String s) {
|
// private String foo(String s) {
|
||||||
return s;
|
// return s;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public String bar(String s) {
|
// public String bar(String s) {
|
||||||
return s;
|
// return s;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private static String baz(String s) {
|
// private static String baz(String s) {
|
||||||
return s;
|
// return s;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private static void expect(boolean v) {
|
// private static void expect(boolean v) {
|
||||||
if (! v) throw new RuntimeException();
|
// if (! v) throw new RuntimeException();
|
||||||
}
|
// }
|
||||||
|
|
||||||
private synchronized byte sync() {
|
// private synchronized byte sync() {
|
||||||
byte[] array = new byte[123];
|
// byte[] array = new byte[123];
|
||||||
return array[42];
|
// return array[42];
|
||||||
}
|
// }
|
||||||
|
|
||||||
private static synchronized byte syncStatic(boolean throw_) {
|
// private static synchronized byte syncStatic(boolean throw_) {
|
||||||
byte[] array = new byte[123];
|
// byte[] array = new byte[123];
|
||||||
if (throw_) {
|
// if (throw_) {
|
||||||
throw new RuntimeException();
|
// throw new RuntimeException();
|
||||||
} else {
|
// } else {
|
||||||
return array[42];
|
// return array[42];
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void putInt(int val, byte[] dst, int offset) {
|
// public static void putInt(int val, byte[] dst, int offset) {
|
||||||
System.out.println("put " + val);
|
// System.out.println("put " + val);
|
||||||
dst[offset] = (byte)((val >> 24) & 0xff);
|
// dst[offset] = (byte)((val >> 24) & 0xff);
|
||||||
dst[offset+1] = (byte)((val >> 16) & 0xff);
|
// dst[offset+1] = (byte)((val >> 16) & 0xff);
|
||||||
dst[offset+2] = (byte)((val >> 8) & 0xff);
|
// dst[offset+2] = (byte)((val >> 8) & 0xff);
|
||||||
dst[offset+3] = (byte)((val ) & 0xff);
|
// dst[offset+3] = (byte)((val ) & 0xff);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void putLong(long val, byte[] dst, int offset) {
|
// public static void putLong(long val, byte[] dst, int offset) {
|
||||||
putInt((int)(val >> 32), dst, offset);
|
// putInt((int)(val >> 32), dst, offset);
|
||||||
putInt((int)val, dst, offset + 4);
|
// putInt((int)val, dst, offset + 4);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public String toString() {
|
// public String toString() {
|
||||||
return super.toString();
|
// return super.toString();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
byte2 = 0;
|
|
||||||
expect(byte2 == 0);
|
|
||||||
|
|
||||||
Misc m = new Misc();
|
|
||||||
m.toString();
|
|
||||||
|
|
||||||
expect(Long.valueOf(231L) == 231L);
|
|
||||||
|
|
||||||
long x = 231;
|
|
||||||
expect((x >> 32) == 0);
|
|
||||||
expect((x >>> 32) == 0);
|
|
||||||
expect((x << 32) == 992137445376L);
|
|
||||||
|
|
||||||
long y = -231;
|
|
||||||
expect((y >> 32) == 0xffffffffffffffffL);
|
|
||||||
expect((y >>> 32) == 0xffffffffL);
|
|
||||||
|
|
||||||
byte[] array = new byte[8];
|
|
||||||
putLong(231, array, 0);
|
|
||||||
expect((array[0] & 0xff) == 0);
|
|
||||||
expect((array[1] & 0xff) == 0);
|
|
||||||
expect((array[2] & 0xff) == 0);
|
|
||||||
expect((array[3] & 0xff) == 0);
|
|
||||||
expect((array[4] & 0xff) == 0);
|
|
||||||
expect((array[5] & 0xff) == 0);
|
|
||||||
expect((array[6] & 0xff) == 0);
|
|
||||||
expect((array[7] & 0xff) == 231);
|
|
||||||
|
|
||||||
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
|
||||||
buffer.putLong(231);
|
|
||||||
buffer.flip();
|
|
||||||
expect(buffer.getLong() == 231);
|
|
||||||
|
|
||||||
boolean v = Boolean.valueOf("true");
|
|
||||||
|
|
||||||
ClassLoader.getSystemClassLoader().toString();
|
|
||||||
|
|
||||||
int a = 2;
|
int a = 2;
|
||||||
int b = 2;
|
int b = 2;
|
||||||
int c = a + b;
|
int c = a + b;
|
||||||
|
|
||||||
String s = "hello";
|
// byte2 = 0;
|
||||||
m.foo(s);
|
// expect(byte2 == 0);
|
||||||
m.bar(s);
|
|
||||||
baz(s);
|
|
||||||
|
|
||||||
m.sync();
|
// Misc m = new Misc();
|
||||||
syncStatic(false);
|
// m.toString();
|
||||||
try {
|
|
||||||
syncStatic(true);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
int d = alpha;
|
// expect(Long.valueOf(231L) == 231L);
|
||||||
beta = 42;
|
|
||||||
alpha = 43;
|
|
||||||
int e = beta;
|
|
||||||
int f = alpha;
|
|
||||||
m.gamma = 44;
|
|
||||||
|
|
||||||
expect(beta == 42);
|
// long x = 231;
|
||||||
expect(alpha == 43);
|
// expect((x >> 32) == 0);
|
||||||
expect(m.gamma == 44);
|
// expect((x >>> 32) == 0);
|
||||||
|
// expect((x << 32) == 992137445376L);
|
||||||
|
|
||||||
|
// long y = -231;
|
||||||
|
// expect((y >> 32) == 0xffffffffffffffffL);
|
||||||
|
// expect((y >>> 32) == 0xffffffffL);
|
||||||
|
|
||||||
|
// byte[] array = new byte[8];
|
||||||
|
// putLong(231, array, 0);
|
||||||
|
// expect((array[0] & 0xff) == 0);
|
||||||
|
// expect((array[1] & 0xff) == 0);
|
||||||
|
// expect((array[2] & 0xff) == 0);
|
||||||
|
// expect((array[3] & 0xff) == 0);
|
||||||
|
// expect((array[4] & 0xff) == 0);
|
||||||
|
// expect((array[5] & 0xff) == 0);
|
||||||
|
// expect((array[6] & 0xff) == 0);
|
||||||
|
// expect((array[7] & 0xff) == 231);
|
||||||
|
|
||||||
|
// java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
||||||
|
// buffer.putLong(231);
|
||||||
|
// buffer.flip();
|
||||||
|
// expect(buffer.getLong() == 231);
|
||||||
|
|
||||||
|
// boolean v = Boolean.valueOf("true");
|
||||||
|
|
||||||
|
// ClassLoader.getSystemClassLoader().toString();
|
||||||
|
|
||||||
|
// int a = 2;
|
||||||
|
// int b = 2;
|
||||||
|
// int c = a + b;
|
||||||
|
|
||||||
|
// String s = "hello";
|
||||||
|
// m.foo(s);
|
||||||
|
// m.bar(s);
|
||||||
|
// baz(s);
|
||||||
|
|
||||||
|
// m.sync();
|
||||||
|
// syncStatic(false);
|
||||||
|
// try {
|
||||||
|
// syncStatic(true);
|
||||||
|
// } catch (RuntimeException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int d = alpha;
|
||||||
|
// beta = 42;
|
||||||
|
// alpha = 43;
|
||||||
|
// int e = beta;
|
||||||
|
// int f = alpha;
|
||||||
|
// m.gamma = 44;
|
||||||
|
|
||||||
|
// expect(beta == 42);
|
||||||
|
// expect(alpha == 43);
|
||||||
|
// expect(m.gamma == 44);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user