Commit f45e5d7f authored by Marius Wachtler's avatar Marius Wachtler

assembler: add leave, jmp indirect and a helper for generating forward jumps

parent 474d13dd
......@@ -790,6 +790,8 @@ void Assembler::cmp(Indirect mem, Register reg) {
}
void Assembler::lea(Indirect mem, Register reg) {
RELEASE_ASSERT(mem.base != RSP && mem.base != R12, "We have to generate the SIB byte...");
int mem_idx = mem.base.regnum;
int reg_idx = reg.regnum;
......@@ -886,6 +888,23 @@ void Assembler::jmp(JumpDestination dest) {
}
}
void Assembler::jmp(Indirect dest) {
int reg_idx = dest.base.regnum;
assert(reg_idx >= 0 && reg_idx < 8 && "not yet implemented");
emitByte(0xFF);
if (dest.offset == 0) {
emitModRM(0b00, 0b100, reg_idx);
} else if (-0x80 <= dest.offset && dest.offset < 0x80) {
emitModRM(0b01, 0b100, reg_idx);
emitByte(dest.offset);
} else {
assert((-1L << 31) <= dest.offset && dest.offset < (1L << 31) - 1);
emitModRM(0b10, 0b100, reg_idx);
emitInt(dest.offset, 4);
}
}
void Assembler::jne(JumpDestination dest) {
jmp_cond(dest, COND_NOT_EQUAL);
}
......@@ -934,6 +953,10 @@ void Assembler::setne(Register reg) {
set_cond(reg, COND_NOT_EQUAL);
}
void Assembler::leave() {
emitByte(0xC9);
}
uint8_t* Assembler::emitCall(void* ptr, Register scratch) {
mov(Immediate(ptr), scratch);
callq(scratch);
......@@ -1002,5 +1025,19 @@ void Assembler::emitAnnotation(int num) {
cmp(RAX, Immediate(num));
nop();
}
ForwardJump::ForwardJump(Assembler& assembler, ConditionCode condition)
: assembler(assembler), condition(condition), jmp_inst(assembler.curInstPointer()) {
assembler.jmp_cond(JumpDestination::fromStart(assembler.bytesWritten() + max_jump_size), condition);
}
ForwardJump::~ForwardJump() {
uint8_t* new_pos = assembler.curInstPointer();
int offset = new_pos - jmp_inst;
RELEASE_ASSERT(offset < max_jump_size, "");
assembler.setCurInstPointer(jmp_inst);
assembler.jmp_cond(JumpDestination::fromStart(assembler.bytesWritten() + offset), condition);
assembler.setCurInstPointer(new_pos);
}
}
}
......@@ -154,6 +154,7 @@ public:
void callq(Register reg);
void retq();
void leave();
void cmp(Register reg1, Register reg2);
void cmp(Register reg, Immediate imm);
......@@ -166,6 +167,7 @@ public:
void jmp_cond(JumpDestination dest, ConditionCode condition);
void jmp(JumpDestination dest);
void jmp(Indirect dest);
void jmpq(Register dest);
void je(JumpDestination dest);
void jne(JumpDestination dest);
......@@ -185,9 +187,27 @@ public:
void fillWithNopsExcept(int bytes);
void emitAnnotation(int num);
int bytesWritten() { return addr - start_addr; }
int bytesLeft() const { return end_addr - addr; }
int bytesWritten() const { return addr - start_addr; }
uint8_t* curInstPointer() { return addr; }
bool isExactlyFull() { return addr == end_addr; }
void setCurInstPointer(uint8_t* ptr) { addr = ptr; }
bool isExactlyFull() const { return addr == end_addr; }
uint8_t* getStartAddr() { return start_addr; }
};
// This class helps generating a forward jump with a relative offset.
// It keeps track of the current assembler offset at construction time and in the destructor patches the
// generated conditional jump with the correct offset depending on the number of bytes emitted in between.
class ForwardJump {
private:
const int max_jump_size = 128;
Assembler& assembler;
ConditionCode condition;
uint8_t* jmp_inst;
public:
ForwardJump(Assembler& assembler, ConditionCode condition);
~ForwardJump();
};
uint8_t* initializePatchpoint2(uint8_t* start_addr, uint8_t* slowpath_start, uint8_t* end_addr, StackInfo stack_info,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment