class RubyVM::RJIT::Assembler

cdrdv2.intel.com/v1/dl/getContent/671110 Mostly an x86_64 assembler, but this also has some stuff that is useful for any architecture.

Constants

IMM32
IMM64
IMM8
Mod00
Mod01
Mod10
Mod11
R32

Operand matchers

R64
REX_B

REX = 0100WR0B

REX_R
REX_W
Rel32Pad

Attributes

comments[R]

Utilities

Public Class Methods

new() click to toggle source
# File ruby_vm/rjit/assembler.rb, line 45
def initialize
  @bytes = []
  @labels = {}
  @label_id = 0
  @comments = Hash.new { |h, k| h[k] = [] }
  @blocks = Hash.new { |h, k| h[k] = [] }
  @stub_starts = Hash.new { |h, k| h[k] = [] }
  @stub_ends = Hash.new { |h, k| h[k] = [] }
  @pos_markers = Hash.new { |h, k| h[k] = [] }
end

Public Instance Methods

add(dst, src) click to toggle source

Instructions

# File ruby_vm/rjit/assembler.rb, line 79
def add(dst, src)
  case [dst, src]
  # ADD r/m64, imm8 (Mod 00: [reg])
  in [QwordPtr[R64 => dst_reg], IMM8 => src_imm]
    # REX.W + 83 /0 ib
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod00, reg: 0, rm: dst_reg],
      imm: imm8(src_imm),
    )
  # ADD r/m64, imm8 (Mod 11: reg)
  in [R64 => dst_reg, IMM8 => src_imm]
    # REX.W + 83 /0 ib
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod11, reg: 0, rm: dst_reg],
      imm: imm8(src_imm),
    )
  # ADD r/m64 imm32 (Mod 11: reg)
  in [R64 => dst_reg, IMM32 => src_imm]
    # REX.W + 81 /0 id
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x81,
      mod_rm: ModRM[mod: Mod11, reg: 0, rm: dst_reg],
      imm: imm32(src_imm),
    )
  # ADD r/m64, r64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 01 /r
    # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x01,
      mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
    )
  end
end
and(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 123
def and(dst, src)
  case [dst, src]
  # AND r/m64, imm8 (Mod 11: reg)
  in [R64 => dst_reg, IMM8 => src_imm]
    # REX.W + 83 /4 ib
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg],
      imm: imm8(src_imm),
    )
  # AND r/m64, imm32 (Mod 11: reg)
  in [R64 => dst_reg, IMM32 => src_imm]
    # REX.W + 81 /4 id
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x81,
      mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg],
      imm: imm32(src_imm),
    )
  # AND r64, r/m64 (Mod 01: [reg]+disp8)
  in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
    # REX.W + 23 /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: 0x23,
      mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
      disp: imm8(src_disp),
    )
  end
end
assemble(addr) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 56
def assemble(addr)
  set_code_addrs(addr)
  resolve_rel32(addr)
  resolve_labels

  write_bytes(addr)

  @pos_markers.each do |write_pos, markers|
    markers.each { |marker| marker.call(addr + write_pos) }
  end
  @bytes.size
ensure
  @bytes.clear
end
block(block) click to toggle source

Mark the starting address of a block

# File ruby_vm/rjit/assembler.rb, line 884
def block(block)
  @blocks[@bytes.size] << block
