diff --git a/osaca/data/a64fx.yml b/osaca/data/a64fx.yml index 8f35c75..a1a6d48 100644 --- a/osaca/data/a64fx.yml +++ b/osaca/data/a64fx.yml @@ -770,7 +770,24 @@ instruction_forms: throughput: 43.0 latency: 43.0 # 1*p0+43*p0DV port_pressure: [[1, '0'], [43.0, [0DV]]] -- name: [fmad, fmla] +- name: [fmad, fmla, mla] + operands: + - class: register + prefix: z + shape: d + width: '*' + - class: register + prefix: z + shape: d + width: '*' + - class: register + prefix: z + shape: d + width: '*' + throughput: 0.5 + latency: 9.0 # 1*p02 + port_pressure: [[1, '02']] +- name: [fmad, fmla, mla, fmsb, fmls, mls] operands: - class: register prefix: z @@ -790,7 +807,7 @@ instruction_forms: throughput: 0.5 latency: 9.0 # 1*p02 port_pressure: [[1, '02']] -- name: [fmad, fmla] +- name: [fmad, fmla, fmsb, fmls] operands: - class: register prefix: z @@ -812,36 +829,19 @@ instruction_forms: throughput: 0.5 latency: 9.0 # 1*p02 port_pressure: [[1, '02']] -- name: [fmla, fmls] +- name: [fmla, fmls, mla, mls] operands: - class: register prefix: v - shape: s + shape: '*' width: '*' - class: register prefix: v - shape: s + shape: '*' width: '*' - class: register prefix: v - shape: s - width: '*' - throughput: 0.5 - latency: 9.0 # 1*p02 - port_pressure: [[1, '02']] -- name: [fmla, fmls] - operands: - - class: register - prefix: v - shape: d - width: '*' - - class: register - prefix: v - shape: d - width: '*' - - class: register - prefix: v - shape: d + shape: '*' width: '*' throughput: 0.5 latency: 9.0 # 1*p02 @@ -1951,15 +1951,26 @@ instruction_forms: operands: - class: register prefix: v - shape: b + shape: '*' width: '*' - class: register prefix: v - shape: b + shape: '*' width: '*' throughput: 0.5 latency: 4.0 # 1*p02 port_pressure: [[1, '02']] +- name: mov + operands: + - class: register + prefix: '*' + - class: register + prefix: v + shape: '*' + width: '*' + throughput: 3.0 + latency: 15.0 # 3*p0+3*p3 + port_pressure: [[3, '0'], [3, '3']] - name: movprfx operands: - class: register @@ -2306,6 +2317,20 @@ instruction_forms: throughput: 1.0 latency: 0 # 1*p56+1*p0 port_pressure: [[1, '5'], [1,'6'], [1, '0']] +- name: str + operands: + - class: register + prefix: d + - class: memory + base: x + offset: '*' + index: '*' + scale: '*' + pre-indexed: true + post-indexed: false + throughput: 1.0 + latency: 0 # 1*p56+1*p0+1*p0234 + port_pressure: [[1, '5'], [1,'6'], [1, '0'], [1, '0234']] - name: str operands: - class: register @@ -2598,8 +2623,50 @@ instruction_forms: throughput: 1.0 latency: 6.0 port_pressure: [[1, '2']] - - - - - +- name: [sadalp, uadalp] + operands: + - class: register + prefix: v + shape: '*' + width: '*' + - class: register + prefix: v + shape: '*' + width: '*' + throughput: 3.0 + latency: 14.0 + port_pressure: [[3, '2']] +- name: [smlal, smlal2] + operands: + - class: register + prefix: v + shape: s + width: '*' + - class: register + prefix: v + shape: '*' + width: '*' + - class: register + prefix: v + shape: '*' + width: '*' + throughput: 8.0 + latency: 18.0 + port_pressure: {0: [[8, '0']], 1: [[8, '2']]} +- name: [smlal, smlal2] + operands: + - class: register + prefix: v + shape: d + width: '*' + - class: register + prefix: v + shape: '*' + width: '*' + - class: register + prefix: v + shape: '*' + width: '*' + throughput: 3.0 + latency: 15.0 + port_pressure: {0: [[3, '0']], 1: [[3, '2']]} diff --git a/osaca/data/isa/aarch64.yml b/osaca/data/isa/aarch64.yml index 144ef0c..73c6223 100644 --- a/osaca/data/isa/aarch64.yml +++ b/osaca/data/isa/aarch64.yml @@ -811,7 +811,7 @@ instruction_forms: imd: int source: false destination: false - - name: fmla + - name: [fmla, fmad, mla, fmls, fmsb, mls] operands: - class: register prefix: "*" @@ -833,7 +833,7 @@ instruction_forms: shape: "*" source: true destination: false - - name: fmla + - name: [fmla, mla, fmls, mls, smlal, smlal2, smlalb, smlalt, smlsl, smlsl2, smlslb, smlslt, umlal, umlal2, umlalb, umlalt, umlsl, umlsl2, umlslb, umlslt] operands: - class: register prefix: "*" @@ -3358,3 +3358,48 @@ instruction_forms: name: "V" source: true destination: true + - name: [sadalp, uadalp] + operands: + - class: register + prefix: "*" + shape: "*" + source: true + destination: true + - class: register + prefix: "*" + shape: "*" + source: true + destination: false + - name: [sadalp, uadalp, sabal, sabal2, sabalb, sabalt] + operands: + - class: register + prefix: "*" + shape: "*" + source: true + destination: true + - class: register + prefix: "*" + shape: "*" + source: true + destination: false + - class: register + prefix: "*" + shape: "*" + source: true + destination: false + - name: [ssra, srsra, usra, ursra] + operands: + - class: register + prefix: "*" + shape: "*" + source: true + destination: true + - class: register + prefix: "*" + shape: "*" + source: true + destination: false + - class: immediate + imd: "int" + source: true + destination: false diff --git a/osaca/parser/parser_AArch64.py b/osaca/parser/parser_AArch64.py index fec3261..439ddbc 100755 --- a/osaca/parser/parser_AArch64.py +++ b/osaca/parser/parser_AArch64.py @@ -132,8 +132,8 @@ class ParserAArch64(BaseParser): pp.Literal(".") + pp.Optional(pp.Word("12468")).setResultsName("lanes") + pp.Word(pp.alphas, exact=1).setResultsName("shape") - + pp.Optional(index) ) + + pp.Optional(index) ) predicate = ( pp.CaselessLiteral("p").setResultsName("prefix") @@ -533,15 +533,12 @@ class ParserAArch64(BaseParser): def get_full_reg_name(self, register): """Return one register name string including all attributes""" - if "lanes" in register: - return ( - register["prefix"] - + str(register["name"]) - + "." - + str(register["lanes"]) - + register["shape"] - ) - return register["prefix"] + str(register["name"]) + name = register["prefix"] + str(register["name"]) + if "shape" in register: + name += "." + str(register.get("lanes", "")) + register["shape"] + if "index" in register: + name += "[" + register["index"] + "]" + return name def normalize_imd(self, imd): """Normalize immediate to decimal based representation""" diff --git a/osaca/semantics/arch_semantics.py b/osaca/semantics/arch_semantics.py index 10b3a97..e37a674 100755 --- a/osaca/semantics/arch_semantics.py +++ b/osaca/semantics/arch_semantics.py @@ -192,11 +192,25 @@ class ArchSemantics(ISASemantics): instruction_data = self._machine_model.get_instruction( instruction_form["instruction"], instruction_form["operands"] ) - if not instruction_data and instruction_form["instruction"][-1] in self.GAS_SUFFIXES: + if ( + not instruction_data + and self._isa == "x86" + and instruction_form["instruction"][-1] in self.GAS_SUFFIXES + ): # check for instruction without GAS suffix instruction_data = self._machine_model.get_instruction( instruction_form["instruction"][:-1], instruction_form["operands"] ) + if ( + instruction_data is None + and self._isa == "aarch64" + and "." in instruction_form["instruction"] + ): + # Check for instruction without shape/cc suffix + suffix_start = instruction_form["instruction"].index(".") + instruction_data = self._machine_model.get_instruction( + instruction_form["instruction"][:suffix_start], instruction_form["operands"] + ) if instruction_data: # instruction form in DB ( @@ -223,12 +237,23 @@ class ArchSemantics(ISASemantics): ) if ( not instruction_data_reg + and self._isa == "x86" and instruction_form["instruction"][-1] in self.GAS_SUFFIXES ): # check for instruction without GAS suffix instruction_data_reg = self._machine_model.get_instruction( instruction_form["instruction"][:-1], operands ) + if ( + instruction_data_reg is None + and self._isa == "aarch64" + and "." in instruction_form["instruction"] + ): + # Check for instruction without shape/cc suffix + suffix_start = instruction_form["instruction"].index(".") + instruction_data_reg = self._machine_model.get_instruction( + instruction_form["instruction"][:suffix_start], operands + ) if instruction_data_reg: assign_unknown = False reg_type = self._parser.get_reg_type( diff --git a/osaca/semantics/isa_semantics.py b/osaca/semantics/isa_semantics.py index 6d523a7..1c26818 100755 --- a/osaca/semantics/isa_semantics.py +++ b/osaca/semantics/isa_semantics.py @@ -55,11 +55,21 @@ class ISASemantics(object): isa_data = self._isa_model.get_instruction( instruction_form["instruction"], instruction_form["operands"] ) - if isa_data is None and instruction_form["instruction"][-1] in self.GAS_SUFFIXES: + if ( + isa_data is None + and self._isa == "x86" + and instruction_form["instruction"][-1] in self.GAS_SUFFIXES + ): # Check for instruction without GAS suffix isa_data = self._isa_model.get_instruction( instruction_form["instruction"][:-1], instruction_form["operands"] ) + if isa_data is None and self._isa == "aarch64" and "." in instruction_form["instruction"]: + # Check for instruction without shape/cc suffix + suffix_start = instruction_form["instruction"].index(".") + isa_data = self._isa_model.get_instruction( + instruction_form["instruction"][:suffix_start], instruction_form["operands"] + ) operands = instruction_form["operands"] op_dict = {} assign_default = False @@ -77,12 +87,23 @@ class ISASemantics(object): ) if ( isa_data_reg is None + and self._isa == "x86" and instruction_form["instruction"][-1] in self.GAS_SUFFIXES ): # Check for instruction without GAS suffix isa_data_reg = self._isa_model.get_instruction( instruction_form["instruction"][:-1], operands_reg ) + if ( + isa_data_reg is None + and self._isa == "aarch64" + and "." in instruction_form["instruction"] + ): + # Check for instruction without shape/cc suffix + suffix_start = instruction_form["instruction"].index(".") + isa_data_reg = self._isa_model.get_instruction( + instruction_form["instruction"][:suffix_start], operands_reg + ) if isa_data_reg: assign_default = False op_dict = self._apply_found_ISA_data(isa_data_reg, operands) @@ -158,11 +179,21 @@ class ISASemantics(object): isa_data = self._isa_model.get_instruction( instruction_form["instruction"], instruction_form["operands"] ) - if isa_data is None and instruction_form["instruction"][-1] in self.GAS_SUFFIXES: + if ( + isa_data is None + and self._isa == "x86" + and instruction_form["instruction"][-1] in self.GAS_SUFFIXES + ): # Check for instruction without GAS suffix isa_data = self._isa_model.get_instruction( instruction_form["instruction"][:-1], instruction_form["operands"] ) + if isa_data is None and self._isa == "aarch64" and "." in instruction_form["instruction"]: + # Check for instruction without shape/cc suffix + suffix_start = instruction_form["instruction"].index(".") + isa_data = self._isa_model.get_instruction( + instruction_form["instruction"][:suffix_start], instruction_form["operands"] + ) if only_postindexed: for o in instruction_form.operands: diff --git a/tests/test_files/kernel_aarch64.s b/tests/test_files/kernel_aarch64.s index 7e4b87a..22d2bc7 100644 --- a/tests/test_files/kernel_aarch64.s +++ b/tests/test_files/kernel_aarch64.s @@ -23,3 +23,4 @@ // OSACA-END fmov s1, #2.0e+2f prfm pldl1keep, [x26, #2112] + add x11, x11, x11 diff --git a/tests/test_parser_AArch64.py b/tests/test_parser_AArch64.py index ba11504..0bac579 100755 --- a/tests/test_parser_AArch64.py +++ b/tests/test_parser_AArch64.py @@ -89,7 +89,8 @@ class TestParserAArch64(unittest.TestCase): instr5 = "ldr x0, [x0, #:got_lo12:q2c]" instr6 = "adrp x0, :got:visited" instr7 = "fadd v17.2d, v16.2d, v1.2d" - instr8 = "ccmp x0, x1, #4, cc" + instr8 = "mov.d x0, v16.d[1]" + instr9 = "ccmp x0, x1, #4, cc" parsed_1 = self.parser.parse_instruction(instr1) parsed_2 = self.parser.parse_instruction(instr2) @@ -99,6 +100,7 @@ class TestParserAArch64(unittest.TestCase): parsed_6 = self.parser.parse_instruction(instr6) parsed_7 = self.parser.parse_instruction(instr7) parsed_8 = self.parser.parse_instruction(instr8) + parsed_9 = self.parser.parse_instruction(instr9) self.assertEqual(parsed_1.instruction, "vcvt.F32.S32") self.assertEqual(parsed_1.operands[0].register.name, "1") @@ -152,10 +154,18 @@ class TestParserAArch64(unittest.TestCase): self.assertEqual(parsed_7.operands[0].register.shape, "d") self.assertEqual(self.parser.get_full_reg_name(parsed_7.operands[2].register), "v1.2d") - self.assertEqual(parsed_8.instruction, "ccmp") + self.assertEqual(parsed_8.instruction, "mov.d") self.assertEqual(parsed_8.operands[0].register.name, "0") self.assertEqual(parsed_8.operands[0].register.prefix, "x") - self.assertEqual(parsed_8.operands[3].condition, "CC") + self.assertEqual(parsed_8.operands[1].register.name, "16") + self.assertEqual(parsed_8.operands[1].register.prefix, "v") + self.assertEqual(parsed_8.operands[1].register.index, "1") + self.assertEqual(self.parser.get_full_reg_name(parsed_8.operands[1].register), "v16.d[1]") + + self.assertEqual(parsed_9.instruction, "ccmp") + self.assertEqual(parsed_9.operands[0].register.name, "0") + self.assertEqual(parsed_9.operands[0].register.prefix, "x") + self.assertEqual(parsed_9.operands[3].condition, "CC") def test_parse_line(self): line_comment = "// -- Begin main" diff --git a/tests/test_semantics.py b/tests/test_semantics.py index f044a00..48247a0 100755 --- a/tests/test_semantics.py +++ b/tests/test_semantics.py @@ -167,6 +167,10 @@ class TestSemanticTools(unittest.TestCase): test_mm_arm.get_instruction("b.ne", [{"class": "identifier"}]), test_mm_arm.get_instruction("b.ne", [{"class": "identifier"}]), ) + self.assertEqual( + test_mm_arm.get_instruction("b.someNameThatDoesNotExist", [{"class": "identifier"}]), + test_mm_arm.get_instruction("b.someOtherName", [{"class": "identifier"}]), + ) # test full instruction name self.assertEqual(