diff options
| author | Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> | 2020-10-23 10:59:22 -0400 |
|---|---|---|
| committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:25 -0400 |
| commit | b761f5c96ff1635aeeb26bb7ba6cb2b30adcddaf (patch) | |
| tree | 126c76c04bfca852b8369d2992bfc1821069790a | |
| parent | 498fe0fb52c4b3f7c8a4abdc9da1fffb2aa8c69b (diff) | |
Implemented mechanism for rel32 call
| -rw-r--r-- | ujit_asm.c | 36 | ||||
| -rw-r--r-- | ujit_asm.h | 1 | ||||
| -rw-r--r-- | ujit_compile.c | 3 |
3 files changed, 37 insertions, 3 deletions
diff --git a/ujit_asm.c b/ujit_asm.c index c99ad37d66..0b833445b2 100644 --- a/ujit_asm.c +++ b/ujit_asm.c @@ -758,7 +758,7 @@ void cb_write_jcc_ptr(codeblock_t* cb, const char* mnem, uint8_t op0, uint8_t op cb_write_byte(cb, op0); cb_write_byte(cb, op1); - // Pointer to the end of this jump + // Pointer to the end of this jump instruction uint8_t* end_ptr = &cb->mem_block[cb->write_pos] + 4; // Compute the jump offset @@ -822,6 +822,40 @@ void and(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1) ); } +// call - Call to a pointer with a 32-bit displacement offset +void call_rel32(codeblock_t* cb, int32_t rel32) +{ + //cb.writeASM("call", rel32); + + // Write the opcode + cb_write_byte(cb, 0xE8); + + // Write the relative 32-bit jump offset + cb_write_int(cb, (int32_t)rel32, 32); +} + +// call - Call a pointer, encode with a 32-bit offset if possible +void call_ptr(codeblock_t* cb, x86opnd_t scratch_reg, uint8_t* dst_ptr) +{ + assert (scratch_reg.type == OPND_REG); + + // Pointer to the end of this call instruction + uint8_t* end_ptr = &cb->mem_block[cb->write_pos] + 5; + + // Compute the jump offset + int64_t rel64 = (int64_t)(dst_ptr - end_ptr); + + // If the offset fits in 32-bit + if (rel64 >= -2147483648 && rel64 <= 2147483647) + { + return call_rel32(cb, (int32_t)rel64); + } + + // Move the pointer into the scratch register and call + mov(cb, scratch_reg, const_ptr_opnd(dst_ptr)); + call(cb, scratch_reg); +} + /// call - Call to label with 32-bit offset void call_label(codeblock_t* cb, size_t label_idx) { diff --git a/ujit_asm.h b/ujit_asm.h index 6d6b18b0a9..ca5e8884ce 100644 --- a/ujit_asm.h +++ b/ujit_asm.h @@ -254,6 +254,7 @@ void cb_link_labels(codeblock_t* cb); // Encode individual instructions into a code block void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void and(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); +void call_ptr(codeblock_t* cb, x86opnd_t scratch_reg, uint8_t* dst_ptr); void call_label(codeblock_t* cb, size_t label_idx); void call(codeblock_t* cb, x86opnd_t opnd); void cmova(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); diff --git a/ujit_compile.c b/ujit_compile.c index dcf4b672c9..678f84c977 100644 --- a/ujit_compile.c +++ b/ujit_compile.c @@ -668,8 +668,7 @@ gen_opt_send_without_block(codeblock_t* cb, codeblock_t* ocb, ctx_t* ctx) // Call the C function // VALUE ret = (cfunc->func)(recv, argv[0], argv[1]); - mov(cb, REG0, const_ptr_opnd(cfunc->func)); - call(cb, REG0); + call_ptr(cb, REG0, cfunc->func); //print_str(cb, "after C call"); |
