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