<commit_before>#    This file is part of Metasm, the Ruby assembly manipulation suite
#    Copyright (C) 2006-2009 <NAME>
#
#    Licence is LGPL, see LICENCE in the top-level directory


require 'metasm/x86_64/opcodes'
require 'metasm/encode'

module Metasm
class X86_64
	class ModRM
		def self.encode_reg(reg, mregval = 0)
			v = reg.kind_of?(Reg) ? reg.val_enc : reg.val & 7
			0xc0 | (mregval << 3) | v
		end

		def encode(reg = 0, endianness = :little)
			reg = reg.val if reg.kind_of? Ia32::Argument

			ret = EncodedData.new << (reg << 3)

			# add bits in the first octet of ret.data (1.9 compatibility layer)
			or_bits = lambda { |v|	# rape me
				if ret.data[0].kind_of? Integer
					ret.data[0] |= v
				else
					ret.data[0] = (ret.data[0].unpack('C').first | v).chr
				end
			}

			if not self.b and not self.i
				# imm only, use sib
				or_bits[4]
				imm = self.imm || Expression[0]
				[ret << ((4 << 3) | 5) << imm.encode(:i32, endianness)]

			elsif self.b.val == 16 or self.i.val == 16	# rip+imm	(rip == addr of the octet after the current instr)
				# should have been filtered by #parse, but just in case
				raise "invalid rip addressing #{self}" if (self.i and self.b) or (self.s and self.s != 1)
				or_bits[5]
				imm = self.imm || Expression[0]
				[ret << imm.encode(:i32, endianness)]

			elsif not self.b and self.s != 1
				# sib with no b
				raise EncodeError, "Invalid ModRM #{self}" if @i.val == 4	# XXX 12 ?
				or_bits[4]
				s = {8=>3, 4=>2, 2=>1}[@s]
				imm = self.imm || Expression[0]
				fu = (s << 6) | (@i.val_enc << 3) | 5
				fu = fu.chr if s >= 2	# rb1.9 encoding fix
				[ret << fu << imm.encode(:i32, endianness)]
			else
				imm = @imm.reduce if self.imm
				imm = nil if imm == 0

				if not self.i or (not self.b and self.s == 1)<commit_msg>x64: fix modrm encoding<commit_after>#    This file is part of Metasm, the Ruby assembly manipulation suite
#    Copyright (C) 2006-2009 <NAME>
#
#    Licence is LGPL, see LICENCE in the top-level directory


require 'metasm/x86_64/opcodes'
require 'metasm/encode'

module Metasm
class X86_64
	class ModRM
		def self.encode_reg(reg, mregval = 0)
			v = reg.kind_of?(Reg) ? reg.val_enc : reg.val & 7
			0xc0 | (mregval << 3) | v
		end

		def encode(reg = 0, endianness = :little)
			reg = reg.val if reg.kind_of? Ia32::Argument

			ret = EncodedData.new << (reg << 3)

			# add bits in the first octet of ret.data (1.9 compatibility layer)
			or_bits = lambda { |v|	# rape me
				if ret.data[0].kind_of? Integer
					ret.data[0] |= v
				else
					ret.data[0] = (ret.data[0].unpack('C').first | v).chr
				end
			}

			if not self.b and not self.i
				# imm only, use sib
				or_bits[4]
				imm = self.imm || Expression[0]
				[ret << ((4 << 3) | 5) << imm.encode(:i32, endianness)]

			elsif (self.b and self.b.val == 16) or (self.i and self.i.val == 16)	# rip+imm	(rip == addr of the octet after the current instr)
				# should have been filtered by #parse, but just in case
				raise "invalid rip addressing #{self}" if (self.i and self.b) or (self.s and self.s != 1)
				or_bits[5]
				imm = self.imm || Expression[0]
				[ret << imm.encode(:i32, endianness)]

			elsif not self.b and self.s != 1
				# sib with no b
				raise EncodeError, "Invalid ModRM #{self}" if @i.val == 4	# XXX 12 ?
				or_bits[4]
				s = {8=>3, 4=>2, 2=>1}[@s]
				imm = self.imm || Expression[0]
				fu = (s << 6) | (@i.val_enc << 3) | 5
				fu = fu.chr if s >= 2	# rb1.9 encoding fix
				[ret << fu << imm.encode(:i32, endianness)]
			else
				imm = @imm.reduce if self.imm
				imm = nil if imm == 0

				if not self.i or (not self.b and self.s == 1)
{'fraction_non_alphanumeric': 0.14707505518763797, 'fraction_numerical': 0.03863134657836645, 'mean_word_length': 2.639558232931727, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1169478', 'n_tokens_mistral': 1672, 'n_tokens_neox': 1367, 'n_words': 448}