Class: UdbGen::InstTable::TableBuilder

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/udb-gen/generators/inst_table/table_builder.rb

Instance Method Summary collapse

Constructor Details

#initialize(arch, file_name) ⇒ TableBuilder

Returns a new instance of TableBuilder.



18
19
20
21
# File 'lib/udb-gen/generators/inst_table/table_builder.rb', line 18

def initialize(arch, file_name)
  @arch = arch
  @file_name = file_name
end

Instance Method Details

#generateObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/udb-gen/generators/inst_table/table_builder.rb', line 61

def generate
  lines = []
  @arch.instructions.each do |inst|
    enc_32 = get_encoding(inst, 32)
    enc_64 = get_encoding(inst, 64)

    if enc_32.empty? && enc_64.empty?
      puts "instruction #{inst.name} not supported by 32-bit or 64-bit"
      next
    end

    # Same encoding for 32/64-bit
    if (enc_32 == enc_64)
      lines << ([inst.name, "common"] + enc_64).join(" ")
      next
    end

    # There are some instructions that have different encodings on 32/64-bit
    unless enc_32.empty? || enc_64.empty?
      lines << ([inst.name, "common,32"] + enc_32).join(" ")
      lines << ([inst.name, "common,64"] + enc_64).join(" ")
      next
    end

    if enc_32.any?
      lines << ([inst.name, "32"] + enc_32).join(" ")
      next
    end

    if enc_64.any?
      lines << ([inst.name, "64"] + enc_64).join(" ")
      next
    end
  end

  command = "./bin/generate inst-table"
  command += " -o #{@file_name}" unless @file_name.nil?

  header = <<EOM
# SPDX-License-Identifier: BSD-3-Clause-Clear
#
# GENERATED WITH https://github.com/riscv-software-src/riscv-unified-db
# "#{command}"
#
# Each line of the instruction table should have the following format:
# NAME BASE FIXED_BITS [VARIABLE_LIST]
# NAME                        instruction name
# BASE                        instruction base size (common[,(32|64)])
#                             "common" means the instruction is valid on both architecture sizes
#                             "32" or "64" means the instruction is valid on that size
#                             if the instruction is valid on both architectures but has unique
#                             encodings, use a 32-bit entry "common,32" and 64-bit entry
# FIXED_BITS                  bitfields of the fixed bits of an instruction concatenated with '|'
#                             continuous grouping of fixed bits are in the form of 'bits<offset'
# VARIABLE_LIST               a variable sized list of all variables in the instruction definition
#                             in the form of name[~][<num][!num...]=(high[-low])|...
#                             symbols after the name represent different modifiers:
#                                 ~ sign extension, can only appear once
#                                 < left shift by 'num' amount on extraction, can only appear once
#                                 ! mark 'num' as an invalid input for this variable
EOM

  header + lines.join("\n") + "\n"
end

#get_encoding(inst, base) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/udb-gen/generators/inst_table/table_builder.rb', line 23

def get_encoding(inst, base)
  return [] unless inst.defined_in_base?(base)

  fields = []

  enc_obj = inst.encoding(base)
  fixed = enc_obj.opcode_fields.map do |fo|
    "#{fo.name}<#{fo.range.first}"
  end

  fields.append(fixed.join("|"))

  dvs = inst.decode_variables(base)

  dvs.each do |d|
    field = "#{d.name}"

    if d.sext?
      field += "~"
    end

    unless d.excludes.empty?
      field += "!#{d.excludes.join('!')}"
    end

    if d.left_shift > 0
      field += "<#{d.left_shift}"
    end

    field += "=#{d.location}"

    fields.append(field)
  end

  return fields
end