end
call(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 158
def call(dst)
  case dst
  # CALL rel32
  in Integer => dst_addr
    # E8 cd
    # D: Operand 1: Offset
    insn(opcode: 0xe8, imm: rel32(dst_addr))
  # CALL r/m64 (Mod 11: reg)
  in R64 => dst_reg
    # FF /2
    # M: Operand 1: ModRM:r/m (r)
    insn(
      opcode: 0xff,
      mod_rm: ModRM[mod: Mod11, reg: 2, rm: dst_reg],
    )
  end
end
cmove(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 176
def cmove(dst, src)
  case [dst, src]
  # CMOVE r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 44 /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x44],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovg(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 190
def cmovg(dst, src)
  case [dst, src]
  # CMOVG r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 4F /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x4f],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovge(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 204
def cmovge(dst, src)
  case [dst, src]
  # CMOVGE r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 4D /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x4d],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovl(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 218
def cmovl(dst, src)
  case [dst, src]
  # CMOVL r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 4C /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x4c],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovle(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 232
def cmovle(dst, src)
  case [dst, src]
  # CMOVLE r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 4E /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x4e],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovne(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 246
def cmovne(dst, src)
  case [dst, src]
  # CMOVNE r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 45 /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x45],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovnz(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 260
def cmovnz(dst, src)
  case [dst, src]
  # CMOVNZ r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 45 /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x45],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  end
end
cmovz(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 274
def cmovz(dst, src)
  case [dst, src]
  # CMOVZ r64, r/m64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 0F 44 /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x44],
      mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
    )
  # CMOVZ r64, r/m64 (Mod 01: [reg]+disp8)
  in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
    # REX.W + 0F 44 /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: [0x0f, 0x44],
      mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
      disp: imm8(src_disp),
    )
  end
end
cmp(left, right) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 298
def cmp(left, right)
  case [left, right]
  # CMP r/m8, imm8 (Mod 01: [reg]+disp8)
  in [BytePtr[R64 => left_reg, IMM8 => left_disp], IMM8 => right_imm]
    # 80 /7 ib
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      opcode: 0x80,
      mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
      disp: left_disp,
      imm: imm8(right_imm),
    )
  # CMP r/m32, imm32 (Mod 01: [reg]+disp8)
  in [DwordPtr[R64 => left_reg, IMM8 => left_disp], IMM32 => right_imm]
    # 81 /7 id
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      opcode: 0x81,
      mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
      disp: left_disp,
      imm: imm32(right_imm),
    )
  # CMP r/m64, imm8 (Mod 01: [reg]+disp8)
  in [QwordPtr[R64 => left_reg, IMM8 => left_disp], IMM8 => right_imm]
    # REX.W + 83 /7 ib
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
      disp: left_disp,
      imm: imm8(right_imm),
    )
  # CMP r/m64, imm8 (Mod 10: [reg]+disp32)
  in [QwordPtr[R64 => left_reg, IMM32 => left_disp], IMM8 => right_imm]
    # REX.W + 83 /7 ib
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod10, reg: 7, rm: left_reg],
      disp: imm32(left_disp),
      imm: imm8(right_imm),
    )
  # CMP r/m64, imm8 (Mod 11: reg)
  in [R64 => left_reg, IMM8 => right_imm]
    # REX.W + 83 /7 ib
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod11, reg: 7, rm: left_reg],
      imm: imm8(right_imm),
    )
  # CMP r/m64, imm32 (Mod 11: reg)
  in [R64 => left_reg, IMM32 => right_imm]
    # REX.W + 81 /7 id
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x81,
      mod_rm: ModRM[mod: Mod11, reg: 7, rm: left_reg],
      imm: imm32(right_imm),
    )
  # CMP r/m64, r64 (Mod 01: [reg]+disp8)
  in [QwordPtr[R64 => left_reg, IMM8 => left_disp], R64 => right_reg]
    # REX.W + 39 /r
    # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x39,
      mod_rm: ModRM[mod: Mod01, reg: right_reg, rm: left_reg],
      disp: left_disp,
    )
  # CMP r/m64, r64 (Mod 10: [reg]+disp32)
  in [QwordPtr[R64 => left_reg, IMM32 => left_disp], R64 => right_reg]
    # REX.W + 39 /r
    # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x39,
      mod_rm: ModRM[mod: Mod10, reg: right_reg, rm: left_reg],
      disp: imm32(left_disp),
    )
  # CMP r/m64, r64 (Mod 11: reg)
  in [R64 => left_reg, R64 => right_reg]
    # REX.W + 39 /r
    # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x39,
      mod_rm: ModRM[mod: Mod11, reg: right_reg, rm: left_reg],
    )
  end
end
comment(message) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 879
def comment(message)
  @comments[@bytes.size] << message
end
incr_counter(name) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 909
def incr_counter(name)
  if C.rjit_opts.stats
    comment("increment counter #{name}")
    mov(:rax, C.rb_rjit_counters[name].to_i)
    add([:rax], 1) # TODO: lock
  end
