diff --git a/meta/cretonne/__init__.py b/meta/cretonne/__init__.py index 88860286dc..bc20bcbcf3 100644 --- a/meta/cretonne/__init__.py +++ b/meta/cretonne/__init__.py @@ -955,6 +955,37 @@ class TargetISA(object): self.instruction_groups = instruction_groups self.cpumodes = list() + def finish(self): + """ + Finish the definition of a target ISA after adding all CPU modes and + settings. + + This computes some derived properties that are used in multilple + places. + + :returns self: + """ + self._collect_instruction_predicates() + return self + + def _collect_instruction_predicates(self): + """ + Collect and number all instruction predicates in use. + + Sets `instp.number` for all used instruction predicates and places them + in `self.all_instps` in numerical order. + """ + self.all_instps = list() + instps = set() + for cpumode in self.cpumodes: + for enc in cpumode.encodings: + instp = enc.instp + if instp and instp not in instps: + # assign predicate number starting from 0. + instp.number = len(instps) + instps.add(instp) + self.all_instps.append(instp) + class CPUMode(object): """ diff --git a/meta/gen_encoding.py b/meta/gen_encoding.py index a7ac7e2f4a..c10a4f8a06 100644 --- a/meta/gen_encoding.py +++ b/meta/gen_encoding.py @@ -75,10 +75,11 @@ def emit_instp(instp, fmt): # the field names. fields = ', '.join(sorted(set(p.field.name for p in leafs))) - with fmt.indented( - 'if let {} {{ {}, .. }} = *inst {{' - .format(iform.name, fields), '}'): - fmt.line('return {};'.format(instp.rust_predicate(0))) + with fmt.indented('{} => {{'.format(instp.number), '}'): + with fmt.indented( + 'if let {} {{ {}, .. }} = *inst {{' + .format(iform.name, fields), '}'): + fmt.line('return {};'.format(instp.rust_predicate(0))) def emit_instps(instps, fmt): @@ -90,9 +91,8 @@ def emit_instps(instps, fmt): 'fn check_instp(inst: &InstructionData, instp_idx: u16) -> bool {', '}'): with fmt.indented('match instp_idx {', '}'): - for (instp, idx) in instps.items(): - with fmt.indented('{} => {{'.format(idx), '}'): - emit_instp(instp, fmt) + for instp in instps: + emit_instp(instp, fmt) fmt.line('_ => panic!("Invalid instruction predicate")') # The match cases will fall through if the instruction format is wrong. @@ -102,17 +102,6 @@ def emit_instps(instps, fmt): fmt.line(' instp_idx);') -def collect_instps(cpumodes): - # Map instp -> number - instps = OrderedDict() - for cpumode in cpumodes: - for enc in cpumode.encodings: - instp = enc.instp - if instp and instp not in instps: - instps[instp] = 1 + len(instps) - return instps - - class EncList(object): """ List of instructions for encoding a given type + opcode pair. @@ -192,13 +181,12 @@ def make_tables(cpumode): return table -def gen_isa(cpumodes, fmt): +def gen_isa(isa, fmt): # First assign numbers to relevant instruction predicates and generate the # check_instp() function.. - instps = collect_instps(cpumodes) - emit_instps(instps, fmt) + emit_instps(isa.all_instps, fmt) - for cpumode in cpumodes: + for cpumode in isa.cpumodes: level1 = make_tables(cpumode) for level2 in level1: for enclist in level2: @@ -210,5 +198,5 @@ def gen_isa(cpumodes, fmt): def generate(isas, out_dir): for isa in isas: fmt = srcgen.Formatter() - gen_isa(isa.cpumodes, fmt) + gen_isa(isa, fmt) fmt.update_file('encoding-{}.rs'.format(isa.name), out_dir) diff --git a/meta/isa/riscv/__init__.py b/meta/isa/riscv/__init__.py index 1f9ebd3f46..e187a95c0e 100644 --- a/meta/isa/riscv/__init__.py +++ b/meta/isa/riscv/__init__.py @@ -26,8 +26,7 @@ RV32G / RV64G """ from __future__ import absolute_import from . import defs -from . import encodings -from . import settings +from . import encodings, settings # noqa # Re-export the primary target ISA definition. -isa = defs.isa +isa = defs.isa.finish()