summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2020-09-10 14:31:45 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:23 -0400
commit566d4abee5e8e59ce6e080f28a25b7c3431c5b3b (patch)
treed18e08e5d103fb5e7194b4e241218d6c7c2163fa
parentfe1cd076da74be8077509fab5a401060ce1c17a4 (diff)
Added shift instructions
-rw-r--r--compile.c18
-rw-r--r--ujit_asm.c111
-rw-r--r--ujit_asm.h4
-rw-r--r--ujit_asm_tests.c29
4 files changed, 150 insertions, 12 deletions
diff --git a/compile.c b/compile.c
index 49263002e3..a1983eaecb 100644
--- a/compile.c
+++ b/compile.c
@@ -866,14 +866,20 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
unsigned int i;
VALUE *encoded = (VALUE *)iseq->body->iseq_encoded;
- for (i = 0; i < iseq->body->iseq_size; /* */ ) {
- int insn = (int)iseq->body->iseq_encoded[i];
- int len = insn_len(insn);
- encoded[i] = (VALUE)table[insn];
+ for (i = 0; i < iseq->body->iseq_size; /* */ )
+ {
+ int insn = (int)iseq->body->iseq_encoded[i];
+ int len = insn_len(insn);
+ encoded[i] = (VALUE)table[insn];
+
+ if (insn == BIN(pop))
+ encoded[i] = (VALUE)native_pop_code;
+
+ const char* name = insn_name(insn);
+ printf("%s\n", name);
- if (insn == BIN(pop)) encoded[i] = (VALUE)native_pop_code;
- i += len;
+ i += len;
}
FL_SET((VALUE)iseq, ISEQ_TRANSLATED);
#endif
diff --git a/ujit_asm.c b/ujit_asm.c
index 15b0dc5d05..a7c673ef92 100644
--- a/ujit_asm.c
+++ b/ujit_asm.c
@@ -588,6 +588,56 @@ void cb_write_rm_multi(
}
}
+// Encode a single-operand shift instruction
+void cb_write_shift(
+ codeblock_t* cb,
+ const char* mnem,
+ uint8_t opMemOnePref,
+ uint8_t opMemClPref,
+ uint8_t opMemImmPref,
+ uint8_t opExt,
+ x86opnd_t opnd0,
+ x86opnd_t opnd1)
+{
+ // Write a disassembly string
+ //cb.writeASM(mnem, opnd0, opnd1);
+
+ // Check the size of opnd0
+ size_t opndSize;
+ if (opnd0.type == OPND_REG || opnd0.type == OPND_MEM)
+ opndSize = opnd0.num_bits;
+ else
+ assert (false && "shift: invalid first operand");
+
+ assert (opndSize == 16 || opndSize == 32 || opndSize == 64);
+ bool szPref = opndSize == 16;
+ bool rexW = opndSize == 64;
+
+ if (opnd1.type == OPND_IMM)
+ {
+ if (opnd1.imm == 1)
+ {
+ cb_write_rm(cb, szPref, rexW, NO_OPND, opnd0, opExt, 1, opMemOnePref);
+ }
+ else
+ {
+ assert (opnd1.num_bits <= 8);
+ cb_write_rm(cb, szPref, rexW, NO_OPND, opnd0, opExt, 1, opMemImmPref);
+ cb_write_byte(cb, (uint8_t)opnd1.imm);
+ }
+ }
+ /*
+ else if (opnd1.isReg && opnd1.reg == CL)
+ {
+ cb.writeRMInstr!('l', opExt, opMemClPref)(szPref, rexW, opnd0, X86Opnd.NONE);
+ }
+ */
+ else
+ {
+ assert (false);
+ }
+}
+
// add - Integer addition
void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
{
@@ -893,6 +943,65 @@ void ret(codeblock_t* cb)
cb_write_byte(cb, 0xC3);
}
+// sal - Shift arithmetic left
+void sal(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
+{
+ cb_write_shift(
+ cb,
+ "sal",
+ 0xD1, // opMemOnePref,
+ 0xD3, // opMemClPref,
+ 0xC1, // opMemImmPref,
+ 0x04,
+ opnd0,
+ opnd1
+ );
+}
+
+/// sar - Shift arithmetic right (signed)
+void sar(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
+{
+ cb_write_shift(
+ cb,
+ "sar",
+ 0xD1, // opMemOnePref,
+ 0xD3, // opMemClPref,
+ 0xC1, // opMemImmPref,
+ 0x07,
+ opnd0,
+ opnd1
+ );
+}
+// shl - Shift logical left
+void shl(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
+{
+ cb_write_shift(
+ cb,
+ "shl",
+ 0xD1, // opMemOnePref,
+ 0xD3, // opMemClPref,
+ 0xC1, // opMemImmPref,
+ 0x04,
+ opnd0,
+ opnd1
+ );
+}
+
+/// shr - Shift logical right (unsigned)
+void shr(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
+{
+ cb_write_shift(
+ cb,
+ "shr",
+ 0xD1, // opMemOnePref,
+ 0xD3, // opMemClPref,
+ 0xC1, // opMemImmPref,
+ 0x05,
+ opnd0,
+ opnd1
+ );
+}
+
/// sub - Integer subtraction
void sub(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
{
@@ -906,7 +1015,7 @@ void sub(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1)
0x80, // opMemImm8
0x83, // opMemImmSml
0x81, // opMemImmLrg
- 0x05, // opExtImm
+ 0x05, // opExtImm
opnd0,
opnd1
);
diff --git a/ujit_asm.h b/ujit_asm.h
index bc93b1e360..714bfa2f31 100644
--- a/ujit_asm.h
+++ b/ujit_asm.h
@@ -194,6 +194,10 @@ void nop(codeblock_t* cb, size_t length);
void push(codeblock_t* cb, x86opnd_t reg);
void pop(codeblock_t* cb, x86opnd_t reg);
void ret(codeblock_t* cb);
+void sal(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
+void sar(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
+void shl(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
+void shr(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
void sub(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
#endif
diff --git a/ujit_asm_tests.c b/ujit_asm_tests.c
index 3e2c28cca9..cbb115eec7 100644
--- a/ujit_asm_tests.c
+++ b/ujit_asm_tests.c
@@ -156,15 +156,34 @@ void run_tests()
// ret
cb_set_pos(cb, 0); ret(cb); check_bytes(cb, "C3");
- // sub
- cb_set_pos(cb, 0); sub(cb, EAX, imm_opnd(1)); check_bytes(cb, "83E801");
- cb_set_pos(cb, 0); sub(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883E802");
-
-
+ // sal
+ /*
+ test(
+ delegate void (CodeBlock cb) { cb.sal(X86Opnd(CX), X86Opnd(1)); },
+ "66D1E1"
+ );
+ */
+ cb_set_pos(cb, 0); sal(cb, ECX, imm_opnd(1)); check_bytes(cb, "D1E1");
+ cb_set_pos(cb, 0); sal(cb, EBP, imm_opnd(5)); check_bytes(cb, "C1E505");
+ cb_set_pos(cb, 0); sal(cb, mem_opnd(32, RSP, 68), imm_opnd(1)); check_bytes(cb, "D1642444");
+ // sar
+ cb_set_pos(cb, 0); sar(cb, EDX, imm_opnd(1)); check_bytes(cb, "D1FA");
+ // shr
+ cb_set_pos(cb, 0); shr(cb, R14, imm_opnd(7)); check_bytes(cb, "49C1EE07");
+ /*
+ // sqrtsd
+ test(
+ delegate void (CodeBlock cb) { cb.sqrtsd(X86Opnd(XMM2), X86Opnd(XMM6)); },
+ "F20F51D6"
+ );
+ */
+ // sub
+ cb_set_pos(cb, 0); sub(cb, EAX, imm_opnd(1)); check_bytes(cb, "83E801");
+ cb_set_pos(cb, 0); sub(cb, RAX, imm_opnd(2)); check_bytes(cb, "4883E802");
printf("Assembler tests done\n");
}