xref: /openbmc/qemu/tests/tcg/i386/test-avx.py (revision 3c95fd4ed8952abea0090b3e7751903c5e0cfef6)
191117bc5SPaul Brook#! /usr/bin/env python3
291117bc5SPaul Brook
391117bc5SPaul Brook# Generate test-avx.h from x86.csv
491117bc5SPaul Brook
591117bc5SPaul Brookimport csv
691117bc5SPaul Brookimport sys
791117bc5SPaul Brookfrom fnmatch import fnmatch
891117bc5SPaul Brook
991117bc5SPaul Brookarchs = [
1091117bc5SPaul Brook    "SSE", "SSE2", "SSE3", "SSSE3", "SSE4_1", "SSE4_2",
110339ddfaSPaolo Bonzini    "AES", "AVX", "AVX2", "AES+AVX", "VAES+AVX",
12*48adb240SPaolo Bonzini    "F16C", "FMA", "SHA",
1391117bc5SPaul Brook]
1491117bc5SPaul Brook
1591117bc5SPaul Brookignore = set(["FISTTP",
1691117bc5SPaul Brook    "LDMXCSR", "VLDMXCSR", "STMXCSR", "VSTMXCSR"])
1791117bc5SPaul Brook
1891117bc5SPaul Brookimask = {
1991117bc5SPaul Brook    'vBLENDPD': 0xff,
2091117bc5SPaul Brook    'vBLENDPS': 0x0f,
2191117bc5SPaul Brook    'CMP[PS][SD]': 0x07,
2291117bc5SPaul Brook    'VCMP[PS][SD]': 0x1f,
23cf5ec664SPaolo Bonzini    'vCVTPS2PH': 0x7,
2491117bc5SPaul Brook    'vDPPD': 0x33,
2591117bc5SPaul Brook    'vDPPS': 0xff,
2691117bc5SPaul Brook    'vEXTRACTPS': 0x03,
2791117bc5SPaul Brook    'vINSERTPS': 0xff,
2891117bc5SPaul Brook    'MPSADBW': 0x7,
2991117bc5SPaul Brook    'VMPSADBW': 0x3f,
3091117bc5SPaul Brook    'vPALIGNR': 0x3f,
3191117bc5SPaul Brook    'vPBLENDW': 0xff,
3291117bc5SPaul Brook    'vPCMP[EI]STR*': 0x0f,
3391117bc5SPaul Brook    'vPEXTRB': 0x0f,
3491117bc5SPaul Brook    'vPEXTRW': 0x07,
3591117bc5SPaul Brook    'vPEXTRD': 0x03,
3691117bc5SPaul Brook    'vPEXTRQ': 0x01,
3791117bc5SPaul Brook    'vPINSRB': 0x0f,
3891117bc5SPaul Brook    'vPINSRW': 0x07,
3991117bc5SPaul Brook    'vPINSRD': 0x03,
4091117bc5SPaul Brook    'vPINSRQ': 0x01,
4191117bc5SPaul Brook    'vPSHUF[DW]': 0xff,
4291117bc5SPaul Brook    'vPSHUF[LH]W': 0xff,
4391117bc5SPaul Brook    'vPS[LR][AL][WDQ]': 0x3f,
4491117bc5SPaul Brook    'vPS[RL]LDQ': 0x1f,
4591117bc5SPaul Brook    'vROUND[PS][SD]': 0x7,
46*48adb240SPaolo Bonzini    'SHA1RNDS4': 0x03,
4791117bc5SPaul Brook    'vSHUFPD': 0x0f,
4891117bc5SPaul Brook    'vSHUFPS': 0xff,
490339ddfaSPaolo Bonzini    'vAESKEYGENASSIST': 0xff,
5091117bc5SPaul Brook    'VEXTRACT[FI]128': 0x01,
5191117bc5SPaul Brook    'VINSERT[FI]128': 0x01,
5291117bc5SPaul Brook    'VPBLENDD': 0xff,
539e658296SPaolo Bonzini    'VPERM2[FI]128': 0xbb,
5491117bc5SPaul Brook    'VPERMPD': 0xff,
5591117bc5SPaul Brook    'VPERMQ': 0xff,
5691117bc5SPaul Brook    'VPERMILPS': 0xff,
5791117bc5SPaul Brook    'VPERMILPD': 0x0f,
5891117bc5SPaul Brook    }
5991117bc5SPaul Brook
6091117bc5SPaul Brookdef strip_comments(x):
6191117bc5SPaul Brook    for l in x:
6291117bc5SPaul Brook        if l != '' and l[0] != '#':
6391117bc5SPaul Brook            yield l
6491117bc5SPaul Brook
6591117bc5SPaul Brookdef reg_w(w):
6691117bc5SPaul Brook    if w == 8:
6791117bc5SPaul Brook        return 'al'
6891117bc5SPaul Brook    elif w == 16:
6991117bc5SPaul Brook        return 'ax'
7091117bc5SPaul Brook    elif w == 32:
7191117bc5SPaul Brook        return 'eax'
7291117bc5SPaul Brook    elif w == 64:
7391117bc5SPaul Brook        return 'rax'
7491117bc5SPaul Brook    raise Exception("bad reg_w %d" % w)
7591117bc5SPaul Brook
7691117bc5SPaul Brookdef mem_w(w):
7791117bc5SPaul Brook    if w == 8:
7891117bc5SPaul Brook        t = "BYTE"
7991117bc5SPaul Brook    elif w == 16:
8091117bc5SPaul Brook        t = "WORD"
8191117bc5SPaul Brook    elif w == 32:
8291117bc5SPaul Brook        t = "DWORD"
8391117bc5SPaul Brook    elif w == 64:
8491117bc5SPaul Brook        t = "QWORD"
8591117bc5SPaul Brook    elif w == 128:
8691117bc5SPaul Brook        t = "XMMWORD"
8791117bc5SPaul Brook    elif w == 256:
8891117bc5SPaul Brook        t = "YMMWORD"
8991117bc5SPaul Brook    else:
9091117bc5SPaul Brook        raise Exception()
9191117bc5SPaul Brook
920339ddfaSPaolo Bonzini    return t + " PTR 32[rdx]"
9391117bc5SPaul Brook
9491117bc5SPaul Brookclass XMMArg():
9591117bc5SPaul Brook    isxmm = True
9691117bc5SPaul Brook    def __init__(self, reg, mw):
9791117bc5SPaul Brook        if mw not in [0, 8, 16, 32, 64, 128, 256]:
9891117bc5SPaul Brook            raise Exception("Bad /m width: %s" % w)
9991117bc5SPaul Brook        self.reg = reg
10091117bc5SPaul Brook        self.mw = mw
10191117bc5SPaul Brook        self.ismem = mw != 0
10291117bc5SPaul Brook    def regstr(self, n):
10391117bc5SPaul Brook        if n < 0:
10491117bc5SPaul Brook            return mem_w(self.mw)
10591117bc5SPaul Brook        else:
10691117bc5SPaul Brook            return "%smm%d" % (self.reg, n)
10791117bc5SPaul Brook
10891117bc5SPaul Brookclass MMArg():
10991117bc5SPaul Brook    isxmm = True
110e02907ccSPaolo Bonzini    def __init__(self, mw):
111e02907ccSPaolo Bonzini        if mw not in [0, 32, 64]:
112e02907ccSPaolo Bonzini            raise Exception("Bad mem width: %s" % mw)
113e02907ccSPaolo Bonzini        self.mw = mw
114e02907ccSPaolo Bonzini        self.ismem = mw != 0
11591117bc5SPaul Brook    def regstr(self, n):
11691117bc5SPaul Brook        return "mm%d" % (n & 7)
11791117bc5SPaul Brook
11891117bc5SPaul Brookdef match(op, pattern):
11991117bc5SPaul Brook    if pattern[0] == 'v':
12091117bc5SPaul Brook        return fnmatch(op, pattern[1:]) or fnmatch(op, 'V'+pattern[1:])
12191117bc5SPaul Brook    return fnmatch(op, pattern)
12291117bc5SPaul Brook
12391117bc5SPaul Brookclass ArgVSIB():
12491117bc5SPaul Brook    isxmm = True
12591117bc5SPaul Brook    ismem = False
12691117bc5SPaul Brook    def __init__(self, reg, w):
12791117bc5SPaul Brook        if w not in [32, 64]:
12891117bc5SPaul Brook            raise Exception("Bad vsib width: %s" % w)
12991117bc5SPaul Brook        self.w = w
13091117bc5SPaul Brook        self.reg = reg
13191117bc5SPaul Brook    def regstr(self, n):
13291117bc5SPaul Brook        reg = "%smm%d" % (self.reg, n >> 2)
13391117bc5SPaul Brook        return "[rsi + %s * %d]" % (reg, 1 << (n & 3))
13491117bc5SPaul Brook
13591117bc5SPaul Brookclass ArgImm8u():
13691117bc5SPaul Brook    isxmm = False
13791117bc5SPaul Brook    ismem = False
13891117bc5SPaul Brook    def __init__(self, op):
13991117bc5SPaul Brook        for k, v in imask.items():
14091117bc5SPaul Brook            if match(op, k):
14191117bc5SPaul Brook                self.mask = imask[k];
14291117bc5SPaul Brook                return
14391117bc5SPaul Brook        raise Exception("Unknown immediate")
14491117bc5SPaul Brook    def vals(self):
14591117bc5SPaul Brook        mask = self.mask
14691117bc5SPaul Brook        yield 0
14791117bc5SPaul Brook        n = 0
14891117bc5SPaul Brook        while n != mask:
14991117bc5SPaul Brook            n += 1
15091117bc5SPaul Brook            while (n & ~mask) != 0:
15191117bc5SPaul Brook                n += (n & ~mask)
15291117bc5SPaul Brook            yield n
15391117bc5SPaul Brook
15491117bc5SPaul Brookclass ArgRM():
15591117bc5SPaul Brook    isxmm = False
15691117bc5SPaul Brook    def __init__(self, rw, mw):
15791117bc5SPaul Brook        if rw not in [8, 16, 32, 64]:
15891117bc5SPaul Brook            raise Exception("Bad r/w width: %s" % w)
15991117bc5SPaul Brook        if mw not in [0, 8, 16, 32, 64]:
16091117bc5SPaul Brook            raise Exception("Bad r/w width: %s" % w)
16191117bc5SPaul Brook        self.rw = rw
16291117bc5SPaul Brook        self.mw = mw
16391117bc5SPaul Brook        self.ismem = mw != 0
16491117bc5SPaul Brook    def regstr(self, n):
16591117bc5SPaul Brook        if n < 0:
16691117bc5SPaul Brook            return mem_w(self.mw)
16791117bc5SPaul Brook        else:
16891117bc5SPaul Brook            return reg_w(self.rw)
16991117bc5SPaul Brook
17091117bc5SPaul Brookclass ArgMem():
17191117bc5SPaul Brook    isxmm = False
17291117bc5SPaul Brook    ismem = True
17391117bc5SPaul Brook    def __init__(self, w):
17491117bc5SPaul Brook        if w not in [8, 16, 32, 64, 128, 256]:
17591117bc5SPaul Brook            raise Exception("Bad mem width: %s" % w)
17691117bc5SPaul Brook        self.w = w
17791117bc5SPaul Brook    def regstr(self, n):
17891117bc5SPaul Brook        return mem_w(self.w)
17991117bc5SPaul Brook
180e02907ccSPaolo Bonziniclass SkipInstruction(Exception):
181e02907ccSPaolo Bonzini    pass
182e02907ccSPaolo Bonzini
18391117bc5SPaul Brookdef ArgGenerator(arg, op):
18491117bc5SPaul Brook    if arg[:3] == 'xmm' or arg[:3] == "ymm":
18591117bc5SPaul Brook        if "/" in arg:
18691117bc5SPaul Brook            r, m = arg.split('/')
18791117bc5SPaul Brook            if (m[0] != 'm'):
18891117bc5SPaul Brook                raise Exception("Expected /m: %s", arg)
18991117bc5SPaul Brook            return XMMArg(arg[0], int(m[1:]));
19091117bc5SPaul Brook        else:
19191117bc5SPaul Brook            return XMMArg(arg[0], 0);
19291117bc5SPaul Brook    elif arg[:2] == 'mm':
193e02907ccSPaolo Bonzini        if "/" in arg:
194e02907ccSPaolo Bonzini            r, m = arg.split('/')
195e02907ccSPaolo Bonzini            if (m[0] != 'm'):
196e02907ccSPaolo Bonzini                raise Exception("Expected /m: %s", arg)
197e02907ccSPaolo Bonzini            return MMArg(int(m[1:]));
198e02907ccSPaolo Bonzini        else:
199e02907ccSPaolo Bonzini            return MMArg(0);
20091117bc5SPaul Brook    elif arg[:4] == 'imm8':
20191117bc5SPaul Brook        return ArgImm8u(op);
20291117bc5SPaul Brook    elif arg == '<XMM0>':
20391117bc5SPaul Brook        return None
20491117bc5SPaul Brook    elif arg[0] == 'r':
20591117bc5SPaul Brook        if '/m' in arg:
20691117bc5SPaul Brook            r, m = arg.split('/')
20791117bc5SPaul Brook            if (m[0] != 'm'):
20891117bc5SPaul Brook                raise Exception("Expected /m: %s", arg)
20991117bc5SPaul Brook            mw = int(m[1:])
21091117bc5SPaul Brook            if r == 'r':
21191117bc5SPaul Brook                rw = mw
21291117bc5SPaul Brook            else:
21391117bc5SPaul Brook                rw = int(r[1:])
21491117bc5SPaul Brook            return ArgRM(rw, mw)
21591117bc5SPaul Brook
21691117bc5SPaul Brook        return ArgRM(int(arg[1:]), 0);
21791117bc5SPaul Brook    elif arg[0] == 'm':
21891117bc5SPaul Brook        return ArgMem(int(arg[1:]))
21991117bc5SPaul Brook    elif arg[:2] == 'vm':
22091117bc5SPaul Brook        return ArgVSIB(arg[-1], int(arg[2:-1]))
22191117bc5SPaul Brook    else:
22291117bc5SPaul Brook        raise Exception("Unrecognised arg: %s", arg)
22391117bc5SPaul Brook
22491117bc5SPaul Brookclass InsnGenerator:
22591117bc5SPaul Brook    def __init__(self, op, args):
22691117bc5SPaul Brook        self.op = op
227cf5ec664SPaolo Bonzini        if op[-2:] in ["PH", "PS", "PD", "SS", "SD"]:
228cf5ec664SPaolo Bonzini            if op[-1] == 'H':
229cf5ec664SPaolo Bonzini                self.optype = 'F16'
230cf5ec664SPaolo Bonzini            elif op[-1] == 'S':
23191117bc5SPaul Brook                self.optype = 'F32'
23291117bc5SPaul Brook            else:
23391117bc5SPaul Brook                self.optype = 'F64'
23491117bc5SPaul Brook        else:
23591117bc5SPaul Brook            self.optype = 'I'
23691117bc5SPaul Brook
23791117bc5SPaul Brook        try:
23891117bc5SPaul Brook            self.args = list(ArgGenerator(a, op) for a in args)
239e02907ccSPaolo Bonzini            if not any((x.isxmm for x in self.args)):
240e02907ccSPaolo Bonzini                raise SkipInstruction
24191117bc5SPaul Brook            if len(self.args) > 0 and self.args[-1] is None:
24291117bc5SPaul Brook                self.args = self.args[:-1]
243e02907ccSPaolo Bonzini        except SkipInstruction:
244e02907ccSPaolo Bonzini            raise
24591117bc5SPaul Brook        except Exception as e:
24691117bc5SPaul Brook            raise Exception("Bad arg %s: %s" % (op, e))
24791117bc5SPaul Brook
24891117bc5SPaul Brook    def gen(self):
24991117bc5SPaul Brook        regs = (10, 11, 12)
25091117bc5SPaul Brook        dest = 9
25191117bc5SPaul Brook
25291117bc5SPaul Brook        nreg = len(self.args)
25391117bc5SPaul Brook        if nreg == 0:
25491117bc5SPaul Brook            yield self.op
25591117bc5SPaul Brook            return
25691117bc5SPaul Brook        if isinstance(self.args[-1], ArgImm8u):
25791117bc5SPaul Brook            nreg -= 1
25891117bc5SPaul Brook            immarg = self.args[-1]
25991117bc5SPaul Brook        else:
26091117bc5SPaul Brook            immarg = None
26191117bc5SPaul Brook        memarg = -1
26291117bc5SPaul Brook        for n, arg in enumerate(self.args):
26391117bc5SPaul Brook            if arg.ismem:
26491117bc5SPaul Brook                memarg = n
26591117bc5SPaul Brook
26691117bc5SPaul Brook        if (self.op.startswith("VGATHER") or self.op.startswith("VPGATHER")):
26791117bc5SPaul Brook            if "GATHERD" in self.op:
26891117bc5SPaul Brook                ireg = 13 << 2
26991117bc5SPaul Brook            else:
27091117bc5SPaul Brook                ireg = 14 << 2
27191117bc5SPaul Brook            regset = [
27291117bc5SPaul Brook                (dest, ireg | 0, regs[0]),
27391117bc5SPaul Brook                (dest, ireg | 1, regs[0]),
27491117bc5SPaul Brook                (dest, ireg | 2, regs[0]),
27591117bc5SPaul Brook                (dest, ireg | 3, regs[0]),
27691117bc5SPaul Brook                ]
27791117bc5SPaul Brook            if memarg >= 0:
27891117bc5SPaul Brook                raise Exception("vsib with memory: %s" % self.op)
27991117bc5SPaul Brook        elif nreg == 1:
28091117bc5SPaul Brook            regset = [(regs[0],)]
28191117bc5SPaul Brook            if memarg == 0:
28291117bc5SPaul Brook                regset += [(-1,)]
28391117bc5SPaul Brook        elif nreg == 2:
28491117bc5SPaul Brook            regset = [
28591117bc5SPaul Brook                (regs[0], regs[1]),
28691117bc5SPaul Brook                (regs[0], regs[0]),
28791117bc5SPaul Brook                ]
28891117bc5SPaul Brook            if memarg == 0:
28991117bc5SPaul Brook                regset += [(-1, regs[0])]
29091117bc5SPaul Brook            elif memarg == 1:
29191117bc5SPaul Brook                regset += [(dest, -1)]
29291117bc5SPaul Brook        elif nreg == 3:
29391117bc5SPaul Brook            regset = [
29491117bc5SPaul Brook                (dest, regs[0], regs[1]),
29591117bc5SPaul Brook                (dest, regs[0], regs[0]),
29691117bc5SPaul Brook                (regs[0], regs[0], regs[1]),
29791117bc5SPaul Brook                (regs[0], regs[1], regs[0]),
29891117bc5SPaul Brook                (regs[0], regs[0], regs[0]),
29991117bc5SPaul Brook                ]
30091117bc5SPaul Brook            if memarg == 2:
30191117bc5SPaul Brook                regset += [
30291117bc5SPaul Brook                    (dest, regs[0], -1),
30391117bc5SPaul Brook                    (regs[0], regs[0], -1),
30491117bc5SPaul Brook                    ]
30591117bc5SPaul Brook            elif memarg > 0:
30691117bc5SPaul Brook                raise Exception("Memarg %d" % memarg)
30791117bc5SPaul Brook        elif nreg == 4:
30891117bc5SPaul Brook            regset = [
30991117bc5SPaul Brook                (dest, regs[0], regs[1], regs[2]),
31091117bc5SPaul Brook                (dest, regs[0], regs[0], regs[1]),
31191117bc5SPaul Brook                (dest, regs[0], regs[1], regs[0]),
31291117bc5SPaul Brook                (dest, regs[1], regs[0], regs[0]),
31391117bc5SPaul Brook                (dest, regs[0], regs[0], regs[0]),
31491117bc5SPaul Brook                (regs[0], regs[0], regs[1], regs[2]),
31591117bc5SPaul Brook                (regs[0], regs[1], regs[0], regs[2]),
31691117bc5SPaul Brook                (regs[0], regs[1], regs[2], regs[0]),
31791117bc5SPaul Brook                (regs[0], regs[0], regs[0], regs[1]),
31891117bc5SPaul Brook                (regs[0], regs[0], regs[1], regs[0]),
31991117bc5SPaul Brook                (regs[0], regs[1], regs[0], regs[0]),
32091117bc5SPaul Brook                (regs[0], regs[0], regs[0], regs[0]),
32191117bc5SPaul Brook                ]
32291117bc5SPaul Brook            if memarg == 2:
32391117bc5SPaul Brook                regset += [
32491117bc5SPaul Brook                    (dest, regs[0], -1, regs[1]),
32591117bc5SPaul Brook                    (dest, regs[0], -1, regs[0]),
32691117bc5SPaul Brook                    (regs[0], regs[0], -1, regs[1]),
32791117bc5SPaul Brook                    (regs[0], regs[1], -1, regs[0]),
32891117bc5SPaul Brook                    (regs[0], regs[0], -1, regs[0]),
32991117bc5SPaul Brook                    ]
33091117bc5SPaul Brook            elif memarg > 0:
33191117bc5SPaul Brook                raise Exception("Memarg4 %d" % memarg)
33291117bc5SPaul Brook        else:
33391117bc5SPaul Brook            raise Exception("Too many regs: %s(%d)" % (self.op, nreg))
33491117bc5SPaul Brook
33591117bc5SPaul Brook        for regv in regset:
33691117bc5SPaul Brook            argstr = []
33791117bc5SPaul Brook            for i in range(nreg):
33891117bc5SPaul Brook                arg = self.args[i]
33991117bc5SPaul Brook                argstr.append(arg.regstr(regv[i]))
34091117bc5SPaul Brook            if immarg is None:
34191117bc5SPaul Brook                yield self.op + ' ' + ','.join(argstr)
34291117bc5SPaul Brook            else:
34391117bc5SPaul Brook                for immval in immarg.vals():
34491117bc5SPaul Brook                    yield self.op + ' ' + ','.join(argstr) + ',' + str(immval)
34591117bc5SPaul Brook
34691117bc5SPaul Brookdef split0(s):
34791117bc5SPaul Brook    if s == '':
34891117bc5SPaul Brook        return []
34991117bc5SPaul Brook    return s.split(',')
35091117bc5SPaul Brook
35191117bc5SPaul Brookdef main():
35291117bc5SPaul Brook    n = 0
35391117bc5SPaul Brook    if len(sys.argv) != 3:
35491117bc5SPaul Brook        print("Usage: test-avx.py x86.csv test-avx.h")
35591117bc5SPaul Brook        exit(1)
35691117bc5SPaul Brook    csvfile = open(sys.argv[1], 'r', newline='')
35791117bc5SPaul Brook    with open(sys.argv[2], "w") as outf:
35891117bc5SPaul Brook        outf.write("// Generated by test-avx.py. Do not edit.\n")
35991117bc5SPaul Brook        for row in csv.reader(strip_comments(csvfile)):
36091117bc5SPaul Brook            insn = row[0].replace(',', '').split()
36191117bc5SPaul Brook            if insn[0] in ignore:
36291117bc5SPaul Brook                continue
36391117bc5SPaul Brook            cpuid = row[6]
36491117bc5SPaul Brook            if cpuid in archs:
365e02907ccSPaolo Bonzini                try:
36691117bc5SPaul Brook                    g = InsnGenerator(insn[0], insn[1:])
36791117bc5SPaul Brook                    for insn in g.gen():
36891117bc5SPaul Brook                        outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype))
36991117bc5SPaul Brook                        n += 1
370e02907ccSPaolo Bonzini                except SkipInstruction:
371e02907ccSPaolo Bonzini                    pass
37291117bc5SPaul Brook        outf.write("#undef TEST\n")
37391117bc5SPaul Brook        csvfile.close()
37491117bc5SPaul Brook
37591117bc5SPaul Brookif __name__ == "__main__":
37691117bc5SPaul Brook    main()
377