CSES - Datatähti 2019 alku - Results
Submission details
Task:Leimasin
Sender:ollpu
Submission time:2018-10-01 18:36:42 +0300
Language:Ruby
Status:READY
Result:60
Feedback
groupverdictscore
#1ACCEPTED29
#2ACCEPTED31
#30
Test results
testverdicttimegroup
#1ACCEPTED0.15 s1details
#2ACCEPTED0.15 s1details
#3ACCEPTED0.14 s1details
#4ACCEPTED0.14 s1details
#5ACCEPTED0.14 s1details
#6ACCEPTED0.14 s1details
#7ACCEPTED0.14 s1details
#8ACCEPTED0.15 s1details
#9ACCEPTED0.15 s1details
#10ACCEPTED0.14 s1details
#11ACCEPTED0.14 s1details
#12ACCEPTED0.15 s1details
#13ACCEPTED0.15 s1details
#14ACCEPTED0.15 s1details
#15ACCEPTED0.14 s2details
#16ACCEPTED0.15 s2details
#17ACCEPTED0.14 s2details
#18ACCEPTED0.14 s2details
#19ACCEPTED0.15 s2details
#20ACCEPTED0.14 s2details
#21ACCEPTED0.14 s2details
#22ACCEPTED0.14 s2details
#23ACCEPTED0.14 s2details
#24ACCEPTED0.14 s2details
#25ACCEPTED0.15 s2details
#26ACCEPTED0.14 s2details
#27ACCEPTED0.15 s2details
#28ACCEPTED0.15 s2details
#29ACCEPTED0.16 s3details
#30ACCEPTED0.14 s3details
#31ACCEPTED0.14 s3details
#32ACCEPTED0.14 s3details
#33ACCEPTED0.14 s3details
#34ACCEPTED0.15 s3details
#35ACCEPTED0.16 s3details
#36ACCEPTED0.14 s3details
#37ACCEPTED0.14 s3details
#38ACCEPTED0.15 s3details
#39ACCEPTED0.15 s3details
#400.13 s3details
#41ACCEPTED0.15 s3details
#42ACCEPTED0.14 s3details

Code

def main
  a = gets.strip
  b = gets.strip
  mem = Fiddle.malloc(a.size*4)
  zmem = Fiddle.malloc(a.size)
  LibC.memset(zmem, 0, a.size)
  x = asm a, b do
    ar, br, memr, zr = rdi, rsi, r8, r9
    memr.mov mem
    zr.mov zmem
    
    strcmp = -> do #@rax
      r10.xor r10
    l = label
      test [:b8, zr, rax], 1
      jnz nxt = flabel
      r11b.mov [ar, rax]
      r11b.cmp [br, r10]
      jne neq = flabel
    nxt.plant
      rax.inc
      r10.inc
      r10.cmp b.size
      jl l
      rax.mov 1
      jmp over = flabel
    neq.plant
      rax.mov 0
    over.plant
    end
    
    stamp = -> do #@rax
      eax.inc
      mov [memr], eax
      eax.dec
      memr.add 4
      r10.mov rax
      r10.add b.size
    l = label
      mov [:b8, zr, rax], 1
      rax.inc
      rax.cmp r10
      jl l
      rax.sub b.size
    end
    
    rbx.xor rbx
    rcx.xor rcx
  l0 = label
    rax.mov rbx
    strcmp.call
    rax.test 1
    jz l0nxt = flabel
    
    # full stamp
    rax.mov rbx
    stamp.call
    
    rdx.mov rbx
  l1 = label
    rdx.dec
    rdx.cmp rcx
    jl l1o = flabel
    rax.mov rdx
    strcmp.call
    rax.test 1
    jz l1
    # partial stamp (from left)
    rax.mov rdx
    stamp.call
    jmp l1
  l1o.plant
    rcx.mov rbx
    rcx.inc
    rdx.mov rbx
    r12.mov rbx
    r12.add b.size
  l1 = label
    rdx.inc
    rdx.cmp a.size-b.size
    jg l1o = flabel
    rdx.cmp r12
    jge l1o
    rax.mov rdx
    strcmp.call
    rax.test 1
    jz l1
    # partial stamp (from right)
    rax.mov rdx
    stamp.call
    rcx.mov rdx
    rbx.mov rdx
    r12.mov rdx
    r12.add b.size
    rcx.inc
    jmp l1
  l1o.plant
    rbx.add b.size
    rbx.dec
    
  l0nxt.plant
    rbx.inc
    rbx.cmp a.size-b.size
    jle l0
    
    rax.xor rax
    rbx.xor rbx
  l0 = label
    mov cl, [zr, rbx]
    cl.test 1
    jz invalid = flabel
    rbx.inc
    rbx.cmp a.size
    jl l0
    rax.mov memr
  invalid.plant
  end
  # p Fiddle::Pointer.new(zmem).to_s(a.size).unpack("C*")
  if x == 0
    puts -1
  else
    k = (x-mem)/4
    mem = Fiddle::Pointer.new(mem).to_s k*4
    puts k
    puts mem.unpack("L*").reverse.join(" ")
  end
end

##
# Wilson is a pure ruby x86 assembler. No, really. Worst Idea Evar.
# Source: https://github.com/seattlerb/wilson/
# Modded by ollpu to run in modern Ruby (Linux x86_64)
##
#
# Why "wilson"? I wanted to name it "metal", but there is an existing
# project with that name... So I'm naming it after Wilson Bilkovich, who
# is about as metal as you can get (and it is easier to spell than
# "bilkovich", even tho that sounds more metal).
#
# Wilson is a port (and extension) of the smalltalk x86 assembler by
# Michael Lucas-Smith. I came across it when he presented it at
# Smalltalk SuperPowers at OOPSLA 2008.

require 'fiddle'
require 'fiddle/import'
require 'set'

module LibC
  extend Fiddle::Importer
  dlload "libc.so.6"
  extern "void* mmap(void*, size_t, int, int, int, ptrdiff_t)"
  extern "void* memcpy(void*, const void*, size_t)"
  extern "void* memset(void*, int, size_t)"
  def self.mmap_rwx length
    LibC.mmap(0, length, 0x7, 0x22, -1, 0)
  end
end

class Object
  def subclass_responsibility; raise "subclass responsibility" end
  def no!; false end

  alias :address?          :no!
  alias :future_label?     :no!
  alias :immediate?        :no!
  alias :immediate_value?  :no!
  alias :label?            :no!
  alias :offset?           :no!
  alias :operand?          :no!
  alias :register?         :no!
  alias :special_register? :no!
end