end
jbe(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 394
def jbe(dst)
  case dst
  # JBE rel8
  in Label => dst_label
    # 76 cb
    insn(opcode: 0x76, imm: dst_label)
  # JBE rel32
  in Integer => dst_addr
    # 0F 86 cd
    insn(opcode: [0x0f, 0x86], imm: rel32(dst_addr))
  end
end
je(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 407
def je(dst)
  case dst
  # JE rel8
  in Label => dst_label
    # 74 cb
    insn(opcode: 0x74, imm: dst_label)
  # JE rel32
  in Integer => dst_addr
    # 0F 84 cd
    insn(opcode: [0x0f, 0x84], imm: rel32(dst_addr))
  end
end
jl(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 420
def jl(dst)
  case dst
  # JL rel32
  in Integer => dst_addr
    # 0F 8C cd
    insn(opcode: [0x0f, 0x8c], imm: rel32(dst_addr))
  end
end
jmp(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 429
def jmp(dst)
  case dst
  # JZ rel8
  in Label => dst_label
    # EB cb
    insn(opcode: 0xeb, imm: dst_label)
  # JMP rel32
  in Integer => dst_addr
    # E9 cd
    insn(opcode: 0xe9, imm: rel32(dst_addr))
  # JMP r/m64 (Mod 01: [reg]+disp8)
  in QwordPtr[R64 => dst_reg, IMM8 => dst_disp]
    # FF /4
    insn(opcode: 0xff, mod_rm: ModRM[mod: Mod01, reg: 4, rm: dst_reg], disp: dst_disp)
  # JMP r/m64 (Mod 11: reg)
  in R64 => dst_reg
    # FF /4
    insn(opcode: 0xff, mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg])
  end
end
jne(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 450
def jne(dst)
  case dst
  # JNE rel8
  in Label => dst_label
    # 75 cb
    insn(opcode: 0x75, imm: dst_label)
  # JNE rel32
  in Integer => dst_addr
    # 0F 85 cd
    insn(opcode: [0x0f, 0x85], imm: rel32(dst_addr))
  end
end
jnz(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 463
def jnz(dst)
  case dst
  # JE rel8
  in Label => dst_label
    # 75 cb
    insn(opcode: 0x75, imm: dst_label)
  # JNZ rel32
  in Integer => dst_addr
    # 0F 85 cd
    insn(opcode: [0x0f, 0x85], imm: rel32(dst_addr))
  end
end
jo(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 476
def jo(dst)
  case dst
  # JO rel32
  in Integer => dst_addr
    # 0F 80 cd
    insn(opcode: [0x0f, 0x80], imm: rel32(dst_addr))
  end
end
jz(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 485
def jz(dst)
  case dst
  # JZ rel8
  in Label => dst_label
    # 74 cb
    insn(opcode: 0x74, imm: dst_label)
  # JZ rel32
  in Integer => dst_addr
    # 0F 84 cd
    insn(opcode: [0x0f, 0x84], imm: rel32(dst_addr))
  end
end
lea(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 498
def lea(dst, src)
  case [dst, src]
  # LEA r64,m (Mod 01: [reg]+disp8)
  in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
    # REX.W + 8D /r
    # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: 0x8d,
      mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
      disp: imm8(src_disp),
    )
  # LEA r64,m (Mod 10: [reg]+disp32)
  in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM32 => src_disp]]
    # REX.W + 8D /r
    # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: 0x8d,
      mod_rm: ModRM[mod: Mod10, reg: dst_reg, rm: src_reg],
      disp: imm32(src_disp),
    )
  end
end
mov(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 523
def mov(dst, src)
  case dst
  in R32 => dst_reg
    case src
    # MOV r32 r/m32 (Mod 01: [reg]+disp8)
    in DwordPtr[R64 => src_reg, IMM8 => src_disp]
      # 8B /r
      # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
      insn(
        opcode: 0x8b,
        mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
        disp: src_disp,
      )
    # MOV r32, imm32 (Mod 11: reg)
    in IMM32 => src_imm
      # B8+ rd id
      # OI: Operand 1: opcode + rd (w), Operand 2: imm8/16/32/64
      insn(
        opcode: 0xb8,
        rd: dst_reg,
        imm: imm32(src_imm),
      )
    end
  in R64 => dst_reg
    case src
    # MOV r64, r/m64 (Mod 00: [reg])
    in QwordPtr[R64 => src_reg]
      # REX.W + 8B /r
      # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
      insn(
        prefix: REX_W,
        opcode: 0x8b,
        mod_rm: ModRM[mod: Mod00, reg: dst_reg, rm: src_reg],
      )
    # MOV r64, r/m64 (Mod 01: [reg]+disp8)
    in QwordPtr[R64 => src_reg, IMM8 => src_disp]
      # REX.W + 8B /r
      # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
      insn(
        prefix: REX_W,
        opcode: 0x8b,
        mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
        disp: src_disp,
      )
    # MOV r64, r/m64 (Mod 10: [reg]+disp32)
    in QwordPtr[R64 => src_reg, IMM32 => src_disp]
      # REX.W + 8B /r
      # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
      insn(
        prefix: REX_W,
        opcode: 0x8b,
        mod_rm: ModRM[mod: Mod10, reg: dst_reg, rm: src_reg],
        disp: imm32(src_disp),
      )
    # MOV r64, r/m64 (Mod 11: reg)
    in R64 => src_reg
      # REX.W + 8B /r
      # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
      insn(
        prefix: REX_W,
        opcode: 0x8b,
        mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
      )
    # MOV r/m64, imm32 (Mod 11: reg)
    in IMM32 => src_imm
      # 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: ModRM[mod: Mod11, reg: 0, rm: dst_reg],
        imm: imm32(src_imm),
      )
    # MOV r64, imm64
    in IMM64 => src_imm
      # REX.W + B8+ rd io
      # OI: Operand 1: opcode + rd (w), Operand 2: imm8/16/32/64
      insn(
        prefix: REX_W,
        opcode: 0xb8,
        rd: dst_reg,
        imm: imm64(src_imm),
      )
    end
  in DwordPtr[R64 => dst_reg, IMM8 => dst_disp]
    case src
    # MOV r/m32, imm32 (Mod 01: [reg]+disp8)
    in IMM32 => src_imm
      # C7 /0 id
      # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
      insn(
        opcode: 0xc7,
        mod_rm: ModRM[mod: Mod01, reg: 0, rm: dst_reg],
        disp: dst_disp,
        imm: imm32(src_imm),
      )
    end
  in QwordPtr[R64 => dst_reg]
    case src
    # MOV r/m64, imm32 (Mod 00: [reg])
    in IMM32 => src_imm
      # 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: ModRM[mod: Mod00, reg: 0, rm: dst_reg],
        imm: imm32(src_imm),
      )
    # MOV r/m64, r64 (Mod 00: [reg])
    in R64 => src_reg
      # REX.W + 89 /r
      # MR: Operand 1: ModRM:r/m (w), Operand 2: ModRM:reg (r)
      insn(
        prefix: REX_W,
        opcode: 0x89,
        mod_rm: ModRM[mod: Mod00, reg: src_reg, rm: dst_reg],
      )
    end
  in QwordPtr[R64 => dst_reg, IMM8 => dst_disp]
    # Optimize encoding when disp is 0
    return mov([dst_reg], src) if dst_disp == 0

    case src
    # MOV r/m64, imm32 (Mod 01: [reg]+disp8)
    in IMM32 => src_imm
      # 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: ModRM[mod: Mod01, reg: 0, rm: dst_reg],
        disp: dst_disp,
        imm: imm32(src_imm),
      )
    # MOV r/m64, r64 (Mod 01: [reg]+disp8)
    in R64 => src_reg
      # REX.W + 89 /r
      # MR: Operand 1: ModRM:r/m (w), Operand 2: ModRM:reg (r)
      insn(
        prefix: REX_W,
        opcode: 0x89,
        mod_rm: ModRM[mod: Mod01, reg: src_reg, rm: dst_reg],
        disp: dst_disp,
      )
    end
  in QwordPtr[R64 => dst_reg, IMM32 => dst_disp]
    case src
    # MOV r/m64, imm32 (Mod 10: [reg]+disp32)
    in IMM32 => src_imm
      # 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: ModRM[mod: Mod10, reg: 0, rm: dst_reg],
        disp: imm32(dst_disp),
        imm: imm32(src_imm),
      )
    # MOV r/m64, r64 (Mod 10: [reg]+disp32)
    in R64 => src_reg
      # REX.W + 89 /r
      # MR: Operand 1: ModRM:r/m (w), Operand 2: ModRM:reg (r)
      insn(
        prefix: REX_W,
        opcode: 0x89,
        mod_rm: ModRM[mod: Mod10, reg: src_reg, rm: dst_reg],
        disp: imm32(dst_disp),
      )
    end
  end
end
new_label(name) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 900
def new_label(name)
  Label.new(id: @label_id += 1, name:)
end
or(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 696
def or(dst, src)
  case [dst, src]
  # OR r/m64, imm8 (Mod 11: reg)
  in [R64 => dst_reg, IMM8 => src_imm]
    # REX.W + 83 /1 ib
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod11, reg: 1, rm: dst_reg],
      imm: imm8(src_imm),
    )
  # OR r/m64, imm32 (Mod 11: reg)
  in [R64 => dst_reg, IMM32 => src_imm]
    # REX.W + 81 /1 id
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x81,
      mod_rm: ModRM[mod: Mod11, reg: 1, rm: dst_reg],
      imm: imm32(src_imm),
    )
  # OR r64, r/m64 (Mod 01: [reg]+disp8)
  in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
    # REX.W + 0B /r
    # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
    insn(
      prefix: REX_W,
      opcode: 0x0b,
      mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
      disp: imm8(src_disp),
    )
  end
