diff --git a/src/assembler.h b/src/assembler.h index 9a7a361784..117d7d3618 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -13,16 +13,17 @@ enum Operation { const unsigned OperationCount = Return + 1; enum UnaryOperation { - Call, Push, Pop, + Call, + AlignedCall, + Jump, JumpIfLess, JumpIfGreater, JumpIfLessOrEqual, JumpIfGreaterOrEqual, JumpIfEqual, JumpIfNotEqual, - Jump, Negate }; diff --git a/src/compile.cpp b/src/compile.cpp index 3106bb73d0..4c0d8bb32b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3510,7 +3510,7 @@ finish(MyThread* t, Context* context) } // for debugging: - if (//false and + if (true or//false and strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), @@ -3966,7 +3966,7 @@ saveStackAndBase(MyThread* t, Assembler* a) a->apply(Move, BytesPerWord, Register, &base, Memory, &baseDst); Assembler::Register stack(a->stack()); - Assembler::Memory stackDst(a->thread(), difference(&(t->base), t)); + Assembler::Memory stackDst(a->thread(), difference(&(t->stack), t)); a->apply(Move, BytesPerWord, Register, &stack, Memory, &stackDst); } @@ -3983,16 +3983,29 @@ pushThread(MyThread*, Assembler* a) } } +void +popThread(MyThread*, Assembler* a) +{ + if (a->argumentRegisterCount() == 0) { + ResolvedPromise bpwPromise(BytesPerWord); + Assembler::Constant bpw(&bpwPromise); + Assembler::Register stack(a->stack()); + a->apply(Add, BytesPerWord, Constant, &bpw, Register, &stack); + } +} + object compileDefault(MyThread* t, Assembler* a) { saveStackAndBase(t, a); pushThread(t, a); - ResolvedPromise promise(reinterpret_cast(compileMethod)); - Assembler::Constant proc(&promise); + ResolvedPromise procPromise(reinterpret_cast(compileMethod)); + Assembler::Constant proc(&procPromise); a->apply(Call, BytesPerWord, Constant, &proc); + popThread(t, a); + Assembler::Register result(a->returnLow()); a->apply(Jump, BytesPerWord, Register, &result); @@ -4009,6 +4022,8 @@ compileNative(MyThread* t, Assembler* a) Assembler::Constant proc(&promise); a->apply(Call, BytesPerWord, Constant, &proc); + popThread(t, a); + a->apply(Return); return finish(t, a, "native"); diff --git a/src/compiler.cpp b/src/compiler.cpp index 7e40a4655c..52b0e2bf88 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -513,7 +513,7 @@ class ArgumentEvent: public Event { return register_(c, c->assembler->argumentRegister(index)); } else { return memory(c, c->assembler->base(), - index + (c->stackOffset * BytesPerWord), + -(index + ((c->stackOffset + 1) * BytesPerWord)), NoRegister, 0, 0); } } @@ -617,7 +617,7 @@ class SyncForCallEvent: public Event { assert(c, v == src); return memory(c, c->assembler->base(), - index + (c->stackOffset * BytesPerWord), + -(index + ((c->stackOffset + 1) * BytesPerWord)), NoRegister, 0, 0); } @@ -749,8 +749,7 @@ class CallEvent: public Event { assert(c, v == address); if (indirection) { - return register_ - (c, c->assembler->returnLow(), c->assembler->returnHigh()); + return register_(c, c->assembler->returnLow(), NoRegister); } else { return 0; } @@ -777,19 +776,23 @@ class CallEvent: public Event { } if (stackOffset != c->stackOffset) { - apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()), - memory(c, c->assembler->base(), stackOffset * BytesPerWord, - NoRegister, 0, 0)); + apply(c, LoadAddress, BytesPerWord, + memory(c, c->assembler->base(), + -((stackOffset + 1) * BytesPerWord), + NoRegister, 0, 0), + register_(c, c->assembler->stack())); } + UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); + if (indirection) { - if (address->target->equals(address->value)) { + if (not address->target->equals(address->value)) { apply(c, Move, BytesPerWord, address->value, address->target); } - apply(c, Call, BytesPerWord, + apply(c, type, BytesPerWord, constant(c, reinterpret_cast(indirection))); } else { - apply(c, Call, BytesPerWord, address->value); + apply(c, type, BytesPerWord, address->value); } if (traceHandler) { @@ -1303,17 +1306,19 @@ stack(Context* c, MyOperand* operand, unsigned size, unsigned index, Stack(operand, size, index, next); } +Stack* +stack(Context* c, MyOperand* operand, unsigned size, Stack* next) +{ + return stack(c, operand, size, (next ? next->index + size : 0), next); +} + void push(Context* c, unsigned size, MyOperand* o) { assert(c, ceiling(size, BytesPerWord)); assert(c, o->event == 0); - c->state->stack = stack - (c, o, ceiling(size, BytesPerWord), - ceiling(size, BytesPerWord) - + (c->state->stack ? c->state->stack->index : 0), - c->state->stack); + c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); } MyOperand* @@ -1571,9 +1576,9 @@ class MyCompiler: public Compiler { syncStack(&c, SyncForCall); unsigned stackOffset = c.stackOffset - + (c.state->stack ? c.state->stack->index - + (footprint > c.assembler->argumentRegisterCount() ? - footprint - c.assembler->argumentRegisterCount() : 0) : 0); + + (c.state->stack ? c.state->stack->index + c.state->stack->size : 0) + + (footprint > c.assembler->argumentRegisterCount() ? + footprint - c.assembler->argumentRegisterCount() : 0); MyOperand* result = operand(&c); appendCall(&c, static_cast(address), indirection, flags, diff --git a/src/x86.cpp b/src/x86.cpp index b58944785c..9815eb315a 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -297,7 +297,16 @@ callC(Context* c, unsigned size UNUSED, Assembler::Constant* a) } void -jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) +alignedCallC(Context* c, unsigned size, Assembler::Constant* a) +{ + while ((c->code.length() + 1) % 4) { + c->code.append(0x90); + } + callC(c, size, a); +} + +void +callR(Context* c, unsigned size UNUSED, Assembler::Register* a) { assert(c, size == BytesPerWord); @@ -305,6 +314,15 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) c->code.append(0xd0 | a->low); } +void +jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) +{ + assert(c, size == BytesPerWord); + + c->code.append(0xff); + c->code.append(0xe0 | a->low); +} + void pushR(Context* c, unsigned size, Assembler::Register* a) { @@ -318,6 +336,10 @@ pushR(Context* c, unsigned size, Assembler::Register* a) } } +void +move4To8RR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b); + void popR(Context* c, unsigned size, Assembler::Register* a) { @@ -327,12 +349,15 @@ popR(Context* c, unsigned size, Assembler::Register* a) popR(c, 4, a); popR(c, 4, &ah); } else { - c->code.append(0x50 | a->low); + c->code.append(0x58 | a->low); + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, 0, a, a); + } } } void -leaRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) +leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) { if (BytesPerWord == 8 and size == 4) { encode(c, 0x8d, a->low, b, false); @@ -403,6 +428,17 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } } +void +move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8); + + rex(c); + c->code.append(0x63); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + void moveMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) { @@ -455,6 +491,29 @@ move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b) encode(c, 0x63, b->low, a, true); } +void +addCR(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + if (v) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xc0 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xc0 | b->low); + c->code.append4(v); + } else { + abort(c); + } + } +} + void addRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -481,18 +540,22 @@ populateTables() Operations[Return] = return_; UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); + UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); + UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); - BinaryOperations[INDEX2(LoadAddress, Register, Memory)] = CAST2(leaRM); + BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); + BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); + BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); }