summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/mjit/insn_compiler.rb15
-rw-r--r--lib/mjit/x86_assembler.rb26
-rw-r--r--lib/ruby_vm/mjit/compiler.rb47
3 files changed, 58 insertions, 30 deletions
diff --git a/lib/mjit/insn_compiler.rb b/lib/mjit/insn_compiler.rb
index c6f88b37fb..4dbb19a96e 100644
--- a/lib/mjit/insn_compiler.rb
+++ b/lib/mjit/insn_compiler.rb
@@ -1,14 +1,21 @@
module RubyVM::MJIT
+ # ec: rdi
+ # cfp: rsi
+ # sp: rbx
+ # scratch regs: rax
class InsnCompiler
- def putnil(_asm)
- # TODO
+ # Ruby constants
+ Qnil = Fiddle::Qnil
+
+ def putnil(asm)
+ asm.mov([:rbx], Qnil)
KeepCompiling
end
def leave(asm)
# pop the current frame (ec->cfp++)
- asm.add(:rsi, C.rb_control_frame_t.size)
- asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi)
+ asm.add(:rsi, C.rb_control_frame_t.size) # rsi = cfp + 1
+ asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi) # ec->cfp = rsi
# return a value
asm.mov(:rax, 1001)
diff --git a/lib/mjit/x86_assembler.rb b/lib/mjit/x86_assembler.rb
index 934bf071c7..bc447e7808 100644
--- a/lib/mjit/x86_assembler.rb
+++ b/lib/mjit/x86_assembler.rb
@@ -43,14 +43,24 @@ module RubyVM::MJIT
def mov(dst, src)
case [dst, src]
- # MOV r/m64, imm32
+ # MOV r/m64, imm32 (Mod 00)
+ in [[Symbol => dst_reg], Integer => src_imm] if r_reg?(dst_reg)
+ # REX.W + C7 /0 id
+ # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
+ insn(
+ prefix: REX_W,
+ opcode: 0xc7,
+ mod_rm: mod_rm(mod: 0b00, rm: reg_code(dst_reg)), # Mod 00: [reg]
+ imm: imm32(src_imm),
+ )
+ # MOV r/m64, imm32 (Mod 11)
in [Symbol => dst_reg, Integer => src_imm] if r_reg?(dst_reg)
# REX.W + C7 /0 id
# MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
insn(
prefix: REX_W,
opcode: 0xc7,
- mod_rm: mod_rm(mod: 0b11, rm: reg_code(dst_reg)),
+ mod_rm: mod_rm(mod: 0b11, rm: reg_code(dst_reg)), # Mod 11: reg
imm: imm32(src_imm),
)
# MOV r/m64, r64
@@ -60,9 +70,19 @@ module RubyVM::MJIT
insn(
prefix: REX_W,
opcode: 0x89,
- mod_rm: mod_rm(mod: 0b01, reg: reg_code(src_reg), rm: reg_code(dst_reg)), # disp8
+ mod_rm: mod_rm(mod: 0b01, reg: reg_code(src_reg), rm: reg_code(dst_reg)), # Mod 01: [reg]+disp8
disp: dst_offset,
)
+ # MOV r64, r/m64
+ in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_offset]] if r_reg?(dst_reg) && r_reg?(src_reg) && src_offset <= 0xff
+ # REX.W + 8B /r
+ # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
+ insn(
+ prefix: REX_W,
+ opcode: 0x8b,
+ mod_rm: mod_rm(mod: 0b01, reg: reg_code(dst_reg), rm: reg_code(src_reg)), # Mod 01: [reg]+disp8
+ disp: src_offset,
+ )
else
raise NotImplementedError, "mov: not-implemented input: #{dst.inspect}, #{src.inspect}"
end
diff --git a/lib/ruby_vm/mjit/compiler.rb b/lib/ruby_vm/mjit/compiler.rb
index 75314501c1..9383c189b2 100644
--- a/lib/ruby_vm/mjit/compiler.rb
+++ b/lib/ruby_vm/mjit/compiler.rb
@@ -9,9 +9,6 @@ module RubyVM::MJIT
EndBlock = :end_block
class Compiler
- # Ruby constants
- Qundef = Fiddle::Qundef
-
attr_accessor :write_pos
# @param mem_block [Integer] JIT buffer address
@@ -24,7 +21,11 @@ module RubyVM::MJIT
# @param iseq [RubyVM::MJIT::CPointer::Struct]
def call(iseq)
return if iseq.body.location.label == '<main>'
- iseq.body.jit_func = compile_block(iseq)
+
+ asm = X86Assembler.new
+ compile_prologue(asm)
+ compile_block(asm, iseq)
+ iseq.body.jit_func = compile(asm)
rescue Exception => e
$stderr.puts e.full_message # TODO: check verbose
end
@@ -35,25 +36,13 @@ module RubyVM::MJIT
private
- def compile(asm)
- start_addr = write_addr
-
- C.mjit_mark_writable
- @write_pos += asm.compile(start_addr)
- C.mjit_mark_executable
-
- end_addr = write_addr
- if C.mjit_opts.dump_disasm && start_addr < end_addr
- dump_disasm(start_addr, end_addr)
- end
- start_addr
+ # ec: rdi
+ # cfp: rsi
+ def compile_prologue(asm)
+ asm.mov(:rbx, [:rsi, C.rb_control_frame_t.offsetof(:sp)]) # rbx = cfp->sp
end
- # ec -> RDI, cfp -> RSI
- def compile_block(iseq)
- addr = write_addr
- asm = X86Assembler.new
-
+ def compile_block(asm, iseq)
index = 0
while index < iseq.body.iseq_size
insn = decode_insn(iseq.body.iseq_encoded[index])
@@ -63,8 +52,6 @@ module RubyVM::MJIT
end
index += insn.len
end
-
- compile(asm)
end
def compile_insn(asm, insn)
@@ -75,6 +62,20 @@ module RubyVM::MJIT
end
end
+ def compile(asm)
+ start_addr = write_addr
+
+ C.mjit_mark_writable
+ @write_pos += asm.compile(start_addr)
+ C.mjit_mark_executable
+
+ end_addr = write_addr
+ if C.mjit_opts.dump_disasm && start_addr < end_addr
+ dump_disasm(start_addr, end_addr)
+ end
+ start_addr
+ end
+
def decode_insn(encoded)
INSNS.fetch(C.rb_vm_insn_decode(encoded))
end