ruby-changes:68570
From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:09:42 +0900 (JST)
Subject: [ruby-changes:68570] 1879a123ca (master): Added cmp, not. Generate code for nop instruction.
https://git.ruby-lang.org/ruby.git/commit/?id=1879a123ca From 1879a123caeb9caced2eeb2bb7a7a91a4a8e1930 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...> Date: Mon, 14 Sep 2020 11:54:25 -0400 Subject: Added cmp, not. Generate code for nop instruction. --- ujit_asm.c | 66 ++++++++++++++++++++++++++++- ujit_asm.h | 4 ++ ujit_asm_tests.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ujit_compile.c | 29 ++++++++++--- 4 files changed, 216 insertions(+), 7 deletions(-) diff --git a/ujit_asm.c b/ujit_asm.c index 2cebc8caa6..6b6c586045 100644 --- a/ujit_asm.c +++ b/ujit_asm.c @@ -548,10 +548,11 @@ void cb_write_rm( https://github.com/ruby/ruby/blob/trunk/ujit_asm.c#L548 } // Add the displacement size - if (rm_opnd.type == OPND_MEM && rm_opnd.mem.disp != 0) + if (rm_opnd.type == OPND_MEM) { size_t dsize = disp_size(rm_opnd); - cb_write_int(cb, rm_opnd.mem.disp, dsize); + if (dsize > 0) + cb_write_int(cb, rm_opnd.mem.disp, dsize); } } @@ -791,6 +792,39 @@ void call(codeblock_t* cb, x86opnd_t opnd) https://github.com/ruby/ruby/blob/trunk/ujit_asm.c#L792 cb_write_rm(cb, false, false, NO_OPND, opnd, 2, 1, 0xFF); } +/// cmp - Compare and set flags +void cmp(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1) +{ + cb_write_rm_multi( + cb, + "cmp", + 0x38, // opMemReg8 + 0x39, // opMemRegPref + 0x3A, // opRegMem8 + 0x3B, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x07, // opExtImm + opnd0, + opnd1 + ); +} + +/// cdq - Convert doubleword to quadword +void cdq(codeblock_t* cb) +{ + //cb.writeASM("cdq"); + cb_write_byte(cb, 0x99); +} + +/// cqo - Convert quadword to octaword +void cqo(codeblock_t* cb) +{ + //cb.writeASM("cqo"); + cb_write_bytes(cb, 2, 0x48, 0x99); +} + // dec - Decrement integer by 1 void dec(codeblock_t* cb, x86opnd_t opnd) { @@ -1132,6 +1166,34 @@ void nop(codeblock_t* cb, size_t length) https://github.com/ruby/ruby/blob/trunk/ujit_asm.c#L1166 } } +// not - Bitwise NOT +void not(codeblock_t* cb, x86opnd_t opnd) +{ + write_rm_unary( + cb, + "not", + 0xF6, // opMemReg8 + 0xF7, // opMemRegPref + 0x02, // opExt + opnd + ); +} + +/* +/// or - Bitwise OR +alias or = writeRMMulti!( + "or", + 0x08, // opMemReg8 + 0x09, // opMemRegPref + 0x0A, // opRegMem8 + 0x0B, // opRegMemPref + 0x80, // opMemImm8 + 0x83, // opMemImmSml + 0x81, // opMemImmLrg + 0x01 // opExtImm +); +*/ + /// push - Push a register on the stack void push(codeblock_t* cb, x86opnd_t reg) { diff --git a/ujit_asm.h b/ujit_asm.h index da249abf65..d0de30628e 100644 --- a/ujit_asm.h +++ b/ujit_asm.h @@ -196,6 +196,9 @@ void cb_write_epilogue(codeblock_t* cb); https://github.com/ruby/ruby/blob/trunk/ujit_asm.h#L196 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 cmp(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); +void cdq(codeblock_t* cb); +void cqo(codeblock_t* cb); 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); @@ -233,6 +236,7 @@ void jmp_rm(codeblock_t* cb, x86opnd_t opnd); https://github.com/ruby/ruby/blob/trunk/ujit_asm.h#L236 void lea(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void mov(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void nop(codeblock_t* cb, size_t length); +void not(codeblock_t* cb, x86opnd_t opnd); void push(codeblock_t* cb, x86opnd_t reg); void pop(codeblock_t* cb, x86opnd_t reg); void ret(codeblock_t* cb); diff --git a/ujit_asm_tests.c b/ujit_asm_tests.c index 4d2ed9cff4..4ada3a9ecd 100644 --- a/ujit_asm_tests.c +++ b/ujit_asm_tests.c @@ -93,6 +93,44 @@ void run_tests() https://github.com/ruby/ruby/blob/trunk/ujit_asm_tests.c#L93 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"); + /* + // cmovcc + test( + delegate void (CodeBlock cb) { cb.cmovg(ESI, X86Opnd(EDI)); }, + "0F4FF7" + ); + test( + delegate void (CodeBlock cb) { cb.cmovg(ESI, X86Opnd(32, RBP, 12)); }, + "0F4F750C" + ); + test( + delegate void (CodeBlock cb) { cb.cmovl(EAX, X86Opnd(ECX)); }, + "0F4CC1" + ); + test( + delegate void (CodeBlock cb) { cb.cmovl(RBX, X86Opnd(RBP)); }, + "480F4CDD" + ); + test( + delegate void (CodeBlock cb) { cb.cmovle(ESI, X86Opnd(32, RSP, 4)); }, + "0F4E742404" + ); + */ + + // cmp + /* + test( + delegate void (CodeBlock cb) { cb.cmp(X86Opnd(CL), X86Opnd(DL)); }, + "38D1" + ); + */ + cb_set_pos(cb, 0); cmp(cb, ECX, EDI); check_bytes(cb, "39F9"); + cb_set_pos(cb, 0); cmp(cb, RDX, mem_opnd(64, R12, 0)); check_bytes(cb, "493B1424"); + cb_set_pos(cb, 0); cmp(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883F802"); + + // cqo + cb_set_pos(cb, 0); cqo(cb); check_bytes(cb, "4899"); + // dec /* test( @@ -178,6 +216,92 @@ void run_tests() https://github.com/ruby/ruby/blob/trunk/ujit_asm_tests.c#L216 // nop cb_set_pos(cb, 0); nop(cb, 1); check_bytes(cb, "90"); + // not + /* + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(AX)); }, + "66F7D0" + ); + */ + cb_set_pos(cb, 0); not(cb, EAX); check_bytes(cb, "F7D0"); + cb_set_pos(cb, 0); not(cb, mem_opnd(64, R12, 0)); check_bytes(cb, "49F71424"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 301)); check_bytes(cb, "F794242D010000"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 0)); check_bytes(cb, "F71424"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSP, 3)); check_bytes(cb, "F7542403"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RBP, 0)); check_bytes(cb, "F75500"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RBP, 13)); check_bytes(cb, "F7550D"); + cb_set_pos(cb, 0); not(cb, RAX); check_bytes(cb, "48F7D0"); + cb_set_pos(cb, 0); not(cb, R11); check_bytes(cb, "49F7D3"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RAX, 0)); check_bytes(cb, "F710"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RSI, 0)); check_bytes(cb, "F716"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDI, 0)); check_bytes(cb, "F717"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, 55)); check_bytes(cb, "F75237"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, 1337)); check_bytes(cb, "F79239050000"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, -55)); check_bytes(cb, "F752C9"); + cb_set_pos(cb, 0); not(cb, mem_opnd(32, RDX, -555)); check_bytes(cb, "F792D5FDFFFF"); + /* + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 0, 1, RBX)); }, + "F71418" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 0, 1, R12)); }, + "42F71420" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 0, 1, R12)); }, + "43F71427" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 1, R12)); }, + "43F7542705" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 8, R12)); }, + "43F754E705" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R15, 5, 8, R13)); }, + "43F754EF05" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R12, 5, 4, R9)); }, + "43F7548C05" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, R12, 301, 4, R9)); }, + "43F7948C2D010000" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RAX, 5, 4, RDX)); }, + "F7549005" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(64, RAX, 0, 2, RDX)); }, + "48F71450" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RSP, 0, 1, RBX)); }, + "F7141C" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RSP, 3, 1, RBX)); }, + "F7541C03" + ); + test( + delegate void (CodeBlock cb) { cb.not(X86Opnd(32, RBP, 13, 1, RDX)); }, + "F754150D" + ); + */ + + // or + /* + test( + delegate void (CodeBlock cb) { cb.or(X86Opnd(EDX), X86Opnd(ESI)); }, + "09F2" + ); + */ + // pop cb_set_pos(cb, 0); pop(cb, RAX); check_bytes(cb, "58"); cb_set_pos(cb, 0); pop(cb, RBX); check_bytes(cb, "5B"); diff --git a/ujit_compile.c b/ujit_compile.c index bc49d63fee..82ea7291f8 100644 --- a/ujit_compile.c +++ b/ujit_compile.c @@ -42,18 +42,37 @@ ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx) https://github.com/ruby/ruby/blob/trunk/ujit_compile.c#L42 } int insn = (int)iseq->body->iseq_encoded[insn_idx]; - //const char* name = insn_name(insn); //printf("%s\n", name); + // Get a pointer to the current write position in the code block + uint8_t* code_ptr = &cb->mem_block[cb->write_pos]; + //printf("write pos: %ld\n", cb->write_pos); + // TODO: encode individual instructions, eg - // nop, putnil, putobject, putself, pop, dup, getlocal, nilp + // nop, putnil, putobject, putself, pop, dup, getlocal, setlocal, nilp - if (insn == BIN(pop)) + // TODO: we should move the codegen for individual instructions + // into separate functions + if (insn == BIN(nop)) { - // Get a pointer to the current write position in the code block - uint8_t* code_ptr = &cb->mem_block[cb->write_pos]; + // Write the pre call bytes + cb_write_prologue(cb); + + add(cb, RSI, imm_opnd(8)); // increment PC + mov(cb, mem_opnd(64, RDI, 0), RSI); // write new PC to EC object, not ne (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/