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



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
966
967
968
# File 'lib/udb/obj/instruction.rb', line 933

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:



852
853
854
# File 'lib/udb/obj/instruction.rb', line 852

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



844
845
846
# File 'lib/udb/obj/instruction.rb', line 844

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



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

def opcode_fields
  @opcode_fields
end

Class Method Details

.overlapping_format?(format1, format2) ⇒ Boolean

Returns:

  • (Boolean)


883
884
885
886
887
888
889
890
891
# File 'lib/udb/obj/instruction.rb', line 883

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



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
927
928
929
# File 'lib/udb/obj/instruction.rb', line 894

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



971
972
973
# File 'lib/udb/obj/instruction.rb', line 971

def size
  @format.size
end