mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Ported inc/dec instructions
This commit is contained in:
parent
26fecc7236
commit
7d0df31d7a
4 changed files with 199 additions and 12 deletions
175
ujit_asm.c
175
ujit_asm.c
|
@ -555,6 +555,35 @@ void cb_write_rm(
|
|||
}
|
||||
}
|
||||
|
||||
// Encode a mul-like single-operand RM instruction
|
||||
void write_rm_unary(
|
||||
codeblock_t* cb,
|
||||
const char* mnem,
|
||||
uint8_t opMemReg8,
|
||||
uint8_t opMemRegPref,
|
||||
uint8_t opExt,
|
||||
x86opnd_t opnd)
|
||||
{
|
||||
// Write a disassembly string
|
||||
//cb.writeASM(mnem, opnd);
|
||||
|
||||
// Check the size of opnd0
|
||||
size_t opndSize;
|
||||
if (opnd.type == OPND_REG || opnd.type == OPND_MEM)
|
||||
opndSize = opnd.num_bits;
|
||||
else
|
||||
assert (false && "invalid operand");
|
||||
|
||||
assert (opndSize == 8 || opndSize == 16 || opndSize == 32 || opndSize == 64);
|
||||
bool szPref = opndSize == 16;
|
||||
bool rexW = opndSize == 64;
|
||||
|
||||
if (opndSize == 8)
|
||||
cb_write_rm(cb, false, false, NO_OPND, opnd, opExt, 1, opMemReg8);
|
||||
else
|
||||
cb_write_rm(cb, szPref, rexW, NO_OPND, opnd, opExt, 1, opMemRegPref);
|
||||
}
|
||||
|
||||
// Encode an add-like RM instruction with multiple possible encodings
|
||||
void cb_write_rm_multi(
|
||||
codeblock_t* cb,
|
||||
|
@ -704,6 +733,23 @@ void cb_write_shift(
|
|||
}
|
||||
}
|
||||
|
||||
// Encode a relative jump to a label (direct or conditional)
|
||||
// Note: this always encodes a 32-bit offset
|
||||
void cb_write_jcc(codeblock_t* cb, const char* mnem, uint8_t op0, uint8_t op1, size_t label_idx)
|
||||
{
|
||||
//cb.writeASM(mnem, label);
|
||||
|
||||
// Write the opcode
|
||||
cb_write_byte(cb, op0);
|
||||
cb_write_byte(cb, op1);
|
||||
|
||||
// Add a reference to the label
|
||||
cb_label_ref(cb, label_idx);
|
||||
|
||||
// Relative 32-bit offset to be patched
|
||||
cb_write_int(cb, 0, 32);
|
||||
}
|
||||
|
||||
// add - Integer addition
|
||||
void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
|
||||
{
|
||||
|
@ -745,21 +791,128 @@ void call(codeblock_t* cb, x86opnd_t opnd)
|
|||
cb_write_rm(cb, false, false, NO_OPND, opnd, 2, 1, 0xFF);
|
||||
}
|
||||
|
||||
// Encode a relative jump to a label (direct or conditional)
|
||||
// Note: this always encodes a 32-bit offset
|
||||
void cb_write_jcc(codeblock_t* cb, const char* mnem, uint8_t op0, uint8_t op1, size_t label_idx)
|
||||
// dec - Decrement integer by 1
|
||||
void dec(codeblock_t* cb, x86opnd_t opnd)
|
||||
{
|
||||
//cb.writeASM(mnem, label);
|
||||
write_rm_unary(
|
||||
cb,
|
||||
"dec",
|
||||
0xFE, // opMemReg8
|
||||
0xFF, // opMemRegPref
|
||||
0x01, // opExt
|
||||
opnd
|
||||
);
|
||||
}
|
||||
|
||||
// Write the opcode
|
||||
cb_write_byte(cb, op0);
|
||||
cb_write_byte(cb, op1);
|
||||
/*
|
||||
// div - Unsigned integer division
|
||||
alias div = writeRMUnary!(
|
||||
"div",
|
||||
0xF6, // opMemReg8
|
||||
0xF7, // opMemRegPref
|
||||
0x06 // opExt
|
||||
);
|
||||
*/
|
||||
|
||||
// Add a reference to the label
|
||||
cb_label_ref(cb, label_idx);
|
||||
/*
|
||||
/// divsd - Divide scalar double
|
||||
alias divsd = writeXMM64!(
|
||||
"divsd",
|
||||
0xF2, // prefix
|
||||
0x0F, // opRegMem0
|
||||
0x5E // opRegMem1
|
||||
);
|
||||
*/
|
||||
|
||||
// Relative 32-bit offset to be patched
|
||||
cb_write_int(cb, 0, 32);
|
||||
/*
|
||||
// idiv - Signed integer division
|
||||
alias idiv = writeRMUnary!(
|
||||
"idiv",
|
||||
0xF6, // opMemReg8
|
||||
0xF7, // opMemRegPref
|
||||
0x07 // opExt
|
||||
);
|
||||
*/
|
||||
|
||||
/*
|
||||
/// imul - Signed integer multiplication with two operands
|
||||
void imul(CodeBlock cb, X86Opnd opnd0, X86Opnd opnd1)
|
||||
{
|
||||
cb.writeASM("imul", opnd0, opnd1);
|
||||
|
||||
assert (opnd0.isReg, "invalid first operand");
|
||||
auto opndSize = opnd0.reg.size;
|
||||
|
||||
// Check the size of opnd1
|
||||
if (opnd1.isReg)
|
||||
assert (opnd1.reg.size is opndSize, "operand size mismatch");
|
||||
else if (opnd1.isMem)
|
||||
assert (opnd1.mem.size is opndSize, "operand size mismatch");
|
||||
|
||||
assert (opndSize is 16 || opndSize is 32 || opndSize is 64);
|
||||
auto szPref = opndSize is 16;
|
||||
auto rexW = opndSize is 64;
|
||||
|
||||
cb.writeRMInstr!('r', 0xFF, 0x0F, 0xAF)(szPref, rexW, opnd0, opnd1);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
/// imul - Signed integer multiplication with three operands (one immediate)
|
||||
void imul(CodeBlock cb, X86Opnd opnd0, X86Opnd opnd1, X86Opnd opnd2)
|
||||
{
|
||||
cb.writeASM("imul", opnd0, opnd1, opnd2);
|
||||
|
||||
assert (opnd0.isReg, "invalid first operand");
|
||||
auto opndSize = opnd0.reg.size;
|
||||
|
||||
// Check the size of opnd1
|
||||
if (opnd1.isReg)
|
||||
assert (opnd1.reg.size is opndSize, "operand size mismatch");
|
||||
else if (opnd1.isMem)
|
||||
assert (opnd1.mem.size is opndSize, "operand size mismatch");
|
||||
|
||||
assert (opndSize is 16 || opndSize is 32 || opndSize is 64);
|
||||
auto szPref = opndSize is 16;
|
||||
auto rexW = opndSize is 64;
|
||||
|
||||
assert (opnd2.isImm, "invalid third operand");
|
||||
auto imm = opnd2.imm;
|
||||
|
||||
// 8-bit immediate
|
||||
if (imm.immSize <= 8)
|
||||
{
|
||||
cb.writeRMInstr!('r', 0xFF, 0x6B)(szPref, rexW, opnd0, opnd1);
|
||||
cb.writeInt(imm.imm, 8);
|
||||
}
|
||||
|
||||
// 32-bit immediate
|
||||
else if (imm.immSize <= 32)
|
||||
{
|
||||
assert (imm.immSize <= opndSize, "immediate too large for dst");
|
||||
cb.writeRMInstr!('r', 0xFF, 0x69)(szPref, rexW, opnd0, opnd1);
|
||||
cb.writeInt(imm.imm, min(opndSize, 32));
|
||||
}
|
||||
|
||||
// Immediate too large
|
||||
else
|
||||
{
|
||||
assert (false, "immediate value too large");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// inc - Increment integer by 1
|
||||
void inc(codeblock_t* cb, x86opnd_t opnd)
|
||||
{
|
||||
write_rm_unary(
|
||||
cb,
|
||||
"inc",
|
||||
0xFE, // opMemReg8
|
||||
0xFF, // opMemRegPref
|
||||
0x00, // opExt
|
||||
opnd
|
||||
);
|
||||
}
|
||||
|
||||
/// jcc - Conditional relative jump to a label
|
||||
|
|
|
@ -196,6 +196,8 @@ void cb_write_epilogue(codeblock_t* cb);
|
|||
void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
|
||||
void call_label(codeblock_t* cb, size_t label_idx);
|
||||
void call(codeblock_t* cb, x86opnd_t opnd);
|
||||
void dec(codeblock_t* cb, x86opnd_t opnd);
|
||||
void inc(codeblock_t* cb, x86opnd_t opnd);
|
||||
void ja(codeblock_t* cb, size_t label_idx);
|
||||
void jae(codeblock_t* cb, size_t label_idx);
|
||||
void jb(codeblock_t* cb, size_t label_idx);
|
||||
|
|
|
@ -93,6 +93,38 @@ void run_tests()
|
|||
cb_set_pos(cb, 0); call(cb, RAX); check_bytes(cb, "FFD0");
|
||||
cb_set_pos(cb, 0); call(cb, mem_opnd(64, RSP, 8)); check_bytes(cb, "FF542408");
|
||||
|
||||
// dec
|
||||
/*
|
||||
test(
|
||||
delegate void (CodeBlock cb) { cb.dec(X86Opnd(CX)); },
|
||||
"66FFC9"
|
||||
);
|
||||
*/
|
||||
cb_set_pos(cb, 0); dec(cb, EDX); check_bytes(cb, "FFCA");
|
||||
|
||||
// div
|
||||
/*
|
||||
test(
|
||||
delegate void (CodeBlock cb) { cb.div(X86Opnd(EDX)); },
|
||||
"F7F2"
|
||||
);
|
||||
test(
|
||||
delegate void (CodeBlock cb) { cb.div(X86Opnd(32, RSP, -12)); },
|
||||
"F77424F4"
|
||||
);
|
||||
*/
|
||||
|
||||
// inc
|
||||
/*
|
||||
test(
|
||||
delegate void (CodeBlock cb) { cb.inc(X86Opnd(BL)); },
|
||||
"FEC3"
|
||||
);
|
||||
*/
|
||||
cb_set_pos(cb, 0); inc(cb, ESP); check_bytes(cb, "FFC4");
|
||||
cb_set_pos(cb, 0); inc(cb, mem_opnd(32, RSP, 0)); check_bytes(cb, "FF0424");
|
||||
cb_set_pos(cb, 0); inc(cb, mem_opnd(64, RSP, 4)); check_bytes(cb, "48FF442404");
|
||||
|
||||
// jcc
|
||||
{
|
||||
cb_set_pos(cb, 0);
|
||||
|
|
|
@ -47,7 +47,7 @@ ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx)
|
|||
//printf("%s\n", name);
|
||||
|
||||
// TODO: encode individual instructions, eg
|
||||
// putnil, putobject, pop, dup, getlocal, nilp
|
||||
// nop, putnil, putobject, putself, pop, dup, getlocal, nilp
|
||||
|
||||
if (insn == BIN(pop))
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue