diff options
author | Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> | 2020-09-10 14:31:45 -0400 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:23 -0400 |
commit | 566d4abee5e8e59ce6e080f28a25b7c3431c5b3b (patch) | |
tree | d18e08e5d103fb5e7194b4e241218d6c7c2163fa | |
parent | fe1cd076da74be8077509fab5a401060ce1c17a4 (diff) |
Added shift instructions
-rw-r--r-- | compile.c | 18 | ||||
-rw-r--r-- | ujit_asm.c | 111 | ||||
-rw-r--r-- | ujit_asm.h | 4 | ||||
-rw-r--r-- | ujit_asm_tests.c | 29 |
4 files changed, 150 insertions, 12 deletions
@@ -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"); } |