xref: /aosp_15_r20/external/gemmlowp/standalone/encode.py (revision 5f39d1b313f0528e11bae88b3029b54b9e1033e7)
1*5f39d1b3SJooyung Han# Copyright 2018 The gemmlowp Authors. All Rights Reserved.
2*5f39d1b3SJooyung Han#
3*5f39d1b3SJooyung Han# Licensed under the Apache License, Version 2.0 (the "License");
4*5f39d1b3SJooyung Han# you may not use this file except in compliance with the License.
5*5f39d1b3SJooyung Han# You may obtain a copy of the License at
6*5f39d1b3SJooyung Han#
7*5f39d1b3SJooyung Han#     http://www.apache.org/licenses/LICENSE-2.0
8*5f39d1b3SJooyung Han#
9*5f39d1b3SJooyung Han# Unless required by applicable law or agreed to in writing, software
10*5f39d1b3SJooyung Han# distributed under the License is distributed on an "AS IS" BASIS,
11*5f39d1b3SJooyung Han# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5f39d1b3SJooyung Han# See the License for the specific language governing permissions and
13*5f39d1b3SJooyung Han# limitations under the License.
14*5f39d1b3SJooyung Han# ==============================================================================
15*5f39d1b3SJooyung Han"""Encodes ARM asm code for certain instructions into the corresponding machine code encoding, as a .word directive in the asm code, preserving the original code in a comment.
16*5f39d1b3SJooyung Han
17*5f39d1b3SJooyung HanReads from stdin, writes to stdout.
18*5f39d1b3SJooyung Han
19*5f39d1b3SJooyung HanExample diff:
20*5f39d1b3SJooyung Han-        "udot v16.4s, v4.16b, v0.16b\n"
21*5f39d1b3SJooyung Han+        ".word 0x6e809490  // udot v16.4s, v4.16b, v0.16b\n"
22*5f39d1b3SJooyung Han
23*5f39d1b3SJooyung HanThe intended use case is to make asm code easier to compile on toolchains that
24*5f39d1b3SJooyung Hando not support certain new instructions.
25*5f39d1b3SJooyung Han"""
26*5f39d1b3SJooyung Han
27*5f39d1b3SJooyung Hanimport sys
28*5f39d1b3SJooyung Hanimport re
29*5f39d1b3SJooyung Hanimport argparse
30*5f39d1b3SJooyung Han
31*5f39d1b3SJooyung Han
32*5f39d1b3SJooyung Handef encode_udot_sdot_vector(line):
33*5f39d1b3SJooyung Han  m = re.search(
34*5f39d1b3SJooyung Han      r'\b([us])dot[ ]+v([0-9]+)[ ]*\.[ ]*4s[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*16b[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*16b',
35*5f39d1b3SJooyung Han      line)
36*5f39d1b3SJooyung Han  if not m:
37*5f39d1b3SJooyung Han    return 0, line
38*5f39d1b3SJooyung Han
39*5f39d1b3SJooyung Han  match = m.group(0)
40*5f39d1b3SJooyung Han  unsigned = 1 if m.group(1) == 'u' else 0
41*5f39d1b3SJooyung Han  accum = int(m.group(2))
42*5f39d1b3SJooyung Han  lhs = int(m.group(3))
43*5f39d1b3SJooyung Han  rhs = int(m.group(4))
44*5f39d1b3SJooyung Han  assert accum >= 0 and accum <= 31
45*5f39d1b3SJooyung Han  assert lhs >= 0 and lhs <= 31
46*5f39d1b3SJooyung Han  assert rhs >= 0 and rhs <= 31
47*5f39d1b3SJooyung Han  mcode = 0x4e809400 | (accum << 0) | (lhs << 5) | (rhs << 16) | (
48*5f39d1b3SJooyung Han      unsigned << 29)
49*5f39d1b3SJooyung Han  return mcode, match
50*5f39d1b3SJooyung Han
51*5f39d1b3SJooyung Han
52*5f39d1b3SJooyung Handef encode_udot_sdot_element(line):
53*5f39d1b3SJooyung Han  m = re.search(
54*5f39d1b3SJooyung Han      r'\b([us])dot[ ]+v([0-9]+)[ ]*\.[ ]*4s[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*16b[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*4b[ ]*\[([0-9])\]',
55*5f39d1b3SJooyung Han      line)
56*5f39d1b3SJooyung Han  if not m:
57*5f39d1b3SJooyung Han    return 0, line
58*5f39d1b3SJooyung Han
59*5f39d1b3SJooyung Han  match = m.group(0)
60*5f39d1b3SJooyung Han  unsigned = 1 if m.group(1) == 'u' else 0
61*5f39d1b3SJooyung Han  accum = int(m.group(2))
62*5f39d1b3SJooyung Han  lhs = int(m.group(3))
63*5f39d1b3SJooyung Han  rhs = int(m.group(4))
64*5f39d1b3SJooyung Han  lanegroup = int(m.group(5))
65*5f39d1b3SJooyung Han  assert accum >= 0 and accum <= 31
66*5f39d1b3SJooyung Han  assert lhs >= 0 and lhs <= 31
67*5f39d1b3SJooyung Han  assert rhs >= 0 and rhs <= 31
68*5f39d1b3SJooyung Han  assert lanegroup >= 0 and lanegroup <= 3
69*5f39d1b3SJooyung Han  l = 1 if lanegroup & 1 else 0
70*5f39d1b3SJooyung Han  h = 1 if lanegroup & 2 else 0
71*5f39d1b3SJooyung Han  mcode = 0x4f80e000 | (accum << 0) | (lhs << 5) | (rhs << 16) | (l << 21) | (
72*5f39d1b3SJooyung Han      h << 11) | (
73*5f39d1b3SJooyung Han          unsigned << 29)
74*5f39d1b3SJooyung Han  return mcode, match
75*5f39d1b3SJooyung Han
76*5f39d1b3SJooyung Han
77*5f39d1b3SJooyung Handef encode(line):
78*5f39d1b3SJooyung Han  for encode_func in [encode_udot_sdot_vector, encode_udot_sdot_element]:
79*5f39d1b3SJooyung Han    mcode, match = encode_func(line)
80*5f39d1b3SJooyung Han    if mcode:
81*5f39d1b3SJooyung Han      return mcode, match
82*5f39d1b3SJooyung Han  return 0, line
83*5f39d1b3SJooyung Han
84*5f39d1b3SJooyung Han
85*5f39d1b3SJooyung Handef read_existing_encoding(line):
86*5f39d1b3SJooyung Han  m = re.search(r'\.word\ (0x[0-9a-f]+)', line)
87*5f39d1b3SJooyung Han  if m:
88*5f39d1b3SJooyung Han    return int(m.group(1), 16)
89*5f39d1b3SJooyung Han  return 0
90*5f39d1b3SJooyung Han
91*5f39d1b3SJooyung Han
92*5f39d1b3SJooyung Hanparser = argparse.ArgumentParser(description='Encode some A64 instructions.')
93*5f39d1b3SJooyung Hanparser.add_argument(
94*5f39d1b3SJooyung Han    '-f',
95*5f39d1b3SJooyung Han    '--fix',
96*5f39d1b3SJooyung Han    help='fix existing wrong encodings in-place and continue',
97*5f39d1b3SJooyung Han    action='store_true')
98*5f39d1b3SJooyung Hanargs = parser.parse_args()
99*5f39d1b3SJooyung Han
100*5f39d1b3SJooyung Hanlineno = 0
101*5f39d1b3SJooyung Hanfound_existing_encodings = False
102*5f39d1b3SJooyung Hanfound_error = False
103*5f39d1b3SJooyung Hanfound_fixes = False
104*5f39d1b3SJooyung Hanfor line in sys.stdin:
105*5f39d1b3SJooyung Han  lineno = lineno + 1
106*5f39d1b3SJooyung Han  mcode, match = encode(line)
107*5f39d1b3SJooyung Han  if mcode:
108*5f39d1b3SJooyung Han    existing_encoding = read_existing_encoding(line)
109*5f39d1b3SJooyung Han    if existing_encoding:
110*5f39d1b3SJooyung Han      found_existing_encodings = True
111*5f39d1b3SJooyung Han      if mcode != existing_encoding:
112*5f39d1b3SJooyung Han        if args.fix:
113*5f39d1b3SJooyung Han          line = line.replace('.word 0x%x  // %s' % (existing_encoding, match),
114*5f39d1b3SJooyung Han                              '.word 0x%x  // %s' % (mcode, match))
115*5f39d1b3SJooyung Han          found_fixes = True
116*5f39d1b3SJooyung Han        else:
117*5f39d1b3SJooyung Han          sys.stderr.write(
118*5f39d1b3SJooyung Han              "Error at line %d: existing encoding 0x%x differs from encoding 0x%x for instruction '%s':\n\n%s\n\n"
119*5f39d1b3SJooyung Han              % (lineno, existing_encoding, mcode, match, line))
120*5f39d1b3SJooyung Han          found_error = True
121*5f39d1b3SJooyung Han    else:
122*5f39d1b3SJooyung Han      line = line.replace(match, '.word 0x%x  // %s' % (mcode, match))
123*5f39d1b3SJooyung Han  sys.stdout.write(line)
124*5f39d1b3SJooyung Hanif found_error:
125*5f39d1b3SJooyung Han  sys.exit(1)
126*5f39d1b3SJooyung Hanif found_existing_encodings:
127*5f39d1b3SJooyung Han  if found_fixes:
128*5f39d1b3SJooyung Han    sys.stderr.write(
129*5f39d1b3SJooyung Han        'Note: some instructions that this program is able to encode, were already encoded and their existing encodings didn\'t match the specified asm instructions. Since --fix was passed, these were fixed in-place.\n'
130*5f39d1b3SJooyung Han    )
131*5f39d1b3SJooyung Han  else:
132*5f39d1b3SJooyung Han    sys.stderr.write(
133*5f39d1b3SJooyung Han        'Note: some instructions that this program is able to encode, were already encoded. These encodings have been checked.\n'
134*5f39d1b3SJooyung Han    )
135