[前][次][番号順一覧][スレッド一覧]

ruby-changes:68683

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:12:20 +0900 (JST)
Subject: [ruby-changes:68683] 7d0df31d7a (master): Ported inc/dec instructions

https://git.ruby-lang.org/ruby.git/commit/?id=7d0df31d7a

From 7d0df31d7ab834526a0b5450128602c04fddb2b0 Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Fri, 11 Sep 2020 16:42:51 -0400
Subject: Ported inc/dec instructions

---
 ujit_asm.c       | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 ujit_asm.h       |   2 +
 ujit_asm_tests.c |  32 ++++++++++
 ujit_compile.c   |   2 +-
 4 files changed, 199 insertions(+), 12 deletions(-)

diff --git a/ujit_asm.c b/ujit_asm.c
index b69d37e4b4..2cebc8caa6 100644
--- a/ujit_asm.c
+++ b/ujit_asm.c
@@ -555,6 +555,35 @@ void cb_write_rm( https://github.com/ruby/ruby/blob/trunk/ujit_asm.c#L555
     }
 }
 
+// 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( https://github.com/ruby/ruby/blob/trunk/ujit_asm.c#L733
     }
 }
 
+// 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) https://github.com/ruby/ruby/blob/trunk/ujit_asm.c#L791
     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
diff --git a/ujit_asm.h b/ujit_asm.h
index 339027d726..da249abf65 100644
--- a/ujit_asm.h
+++ b/ujit_asm.h
@@ -196,6 +196,8 @@ 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 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);
diff --git a/ujit_asm_tests.c b/ujit_asm_tests.c
index 8f93f8fefe..4d2ed9cff4 100644
--- a/ujit_asm_tests.c
+++ b/ujit_asm_tests.c
@@ -93,6 +93,38 @@ 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");
 
+    // 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);
diff --git a/ujit_compile.c b/ujit_compile.c
index 60439e7260..bc49d63fee 100644
--- a/ujit_compile.c
+++ b/ujit_compile.c
@@ -47,7 +47,7 @@ ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx) https://github.com/ruby/ruby/blob/trunk/ujit_compile.c#L47
     //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))
     {
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]