Class: Udb::Instruction::Encoding

Inherits:
Object
  • Object
show all
Defined in:
lib/udb/obj/instruction.rb

Overview

represents an instruction encoding

Defined Under Namespace

Classes: Field

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format, decode_vars, opcode_fields = nil) ⇒ Encoding

Returns a new instance of Encoding.

Parameters:

  • format (String)

    Format of the encoding, as 0’s, 1’s and -‘s (for decode variables)

  • decode_vars (Array<Hash<String,Object>>)

    List of decode variable definitions from the arch spec



984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
# File 'lib/udb/obj/instruction.rb', line 984

def initialize(format, decode_vars, opcode_fields = nil)
  @format = format

  @opcode_fields = opcode_fields.nil? ? [] : opcode_fields
  field_chars = []
  @format.chars.each_with_index do |c, idx|
    if c == "-"
      next if field_chars.empty?

      field_text = field_chars.join("")
      field_lsb = @format.size - idx
      field_msb = @format.size - idx - 1 + field_text.size
      @opcode_fields << Field.new(field_text, field_lsb..field_msb) if opcode_fields.nil?

      field_chars.clear
      next
    else
      field_chars << c
    end
  end

  # add the least significant field
  unless field_chars.empty?
    field_text = field_chars.join("")
    @opcode_fields << Field.new(field_text, 0...field_text.size) if opcode_fields.nil?
  end

  if decode_vars&.last.is_a?(DecodeVariable)
    @decode_variables = decode_vars
  else
    @decode_variables = []
    decode_vars&.each do |var|
      @decode_variables << DecodeVariable.new(var["name"], var)
    end
  end
end

Instance Attribute Details

#decode_variablesArray<DecodeVariable> (readonly)

Returns List of decode variables.

Returns:



903
904
905
# File 'lib/udb/obj/instruction.rb', line 903

def decode_variables
  @decode_variables
end

#formatString (readonly)

Returns format, as a string of 0,1 and -,.

Examples:

Format of ‘sd`

sd.format #=> '-----------------011-----0100011'

Returns:

  • (String)

    format, as a string of 0,1 and -,



895
896
897
# File 'lib/udb/obj/instruction.rb', line 895

def format
  @format
end

#opcode_fieldsArray<Field> (readonly)

Returns List of fields containing opcodes.

Examples:

opcode_fields of ‘sd`

sd.opcode_fields #=> [Field('011', ...), Field('0100011', ...)]

Returns:

  • (Array<Field>)

    List of fields containing opcodes



900
901
902
# File 'lib/udb/obj/instruction.rb', line 900

def opcode_fields
  @opcode_fields
end

Class Method Details

.overlapping_format?(format1, format2) ⇒ Boolean

Returns:

  • (Boolean)


934
935
936
937
938
939
940
941
942
# File 'lib/udb/obj/instruction.rb', line 934

def self.overlapping_format?(format1, format2)
  format1.size.times.all? do |i|
    rev_idx = (format1.size - 1) - i
    other_rev_idx = (format2.size - 1) - i
    format1[rev_idx] == "-" \
      || (i >= format2.size) \
      || (format1[rev_idx] == format2[other_rev_idx])
  end
end

Instance Method Details

#indistinguishable?(other_encoding, check_other: true) ⇒ Boolean

Returns true if self and other_encoding cannot be distinguished, i.e., they share the same encoding.

Returns:

  • (Boolean)

    true if self and other_encoding cannot be distinguished, i.e., they share the same encoding



945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
# File 'lib/udb/obj/instruction.rb', line 945

def indistinguishable?(other_encoding, check_other: true)
  other_format = other_encoding.format
  same = Encoding.overlapping_format?(format, other_format)

  if same
    # the mask can't be distinguished; is there one or more exclusions that distinguishes them?

    # we have to check all combinations of dvs with exclusions, and their values
    exclusion_dvs = @decode_variables.reject { |dv| dv.excludes.empty? }
    exclusion_dv_values = []
    def expand(exclusion_dvs, exclusion_dv_values, base, idx)
      other_dv = exclusion_dvs[idx]
      other_dv.excludes.each do |other_exclusion_value|
        exclusion_dv_values << base + [[other_dv, other_exclusion_value]]
        if (idx + 1) < exclusion_dvs.size
          expand(exclusion_dvs, exclusion_dv_values, exclusion_dv_values.last, idx + 1)
        end
      end
    end
    exclusion_dvs.each_index do |idx|
      expand(exclusion_dvs, exclusion_dv_values, [], idx)
    end

    exclusion_dv_values.each do |dv_values|
      repl_format = format.dup
      dv_values.each { |dv_and_value| repl_format = dv_and_value[0].encoding_repl(repl_format, dv_and_value[1]) }

      if repl_format == other_format || !Encoding.overlapping_format?(repl_format, other_format)
        same = false
        break
      end
    end
  end

  check_other ? same || other_encoding.indistinguishable?(self, check_other: false) : same
end

#sizeInteger

Returns Size, in bits, of the encoding.

Returns:

  • (Integer)

    Size, in bits, of the encoding



1022
1023
1024
# File 'lib/udb/obj/instruction.rb', line 1022

def size
  @format.size
end