module Wilson
  VERSION = '1.1.2'

  ##
  # Assembler parses the NASM documentation and creates Command
  # objects for it

  class Assembler
    attr_accessor :commands
    attr_accessor :commands_by_mnemonic

    def self.instruction_list
      File.read(__FILE__).split("__END__").last
    end

    @@default = nil

    def self.default
      @@default ||= self.new.parse
    end

    def self.default= o
      @@default = o
    end

    def self.commands
      self.default.commands
    end
    
    def self.commands_by_mnemonic
      self.default.commands_by_mnemonic
    end

    def self.parse
      self.default
    end

    def initialize
      self.commands = []
      self.commands_by_mnemonic = {}
    end

    def expand_parameters command
      gen_commands = [command]
      command.parameters.each_with_index do |parameter, index|
        if String === parameter && parameter.start_with?('rm')
          bits = parameter[2..-1].to_i
          new_command = command.dup
          gen_commands << new_command
          command.parameters[index]     = Register.new bits
          new_command.parameters[index] = Address.new false, bits
          break
        end
      end
      gen_commands
    end

    CONDITIONALS = {
      'O'   =>  0, 'NO' =>  1, 'B'  =>  2, 'C'   =>  2, 'NAE' =>  2,
      'AE'  =>  3, 'NB' =>  3, 'NC' =>  3, 'E'   =>  4, 'Z'   =>  4,
      'NE'  =>  5, 'NZ' =>  5, 'BE' =>  6, 'NA'  =>  6, 'A'   =>  7,
      'NBE' =>  7, 'S'  =>  8, 'NS' =>  9, 'P'   => 10, 'PE'  => 10,
      'NP'  => 11, 'PO' => 11, 'L'  => 12, 'NGE' => 12, 'GE'  => 13,
      'NL'  => 13, 'LE' => 14, 'NG' => 14, 'G'   => 15, 'NLE' => 15,
    }
    
    def expand_conditional_commands prototype
      prototype.mnemonic = prototype.mnemonic[0..-3]
      gen_commands = []

      CONDITIONALS.each do |conditional, value|
        command = prototype.dup
        command.mnemonic += conditional
        gen_commands << command

        command.opcodes.each_with_index do |op, index|
          command.opcodes[index] = (op.hex+value).to_s(16) if op.end_with? '+c'
        end
      end
      gen_commands
    end
    
    def to_parameter parameter
      @simple_parameters ||= begin
        # Cached for performance, values must be such that they aren't mutated
        {
          'reg_al'   => Register.on_id_bits(nil, 0, 8),
          'reg_ax'   => Register.on_id_bits(nil, 0, 16),
          'reg_eax'  => Register.on_id_bits(nil, 0, 32),
          'reg_rax'  => Register.on_id_bits(nil, 0, 64),
          'reg_cl'   => Register.on_id_bits(nil, 1, 8),
          'reg_cx'   => Register.on_id_bits(nil, 1, 16),
          'reg_ecx'  => Register.on_id_bits(nil, 1, 32),
          'reg_rcx'  => Register.on_id_bits(nil, 1, 64),
          'reg_dl'   => Register.on_id_bits(nil, 2, 8),
          'reg_dx'   => Register.on_id_bits(nil, 2, 16),
          'reg_edx'  => Register.on_id_bits(nil, 2, 32),
          'reg_rdx'  => Register.on_id_bits(nil, 2, 64),
          'reg_bl'   => Register.on_id_bits(nil, 3, 8),
          'reg_bx'   => Register.on_id_bits(nil, 3, 16),
          'reg_ebx'  => Register.on_id_bits(nil, 3, 32),
          'reg_rbx'  => Register.on_id_bits(nil, 3, 64),
          'reg_fs'   => SegmentRegister.on_id(nil, 4),
          'reg_gs'   => SegmentRegister.on_id(nil, 5),
          'reg32na'  => Register.new(32, nil, 0, true),
          'fpureg'   => FPURegister.new,
          'reg_creg' => ControlRegister.new,
          'reg_dreg' => DebugRegister.new,
          'reg_treg' => TestRegister.new,
          'reg_sreg' => SegmentRegister.new,
          'fpu0'     => FPURegister.new(0),
          'unity'    => Immediate.new(1, false, 1),
        }
      end
      return @simple_parameters[parameter] if @simple_parameters.key? parameter
      return parameter if parameter.start_with? 'rm' # Expanded later
      case parameter
      when /^imm(\d+)?$/       then return Immediate.new($1 && $1.to_i)
      when /^(.)byte(.)?word(\d+)?$/
        return Immediate.new(8, $1 == 's')
      when /^(.)dword(\d+)?$/
        return Immediate.new(16, $1 == 's')
      when /^reg(\d+)?$/       then return Register.new($1 && $1.to_i)
      when /^mem(\d+)?$/       then return Address.new(false, $1 && $1.to_i)
      when 'mem_offs'          then return Address.new(true)
      else
        warn "unknown parameter: #{parameter.inspect}"
        return parameter
      end
    end

    UNUSED_CODES = [
      # locks not used
      'hlexr', 'hlenl', 'hle',
      # otherwise unused (refer to nasm/asm/assemble.c)
      'norexb', 'norexx', 'norexr', 'norexw', 'odf', 'nof3', 'np',
      'jcc8', 'jmp8',
      # only 64-bit addressing used, we don't need this
      'a64'
    ].to_set
    def parse_command line
      return if line.empty? or line[0] == ';'
      if line =~ /^(\w+)\s+([^\s]*)\s+\[([rmij-]+:)?([^\]]*)\]/
        name, params, param_layout, ops = $1, $2, $3, $4
        
        params = params.split ','
        spec = nil
        if params == ["void"]
          params = []
        else
          params[0], spec = params[0].split '|'
        end
            
        param_layout ||= ''
        param_layout.tr! ':', ''
        
        ops = ops.split
        
        # only 64-bit addressing used
        return if ops.include? 'a32'
        
        # remove unused codes
        ops.delete_if do |cd|
          UNUSED_CODES.include? cd
        end
        
        command              = Command.new
        command.mnemonic     = name
        command.specifier    = spec
        command.param_layout = param_layout
        command.opcodes      = ops
        
        command.parameters = params.map { |pm| to_parameter pm }
        command.extract_sizes
        
        gen_commands = self.expand_parameters command
        if command.mnemonic.end_with? "cc"
          gen_commands = gen_commands.flat_map do |cmd|
            self.expand_conditional_commands cmd
          end
        end
        self.commands += gen_commands
      else
        raise "unable to parse line: #{line}"
      end
    end

    def parse
      Assembler.instruction_list.each_line do |line|
        self.parse_command line.strip
      end
      self.commands.each do |cmd|
        self.commands_by_mnemonic[cmd.mnemonic] ||= []
        self.commands_by_mnemonic[cmd.mnemonic] << cmd
      end
      self
    end
  end

  ##
  # Command is a potential command you can call. It has a
  # mnemonic (eg: MOV) and the memory format that it outputs as
  # (opcodes) as well as the kinds of parameters it takes and the
  # processor types that support the command.

  class Command
    attr_accessor :mnemonic, :specifier, :parameters, :param_layout, :opcodes
    attr_accessor :opsize
    attr_accessor :estimated_size
    def dup
      x            = super
      x.parameters = x.parameters.dup
      x.opcodes    = x.opcodes.dup
      x
    end
    
    def extract_sizes
      pos = [param_layout.index('i'), param_layout.index('j')].compact
      self.estimated_size = 0
      self.opsize = 8
      opcodes.each do |op|
        case op
        when 'o16'
          self.estimated_size += 1
          self.opsize = 16
        when 'o32'
          self.opsize = 32
        when 'o64'
          self.estimated_size += 1
          self.opsize = 64
        when 'o64nw'
          self.opsize = 64
        when /^[0-9a-f]{2}/, /^\//
          self.estimated_size += 1
        when 'ib'
          self.estimated_size += 1
          ppos = pos.shift
          parameters[ppos].bits = 8
          parameters[ppos].signed = nil
        when /^ib,(.)$/
          self.estimated_size += 1
          ppos = pos.shift
          parameters[ppos].bits = 8
          parameters[ppos].signed = $1 == 's'
        when 'iw'
          self.estimated_size += 2
          ppos = pos.shift
          parameters[ppos].bits = 16
          parameters[ppos].signed = nil
        when 'id'
          self.estimated_size += 4
          ppos = pos.shift
          parameters[ppos].bits = 32
          parameters[ppos].signed = nil
        when 'id,s'
          self.estimated_size += 4
          ppos = pos.shift
          parameters[ppos].bits = 32
          parameters[ppos].signed = true
        when 'iq'
          self.estimated_size += 8
          ppos = pos.shift
          parameters[ppos].bits = 64
          parameters[ppos].signed = nil
        when 'iwdq'
          # not an Immediate
          self.estimated_size += 8
        when 'rel'
          self.estimated_size += 4
          ppos = pos.shift
          parameters[ppos].bits = 32
          parameters[ppos].signed = true
        when 'rel8'
          self.estimated_size += 1
          ppos = pos.shift
          parameters[ppos].bits = 8
          parameters[ppos].signed = true
        end
      end
    end
    
    def parameter_applies? ip, cp, idx
      return false if cp.is_a? String

      if ip.register? && cp.register?
        return false if ip.bits != (cp.bits || self.opsize)
        unless cp.negative_match
          return cp.id.nil? || ip.id == cp.id
        else
          return ip.id != cp.id
        end
      end

      if ip.address? && cp.address?
        return false if ip.bits && ip.bits != (cp.bits || self.opsize)
        return !cp.no_modrm || ip.offset?
      end

      if ip.special_register? && cp.special_register?
        return ip.class == cp.class && (cp.id.nil? || ip.id == cp.id)
      end

      return false unless cp.immediate?

      if ip.immediate_value?
        return true if cp.value && cp.value == ip
        if cp.signed
          return ip >= 0 && ip < (1 << cp.bits)
        else
          return ip >= -(1 << cp.bits-1) && ip < (1 << cp.bits-1)
        end
      end

      if ip.label?
        return ip.future_label? ? cp.bits == 32 : ip.bits <= cp.bits
      end

      false
    end

    def instruction_applies? instruction
      return false if instruction.mnemonic != self.mnemonic
      return false if instruction.specifier && instruction.specifier != self.specifier
      return false if instruction.parameters.size != self.parameters.size

      instruction.parameters.zip(self.parameters, 0..2).all? do |ip, cp, idx|
        self.parameter_applies? ip, cp, idx
      end
    end

  end

  ##
  # Instruction is an instruction shape that we're going to match to
  # Commands to find out what we should write in to memory.

  class Instruction
    attr_accessor :mnemonic, :specifier, :machine, :parameters, :x64_mode

    def initialize message, machine
      self.machine = machine
      self.mnemonic, *self.parameters = message
      self.mnemonic = mnemonic.to_s.upcase
      self.specifier = nil

      self.parameters.delete_if do |par|
        if par.is_a? String or par.is_a? Symbol
          raise ArgumentError("multiple specifiers not allowed") if self.specifier
          self.specifier = par.to_s
          true
        end
      end

      self.parameters.map! do |par|
        if par.kind_of? Array
          Address.from_array par
        else par end
      end

      self.parameters.each do |par|
        par.machine = self.machine if par.operand?
      end
      self.x64_mode = false
    end

    def first
      parameters.first
    end

    def second
      parameters.second
    end

    def assemble
      return false unless machine.instructions_by_mnemonic.key? self.mnemonic
      commands = machine.instructions_by_mnemonic[self.mnemonic].select { |command|
        command.instruction_applies? self
      }

      return false if commands.empty?
      
      # Heuristically select "smallest" instruction
      command = commands.each.with_index.min_by { |comm, i| [comm.estimated_size, i] }.first

      encoder = InstructionEncoder.new command, self, machine
      machine.stream.concat(encoder.encode)
      true
    end
  end
  
  ##
  # InstructionEncoder is responsible for encoding instructions
  
  class InstructionEncoder
    attr_accessor :command, :instruction, :machine
    attr_accessor :prefixes, :rex, :opcode, :modrm, :sib, :disp, :imm
    attr_accessor :opsize, :addrsize
    def initialize command, instruction, machine
      @command, @instruction, @machine = command, instruction, machine
      @prefixes = []
      @rex      = nil
      @opcode   = []
      @modrm    = nil
      @sib      = nil
      @disp     = []
      @imm      = []
      @opsize = 8
      @addrsize = 64
    end
    
    def param_by_type c
      idx = command.param_layout.index c
      raise "param with type code #{c} not found" if idx.nil?
      instruction.parameters[idx]
    end
    
    def encode
      imm_types = ['i', 'j']
      command.opcodes.each do |op|
        case op
        when 'o16'
          @opsize = 16
          prefixes.append 0x66
        when 'o32'
          @opsize = 32
        when 'o64'
          @opsize = 64
          set_rex :w, true
        when 'o64nw'
          @opsize = 64
        when /([0-9a-f]{2})i/
          prefixes.append $1.hex
        when /\/(r|[0-7])/
          num = if $1 == 'r'
            register = param_by_type 'r'
            set_rex_reg :r, register
            register.id & 7
          else
            $1.hex
          end
          encode_modrm num
        when /^i([bwdq])(,.)?$/
          param = param_by_type imm_types.shift
          case $1
          when 'b'
            self.imm.push_B param
          when 'w'
            self.imm.push_W param
          when 'd'
            self.imm.push_D param
          when 'q'
            self.imm.push_Q param
          end
        when "iwdq"
          param = param_by_type imm_types.shift
          self.imm.push_Q param.offset
        when 'rel'
          param = param_by_type imm_types.shift
          if param.label?
            if param.future_label?
              param.add machine.stream.size + bytes.size
              param = 4
            else
              param = -(machine.stream.size + bytes.size + 4 - param.position)
            end
          end
          self.imm.push_D param
        when 'rel8'
          param = param_by_type imm_types.shift
          if param.label?
            raise "rel8 used for future label reference" if param.future_label?
            param = -(machine.stream.size + bytes.size + 1 - param.position)
          end
          self.imm.push_B param
        when /^([0-9a-f]{1,2})(\+r)?$/
          num = $1.hex
          if $2
            register = param_by_type 'r'
            set_rex_reg :b, register
            num += register.id & 7
          end
          self.opcode.push num
        else
          raise "unrecognized code #{op}"
        end
      end
      
      bytes
    end
    
    def use_rex
      self.rex = 0x40 if rex.nil?
    end
    
    REX_BIT = {b: 0, x: 1, r: 2, w: 3}
    def set_rex key, val
      use_rex
      bit = REX_BIT[key]
      val = val && val != 0 ? 1 : 0
      self.rex |= val << bit
    end
    
    def set_rex_reg key, register
      if register.id >= 8
        set_rex key, 1
      end
    end
    
    def encode_modrm reg_field
      self.modrm = 0
      set_modrm :reg, reg_field
      param = param_by_type 'm'
      if param.register?
        set_modrm :mod, 0b11
        set_rex_reg :b, param
        set_modrm :rm, param.id & 7
      elsif param.address?
        if param.sib_needed?
          set_modrm :rm, 0b100
          encode_sib param
        else
          disp_bits = param.disp_bits
          disp_bits = 8 if param.base.id & 7 == 0b101 && disp_bits == 0
          set_rex_reg :b, param.base
          set_modrm :rm, param.base.id & 7
          case disp_bits
          when 8
            set_modrm :mod, 0b01
            self.disp.push_B param.offset
          when 32
            set_modrm :mod, 0b10
            self.disp.push_D param.offset
          end
        end
      else
        raise "invalid modrm memory param"
      end
    end
    
    def encode_sib address
      self.sib = 0
      disp_bits = address.disp_bits
      if address.base.nil?
        set_sib :base, 0b101
        if address.index.nil?
          set_sib :index, 0b100
        else
          set_rex_reg :x, address.index
          set_sib :index, address.index.id & 7
          
          set_sib :scale, address.scale_code
        end
        self.disp.push_D address.offset
        return
      end
      
      if disp_bits == 0 && address.base.id & 7 == 0b101
        disp_bits = 8
      end
      
      if address.index.nil?
        set_sib :index, 0b100
      else
        set_rex_reg :x, address.index
        set_sib :index, address.index.id & 7
      end
      
      set_rex_reg :b, address.base
      set_sib :base, address.base.id & 7
      
      set_sib :scale, address.scale_code
      
      case disp_bits
      when 8
        set_modrm :mod, 0b01
        self.disp.push_B address.offset
      when 32
        set_modrm :mod, 0b10
        self.disp.push_D address.offset
      end
    end
    
    MODRM_SHIFT = {rm: 0, reg: 3, mod: 6}
    def set_modrm key, val
      bit = MODRM_SHIFT[key]
      self.modrm |= val << bit
    end
    
    SIB_SHIFT = {base: 0, index: 3, scale: 6}
    def set_sib key, val
      bit = SIB_SHIFT[key]
      self.sib |= val << bit
    end
  
    def bytes
      l = []
      l += prefixes
      l.append(rex) if rex
      l += opcode
      l.append(modrm) if modrm
      l.append(sib) if sib
      l += disp
      l += imm
      l
    end
  end

  ##
  # MachineCode is an abstract machine that has subclasses for each
  # concrete machine type that you can write assembly language for.
  # Right now this library only supports X86, so look at
  # MachineCodeX86 for more details on how to use it.

  $wilson_method_missing = false
  class MachineCode
    attr_accessor :stream, :procedure, :bits
    attr_accessor :instructions_by_mnemonic

    def initialize
      self.procedure  = nil
      self.bits       = self.defaultBits
      self.stream     = []

      self.setupMachine
    end

    def inspect
      "#{self.class}#{stream.inspect}"
    end

    def method_missing msg, *args
      # prevent accidental recursion
      if $wilson_method_missing
        super
        return
      end
      $wilson_method_missing = true
      super unless self.instruction_from_message(msg, *args).assemble
      $wilson_method_missing = false
    end

    def instruction_from_message msg, *args
      Instruction.new [msg, *args], self
    end

    def label
      Label.on_at(self, stream.size)
    end

    def flabel
      FutureLabel.on self
    end

    def assemble instruction
      # wtf?
      raise "no"
    end

    alias :setupMachine :subclass_responsibility
    alias :platform     :subclass_responsibility
    alias :defaultBits  :subclass_responsibility
  end

  ##
  # MachineCodeX86 is a concrete implementation of a machine to create
  # X86 assembly code on.
  #
  # You can use this class in two ways:
  #
  # a) you can instantiate an instance and use its register variables
  #    to build up machine code in the @stream variable and then use
  #    those bytes in any way that you see fit, or
  #
  # b) you can make a subclass of this class much like you do with
  #    ExternalInterface and put methods on the class that will
  #    compile in to assembler code that can be called from Smalltalk
  #    code
  #
  # == Using MachineCodeX86 for scripting
  #
  # This is the long hand way of writing assembly code, since you
  # always include a receiver with every command.
  #
  #     asm = Assembler.MachineCodeX86.new
  #
  # Once you have an assembler, you can access the registers and send
  # commands to them, eg:
  #
  #     asm.eax.mov 1
  #
  # As you send the commands, the @stream will build up containing the
  # X86 assembler bytes you can use. You can use memory addresses in
  # your assembler code with the #m method, eg:
  #
  #     asm.eax.m.mov 1
  #
  # Once you are finished, you simply send:
  #
  #     asm.stream
  #
  # This will return you the stream of bytes.
  #
  # == Labels & Jumps
  #
  # You can do labels and jump to them using two different label
  # commands. The first is #label, which places a label jump point
  # immediately on call, eg:
  #
  #         label = asm.label
  #         label.jmp
  #
  # The other is a future label that can be placed at some future
  # point in the program and jumped too
  #
  #         label = asm.future_label
  #         asm.eax.xor asm.eax
  #         label.jmp
  #         asm.eax.inc
  #         label.plant
  #
  # You #plant the future label where you want it to actually be and
  # past references to it will be updated. Future labels will always
  # use a dword jmp so that there's space to fill in the command if
  # the jmp ends up being far.

  class MachineCodeX86 < MachineCode
    # registers-general-64bit
    attr_accessor :rax, :rbx, :rbp, :rsp, :rdi, :rsi, :rcx, :rdx
    
    # Not supported yet
    attr_accessor :r8, :r9, :r10, :r11, :r12, :r13, :r14, :r15
    attr_accessor :r8d, :r9d, :r10d, :r11d, :r12d, :r13d, :r14d, :r15d
    attr_accessor :r8w, :r9w, :r10w, :r11w, :r12w, :r13w, :r14w, :r15w
    attr_accessor :r8b, :r9b, :r10b, :r11b, :r12b, :r13b, :r14b, :r15b
    
    # registers-general-32bit
    attr_accessor :eax, :ebx, :ebp, :esp, :edi, :esi, :ecx, :edx

    # registers-fpu
    attr_accessor :st0, :st1, :st2, :st3, :st4, :st5, :st6, :st7

    # registers-debug
    attr_accessor :dr0, :dr1, :dr2, :dr3, :dr6, :dr7

    # registers-segment
    attr_accessor :es, :ss, :cs, :gs, :fs, :ds

    # registers-test
    attr_accessor :tr3, :tr4, :tr5, :tr6, :tr7

    # registers-general-8bit
    attr_accessor :al, :ah, :bl, :bh, :cl, :ch, :dl, :dh

    # registers-general-16bit
    attr_accessor :ax, :bx, :cx, :dx, :sp, :bp, :si, :di

    # registers-control
    attr_accessor :cr0, :cr2, :cr3, :cr4

    # registers-mmx
    attr_accessor :mm0, :mm1, :mm2, :mm3, :mm4, :mm5, :mm6, :mm7

    def setupMachine
      self.instructions_by_mnemonic = Assembler.commands_by_mnemonic

      # 8-bit registers
      self.al = Register.on_id_bits self, 0, 8
      self.cl = Register.on_id_bits self, 1, 8
      self.dl = Register.on_id_bits self, 2, 8
      self.bl = Register.on_id_bits self, 3, 8
      self.ah = Register.on_id_bits self, 4, 8
      self.ch = Register.on_id_bits self, 5, 8
      self.dh = Register.on_id_bits self, 6, 8
      self.bh = Register.on_id_bits self, 7, 8
      
       self.r8b = Register.on_id_bits self, 8,  8
       self.r9b = Register.on_id_bits self, 9,  8
      self.r10b = Register.on_id_bits self, 10, 8
      self.r11b = Register.on_id_bits self, 11, 8
      self.r12b = Register.on_id_bits self, 12, 8
      self.r13b = Register.on_id_bits self, 13, 8
      self.r14b = Register.on_id_bits self, 14, 8
      self.r15b = Register.on_id_bits self, 15, 8
      
      # 16-bit registers
      self.ax = Register.on_id_bits self, 0, 16
      self.cx = Register.on_id_bits self, 1, 16
      self.dx = Register.on_id_bits self, 2, 16
      self.bx = Register.on_id_bits self, 3, 16
      self.sp = Register.on_id_bits self, 4, 16
      self.bp = Register.on_id_bits self, 5, 16
      self.si = Register.on_id_bits self, 6, 16
      self.di = Register.on_id_bits self, 7, 16
      
       self.r8w = Register.on_id_bits self, 8,  16
       self.r9w = Register.on_id_bits self, 9,  16
      self.r10w = Register.on_id_bits self, 10, 16
      self.r11w = Register.on_id_bits self, 11, 16
      self.r12w = Register.on_id_bits self, 12, 16
      self.r13w = Register.on_id_bits self, 13, 16
      self.r14w = Register.on_id_bits self, 14, 16
      self.r15w = Register.on_id_bits self, 15, 16
      
      # 32-bit registers
      self.eax = Register.on_id_bits self, 0, 32
      self.ecx = Register.on_id_bits self, 1, 32
      self.edx = Register.on_id_bits self, 2, 32
      self.ebx = Register.on_id_bits self, 3, 32
      self.esp = Register.on_id_bits self, 4, 32
      self.ebp = Register.on_id_bits self, 5, 32
      self.esi = Register.on_id_bits self, 6, 32
      self.edi = Register.on_id_bits self, 7, 32
      
       self.r8d = Register.on_id_bits self, 8,  32
       self.r9d = Register.on_id_bits self, 9,  32
      self.r10d = Register.on_id_bits self, 10, 32
      self.r11d = Register.on_id_bits self, 11, 32
      self.r12d = Register.on_id_bits self, 12, 32
      self.r13d = Register.on_id_bits self, 13, 32
      self.r14d = Register.on_id_bits self, 14, 32
      self.r15d = Register.on_id_bits self, 15, 32
      
      # 64-bit registers
      self.rax = Register.on_id_bits self, 0, 64
      self.rcx = Register.on_id_bits self, 1, 64
      self.rdx = Register.on_id_bits self, 2, 64
      self.rbx = Register.on_id_bits self, 3, 64
      self.rsp = Register.on_id_bits self, 4, 64
      self.rbp = Register.on_id_bits self, 5, 64
      self.rsi = Register.on_id_bits self, 6, 64
      self.rdi = Register.on_id_bits self, 7, 64
      
       self.r8 = Register.on_id_bits self, 8,  64
       self.r9 = Register.on_id_bits self, 9,  64
      self.r10 = Register.on_id_bits self, 10, 64
      self.r11 = Register.on_id_bits self, 11, 64
      self.r12 = Register.on_id_bits self, 12, 64
      self.r13 = Register.on_id_bits self, 13, 64
      self.r14 = Register.on_id_bits self, 14, 64
      self.r15 = Register.on_id_bits self, 15, 64
      
      # Segment registers
      self.es = SegmentRegister.on_id self, 0
      self.cs = SegmentRegister.on_id self, 1
      self.ss = SegmentRegister.on_id self, 2
      self.ds = SegmentRegister.on_id self, 3
      self.fs = SegmentRegister.on_id self, 4
      self.gs = SegmentRegister.on_id self, 5
      
      # Control registers
      self.cr0 = ControlRegister.on_id self, 0
      self.cr2 = ControlRegister.on_id self, 2
      self.cr3 = ControlRegister.on_id self, 3
      self.cr4 = ControlRegister.on_id self, 4
      
      # Test registers
      self.tr3 = TestRegister.on_id self, 3
      self.tr4 = TestRegister.on_id self, 4
      self.tr5 = TestRegister.on_id self, 5
      self.tr6 = TestRegister.on_id self, 6
      self.tr7 = TestRegister.on_id self, 7
      
      # Debug registers
      self.dr0 = DebugRegister.on_id self, 0
      self.dr1 = DebugRegister.on_id self, 1
      self.dr2 = DebugRegister.on_id self, 2
      self.dr3 = DebugRegister.on_id self, 3
      self.dr6 = DebugRegister.on_id self, 6
      self.dr7 = DebugRegister.on_id self, 7
      
      # FPU registers
      self.st0 = FPURegister.on_id self, 0
      self.st1 = FPURegister.on_id self, 1
      self.st2 = FPURegister.on_id self, 2
      self.st3 = FPURegister.on_id self, 3
      self.st4 = FPURegister.on_id self, 4
      self.st5 = FPURegister.on_id self, 5
      self.st6 = FPURegister.on_id self, 6
      self.st7 = FPURegister.on_id self, 7
    end
    
    def platform
      'x86_64'
    end

    def defaultBits
      64
    end

    def syscall
      # Override Ruby's syscall
      method_missing :syscall
    end
    
    def test *args
      # Override Ruby's test
      method_missing :test, *args
    end
  end

  ##
  # Operand is any kind of operand used in a command or instruction,
  # eg: registers, memory addresses, labels, immediates, etc.

  class Operand
    attr_accessor :machine, :bits

    def self.on machine
      x = self.new
      x.machine = machine
      x
    end

    # TODO: fix _all_ initialize methods from here down to have cleaner args
    def initialize bits = nil, machine = nil
      @bits = bits
      @machine = machine
    end

    def method_missing msg, *args, &b
      # prevent accidental recursion
      if $wilson_method_missing
        super
        return
      end
      $wilson_method_missing = true
      super unless self.instructionFromMessage(msg, *args, &b).assemble
      $wilson_method_missing = false
    end

    def instructionFromMessage msg, *args, &b
      Instruction.new [msg, self, *args] + (b ? [b] : []), machine
    end

    def operand?
      true
    end
  end

  ##
  # Immediate is an Integer wrapper so that we know the machine we're
  # dealing with when we apply commands

  class Immediate < Operand
    attr_accessor :value, :signed

    def initialize bits=nil, signed=nil, value=nil
      super(bits)
      self.signed = signed
      self.value = value
    end
    
    def immediate?
      true
    end
  end

  ##
  # Address is a memory address in one of the following example forms:
  #
  #     eax, ebx + ecx, eax + 5, 23545, edx + eax + 2312

  class Address < Operand
    attr_accessor :base, :index, :scale
    attr_accessor :offset
    attr_accessor :no_modrm
 
    def self.from_array arr
      address = self.new
      address.bits = nil
      arr.delete_if do |x|
        if x.is_a? Symbol
          case x
          when :b8
            address.bits = 8
          when :b16
            address.bits = 16
          when :b32
            address.bits = 32
          when :b64
            address.bits = 64
          else
            raise "unrecognized address specifier"
          end
        end
      end
      ints, regs = arr.partition { |x| x.is_a? Integer }
      address.offset = ints.sum
      raise "at most 2 registers allowed in addressing mode" if regs.size > 2
      address.machine = regs.first.to_reg.machine
      base, index = regs
      scale = nil
      base, index = index, base if base.is_a? Register::Scaled
      raise "only one scaled register allowed in addressing mode" if base.is_a? Register::Scaled
      if index.is_a? Register::Scaled
        index, scale = index.register, index.scale
      end
      raise "sp can't be index" if index && index.id == 0b0100
      address.base, address.index, address.scale = base, index, scale
      address
    end
    
    def initialize no_modrm = nil, bits = nil, base = nil
      super(bits)

      self.no_modrm = no_modrm
      self.base = base

      self.index = self.offset = self.scale = nil
    end
    
    def offset_bits
      case offset
      when 0
        0
      when -(1<<7)...(1<<7)
        8
      when -(1<<15)...(1<<15)
        16
      when -(1<<31)...(1<<31)
        32
      else
        64
      end
    end
    
    def disp_bits
      b = offset_bits
      raise "too large disp #{offset}" if b == 64
      b == 16 ? 32 : b
    end
    
    def scale_code
      case scale
      when nil, 1
        0b00
      when 2
        0b01
      when 4
        0b10
      when 8
        0b11
      end
    end
    
    def address?
      true
    end

    def offset?
      base.nil? && index.nil?
    end
    
    def sib_needed?
      return false if no_modrm
      return true if offset?
      return false if index.nil? && (base.id & 7 != 0b100)
      true
    end
  end

  ##
  # Register is a general X86 register, such as eax, ebx, ecx, edx,
  # etc...

  class Register < Operand
    attr_accessor :id
    
    # Any register except id when true
    attr_accessor :negative_match
    
    def self.on_id_bits machine, id, bits
      self.new bits, machine, id
    end

    def initialize bits = nil, machine = nil, id = nil, negative = nil
      super(bits, machine)
      self.id = id
      self.negative_match = negative
    end

    def memory_register?
      false
    end

    def register?
      true
    end

    def get address # TODO: test
      self.mov address
      self.mov [self]
    end

    def push_mod_rm_on spareRegister, stream
      stream << (0b11000000 + id + (spareRegister.id << 3))
    end

    # def m
    #   self + 0
    # end

    # def - offset
    #   self + -offset
    # end

    # def + offset
    #   Address.on_id_offset machine, id, offset
    # end
    
    def * scale
      scale == 1 ? self : Scaled.new(self, scale)
    end
    
    def to_reg
      self
    end
    
    class Scaled
      attr_accessor :register, :scale
      def initialize register, scale
        raise "scale not in 2, 4, 8" unless [2, 4, 8].include? scale
        self.register = register
        self.scale = scale
      end
      def to_reg
        register
      end
    end
  end

  ##
  # MemoryRegister is a regular Register, but the parser needs to know
  # if it is a primary or secondary register. This form is a private
  # secondary register. Use Register instead of this guy.

  # class MemoryRegister < Register
  #   def memory_register?
  #     true
  #   end
  # end

  ##
  # Label is a known point in the byte stream that we can jmp/loop back to.

  class Label < Operand
    attr_accessor :position

    def self.on_at machine, position
      label = self.new
      label.machine = machine
      label.position = position
      label
    end

    def bits
      distance = machine.stream.size - position

      # assuming length of short jump is 2 bytes, near jump at most 6 bytes
      # encoded value would be - distance - instruction length
      if distance + 2 <= (1<<7)
        8
      elsif distance + 6 <= (1<<31)
        32
      else
        raise "label too far"
      end
    end

    def label?
      true
    end
  end

  ##
  # FutureLabel is a label in memory that hasn't been defined yet and
  # will go back and fill in the appropriate memory bytes later

  class FutureLabel < Label
    attr_accessor :positions

    def initialize
      super
      self.positions = []
    end

    def plant
      self.position = machine.stream.size

      positions.each do |pos|
        size = machine.stream[pos]
        address = []
        case size
        when 1 then
          address.push_B(position - pos - 1)
        when 2 then
          address.push_W(position - pos - 2)
        when 4 then
          address.push_D(position - pos - 4)
        else
          raise "unhandled size #{size}"
        end

        machine.stream[pos...pos+size] = address
      end
    end

    def future_label?
      position.nil?
    end

    def add aPosition
      positions << aPosition
    end
  end

  ##
  # SpecialRegister is the abstract implementation of any kind of
  # register that isn't a general register, eg: segment registers, mmx
  # registers, fpu registers, etc...

  class SpecialRegister < Operand
    attr_accessor :id

    def self.on_id machine, id
      register = self.new
      register.machine = machine
      register.id = id
      register
    end

    def special_register?
      true
    end
  end

  ##
  # DebugRegister is an X86 DRx register

  class DebugRegister < SpecialRegister
  end

  ##
  # TestRegister is an X86 Test Register, TRx

  class TestRegister < SpecialRegister
  end

  ##
  # FPURegister is an X86 fpureg, STx

  class FPURegister < SpecialRegister
    def initialize id = nil
      super()
      self.id = id
    end
  end

  ##
  # ControlRegister is an X86 CRx register

  class ControlRegister < SpecialRegister
  end

  ##
  # SegmentRegister is an X86 segment register, eg: ss, cs, ds, es...

  class SegmentRegister < SpecialRegister
  end
