diff options
author | Takashi Kokubun <[email protected]> | 2023-03-10 14:09:34 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2023-03-10 14:57:37 -0800 |
commit | 93e34fe42e81d72a3e45501bf3f200ca5e78442f (patch) | |
tree | f7f2184bb2089549730488d8b863f3d7d7043d99 /test/ruby/rjit/test_assembler.rb | |
parent | 83f6eee76cbffbfd363e0bd9d633914e257d68e8 (diff) |
RJIT: Write initial tests for Assembler
Diffstat (limited to 'test/ruby/rjit/test_assembler.rb')
-rw-r--r-- | test/ruby/rjit/test_assembler.rb | 265 |
1 files changed, 258 insertions, 7 deletions
diff --git a/test/ruby/rjit/test_assembler.rb b/test/ruby/rjit/test_assembler.rb index 12d73b2410..d32f6676db 100644 --- a/test/ruby/rjit/test_assembler.rb +++ b/test/ruby/rjit/test_assembler.rb @@ -19,24 +19,270 @@ module RubyVM::RJIT def test_add asm = Assembler.new - asm.add(:rax, 255) - assert_compile(asm, '0x0: add rax, 0xff') + asm.add([:rcx], 1) # ADD r/m64, imm8 (Mod 00: [reg]) + asm.add(:rax, 0x7f) # ADD r/m64, imm8 (Mod 11: reg) + asm.add(:rbx, 0x7fffffff) # ADD r/m64 imm32 (Mod 11: reg) + asm.add(:rsi, :rdi) # ADD r/m64, r64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: add qword ptr [rcx], 1 + 0x4: add rax, 0x7f + 0x8: add rbx, 0x7fffffff + 0xf: add rsi, rdi + EOS + end + + def test_and + asm = Assembler.new + asm.and(:rax, 0) # AND r/m64, imm8 (Mod 11: reg) + asm.and(:rbx, 0x7fffffff) # AND r/m64, imm32 (Mod 11: reg) + asm.and(:rcx, [:rdi, 8]) # AND r64, r/m64 (Mod 01: [reg]+disp8) + assert_compile(asm, <<~EOS) + 0x0: and rax, 0 + 0x4: and rbx, 0x7fffffff + 0xb: and rcx, qword ptr [rdi + 8] + EOS + end + + def test_call + asm = Assembler.new + asm.call(rel32(0xff)) # CALL rel32 + asm.call(:rax) # CALL r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: call 0xff + 0x5: call rax + EOS + end + + def test_cmove + asm = Assembler.new + asm.cmove(:rax, :rcx) # CMOVE r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: cmove rax, rcx + EOS + end + + def test_cmovg + asm = Assembler.new + asm.cmovg(:rbx, :rdi) # CMOVG r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: cmovg rbx, rdi + EOS + end + + def test_cmovge + asm = Assembler.new + asm.cmovge(:rsp, :rbp) # CMOVGE r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: cmovge rsp, rbp + EOS + end + + def test_cmovl + asm = Assembler.new + asm.cmovl(:rdx, :rsp) # CMOVL r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: cmovl rdx, rsp + EOS + end + + def test_cmovle + asm = Assembler.new + asm.cmovle(:rax, :rax) # CMOVLE r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: cmovle rax, rax + EOS + end + + def test_cmovnz + asm = Assembler.new + asm.cmovnz(:rax, :rbx) # CMOVNZ r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) # cmovne == cmovnz + 0x0: cmovne rax, rbx + EOS + end + + def test_cmovz + asm = Assembler.new + asm.cmovz(:rax, :rbx) # CMOVZ r64, r/m64 (Mod 11: reg) + assert_compile(asm, <<~EOS) # cmove == cmovz + 0x0: cmove rax, rbx + EOS + end + + def test_cmp + asm = Assembler.new + asm.cmp(:rax, 0) # CMP r/m64, imm8 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: cmp rax, 0 + EOS + end + + def test_jbe + asm = Assembler.new + asm.jbe(rel32(0xff)) # JBE rel32 + assert_compile(asm, <<~EOS) + 0x0: jbe 0xff + EOS + end + + def test_je + asm = Assembler.new + asm.je(rel32(0xff)) # JE rel32 + assert_compile(asm, <<~EOS) + 0x0: je 0xff + EOS + end + + def test_jl + asm = Assembler.new + asm.jl(rel32(0xff)) # JL rel32 + assert_compile(asm, <<~EOS) + 0x0: jl 0xff + EOS end def test_jmp asm = Assembler.new label = asm.new_label('label') - asm.jmp(label) + asm.jmp(label) # JZ rel8 asm.write_label(label) - asm.jmp(label) + asm.jmp(rel32(0xff)) # JMP rel32 + asm.jmp([:rax, 8]) # JMP r/m64 (Mod 01: [reg]+disp8) + asm.jmp(:rax) # JMP r/m64 (Mod 11: reg) assert_compile(asm, <<~EOS) 0x0: jmp 0x2 - 0x2: jmp 0x2 + 0x2: jmp 0xff + 0x7: jmp qword ptr [rax + 8] + 0xa: jmp rax + EOS + end + + def test_jne + asm = Assembler.new + asm.jne(rel32(0xff)) # JNE rel32 + assert_compile(asm, <<~EOS) + 0x0: jne 0xff + EOS + end + + def test_jnz + asm = Assembler.new + asm.jnz(rel32(0xff)) # JNZ rel32 + assert_compile(asm, <<~EOS) + 0x0: jne 0xff + EOS + end + + def test_jo + asm = Assembler.new + asm.jo(rel32(0xff)) # JO rel32 + assert_compile(asm, <<~EOS) + 0x0: jo 0xff + EOS + end + + def test_jz + asm = Assembler.new + asm.jz(rel32(0xff)) # JZ rel32 + assert_compile(asm, <<~EOS) + 0x0: je 0xff + EOS + end + + def test_lea + asm = Assembler.new + asm.lea(:rax, [:rax, 8]) # LEA r64,m (Mod 01: [reg]+disp8) + asm.lea(:rax, [:rax, 0xffff]) # LEA r64,m (Mod 10: [reg]+disp32) + assert_compile(asm, <<~EOS) + 0x0: lea rax, [rax + 8] + 0x4: lea rax, [rax + 0xffff] + EOS + end + + def test_mov + asm = Assembler.new + asm.mov(:rax, :rbx) # MOV r64, r/m64 (Mod 00: [reg]) + asm.mov(:rax, [:rbx, 8]) # MOV r64, r/m64 (Mod 01: [reg]+disp8) + assert_compile(asm, <<~EOS) + 0x0: mov rax, rbx + 0x3: mov rax, qword ptr [rbx + 8] + EOS + end + + def test_or + asm = Assembler.new + asm.or(:rax, 0) # OR r/m64, imm8 (Mod 11: reg) + asm.or(:rax, 0xffff) # OR r/m64, imm32 (Mod 11: reg) + asm.or(:rax, [:rbx, 8]) # OR r64, r/m64 (Mod 01: [reg]+disp8) + assert_compile(asm, <<~EOS) + 0x0: or rax, 0 + 0x4: or rax, 0xffff + 0xb: or rax, qword ptr [rbx + 8] + EOS + end + + def test_push + asm = Assembler.new + asm.push(:rax) # PUSH r64 + assert_compile(asm, <<~EOS) + 0x0: push rax + EOS + end + + def test_pop + asm = Assembler.new + asm.pop(:rax) # POP r64 + assert_compile(asm, <<~EOS) + 0x0: pop rax + EOS + end + + def test_ret + asm = Assembler.new + asm.ret # RET + assert_compile(asm, "0x0: ret \n") + end + + def test_sar + asm = Assembler.new + asm.sar(:rax, 0) # SAR r/m64, imm8 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: sar rax, 0 + EOS + end + + def test_sub + asm = Assembler.new + asm.sub(:rax, 0) # SUB r/m64, imm8 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: sub rax, 0 + EOS + end + + def test_test + asm = Assembler.new + asm.test(BytePtr[:rax, 8], 16) # TEST r/m8*, imm8 (Mod 01: [reg]+disp8) + asm.test([:rax, 8], 8) # TEST r/m64, imm32 (Mod 01: [reg]+disp8) + asm.test([:rax, 0xffff], 0xffff) # TEST r/m64, imm32 (Mod 10: [reg]+disp32) + asm.test(:rax, 0xffff) # TEST r/m64, imm32 (Mod 11: reg) + asm.test(:eax, :ebx) # TEST r/m32, r32 (Mod 11: reg) + asm.test(:rax, :rbx) # TEST r/m64, r64 (Mod 11: reg) + assert_compile(asm, <<~EOS) + 0x0: test byte ptr [rax + 8], 0x10 + 0x4: test qword ptr [rax + 8], 8 + 0xc: test qword ptr [rax + 0xffff], 0xffff + 0x17: test rax, 0xffff + 0x1e: test eax, ebx + 0x20: test rax, rbx EOS end private + def rel32(offset) + @cb.write_addr + 0xff + end + def assert_compile(asm, expected) actual = compile(asm) assert_equal expected, actual, "---\n#{actual}---" @@ -54,8 +300,13 @@ module RubyVM::RJIT disasm.gsub!(/^ /, '') disasm.sub!(/\n\z/, '') - if disasm.lines.size == 1 - disasm.rstrip! + disasm.gsub!(/0x(\h{12})/) do + offset = $1.to_i(16) - start_addr + if offset.negative? + "-0x#{offset.to_s(16)}" + else + "0x#{offset.to_s(16)}" + end end (start_addr...end_addr).each do |addr| disasm.gsub!("0x#{addr.to_s(16)}", "0x#{(addr - start_addr).to_s(16)}") |