-rwxr-xr-x 15949 libmceliece-20240726/inttypes/readasm.py raw
#!/usr/bin/env python3 import re import sys machinedesc = {} # note for qhasm users: # the machine descriptions here have, e.g., # int8 meaning where the C ABI stores an int8, # such as a 64-bit integer register on amd64 # ===== amd64 machinedesc['amd64'] = r''' int8 r:var/r=int8: int16 r:var/r=int16: int32 r:var/r=int32: int64 r:var/r=int64: int8 r s:var/r=int8:var/s=int8: int16 r s:var/r=int16:var/s=int16: int32 r s:var/r=int32:var/s=int32: int64 r s:var/r=int64:var/s=int64: int8 r s t:var/r=int8:var/s=int8:var/t=int8: int16 r s t:var/r=int16:var/s=int16:var/t=int16: int32 r s t:var/r=int32:var/s=int32:var/t=int32: int64 r s t:var/r=int64:var/s=int64:var/t=int64: int8 r s t u:var/r=int8:var/s=int8:var/t=int8:var/u=int8: int16 r s t u:var/r=int16:var/s=int16:var/t=int16:var/u=int16: int32 r s t u:var/r=int32:var/s=int32:var/t=int32:var/u=int32: int64 r s t u:var/r=int64:var/s=int64:var/t=int64:var/u=int64: r signed>>= n:+r=int8:#n:asm/sarb $#n,+r:>?cc: r signed>>= n:+r=int16:#n:asm/sarw $#n,+r:>?cc: r signed>>= n:+r=int32:#n:asm/sarl $#n,+r:>?cc: r signed>>= n:+r=int64:#n:asm/sarq $#n,+r:>?cc: r signed>>= s:+r=int8:<s=int8#4:asm/sarb %%cl,+r:>?cc: r signed>>= s:+r=int16:<s=int16#4:asm/sarw %%cl,+r:>?cc: r signed>>= s:+r=int32:<s=int32#4:asm/sarl %%cl,+r:>?cc: r signed>>= s:+r=int64:<s=int64#4:asm/sarq %%cl,+r:>?cc: r unsigned>>= n:+r=int8:#n:asm/shrb $#n,+r:>?cc: r unsigned>>= n:+r=int16:#n:asm/shrw $#n,+r:>?cc: r unsigned>>= n:+r=int32:#n:asm/shrl $#n,+r:>?cc: r unsigned>>= n:+r=int64:#n:asm/shrq $#n,+r:>?cc: r unsigned>>= s:+r=int8:<s=int8#4:asm/shrb %%cl,+r:>?cc: r unsigned>>= s:+r=int16:<s=int16#4:asm/shrw %%cl,+r:>?cc: r unsigned>>= s:+r=int32:<s=int32#4:asm/shrl %%cl,+r:>?cc: r unsigned>>= s:+r=int64:<s=int64#4:asm/shrq %%cl,+r:>?cc: r <<= n:+r=int8:#n:asm/shlb $#n,+r:>?cc: r <<= n:+r=int16:#n:asm/shlw $#n,+r:>?cc: r <<= n:+r=int32:#n:asm/shll $#n,+r:>?cc: r <<= n:+r=int64:#n:asm/shlq $#n,+r:>?cc: r <<= s:+r=int8:<s=int8#4:asm/shlb %%cl,+r:>?cc: r <<= s:+r=int16:<s=int16#4:asm/shlw %%cl,+r:>?cc: r <<= s:+r=int32:<s=int32#4:asm/shll %%cl,+r:>?cc: r <<= s:+r=int64:<s=int64#4:asm/shlq %%cl,+r:>?cc: r &= n:+r=int8:#n:asm/andb $#n,+r:>?cc: r &= n:+r=int16:#n:asm/andw $#n,+r:>?cc: r &= n:+r=int32:#n:asm/andl $#n,+r:>?cc: r &= n:+r=int64:#n:asm/andq $#n,+r:>?cc: r - (int8) s:<r=int32:<s=int32:asm/cmpb <s%8,<r%8:>?cc: r - s:<r=int16:<s=int16:asm/cmpw <s,<r:>?cc: r - s:<r=int32:<s=int32:asm/cmpl <s,<r:>?cc: r - s:<r=int64:<s=int64:asm/cmpq <s,<r:>?cc: r = s:>r=int16:<s=int16:asm/movw <s,>r: r = s:>r=int32:<s=int32:asm/movl <s,>r: r = s:>r=int64:<s=int64:asm/movq <s,>r: r = s if signed<:+r=int16:<s=int16:<?cc:asm/cmovlw <s,+r: r = s if signed<:+r=int32:<s=int32:<?cc:asm/cmovll <s,+r: r = s if signed<:+r=int64:<s=int64:<?cc:asm/cmovlq <s,+r: r = s if signed>:+r=int16:<s=int16:<?cc:asm/cmovgw <s,+r: r = s if signed>:+r=int32:<s=int32:<?cc:asm/cmovgl <s,+r: r = s if signed>:+r=int64:<s=int64:<?cc:asm/cmovgq <s,+r: r = s if unsigned<:+r=int16:<s=int16:<?cc:asm/cmovbw <s,+r: r = s if unsigned<:+r=int32:<s=int32:<?cc:asm/cmovbl <s,+r: r = s if unsigned<:+r=int64:<s=int64:<?cc:asm/cmovbq <s,+r: r = s if unsigned>:+r=int16:<s=int16:<?cc:asm/cmovaw <s,+r: r = s if unsigned>:+r=int32:<s=int32:<?cc:asm/cmoval <s,+r: r = s if unsigned>:+r=int64:<s=int64:<?cc:asm/cmovaq <s,+r: r = s if =:+r=int16:<s=int16:<?cc:asm/cmovew <s,+r: r = s if =:+r=int32:<s=int32:<?cc:asm/cmovel <s,+r: r = s if =:+r=int64:<s=int64:<?cc:asm/cmoveq <s,+r: r = numbottomzeros_tricky s:>r=int16:<s=int16:>?cc:asm/bsfw <s,>r: r = numbottomzeros_tricky s:>r=int32:<s=int32:>?cc:asm/bsfl <s,>r: r = numbottomzeros_tricky s:>r=int64:<s=int64:>?cc:asm/bsfq <s,>r: ''' # ===== arm64 machinedesc['arm64'] = r''' int8 r:var/r=int8: int16 r:var/r=int16: int32 r:var/r=int32: int64 r:var/r=int64: int8 r s:var/r=int8:var/s=int8: int16 r s:var/r=int16:var/s=int16: int32 r s:var/r=int32:var/s=int32: int64 r s:var/r=int64:var/s=int64: int8 r s t:var/r=int8:var/s=int8:var/t=int8: int16 r s t:var/r=int16:var/s=int16:var/t=int16: int32 r s t:var/r=int32:var/s=int32:var/t=int32: int64 r s t:var/r=int64:var/s=int64:var/t=int64: int8 r s t u:var/r=int8:var/s=int8:var/t=int8:var/u=int8: int16 r s t u:var/r=int16:var/s=int16:var/t=int16:var/u=int16: int32 r s t u:var/r=int32:var/s=int32:var/t=int32:var/u=int32: int64 r s t u:var/r=int64:var/s=int64:var/t=int64:var/u=int64: r = s signed>> n:>r=int32:<s=int32:#n:asm/asr >r,<s,#n: r = s signed>> n:>r=int64:<s=int64:#n:asm/asr >r,<s,#n: r = s unsigned>> n:>r=int32:<s=int32:#n:asm/lsr >r,<s,#n: r = s unsigned>> n:>r=int64:<s=int64:#n:asm/lsr >r,<s,#n: r = s signed>> t:>r=int8:<s=int8:<t=int8:#n:asm/asr >r,<s,<t: r = s signed>> t:>r=int16:<s=int16:<t=int16:#n:asm/asr >r,<s,<t: r = s signed>> t:>r=int32:<s=int32:<t=int32:#n:asm/asr >r,<s,<t: r = s signed>> t:>r=int64:<s=int64:<t=int64:#n:asm/asr >r,<s,<t: r = s unsigned>> t:>r=int8:<s=int8:<t=int8:#n:asm/lsr >r,<s,<t: r = s unsigned>> t:>r=int16:<s=int16:<t=int16:#n:asm/lsr >r,<s,<t: r = s unsigned>> t:>r=int32:<s=int32:<t=int32:#n:asm/lsr >r,<s,<t: r = s unsigned>> t:>r=int64:<s=int64:<t=int64:#n:asm/lsr >r,<s,<t: r = s << t:>r=int8:<s=int8:<t=int8:#n:asm/lsl >r,<s,<t: r = s << t:>r=int16:<s=int16:<t=int16:#n:asm/lsl >r,<s,<t: r = s << t:>r=int32:<s=int32:<t=int32:#n:asm/lsl >r,<s,<t: r = s << t:>r=int64:<s=int64:<t=int64:#n:asm/lsl >r,<s,<t: r = s | n:>r=int8:<s=int8:#n:asm/orr >r,<s,#n: r = s | n:>r=int16:<s=int16:#n:asm/orr >r,<s,#n: r = s | -n:>r=int8:<s=int8:#n:asm/orr >r,<s,-#n: r = s | -n:>r=int16:<s=int16:#n:asm/orr >r,<s,-#n: r = (int8) s:>r=int8:<s=int8:asm/sxtb >r,<s: r = (uint8) s:>r=int8:<s=int8:asm/and >r,<s,255: r = (int16) s:>r=int16:<s=int16:asm/sxth >r,<s: r = (uint16) s:>r=int16:<s=int16:asm/and >r,<s,65535: r = s & n:>r=int8:<s=int8:#n:asm/and >r,<s,#n: r = s & n:>r=int16:<s=int16:#n:asm/and >r,<s,#n: r & n:<r=int8:#n:asm/tst <r,#n:>?cc: r & n:<r=int16:#n:asm/tst <r,#n:>?cc: r - n:<r=int8:#n:asm/cmp <r,#n:>?cc: r - n:<r=int16:#n:asm/cmp <r,#n:>?cc: r - n:<r=int32:#n:asm/cmp <r,#n:>?cc: r - n:<r=int64:#n:asm/cmp <r,#n:>?cc: r - s:<r=int8:<s=int8:asm/cmp <r,<s:>?cc: r - s:<r=int16:<s=int16:asm/cmp <r,<s:>?cc: r - s:<r=int32:<s=int32:asm/cmp <r,<s:>?cc: r - s:<r=int64:<s=int64:asm/cmp <r,<s:>?cc: r - (int8) s:<r=int8:<s=int8:asm/cmp <r,<s,sxtb:>?cc: r - (uint8) s:<r=int8:<s=int8:asm/cmp <r,<s,uxtb:>?cc: r - (int16) s:<r=int16:<s=int16:asm/cmp <r,<s,sxth:>?cc: r - (uint16) s:<r=int16:<s=int16:asm/cmp <r,<s,uxth:>?cc: r = -1 if != else 0:>r=int8:<?cc:asm/csetm >r,ne: r = -1 if != else 0:>r=int16:<?cc:asm/csetm >r,ne: r = -1 if != else 0:>r=int32:<?cc:asm/csetm >r,ne: r = -1 if != else 0:>r=int64:<?cc:asm/csetm >r,ne: r = -1 if = else 0:>r=int8:<?cc:asm/csetm >r,eq: r = -1 if = else 0:>r=int16:<?cc:asm/csetm >r,eq: r = -1 if = else 0:>r=int32:<?cc:asm/csetm >r,eq: r = -1 if = else 0:>r=int64:<?cc:asm/csetm >r,eq: r = -1 if signed< else 0:>r=int8:<?cc:asm/csetm >r,lt: r = -1 if signed< else 0:>r=int16:<?cc:asm/csetm >r,lt: r = -1 if signed< else 0:>r=int32:<?cc:asm/csetm >r,lt: r = -1 if signed< else 0:>r=int64:<?cc:asm/csetm >r,lt: r = -1 if signed> else 0:>r=int8:<?cc:asm/csetm >r,gt: r = -1 if signed> else 0:>r=int16:<?cc:asm/csetm >r,gt: r = -1 if signed> else 0:>r=int32:<?cc:asm/csetm >r,gt: r = -1 if signed> else 0:>r=int64:<?cc:asm/csetm >r,gt: r = -1 if signed<= else 0:>r=int8:<?cc:asm/csetm >r,le: r = -1 if signed<= else 0:>r=int16:<?cc:asm/csetm >r,le: r = -1 if signed<= else 0:>r=int32:<?cc:asm/csetm >r,le: r = -1 if signed<= else 0:>r=int64:<?cc:asm/csetm >r,le: r = -1 if unsigned< else 0:>r=int8:<?cc:asm/csetm >r,lo: r = -1 if unsigned< else 0:>r=int16:<?cc:asm/csetm >r,lo: r = -1 if unsigned< else 0:>r=int32:<?cc:asm/csetm >r,lo: r = -1 if unsigned< else 0:>r=int64:<?cc:asm/csetm >r,lo: r = -1 if unsigned<= else 0:>r=int8:<?cc:asm/csetm >r,ls: r = -1 if unsigned<= else 0:>r=int16:<?cc:asm/csetm >r,ls: r = -1 if unsigned<= else 0:>r=int32:<?cc:asm/csetm >r,ls: r = -1 if unsigned<= else 0:>r=int64:<?cc:asm/csetm >r,ls: r = s if signed< else t:>r=int8:<s=int8:<t=int8:<?cc:asm/csel >r,<s,<t,lt: r = s if signed< else t:>r=int16:<s=int16:<t=int16:<?cc:asm/csel >r,<s,<t,lt: r = s if signed< else t:>r=int32:<s=int32:<t=int32:<?cc:asm/csel >r,<s,<t,lt: r = s if signed< else t:>r=int64:<s=int64:<t=int64:<?cc:asm/csel >r,<s,<t,lt: r = s if unsigned< else t:>r=int8:<s=int8:<t=int8:<?cc:asm/csel >r,<s,<t,lo: r = s if unsigned< else t:>r=int16:<s=int16:<t=int16:<?cc:asm/csel >r,<s,<t,lo: r = s if unsigned< else t:>r=int32:<s=int32:<t=int32:<?cc:asm/csel >r,<s,<t,lo: r = s if unsigned< else t:>r=int64:<s=int64:<t=int64:<?cc:asm/csel >r,<s,<t,lo: r = bitrev32 s:>r=int8:<s=int8:asm/rbit >r,<s: r = bitrev32 s:>r=int16:<s=int16:asm/rbit >r,<s: r = bitrev32 s:>r=int32:<s=int32:asm/rbit >r,<s: r = bitrev64 s:>r=int64:<s=int64:asm/rbit >r,<s: r = numbottomzeros s:>r=int8:<s=int8:asm/clz >r,<s: r = numbottomzeros s:>r=int16:<s=int16:asm/clz >r,<s: r = numbottomzeros s:>r=int32:<s=int32:asm/clz >r,<s: r = numbottomzeros s:>r=int64:<s=int64:asm/clz >r,<s: r = -(1 & (s unsigned>> n)):>r=int8:<s=int8:#n:asm/sbfx >r,<s,#n,1: r = -(1 & (s unsigned>> n)):>r=int16:<s=int16:#n:asm/sbfx >r,<s,#n,1: r = -(1 & (s unsigned>> n)):>r=int32:<s=int32:#n:asm/sbfx >r,<s,#n,1: r = -(1 & (s unsigned>> n)):>r=int64:<s=int64:#n:asm/sbfx >r,<s,#n,1: ''' # ===== general processing def isvarname(line): return re.fullmatch(r'\w+',line) def tokens(line): return re.findall(r'\w+|[^\w\s]',line) def process(script): todo = [] machine = None vartype = {} ccinit = False inputvars = [] outputvars = [] earlyclobber = set() rcxvars = set() for line in script.split(';'): line = tokens(line.strip()) if machine is None: assert len(line) == 1 machine = line[0] assert machine in machinedesc continue foundinsn = False for insndesc in machinedesc[machine].splitlines(): insndesc = insndesc.split(':') if len(insndesc) == 0: continue insnvars = [] insnvartype = {} insnvarpos = {} insnvar2line = {} insnmakevars = [] insnasm = [] insnread = [] insnwrite = [] for x in insndesc[1:]: if x == '': continue if x[0] == '#': assert len(x) == 2 insnvars += [x[1]] insnvartype[x[1]] = '#' continue if x[0] in ('<','+','>'): if x[1:] == '?cc': if x[0] != '<': insnwrite += ['?cc'] if x[0] != '>': insnread += ['?cc'] continue if x[0] != '<': insnwrite += [x[1]] if x[0] != '>': insnread += [x[1]] insnvars += [x[1]] assert x[2] == '=' insnvartype[x[1]] = x[3:].split('#')[0] if len(x[3:].split('#')) > 1: insnvarpos[x[1]] = int(x[3:].split('#')[1]) continue if x.startswith('var/'): insnvars += [x[4]] assert x[5] == '=' insnvartype[x[4]] = x[6:] insnmakevars += [x[4]] continue if x.startswith('asm/'): insnasm += [x[4:]] continue raise Exception(x) insn = tokens(insndesc[0]) insnpos = 0 linepos = 0 while True: if insnpos == len(insn) and linepos == len(line): foundinsn = True if insnpos == len(insn) or linepos == len(line): break x = insn[insnpos] y = line[linepos] if x in insnvars: if y in vartype: if vartype[y] != insnvartype[x]: break # line and insn both have variables, but different types if x in insnvar2line: if insnvar2line[x] != y: break # insn variable already assigned to something different in line else: insnvar2line[x] = y else: if not isvarname(y): break # not an acceptable variable name insnvar2line[x] = y else: if y in vartype: break # XXX: but maybe sometimes want to allow variable in line to match literal in insn if y != x: break # non-matching literals insnpos += 1 linepos += 1 if foundinsn: break if not foundinsn: print(line) assert foundinsn insnvar2line['?cc'] = '?cc' for v in insnmakevars: w = insnvar2line[v] vartype[w] = insnvartype[v] for v in insnvar2line: if v == '?cc': continue if insnvartype[v] == '#': continue w = insnvar2line[v] if w not in vartype: raise Exception(f'undefined variable {w}') for v in insnread: w = insnvar2line[v] if v in insnvarpos: assert insnvarpos[v] == 4 assert machine == 'amd64' rcxvars.add(w) if w not in outputvars: if w not in inputvars: inputvars += [w] for z in outputvars: earlyclobber.add(z) for v in insnwrite: w = insnvar2line[v] if w not in outputvars: outputvars += [w] for asm in insnasm: todo += [(asm,insnvar2line)] need8 = set() todo2 = [] for asm,insnvar2line in todo: todo2 += [('asm',)] while len(asm) > 0: if asm[0] in ('<','+','>'): if asm[2:].startswith('%8'): todo2 += [('var8',insnvar2line[asm[1]])] need8.add(insnvar2line[asm[1]]) asm = asm[4:] else: todo2 += [('var',insnvar2line[asm[1]])] asm = asm[2:] elif asm[0] == '#': todo2 += [('str',insnvar2line[asm[1]])] asm = asm[2:] else: todo2 += [('str',asm[0])] asm = asm[1:] varnextpos = 0 var2name = {} outputs = [] for w in outputvars: if w == '?cc': continue if machine == 'arm64' and vartype[w] != 'int64': # XXX: abstract this var2name[w] = f'%w{varnextpos}' else: var2name[w] = f'%{varnextpos}' varnextpos += 1 regtype = 'r' if w in need8: regtype = 'q' if w in rcxvars: regtype = 'c' if w in earlyclobber: regtype = '&'+regtype if w in inputvars: outputs += [f'"+{regtype}"({w})'] else: outputs += [f'"={regtype}"({w})'] inputs = [] for w in inputvars: if w in outputvars: continue assert w != '?cc' if machine == 'arm64' and vartype[w] != 'int64': # XXX: abstract this var2name[w] = f'%w{varnextpos}' else: var2name[w] = f'%{varnextpos}' varnextpos += 1 regtype = 'r' if w in need8: regtype = 'q' if w in rcxvars: regtype = 'c' inputs += [f'"{regtype}"({w})'] clobbers = [] for w in outputvars: if w != '?cc': continue clobbers += ['"cc"'] result = '' for T in todo2: if T[0] == 'asm': if result != '': result += '\\n ' elif T[0] == 'var8': result += var2name[T[1]].replace('%','%b') elif T[0] == 'var': result += var2name[T[1]] else: assert T[0] == 'str' result += T[1] outputs = ', '.join(outputs) if len(outputs) > 0: outputs += ' ' inputs = ', '.join(inputs) if len(inputs) > 0: inputs += ' ' clobbers = ', '.join(clobbers) result = f'__asm__ ("{result}" : {outputs}: {inputs}: {clobbers})' return result def substitute(program): result = '' for line in program.splitlines(): m = re.fullmatch(r'(.*)\breadasm\("([^"]*)"\)(.*)',line) if m: result += m.group(1)+process(m.group(2))+m.group(3)+'\n' else: result += line+'\n' return result def test(): print(process('amd64; int64 X; X signed>>= 63')) print(process('arm64; int8 X; int8 Y; X = (int8) X; Y = (int8) Y; X - Y; X = Y if signed< else X')) print(process('arm64; int8 X; int8 Y; int8 Z; Z = (uint8) X; Z - (uint8) Y; Z = -1 if unsigned<= else 0')) print(process('arm64; int64 X; int64 Y; int64 R; int64 S; X - Y; R = X if unsigned< else Y; S = Y if unsigned< else X')) if __name__ == '__main__': test()