diff options
author | Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> | 2020-09-09 17:16:21 -0400 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:22 -0400 |
commit | 1392a6f2a499f7400320b87d0bf53d3ef0e26d93 (patch) | |
tree | 741975dd46c2c31f94df9b5138fcf357cc370769 | |
parent | a3b411b9c82010d480ce3bf203dcc8b8600722ce (diff) | |
download | ruby-1392a6f2a499f7400320b87d0bf53d3ef0e26d93.tar.gz |
Added jmp R/M instruction
-rw-r--r-- | ujit_asm.c | 99 | ||||
-rw-r--r-- | ujit_asm.h | 1 | ||||
-rw-r--r-- | ujit_asm_tests.c | 24 |
3 files changed, 118 insertions, 6 deletions
diff --git a/ujit_asm.c b/ujit_asm.c index 41167e9d42..d8d7756ac4 100644 --- a/ujit_asm.c +++ b/ujit_asm.c @@ -613,6 +613,105 @@ 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 writeJcc(string mnem, opcode...)(CodeBlock cb, Label label) +{ + cb.writeASM(mnem, label); + + // Write the opcode + cb.writeBytes(opcode); + + // Add a reference to the label + cb.addLabelRef(label); + + // Relative 32-bit offset to be patched + cb.writeInt(0, 32); +} +*/ + +/* +/// jcc - Conditional relative jump to a label +alias ja = writeJcc!("ja", 0x0F, 0x87); +alias jae = writeJcc!("jae", 0x0F, 0x83); +alias jb = writeJcc!("jb", 0x0F, 0x82); +alias jbe = writeJcc!("jbe", 0x0F, 0x86); +alias jc = writeJcc!("jc", 0x0F, 0x82); +alias je = writeJcc!("je", 0x0F, 0x84); +alias jg = writeJcc!("jg", 0x0F, 0x8F); +alias jge = writeJcc!("jge", 0x0F, 0x8D); +alias jl = writeJcc!("jl", 0x0F, 0x8C); +alias jle = writeJcc!("jle", 0x0F, 0x8E); +alias jna = writeJcc!("jna", 0x0F, 0x86); +alias jnae = writeJcc!("jnae", 0x0F, 0x82); +alias jnb = writeJcc!("jnb", 0x0F, 0x83); +alias jnbe = writeJcc!("jnbe", 0x0F, 0x87); +alias jnc = writeJcc!("jnc", 0x0F, 0x83); +alias jne = writeJcc!("jne", 0x0F, 0x85); +alias jng = writeJcc!("jng", 0x0F, 0x8E); +alias jnge = writeJcc!("jnge", 0x0F, 0x8C); +alias jnl = writeJcc!("jnl", 0x0F, 0x8D); +alias jnle = writeJcc!("jnle", 0x0F, 0x8F); +alias jno = writeJcc!("jno", 0x0F, 0x81); +alias jnp = writeJcc!("jnp", 0x0F, 0x8b); +alias jns = writeJcc!("jns", 0x0F, 0x89); +alias jnz = writeJcc!("jnz", 0x0F, 0x85); +alias jo = writeJcc!("jo", 0x0F, 0x80); +alias jp = writeJcc!("jp", 0x0F, 0x8A); +alias jpe = writeJcc!("jpe", 0x0F, 0x8A); +alias jpo = writeJcc!("jpo", 0x0F, 0x8B); +alias js = writeJcc!("js", 0x0F, 0x88); +alias jz = writeJcc!("jz", 0x0F, 0x84); + +/// Opcode for direct jump with relative 8-bit offset +const ubyte JMP_REL8_OPCODE = 0xEB; + +/// Opcode for direct jump with relative 32-bit offset +const ubyte JMP_REL32_OPCODE = 0xE9; + +/// Opcode for jump on equal with relative 32-bit offset +const ubyte[] JE_REL32_OPCODE = [0x0F, 0x84]; + +/// jmp - Direct relative jump to label +alias jmp = writeJcc!("jmp", JMP_REL32_OPCODE); +*/ + +/// jmp - Indirect jump near to an R/M operand +void jmp(codeblock_t* cb, x86opnd_t opnd) +{ + //cb.writeASM("jmp", opnd); + cb_write_rm(cb, false, false, NO_OPND, opnd, 4, 1, 0xFF); +} + +/* +/// jmp - Jump with relative 8-bit offset +void jmp8(CodeBlock cb, int8_t offset) +{ + cb.writeASM("jmp", ((offset > 0)? "+":"-") ~ to!string(offset)); + cb.writeByte(JMP_REL8_OPCODE); + cb.writeByte(offset); +} + +/// jmp - Jump with relative 32-bit offset +void jmp32(CodeBlock cb, int32_t offset) +{ + cb.writeASM("jmp", ((offset > 0)? "+":"-") ~ to!string(offset)); + cb.writeByte(JMP_REL32_OPCODE); + cb.writeInt(offset, 32); +} +*/ + +/// lea - Load Effective Address +void lea(codeblock_t* cb, x86opnd_t dst, x86opnd_t src) +{ + //cb.writeASM("lea", dst, src); + assert (dst.num_bits == 64); + cb_write_rm(cb, false, true, dst, src, 0xFF, 1, 0x8D); +} + /// mov - Data move operation void mov(codeblock_t* cb, x86opnd_t dst, x86opnd_t src) { diff --git a/ujit_asm.h b/ujit_asm.h index 9facd68017..1f8ed35f8f 100644 --- a/ujit_asm.h +++ b/ujit_asm.h @@ -169,6 +169,7 @@ void cb_write_epilogue(codeblock_t* cb); // Encode individual instructions into a code block void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void call(codeblock_t* cb, x86opnd_t opnd); +void jmp(codeblock_t* cb, x86opnd_t opnd); void mov(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void nop(codeblock_t* cb, size_t length); void push(codeblock_t* cb, x86opnd_t reg); diff --git a/ujit_asm_tests.c b/ujit_asm_tests.c index ac148d1b7f..b705c7bfe7 100644 --- a/ujit_asm_tests.c +++ b/ujit_asm_tests.c @@ -105,6 +105,24 @@ 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"); + /* + // jcc + test( + delegate void (CodeBlock cb) { auto l = cb.label(Label.LOOP); cb.jge(l); }, + "0F8DFAFFFFFF" + ); + test( + delegate void (CodeBlock cb) { cb.label(Label.LOOP); cb.jo(Label.LOOP); }, + "0F80FAFFFFFF" + ); + */ + + // jmp + cb_set_pos(cb, 0); jmp(cb, R12); check_bytes(cb, "41FFE4"); + + // lea + //cb_set_pos(cb, 0); mov(cb, EBX, mem_opnd(32, RSP, 4))); check_bytes(cb, "8D5C2404"); + // mov /* test( @@ -117,7 +135,6 @@ void run_tests() ); */ cb_set_pos(cb, 0); mov(cb, R15, imm_opnd(3)); check_bytes(cb, "49BF0300000000000000"); - /* test( delegate void (CodeBlock cb) { cb.mov(X86Opnd(EAX), X86Opnd(EBX)); }, @@ -150,11 +167,6 @@ void run_tests() */ cb_set_pos(cb, 0); mov(cb, mem_opnd(8, RSP, 0), imm_opnd(-3)); check_bytes(cb, "C60424FD"); - - - - - // nop cb_set_pos(cb, 0); nop(cb, 1); check_bytes(cb, "90"); |