end
pop(dst) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 741
def pop(dst)
  case dst
  # POP r64
  in R64 => dst_reg
    # 58+ rd
    # O: Operand 1: opcode + rd (r)
    insn(opcode: 0x58, rd: dst_reg)
  end
end
pos_marker(&block) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 896
def pos_marker(&block)
  @pos_markers[@bytes.size] << block
end
push(src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 731
def push(src)
  case src
  # PUSH r64
  in R64 => src_reg
    # 50+rd
    # O: Operand 1: opcode + rd (r)
    insn(opcode: 0x50, rd: src_reg)
  end
end
ret() click to toggle source
# File ruby_vm/rjit/assembler.rb, line 751
def ret
  # RET
  # Near return: A return to a procedure within the current code segment
  insn(opcode: 0xc3)
end
sar(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 757
def sar(dst, src)
  case [dst, src]
  in [R64 => dst_reg, IMM8 => src_imm]
    # REX.W + C1 /7 ib
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8
    insn(
      prefix: REX_W,
      opcode: 0xc1,
      mod_rm: ModRM[mod: Mod11, reg: 7, rm: dst_reg],
      imm: imm8(src_imm),
    )
  end
end
size() click to toggle source
# File ruby_vm/rjit/assembler.rb, line 71
def size
  @bytes.size
end
stub(stub) { || ... } click to toggle source

Mark the starting/ending addresses of a stub

# File ruby_vm/rjit/assembler.rb, line 889
def stub(stub)
  @stub_starts[@bytes.size] << stub
  yield
ensure
  @stub_ends[@bytes.size] << stub
end
sub(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 771
def sub(dst, src)
  case [dst, src]
  # SUB r/m64, imm8 (Mod 11: reg)
  in [R64 => dst_reg, IMM8 => src_imm]
    # REX.W + 83 /5 ib
    # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0x83,
      mod_rm: ModRM[mod: Mod11, reg: 5, rm: dst_reg],
      imm: imm8(src_imm),
    )
  # SUB r/m64, r64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 29 /r
    # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x29,
      mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
    )
  end
end
test(left, right) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 795
def test(left, right)
  case [left, right]
  # TEST r/m8*, imm8 (Mod 01: [reg]+disp8)
  in [BytePtr[R64 => left_reg, IMM8 => left_disp], IMM8 => right_imm]
    # REX + F6 /0 ib
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      opcode: 0xf6,
      mod_rm: ModRM[mod: Mod01, reg: 0, rm: left_reg],
      disp: left_disp,
      imm: imm8(right_imm),
    )
  # TEST r/m64, imm32 (Mod 01: [reg]+disp8)
  in [QwordPtr[R64 => left_reg, IMM8 => left_disp], IMM32 => right_imm]
    # REX.W + F7 /0 id
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0xf7,
      mod_rm: ModRM[mod: Mod01, reg: 0, rm: left_reg],
      disp: left_disp,
      imm: imm32(right_imm),
    )
  # TEST r/m64, imm32 (Mod 10: [reg]+disp32)
  in [QwordPtr[R64 => left_reg, IMM32 => left_disp], IMM32 => right_imm]
    # REX.W + F7 /0 id
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0xf7,
      mod_rm: ModRM[mod: Mod10, reg: 0, rm: left_reg],
      disp: imm32(left_disp),
      imm: imm32(right_imm),
    )
  # TEST r/m64, imm32 (Mod 11: reg)
  in [R64 => left_reg, IMM32 => right_imm]
    # REX.W + F7 /0 id
    # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
    insn(
      prefix: REX_W,
      opcode: 0xf7,
      mod_rm: ModRM[mod: Mod11, reg: 0, rm: left_reg],
      imm: imm32(right_imm),
    )
  # TEST r/m32, r32 (Mod 11: reg)
  in [R32 => left_reg, R32 => right_reg]
    # 85 /r
    # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
    insn(
      opcode: 0x85,
      mod_rm: ModRM[mod: Mod11, reg: right_reg, rm: left_reg],
    )
  # TEST r/m64, r64 (Mod 11: reg)
  in [R64 => left_reg, R64 => right_reg]
    # REX.W + 85 /r
    # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x85,
      mod_rm: ModRM[mod: Mod11, reg: right_reg, rm: left_reg],
    )
  end
end
write_label(label) click to toggle source

@param [RubyVM::RJIT::Assembler::Label] label

# File ruby_vm/rjit/assembler.rb, line 905
def write_label(label)
  @labels[label] = @bytes.size
end
xor(dst, src) click to toggle source
# File ruby_vm/rjit/assembler.rb, line 859
def xor(dst, src)
  case [dst, src]
  # XOR r/m64, r64 (Mod 11: reg)
  in [R64 => dst_reg, R64 => src_reg]
    # REX.W + 31 /r
    # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
    insn(
      prefix: REX_W,
      opcode: 0x31,
      mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
    )
  end
end