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