end # module Wilson

require 'rbconfig'

class Integer
  def immediate_value?
    true
  end

  def inspect
    "0x#{to_s 16}"
  end if $DEBUG
end

class Array
  def second
    self[1]
  end

  def push_B integer
    self << (integer & 255)
  end
  
  def push_W integer
    self.concat [integer].pack("v").unpack("C2")
  end
  
  def push_D integer
    self.concat [integer].pack("V").unpack("C4")
  end

  def push_Q integer
    self.concat [integer & (1<<32)-1, integer >> 32].pack("VV").unpack("C8")
  end
end

class Module
  def defasm name, *args, &block
    fn = assemble(*args, &block)
    define_method(name, &fn)
  end
end

class Object
  def assemble *args, &block
    asm = $machine

    asm.rbp.push
    asm.rbp.mov asm.rsp

    size = asm.stream.size

    asm.instance_eval(&block)

    if asm.stream.size == size  # return nil
      warn "returning nil for #{self}"
      asm.rax.mov 0
    end

    asm.rbp.pop
    asm.ret

    code = asm.stream.pack("C*")

    if $DEBUG then
      path = "#{$$}.obj"
      File.open path, "wb" do |f|
        f.write code
      end

      puts code.unpack("C*").map { |n| "%02X" % n }.join(' ')
      system "ndisasm", "-b", "64", path

      File.unlink path
    end

    ptr = LibC.mmap_rwx code.size
    LibC.memcpy(ptr, code, code.size)
    if $DEBUG
      puts "To debug: disas #{ptr.to_i.inspect}, +#{code.size.inspect}"
      gets
    end
    Fiddle::Function.new(ptr, args, Fiddle::TYPE_LONG)
  end
  
  def asm(*args, &block)
    argtypes = args.map do |val|
      case val
      when String
        Fiddle::TYPE_VOIDP
      else
        Fiddle::INTEGER
      end
    end
    assemble(*argtypes, &block).call(*args)
  end
  
end

$machine = Wilson::MachineCodeX86.new
main

