4 ## Copyright (c) 2024 Taylor Simpson <ltaylorsimpson@gmail.com>
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
29 tag
: "".join(reversed(iset
.iset
[tag
]["enc"].replace(" ", "")))
31 if iset
.iset
[tag
]["enc"] != "MISSING ENCODING"
35 regre
= re
.compile(r
"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
36 immre
= re
.compile(r
"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
39 def ordered_unique(l
):
40 return sorted(set(l
), key
=l
.index
)
42 num_registers
= {"R": 32, "V": 32}
64 # These instructions have unused operand letters in their encoding
65 # They don't correspond to actual operands in the instruction semantics
66 # We will mark them as ignored in QEMU decodetree
68 tags_with_unused_d_encoding
= {
78 tags_with_unused_t_encoding
= {
83 def skip_tag(tag
, class_to_decode
):
84 enc_class
= iset
.iset
[tag
]["enc_class"]
85 return enc_class
!= class_to_decode
89 ## Generate the QEMU decodetree file for each instruction in class_to_decode
90 ## For A2_add: Rd32=add(Rs32,Rt32)
95 ## @A2_add 11110011000.......-.....---..... Rd=%A2_add_Rd Rs=%A2_add_Rs Rt=%A2_add_Rt %PP
96 ## A2_add ..................-.....---..... @A2_add
98 def gen_decodetree_file(f
, class_to_decode
):
99 is_subinsn
= class_to_decode
.startswith("SUBINSN_")
100 f
.write(f
"## DO NOT MODIFY - This file is generated by {sys.argv[0]}\n\n")
102 f
.write("%PP\t14:2\n\n")
103 for tag
in sorted(encs
.keys(), key
=iset
.tags
.index
):
104 if skip_tag(tag
, class_to_decode
):
108 enc_str
= "".join(reversed(encs
[tag
]))
109 f
.write(("#" * 80) + "\n"
110 f
"## {tag}:\t{enc_str}\n"
113 # The subinstructions come with a 13-bit encoding, but
114 # decodetree.py needs 16 bits
116 enc_str
= "---" + enc_str
118 regs
= ordered_unique(regre
.findall(iset
.iset
[tag
]["syntax"]))
119 imms
= ordered_unique(immre
.findall(iset
.iset
[tag
]["syntax"]))
121 # Write the field definitions for the registers
122 for regno
, reg
in enumerate(regs
):
123 reg_type
, reg_id
, _
, reg_enc_size
= reg
124 reg_letter
= reg_id
[0]
125 reg_num_choices
= int(reg_enc_size
.rstrip("S"))
126 reg_mapping
= reg_type
+ "".join("_" for letter
in reg_id
) + \
128 reg_enc_fields
= re
.findall(reg_letter
+ "+", enc
)
130 # Check for some errors
131 if len(reg_enc_fields
) == 0:
132 raise Exception(f
"{tag} missing register field!")
133 if len(reg_enc_fields
) > 1:
134 raise Exception(f
"{tag} has split register field!")
135 reg_enc_field
= reg_enc_fields
[0]
136 if 2 ** len(reg_enc_field
) != reg_num_choices
:
137 raise Exception(f
"{tag} has incorrect register field width!")
139 f
.write(f
"%{tag}_{reg_type}{reg_id}\t"
140 f
"{enc.index(reg_enc_field)}:{len(reg_enc_field)}")
142 if (reg_type
in num_registers
and
143 reg_num_choices
!= num_registers
[reg_type
]):
144 f
.write(f
"\t!function=decode_mapped_reg_{reg_mapping}")
147 # Write the field definitions for the immediates
149 immno
= 1 if imm
[0].isupper() else 0
151 imm_width
= int(imm
[1])
152 imm_letter
= "i" if imm_type
.islower() else "I"
154 sign_mark
= "s" if imm_type
.lower() in "sr" else ""
155 for m
in reversed(list(re
.finditer(imm_letter
+ "+", enc
))):
156 fields
.append(f
"{m.start()}:{sign_mark}{m.end() - m.start()}")
158 field_str
= " ".join(fields
)
159 f
.write(f
"%{tag}_{imm_type}{imm_letter}\t{field_str}\n")
161 ## Handle instructions with unused encoding letters
162 ## Change the unused letters to ignored
163 if tag
in tags_with_unused_d_encoding
:
164 enc_str
= enc_str
.replace("d", "-")
165 if tag
in tags_with_unused_t_encoding
:
166 enc_str
= enc_str
.replace("t", "-")
168 # Replace the operand letters with .
169 for x
in operand_letters
:
170 enc_str
= enc_str
.replace(x
, ".")
172 # Write the instruction format
173 f
.write(f
"@{tag}\t{enc_str}")
177 f
.write(f
" {reg_type}{reg_id}=%{tag}_{reg_type}{reg_id}")
180 imm_letter
= "i" if imm_type
.islower() else "I"
181 f
.write(f
" {imm_type}{imm_letter}=%{tag}_{imm_type}{imm_letter}")
187 # Replace the 0s and 1s with .
188 enc_str
= enc_str
.replace("0", ".").replace("1", ".")
190 # Write the instruction pattern
191 f
.write(f
"{tag}\t{enc_str} @{tag}\n")
194 if __name__
== "__main__":
195 hex_common
.read_semantics_file(sys
.argv
[1])
196 class_to_decode
= sys
.argv
[2]
197 with
open(sys
.argv
[3], "w") as f
:
198 gen_decodetree_file(f
, class_to_decode
)