1*fa7ce0b0SPaolo Bonzini#! /usr/bin/env python3 2*fa7ce0b0SPaolo Bonzini 3*fa7ce0b0SPaolo Bonzini# Generate test-avx.h from x86.csv 4*fa7ce0b0SPaolo Bonzini 5*fa7ce0b0SPaolo Bonziniimport csv 6*fa7ce0b0SPaolo Bonziniimport sys 7*fa7ce0b0SPaolo Bonzinifrom fnmatch import fnmatch 8*fa7ce0b0SPaolo Bonzini 9*fa7ce0b0SPaolo Bonziniignore = set(["EMMS", "FEMMS", "FISTTP", 10*fa7ce0b0SPaolo Bonzini "LDMXCSR", "VLDMXCSR", "STMXCSR", "VSTMXCSR"]) 11*fa7ce0b0SPaolo Bonzini 12*fa7ce0b0SPaolo Bonziniimask = { 13*fa7ce0b0SPaolo Bonzini 'PALIGNR': 0x3f, 14*fa7ce0b0SPaolo Bonzini 'PEXTRB': 0x0f, 15*fa7ce0b0SPaolo Bonzini 'PEXTRW': 0x07, 16*fa7ce0b0SPaolo Bonzini 'PEXTRD': 0x03, 17*fa7ce0b0SPaolo Bonzini 'PEXTRQ': 0x01, 18*fa7ce0b0SPaolo Bonzini 'PINSRB': 0x0f, 19*fa7ce0b0SPaolo Bonzini 'PINSRW': 0x07, 20*fa7ce0b0SPaolo Bonzini 'PINSRD': 0x03, 21*fa7ce0b0SPaolo Bonzini 'PINSRQ': 0x01, 22*fa7ce0b0SPaolo Bonzini 'PSHUF[DW]': 0xff, 23*fa7ce0b0SPaolo Bonzini 'PSHUF[LH]W': 0xff, 24*fa7ce0b0SPaolo Bonzini 'PS[LR][AL][WDQ]': 0x3f, 25*fa7ce0b0SPaolo Bonzini} 26*fa7ce0b0SPaolo Bonzini 27*fa7ce0b0SPaolo Bonzinidef strip_comments(x): 28*fa7ce0b0SPaolo Bonzini for l in x: 29*fa7ce0b0SPaolo Bonzini if l != '' and l[0] != '#': 30*fa7ce0b0SPaolo Bonzini yield l 31*fa7ce0b0SPaolo Bonzini 32*fa7ce0b0SPaolo Bonzinidef reg_w(w): 33*fa7ce0b0SPaolo Bonzini if w == 8: 34*fa7ce0b0SPaolo Bonzini return 'al' 35*fa7ce0b0SPaolo Bonzini elif w == 16: 36*fa7ce0b0SPaolo Bonzini return 'ax' 37*fa7ce0b0SPaolo Bonzini elif w == 32: 38*fa7ce0b0SPaolo Bonzini return 'eax' 39*fa7ce0b0SPaolo Bonzini elif w == 64: 40*fa7ce0b0SPaolo Bonzini return 'rax' 41*fa7ce0b0SPaolo Bonzini raise Exception("bad reg_w %d" % w) 42*fa7ce0b0SPaolo Bonzini 43*fa7ce0b0SPaolo Bonzinidef mem_w(w): 44*fa7ce0b0SPaolo Bonzini if w == 8: 45*fa7ce0b0SPaolo Bonzini t = "BYTE" 46*fa7ce0b0SPaolo Bonzini elif w == 16: 47*fa7ce0b0SPaolo Bonzini t = "WORD" 48*fa7ce0b0SPaolo Bonzini elif w == 32: 49*fa7ce0b0SPaolo Bonzini t = "DWORD" 50*fa7ce0b0SPaolo Bonzini elif w == 64: 51*fa7ce0b0SPaolo Bonzini t = "QWORD" 52*fa7ce0b0SPaolo Bonzini else: 53*fa7ce0b0SPaolo Bonzini raise Exception() 54*fa7ce0b0SPaolo Bonzini 55*fa7ce0b0SPaolo Bonzini return t + " PTR 32[rdx]" 56*fa7ce0b0SPaolo Bonzini 57*fa7ce0b0SPaolo Bonziniclass MMArg(): 58*fa7ce0b0SPaolo Bonzini isxmm = True 59*fa7ce0b0SPaolo Bonzini 60*fa7ce0b0SPaolo Bonzini def __init__(self, mw): 61*fa7ce0b0SPaolo Bonzini if mw not in [0, 32, 64]: 62*fa7ce0b0SPaolo Bonzini raise Exception("Bad /m width: %s" % w) 63*fa7ce0b0SPaolo Bonzini self.mw = mw 64*fa7ce0b0SPaolo Bonzini self.ismem = mw != 0 65*fa7ce0b0SPaolo Bonzini def regstr(self, n): 66*fa7ce0b0SPaolo Bonzini if n < 0: 67*fa7ce0b0SPaolo Bonzini return mem_w(self.mw) 68*fa7ce0b0SPaolo Bonzini else: 69*fa7ce0b0SPaolo Bonzini return "mm%d" % (n, ) 70*fa7ce0b0SPaolo Bonzini 71*fa7ce0b0SPaolo Bonzinidef match(op, pattern): 72*fa7ce0b0SPaolo Bonzini return fnmatch(op, pattern) 73*fa7ce0b0SPaolo Bonzini 74*fa7ce0b0SPaolo Bonziniclass ArgImm8u(): 75*fa7ce0b0SPaolo Bonzini isxmm = False 76*fa7ce0b0SPaolo Bonzini ismem = False 77*fa7ce0b0SPaolo Bonzini def __init__(self, op): 78*fa7ce0b0SPaolo Bonzini for k, v in imask.items(): 79*fa7ce0b0SPaolo Bonzini if match(op, k): 80*fa7ce0b0SPaolo Bonzini self.mask = imask[k]; 81*fa7ce0b0SPaolo Bonzini return 82*fa7ce0b0SPaolo Bonzini raise Exception("Unknown immediate") 83*fa7ce0b0SPaolo Bonzini def vals(self): 84*fa7ce0b0SPaolo Bonzini mask = self.mask 85*fa7ce0b0SPaolo Bonzini yield 0 86*fa7ce0b0SPaolo Bonzini n = 0 87*fa7ce0b0SPaolo Bonzini while n != mask: 88*fa7ce0b0SPaolo Bonzini n += 1 89*fa7ce0b0SPaolo Bonzini while (n & ~mask) != 0: 90*fa7ce0b0SPaolo Bonzini n += (n & ~mask) 91*fa7ce0b0SPaolo Bonzini yield n 92*fa7ce0b0SPaolo Bonzini 93*fa7ce0b0SPaolo Bonziniclass ArgRM(): 94*fa7ce0b0SPaolo Bonzini isxmm = False 95*fa7ce0b0SPaolo Bonzini def __init__(self, rw, mw): 96*fa7ce0b0SPaolo Bonzini if rw not in [8, 16, 32, 64]: 97*fa7ce0b0SPaolo Bonzini raise Exception("Bad r/w width: %s" % w) 98*fa7ce0b0SPaolo Bonzini if mw not in [0, 8, 16, 32, 64]: 99*fa7ce0b0SPaolo Bonzini raise Exception("Bad r/w width: %s" % w) 100*fa7ce0b0SPaolo Bonzini self.rw = rw 101*fa7ce0b0SPaolo Bonzini self.mw = mw 102*fa7ce0b0SPaolo Bonzini self.ismem = mw != 0 103*fa7ce0b0SPaolo Bonzini def regstr(self, n): 104*fa7ce0b0SPaolo Bonzini if n < 0: 105*fa7ce0b0SPaolo Bonzini return mem_w(self.mw) 106*fa7ce0b0SPaolo Bonzini else: 107*fa7ce0b0SPaolo Bonzini return reg_w(self.rw) 108*fa7ce0b0SPaolo Bonzini 109*fa7ce0b0SPaolo Bonziniclass ArgMem(): 110*fa7ce0b0SPaolo Bonzini isxmm = False 111*fa7ce0b0SPaolo Bonzini ismem = True 112*fa7ce0b0SPaolo Bonzini def __init__(self, w): 113*fa7ce0b0SPaolo Bonzini if w not in [8, 16, 32, 64, 128, 256]: 114*fa7ce0b0SPaolo Bonzini raise Exception("Bad mem width: %s" % w) 115*fa7ce0b0SPaolo Bonzini self.w = w 116*fa7ce0b0SPaolo Bonzini def regstr(self, n): 117*fa7ce0b0SPaolo Bonzini return mem_w(self.w) 118*fa7ce0b0SPaolo Bonzini 119*fa7ce0b0SPaolo Bonziniclass SkipInstruction(Exception): 120*fa7ce0b0SPaolo Bonzini pass 121*fa7ce0b0SPaolo Bonzini 122*fa7ce0b0SPaolo Bonzinidef ArgGenerator(arg, op): 123*fa7ce0b0SPaolo Bonzini if arg[:2] == 'mm': 124*fa7ce0b0SPaolo Bonzini if "/" in arg: 125*fa7ce0b0SPaolo Bonzini r, m = arg.split('/') 126*fa7ce0b0SPaolo Bonzini if (m[0] != 'm'): 127*fa7ce0b0SPaolo Bonzini raise Exception("Expected /m: %s", arg) 128*fa7ce0b0SPaolo Bonzini return MMArg(int(m[1:])); 129*fa7ce0b0SPaolo Bonzini else: 130*fa7ce0b0SPaolo Bonzini return MMArg(0); 131*fa7ce0b0SPaolo Bonzini elif arg[:4] == 'imm8': 132*fa7ce0b0SPaolo Bonzini return ArgImm8u(op); 133*fa7ce0b0SPaolo Bonzini elif arg[0] == 'r': 134*fa7ce0b0SPaolo Bonzini if '/m' in arg: 135*fa7ce0b0SPaolo Bonzini r, m = arg.split('/') 136*fa7ce0b0SPaolo Bonzini if (m[0] != 'm'): 137*fa7ce0b0SPaolo Bonzini raise Exception("Expected /m: %s", arg) 138*fa7ce0b0SPaolo Bonzini mw = int(m[1:]) 139*fa7ce0b0SPaolo Bonzini if r == 'r': 140*fa7ce0b0SPaolo Bonzini rw = mw 141*fa7ce0b0SPaolo Bonzini else: 142*fa7ce0b0SPaolo Bonzini rw = int(r[1:]) 143*fa7ce0b0SPaolo Bonzini return ArgRM(rw, mw) 144*fa7ce0b0SPaolo Bonzini 145*fa7ce0b0SPaolo Bonzini return ArgRM(int(arg[1:]), 0); 146*fa7ce0b0SPaolo Bonzini elif arg[0] == 'm': 147*fa7ce0b0SPaolo Bonzini return ArgMem(int(arg[1:])) 148*fa7ce0b0SPaolo Bonzini else: 149*fa7ce0b0SPaolo Bonzini raise SkipInstruction 150*fa7ce0b0SPaolo Bonzini 151*fa7ce0b0SPaolo Bonziniclass InsnGenerator: 152*fa7ce0b0SPaolo Bonzini def __init__(self, op, args): 153*fa7ce0b0SPaolo Bonzini self.op = op 154*fa7ce0b0SPaolo Bonzini if op[0:2] == "PF": 155*fa7ce0b0SPaolo Bonzini self.optype = 'F32' 156*fa7ce0b0SPaolo Bonzini else: 157*fa7ce0b0SPaolo Bonzini self.optype = 'I' 158*fa7ce0b0SPaolo Bonzini 159*fa7ce0b0SPaolo Bonzini try: 160*fa7ce0b0SPaolo Bonzini self.args = list(ArgGenerator(a, op) for a in args) 161*fa7ce0b0SPaolo Bonzini if len(self.args) > 0 and self.args[-1] is None: 162*fa7ce0b0SPaolo Bonzini self.args = self.args[:-1] 163*fa7ce0b0SPaolo Bonzini except SkipInstruction: 164*fa7ce0b0SPaolo Bonzini raise 165*fa7ce0b0SPaolo Bonzini except Exception as e: 166*fa7ce0b0SPaolo Bonzini raise Exception("Bad arg %s: %s" % (op, e)) 167*fa7ce0b0SPaolo Bonzini 168*fa7ce0b0SPaolo Bonzini def gen(self): 169*fa7ce0b0SPaolo Bonzini regs = (5, 6, 7) 170*fa7ce0b0SPaolo Bonzini dest = 4 171*fa7ce0b0SPaolo Bonzini 172*fa7ce0b0SPaolo Bonzini nreg = len(self.args) 173*fa7ce0b0SPaolo Bonzini if nreg == 0: 174*fa7ce0b0SPaolo Bonzini yield self.op 175*fa7ce0b0SPaolo Bonzini return 176*fa7ce0b0SPaolo Bonzini if isinstance(self.args[-1], ArgImm8u): 177*fa7ce0b0SPaolo Bonzini nreg -= 1 178*fa7ce0b0SPaolo Bonzini immarg = self.args[-1] 179*fa7ce0b0SPaolo Bonzini else: 180*fa7ce0b0SPaolo Bonzini immarg = None 181*fa7ce0b0SPaolo Bonzini memarg = -1 182*fa7ce0b0SPaolo Bonzini for n, arg in enumerate(self.args): 183*fa7ce0b0SPaolo Bonzini if arg.ismem: 184*fa7ce0b0SPaolo Bonzini memarg = n 185*fa7ce0b0SPaolo Bonzini 186*fa7ce0b0SPaolo Bonzini if nreg == 1: 187*fa7ce0b0SPaolo Bonzini regset = [(regs[0],)] 188*fa7ce0b0SPaolo Bonzini if memarg == 0: 189*fa7ce0b0SPaolo Bonzini regset += [(-1,)] 190*fa7ce0b0SPaolo Bonzini elif nreg == 2: 191*fa7ce0b0SPaolo Bonzini regset = [ 192*fa7ce0b0SPaolo Bonzini (regs[0], regs[1]), 193*fa7ce0b0SPaolo Bonzini (regs[0], regs[0]), 194*fa7ce0b0SPaolo Bonzini ] 195*fa7ce0b0SPaolo Bonzini if memarg == 0: 196*fa7ce0b0SPaolo Bonzini regset += [(-1, regs[0])] 197*fa7ce0b0SPaolo Bonzini elif memarg == 1: 198*fa7ce0b0SPaolo Bonzini regset += [(dest, -1)] 199*fa7ce0b0SPaolo Bonzini else: 200*fa7ce0b0SPaolo Bonzini raise Exception("Too many regs: %s(%d)" % (self.op, nreg)) 201*fa7ce0b0SPaolo Bonzini 202*fa7ce0b0SPaolo Bonzini for regv in regset: 203*fa7ce0b0SPaolo Bonzini argstr = [] 204*fa7ce0b0SPaolo Bonzini for i in range(nreg): 205*fa7ce0b0SPaolo Bonzini arg = self.args[i] 206*fa7ce0b0SPaolo Bonzini argstr.append(arg.regstr(regv[i])) 207*fa7ce0b0SPaolo Bonzini if immarg is None: 208*fa7ce0b0SPaolo Bonzini yield self.op + ' ' + ','.join(argstr) 209*fa7ce0b0SPaolo Bonzini else: 210*fa7ce0b0SPaolo Bonzini for immval in immarg.vals(): 211*fa7ce0b0SPaolo Bonzini yield self.op + ' ' + ','.join(argstr) + ',' + str(immval) 212*fa7ce0b0SPaolo Bonzini 213*fa7ce0b0SPaolo Bonzinidef split0(s): 214*fa7ce0b0SPaolo Bonzini if s == '': 215*fa7ce0b0SPaolo Bonzini return [] 216*fa7ce0b0SPaolo Bonzini return s.split(',') 217*fa7ce0b0SPaolo Bonzini 218*fa7ce0b0SPaolo Bonzinidef main(): 219*fa7ce0b0SPaolo Bonzini n = 0 220*fa7ce0b0SPaolo Bonzini if len(sys.argv) <= 3: 221*fa7ce0b0SPaolo Bonzini print("Usage: test-mmx.py x86.csv test-mmx.h CPUID...") 222*fa7ce0b0SPaolo Bonzini exit(1) 223*fa7ce0b0SPaolo Bonzini csvfile = open(sys.argv[1], 'r', newline='') 224*fa7ce0b0SPaolo Bonzini archs = sys.argv[3:] 225*fa7ce0b0SPaolo Bonzini with open(sys.argv[2], "w") as outf: 226*fa7ce0b0SPaolo Bonzini outf.write("// Generated by test-mmx.py. Do not edit.\n") 227*fa7ce0b0SPaolo Bonzini for row in csv.reader(strip_comments(csvfile)): 228*fa7ce0b0SPaolo Bonzini insn = row[0].replace(',', '').split() 229*fa7ce0b0SPaolo Bonzini if insn[0] in ignore: 230*fa7ce0b0SPaolo Bonzini continue 231*fa7ce0b0SPaolo Bonzini cpuid = row[6] 232*fa7ce0b0SPaolo Bonzini if cpuid in archs: 233*fa7ce0b0SPaolo Bonzini try: 234*fa7ce0b0SPaolo Bonzini g = InsnGenerator(insn[0], insn[1:]) 235*fa7ce0b0SPaolo Bonzini for insn in g.gen(): 236*fa7ce0b0SPaolo Bonzini outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype)) 237*fa7ce0b0SPaolo Bonzini n += 1 238*fa7ce0b0SPaolo Bonzini except SkipInstruction: 239*fa7ce0b0SPaolo Bonzini pass 240*fa7ce0b0SPaolo Bonzini outf.write("#undef TEST\n") 241*fa7ce0b0SPaolo Bonzini csvfile.close() 242*fa7ce0b0SPaolo Bonzini 243*fa7ce0b0SPaolo Bonziniif __name__ == "__main__": 244*fa7ce0b0SPaolo Bonzini main() 245