__END__
ADC mem,reg8 [mr: hle 10 /r]
ADC reg8,reg8 [mr: 10 /r]
ADC mem,reg16 [mr: hle o16 11 /r]
ADC reg16,reg16 [mr: o16 11 /r]
ADC mem,reg32 [mr: hle o32 11 /r]
ADC reg32,reg32 [mr: o32 11 /r]
ADC mem,reg64 [mr: hle o64 11 /r]
ADC reg64,reg64 [mr: o64 11 /r]
ADC reg8,mem [rm: 12 /r]
ADC reg8,reg8 [rm: 12 /r]
ADC reg16,mem [rm: o16 13 /r]
ADC reg16,reg16 [rm: o16 13 /r]
ADC reg32,mem [rm: o32 13 /r]
ADC reg32,reg32 [rm: o32 13 /r]
ADC reg64,mem [rm: o64 13 /r]
ADC reg64,reg64 [rm: o64 13 /r]
ADC rm16,imm8 [mi: hle o16 83 /2 ib,s]
ADC rm32,imm8 [mi: hle o32 83 /2 ib,s]
ADC rm64,imm8 [mi: hle o64 83 /2 ib,s]
ADC reg_al,imm [-i: 14 ib]
ADC reg_ax,sbyteword [mi: o16 83 /2 ib,s]
ADC reg_ax,imm [-i: o16 15 iw]
ADC reg_eax,sbytedword [mi: o32 83 /2 ib,s]
ADC reg_eax,imm [-i: o32 15 id]
ADC reg_rax,sbytedword [mi: o64 83 /2 ib,s]
ADC reg_rax,imm [-i: o64 15 id,s]
ADC rm8,imm [mi: hle 80 /2 ib]
ADC rm16,sbyteword [mi: hle o16 83 /2 ib,s]
ADC rm16,imm [mi: hle o16 81 /2 iw]
ADC rm32,sbytedword [mi: hle o32 83 /2 ib,s]
ADC rm32,imm [mi: hle o32 81 /2 id]
ADC rm64,sbytedword [mi: hle o64 83 /2 ib,s]
ADC rm64,imm [mi: hle o64 81 /2 id,s]
ADC mem,imm8 [mi: hle 80 /2 ib]
ADC mem,sbyteword16 [mi: hle o16 83 /2 ib,s]
ADC mem,imm16 [mi: hle o16 81 /2 iw]
ADC mem,sbytedword32 [mi: hle o32 83 /2 ib,s]
ADC mem,imm32 [mi: hle o32 81 /2 id]
ADD mem,reg8 [mr: hle 00 /r]
ADD reg8,reg8 [mr: 00 /r]
ADD mem,reg16 [mr: hle o16 01 /r]
ADD reg16,reg16 [mr: o16 01 /r]
ADD mem,reg32 [mr: hle o32 01 /r]
ADD reg32,reg32 [mr: o32 01 /r]
ADD mem,reg64 [mr: hle o64 01 /r]
ADD reg64,reg64 [mr: o64 01 /r]
ADD reg8,mem [rm: 02 /r]
ADD reg8,reg8 [rm: 02 /r]
ADD reg16,mem [rm: o16 03 /r]
ADD reg16,reg16 [rm: o16 03 /r]
ADD reg32,mem [rm: o32 03 /r]
ADD reg32,reg32 [rm: o32 03 /r]
ADD reg64,mem [rm: o64 03 /r]
ADD reg64,reg64 [rm: o64 03 /r]
ADD rm16,imm8 [mi: hle o16 83 /0 ib,s]
ADD rm32,imm8 [mi: hle o32 83 /0 ib,s]
ADD rm64,imm8 [mi: hle o64 83 /0 ib,s]
ADD reg_al,imm [-i: 04 ib]
ADD reg_ax,sbyteword [mi: o16 83 /0 ib,s]
ADD reg_ax,imm [-i: o16 05 iw]
ADD reg_eax,sbytedword [mi: o32 83 /0 ib,s]
ADD reg_eax,imm [-i: o32 05 id]
ADD reg_rax,sbytedword [mi: o64 83 /0 ib,s]
ADD reg_rax,imm [-i: o64 05 id,s]
ADD rm8,imm [mi: hle 80 /0 ib]
ADD rm16,sbyteword [mi: hle o16 83 /0 ib,s]
ADD rm16,imm [mi: hle o16 81 /0 iw]
ADD rm32,sbytedword [mi: hle o32 83 /0 ib,s]
ADD rm32,imm [mi: hle o32 81 /0 id]
ADD rm64,sbytedword [mi: hle o64 83 /0 ib,s]
ADD rm64,imm [mi: hle o64 81 /0 id,s]
ADD mem,imm8 [mi: hle 80 /0 ib]
ADD mem,sbyteword16 [mi: hle o16 83 /0 ib,s]
ADD mem,imm16 [mi: hle o16 81 /0 iw]
ADD mem,sbytedword32 [mi: hle o32 83 /0 ib,s]
ADD mem,imm32 [mi: hle o32 81 /0 id]
AND mem,reg8 [mr: hle 20 /r]
AND reg8,reg8 [mr: 20 /r]
AND mem,reg16 [mr: hle o16 21 /r]
AND reg16,reg16 [mr: o16 21 /r]
AND mem,reg32 [mr: hle o32 21 /r]
AND reg32,reg32 [mr: o32 21 /r]
AND mem,reg64 [mr: hle o64 21 /r]
AND reg64,reg64 [mr: o64 21 /r]
AND reg8,mem [rm: 22 /r]
AND reg8,reg8 [rm: 22 /r]
AND reg16,mem [rm: o16 23 /r]
AND reg16,reg16 [rm: o16 23 /r]
AND reg32,mem [rm: o32 23 /r]
AND reg32,reg32 [rm: o32 23 /r]
AND reg64,mem [rm: o64 23 /r]
AND reg64,reg64 [rm: o64 23 /r]
AND rm16,imm8 [mi: hle o16 83 /4 ib,s]
AND rm32,imm8 [mi: hle o32 83 /4 ib,s]
AND rm64,imm8 [mi: hle o64 83 /4 ib,s]
AND reg_al,imm [-i: 24 ib]
AND reg_ax,sbyteword [mi: o16 83 /4 ib,s]
AND reg_ax,imm [-i: o16 25 iw]
AND reg_eax,sbytedword [mi: o32 83 /4 ib,s]
AND reg_eax,imm [-i: o32 25 id]
AND reg_rax,sbytedword [mi: o64 83 /4 ib,s]
AND reg_rax,imm [-i: o64 25 id,s]
AND rm8,imm [mi: hle 80 /4 ib]
AND rm16,sbyteword [mi: hle o16 83 /4 ib,s]
AND rm16,imm [mi: hle o16 81 /4 iw]
AND rm32,sbytedword [mi: hle o32 83 /4 ib,s]
AND rm32,imm [mi: hle o32 81 /4 id]
AND rm64,sbytedword [mi: hle o64 83 /4 ib,s]
AND rm64,imm [mi: hle o64 81 /4 id,s]
AND mem,imm8 [mi: hle 80 /4 ib]
AND mem,sbyteword16 [mi: hle o16 83 /4 ib,s]
AND mem,imm16 [mi: hle o16 81 /4 iw]
AND mem,sbytedword32 [mi: hle o32 83 /4 ib,s]
AND mem,imm32 [mi: hle o32 81 /4 id]
BSF reg16,mem [rm: o16 nof3 0f bc /r]
BSF reg16,reg16 [rm: o16 nof3 0f bc /r]
BSF reg32,mem [rm: o32 nof3 0f bc /r]
BSF reg32,reg32 [rm: o32 nof3 0f bc /r]
BSF reg64,mem [rm: o64 nof3 0f bc /r]
BSF reg64,reg64 [rm: o64 nof3 0f bc /r]
BSR reg16,mem [rm: o16 nof3 0f bd /r]
BSR reg16,reg16 [rm: o16 nof3 0f bd /r]
BSR reg32,mem [rm: o32 nof3 0f bd /r]
BSR reg32,reg32 [rm: o32 nof3 0f bd /r]
BSR reg64,mem [rm: o64 nof3 0f bd /r]
BSR reg64,reg64 [rm: o64 nof3 0f bd /r]
BSWAP reg32 [r: o32 0f c8+r]
BSWAP reg64 [r: o64 0f c8+r]
BT mem,reg16 [mr: o16 0f a3 /r]
BT reg16,reg16 [mr: o16 0f a3 /r]
BT mem,reg32 [mr: o32 0f a3 /r]
BT reg32,reg32 [mr: o32 0f a3 /r]
BT mem,reg64 [mr: o64 0f a3 /r]
BT reg64,reg64 [mr: o64 0f a3 /r]
BT rm16,imm [mi: o16 0f ba /4 ib,u]
BT rm32,imm [mi: o32 0f ba /4 ib,u]
BT rm64,imm [mi: o64 0f ba /4 ib,u]
BTC mem,reg16 [mr: hle o16 0f bb /r]
BTC reg16,reg16 [mr: o16 0f bb /r]
BTC mem,reg32 [mr: hle o32 0f bb /r]
BTC reg32,reg32 [mr: o32 0f bb /r]
BTC mem,reg64 [mr: hle o64 0f bb /r]
BTC reg64,reg64 [mr: o64 0f bb /r]
BTC rm16,imm [mi: hle o16 0f ba /7 ib,u]
BTC rm32,imm [mi: hle o32 0f ba /7 ib,u]
BTC rm64,imm [mi: hle o64 0f ba /7 ib,u]
BTR mem,reg16 [mr: hle o16 0f b3 /r]
BTR reg16,reg16 [mr: o16 0f b3 /r]
BTR mem,reg32 [mr: hle o32 0f b3 /r]
BTR reg32,reg32 [mr: o32 0f b3 /r]
BTR mem,reg64 [mr: hle o64 0f b3 /r]
BTR reg64,reg64 [mr: o64 0f b3 /r]
BTR rm16,imm [mi: hle o16 0f ba /6 ib,u]
BTR rm32,imm [mi: hle o32 0f ba /6 ib,u]
BTR rm64,imm [mi: hle o64 0f ba /6 ib,u]
BTS mem,reg16 [mr: hle o16 0f ab /r]
BTS reg16,reg16 [mr: o16 0f ab /r]
BTS mem,reg32 [mr: hle o32 0f ab /r]
BTS reg32,reg32 [mr: o32 0f ab /r]
BTS mem,reg64 [mr: hle o64 0f ab /r]
BTS reg64,reg64 [mr: o64 0f ab /r]
BTS rm16,imm [mi: hle o16 0f ba /5 ib,u]
BTS rm32,imm [mi: hle o32 0f ba /5 ib,u]
BTS rm64,imm [mi: hle o64 0f ba /5 ib,u]
CALL imm [i: odf e8 rel]
CALL imm|near [i: odf e8 rel]
; Call/jmp near imm/reg/mem is always 64-bit in long mode.
CALL imm64 [i: o64nw e8 rel]
CALL imm64|near [i: o64nw e8 rel]
CALL mem|far [m: o64 ff /3]
CALL mem16|far [m: o16 ff /3]
CALL mem32|far [m: o32 ff /3]
CALL mem64|far [m: o64 ff /3]
CALL mem|near [m: odf ff /2]
CALL rm64|near [m: o64nw ff /2]
CALL mem [m: odf ff /2]
CALL rm64 [m: o64nw ff /2]

