xref: /qemu/tests/tcg/i386/test-mmx.py (revision 1b3a3383df62e32485161712405c2e3dd8b478b0)
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