1 #define XBYAK_DONT_READ_LIST
2 #include <stdio.h>
3 #include <string.h>
4 #include "xbyak/xbyak.h"
5 #define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
6 
7 using namespace Xbyak;
8 #ifdef _MSC_VER
9 	#pragma warning(disable : 4996) // scanf
10 	#define snprintf _snprintf_s
11 #endif
12 
13 #include "avx_type.hpp"
14 /*
15 	reg = cx/ecx/rcx
16 	insert 0x67 if prefix is true
17 */
put_jREGz(const char * reg,bool prefix)18 void put_jREGz(const char *reg, bool prefix)
19 {
20 	printf("void j%sz(std::string label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
21 	printf("void j%sz(const Label& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
22 }
23 
24 struct GenericTbl {
25 	const char *name;
26 	uint8 code1;
27 	uint8 code2;
28 	uint8 code3;
29 };
30 
putGeneric(const GenericTbl * p,size_t n)31 void putGeneric(const GenericTbl *p, size_t n)
32 {
33 	for (size_t i = 0; i < n; i++) {
34 		printf("void %s() { db(0x%02X); ", p->name, p->code1);
35 		if (p->code2) printf("db(0x%02X); ", p->code2);
36 		if (p->code3) printf("db(0x%02X); ", p->code3);
37 		printf("}\n");
38 		p++;
39 	}
40 }
41 
putX_X_XM(bool omitOnly)42 void putX_X_XM(bool omitOnly)
43 {
44 	// (x, x, x/m[, imm]) or (y, y, y/m[, imm])
45 	{
46 		const struct Tbl {
47 			uint8 code;
48 			const char *name;
49 			int type;
50 			bool hasIMM;
51 			bool enableOmit;
52 			int mode; // 1 : sse, 2 : avx, 3 : sse + avx
53 		} tbl[] = {
54 			{ 0x0D, "blendpd", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
55 			{ 0x0C, "blendps", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
56 			{ 0x41, "dppd", T_0F3A | T_66 | T_W0, true, true, 3 },
57 			{ 0x40, "dpps", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
58 			{ 0x42, "mpsadbw", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
59 			{ 0x0E, "pblendw", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 3 },
60 			{ 0x02, "pblendd", T_0F3A | T_66 | T_W0 | T_YMM, true, true, 2 },
61 			{ 0x0B, "roundsd", T_0F3A | T_66 | T_W0, true, true, 3 },
62 			{ 0x0A, "roundss", T_0F3A | T_66 | T_W0, true, true, 3 },
63 			{ 0x44, "pclmulqdq", T_0F3A | T_66 | T_W0 | T_YMM | T_EVEX, true, true, 3 },
64 			{ 0x0C, "permilps", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
65 			{ 0x0D, "permilpd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
66 
67 			{ 0x47, "psllvd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
68 			{ 0x47, "psllvq", T_0F38 | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
69 			{ 0x46, "psravd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
70 			{ 0x45, "psrlvd", T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32, false, false, 2 },
71 			{ 0x45, "psrlvq", T_0F38 | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64, false, false, 2 },
72 
73 			{ 0xC2, "cmppd", T_0F | T_66 | T_YMM, true, true, 2 },
74 			{ 0xC2, "cmpps", T_0F | T_YMM, true, true, 2 },
75 			{ 0xC2, "cmpsd", T_0F | T_F2, true, true, 2 },
76 			{ 0xC2, "cmpss", T_0F | T_F3, true, true, 2 },
77 			{ 0x5A, "cvtsd2ss", T_0F | T_F2 | T_EVEX | T_EW1 | T_N8 | T_ER_X, false, true, 2 },
78 			{ 0x5A, "cvtss2sd", T_0F | T_F3 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, false, true, 2 },
79 			{ 0x21, "insertps", T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, true, true, 2 },
80 			{ 0x63, "packsswb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
81 			{ 0x6B, "packssdw", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
82 			{ 0x67, "packuswb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
83 			{ 0x2B, "packusdw", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
84 
85 			{ 0xFC, "paddb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
86 			{ 0xFD, "paddw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
87 			{ 0xFE, "paddd", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
88 			{ 0xD4, "paddq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
89 
90 			{ 0xEC, "paddsb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
91 			{ 0xED, "paddsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
92 
93 			{ 0xDC, "paddusb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
94 			{ 0xDD, "paddusw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
95 
96 			{ 0x0F, "palignr", T_0F3A | T_66 | T_YMM | T_EVEX, true, true, 2 },
97 
98 			{ 0xDB, "pand", T_0F | T_66 | T_YMM, false, true, 2 },
99 			{ 0xDF, "pandn", T_0F | T_66 | T_YMM, false, true, 2 },
100 
101 			{ 0xE0, "pavgb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
102 			{ 0xE3, "pavgw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
103 
104 			{ 0x74, "pcmpeqb", T_0F | T_66 | T_YMM, false, true, 2 },
105 			{ 0x75, "pcmpeqw", T_0F | T_66 | T_YMM, false, true, 2 },
106 			{ 0x76, "pcmpeqd", T_0F | T_66 | T_YMM, false, true, 2 },
107 			{ 0x29, "pcmpeqq", T_0F38 | T_66 | T_YMM, false, true, 3 },
108 
109 			{ 0x64, "pcmpgtb", T_0F | T_66 | T_YMM, false, true, 2 },
110 			{ 0x65, "pcmpgtw", T_0F | T_66 | T_YMM, false, true, 2 },
111 			{ 0x66, "pcmpgtd", T_0F | T_66 | T_YMM, false, true, 2 },
112 			{ 0x37, "pcmpgtq", T_0F38 | T_66 | T_YMM, false, true, 3 },
113 
114 			{ 0x01, "phaddw", T_0F38 | T_66 | T_YMM, false, true, 2 },
115 			{ 0x02, "phaddd", T_0F38 | T_66 | T_YMM, false, true, 2 },
116 			{ 0x03, "phaddsw", T_0F38 | T_66 | T_YMM, false, true, 2 },
117 
118 			{ 0x05, "phsubw", T_0F38 | T_66 | T_YMM, false, true, 2 },
119 			{ 0x06, "phsubd", T_0F38 | T_66 | T_YMM, false, true, 2 },
120 			{ 0x07, "phsubsw", T_0F38 | T_66 | T_YMM, false, true, 2 },
121 			{ 0xF5, "pmaddwd", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
122 			{ 0x04, "pmaddubsw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 2 },
123 
124 			{ 0x3C, "pmaxsb", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
125 			{ 0xEE, "pmaxsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
126 			{ 0x3D, "pmaxsd", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
127 
128 			{ 0xDE, "pmaxub", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
129 			{ 0x3E, "pmaxuw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
130 			{ 0x3F, "pmaxud", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
131 
132 			{ 0x38, "pminsb", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
133 			{ 0xEA, "pminsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
134 			{ 0x39, "pminsd", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
135 
136 			{ 0xDA, "pminub", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
137 			{ 0x3A, "pminuw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 3 },
138 			{ 0x3B, "pminud", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
139 
140 			{ 0xE4, "pmulhuw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
141 			{ 0x0B, "pmulhrsw", T_0F38 | T_66 | T_YMM | T_EVEX, false, true, 2 },
142 			{ 0xE5, "pmulhw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
143 			{ 0xD5, "pmullw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
144 			{ 0x40, "pmulld", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 3 },
145 
146 			{ 0xF4, "pmuludq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
147 			{ 0x28, "pmuldq", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 3 },
148 
149 			{ 0xEB, "por", T_0F | T_66 | T_YMM, false, true, 2 },
150 			{ 0xF6, "psadbw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
151 
152 			{ 0x00, "pshufb", T_0F38 | T_66 | T_YMM | T_EVEX, false, false, 2 },
153 
154 			{ 0x08, "psignb", T_0F38 | T_66 | T_YMM, false, true, 2 },
155 			{ 0x09, "psignw", T_0F38 | T_66 | T_YMM, false, true, 2 },
156 			{ 0x0A, "psignd", T_0F38 | T_66 | T_YMM, false, true, 2 },
157 
158 			{ 0xF1, "psllw", T_0F | T_66 | T_YMM | T_EVEX | T_N16, false, true, 2 },
159 			{ 0xF2, "pslld", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_N16, false, true, 2 },
160 			{ 0xF3, "psllq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_N16, false, true, 2 },
161 
162 			{ 0xE1, "psraw", T_0F | T_66 | T_YMM | T_EVEX | T_N16, false, true, 2 },
163 			{ 0xE2, "psrad", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_N16, false, true, 2 },
164 			{ 0xD1, "psrlw", T_0F | T_66 | T_YMM | T_EVEX | T_N16, false, true, 2 },
165 			{ 0xD2, "psrld", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_N16, false, true, 2 },
166 			{ 0xD3, "psrlq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_N16, false, true, 2 },
167 
168 			{ 0xF8, "psubb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
169 			{ 0xF9, "psubw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
170 			{ 0xFA, "psubd", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
171 			{ 0xFB, "psubq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
172 
173 			{ 0xE8, "psubsb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
174 			{ 0xE9, "psubsw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
175 
176 			{ 0xD8, "psubusb", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
177 			{ 0xD9, "psubusw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
178 
179 			{ 0x68, "punpckhbw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
180 			{ 0x69, "punpckhwd", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
181 			{ 0x6A, "punpckhdq", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
182 			{ 0x6D, "punpckhqdq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
183 
184 			{ 0x60, "punpcklbw", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
185 			{ 0x61, "punpcklwd", T_0F | T_66 | T_YMM | T_EVEX, false, true, 2 },
186 			{ 0x62, "punpckldq", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
187 			{ 0x6C, "punpcklqdq", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
188 
189 			{ 0xEF, "pxor", T_0F | T_66 | T_YMM, false, true, 2 },
190 
191 			{ 0x53, "rcpss", T_0F | T_F3, false, true, 2 },
192 			{ 0x52, "rsqrtss", T_0F | T_F3, false, true, 2 },
193 
194 			{ 0xC6, "shufpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, true, true, 2 },
195 			{ 0xC6, "shufps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, true, true, 2 },
196 
197 			{ 0x51, "sqrtsd", T_0F | T_F2 | T_EVEX | T_EW1 | T_ER_X | T_N8, false, true, 2 },
198 			{ 0x51, "sqrtss", T_0F | T_F3 | T_EVEX | T_EW0 | T_ER_X | T_N4, false, true, 2 },
199 
200 			{ 0x15, "unpckhpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
201 			{ 0x15, "unpckhps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
202 
203 			{ 0x14, "unpcklpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, false, true, 2 },
204 			{ 0x14, "unpcklps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32, false, true, 2 },
205 
206 			{ 0xCF, "gf2p8affineinvqb", T_66 | T_0F3A | T_W1 | T_EVEX | T_YMM | T_EW1 | T_SAE_Z | T_B64, true, false, 3 },
207 			{ 0xCE, "gf2p8affineqb", T_66 | T_0F3A | T_W1 | T_EVEX | T_YMM | T_EW1 | T_SAE_Z | T_B64, true, false, 3 },
208 			{ 0xCF, "gf2p8mulb", T_66 | T_0F38 | T_W0 | T_EVEX | T_YMM | T_EW0 | T_SAE_Z, false, false, 3 },
209 		};
210 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
211 			const Tbl *p = &tbl[i];
212 			std::string type = type2String(p->type);
213 			if (omitOnly) {
214 				if (p->enableOmit) {
215 					printf("void v%s(const Xmm& x, const Operand& op%s) { v%s(x, x, op%s); }\n", p->name, p->hasIMM ? ", uint8 imm" : "", p->name, p->hasIMM ? ", imm" : "");
216 				}
217 			} else {
218 				if (p->mode & 1) {
219 					if (p->hasIMM) {
220 						printf("void %s(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, static_cast<uint8>(imm), 0x3A); }\n", p->name, p->code);
221 					} else {
222 						printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x66, isXMM_XMMorMEM, NONE, 0x38); }\n", p->name, p->code);
223 					}
224 				}
225 				if (p->mode & 2) {
226 					printf("void v%s(const Xmm& x1, const Xmm& x2, const Operand& op%s) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X%s); }\n"
227 					, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
228 				}
229 			}
230 		}
231 	}
232 }
233 
put()234 void put()
235 {
236 	const int NO = CodeGenerator::NONE;
237 	{
238 		char buf[16];
239 		unsigned int v = VERSION;
240 		if (v & 0xF) {
241 			snprintf(buf, sizeof(buf), "%d.%02X%x", v >> 12, (v >> 4) & 0xFF, v & 0xF);
242 		} else {
243 			snprintf(buf, sizeof(buf), "%d.%02X", v >> 12, (v >> 4) & 0xFF);
244 		}
245 		printf("const char *getVersionString() const { return \"%s\"; }\n", buf);
246 	}
247 	const int B = 1 << 0;
248 	const int W = 1 << 1;
249 	const int D = 1 << 2;
250 	const int Q = 1 << 3;
251 	{
252 		const struct Tbl {
253 			uint8 code;
254 			const char *name;
255 		} tbl[] = {
256 			// MMX
257 			{ 0x6B, "packssdw" },
258 			{ 0x63, "packsswb" },
259 			{ 0x67, "packuswb" },
260 
261 			{ 0xDB, "pand" },
262 			{ 0xDF, "pandn" },
263 
264 			{ 0xF5, "pmaddwd" },
265 			{ 0xE4, "pmulhuw" },
266 			{ 0xE5, "pmulhw" },
267 			{ 0xD5, "pmullw" },
268 
269 			{ 0xEB, "por" },
270 
271 			{ 0x68, "punpckhbw" },
272 			{ 0x69, "punpckhwd" },
273 			{ 0x6A, "punpckhdq" },
274 
275 			{ 0x60, "punpcklbw" },
276 			{ 0x61, "punpcklwd" },
277 			{ 0x62, "punpckldq" },
278 
279 			{ 0xEF, "pxor" },
280 
281 			// MMX2
282 			{ 0xE0, "pavgb" },
283 			{ 0xE3, "pavgw" },
284 			{ 0xEE, "pmaxsw" },
285 			{ 0xDE, "pmaxub" },
286 			{ 0xEA, "pminsw" },
287 			{ 0xDA, "pminub" },
288 			{ 0xF6, "psadbw" },
289 			//
290 			{ 0xD4, "paddq" },
291 			{ 0xF4, "pmuludq" },
292 			{ 0xFB, "psubq" },
293 		};
294 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
295 			const Tbl *p = &tbl[i];
296 			printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X); }\n"
297 				, p->name, p->code);
298 		}
299 	}
300 
301 	{
302 		const struct Tbl {
303 			uint8 code;
304 			int mode;
305 			const char *name;
306 		} tbl[] = {
307 			{ 0xFC, B|W|D, "padd" },
308 			{ 0xEC, B|W , "padds" },
309 			{ 0xDC, B|W , "paddus" },
310 			{ 0x74, B|W|D, "pcmpeq" },
311 			{ 0x64, B|W|D, "pcmpgt" },
312 			{ 0xF0, W|D|Q, "psll" },
313 			{ 0xE0, W|D , "psra" },
314 			{ 0xD0, W|D|Q, "psrl" },
315 			{ 0xF8, B|W|D, "psub" },
316 			{ 0xE8, B|W , "psubs" },
317 			{ 0xD8, B|W , "psubus" },
318 		};
319 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
320 			const Tbl *p = &tbl[i];
321 			static const char modTbl[][4] = {
322 				"b", "w", "d", "q"
323 			};
324 			for (int j = 0; j < 4; j++) {
325 				// B(0), W(1), D(2), Q(3)
326 				if (!(p->mode & (1 << j))) continue;
327 				printf("void %s%s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X); }\n"
328 					, p->name, modTbl[j]
329 					, p->code | j
330 				);
331 			}
332 		}
333 	}
334 
335 	{
336 		const struct Tbl {
337 			uint8 code;
338 			int ext;
339 			int mode;
340 			const char *name;
341 		} tbl[] = {
342 			{ 0x70, 6, W|D|Q, "psll" },
343 			{ 0x70, 4, W|D , "psra" },
344 			{ 0x70, 2, W|D|Q, "psrl" },
345 		};
346 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
347 			const Tbl *p = &tbl[i];
348 			static const char modTbl[][4] = {
349 				"b", "w", "d", "q"
350 			};
351 			for (int j = 0; j < 4; j++) {
352 				// B(0), W(1), D(2), Q(3)
353 				if (!(p->mode & (1 << j))) continue;
354 				printf("void %s%s(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x%02X, %d); }\n"
355 					, p->name, modTbl[j]
356 					, p->code | j
357 					, p->ext
358 				);
359 			}
360 		}
361 		printf("void pslldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x%02X, %d); }\n", 0x73, 7);
362 		printf("void psrldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x%02X, %d); }\n", 0x73, 3);
363 	}
364 
365 	{
366 		const struct Tbl {
367 			uint8 code;
368 			uint8 pref;
369 			const char *name;
370 		} tbl[] = {
371 			{ 0x70, 0, "pshufw" },
372 			{ 0x70, 0xF2, "pshuflw" },
373 			{ 0x70, 0xF3, "pshufhw" },
374 			{ 0x70, 0x66, "pshufd" },
375 		};
376 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
377 			const Tbl *p = &tbl[i];
378 			printf("void %s(const Mmx& mmx, const Operand& op, uint8 imm8) { opMMX(mmx, op, 0x%02X, 0x%02X, imm8); }\n", p->name, p->code, p->pref);
379 		}
380 	}
381 	{
382 		const struct MmxTbl6 {
383 			uint8 code; // for (reg, reg/[mem])
384 			uint8 code2; // for ([mem], reg)
385 			int pref;
386 			const char *name;
387 		} mmxTbl6[] = {
388 			{ 0x6F, 0x7F, 0x66, "movdqa" },
389 			{ 0x6F, 0x7F, 0xF3, "movdqu" },
390 			// SSE2
391 			{ 0x28, 0x29, NO, "movaps" },
392 			{ 0x10, 0x11, 0xF3, "movss" },
393 			{ 0x10, 0x11, NO, "movups" },
394 			{ 0x28, 0x29, 0x66, "movapd" },
395 			{ 0x10, 0x11, 0xF2, "movsd" },
396 			{ 0x10, 0x11, 0x66, "movupd" },
397 		};
398 		for (size_t i = 0; i < NUM_OF_ARRAY(mmxTbl6); i++) {
399 			const MmxTbl6 *p = &mmxTbl6[i];
400 			printf("void %s(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x%02X, 0x%02X); }\n", p->name, p->code, p->pref);
401 			printf("void %s(const Address& addr, const Xmm& xmm) { ", p->name);
402 			if (p->pref != NO) printf("db(0x%02X); ", p->pref);
403 			printf("opModM(addr, xmm, 0x0F, 0x%02X); }\n", p->code2);
404 		}
405 	}
406 	{
407 		enum {
408 			PS = 1 << 0,
409 			SS = 1 << 1,
410 			PD = 1 << 2,
411 			SD = 1 << 3
412 		};
413 		const struct {
414 			int code;
415 			const char *name;
416 		} sufTbl[] = {
417 			{ NO, "ps" },
418 			{ 0xF3, "ss" },
419 			{ 0x66, "pd" },
420 			{ 0xF2, "sd" },
421 		};
422 		const struct Tbl {
423 			uint8 code;
424 			int mode;
425 			const char *name;
426 			bool hasImm;
427 		} tbl[] = {
428 			{ 0x58, PS|SS|PD|SD, "add" },
429 			{ 0x55, PS|PD     , "andn" },
430 			{ 0x54, PS|PD     , "and" },
431 			{ 0xC2, PS|SS|PD|SD, "cmp", true },
432 			{ 0x5E, PS|SS|PD|SD, "div" },
433 			{ 0x5F, PS|SS|PD|SD, "max" },
434 			{ 0x5D, PS|SS|PD|SD, "min" },
435 			{ 0x59, PS|SS|PD|SD, "mul" },
436 			{ 0x56, PS|PD     , "or" },
437 			{ 0x53, PS|SS     , "rcp" },
438 			{ 0x52, PS|SS     , "rsqrt" },
439 			{ 0xC6, PS|PD     , "shuf", true },
440 			{ 0x51, PS|SS|PD|SD, "sqrt" },
441 			{ 0x5C, PS|SS|PD|SD, "sub" },
442 			{ 0x15, PS|PD     , "unpckh" },
443 			{ 0x14, PS|PD     , "unpckl" },
444 			{ 0x57, PS|PD     , "xor" },
445 			//
446 		};
447 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
448 			const Tbl *p = &tbl[i];
449 			for (size_t j = 0; j < NUM_OF_ARRAY(sufTbl); j++) {
450 				if (!(p->mode & (1 << j))) continue;
451 				if (p->hasImm) {
452 					// don't change uint8 to int because NO is not in byte
453 					printf("void %s%s(const Xmm& xmm, const Operand& op, uint8 imm8) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM, imm8); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
454 				} else {
455 					printf("void %s%s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%2X, 0x%02X, isXMM_XMMorMEM); }\n", p->name, sufTbl[j].name, p->code, sufTbl[j].code);
456 				}
457 			}
458 		}
459 	}
460 	{
461 		// (XMM, XMM)
462 		const struct Tbl {
463 			uint8 code;
464 			uint8 pref;
465 			const char *name;
466 		} tbl[] = {
467 			{ 0xF7, 0x66, "maskmovdqu" },
468 			{ 0x12, 0  , "movhlps" },
469 			{ 0x16, 0  , "movlhps" },
470 		};
471 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
472 			const Tbl *p = &tbl[i];
473 			printf("void %s(const Xmm& reg1, const Xmm& reg2) { ", p->name);
474 			if (p->pref) printf("db(0x%02X); ", p->pref);
475 			printf(" opModR(reg1, reg2, 0x0F, 0x%02X); }\n", p->code);
476 		}
477 	}
478 	{
479 		// (XMM, XMM|MEM)
480 		const struct Tbl {
481 			uint8 code;
482 			int pref;
483 			const char *name;
484 		} tbl[] = {
485 			{ 0x6D, 0x66, "punpckhqdq" },
486 			{ 0x6C, 0x66, "punpcklqdq" },
487 
488 			{ 0x2F, NO , "comiss" },
489 			{ 0x2E, NO , "ucomiss" },
490 			{ 0x2F, 0x66, "comisd" },
491 			{ 0x2E, 0x66, "ucomisd" },
492 
493 			{ 0x5A, 0x66, "cvtpd2ps" },
494 			{ 0x5A, NO , "cvtps2pd" },
495 			{ 0x5A, 0xF2, "cvtsd2ss" },
496 			{ 0x5A, 0xF3, "cvtss2sd" },
497 			{ 0xE6, 0xF2, "cvtpd2dq" },
498 			{ 0xE6, 0x66, "cvttpd2dq" },
499 			{ 0xE6, 0xF3, "cvtdq2pd" },
500 			{ 0x5B, 0x66, "cvtps2dq" },
501 			{ 0x5B, 0xF3, "cvttps2dq" },
502 			{ 0x5B, NO , "cvtdq2ps" },
503 		};
504 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
505 			const Tbl *p = &tbl[i];
506 			printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x%02X, isXMM_XMMorMEM); }\n", p->name, p->code, p->pref);
507 		}
508 	}
509 
510 	{
511 		// special type
512 		const struct Tbl {
513 			uint8 code;
514 			int pref;
515 			const char *name;
516 			const char *cond;
517 		} tbl[] = {
518 			{ 0x2A, NO , "cvtpi2ps",  "isXMM_MMXorMEM" },
519 			{ 0x2D, NO , "cvtps2pi",  "isMMX_XMMorMEM" },
520 			{ 0x2A, 0xF3, "cvtsi2ss",  "isXMM_REG32orMEM" },
521 			{ 0x2D, 0xF3, "cvtss2si",  "isREG32_XMMorMEM" },
522 			{ 0x2C, NO , "cvttps2pi", "isMMX_XMMorMEM" },
523 			{ 0x2C, 0xF3, "cvttss2si", "isREG32_XMMorMEM" },
524 			{ 0x2A, 0x66, "cvtpi2pd",  "isXMM_MMXorMEM" },
525 			{ 0x2D, 0x66, "cvtpd2pi",  "isMMX_XMMorMEM" },
526 			{ 0x2A, 0xF2, "cvtsi2sd",  "isXMM_REG32orMEM" },
527 			{ 0x2D, 0xF2, "cvtsd2si",  "isREG32_XMMorMEM" },
528 			{ 0x2C, 0x66, "cvttpd2pi", "isMMX_XMMorMEM" },
529 			{ 0x2C, 0xF2, "cvttsd2si", "isREG32_XMMorMEM" },
530 		};
531 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
532 			const Tbl *p = &tbl[i];
533 			printf("void %s(const Operand& reg, const Operand& op) { opGen(reg, op, 0x%02X, 0x%02X, %s); }\n", p->name, p->code, p->pref, p->cond);
534 		}
535 	}
536 	{
537 		// prefetch
538 		const struct Tbl {
539 			int ext;
540 			const char *name;
541 			int code;
542 		} tbl[] = {
543 			{ 1, "t0", 0x18},
544 			{ 2, "t1", 0x18},
545 			{ 3, "t2", 0x18},
546 			{ 0, "nta", 0x18},
547 			{ 2, "wt1", 0x0D},
548 			{ 1, "w", 0x0D},
549 		};
550 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
551 			const Tbl *p = &tbl[i];
552 			printf("void prefetch%s(const Address& addr) { opModM(addr, Reg32(%d), 0x0F, 0x%02X); }\n", p->name, p->ext, p->code);
553 		}
554 	}
555 	{
556 		const struct Tbl {
557 			uint8 code;
558 			int pref;
559 			const char *name;
560 		} tbl[] = {
561 			{ 0x16, NO,   "movhps" },
562 			{ 0x12, NO,   "movlps" },
563 			{ 0x16, 0x66, "movhpd" },
564 			{ 0x12, 0x66, "movlpd" },
565 		};
566 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
567 			const Tbl *p = &tbl[i];
568 			printf("void %s(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x%02X, 0x%02X); }\n", p->name, p->code, p->pref);
569 		}
570 	}
571 	{
572 		// cmov
573 		const struct Tbl {
574 			uint8 ext;
575 			const char *name;
576 		} tbl[] = {
577 			{ 0, "o" },
578 			{ 1, "no" },
579 			{ 2, "b" },
580 			{ 2, "c" },
581 			{ 2, "nae" },
582 			{ 3, "nb" },
583 			{ 3, "ae" },
584 			{ 3, "nc" },
585 			{ 4, "e" },
586 			{ 4, "z" },
587 			{ 5, "ne" },
588 			{ 5, "nz" },
589 			{ 6, "be" },
590 			{ 6, "na" },
591 			{ 7, "nbe" },
592 			{ 7, "a" },
593 			{ 8, "s" },
594 			{ 9, "ns" },
595 			{ 10, "p" },
596 			{ 10, "pe" },
597 			{ 11, "np" },
598 			{ 11, "po" },
599 			{ 12, "l" },
600 			{ 12, "nge" },
601 			{ 13, "nl" },
602 			{ 13, "ge" },
603 			{ 14, "le" },
604 			{ 14, "ng" },
605 			{ 15, "nle" },
606 			{ 15, "g" },
607 		};
608 		const char *msg = "//-V524"; // disable warning of PVS-Studio
609 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
610 			const Tbl *p = &tbl[i];
611 			printf("void cmov%s(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | %d); }%s\n", p->name, p->ext, msg);
612 			printf("void j%s(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x%02X, 0x%02X, 0x%02X); }%s\n", p->name, p->ext | 0x70, p->ext | 0x80, 0x0F, msg);
613 			printf("void j%s(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x%02X, 0x%02X, 0x%02X); }%s\n", p->name, p->ext | 0x70, p->ext | 0x80, 0x0F, msg);
614 			printf("void j%s(const char *label, LabelType type = T_AUTO) { j%s(std::string(label), type); }%s\n", p->name, p->name, msg);
615 			printf("void j%s(const void *addr) { opJmpAbs(addr, T_NEAR, 0x%02X, 0x%02X, 0x%02X); }%s\n", p->name, p->ext | 0x70, p->ext | 0x80, 0x0F, msg);
616 			printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | %d); }%s\n", p->name, p->ext, msg);
617 		}
618 	}
619 	////////////////////////////////////////////////////////////////
620 	{
621 		const GenericTbl tbl[] = {
622 			{ "bnd", 0xf2 }, /* 0xf2 prefix for MPX */
623 			{ "cbw", 0x66, 0x98 },
624 			{ "cdq", 0x99 },
625 			{ "clc", 0xF8 },
626 			{ "cld", 0xFC },
627 			{ "cli", 0xFA },
628 			{ "cmc", 0xF5 },
629 
630 			{ "cpuid", 0x0F, 0xA2 },
631 			{ "cwd", 0x66, 0x99 },
632 			{ "cwde", 0x98 },
633 			{ "cmpsb", 0xA6 },
634 			{ "cmpsw", 0x66, 0xA7 },
635 			{ "cmpsd", 0xA7 },
636 			{ "scasb", 0xAE },
637 			{ "scasw", 0x66, 0xAF },
638 			{ "scasd", 0xAF },
639 			{ "movsb", 0xA4 },
640 			{ "movsw", 0x66, 0xA5 },
641 			{ "movsd", 0xA5 },
642 			{ "stosb", 0xAA },
643 			{ "stosw", 0x66, 0xAB },
644 			{ "stosd", 0xAB },
645 			{ "rep", 0xF3 },
646 
647 			{ "lahf", 0x9F },
648 			{ "lock", 0xF0 },
649 
650 			{ "sahf", 0x9E },
651 			{ "stc", 0xF9 },
652 			{ "std", 0xFD },
653 			{ "sti", 0xFB },
654 
655 			{ "emms", 0x0F, 0x77 },
656 			{ "pause", 0xF3, 0x90 },
657 			{ "sfence", 0x0F, 0xAE, 0xF8 },
658 			{ "lfence", 0x0F, 0xAE, 0xE8 },
659 			{ "mfence", 0x0F, 0xAE, 0xF0 },
660 			{ "monitor", 0x0F, 0x01, 0xC8 },
661 			{ "mwait", 0x0F, 0x01, 0xC9 },
662 
663 			{ "rdmsr", 0x0F, 0x32 },
664 			{ "rdpmc", 0x0F, 0x33 },
665 			{ "rdtsc", 0x0F, 0x31 },
666 			{ "rdtscp", 0x0F, 0x01, 0xF9 },
667 			{ "ud2", 0x0F, 0x0B },
668 			{ "wait", 0x9B },
669 			{ "fwait", 0x9B },
670 			{ "wbinvd", 0x0F, 0x09 },
671 			{ "wrmsr", 0x0F, 0x30 },
672 			{ "xlatb", 0xD7 },
673 
674 			{ "popf", 0x9D },
675 			{ "pushf", 0x9C },
676 			{ "stac", 0x0F, 0x01, 0xCB },
677 
678 			{ "vzeroall", 0xC5, 0xFC, 0x77 },
679 			{ "vzeroupper", 0xC5, 0xF8, 0x77 },
680 			{ "xgetbv", 0x0F, 0x01, 0xD0 },
681 
682 			// FPU
683 			{ "f2xm1", 0xD9, 0xF0 },
684 			{ "fabs", 0xD9, 0xE1 },
685 			{ "faddp", 0xDE, 0xC1 },
686 			{ "fchs", 0xD9, 0xE0 },
687 
688 			{ "fcom", 0xD8, 0xD1 },
689 			{ "fcomp", 0xD8, 0xD9 },
690 			{ "fcompp", 0xDE, 0xD9 },
691 			{ "fcos", 0xD9, 0xFF },
692 			{ "fdecstp", 0xD9, 0xF6 },
693 			{ "fdivp", 0xDE, 0xF9 },
694 			{ "fdivrp", 0xDE, 0xF1 },
695 			{ "fincstp", 0xD9, 0xF7 },
696 			{ "finit", 0x9B, 0xDB, 0xE3 },
697 			{ "fninit", 0xDB, 0xE3 },
698 			{ "fld1", 0xD9, 0xE8 },
699 			{ "fldl2t", 0xD9, 0xE9 },
700 			{ "fldl2e", 0xD9, 0xEA },
701 			{ "fldpi", 0xD9, 0xEB },
702 			{ "fldlg2", 0xD9, 0xEC },
703 			{ "fldln2", 0xD9, 0xED },
704 			{ "fldz", 0xD9, 0xEE },
705 			{ "fmulp", 0xDE, 0xC9 },
706 			{ "fnop", 0xD9, 0xD0 },
707 			{ "fpatan", 0xD9, 0xF3 },
708 			{ "fprem", 0xD9, 0xF8 },
709 			{ "fprem1", 0xD9, 0xF5 },
710 			{ "fptan", 0xD9, 0xF2 },
711 			{ "frndint", 0xD9, 0xFC },
712 			{ "fscale", 0xD9, 0xFD },
713 			{ "fsin", 0xD9, 0xFE },
714 			{ "fsincos", 0xD9, 0xFB },
715 			{ "fsqrt", 0xD9, 0xFA },
716 			{ "fsubp", 0xDE, 0xE9 },
717 			{ "fsubrp", 0xDE, 0xE1 },
718 			{ "ftst", 0xD9, 0xE4 },
719 			{ "fucom", 0xDD, 0xE1 },
720 			{ "fucomp", 0xDD, 0xE9 },
721 			{ "fucompp", 0xDA, 0xE9 },
722 			{ "fxam", 0xD9, 0xE5 },
723 			{ "fxch", 0xD9, 0xC9 },
724 			{ "fxtract", 0xD9, 0xF4 },
725 			{ "fyl2x", 0xD9, 0xF1 },
726 			{ "fyl2xp1", 0xD9, 0xF9 },
727 		};
728 		putGeneric(tbl, NUM_OF_ARRAY(tbl));
729 	}
730 	{
731 		const struct Tbl {
732 			uint8 code; // (reg, reg)
733 			uint8 ext; // (reg, imm)
734 			const char *name;
735 		} tbl[] = {
736 			{ 0x10, 2, "adc" },
737 			{ 0x00, 0, "add" },
738 			{ 0x20, 4, "and_" },
739 			{ 0x38, 7, "cmp" },
740 			{ 0x08, 1, "or_" },
741 			{ 0x18, 3, "sbb" },
742 			{ 0x28, 5, "sub" },
743 			{ 0x30, 6, "xor_" },
744 		};
745 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
746 			const Tbl *p = &tbl[i];
747 			printf("void %s(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x%02X); }\n", p->name, p->code);
748 			printf("void %s(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext);
749 		}
750 	}
751 
752 	{
753 		const struct Tbl {
754 			uint8 code;
755 			uint8 ext;
756 			const char *name;
757 		} tbl[] = {
758 			{ 0x48, 1, "dec" },
759 			{ 0x40, 0, "inc" },
760 		};
761 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
762 			const Tbl *p = &tbl[i];
763 			printf("void %s(const Operand& op) { opIncDec(op, 0x%02X, %d); }\n", p->name, p->code, p->ext);
764 		}
765 	}
766 	{
767 		const struct Tbl {
768 			uint8 code;
769 			uint8 ext;
770 			const char *name;
771 		} tbl[] = {
772 			{ 0xa3, 4, "bt" },
773 			{ 0xab, 5, "bts" },
774 			{ 0xb3, 6, "btr" },
775 			{ 0xbb, 7, "btc" },
776 		};
777 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
778 			const Tbl *p = &tbl[i];
779 			printf("void %s(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0x%02X); }\n", p->name, p->code);
780 			printf("void %s(const Operand& op, uint8 imm) { opR_ModM(op, 16|32|64, %d, 0x0f, 0xba, NONE, false, 1); db(imm); }\n", p->name, p->ext);
781 		}
782 	}
783 	{
784 		const struct Tbl {
785 			uint8 code;
786 			uint8 ext;
787 			const char *name;
788 		} tbl[] = {
789 			{ 0xF6, 6, "div" },
790 			{ 0xF6, 7, "idiv" },
791 			{ 0xF6, 5, "imul" },
792 			{ 0xF6, 4, "mul" },
793 			{ 0xF6, 3, "neg" },
794 			{ 0xF6, 2, "not_" },
795 		};
796 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
797 			const Tbl *p = &tbl[i];
798 			const std::string name = p->name;
799 			printf("void %s(const Operand& op) { opR_ModM(op, 0, %d, 0x%02X); }\n", p->name, p->ext, p->code);
800 		}
801 	}
802 	{
803 		const struct Tbl {
804 			const char *name;
805 			uint8 ext;
806 		} tbl[] = {
807 			{ "rcl", 2 },
808 			{ "rcr", 3 },
809 			{ "rol", 0 },
810 			{ "ror", 1 },
811 			{ "sar", 7 },
812 			{ "shl", 4 },
813 			{ "shr", 5 },
814 
815 			{ "sal", 4 },
816 		};
817 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
818 			const Tbl *p = &tbl[i];
819 			printf("void %s(const Operand& op, int imm) { opShift(op, imm, %d); }\n", p->name, p->ext);
820 			printf("void %s(const Operand& op, const Reg8& _cl) { opShift(op, _cl, %d); }\n", p->name, p->ext);
821 		}
822 	}
823 	{
824 		const struct Tbl {
825 			const char *name;
826 			uint8 code;
827 		} tbl[] = {
828 			{ "shld", 0xA4 },
829 			{ "shrd", 0xAC },
830 		};
831 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
832 			const Tbl *p = &tbl[i];
833 			printf("void %s(const Operand& op, const Reg& reg, uint8 imm) { opShxd(op, reg, imm, 0x%02X); }\n", p->name, p->code);
834 			printf("void %s(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0x%02X, &_cl); }\n", p->name, p->code);
835 		}
836 	}
837 	{
838 		const struct Tbl {
839 			const char *name;
840 			uint8 code;
841 		} tbl[] = {
842 			{ "bsf", 0xBC },
843 			{ "bsr", 0xBD },
844 		};
845 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
846 			const Tbl *p = &tbl[i];
847 			printf("void %s(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x%02X); }\n", p->name, p->code);
848 		}
849 	}
850 	{
851 		const struct Tbl {
852 			const char *name;
853 			uint8 code;
854 		} tbl[] = {
855 			{ "popcnt", 0xB8 },
856 			{ "tzcnt", 0xBC },
857 			{ "lzcnt", 0xBD },
858 		};
859 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
860 			const Tbl *p = &tbl[i];
861 			printf("void %s(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0x%02X); }\n", p->name, p->code);
862 		}
863 	}
864 	// SSSE3
865 	{
866 		const struct Tbl {
867 			uint8 code;
868 			const char *name;
869 		} tbl[] = {
870 			{ 0x00, "pshufb" },
871 			{ 0x01, "phaddw" },
872 			{ 0x02, "phaddd" },
873 			{ 0x03, "phaddsw" },
874 			{ 0x04, "pmaddubsw" },
875 			{ 0x05, "phsubw" },
876 			{ 0x06, "phsubd" },
877 			{ 0x07, "phsubsw" },
878 			{ 0x08, "psignb" },
879 			{ 0x09, "psignw" },
880 			{ 0x0a, "psignd" },
881 			{ 0x0b, "pmulhrsw" },
882 			{ 0x1c, "pabsb" },
883 			{ 0x1d, "pabsw" },
884 			{ 0x1e, "pabsd" },
885 		};
886 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
887 			const Tbl *p = &tbl[i];
888 			printf("void %s(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x%02X, 0x66, NONE, 0x38); }\n", p->name, p->code);
889 		}
890 		printf("void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8>(imm), 0x3a); }\n");
891 	}
892 	{
893 		const struct Tbl {
894 			const char *name;
895 			uint8 code;
896 		} tbl[] = {
897 			{ "pclmullqlqdq", 0 },
898 			{ "pclmulhqlqdq", 1 },
899 			{ "pclmullqhdq", 0x10 },
900 			{ "pclmulhqhdq", 0x11 },
901 		};
902 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
903 			const Tbl *p = &tbl[i];
904 			printf("void %s(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x%02X); }\n", p->name, p->code);
905 		}
906 	}
907 	{
908 		const struct Tbl {
909 			uint8 code1;
910 			int code2;
911 			uint8 ext;
912 			const char *name;
913 		} tbl[] = {
914 			{ 0x0F, 0xAE, 2, "ldmxcsr" },
915 			{ 0x0F, 0xAE, 3, "stmxcsr" },
916 			{ 0x0F, 0xAE, 7, "clflush" }, // 0x80 is bug of nasm ?
917 			{ 0xD9, NONE, 5, "fldcw" },
918 //			{ 0x9B, 0xD9, 7, "fstcw" }, // not correct order for fstcw [eax] on 64bit OS
919 		};
920 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
921 			const Tbl *p = &tbl[i];
922 			printf("void %s(const Address& addr) { opModM(addr, Reg32(%d), 0x%02X, 0x%02X); }\n", p->name, p->ext, p->code1, p->code2);
923 		}
924 		printf("void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, NONE); }\n");
925 	}
926 	{
927 		const struct Tbl {
928 			uint8 code;
929 			const char *name;
930 		} tbl[] = {
931 			{ 0x2B, "movntpd" },
932 			{ 0xE7, "movntdq" },
933 		};
934 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
935 			const Tbl *p = &tbl[i];
936 			// cast xmm register to 16bit register to put 0x66
937 			printf("void %s(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x%02X); }\n", p->name, p->code);
938 		}
939 	}
940 	{
941 		const struct Tbl {
942 			uint8 code;
943 			const char *name;
944 		} tbl[] = {
945 			{ 0xBE, "movsx" },
946 			{ 0xB6, "movzx" },
947 		};
948 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
949 			const Tbl *p = &tbl[i];
950 			printf("void %s(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0x%02X); }\n", p->name, p->code);
951 		}
952 	}
953 	// mpx
954 	{
955 		puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
956 		puts("void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
957 		puts("void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }");
958 		puts("void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }");
959 		puts("void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }");
960 		puts("void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }");
961 		puts("void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }");
962 		puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }");
963 	}
964 	// misc
965 	{
966 		puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModM(addr, reg, 0x8D); }");
967 		puts("void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }");
968 		puts("void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }");
969 
970 		puts("void xadd(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xC0 | (reg.isBit(8) ? 0 : 1)); }");
971 		puts("void cmpxchg(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xB0 | (reg.isBit(8) ? 0 : 1)); }");
972 		puts("void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); }");
973 		puts("void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); }");
974 		puts("void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }");
975 		puts("void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); }");
976 		puts("void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); }");
977 
978 		puts("void pextrw(const Operand& op, const Mmx& xmm, uint8 imm) { opExt(op, xmm, 0x15, imm, true); }");
979 		puts("void pextrb(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x14, imm); }");
980 		puts("void pextrd(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x16, imm); }");
981 		puts("void extractps(const Operand& op, const Xmm& xmm, uint8 imm) { opExt(op, xmm, 0x17, imm); }");
982 		puts("void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); }");
983 		puts("void insertps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); }");
984 		puts("void pinsrb(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
985 		puts("void pinsrd(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); }");
986 
987 		puts("void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); }");
988 		puts("void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) throw Error(ERR_BAD_COMBINATION); opModR(reg1, reg2, 0x0F, 0xF7); }");
989 		puts("void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); }");
990 		puts("void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); }");
991 		puts("void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); }");
992 		puts("void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); }");
993 		puts("void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); }");
994 		puts("void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); }");
995 		puts("void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) throw Error(ERR_BAD_COMBINATION); opModM(addr, mmx, 0x0F, 0xE7); }");
996 
997 		puts("void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); }");
998 		puts("void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
999 		puts("void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); }");
1000 		puts("void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
1001 		puts("void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); }");
1002 		puts("void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); }");
1003 		puts("void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); }");
1004 		puts("void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); }");
1005 		puts("void rdrand(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
1006 		puts("void rdseed(const Reg& r) { if (r.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER); opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); }");
1007 		puts("void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); }");
1008 	}
1009 	{
1010 		const struct Tbl {
1011 			uint8 m16;
1012 			uint8 m32;
1013 			uint8 m64;
1014 			uint8 ext;
1015 			const char *name;
1016 			uint8 m64ext;
1017 		} tbl[] = {
1018 			{ 0x00, 0xD8, 0xDC, 0, "fadd" },
1019 			{ 0xDE, 0xDA, 0x00, 0, "fiadd" },
1020 			{ 0x00, 0xD8, 0xDC, 2, "fcom" },
1021 			{ 0x00, 0xD8, 0xDC, 3, "fcomp" },
1022 			{ 0x00, 0xD8, 0xDC, 6, "fdiv" },
1023 			{ 0xDE, 0xDA, 0x00, 6, "fidiv" },
1024 			{ 0x00, 0xD8, 0xDC, 7, "fdivr" },
1025 			{ 0xDE, 0xDA, 0x00, 7, "fidivr" },
1026 			{ 0xDE, 0xDA, 0x00, 2, "ficom" },
1027 			{ 0xDE, 0xDA, 0x00, 3, "ficomp" },
1028 			{ 0xDF, 0xDB, 0xDF, 0, "fild", 5 },
1029 			{ 0xDF, 0xDB, 0x00, 2, "fist" },
1030 			{ 0xDF, 0xDB, 0xDF, 3, "fistp", 7 },
1031 			{ 0xDF, 0xDB, 0xDD, 1, "fisttp" },
1032 			{ 0x00, 0xD9, 0xDD, 0, "fld" },
1033 			{ 0x00, 0xD8, 0xDC, 1, "fmul" },
1034 			{ 0xDE, 0xDA, 0x00, 1, "fimul" },
1035 			{ 0x00, 0xD9, 0xDD, 2, "fst" },
1036 			{ 0x00, 0xD9, 0xDD, 3, "fstp" },
1037 			{ 0x00, 0xD8, 0xDC, 4, "fsub" },
1038 			{ 0xDE, 0xDA, 0x00, 4, "fisub" },
1039 			{ 0x00, 0xD8, 0xDC, 5, "fsubr" },
1040 			{ 0xDE, 0xDA, 0x00, 5, "fisubr" },
1041 		};
1042 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1043 			const Tbl *p = &tbl[i];
1044 			printf("void %s(const Address& addr) { opFpuMem(addr, 0x%02X, 0x%02X, 0x%02X, %d, %d); }\n", p->name, p->m16, p->m32, p->m64, p->ext, p->m64ext);
1045 		}
1046 	}
1047 	{
1048 		const struct Tbl {
1049 			uint32 code1;
1050 			uint32 code2;
1051 			const char *name;
1052 		} tbl[] = {
1053 			{ 0xD8C0, 0xDCC0, "fadd" },
1054 			{ 0x0000, 0xDEC0, "faddp" },
1055 
1056 			{ 0xDAC0, 0x00C0, "fcmovb" },
1057 			{ 0xDAC8, 0x00C8, "fcmove" },
1058 			{ 0xDAD0, 0x00D0, "fcmovbe" },
1059 			{ 0xDAD8, 0x00D8, "fcmovu" },
1060 			{ 0xDBC0, 0x00C0, "fcmovnb" },
1061 			{ 0xDBC8, 0x00C8, "fcmovne" },
1062 			{ 0xDBD0, 0x00D0, "fcmovnbe" },
1063 			{ 0xDBD8, 0x00D8, "fcmovnu" },
1064 
1065 			{ 0xDBF0, 0x00F0, "fcomi" },
1066 			{ 0xDFF0, 0x00F0, "fcomip" },
1067 			{ 0xDBE8, 0x00E8, "fucomi" },
1068 			{ 0xDFE8, 0x00E8, "fucomip" },
1069 
1070 			{ 0xD8F0, 0xDCF8, "fdiv" },
1071 			{ 0x0000, 0xDEF8, "fdivp" },
1072 			{ 0xD8F8, 0xDCF0, "fdivr" },
1073 			{ 0x0000, 0xDEF0, "fdivrp" },
1074 			{ 0xD8C8, 0xDCC8, "fmul" },
1075 			{ 0x0000, 0xDEC8, "fmulp" },
1076 			{ 0xD8E0, 0xDCE8, "fsub" },
1077 			{ 0x0000, 0xDEE8, "fsubp" },
1078 			{ 0xD8E8, 0xDCE0, "fsubr" },
1079 			{ 0x0000, 0xDEE0, "fsubrp" },
1080 		};
1081 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1082 			const Tbl *p = &tbl[i];
1083 			printf("void %s(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x%04X, 0x%04X); }\n", p->name, p->code1, p->code2);
1084 			// omit st0 version(like nasm)
1085 			if (p->code1) {
1086 				printf("void %s(const Fpu& reg1) { opFpuFpu(st0, reg1, 0x%04X, 0x%04X); }\n", p->name, p->code1, p->code2);
1087 			} else {
1088 				printf("void %s(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x%04X, 0x%04X); }\n", p->name, p->code1, p->code2);
1089 			}
1090 		}
1091 	}
1092 	{
1093 		const struct Tbl {
1094 			uint8 code1;
1095 			uint8 code2;
1096 			const char *name;
1097 		} tbl[] = {
1098 			{ 0xD8, 0xD0, "fcom" },
1099 			{ 0xD8, 0xD8, "fcomp" },
1100 			{ 0xDD, 0xC0, "ffree" },
1101 			{ 0xD9, 0xC0, "fld" },
1102 			{ 0xDD, 0xD0, "fst" },
1103 			{ 0xDD, 0xD8, "fstp" },
1104 			{ 0xDD, 0xE0, "fucom" },
1105 			{ 0xDD, 0xE8, "fucomp" },
1106 			{ 0xD9, 0xC8, "fxch" },
1107 		};
1108 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1109 			const Tbl *p = &tbl[i];
1110 			printf("void %s(const Fpu& reg) { opFpu(reg, 0x%02X, 0x%02X); }\n", p->name, p->code1, p->code2);
1111 		}
1112 	}
1113 	// AVX
1114 	{ // pd, ps, sd, ss
1115 		const struct Tbl {
1116 			uint8 code;
1117 			const char *name;
1118 			bool only_pd_ps;
1119 		} tbl[] = {
1120 			{ 0x58, "add", false },
1121 			{ 0x5C, "sub", false },
1122 			{ 0x59, "mul", false },
1123 			{ 0x5E, "div", false },
1124 			{ 0x5F, "max", false },
1125 			{ 0x5D, "min", false },
1126 			{ 0x54, "and", true },
1127 			{ 0x55, "andn", true },
1128 			{ 0x56, "or", true },
1129 			{ 0x57, "xor", true },
1130 		};
1131 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1132 			const Tbl *p = &tbl[i];
1133 			printf("void v%spd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x%02X); }\n", p->name, p->code);
1134 			printf("void v%sps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x%02X); }\n", p->name, p->code);
1135 			if (p->only_pd_ps) continue;
1136 			printf("void v%ssd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_Z | T_N8, 0x%02X); }\n", p->name, p->code);
1137 			printf("void v%sss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_Z | T_N4, 0x%02X); }\n", p->name, p->code);
1138 		}
1139 	}
1140 	putX_X_XM(false);
1141 
1142 	// (x, x/m[, imm]) or (y, y/m[, imm])
1143 	{
1144 		const struct Tbl {
1145 			uint8 code;
1146 			const char *name;
1147 			int type;
1148 			bool hasIMM;
1149 			int mode; // 1 : SSE, 2 : AVX, 3 : SSE + AVX
1150 		} tbl[] = {
1151 			{ 0x15, "blendvpd", T_0F38 | T_66, false, 1 },
1152 			{ 0x14, "blendvps", T_0F38 | T_66, false, 1 },
1153 			{ 0x10, "pblendvb", T_0F38 | T_66, false, 1 },
1154 			{ 0xDF, "aeskeygenassist", T_0F3A | T_66, true, 3 },
1155 			{ 0xDB, "aesimc", T_0F38 | T_66 | T_W0, false, 3 },
1156 			{ 0x09, "roundpd", T_0F3A | T_66 | T_YMM, true, 3 },
1157 			{ 0x08, "roundps", T_0F3A | T_66 | T_YMM, true, 3 },
1158 			{ 0x05, "permilpd", T_0F3A | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64, true, 2 },
1159 			{ 0x04, "permilps", T_0F3A | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, true, 2 },
1160 			{ 0x61, "pcmpestri", T_0F3A | T_66, true, 3 },
1161 			{ 0x60, "pcmpestrm", T_0F3A | T_66, true, 3 },
1162 			{ 0x63, "pcmpistri", T_0F3A | T_66, true, 3 },
1163 			{ 0x62, "pcmpistrm", T_0F3A | T_66, true, 3 },
1164 			{ 0x0E, "testps", T_0F38 | T_66 | T_YMM, false, 2 },
1165 			{ 0x0F, "testpd", T_0F38 | T_66 | T_YMM, false, 2 },
1166 			{ 0x2F, "comisd", T_0F | T_66 | T_EVEX | T_EW1 | T_SAE_X | T_N8, false, 2 },
1167 			{ 0x2F, "comiss", T_0F | T_EVEX | T_EW0 | T_SAE_X | T_N4, false, 2 },
1168 			{ 0x5B, "cvtdq2ps", T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_ER_Z, false, 2 },
1169 			{ 0x5B, "cvtps2dq", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_ER_Z, false, 2 },
1170 			{ 0x5B, "cvttps2dq", T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_SAE_Z, false, 2 },
1171 			{ 0x28, "movapd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1, false, 2 },
1172 			{ 0x28, "movaps", T_0F | T_YMM | T_EVEX | T_EW0, false, 2 },
1173 			{ 0x12, "movddup", T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_ER_X | T_ER_Y | T_ER_Z | T_DUP, false, 3 },
1174 			{ 0x6F, "movdqa", T_0F | T_66 | T_YMM, false, 2 },
1175 			{ 0x6F, "movdqu", T_0F | T_F3 | T_YMM, false, 2 },
1176 			{ 0x16, "movshdup", T_0F | T_F3 | T_YMM | T_EVEX | T_EW0, false, 3 },
1177 			{ 0x12, "movsldup", T_0F | T_F3 | T_YMM | T_EVEX | T_EW0, false, 3 },
1178 			{ 0x10, "movupd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1, false, 2 },
1179 			{ 0x10, "movups", T_0F | T_YMM | T_EVEX | T_EW0, false, 2 },
1180 
1181 			{ 0x1C, "pabsb", T_0F38 | T_66 | T_YMM | T_EVEX, false, 2 },
1182 			{ 0x1D, "pabsw", T_0F38 | T_66 | T_YMM | T_EVEX, false, 2 },
1183 			{ 0x1E, "pabsd", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, false, 2 },
1184 			{ 0x41, "phminposuw", T_0F38 | T_66, false, 3 },
1185 
1186 			{ 0x20, "pmovsxbw", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1187 			{ 0x21, "pmovsxbd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1188 			{ 0x22, "pmovsxbq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N2 | T_N_VL, false, 3 },
1189 			{ 0x23, "pmovsxwd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1190 			{ 0x24, "pmovsxwq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1191 			{ 0x25, "pmovsxdq", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_N8 | T_N_VL, false, 3 },
1192 
1193 			{ 0x30, "pmovzxbw", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1194 			{ 0x31, "pmovzxbd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1195 			{ 0x32, "pmovzxbq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N2 | T_N_VL, false, 3 },
1196 			{ 0x33, "pmovzxwd", T_0F38 | T_66 | T_YMM | T_EVEX | T_N8 | T_N_VL, false, 3 },
1197 			{ 0x34, "pmovzxwq", T_0F38 | T_66 | T_YMM | T_EVEX | T_N4 | T_N_VL, false, 3 },
1198 			{ 0x35, "pmovzxdq", T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0 | T_N8 | T_N_VL, false, 3 },
1199 
1200 			{ 0x70, "pshufd", T_0F | T_66 | T_YMM | T_EVEX | T_EW0 | T_B32, true, 2 },
1201 			{ 0x70, "pshufhw", T_0F | T_F3 | T_YMM | T_EVEX, true, 2 },
1202 			{ 0x70, "pshuflw", T_0F | T_F2 | T_YMM | T_EVEX, true, 2 },
1203 
1204 			{ 0x17, "ptest", T_0F38 | T_66 | T_YMM, false, 3 },
1205 			{ 0x53, "rcpps", T_0F | T_YMM, false, 2 },
1206 			{ 0x52, "rsqrtps", T_0F | T_YMM, false, 2 },
1207 
1208 			{ 0x51, "sqrtpd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_ER_Z | T_B64, false, 2 },
1209 			{ 0x51, "sqrtps", T_0F | T_YMM | T_EVEX | T_EW0 | T_ER_Z | T_B32, false, 2 },
1210 
1211 			{ 0x2E, "ucomisd", T_0F | T_66 | T_EVEX | T_EW1 | T_SAE_X | T_N8, false, 2 },
1212 			{ 0x2E, "ucomiss", T_0F | T_EVEX | T_EW0 | T_SAE_X | T_N4, false, 2 },
1213 
1214 			{ 0xCC, "sha1rnds4", T_0F3A, true, 1 },
1215 			{ 0xC8, "sha1nexte", T_0F38, false, 1 },
1216 			{ 0xC9, "sha1msg1", T_0F38, false, 1 },
1217 			{ 0xCA, "sha1msg2", T_0F38, false, 1 },
1218 			{ 0xCB, "sha256rnds2", T_0F38, false, 1 },
1219 			{ 0xCC, "sha256msg1", T_0F38, false, 1 },
1220 			{ 0xCD, "sha256msg2", T_0F38, false, 1 },
1221 		};
1222 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1223 			const Tbl *p = &tbl[i];
1224 			std::string type = type2String(p->type);
1225 			if (p->mode & 1) {
1226 				const char *immS1 = p->hasIMM ? ", uint8 imm" : "";
1227 				const char *immS2 = p->hasIMM ? ", imm" : ", NONE";
1228 				const char *pref = p->type & T_66 ? "0x66" : p->type & T_F2 ? "0xF2" : p->type & T_F3 ? "0xF3" : "NONE";
1229 				const char *suf = p->type & T_0F38 ? "0x38" : p->type & T_0F3A ? "0x3A" : "NONE";
1230 				printf("void %s(const Xmm& xmm, const Operand& op%s) { opGen(xmm, op, 0x%02X, %s, isXMM_XMMorMEM%s, %s); }\n", p->name, immS1, p->code, pref, immS2, suf);
1231 			}
1232 			if (p->mode & 2) {
1233 				printf("void v%s(const Xmm& xm, const Operand& op%s) { opAVX_X_XM_IMM(xm, op, %s, 0x%02X%s); }\n"
1234 					, p->name, p->hasIMM ? ", uint8 imm" : "", type.c_str(), p->code, p->hasIMM ? ", imm" : "");
1235 			}
1236 		}
1237 	}
1238 	// (m, x), (m, y)
1239 	{
1240 		const struct Tbl {
1241 			uint8 code;
1242 			const char *name;
1243 			int type;
1244 		} tbl[] = {
1245 			{ 0x29, "movapd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_M_K },
1246 			{ 0x29, "movaps", T_0F | T_YMM | T_EVEX | T_EW0 | T_M_K },
1247 			{ 0x7F, "movdqa", T_0F | T_66 | T_YMM  },
1248 			{ 0x7F, "movdqu", T_0F | T_F3 | T_YMM  },
1249 			{ 0x11, "movupd", T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_M_K },
1250 			{ 0x11, "movups", T_0F | T_YMM | T_EVEX | T_EW0 | T_M_K },
1251 		};
1252 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1253 			const Tbl *p = &tbl[i];
1254 			std::string type = type2String(p->type);
1255 			printf("void v%s(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, %s, 0x%02X); }\n"
1256 				, p->name, type.c_str(), p->code);
1257 		}
1258 	}
1259 	// (x, x/m), (y, y/m), (x, x, x/m), (y, y, y/m)
1260 	{
1261 		const struct Tbl {
1262 			uint8 code;
1263 			const char *name;
1264 			int type;
1265 			int mode; // 1 : sse, 2 : avx, 3 : sse + avx
1266 		} tbl[] = {
1267 			{ 0xD0, "addsubpd", T_0F | T_66 | T_YMM, 3 },
1268 			{ 0xD0, "addsubps", T_0F | T_F2 | T_YMM, 3 },
1269 			{ 0x7C, "haddpd", T_0F | T_66 | T_YMM, 3 },
1270 			{ 0x7C, "haddps", T_0F | T_F2 | T_YMM, 3 },
1271 			{ 0x7D, "hsubpd", T_0F | T_66 | T_YMM, 3 },
1272 			{ 0x7D, "hsubps", T_0F | T_F2 | T_YMM, 3 },
1273 
1274 			{ 0xDC, "aesenc", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1275 			{ 0xDD, "aesenclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1276 			{ 0xDE, "aesdec", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1277 			{ 0xDF, "aesdeclast", T_0F38 | T_66 | T_YMM | T_EVEX, 3 },
1278 		};
1279 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1280 			const Tbl *p = &tbl[i];
1281 			std::string type = type2String(p->type);
1282 			if (p->mode & 1) {
1283 				uint8 pref = p->type & T_66 ? 0x66 : p->type & T_F2 ? 0xF2 : p->type & T_F3 ? 0xF3 : 0;
1284 				printf("void %s(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x%02X, 0x%02X, isXMM_XMMorMEM%s); }\n", p->name, p->code, pref, p->type & T_0F38 ? ", NONE, 0x38" : "");
1285 			}
1286 			if (p->mode & 2) {
1287 				printf("void v%s(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, %s, 0x%02X); }\n"
1288 					, p->name, type.c_str(), p->code);
1289 			}
1290 		}
1291 	}
1292 	// vmaskmov
1293 	{
1294 		const char suf[][8] = { "ps", "pd" };
1295 		for (int i = 0; i < 2; i++) {
1296 			printf("void vmaskmov%s(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x%02X); }\n", suf[i], 0x2C + i);
1297 			printf("void vmaskmov%s(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x%02X); }\n", suf[i], 0x2E + i);
1298 		}
1299 	}
1300 	// vpmaskmov
1301 	{
1302 		const char suf[][8] = { "d", "q" };
1303 		for (int i = 0; i < 2; i++) {
1304 			printf("void vpmaskmov%s(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W%d | T_YMM, 0x%02X); }\n", suf[i], i, 0x8C);
1305 			printf("void vpmaskmov%s(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W%d | T_YMM, 0x%02X); }\n", suf[i], i, 0x8E);
1306 		}
1307 	}
1308 	// vpermd, vpermps
1309 	{
1310 		const struct Tbl {
1311 			uint8 code;
1312 			const char *name;
1313 			int type;
1314 		} tbl[] = {
1315 			{ 0x36, "vpermd", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1316 			{ 0x36, "vpermq", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1317 			{ 0x16, "vpermps", T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX | T_EW0 | T_B32 },
1318 			{ 0x16, "vpermpd", T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_YMM | T_B64 },
1319 		};
1320 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1321 			const Tbl& p = tbl[i];
1322 			std::string type = type2String(p.type);
1323 			printf("void %s(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, %s, 0x%02X); }\n", p.name, type.c_str(), p.code);
1324 		}
1325 	}
1326 	// vpermq, vpermpd
1327 	{
1328 		const struct Tbl {
1329 			uint8 code;
1330 			const char *name;
1331 			int type;
1332 		} tbl[] = {
1333 			{ 0x00, "vpermq", T_0F3A | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1334 			{ 0x01, "vpermpd", T_0F3A | T_66 | T_W1 | T_YMM | T_EVEX | T_EW1 | T_B64 },
1335 		};
1336 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1337 			const Tbl& p = tbl[i];
1338 			std::string type = type2String(p.type);
1339 			printf("void %s(const Ymm& y, const Operand& op, uint8 imm) { opAVX_X_XM_IMM(y, op, %s, 0x%02X, imm); }\n", p.name, type.c_str(), p.code);
1340 		}
1341 	}
1342 	// vcmpeqps
1343 	{
1344 		const char pred[32][16] = {
1345 			"eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord",
1346 			"eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt",
1347 			"true", "eq_os", "lt_oq", "le_oq", "unord_s", "neq_us", "nlt_uq", "nle_uq", "ord_s",
1348 			"eq_us", "nge_uq", "ngt_uq", "false_os", "neq_os", "ge_oq", "gt_oq", "true_us"
1349 		};
1350 		const char suf[][4] = { "pd", "ps", "sd", "ss" };
1351 		for (int i = 0; i < 4; i++) {
1352 			const char *s = suf[i];
1353 			for (int j = 0; j < 32; j++) {
1354 				if (j < 8) {
1355 					printf("void cmp%s%s(const Xmm& x, const Operand& op) { cmp%s(x, op, %d); }\n", pred[j], s, s, j);
1356 				}
1357 				printf("void vcmp%s%s(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmp%s(x1, x2, op, %d); }\n", pred[j], s, s, j);
1358 			}
1359 		}
1360 	}
1361 	// vmov(h|l)(pd|ps)
1362 	{
1363 		const struct Tbl {
1364 			bool isH;
1365 			bool isPd;
1366 			uint8 code;
1367 		} tbl[] = {
1368 			{ true, true, 0x16 },
1369 			{ true, false, 0x16 },
1370 			{ false, true, 0x12 },
1371 			{ false, false, 0x12 },
1372 		};
1373 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1374 			const Tbl& p = tbl[i];
1375 			char c = p.isH ? 'h' : 'l';
1376 			const char *suf = p.isPd ? "pd" : "ps";
1377 			const char *type = p.isPd ? "T_0F | T_66 | T_EVEX | T_EW1 | T_N8" : "T_0F | T_EVEX | T_EW0 | T_N8";
1378 			printf("void vmov%c%s(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, op1, op2, %s, 0x%02X); }\n"
1379 				, c, suf, type, p.code);
1380 			printf("void vmov%c%s(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s, 0x%02X); }\n"
1381 				, c, suf, type, p.code + 1);
1382 		}
1383 	}
1384 	// FMA
1385 	{
1386 		const struct Tbl {
1387 			uint8 code;
1388 			const char *name;
1389 			bool supportYMM;
1390 		} tbl[] = {
1391 			{ 0x08, "vfmadd", true },
1392 			{ 0x09, "vfmadd", false },
1393 			{ 0x06, "vfmaddsub", true },
1394 			{ 0x07, "vfmsubadd", true },
1395 			{ 0x0A, "vfmsub", true },
1396 			{ 0x0B, "vfmsub", false },
1397 			{ 0x0C, "vfnmadd", true },
1398 			{ 0x0D, "vfnmadd", false },
1399 			{ 0x0E, "vfnmsub", true },
1400 			{ 0x0F, "vfnmsub", false },
1401 		};
1402 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1403 			for (int j = 0; j < 2; j++) {
1404 				const char sufTbl[][2][8] = {
1405 					{ "pd", "ps" },
1406 					{ "sd", "ss" },
1407 				};
1408 				for (int k = 0; k < 3; k++) {
1409 					const struct Ord {
1410 						const char *str;
1411 						uint8 code;
1412 					} ord[] = {
1413 						{ "132", 0x90 },
1414 						{ "213", 0xA0 },
1415 						{ "231", 0xB0 },
1416 					};
1417 					int t = T_0F38 | T_66 | T_EVEX;
1418 					t |= (j == 0) ? (T_W1 | T_EW1) : (T_W0 | T_EW0);
1419 					if (tbl[i].supportYMM) t |= T_YMM;
1420 					const std::string suf = sufTbl[tbl[i].supportYMM ? 0 : 1][j];
1421 					if (suf == "pd") {
1422 						t |= T_B64;
1423 					} else if (suf == "ps") {
1424 						t |= T_B32;
1425 					} else if (suf == "sd") {
1426 						t |= T_ER_X | T_N8;
1427 					} else { // ss
1428 						t |= T_ER_X | T_N4;
1429 					}
1430 					std::string type = type2String(t);
1431 					printf("void %s%s%s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, %s, 0x%02X); }\n"
1432 						, tbl[i].name, ord[k].str, suf.c_str(), type.c_str(), tbl[i].code + ord[k].code);
1433 				}
1434 			}
1435 		}
1436 	}
1437 	// FMA others
1438 	{
1439 		printf("void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); }\n");
1440 		printf("void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); }\n");
1441 		printf("void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); }\n");
1442 		const struct Tbl {
1443 			const char *name;
1444 			uint8 code;
1445 			int type;
1446 			bool ew1;
1447 		} tbl[] = {
1448 			{ "vbroadcastss", 0x18, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N4 },
1449 			{ "vpbroadcastb", 0x78, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N1 },
1450 			{ "vpbroadcastw", 0x79, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N2 },
1451 			{ "vpbroadcastd", 0x58, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_N4 },
1452 			{ "vpbroadcastq", 0x59, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8 },
1453 		};
1454 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1455 			const Tbl& p = tbl[i];
1456 			std::string type = type2String(p.type);
1457 			printf("void %s(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) throw Error(ERR_BAD_COMBINATION); opAVX_X_XM_IMM(x, op, %s, 0x%02X); }\n", p.name, type.c_str(), p.code);
1458 		}
1459 
1460 		puts("void vextractf128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); }");
1461 		puts("void vextracti128(const Operand& op, const Ymm& y, uint8 imm) { if (!(op.isXMEM() && y.isYMM())) throw Error(ERR_BAD_COMBINATION); opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); }");
1462 		puts("void vextractps(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); }");
1463 		puts("void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); }");
1464 		puts("void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); }");
1465 		puts("void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); }");
1466 		puts("void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8 imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) throw Error(ERR_BAD_COMBINATION); opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); }");
1467 
1468 		puts("void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); }");
1469 		puts("void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); }");
1470 		puts("void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); }");
1471 		puts("void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); }");
1472 
1473 		puts("void vpextrb(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); }");
1474 		puts("void vpextrw(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } }");
1475 		puts("void vpextrd(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); }");
1476 		puts("void vpextrq(const Operand& op, const Xmm& x, uint8 imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) throw Error(ERR_BAD_COMBINATION); opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); }");
1477 
1478 		puts("void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); }");
1479 		puts("void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); }");
1480 		puts("void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); }");
1481 		puts("void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8 imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION); opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); }");
1482 
1483 		puts("void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) throw Error(ERR_BAD_COMBINATION); opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); }");
1484 
1485 	}
1486 	// (x, x, imm), (x, imm)
1487 	{
1488 		const struct Tbl {
1489 			const char *name;
1490 			uint8 code;
1491 			int idx;
1492 			int type;
1493 		} tbl[] = {
1494 			{ "pslldq", 0x73, 7, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
1495 			{ "psrldq", 0x73, 3, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
1496 			{ "psllw", 0x71, 6, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
1497 			{ "pslld", 0x72, 6, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX | T_EW0 | T_B32 },
1498 			{ "psllq", 0x73, 6, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX | T_EW1 | T_B64 },
1499 			{ "psraw", 0x71, 4, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
1500 			{ "psrad", 0x72, 4, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX | T_EW0 | T_B32 },
1501 			{ "psrlw", 0x71, 2, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX },
1502 			{ "psrld", 0x72, 2, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX | T_EW0 | T_B32 },
1503 			{ "psrlq", 0x73, 2, T_0F | T_66 | T_YMM | T_EVEX | T_MEM_EVEX | T_EW1 | T_B64 },
1504 		};
1505 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1506 			const Tbl& p = tbl[i];
1507 			std::string type = type2String(p.type);
1508 			printf("void v%s(const Xmm& x, const Operand& op, uint8 imm) { opAVX_X_X_XM(Xmm(x.getKind(), %d), x, op, %s, 0x%02X, imm); }\n", p.name, p.idx, type.c_str(), p.code);
1509 		}
1510 	}
1511 	// 4-op
1512 	{
1513 		const struct Tbl {
1514 			const char *name;
1515 			uint8 code;
1516 		} tbl[] = {
1517 			{ "vblendvpd", 0x4B },
1518 			{ "vblendvps", 0x4A },
1519 			{ "vpblendvb", 0x4C },
1520 		};
1521 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1522 			const Tbl& p = tbl[i];
1523 			printf("void %s(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x%02X, x4.getIdx() << 4); }\n", p.name, p.code);
1524 		}
1525 	}
1526 	// mov
1527 	{
1528 		printf("void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); }\n");
1529 		printf("void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); }\n");
1530 
1531 		printf("void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); }\n");
1532 		printf("void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); }\n");
1533 		printf("void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); }\n");
1534 
1535 		printf("void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); }\n");
1536 		printf("void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); }\n");
1537 
1538 		printf("void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); }\n");
1539 		printf("void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); }\n");
1540 
1541 		puts("void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); }");
1542 		puts("void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); }");
1543 		puts("void vmovntps(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_YMM | T_EVEX | T_EW0, 0x2B); }");
1544 		puts("void vmovntdqa(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0, 0x2A); }");
1545 
1546 		// vmovsd, vmovss
1547 		for (int i = 0; i < 2; i++) {
1548 			char c1 = i == 0 ? 'd' : 's';
1549 			int type = T_0F | T_EVEX;
1550 			type |= i == 0 ? (T_F2 | T_EW1 | T_N8) : (T_F3 | T_EW0 | T_N4);
1551 			std::string s = type2String(type);
1552 			printf("void vmovs%c(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION); opAVX_X_X_XM(x1, x2, op, %s, 0x10); }\n", c1, s.c_str());
1553 			printf("void vmovs%c(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, %s, 0x10); }\n", c1, s.c_str());
1554 			printf("void vmovs%c(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, %s | T_M_K, 0x11); }\n", c1, s.c_str());
1555 		}
1556 	}
1557 	// cvt
1558 	{
1559 		puts("void vcvtss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_ER_X | T_N8, 0x2D); }");
1560 		puts("void vcvttss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_SAE_X | T_N8, 0x2C); }");
1561 		puts("void vcvtsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_ER_X, 0x2D); }");
1562 		puts("void vcvttsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, 0x2C); }");
1563 
1564 		puts("void vcvtsi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F3 | T_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }");
1565 		puts("void vcvtsi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F2 | T_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); }");
1566 
1567 
1568 		puts("void vcvtps2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x5A); }");
1569 		puts("void vcvtdq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0xE6); }");
1570 
1571 		puts("void vcvtpd2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5A); }");
1572 		puts("void vcvtpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0xE6); }");
1573 
1574 		puts("void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); }");
1575 
1576 		puts("void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); }");
1577 		puts("void vcvtps2ph(const Operand& op, const Xmm& x, uint8 imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x1D, imm); }");
1578 
1579 	}
1580 	// haswell gpr(reg, reg, r/m)
1581 	{
1582 		const struct Tbl {
1583 			const char *name;
1584 			int type;
1585 			uint8 code;
1586 		} tbl[] = {
1587 			{ "andn", T_0F38, 0xF2 },
1588 			{ "mulx", T_F2 | T_0F38, 0xF6 },
1589 			{ "pdep", T_F2 | T_0F38, 0xF5 },
1590 			{ "pext", T_F3 | T_0F38, 0xF5 },
1591 		};
1592 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1593 			const Tbl& p = tbl[i];
1594 			printf("void %s(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, %s, 0x%x, true); }\n", p.name, type2String(p.type).c_str(), p.code);
1595 		}
1596 	}
1597 	// gpr(reg, r/m, reg)
1598 	{
1599 		const struct Tbl {
1600 			const char *name;
1601 			int type;
1602 			uint8 code;
1603 		} tbl[] = {
1604 			{ "bextr", T_0F38, 0xF7 },
1605 			{ "bzhi", T_0F38, 0xF5 },
1606 			{ "sarx", T_0F38 | T_F3, 0xF7 },
1607 			{ "shlx", T_0F38 | T_66, 0xF7 },
1608 			{ "shrx", T_0F38 | T_F2, 0xF7 },
1609 		};
1610 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1611 			const Tbl& p = tbl[i];
1612 			printf("void %s(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, %s, 0x%x, false); }\n", p.name, type2String(p.type).c_str(), p.code);
1613 		}
1614 		puts("void rorx(const Reg32e& r, const Operand& op, uint8 imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); }");
1615 	}
1616 	// gpr(reg, r/m)
1617 	{
1618 		const struct Tbl {
1619 			const char *name;
1620 			int type;
1621 			uint8 code;
1622 			uint8 idx;
1623 		} tbl[] = {
1624 			{ "blsi", T_0F38, 0xF3, 3 },
1625 			{ "blsmsk", T_0F38, 0xF3, 2 },
1626 			{ "blsr", T_0F38, 0xF3, 1 },
1627 		};
1628 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1629 			const Tbl& p = tbl[i];
1630 			printf("void %s(const Reg32e& r, const Operand& op) { opGpr(Reg32e(%d, r.getBit()), op, r, %s, 0x%x, false); }\n", p.name, p.idx, type2String(p.type).c_str(), p.code);
1631 		}
1632 	}
1633 	// gather
1634 	{
1635 		const int y_vx_y = 0;
1636 		const int y_vy_y = 1;
1637 		const int x_vy_x = 2;
1638 		const struct Tbl {
1639 			const char *name;
1640 			uint8 code;
1641 			int w;
1642 			int mode;
1643 		} tbl[] = {
1644 			{ "vgatherdpd", 0x92, 1, y_vx_y },
1645 			{ "vgatherqpd", 0x93, 1, y_vy_y },
1646 			{ "vgatherdps", 0x92, 0, y_vy_y },
1647 			{ "vgatherqps", 0x93, 0, x_vy_x },
1648 			{ "vpgatherdd",  0x90, 0, y_vy_y },
1649 			{ "vpgatherqd",  0x91, 0, x_vy_x },
1650 			{ "vpgatherdq",  0x90, 1, y_vx_y },
1651 			{ "vpgatherqq",  0x91, 1, y_vy_y },
1652 		};
1653 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1654 			const Tbl& p = tbl[i];
1655 			printf("void %s(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W%d, 0x%x, %d); }\n", p.name, p.w, p.code, p.mode);
1656 		}
1657 	}
1658 }
1659 
put32()1660 void put32()
1661 {
1662 	put_jREGz("cx", true);
1663 	put_jREGz("ecx", false);
1664 
1665 	const GenericTbl tbl[] = {
1666 		{ "aaa", 0x37 },
1667 		{ "aad", 0xD5, 0x0A },
1668 		{ "aam", 0xD4, 0x0A },
1669 		{ "aas", 0x3F },
1670 		{ "daa", 0x27 },
1671 		{ "das", 0x2F },
1672 		{ "popad", 0x61 },
1673 		{ "popfd", 0x9D },
1674 		{ "pusha", 0x60 },
1675 		{ "pushad", 0x60 },
1676 		{ "pushfd", 0x9C },
1677 		{ "popa", 0x61 },
1678 	};
1679 	putGeneric(tbl, NUM_OF_ARRAY(tbl));
1680 }
1681 
put64()1682 void put64()
1683 {
1684 	put_jREGz("ecx", true);
1685 	put_jREGz("rcx", false);
1686 
1687 	const GenericTbl tbl[] = {
1688 		{ "cdqe", 0x48, 0x98 },
1689 		{ "cqo", 0x48, 0x99 },
1690 		{ "cmpsq", 0x48, 0xA7 },
1691 		{ "movsq", 0x48, 0xA5 },
1692 		{ "scasq", 0x48, 0xAF },
1693 		{ "stosq", 0x48, 0xAB },
1694 	};
1695 	putGeneric(tbl, NUM_OF_ARRAY(tbl));
1696 
1697 	puts("void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); }");
1698 	puts("void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); }");
1699 	puts("void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); }");
1700 	puts("void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) throw Error(ERR_BAD_COMBINATION); opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); }");
1701 	puts("void pextrq(const Operand& op, const Xmm& xmm, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); }");
1702 	puts("void pinsrq(const Xmm& xmm, const Operand& op, uint8 imm) { if (!op.isREG(64) && !op.isMEM()) throw Error(ERR_BAD_COMBINATION); opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); }");
1703 
1704 	puts("void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); }");
1705 	puts("void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); }");
1706 	puts("void vcvtsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_ER_X, 0x2D); }");
1707 	puts("void vcvttsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_SAE_X, 0x2C); }");
1708 
1709 	puts("void vmovq(const Xmm& x, const Reg64& r) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x6E); }");
1710 	puts("void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); }");
1711 }
1712 
putFixed()1713 void putFixed()
1714 {
1715 	puts("#ifdef XBYAK64");
1716 	put64();
1717 	puts("#else");
1718 	put32();
1719 	puts("#endif");
1720 	puts("#ifndef XBYAK_NO_OP_NAMES");
1721 	const char *tbl[] = {
1722 		"and", "or", "xor",
1723 	};
1724 	for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1725 		const char *name = tbl[i];
1726 		printf("void %s(const Operand& op1, const Operand& op2) { %s_(op1, op2); }\n", name, name);
1727 		printf("void %s(const Operand& op, uint32 imm) { %s_(op, imm); }\n", name, name);
1728 	}
1729 	puts("void not(const Operand& op) { not_(op); }");
1730 	puts("#endif");
1731 }
1732 
putOmit()1733 void putOmit()
1734 {
1735 	puts("void vpinsrb(const Xmm& x, const Operand& op, uint8 imm) { vpinsrb(x, x, op, imm); }");
1736 	puts("void vpinsrd(const Xmm& x, const Operand& op, uint8 imm) { vpinsrd(x, x, op, imm); }");
1737 	puts("void vpinsrq(const Xmm& x, const Operand& op, uint8 imm) { vpinsrq(x, x, op, imm); }");
1738 	puts("void vpinsrw(const Xmm& x, const Operand& op, uint8 imm) { vpinsrw(x, x, op, imm); }");
1739 
1740 	puts("void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); }");
1741 	puts("void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); }");
1742 	{
1743 		const char pred[32][16] = {
1744 			"eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord",
1745 			"eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt",
1746 			"true", "eq_os", "lt_oq", "le_oq", "unord_s", "neq_us", "nlt_uq", "nle_uq", "ord_s",
1747 			"eq_us", "nge_uq", "ngt_uq", "false_os", "neq_os", "ge_oq", "gt_oq", "true_us"
1748 		};
1749 		const char suf[][4] = { "pd", "ps", "sd", "ss" };
1750 		for (int i = 0; i < 4; i++) {
1751 			const char *s = suf[i];
1752 			for (int j = 0; j < 32; j++) {
1753 				printf("void vcmp%s%s(const Xmm& x, const Operand& op) { vcmp%s%s(x, x, op); }\n", pred[j], s, pred[j], s);
1754 			}
1755 		}
1756 	}
1757 	{
1758 		const char *tbl[] = {
1759 			"pslldq",
1760 			"psrldq",
1761 			"psllw",
1762 			"pslld",
1763 			"psllq",
1764 			"psraw",
1765 			"psrad",
1766 			"psrlw",
1767 			"psrld",
1768 			"psrlq",
1769 		};
1770 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1771 			const char *name = tbl[i];
1772 			printf("void v%s(const Xmm& x, uint8 imm) { v%s(x, x, imm); }\n", name, name);
1773 		}
1774 	}
1775 	{
1776 		const char *tbl[] = {
1777 			"vblendvpd",
1778 			"vblendvps",
1779 			"vpblendvb",
1780 		};
1781 		for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
1782 			const char *name = tbl[i];
1783 			printf("void %s(const Xmm& x1, const Operand& op, const Xmm& x4) { %s(x1, x1, op, x4); }\n", name, name);
1784 		}
1785 	}
1786 	putX_X_XM(true);
1787 }
1788 
main(int argc,char * argv[])1789 int main(int argc, char *argv[])
1790 {
1791 	std::string mode = argc == 2 ? argv[1] : "";
1792 	if (mode == "") {
1793 		put();
1794 	} else if (mode == "fixed") {
1795 		putFixed();
1796 	} else {
1797 		putOmit();
1798 	}
1799 }
1800