CBW void [ o16 98]
CDQ void [ o32 99]
CDQE void [ o64 98]
CLC void [ f8]
CLD void [ fc]
CLI void [ fa]
CLTS void [ 0f 06]
CMC void [ f5]
CMP mem,reg8 [mr: 38 /r]
CMP reg8,reg8 [mr: 38 /r]
CMP mem,reg16 [mr: o16 39 /r]
CMP reg16,reg16 [mr: o16 39 /r]
CMP mem,reg32 [mr: o32 39 /r]
CMP reg32,reg32 [mr: o32 39 /r]
CMP mem,reg64 [mr: o64 39 /r]
CMP reg64,reg64 [mr: o64 39 /r]
CMP reg8,mem [rm: 3a /r]
CMP reg8,reg8 [rm: 3a /r]
CMP reg16,mem [rm: o16 3b /r]
CMP reg16,reg16 [rm: o16 3b /r]
CMP reg32,mem [rm: o32 3b /r]
CMP reg32,reg32 [rm: o32 3b /r]
CMP reg64,mem [rm: o64 3b /r]
CMP reg64,reg64 [rm: o64 3b /r]
CMP rm16,imm8 [mi: o16 83 /7 ib,s]
CMP rm32,imm8 [mi: o32 83 /7 ib,s]
CMP rm64,imm8 [mi: o64 83 /7 ib,s]
CMP reg_al,imm [-i: 3c ib]
CMP reg_ax,sbyteword [mi: o16 83 /7 ib,s]
CMP reg_ax,imm [-i: o16 3d iw]
CMP reg_eax,sbytedword [mi: o32 83 /7 ib,s]
CMP reg_eax,imm [-i: o32 3d id]
CMP reg_rax,sbytedword [mi: o64 83 /7 ib,s]
CMP reg_rax,imm [-i: o64 3d id,s]
CMP rm8,imm [mi: 80 /7 ib]
CMP rm16,sbyteword [mi: o16 83 /7 ib,s]
CMP rm16,imm [mi: o16 81 /7 iw]
CMP rm32,sbytedword [mi: o32 83 /7 ib,s]
CMP rm32,imm [mi: o32 81 /7 id]
CMP rm64,sbytedword [mi: o64 83 /7 ib,s]
CMP rm64,imm [mi: o64 81 /7 id,s]
CMP mem,imm8 [mi: 80 /7 ib]
CMP mem,sbyteword16 [mi: o16 83 /7 ib,s]
CMP mem,imm16 [mi: o16 81 /7 iw]
CMP mem,sbytedword32 [mi: o32 83 /7 ib,s]
CMP mem,imm32 [mi: o32 81 /7 id]
CMPSB void [ repe a6]
CMPSD void [ repe o32 a7]
CMPSQ void [ repe o64 a7]
CMPSW void [ repe o16 a7]
CMPXCHG mem,reg8 [mr: hle 0f b0 /r]
CMPXCHG reg8,reg8 [mr: 0f b0 /r]
CMPXCHG mem,reg16 [mr: hle o16 0f b1 /r]
CMPXCHG reg16,reg16 [mr: o16 0f b1 /r]
CMPXCHG mem,reg32 [mr: hle o32 0f b1 /r]
CMPXCHG reg32,reg32 [mr: o32 0f b1 /r]
CMPXCHG mem,reg64 [mr: hle o64 0f b1 /r]
CMPXCHG reg64,reg64 [mr: o64 0f b1 /r]
CMPXCHG8B mem [m: hle norexw 0f c7 /1]
CMPXCHG16B mem [m: o64 0f c7 /1]
CPUID void [ 0f a2]
CPU_READ void [ 0f 3d]
CPU_WRITE void [ 0f 3c]
CQO void [ o64 99]
CWD void [ o16 99]
CWDE void [ o32 98]
DEC rm8 [m: hle fe /1]
DEC rm16 [m: hle o16 ff /1]
DEC rm32 [m: hle o32 ff /1]
DEC rm64 [m: hle o64 ff /1]
DIV rm8 [m: f6 /6]
DIV rm16 [m: o16 f7 /6]
DIV rm32 [m: o32 f7 /6]
DIV rm64 [m: o64 f7 /6]
DMINT void [ 0f 39]
ENTER imm,imm [ij: c8 iw ib,u]
F2XM1 void [ d9 f0]
FABS void [ d9 e1]
FADD mem32 [m: d8 /0]
FADD mem64 [m: dc /0]
FADD fpureg|to [r: dc c0+r]
FADD fpureg [r: d8 c0+r]
FADD fpureg,fpu0 [r-: dc c0+r]
FADD fpu0,fpureg [-r: d8 c0+r]
FADD void [ de c1]
FADDP fpureg [r: de c0+r]
FADDP fpureg,fpu0 [r-: de c0+r]
FADDP void [ de c1]
FBLD mem80 [m: df /4]
FBLD mem [m: df /4]
FBSTP mem80 [m: df /6]
FBSTP mem [m: df /6]
FCHS void [ d9 e0]
FCLEX void [ wait db e2]
FCMOVB fpureg [r: da c0+r]
FCMOVB fpu0,fpureg [-r: da c0+r]
FCMOVB void [ da c1]
FCMOVBE fpureg [r: da d0+r]
FCMOVBE fpu0,fpureg [-r: da d0+r]
FCMOVBE void [ da d1]
FCMOVE fpureg [r: da c8+r]
FCMOVE fpu0,fpureg [-r: da c8+r]
FCMOVE void [ da c9]
FCMOVNB fpureg [r: db c0+r]
FCMOVNB fpu0,fpureg [-r: db c0+r]
FCMOVNB void [ db c1]
FCMOVNBE fpureg [r: db d0+r]
FCMOVNBE fpu0,fpureg [-r: db d0+r]
FCMOVNBE void [ db d1]
FCMOVNE fpureg [r: db c8+r]
FCMOVNE fpu0,fpureg [-r: db c8+r]
FCMOVNE void [ db c9]
FCMOVNU fpureg [r: db d8+r]
FCMOVNU fpu0,fpureg [-r: db d8+r]
FCMOVNU void [ db d9]
FCMOVU fpureg [r: da d8+r]
FCMOVU fpu0,fpureg [-r: da d8+r]
FCMOVU void [ da d9]
FCOM mem32 [m: d8 /2]
FCOM mem64 [m: dc /2]
FCOM fpureg [r: d8 d0+r]
FCOM fpu0,fpureg [-r: d8 d0+r]
FCOM void [ d8 d1]
FCOMI fpureg [r: db f0+r]
FCOMI fpu0,fpureg [-r: db f0+r]
FCOMI void [ db f1]
FCOMIP fpureg [r: df f0+r]
FCOMIP fpu0,fpureg [-r: df f0+r]
FCOMIP void [ df f1]
FCOMP mem32 [m: d8 /3]
FCOMP mem64 [m: dc /3]
FCOMP fpureg [r: d8 d8+r]
FCOMP fpu0,fpureg [-r: d8 d8+r]
FCOMP void [ d8 d9]
FCOMPP void [ de d9]
FCOS void [ d9 ff]
FDECSTP void [ d9 f6]
FDISI void [ wait db e1]
FDIV mem32 [m: d8 /6]
FDIV mem64 [m: dc /6]
FDIV fpureg|to [r: dc f8+r]
FDIV fpureg [r: d8 f0+r]
FDIV fpureg,fpu0 [r-: dc f8+r]
FDIV fpu0,fpureg [-r: d8 f0+r]
FDIV void [ de f9]
FDIVP fpureg [r: de f8+r]
FDIVP fpureg,fpu0 [r-: de f8+r]
FDIVP void [ de f9]
FDIVR mem32 [m: d8 /7]
FDIVR mem64 [m: dc /7]
FDIVR fpureg|to [r: dc f0+r]
FDIVR fpureg,fpu0 [r-: dc f0+r]
FDIVR fpureg [r: d8 f8+r]
FDIVR fpu0,fpureg [-r: d8 f8+r]
FDIVR void [ de f1]
FDIVRP fpureg [r: de f0+r]
FDIVRP fpureg,fpu0 [r-: de f0+r]
FDIVRP void [ de f1]
FEMMS void [ 0f 0e]
FENI void [ wait db e0]
FFREE fpureg [r: dd c0+r]
FFREE void [ dd c1]
FFREEP fpureg [r: df c0+r]
FFREEP void [ df c1]
FIADD mem32 [m: da /0]
FIADD mem16 [m: de /0]
FICOM mem32 [m: da /2]
FICOM mem16 [m: de /2]
FICOMP mem32 [m: da /3]
FICOMP mem16 [m: de /3]
FIDIV mem32 [m: da /6]
FIDIV mem16 [m: de /6]
FIDIVR mem32 [m: da /7]
FIDIVR mem16 [m: de /7]
FILD mem32 [m: db /0]
FILD mem16 [m: df /0]
FILD mem64 [m: df /5]
FIMUL mem32 [m: da /1]
FIMUL mem16 [m: de /1]
FINCSTP void [ d9 f7]
FINIT void [ wait db e3]
FIST mem32 [m: db /2]
FIST mem16 [m: df /2]
FISTP mem32 [m: db /3]
FISTP mem16 [m: df /3]
FISTP mem64 [m: df /7]
FISTTP mem16 [m: df /1]
FISTTP mem32 [m: db /1]
FISTTP mem64 [m: dd /1]
FISUB mem32 [m: da /4]
FISUB mem16 [m: de /4]
FISUBR mem32 [m: da /5]
FISUBR mem16 [m: de /5]
FLD mem32 [m: d9 /0]
FLD mem64 [m: dd /0]
FLD mem80 [m: db /5]
FLD fpureg [r: d9 c0+r]
FLD void [ d9 c1]
FLD1 void [ d9 e8]
FLDCW mem [m: d9 /5]
FLDENV mem [m: d9 /4]
FLDL2E void [ d9 ea]
FLDL2T void [ d9 e9]
FLDLG2 void [ d9 ec]
FLDLN2 void [ d9 ed]
FLDPI void [ d9 eb]
FLDZ void [ d9 ee]
FMUL mem32 [m: d8 /1]
FMUL mem64 [m: dc /1]
FMUL fpureg|to [r: dc c8+r]
FMUL fpureg,fpu0 [r-: dc c8+r]
FMUL fpureg [r: d8 c8+r]
FMUL fpu0,fpureg [-r: d8 c8+r]
FMUL void [ de c9]
FMULP fpureg [r: de c8+r]
FMULP fpureg,fpu0 [r-: de c8+r]
FMULP void [ de c9]
FNCLEX void [ db e2]
FNDISI void [ db e1]
FNENI void [ db e0]
FNINIT void [ db e3]
FNOP void [ d9 d0]
FNSAVE mem [m: dd /6]
FNSTCW mem [m: d9 /7]
FNSTENV mem [m: d9 /6]
FNSTSW mem [m: dd /7]
FNSTSW reg_ax [-: df e0]
FPATAN void [ d9 f3]
FPREM void [ d9 f8]
FPREM1 void [ d9 f5]
FPTAN void [ d9 f2]
FRNDINT void [ d9 fc]
FRSTOR mem [m: dd /4]
FSAVE mem [m: wait dd /6]
FSCALE void [ d9 fd]
FSETPM void [ db e4]
FSIN void [ d9 fe]
FSINCOS void [ d9 fb]
FSQRT void [ d9 fa]
FST mem32 [m: d9 /2]
FST mem64 [m: dd /2]
FST fpureg [r: dd d0+r]
FST void [ dd d1]
FSTCW mem [m: wait d9 /7]
FSTENV mem [m: wait d9 /6]
FSTP mem32 [m: d9 /3]
FSTP mem64 [m: dd /3]
FSTP mem80 [m: db /7]
FSTP fpureg [r: dd d8+r]
FSTP void [ dd d9]
FSTSW mem [m: wait dd /7]
FSTSW reg_ax [-: wait df e0]
FSUB mem32 [m: d8 /4]
FSUB mem64 [m: dc /4]
FSUB fpureg|to [r: dc e8+r]
FSUB fpureg,fpu0 [r-: dc e8+r]
FSUB fpureg [r: d8 e0+r]
FSUB fpu0,fpureg [-r: d8 e0+r]
FSUB void [ de e9]
FSUBP fpureg [r: de e8+r]
FSUBP fpureg,fpu0 [r-: de e8+r]
FSUBP void [ de e9]
FSUBR mem32 [m: d8 /5]
FSUBR mem64 [m: dc /5]
FSUBR fpureg|to [r: dc e0+r]
FSUBR fpureg,fpu0 [r-: dc e0+r]
FSUBR fpureg [r: d8 e8+r]
FSUBR fpu0,fpureg [-r: d8 e8+r]
FSUBR void [ de e1]
FSUBRP fpureg [r: de e0+r]
FSUBRP fpureg,fpu0 [r-: de e0+r]
FSUBRP void [ de e1]
FTST void [ d9 e4]
FUCOM fpureg [r: dd e0+r]
FUCOM fpu0,fpureg [-r: dd e0+r]
FUCOM void [ dd e1]
FUCOMI fpureg [r: db e8+r]
FUCOMI fpu0,fpureg [-r: db e8+r]
FUCOMI void [ db e9]
FUCOMIP fpureg [r: df e8+r]
FUCOMIP fpu0,fpureg [-r: df e8+r]
FUCOMIP void [ df e9]
FUCOMP fpureg [r: dd e8+r]
FUCOMP fpu0,fpureg [-r: dd e8+r]
FUCOMP void [ dd e9]
FUCOMPP void [ da e9]
FXAM void [ d9 e5]
FXCH fpureg [r: d9 c8+r]
FXCH fpureg,fpu0 [r-: d9 c8+r]
FXCH fpu0,fpureg [-r: d9 c8+r]
FXCH void [ d9 c9]
FXTRACT void [ d9 f4]
FYL2X void [ d9 f1]
FYL2XP1 void [ d9 f9]
HLT void [ f4]
ICEBP void [ f1]
IDIV rm8 [m: f6 /7]
IDIV rm16 [m: o16 f7 /7]
IDIV rm32 [m: o32 f7 /7]
IDIV rm64 [m: o64 f7 /7]
IMUL rm8 [m: f6 /5]
IMUL rm16 [m: o16 f7 /5]
IMUL rm32 [m: o32 f7 /5]
IMUL rm64 [m: o64 f7 /5]
IMUL reg16,mem [rm: o16 0f af /r]
IMUL reg16,reg16 [rm: o16 0f af /r]
IMUL reg32,mem [rm: o32 0f af /r]
IMUL reg32,reg32 [rm: o32 0f af /r]
IMUL reg64,mem [rm: o64 0f af /r]
IMUL reg64,reg64 [rm: o64 0f af /r]
IMUL reg16,mem,imm8 [rmi: o16 6b /r ib,s]
IMUL reg16,mem,sbyteword [rmi: o16 6b /r ib,s]
IMUL reg16,mem,imm16 [rmi: o16 69 /r iw]
IMUL reg16,mem,imm [rmi: o16 69 /r iw]
IMUL reg16,reg16,imm8 [rmi: o16 6b /r ib,s]
IMUL reg16,reg16,sbyteword [rmi: o16 6b /r ib,s]
IMUL reg16,reg16,imm16 [rmi: o16 69 /r iw]
IMUL reg16,reg16,imm [rmi: o16 69 /r iw]
IMUL reg32,mem,imm8 [rmi: o32 6b /r ib,s]
IMUL reg32,mem,sbytedword [rmi: o32 6b /r ib,s]
IMUL reg32,mem,imm32 [rmi: o32 69 /r id]
IMUL reg32,mem,imm [rmi: o32 69 /r id]
IMUL reg32,reg32,imm8 [rmi: o32 6b /r ib,s]
IMUL reg32,reg32,sbytedword [rmi: o32 6b /r ib,s]
IMUL reg32,reg32,imm32 [rmi: o32 69 /r id]
IMUL reg32,reg32,imm [rmi: o32 69 /r id]
IMUL reg64,mem,imm8 [rmi: o64 6b /r ib,s]
IMUL reg64,mem,sbytedword [rmi: o64 6b /r ib,s]
IMUL reg64,mem,imm32 [rmi: o64 69 /r id]
IMUL reg64,mem,imm [rmi: o64 69 /r id,s]
IMUL reg64,reg64,imm8 [rmi: o64 6b /r ib,s]
IMUL reg64,reg64,sbytedword [rmi: o64 6b /r ib,s]
IMUL reg64,reg64,imm32 [rmi: o64 69 /r id]
IMUL reg64,reg64,imm [rmi: o64 69 /r id,s]
;omitting r+m (same parameter stored multiple times) support
;these can be replaced IMUL a,b --> IMUL a,a,b
;IMUL reg16,imm8 [r+mi: o16 6b /r ib,s]
;IMUL reg16,sbyteword [r+mi: o16 6b /r ib,s]
;IMUL reg16,imm16 [r+mi: o16 69 /r iw]
;IMUL reg16,imm [r+mi: o16 69 /r iw]
;IMUL reg32,imm8 [r+mi: o32 6b /r ib,s]
;IMUL reg32,sbytedword [r+mi: o32 6b /r ib,s]
;IMUL reg32,imm32 [r+mi: o32 69 /r id]
;IMUL reg32,imm [r+mi: o32 69 /r id]
;IMUL reg64,imm8 [r+mi: o64 6b /r ib,s]
;IMUL reg64,sbytedword [r+mi: o64 6b /r ib,s]
;IMUL reg64,imm32 [r+mi: o64 69 /r id,s]
;IMUL reg64,imm [r+mi: o64 69 /r id,s]
IN reg_al,imm [-i: e4 ib,u]
IN reg_ax,imm [-i: o16 e5 ib,u]
IN reg_eax,imm [-i: o32 e5 ib,u]
IN reg_al,reg_dx [--: ec]
IN reg_ax,reg_dx [--: o16 ed]
IN reg_eax,reg_dx [--: o32 ed]
INC rm8 [m: hle fe /0]
INC rm16 [m: hle o16 ff /0]
INC rm32 [m: hle o32 ff /0]
INC rm64 [m: hle o64 ff /0]
INSB void [ 6c]
INSD void [ o32 6d]
INSW void [ o16 6d]
INT imm [i: cd ib,u]
INT01 void [ f1]
INT1 void [ f1]
INT03 void [ cc]
INT3 void [ cc]
INVD void [ 0f 08]
INVPCID reg64,mem128 [rm: 66 0f 38 82 /r]
INVLPG mem [m: 0f 01 /7]
INVLPGA reg_eax,reg_ecx [--: a32 0f 01 df]
INVLPGA reg_rax,reg_ecx [--: o64nw a64 0f 01 df]
INVLPGA void [ 0f 01 df]
IRET void [ odf cf]
IRETD void [ o32 cf]
IRETQ void [ o64 cf]
IRETW void [ o16 cf]
JECXZ imm [i: a32 e3 rel8]
JRCXZ imm [i: a64 e3 rel8]
JMP imm|short [i: eb rel8]
JMP imm [i: jmp8 eb rel8]
JMP imm [i: odf e9 rel]
JMP imm|near [i: odf e9 rel]
; Call/jmp near imm/reg/mem is always 64-bit in long mode.
JMP imm64 [i: o64nw e9 rel]
JMP imm64|near [i: o64nw e9 rel]
JMP mem|far [m: o64 ff /5]
JMP mem16|far [m: o16 ff /5]
JMP mem32|far [m: o32 ff /5]
JMP mem64|far [m: o64 ff /5]
JMP mem|near [m: odf ff /4]
JMP rm64|near [m: o64nw ff /4]
JMP mem [m: odf ff /4]
JMP rm64 [m: o64nw ff /4]

