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



930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
# File 'lib/udb/obj/instruction.rb', line 930

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:



849
850
851
# File 'lib/udb/obj/instruction.rb', line 849

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 -,



841
842
843
# File 'lib/udb/obj/instruction.rb', line 841

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



846
847
848
# File 'lib/udb/obj/instruction.rb', line 846

def opcode_fields
  @opcode_fields
end

Class Method Details

.overlapping_format?(format1, format2) ⇒ Boolean

Returns:

  • (Boolean)


880
881
882
883
884
885
886
887
888
# File 'lib/udb/obj/instruction.rb', line 880

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



891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
# File 'lib/udb/obj/instruction.rb', line 891

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 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



968
969
970
# File 'lib/udb/obj/instruction.rb', line 968

def size
  @format.size
end