You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.3 KiB
135 lines
4.3 KiB
# Copyright 2018 The gemmlowp Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
# ==============================================================================
|
|
"""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.
|
|
|
|
Reads from stdin, writes to stdout.
|
|
|
|
Example diff:
|
|
- "udot v16.4s, v4.16b, v0.16b\n"
|
|
+ ".word 0x6e809490 // udot v16.4s, v4.16b, v0.16b\n"
|
|
|
|
The intended use case is to make asm code easier to compile on toolchains that
|
|
do not support certain new instructions.
|
|
"""
|
|
|
|
import sys
|
|
import re
|
|
import argparse
|
|
|
|
|
|
def encode_udot_sdot_vector(line):
|
|
m = re.search(
|
|
r'\b([us])dot[ ]+v([0-9]+)[ ]*\.[ ]*4s[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*16b[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*16b',
|
|
line)
|
|
if not m:
|
|
return 0, line
|
|
|
|
match = m.group(0)
|
|
unsigned = 1 if m.group(1) == 'u' else 0
|
|
accum = int(m.group(2))
|
|
lhs = int(m.group(3))
|
|
rhs = int(m.group(4))
|
|
assert accum >= 0 and accum <= 31
|
|
assert lhs >= 0 and lhs <= 31
|
|
assert rhs >= 0 and rhs <= 31
|
|
mcode = 0x4e809400 | (accum << 0) | (lhs << 5) | (rhs << 16) | (
|
|
unsigned << 29)
|
|
return mcode, match
|
|
|
|
|
|
def encode_udot_sdot_element(line):
|
|
m = re.search(
|
|
r'\b([us])dot[ ]+v([0-9]+)[ ]*\.[ ]*4s[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*16b[ ]*\,[ ]*v([0-9]+)[ ]*\.[ ]*4b[ ]*\[([0-9])\]',
|
|
line)
|
|
if not m:
|
|
return 0, line
|
|
|
|
match = m.group(0)
|
|
unsigned = 1 if m.group(1) == 'u' else 0
|
|
accum = int(m.group(2))
|
|
lhs = int(m.group(3))
|
|
rhs = int(m.group(4))
|
|
lanegroup = int(m.group(5))
|
|
assert accum >= 0 and accum <= 31
|
|
assert lhs >= 0 and lhs <= 31
|
|
assert rhs >= 0 and rhs <= 31
|
|
assert lanegroup >= 0 and lanegroup <= 3
|
|
l = 1 if lanegroup & 1 else 0
|
|
h = 1 if lanegroup & 2 else 0
|
|
mcode = 0x4f80e000 | (accum << 0) | (lhs << 5) | (rhs << 16) | (l << 21) | (
|
|
h << 11) | (
|
|
unsigned << 29)
|
|
return mcode, match
|
|
|
|
|
|
def encode(line):
|
|
for encode_func in [encode_udot_sdot_vector, encode_udot_sdot_element]:
|
|
mcode, match = encode_func(line)
|
|
if mcode:
|
|
return mcode, match
|
|
return 0, line
|
|
|
|
|
|
def read_existing_encoding(line):
|
|
m = re.search(r'\.word\ (0x[0-9a-f]+)', line)
|
|
if m:
|
|
return int(m.group(1), 16)
|
|
return 0
|
|
|
|
|
|
parser = argparse.ArgumentParser(description='Encode some A64 instructions.')
|
|
parser.add_argument(
|
|
'-f',
|
|
'--fix',
|
|
help='fix existing wrong encodings in-place and continue',
|
|
action='store_true')
|
|
args = parser.parse_args()
|
|
|
|
lineno = 0
|
|
found_existing_encodings = False
|
|
found_error = False
|
|
found_fixes = False
|
|
for line in sys.stdin:
|
|
lineno = lineno + 1
|
|
mcode, match = encode(line)
|
|
if mcode:
|
|
existing_encoding = read_existing_encoding(line)
|
|
if existing_encoding:
|
|
found_existing_encodings = True
|
|
if mcode != existing_encoding:
|
|
if args.fix:
|
|
line = line.replace('.word 0x%x // %s' % (existing_encoding, match),
|
|
'.word 0x%x // %s' % (mcode, match))
|
|
found_fixes = True
|
|
else:
|
|
sys.stderr.write(
|
|
"Error at line %d: existing encoding 0x%x differs from encoding 0x%x for instruction '%s':\n\n%s\n\n"
|
|
% (lineno, existing_encoding, mcode, match, line))
|
|
found_error = True
|
|
else:
|
|
line = line.replace(match, '.word 0x%x // %s' % (mcode, match))
|
|
sys.stdout.write(line)
|
|
if found_error:
|
|
sys.exit(1)
|
|
if found_existing_encodings:
|
|
if found_fixes:
|
|
sys.stderr.write(
|
|
'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'
|
|
)
|
|
else:
|
|
sys.stderr.write(
|
|
'Note: some instructions that this program is able to encode, were already encoded. These encodings have been checked.\n'
|
|
)
|