JMPE imm [i: odf 0f b8 rel]
JMPE imm16 [i: o16 0f b8 rel]
JMPE imm32 [i: o32 0f b8 rel]
JMPE rm16 [m: o16 0f 00 /6]
JMPE rm32 [m: o32 0f 00 /6]
LAHF void [ 9f]
LAR reg16,mem [rm: o16 0f 02 /r]
LAR reg16,reg16 [rm: o16 0f 02 /r]
LAR reg16,reg32 [rm: o16 0f 02 /r]
LAR reg16,reg64 [rm: o16 o64nw 0f 02 /r]
LAR reg32,mem [rm: o32 0f 02 /r]
LAR reg32,reg16 [rm: o32 0f 02 /r]
LAR reg32,reg32 [rm: o32 0f 02 /r]
LAR reg32,reg64 [rm: o32 o64nw 0f 02 /r]
LAR reg64,mem [rm: o64 0f 02 /r]
LAR reg64,reg16 [rm: o64 0f 02 /r]
LAR reg64,reg32 [rm: o64 0f 02 /r]
LAR reg64,reg64 [rm: o64 0f 02 /r]
LEA reg16,mem [rm: o16 8d /r]
LEA reg32,mem [rm: o32 8d /r]
LEA reg64,mem [rm: o64 8d /r]
LEAVE void [ c9]
LFENCE void [ np 0f ae e8]
LFS reg16,mem [rm: o16 0f b4 /r]
LFS reg32,mem [rm: o32 0f b4 /r]
LFS reg64,mem [rm: o64 0f b4 /r]
LGDT mem [m: 0f 01 /2]
LGS reg16,mem [rm: o16 0f b5 /r]
LGS reg32,mem [rm: o32 0f b5 /r]
LGS reg64,mem [rm: o64 0f b5 /r]
LIDT mem [m: 0f 01 /3]
LLDT mem [m: 0f 00 /2]
LLDT mem16 [m: 0f 00 /2]
LLDT reg16 [m: 0f 00 /2]
LMSW mem [m: 0f 01 /6]
LMSW mem16 [m: 0f 01 /6]
LMSW reg16 [m: 0f 01 /6]
LODSB void [ ac]
LODSD void [ o32 ad]
LODSQ void [ o64 ad]
LODSW void [ o16 ad]
LOOP imm [i: adf e2 rel8]
LOOP imm,reg_ecx [i-: a32 e2 rel8]
LOOP imm,reg_rcx [i-: a64 e2 rel8]
LOOPE imm [i: adf e1 rel8]
LOOPE imm,reg_ecx [i-: a32 e1 rel8]
LOOPE imm,reg_rcx [i-: a64 e1 rel8]
LOOPNE imm [i: adf e0 rel8]
LOOPNE imm,reg_ecx [i-: a32 e0 rel8]
LOOPNE imm,reg_rcx [i-: a64 e0 rel8]
LOOPNZ imm [i: adf e0 rel8]
LOOPNZ imm,reg_ecx [i-: a32 e0 rel8]
LOOPNZ imm,reg_rcx [i-: a64 e0 rel8]
LOOPZ imm [i: adf e1 rel8]
LOOPZ imm,reg_ecx [i-: a32 e1 rel8]
LOOPZ imm,reg_rcx [i-: a64 e1 rel8]
LSL reg16,mem [rm: o16 0f 03 /r]
LSL reg16,reg16 [rm: o16 0f 03 /r]
LSL reg16,reg32 [rm: o16 0f 03 /r]
LSL reg16,reg64 [rm: o16 o64nw 0f 03 /r]
LSL reg32,mem [rm: o32 0f 03 /r]
LSL reg32,reg16 [rm: o32 0f 03 /r]
LSL reg32,reg32 [rm: o32 0f 03 /r]
LSL reg32,reg64 [rm: o32 o64nw 0f 03 /r]
LSL reg64,mem [rm: o64 0f 03 /r]
LSL reg64,reg16 [rm: o64 0f 03 /r]
LSL reg64,reg32 [rm: o64 0f 03 /r]
LSL reg64,reg64 [rm: o64 0f 03 /r]
LSS reg16,mem [rm: o16 0f b2 /r]
LSS reg32,mem [rm: o32 0f b2 /r]
LSS reg64,mem [rm: o64 0f b2 /r]
LTR mem [m: 0f 00 /3]
LTR mem16 [m: 0f 00 /3]
LTR reg16 [m: 0f 00 /3]
MFENCE void [ np 0f ae f0]
MONITOR void [ 0f 01 c8]
MONITOR reg_rax,reg_ecx,reg_edx [---: 0f 01 c8]
MONITORX void [ 0f 01 fa]
MONITORX reg_rax,reg_ecx,reg_edx [---: 0f 01 fa]
MONITORX reg_eax,reg_ecx,reg_edx [---: 0f 01 fa]
MONITORX reg_ax,reg_ecx,reg_edx [---: 0f 01 fa]
MOV mem,reg_sreg [mr: 8c /r]
MOV reg16,reg_sreg [mr: o16 8c /r]
MOV reg32,reg_sreg [mr: o32 8c /r]
;instructions flagged OPT seem to be invalid (in my env)? ;; ollpu
;MOV reg64,reg_sreg [mr: o64nw 8c /r]
MOV rm64,reg_sreg [mr: o64 8c /r]
MOV reg_sreg,mem [rm: 8e /r]
;MOV reg_sreg,reg16 [rm: 8e /r]
;MOV reg_sreg,reg32 [rm: 8e /r]
;MOV reg_sreg,reg64 [rm: o64nw 8e /r]
MOV reg_sreg,reg16 [rm: o16 8e /r]
MOV reg_sreg,reg32 [rm: o32 8e /r]
MOV reg_sreg,rm64 [rm: o64 8e /r]
MOV reg_al,mem_offs [-i: a0 iwdq]
MOV reg_ax,mem_offs [-i: o16 a1 iwdq]
MOV reg_eax,mem_offs [-i: o32 a1 iwdq]
MOV reg_rax,mem_offs [-i: o64 a1 iwdq]
MOV mem_offs,reg_al [i-: a2 iwdq]
MOV mem_offs,reg_ax [i-: o16 a3 iwdq]
MOV mem_offs,reg_eax [i-: o32 a3 iwdq]
MOV mem_offs,reg_rax [i-: o64 a3 iwdq]
MOV reg64,reg_creg [mr: o64nw 0f 20 /r]
MOV reg_creg,reg64 [rm: o64nw 0f 22 /r]
MOV reg64,reg_dreg [mr: o64nw 0f 21 /r]
MOV reg_dreg,reg64 [rm: o64nw 0f 23 /r]
MOV mem,reg8 [mr: hlexr 88 /r]
MOV reg8,reg8 [mr: 88 /r]
MOV mem,reg16 [mr: hlexr o16 89 /r]
MOV reg16,reg16 [mr: o16 89 /r]
MOV mem,reg32 [mr: hlexr o32 89 /r]
MOV reg32,reg32 [mr: o32 89 /r]
MOV mem,reg64 [mr: hlexr o64 89 /r]
MOV reg64,reg64 [mr: o64 89 /r]
MOV reg8,mem [rm: 8a /r]
MOV reg8,reg8 [rm: 8a /r]
MOV reg16,mem [rm: o16 8b /r]
MOV reg16,reg16 [rm: o16 8b /r]
MOV reg32,mem [rm: o32 8b /r]
MOV reg32,reg32 [rm: o32 8b /r]
MOV reg64,mem [rm: o64 8b /r]
MOV reg64,reg64 [rm: o64 8b /r]
MOV reg8,imm [ri: b0+r ib]
MOV reg16,imm [ri: o16 b8+r iw]
MOV reg32,imm [ri: o32 b8+r id]
;MOV reg64,udword [ri: o64nw b8+r id]
;MOV reg64,sdword [mi: o64 c7 /0 id,s]
MOV reg64,imm [ri: o64 b8+r iq]
MOV rm8,imm [mi: hlexr c6 /0 ib]
MOV rm16,imm [mi: hlexr o16 c7 /0 iw]
MOV rm32,imm [mi: hlexr o32 c7 /0 id]
MOV rm64,imm [mi: hlexr o64 c7 /0 id,s]
MOV rm64,imm32 [mi: hlexr o64 c7 /0 id,s]
MOV mem,imm8 [mi: hlexr c6 /0 ib]
MOV mem,imm16 [mi: hlexr o16 c7 /0 iw]
MOV mem,imm32 [mi: hlexr o32 c7 /0 id]
MOVSB void [ a4]
MOVSD void [ o32 a5]
MOVSQ void [ o64 a5]
MOVSW void [ o16 a5]
MOVSX reg16,mem [rm: o16 0f be /r]
MOVSX reg16,reg8 [rm: o16 0f be /r]
MOVSX reg32,rm8 [rm: o32 0f be /r]
MOVSX reg32,rm16 [rm: o32 0f bf /r]
MOVSX reg64,rm8 [rm: o64 0f be /r]
MOVSX reg64,rm16 [rm: o64 0f bf /r]
MOVSXD reg64,rm32 [rm: o64 63 /r]
MOVSX reg64,rm32 [rm: o64 63 /r]
MOVZX reg16,mem [rm: o16 0f b6 /r]
MOVZX reg16,reg8 [rm: o16 0f b6 /r]
MOVZX reg32,rm8 [rm: o32 0f b6 /r]
MOVZX reg32,rm16 [rm: o32 0f b7 /r]
MOVZX reg64,rm8 [rm: o64 0f b6 /r]
MOVZX reg64,rm16 [rm: o64 0f b7 /r]
MUL rm8 [m: f6 /4]
MUL rm16 [m: o16 f7 /4]
MUL rm32 [m: o32 f7 /4]
MUL rm64 [m: o64 f7 /4]
MWAIT void [ 0f 01 c9]
MWAIT reg_eax,reg_ecx [--: 0f 01 c9]
MWAITX void [ 0f 01 fb]
MWAITX reg_eax,reg_ecx [--: 0f 01 fb]
NEG rm8 [m: hle f6 /3]
NEG rm16 [m: hle o16 f7 /3]
NEG rm32 [m: hle o32 f7 /3]
NEG rm64 [m: hle o64 f7 /3]
NOP void [ norexb nof3 90]
NOP rm16 [m: o16 0f 1f /0]
NOP rm32 [m: o32 0f 1f /0]
NOP rm64 [m: o64 0f 1f /0]
NOT rm8 [m: hle f6 /2]
NOT rm16 [m: hle o16 f7 /2]
NOT rm32 [m: hle o32 f7 /2]
NOT rm64 [m: hle o64 f7 /2]
OR mem,reg8 [mr: hle 08 /r]
OR reg8,reg8 [mr: 08 /r]
OR mem,reg16 [mr: hle o16 09 /r]
OR reg16,reg16 [mr: o16 09 /r]
OR mem,reg32 [mr: hle o32 09 /r]
OR reg32,reg32 [mr: o32 09 /r]
OR mem,reg64 [mr: hle o64 09 /r]
OR reg64,reg64 [mr: o64 09 /r]
OR reg8,mem [rm: 0a /r]
OR reg8,reg8 [rm: 0a /r]
OR reg16,mem [rm: o16 0b /r]
OR reg16,reg16 [rm: o16 0b /r]
OR reg32,mem [rm: o32 0b /r]
OR reg32,reg32 [rm: o32 0b /r]
OR reg64,mem [rm: o64 0b /r]
OR reg64,reg64 [rm: o64 0b /r]
OR rm16,imm8 [mi: hle o16 83 /1 ib,s]
OR rm32,imm8 [mi: hle o32 83 /1 ib,s]
OR rm64,imm8 [mi: hle o64 83 /1 ib,s]
OR reg_al,imm [-i: 0c ib]
OR reg_ax,sbyteword [mi: o16 83 /1 ib,s]
OR reg_ax,imm [-i: o16 0d iw]
OR reg_eax,sbytedword [mi: o32 83 /1 ib,s]
OR reg_eax,imm [-i: o32 0d id]
OR reg_rax,sbytedword [mi: o64 83 /1 ib,s]
OR reg_rax,imm [-i: o64 0d id,s]
OR rm8,imm [mi: hle 80 /1 ib]
OR rm16,sbyteword [mi: hle o16 83 /1 ib,s]
OR rm16,imm [mi: hle o16 81 /1 iw]
OR rm32,sbytedword [mi: hle o32 83 /1 ib,s]
OR rm32,imm [mi: hle o32 81 /1 id]
OR rm64,sbytedword [mi: hle o64 83 /1 ib,s]
OR rm64,imm [mi: hle o64 81 /1 id,s]
OR mem,imm8 [mi: hle 80 /1 ib]
OR mem,sbyteword16 [mi: hle o16 83 /1 ib,s]
OR mem,imm16 [mi: hle o16 81 /1 iw]
OR mem,sbytedword32 [mi: hle o32 83 /1 ib,s]
OR mem,imm32 [mi: hle o32 81 /1 id]
OUT imm,reg_al [i-: e6 ib,u]
OUT imm,reg_ax [i-: o16 e7 ib,u]
OUT imm,reg_eax [i-: o32 e7 ib,u]
OUT reg_dx,reg_al [--: ee]
OUT reg_dx,reg_ax [--: o16 ef]
OUT reg_dx,reg_eax [--: o32 ef]
OUTSB void [ 6e]
OUTSD void [ o32 6f]
OUTSW void [ o16 6f]
PAUSE void [ f3i 90]
POP reg16 [r: o16 58+r]
POP reg64 [r: o64nw 58+r]
POP rm16 [m: o16 8f /0]
POP rm64 [m: o64nw 8f /0]
POP reg_fs [-: 0f a1]
POP reg_gs [-: 0f a9]
POPF void [ odf 9d]
POPFQ void [ o32 9d]
POPFW void [ o16 9d]
PREFETCH mem [m: 0f 0d /0]
PREFETCHW mem [m: 0f 0d /1]
PUSH reg16 [r: o16 50+r]
PUSH reg64 [r: o64nw 50+r]
PUSH rm16 [m: o16 ff /6]
PUSH rm64 [m: o64nw ff /6]
PUSH reg_fs [-: 0f a0]
PUSH reg_gs [-: 0f a8]
PUSH imm8 [i: 6a ib,s]
PUSH sbyteword16 [i: o16 6a ib,s]
PUSH imm16 [i: o16 68 iw]
PUSH sbytedword64 [i: o64nw 6a ib,s]
PUSH imm64 [i: o64nw 68 id,s]
PUSH sbytedword32 [i: o64nw 6a ib,s]
PUSH imm32 [i: o64nw 68 id,s]
PUSHF void [ odf 9c]
PUSHFQ void [ o32 9c]
PUSHFW void [ o16 9c]
RCL rm8,unity [m-: d0 /2]
RCL rm8,reg_cl [m-: d2 /2]
RCL rm8,imm8 [mi: c0 /2 ib,u]
RCL rm16,unity [m-: o16 d1 /2]
RCL rm16,reg_cl [m-: o16 d3 /2]
RCL rm16,imm8 [mi: o16 c1 /2 ib,u]
RCL rm32,unity [m-: o32 d1 /2]
RCL rm32,reg_cl [m-: o32 d3 /2]
RCL rm32,imm8 [mi: o32 c1 /2 ib,u]
RCL rm64,unity [m-: o64 d1 /2]
RCL rm64,reg_cl [m-: o64 d3 /2]
RCL rm64,imm8 [mi: o64 c1 /2 ib,u]
RCR rm8,unity [m-: d0 /3]
RCR rm8,reg_cl [m-: d2 /3]
RCR rm8,imm8 [mi: c0 /3 ib,u]
RCR rm16,unity [m-: o16 d1 /3]
RCR rm16,reg_cl [m-: o16 d3 /3]
RCR rm16,imm8 [mi: o16 c1 /3 ib,u]
RCR rm32,unity [m-: o32 d1 /3]
RCR rm32,reg_cl [m-: o32 d3 /3]
RCR rm32,imm8 [mi: o32 c1 /3 ib,u]
RCR rm64,unity [m-: o64 d1 /3]
RCR rm64,reg_cl [m-: o64 d3 /3]
RCR rm64,imm8 [mi: o64 c1 /3 ib,u]
RDSHR rm32 [m: o32 0f 36 /0]
RDMSR void [ 0f 32]
RDPMC void [ 0f 33]
RDTSC void [ 0f 31]
RDTSCP void [ 0f 01 f9]
RET void [ c3]
RET imm [i: c2 iw]
RETF void [ cb]
RETF imm [i: ca iw]
RETN void [ c3]
RETN imm [i: c2 iw]
RETW void [ o16 c3]
RETW imm [i: c2 iw]
RETFW void [ o16 cb]
RETFW imm [i: o16 ca iw]
RETNW void [ o16 c3]
RETNW imm [i: o16 c2 iw]
RETFD void [ o32 cb]
RETFD imm [i: o32 ca iw]
RETQ void [ o64nw c3]
RETQ imm [i: o64nw c2 iw]
RETFQ void [ o64 cb]
RETFQ imm [i: o64 ca iw]
RETNQ void [ o64nw c3]
RETNQ imm [i: o64nw c2 iw]

ROL rm8,unity [m-: d0 /0]
ROL rm8,reg_cl [m-: d2 /0]
ROL rm8,imm8 [mi: c0 /0 ib,u]
ROL rm16,unity [m-: o16 d1 /0]
ROL rm16,reg_cl [m-: o16 d3 /0]
ROL rm16,imm8 [mi: o16 c1 /0 ib,u]
ROL rm32,unity [m-: o32 d1 /0]
ROL rm32,reg_cl [m-: o32 d3 /0]
ROL rm32,imm8 [mi: o32 c1 /0 ib,u]
ROL rm64,unity [m-: o64 d1 /0]
ROL rm64,reg_cl [m-: o64 d3 /0]
ROL rm64,imm8 [mi: o64 c1 /0 ib,u]
ROR rm8,unity [m-: d0 /1]
ROR rm8,reg_cl [m-: d2 /1]
ROR rm8,imm8 [mi: c0 /1 ib,u]
ROR rm16,unity [m-: o16 d1 /1]
ROR rm16,reg_cl [m-: o16 d3 /1]
ROR rm16,imm8 [mi: o16 c1 /1 ib,u]
ROR rm32,unity [m-: o32 d1 /1]
ROR rm32,reg_cl [m-: o32 d3 /1]
ROR rm32,imm8 [mi: o32 c1 /1 ib,u]
ROR rm64,unity [m-: o64 d1 /1]
ROR rm64,reg_cl [m-: o64 d3 /1]
ROR rm64,imm8 [mi: o64 c1 /1 ib,u]
RDM void [ 0f 3a]
RSDC reg_sreg,mem80 [rm: 0f 79 /r]
RSLDT mem80 [m: 0f 7b /0]
RSM void [ 0f aa]
RSTS mem80 [m: 0f 7d /0]
SAHF void [ 9e]
SAL rm8,unity [m-: d0 /4]
SAL rm8,reg_cl [m-: d2 /4]
SAL rm8,imm8 [mi: c0 /4 ib,u]
SAL rm16,unity [m-: o16 d1 /4]
SAL rm16,reg_cl [m-: o16 d3 /4]
SAL rm16,imm8 [mi: o16 c1 /4 ib,u]
SAL rm32,unity [m-: o32 d1 /4]
SAL rm32,reg_cl [m-: o32 d3 /4]
SAL rm32,imm8 [mi: o32 c1 /4 ib,u]
SAL rm64,unity [m-: o64 d1 /4]
SAL rm64,reg_cl [m-: o64 d3 /4]
SAL rm64,imm8 [mi: o64 c1 /4 ib,u]
SALC void [ d6]
SAR rm8,unity [m-: d0 /7]
SAR rm8,reg_cl [m-: d2 /7]
SAR rm8,imm8 [mi: c0 /7 ib,u]
SAR rm16,unity [m-: o16 d1 /7]
SAR rm16,reg_cl [m-: o16 d3 /7]
SAR rm16,imm8 [mi: o16 c1 /7 ib,u]
SAR rm32,unity [m-: o32 d1 /7]
SAR rm32,reg_cl [m-: o32 d3 /7]
SAR rm32,imm8 [mi: o32 c1 /7 ib,u]
SAR rm64,unity [m-: o64 d1 /7]
SAR rm64,reg_cl [m-: o64 d3 /7]
SAR rm64,imm8 [mi: o64 c1 /7 ib,u]
SBB mem,reg8 [mr: hle 18 /r]
SBB reg8,reg8 [mr: 18 /r]
SBB mem,reg16 [mr: hle o16 19 /r]
SBB reg16,reg16 [mr: o16 19 /r]
SBB mem,reg32 [mr: hle o32 19 /r]
SBB reg32,reg32 [mr: o32 19 /r]
SBB mem,reg64 [mr: hle o64 19 /r]
SBB reg64,reg64 [mr: o64 19 /r]
SBB reg8,mem [rm: 1a /r]
SBB reg8,reg8 [rm: 1a /r]
SBB reg16,mem [rm: o16 1b /r]
SBB reg16,reg16 [rm: o16 1b /r]
SBB reg32,mem [rm: o32 1b /r]
SBB reg32,reg32 [rm: o32 1b /r]
SBB reg64,mem [rm: o64 1b /r]
SBB reg64,reg64 [rm: o64 1b /r]
SBB rm16,imm8 [mi: hle o16 83 /3 ib,s]
SBB rm32,imm8 [mi: hle o32 83 /3 ib,s]
SBB rm64,imm8 [mi: hle o64 83 /3 ib,s]
SBB reg_al,imm [-i: 1c ib]
SBB reg_ax,sbyteword [mi: o16 83 /3 ib,s]
SBB reg_ax,imm [-i: o16 1d iw]
SBB reg_eax,sbytedword [mi: o32 83 /3 ib,s]
SBB reg_eax,imm [-i: o32 1d id]
SBB reg_rax,sbytedword [mi: o64 83 /3 ib,s]
SBB reg_rax,imm [-i: o64 1d id,s]
SBB rm8,imm [mi: hle 80 /3 ib]
SBB rm16,sbyteword [mi: hle o16 83 /3 ib,s]
SBB rm16,imm [mi: hle o16 81 /3 iw]
SBB rm32,sbytedword [mi: hle o32 83 /3 ib,s]
SBB rm32,imm [mi: hle o32 81 /3 id]
SBB rm64,sbytedword [mi: hle o64 83 /3 ib,s]
SBB rm64,imm [mi: hle o64 81 /3 id,s]
SBB mem,imm8 [mi: hle 80 /3 ib]
SBB mem,sbyteword16 [mi: hle o16 83 /3 ib,s]
SBB mem,imm16 [mi: hle o16 81 /3 iw]
SBB mem,sbytedword32 [mi: hle o32 83 /3 ib,s]
SBB mem,imm32 [mi: hle o32 81 /3 id]
SCASB void [ repe ae]
SCASD void [ repe o32 af]
SCASQ void [ repe o64 af]
SCASW void [ repe o16 af]
SFENCE void [ np 0f ae f8]
SGDT mem [m: 0f 01 /0]
SHL rm8,unity [m-: d0 /4]
SHL rm8,reg_cl [m-: d2 /4]
SHL rm8,imm8 [mi: c0 /4 ib,u]
SHL rm16,unity [m-: o16 d1 /4]
SHL rm16,reg_cl [m-: o16 d3 /4]
SHL rm16,imm8 [mi: o16 c1 /4 ib,u]
SHL rm32,unity [m-: o32 d1 /4]
SHL rm32,reg_cl [m-: o32 d3 /4]
SHL rm32,imm8 [mi: o32 c1 /4 ib,u]
SHL rm64,unity [m-: o64 d1 /4]
SHL rm64,reg_cl [m-: o64 d3 /4]
SHL rm64,imm8 [mi: o64 c1 /4 ib,u]
SHLD mem,reg16,imm [mri: o16 0f a4 /r ib,u]
SHLD reg16,reg16,imm [mri: o16 0f a4 /r ib,u]
SHLD mem,reg32,imm [mri: o32 0f a4 /r ib,u]
SHLD reg32,reg32,imm [mri: o32 0f a4 /r ib,u]
SHLD mem,reg64,imm [mri: o64 0f a4 /r ib,u]
SHLD reg64,reg64,imm [mri: o64 0f a4 /r ib,u]
SHLD mem,reg16,reg_cl [mr-: o16 0f a5 /r]
SHLD reg16,reg16,reg_cl [mr-: o16 0f a5 /r]
SHLD mem,reg32,reg_cl [mr-: o32 0f a5 /r]
SHLD reg32,reg32,reg_cl [mr-: o32 0f a5 /r]
SHLD mem,reg64,reg_cl [mr-: o64 0f a5 /r]
SHLD reg64,reg64,reg_cl [mr-: o64 0f a5 /r]
SHR rm8,unity [m-: d0 /5]
SHR rm8,reg_cl [m-: d2 /5]
SHR rm8,imm8 [mi: c0 /5 ib,u]
SHR rm16,unity [m-: o16 d1 /5]
SHR rm16,reg_cl [m-: o16 d3 /5]
SHR rm16,imm8 [mi: o16 c1 /5 ib,u]
SHR rm32,unity [m-: o32 d1 /5]
SHR rm32,reg_cl [m-: o32 d3 /5]
SHR rm32,imm8 [mi: o32 c1 /5 ib,u]
SHR rm64,unity [m-: o64 d1 /5]
SHR rm64,reg_cl [m-: o64 d3 /5]
SHR rm64,imm8 [mi: o64 c1 /5 ib,u]
SHRD mem,reg16,imm [mri: o16 0f ac /r ib,u]
SHRD reg16,reg16,imm [mri: o16 0f ac /r ib,u]
SHRD mem,reg32,imm [mri: o32 0f ac /r ib,u]
SHRD reg32,reg32,imm [mri: o32 0f ac /r ib,u]
SHRD mem,reg64,imm [mri: o64 0f ac /r ib,u]
SHRD reg64,reg64,imm [mri: o64 0f ac /r ib,u]
SHRD mem,reg16,reg_cl [mr-: o16 0f ad /r]
SHRD reg16,reg16,reg_cl [mr-: o16 0f ad /r]
SHRD mem,reg32,reg_cl [mr-: o32 0f ad /r]
SHRD reg32,reg32,reg_cl [mr-: o32 0f ad /r]
SHRD mem,reg64,reg_cl [mr-: o64 0f ad /r]
SHRD reg64,reg64,reg_cl [mr-: o64 0f ad /r]
SIDT mem [m: 0f 01 /1]
SLDT mem [m: 0f 00 /0]
SLDT mem16 [m: 0f 00 /0]
SLDT reg16 [m: o16 0f 00 /0]
SLDT reg32 [m: o32 0f 00 /0]
SLDT reg64 [m: o64nw 0f 00 /0]
SLDT reg64 [m: o64 0f 00 /0]
SKINIT void [ 0f 01 de]
SMI void [ f1]
SMINT void [ 0f 38]
; Older Cyrix chips had this; they had to move due to conflict with MMX
SMSW mem [m: 0f 01 /4]
SMSW mem16 [m: 0f 01 /4]
SMSW reg16 [m: o16 0f 01 /4]
SMSW reg32 [m: o32 0f 01 /4]
SMSW reg64 [m: o64 0f 01 /4]
STC void [ f9]
STD void [ fd]
STI void [ fb]
STOSB void [ aa]
STOSD void [ o32 ab]
STOSQ void [ o64 ab]
STOSW void [ o16 ab]
STR mem [m: 0f 00 /1]
STR mem16 [m: 0f 00 /1]
STR reg16 [m: o16 0f 00 /1]
STR reg32 [m: o32 0f 00 /1]
STR reg64 [m: o64 0f 00 /1]
SUB mem,reg8 [mr: hle 28 /r]
SUB reg8,reg8 [mr: 28 /r]
SUB mem,reg16 [mr: hle o16 29 /r]
SUB reg16,reg16 [mr: o16 29 /r]
SUB mem,reg32 [mr: hle o32 29 /r]
SUB reg32,reg32 [mr: o32 29 /r]
SUB mem,reg64 [mr: hle o64 29 /r]
SUB reg64,reg64 [mr: o64 29 /r]
SUB reg8,mem [rm: 2a /r]
SUB reg8,reg8 [rm: 2a /r]
SUB reg16,mem [rm: o16 2b /r]
SUB reg16,reg16 [rm: o16 2b /r]
SUB reg32,mem [rm: o32 2b /r]
SUB reg32,reg32 [rm: o32 2b /r]
SUB reg64,mem [rm: o64 2b /r]
SUB reg64,reg64 [rm: o64 2b /r]
SUB rm16,imm8 [mi: hle o16 83 /5 ib,s]
SUB rm32,imm8 [mi: hle o32 83 /5 ib,s]
SUB rm64,imm8 [mi: hle o64 83 /5 ib,s]
SUB reg_al,imm [-i: 2c ib]
SUB reg_ax,sbyteword [mi: o16 83 /5 ib,s]
SUB reg_ax,imm [-i: o16 2d iw]
SUB reg_eax,sbytedword [mi: o32 83 /5 ib,s]
SUB reg_eax,imm [-i: o32 2d id]
SUB reg_rax,sbytedword [mi: o64 83 /5 ib,s]
SUB reg_rax,imm [-i: o64 2d id,s]
SUB rm8,imm [mi: hle 80 /5 ib]
SUB rm16,sbyteword [mi: hle o16 83 /5 ib,s]
SUB rm16,imm [mi: hle o16 81 /5 iw]
SUB rm32,sbytedword [mi: hle o32 83 /5 ib,s]
SUB rm32,imm [mi: hle o32 81 /5 id]
SUB rm64,sbytedword [mi: hle o64 83 /5 ib,s]
SUB rm64,imm [mi: hle o64 81 /5 id,s]
SUB mem,imm8 [mi: hle 80 /5 ib]
SUB mem,sbyteword16 [mi: hle o16 83 /5 ib,s]
SUB mem,imm16 [mi: hle o16 81 /5 iw]
SUB mem,sbytedword32 [mi: hle o32 83 /5 ib,s]
SUB mem,imm32 [mi: hle o32 81 /5 id]
SVDC mem80,reg_sreg [mr: 0f 78 /r]
SVLDT mem80 [m: 0f 7a /0]
SVTS mem80 [m: 0f 7c /0]
SWAPGS void [ 0f 01 f8]
SYSCALL void [ 0f 05]
SYSENTER void [ 0f 34]
SYSEXIT void [ 0f 35]
SYSRET void [ 0f 07]
TEST mem,reg8 [mr: 84 /r]
TEST reg8,reg8 [mr: 84 /r]
TEST mem,reg16 [mr: o16 85 /r]
TEST reg16,reg16 [mr: o16 85 /r]
TEST mem,reg32 [mr: o32 85 /r]
TEST reg32,reg32 [mr: o32 85 /r]
TEST mem,reg64 [mr: o64 85 /r]
TEST reg64,reg64 [mr: o64 85 /r]
TEST reg8,mem [rm: 84 /r]
TEST reg16,mem [rm: o16 85 /r]
TEST reg32,mem [rm: o32 85 /r]
TEST reg64,mem [rm: o64 85 /r]
TEST reg_al,imm [-i: a8 ib]
TEST reg_ax,imm [-i: o16 a9 iw]
TEST reg_eax,imm [-i: o32 a9 id]
TEST reg_rax,imm [-i: o64 a9 id,s]
TEST rm8,imm [mi: f6 /0 ib]
TEST rm16,imm [mi: o16 f7 /0 iw]
TEST rm32,imm [mi: o32 f7 /0 id]
TEST rm64,imm [mi: o64 f7 /0 id,s]
TEST mem,imm8 [mi: f6 /0 ib]
TEST mem,imm16 [mi: o16 f7 /0 iw]
TEST mem,imm32 [mi: o32 f7 /0 id]
UD0 reg16,rm16 [rm: o16 0f ff /r]
UD0 reg32,rm32 [rm: o32 0f ff /r]
UD0 reg64,rm64 [rm: o64 0f ff /r]
UD1 reg,rm16 [rm: o16 0f b9 /r]
UD1 reg,rm32 [rm: o32 0f b9 /r]
UD1 reg,rm64 [rm: o64 0f b9 /r]
UD1 void [ 0f b9]
UD2B void [ 0f b9]
UD2B reg,rm16 [rm: o16 0f b9 /r]
UD2B reg,rm32 [rm: o32 0f b9 /r]
UD2B reg,rm64 [rm: o64 0f b9 /r]
UD2 void [ 0f 0b]
UD2A void [ 0f 0b]
UMOV mem,reg8 [mr: np 0f 10 /r]
UMOV reg8,reg8 [mr: np 0f 10 /r]
UMOV mem,reg16 [mr: np o16 0f 11 /r]
UMOV reg16,reg16 [mr: np o16 0f 11 /r]
UMOV mem,reg32 [mr: np o32 0f 11 /r]
UMOV reg32,reg32 [mr: np o32 0f 11 /r]
UMOV reg8,mem [rm: np 0f 12 /r]
UMOV reg8,reg8 [rm: np 0f 12 /r]
UMOV reg16,mem [rm: np o16 0f 13 /r]
UMOV reg16,reg16 [rm: np o16 0f 13 /r]
UMOV reg32,mem [rm: np o32 0f 13 /r]
UMOV reg32,reg32 [rm: np o32 0f 13 /r]
VERR mem [m: 0f 00 /4]
VERR mem16 [m: 0f 00 /4]
VERR reg16 [m: 0f 00 /4]
VERW mem [m: 0f 00 /5]
VERW mem16 [m: 0f 00 /5]
VERW reg16 [m: 0f 00 /5]
FWAIT void [ wait]
WBINVD void [ 0f 09]
WRSHR rm32 [m: o32 0f 37 /0]
WRMSR void [ 0f 30]
XADD mem,reg8 [mr: hle 0f c0 /r]
XADD reg8,reg8 [mr: 0f c0 /r]
XADD mem,reg16 [mr: hle o16 0f c1 /r]
XADD reg16,reg16 [mr: o16 0f c1 /r]
XADD mem,reg32 [mr: hle o32 0f c1 /r]
XADD reg32,reg32 [mr: o32 0f c1 /r]
XADD mem,reg64 [mr: hle o64 0f c1 /r]
XADD reg64,reg64 [mr: o64 0f c1 /r]
XBTS reg16,mem [rm: o16 0f a6 /r]
XBTS reg16,reg16 [rm: o16 0f a6 /r]
XBTS reg32,mem [rm: o32 0f a6 /r]
XBTS reg32,reg32 [rm: o32 0f a6 /r]
XCHG reg_ax,reg16 [-r: o16 90+r]
XCHG reg_eax,reg32na [-r: o32 90+r]
XCHG reg_rax,reg64 [-r: o64 90+r]
XCHG reg16,reg_ax [r-: o16 90+r]
XCHG reg32na,reg_eax [r-: o32 90+r]
XCHG reg64,reg_rax [r-: o64 90+r]
; "xchg eax,eax" is *not* a NOP.
XCHG reg8,mem [rm: hlenl 86 /r]
XCHG reg8,reg8 [rm: 86 /r]
XCHG reg16,mem [rm: hlenl o16 87 /r]
XCHG reg16,reg16 [rm: o16 87 /r]
XCHG reg32,mem [rm: hlenl o32 87 /r]
XCHG reg32,reg32 [rm: o32 87 /r]
XCHG reg64,mem [rm: hlenl o64 87 /r]
XCHG reg64,reg64 [rm: o64 87 /r]
XCHG mem,reg8 [mr: hlenl 86 /r]
XCHG reg8,reg8 [mr: 86 /r]
XCHG mem,reg16 [mr: hlenl o16 87 /r]
XCHG reg16,reg16 [mr: o16 87 /r]
XCHG mem,reg32 [mr: hlenl o32 87 /r]
XCHG reg32,reg32 [mr: o32 87 /r]
XCHG mem,reg64 [mr: hlenl o64 87 /r]
XCHG reg64,reg64 [mr: o64 87 /r]
XLATB void [ d7]
XLAT void [ d7]
XOR mem,reg8 [mr: hle 30 /r]
XOR reg8,reg8 [mr: 30 /r]
XOR mem,reg16 [mr: hle o16 31 /r]
XOR reg16,reg16 [mr: o16 31 /r]
XOR mem,reg32 [mr: hle o32 31 /r]
XOR reg32,reg32 [mr: o32 31 /r]
XOR mem,reg64 [mr: hle o64 31 /r]
XOR reg64,reg64 [mr: o64 31 /r]
XOR reg8,mem [rm: 32 /r]
XOR reg8,reg8 [rm: 32 /r]
XOR reg16,mem [rm: o16 33 /r]
XOR reg16,reg16 [rm: o16 33 /r]
XOR reg32,mem [rm: o32 33 /r]
XOR reg32,reg32 [rm: o32 33 /r]
XOR reg64,mem [rm: o64 33 /r]
XOR reg64,reg64 [rm: o64 33 /r]
XOR rm16,imm8 [mi: hle o16 83 /6 ib,s]
XOR rm32,imm8 [mi: hle o32 83 /6 ib,s]
XOR rm64,imm8 [mi: hle o64 83 /6 ib,s]
XOR reg_al,imm [-i: 34 ib]
XOR reg_ax,sbyteword [mi: o16 83 /6 ib,s]
XOR reg_ax,imm [-i: o16 35 iw]
XOR reg_eax,sbytedword [mi: o32 83 /6 ib,s]
XOR reg_eax,imm [-i: o32 35 id]
XOR reg_rax,sbytedword [mi: o64 83 /6 ib,s]
XOR reg_rax,imm [-i: o64 35 id,s]
XOR rm8,imm [mi: hle 80 /6 ib]
XOR rm16,sbyteword [mi: hle o16 83 /6 ib,s]
XOR rm16,imm [mi: hle o16 81 /6 iw]
XOR rm32,sbytedword [mi: hle o32 83 /6 ib,s]
XOR rm32,imm [mi: hle o32 81 /6 id]
XOR rm64,sbytedword [mi: hle o64 83 /6 ib,s]
XOR rm64,imm [mi: hle o64 81 /6 id,s]
XOR mem,imm8 [mi: hle 80 /6 ib]
XOR mem,sbyteword16 [mi: hle o16 83 /6 ib,s]
XOR mem,imm16 [mi: hle o16 81 /6 iw]
XOR mem,sbytedword32 [mi: hle o32 83 /6 ib,s]
XOR mem,imm32 [mi: hle o32 81 /6 id]
CMOVcc reg16,mem [rm: o16 0f 40+c /r]
CMOVcc reg16,reg16 [rm: o16 0f 40+c /r]
CMOVcc reg32,mem [rm: o32 0f 40+c /r]
CMOVcc reg32,reg32 [rm: o32 0f 40+c /r]
CMOVcc reg64,mem [rm: o64 0f 40+c /r]
CMOVcc reg64,reg64 [rm: o64 0f 40+c /r]
Jcc imm|near [i: odf 0f 80+c rel]
Jcc imm64|near [i: o64nw 0f 80+c rel]
Jcc imm|short [i: 70+c rel8]
Jcc imm [i: jcc8 70+c rel8]
Jcc imm [i: 0f 80+c rel]
;? Jcc imm [i: 71+c jlen e9 rel]
Jcc imm [i: 70+c rel8]

SETcc mem [m: 0f 90+c /0]
SETcc reg8 [m: 0f 90+c /0]

POPCNT reg16,rm16 [rm: o16 f3i 0f b8 /r]
POPCNT reg32,rm32 [rm: o32 f3i 0f b8 /r]
POPCNT reg64,rm64 [rm: o64 f3i 0f b8 /r]

Test details

Test 1

Group: 1

Verdict: ACCEPTED

input
BBBBBBBBBB
B

correct output
10
10 9 8 7 6 5 4 3 2 1 

user output
10
10 9 8 7 6 5 4 3 2 1

Test 2

Group: 1

Verdict: ACCEPTED

input
AABBABABAB
AB

correct output
6
1 9 7 5 3 2 

user output
9
8 9 6 7 4 5 3 1 2

Test 3

Group: 1

Verdict: ACCEPTED

input
AABAAABAAA
AABAA

correct output
4
6 5 2 1 

user output
4
6 5 2 1

Test 4

Group: 1

Verdict: ACCEPTED

input
BAAAAAABBB
BAAAAAABB

correct output
2
2 1 

user output
2
2 1

Test 5

Group: 1

Verdict: ACCEPTED

input
AAABBABBAA
AAABBABBAA

correct output
1

user output
1
1

Test 6

Group: 1

Verdict: ACCEPTED

input
GGGGGGGGGG
G

correct output
10
10 9 8 7 6 5 4 3 2 1 

user output
10
10 9 8 7 6 5 4 3 2 1

Test 7

Group: 1

Verdict: ACCEPTED

input
QUUQUUQUQU
QU

correct output
6
9 7 5 4 2 1 

user output
9
8 9 6 7 5 3 4 2 1

Test 8

Group: 1

Verdict: ACCEPTED

input
DWXDWDWXHJ
DWXHJ

correct output
3
1 4 6 

user output
3
1 4 6

Test 9

Group: 1

Verdict: ACCEPTED

input
FSOCRDGQBB
FSOCRDGQB

correct output
2
2 1 

user output
2
2 1

Test 10

Group: 1

Verdict: ACCEPTED

input
OETMIMPUPD
OETMIMPUPD

correct output
1

user output
1
1

Test 11

Group: 1

Verdict: ACCEPTED

input
DOWEUOWUEU
DOWEU

correct output
-1

user output
-1

Test 12

Group: 1

Verdict: ACCEPTED

input
JQZYVSIWTE
JQZVYSIWTE

correct output
-1

user output
-1

Test 13

Group: 1

Verdict: ACCEPTED

input
ABABABABA
ABA

correct output
4
7 5 3 1 

user output
4
7 5 3 1

Test 14

Group: 1

Verdict: ACCEPTED

input
AAAAAAAAAA
AAAAAAAAAB

correct output
-1

user output
-1

Test 15

Group: 2

Verdict: ACCEPTED

input
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB...

correct output
100
100 99 98 97 96 95 94 93 92 91...

user output
100
100 99 98 97 96 95 94 93 92 91...
Truncated

Test 16

Group: 2

Verdict: ACCEPTED

input
BABABAAAAAAAAAAAAAAAAAABABAAAA...

correct output
36
87 43 24 1 91 79 69 68 67 66 6...

user output
82
80 81 82 83 84 85 86 87 88 89 ...
Truncated

Test 17

Group: 2

Verdict: ACCEPTED

input
ABABAAAAABABBBBAAAABBBBAABBBBB...

correct output
22
51 50 43 41 31 28 26 24 21 20 ...

user output
22
51 50 43 41 31 28 26 24 21 20 ...

Test 18

Group: 2

Verdict: ACCEPTED

input
AAABABAAAABBBBBABABBAABBABABBA...

correct output
2
1 2 

user output
2
1 2

Test 19

Group: 2

Verdict: ACCEPTED

input
AABABBBBBBAABBABABBBBBBAABBAAA...

correct output
1

user output
1
1

Test 20

Group: 2

Verdict: ACCEPTED

input
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS...

correct output
100
100 99 98 97 96 95 94 93 92 91...

user output
100
100 99 98 97 96 95 94 93 92 91...
Truncated

Test 21

Group: 2

Verdict: ACCEPTED

input
NNNININIMNIMKLMXCNIMKLMXCDEIMK...

correct output
18
1 2 3 74 5 79 58 7 84 64 37 10...

user output
50
68 69 70 71 72 73 74 79 84 91 ...
Truncated

Test 22

Group: 2

Verdict: ACCEPTED

input
VYQFNHMVTKOEYCXWINLKLHVFMEPQEU...

correct output
3
51 2 1 

user output
3
51 2 1

Test 23

Group: 2

Verdict: ACCEPTED

input
IISNROLHLOJIWPTVFHFLUQRIROVLYP...

correct output
2
1 2 

user output
2
1 2

Test 24

Group: 2

Verdict: ACCEPTED

input
WPMEMERJXXADLKONUZPUUFTPSXDHIV...

correct output
1

user output
1
1

Test 25

Group: 2

Verdict: ACCEPTED

input
LNSBGZAWFJZAWFJWFJLNSBLNSBGZAL...

correct output
-1

user output
-1

Test 26

Group: 2

Verdict: ACCEPTED

input
IPIPYFUMRIPYFUMRLPIIIPYFIPYFUM...

correct output
-1

user output
-1

Test 27

Group: 2

Verdict: ACCEPTED

input
ABABABABABABABABABABABABABABAB...

correct output
49
97 95 93 91 89 87 85 83 81 79 ...

user output
49
97 95 93 91 89 87 85 83 81 79 ...
Truncated

Test 28

Group: 2

Verdict: ACCEPTED

input
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

correct output
-1

user output
-1

Test 29

Group: 3

Verdict: ACCEPTED

input
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB...

correct output
1000
1000 999 998 997 996 995 994 9...

user output
1000
1000 999 998 997 996 995 994 9...
Truncated

Test 30

Group: 3

Verdict: ACCEPTED

input
BBBBBBBBAABBBBBBBBAABBBBBBBAAB...

correct output
218
1 626 607 519 415 5 975 957 92...

user output
791
972 973 974 975 976 977 978 97...
Truncated

Test 31

Group: 3

Verdict: ACCEPTED

input
AABBBABAABABAAABBAAAAAAABBBAAB...

correct output
55
569 639 403 761 663 437 172 90...

user output
373
901 900 897 896 895 885 884 88...
Truncated

Test 32

Group: 3

Verdict: ACCEPTED

input
ABBAAABAAABAAAAABBABABBABBABBB...

correct output
2
2 1 

user output
2
2 1

Test 33

Group: 3

Verdict: ACCEPTED

input
BAAABBABBBAAAABAAAABBBBABAABAA...

correct output
1

user output
1
1

Test 34

Group: 3

Verdict: ACCEPTED

input
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU...

correct output
1000
1000 999 998 997 996 995 994 9...

user output
1000
1000 999 998 997 996 995 994 9...
Truncated

Test 35

Group: 3

Verdict: ACCEPTED

input
KSBMRKKSBMRZXBDKSKSBMRZXBDAMRZ...

correct output
178
723 731 1 935 857 820 760 735 ...

user output
545
991 980 981 982 983 984 985 99...
Truncated

Test 36

Group: 3

Verdict: ACCEPTED

input
ILYLILYLVJILYLVJZCCQDLFRLSXZDM...

correct output
21
671 54 747 504 113 1 856 764 5...

user output
332
797 798 799 800 801 802 803 80...
Truncated

Test 37

Group: 3

Verdict: ACCEPTED

input
ZZJZNKHDLJBPXIAZNJIIGBEEJFSDAF...

correct output
2
1 2 

user output
2
1 2

Test 38

Group: 3

Verdict: ACCEPTED

input
FIMWTOLSRKOWYDPCOFUJZMXJEJFKSU...

correct output
1

user output
1
1

Test 39

Group: 3

Verdict: ACCEPTED

input
AIVHCGUMKSTIYBRNPONXHRFVBKPYHX...

correct output
-1

user output
-1

Test 40

Group: 3

Verdict:

input
QPMSLIDCLFLBEXGVVQQNSVKJYXGETC...

correct output
-1

user output
(empty)

Error:
input/code.rb:1539: [BUG] Segmentation fault at 0x0000557e54e6250a
ruby 2.5.1p57 (2018-03-...

Test 41

Group: 3

Verdict: ACCEPTED

input
ABABABABABABABABABABABABABABAB...

correct output
499
997 995 993 991 989 987 985 98...

user output
499
997 995 993 991 989 987 985 98...
Truncated

Test 42

Group: 3

Verdict: ACCEPTED

input
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

correct output
-1

user output
-1