rework the verifier to prepare for loop cutting
[ajla.git] / c2-x86.inc
blob1676c34b196cbbe60db2a916610295bac7014b6d
1 /*
2  * Copyright (C) 2024 Mikulas Patocka
3  *
4  * This file is part of Ajla.
5  *
6  * Ajla is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation, either version 3 of the License, or (at your option) any later
9  * version.
10  *
11  * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Ajla. If not, see <https://www.gnu.org/licenses/>.
17  */
19 #define test_evex       0
21 #define X86_ALU_RM8_R8                  0x00
22 #define X86_ALU_RM16_R16                0x01
23 #define X86_ALU_R8_RM8                  0x02
24 #define X86_ALU_R16_RM16                0x03
25 #define X86_ALU_AL_IMM8                 0x04
26 #define X86_ALU_AX_IMM16                0x05
27 #define X86_0F                          0x0f
28 #define X86_ES                          0x26
29 #define X86_CS                          0x2e
30 #define X86_SS                          0x36
31 #define X86_DS                          0x3e
32 #define X86_REX                         0x40
33 #define  X86_REX_B                              0x01
34 #define  X86_REX_X                              0x02
35 #define  X86_REX_R                              0x04
36 #define  X86_REX_W                              0x08
37 #define X86_INC_R16                     0x40
38 #define X86_DEC_R16                     0x48
39 #define X86_PUSH_R16                    0x50
40 #define X86_POP_R16                     0x58
41 #define X86_EVEX                        0x62
42 #define X86_MOVSXD                      0x63
43 #define X86_FS                          0x64
44 #define X86_GS                          0x65
45 #define X86_OP_SIZE                     0x66
46 #define X86_PUSH_IMM16                  0x68
47 #define X86_IMUL_R16_RM16_IMM16         0x69
48 #define X86_PUSH_IMM8                   0x6a
49 #define X86_IMUL_R16_RM16_IMM8          0x6b
50 #define X86_JCC_8                       0x70
51 #define X86_ALU_RM8_IMM8                0x80
52 #define X86_ALU_RM16_IMM16              0x81
53 #define X86_ALU_RM16_IMM8               0x83
54 #define X86_TEST_RM8_R8                 0x84
55 #define X86_TEST_RM16_R16               0x85
56 #define X86_MOV_RM8_R8                  0x88
57 #define X86_MOV_RM16_R16                0x89
58 #define X86_MOV_R8_RM8                  0x8a
59 #define X86_MOV_R16_RM16                0x8b
60 #define X86_LEA_R16_RM16                0x8d
61 #define X86_8F                          0x8f
62 #define  X86_8F_POP                             0x0
63 #define X86_CBW                         0x98
64 #define X86_CWD                         0x99
65 #define X86_MOV_AL_M16                  0xa0
66 #define X86_MOV_AX_M16                  0xa1
67 #define X86_MOV_M16_AL                  0xa2
68 #define X86_MOV_M16_AX                  0xa3
69 #define X86_MOVSB                       0xa4
70 #define X86_TEST_AL_IMM8                0xa8
71 #define X86_TEST_AX_IMM16               0xa9
72 #define X86_STOSB                       0xaa
73 #define X86_MOV_R16_IMM16               0xb8
74 #define X86_ROT_RM8_IMM8                0xc0
75 #define X86_ROT_RM16_IMM8               0xc1
76 #define X86_RET_IMM16                   0xc2
77 #define X86_RET                         0xc3
78 #define X86_VEX_3                       0xc4
79 #define X86_VEX_2                       0xc5
80 #define X86_MOV_RM8_IMM8                0xc6
81 #define X86_MOV_RM16_IMM16              0xc7
82 #define  X86_MOV_R16_IMM16_REG                  0x0
83 #define X86_ROT_RM8_1                   0xd0
84 #define X86_ROT_RM16_1                  0xd1
85 #define X86_ROT_RM8_CL                  0xd2
86 #define X86_ROT_RM16_CL                 0xd3
87 #define X86_REX2                        0xd5
88 #define  X86_REX2_B3                            0x01
89 #define  X86_REX2_X3                            0x02
90 #define  X86_REX2_R3                            0x04
91 #define  X86_REX2_W                             0x08
92 #define  X86_REX2_B4                            0x10
93 #define  X86_REX2_X4                            0x20
94 #define  X86_REX2_R4                            0x40
95 #define  X86_REX2_M0                            0x80
96 #define X86_JMP_16                      0xe9
97 #define X86_JMP_8                       0xeb
98 #define X86_REPNE                       0xf2
99 #define X86_REPE                        0xf3
100 #define X86_F6                          0xf6
101 #define  X86_F6_TEST_RM8_IMM8                   0x0
102 #define  X86_F6_NOT_RM8                         0x2
103 #define  X86_F6_NEG_RM8                         0x3
104 #define  X86_F6_MUL_RM8                         0x4
105 #define  X86_F6_IMUL_RM8                        0x5
106 #define  X86_F6_DIV_RM8                         0x6
107 #define  X86_F6_IDIV_RM8                        0x7
108 #define X86_F7                          0xf7
109 #define  X86_F7_TEST_RM16_IMM16                 0x0
110 #define  X86_F7_NOT_RM16                        0x2
111 #define  X86_F7_NEG_RM16                        0x3
112 #define  X86_F7_MUL_RM16                        0x4
113 #define  X86_F7_IMUL_RM16                       0x5
114 #define  X86_F7_DIV_RM16                        0x6
115 #define  X86_F7_IDIV_RM16                       0x7
116 #define X86_FE                          0xfe
117 #define  X86_FE_INC_RM8                         0x0
118 #define  X86_FE_DEC_RM8                         0x1
119 #define X86_FF                          0xff
120 #define  X86_FF_INC_RM16                        0x0
121 #define  X86_FF_DEC_RM16                        0x1
122 #define  X86_FF_CALL_INDIRECT                   0x2
123 #define  X86_FF_JMP_INDIRECT                    0x4
124 #define  X86_FF_PUSH                            0x6
126 #define X86_0F_MOVSS_X128_M32           0x10
127 #define X86_0F_MOVSS_M32_X128           0x11
128 #define X86_0F_MOVAPS_X128_M128         0x28
129 #define X86_0F_MOVAPS_M128_X128         0x29
130 #define X86_0F_CVTSI2SS_X128_RM32       0x2a
131 #define X86_0F_CVTTSS2SI_X128_RM32      0x2c
132 #define X86_0F_UCOMISS_X128_RM32        0x2e
133 #define X86_0F_38                       0x38
134 #define X86_0F_3A                       0x3a
135 #define X86_0F_CMOVCC_R16_RM16          0x40
136 #define X86_0F_SQRTPS_X128_M32          0x51
137 #define X86_0F_ANDPS_X128_M128          0x54
138 #define X86_0F_ANDNPS_X128_M128         0x55
139 #define X86_0F_ORPS_X128_M128           0x56
140 #define X86_0F_XORPS_X128_M128          0x57
141 #define X86_0F_ADDPS_X128_M32           0x58
142 #define X86_0F_MULPS_X128_M32           0x59
143 #define X86_0F_SUBPS_X128_M32           0x5c
144 #define X86_0F_DIVPS_X128_M32           0x5e
145 #define X86_0F_MOVD_X128_RM32           0x6e
146 #define X86_0F_MOVD_RM32_X128           0x7e
147 #define X86_0F_JCC_16                   0x80
148 #define X86_0F_SETCC_RM8                0x90
149 #define X86_0F_BT_RM16_R16              0xa3
150 #define X86_0F_BTS_RM16_R16             0xab
151 #define X86_0F_BTR_RM16_R16             0xb3
152 #define X86_0F_BTX_RM16_IMM8            0xba
153 #define  X86_0F_BTX_BT_RM16_IMM8                0x4
154 #define  X86_0F_BTX_BTS_RM16_IMM8               0x5
155 #define  X86_0F_BTX_BTR_RM16_IMM8               0x6
156 #define  X86_0F_BTX_BTC_RM16_IMM8               0x7
157 #define X86_0F_BSWAP                    0xc8
158 #define X86_0F_BTC_RM16_R16             0xbb
159 #define X86_0F_IMUL_R16_RM16            0xaf
160 #define X86_0F_MOVZX_R16_RM8            0xb6
161 #define X86_0F_MOVZX_R16_RM16           0xb7
162 #define X86_0F_POPCNT_R16_RM16          0xb8
163 #define X86_0F_BSF_R16_RM16             0xbc
164 #define X86_0F_BSR_R16_RM16             0xbd
165 #define X86_0F_MOVSX_R16_RM8            0xbe
166 #define X86_0F_MOVSX_R16_RM16           0xbf
167 #define X86_0F_PINSRW_X128_RM16_IMM8    0xc4
169 #define X86_0F_38_CVTPH2PS_X128_RM64    0x13
170 #define X86_0F_38_ROTX                  0xf7
172 #define X86_0F_3A_ROUNDSS_X128_M32      0x0a
173 #define X86_0F_3A_RNDSCALESH_X128_M16   0x0a
174 #define X86_0F_3A_ROUNDSD_X128_M64      0x0b
175 #define X86_0F_3A_PEXTRW_RM16_X128_IMM8 0x15
176 #define X86_0F_3A_CVTPS2PH_RM64_X128    0x1d
178 #define X86_LEGACY_EVEX_SETCC_R64       0x40
180 #define X86_MAP5_MOVSH_X128_M16         0x10
181 #define X86_MAP5_MOVSH_M16_X128         0x11
182 #define X86_MAP5_CVTSI2SH_X128_RM16     0x2a
183 #define X86_MAP5_UCOMISH_X128_RM16      0x2e
184 #define X86_MAP5_CVTTSH2SI_X128_RM16    0x2c
185 #define X86_MAP5_SQRTPH_X128_M16        0x51
186 #define X86_MAP5_ADDPH_X128_M16         0x58
187 #define X86_MAP5_MULPH_X128_M16         0x59
188 #define X86_MAP5_SUBPH_X128_M16         0x5c
189 #define X86_MAP5_DIVPH_X128_M16         0x5e
191 #define X87_FLD_RM32                    0xd9
192 #define  X87_FLD_RM32_X                         0x0
193 #define X87_FLDCW                       0xd9
194 #define  X87_FLDCW_X                            0x5
195 #define X87_FILD_M32                    0xdb
196 #define  X87_FILD_M32_X                         0x0
197 #define X87_FISTTP_M32                  0xdb
198 #define  X87_FISTTP_M32_X                       0x1
199 #define X87_FISTP_M32                   0xdb
200 #define  X87_FISTP_M32_X                        0x3
201 #define X87_FLD_M80                     0xdb
202 #define  X87_FLD_M80_X                          0x5
203 #define X87_FLD_M64                     0xdd
204 #define  X87_FLD_M64_X                          0x0
205 #define X87_FSTP_M32                    0xd9
206 #define  X87_FSTP_M32_X                         0x3
207 #define X87_FSTP_M80                    0xdb
208 #define  X87_FSTP_M80_X                         0x7
209 #define X87_FSTP_RM64                   0xdd
210 #define  X87_FSTP_RM64_X                        0x3
211 #define X87_FALU_ST_RM32                0xd8
212 #define X87_FCHS                        0xd9
213 #define  X87_FCHS_2                             0xe0
214 #define X87_FSQRT                       0xd9
215 #define  X87_FSQRT_2                            0xfa
216 #define X87_FRNDINT                     0xd9
217 #define  X87_FRNDINT_2                          0xfc
218 #define X87_FALU_ST_M64                 0xdc
219 #define X87_FALU_STi_ST                 0xdc
220 #define X87_FISTTP_M64                  0xdd
221 #define  X87_FISTTP_M64_X                       0x1
222 #define X87_FALUP_STi_ST0               0xde
223 #define  X87_ALU_ADD                            0x0
224 #define  X87_ALU_MUL                            0x1
225 #define  X87_ALU_FCOM                           0x2
226 #define  X87_ALU_FCOMP                          0x3
227 #define  X87_ALU_SUBR                           0x4
228 #define  X87_ALU_SUB                            0x5
229 #define  X87_ALU_DIVR                           0x6
230 #define  X87_ALU_DIV                            0x7
231 #define X87_FCOMPP                      0xde
232 #define  X87_FCOMPP_2                           0xd9
233 #define X87_FILD_M16                    0xdf
234 #define  X87_FILD_M16_X                         0x0
235 #define X87_FISTTP_M16                  0xdf
236 #define  X87_FISTTP_M16_X                       0x1
237 #define X87_FISTP_M16                   0xdf
238 #define  X87_FISTP_M16_X                        0x3
239 #define X87_FILD_M64                    0xdf
240 #define  X87_FILD_M64_X                         0x5
241 #define X87_FISTP_M64                   0xdf
242 #define  X87_FISTP_M64_X                        0x7
243 #define X87_FNSTSW                      0xdf
244 #define  X87_FNSTSW_2                           0xe0
245 #define X87_FCOMIP                      0xdf
246 #define  X87_FCOMIP_2                           0xf0
248 #define SSE_PREFIX_NONE                 0
249 #define SSE_PREFIX_66                   1
250 #define SSE_PREFIX_F3                   2
251 #define SSE_PREFIX_F2                   3
253 #define PREFIX_NONE                     0
254 #define PREFIX_0F                       1
255 #define PREFIX_0F_38                    2
256 #define PREFIX_0F_3A                    3
257 #define PREFIX_LEGACY_EVEX              4
258 #define PREFIX_MAP5                     5
260 static bool attr_w cgen_rex2(struct codegen_context attr_unused *ctx, uint8_t rex2)
262 #ifdef ARCH_X86_32
263         internal(file_line, "cgen_rex: attempting to generate rex in 32-bit mode: %02x", rex2);
264         return false;
265 #else
266         if (!(rex2 & 0xf0)) {
267                 cgen_one(X86_REX | rex2);
268         } else {
269                 if (unlikely(!cpu_test_feature(CPU_FEATURE_apx)))
270                         internal(file_line, "cgen_rex2: attempting to generate rex2 without apx: %02x", rex2);
271                 cgen_one(X86_REX2);
272                 cgen_one(rex2);
273         }
274         return true;
275 #endif
278 #define force_vex                       0x10000
279 #define force_evex                      0x20000
280 #define force_ndd                       0x40000
281 #define SSE_PREFIX_W                    0x80000
283 static bool attr_w cgen_rm_insn(struct codegen_context *ctx, int32_t sse_prefix, uint8_t prefix, uint8_t opcode, unsigned size, bool reg_is_reg, uint8_t reg, uint8_t *arg)
285         uint8_t rex2, mod, rm;
286         int16_t sib;
287         int64_t imm = 0;        /* avoid warning */
288         uint8_t addr_size;
289         uint8_t arg_reg;
290         bool need_rex;
292         if (unlikely(R_IS_XMM(reg)))
293                 reg -= R_XMM0;
294         if (unlikely(R_IS_XMM(arg[0]))) {
295                 arg_reg = arg[0] - R_XMM0;
296                 arg = &arg_reg;
297         }
298         if (unlikely(!R_IS_GPR(reg)))
299                 internal(file_line, "cgen_rm_insn: invalid register %02x", reg);
301         sib = -1;
302         rex2 = 0;
303         if (size == OP_SIZE_8)
304                 rex2 |= X86_REX2_W;
305         if (reg & 8)
306                 rex2 |= X86_REX2_R3;
307         if (reg & 16)
308                 rex2 |= X86_REX2_R4;
309         if (arg[0] < 0x40) {
310                 if (arg[0] & 8)
311                         rex2 |= X86_REX2_B3;
312                 if (arg[0] & 16)
313                         rex2 |= X86_REX2_B4;
314                 mod = 0xc0;
315                 rm = arg[0] & 7;
316                 addr_size = 0;
317         } else {
318                 uint8_t *imm_ptr = arg + arg_size(arg[0]) - 8;
319                 imm = get_imm(imm_ptr);
320                 if (unlikely(!imm_is_32bit(imm)))
321                         internal(file_line, "cgen_rm_insn: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
322                 if (arg[0] == ARG_ADDRESS_0) {
323 address_0:
324                         addr_size = 4;
325                         mod = 0x00;
326                         rm = 0x4;
327                         sib = 0x25;
328                         goto gen;
329                 }
330                 if (!imm) {
331                         addr_size = 0;
332                 } else if (imm >= -0x80 && imm <= 0x7f) {
333                         addr_size = 1;
334                 } else {
335                         addr_size = 4;
336                 }
337                 if ((arg[1] & 7) == 0x5 && addr_size == 0)
338                         addr_size = 1;
339                 if (addr_size == 0)
340                         mod = 0x00;
341                 else if (addr_size == 1)
342                         mod = 0x40;
343                 else
344                         mod = 0x80;
345                 if (arg[0] == ARG_ADDRESS_1) {
346                         if (reg_is_segment(arg[1])) {
347                                 static const uint8_t segments[6] = { X86_ES, X86_CS, X86_SS, X86_DS, X86_FS, X86_GS };
348                                 cgen_one(segments[arg[1] - R_ES]);
349                                 goto address_0;
350                         }
351                         if (arg[1] & 8)
352                                 rex2 |= X86_REX2_B3;
353                         if (arg[1] & 16)
354                                 rex2 |= X86_REX2_B4;
355                         if ((arg[1] & 7) == 0x4) {
356                                 rm = 0x4;
357                                 sib = 0x24;
358                                 goto gen;
359                         }
360                         rm = arg[1] & 7;
361                         goto gen;
362                 }
363                 if (arg[0] >= ARG_ADDRESS_1_2 && arg[0] <= ARG_ADDRESS_1_8) {
364                         if (unlikely(arg[1] == R_SP))
365                                 internal(file_line, "cgen_rm_insn: attemptint to scale SP");
366                         if (arg[1] & 8)
367                                 rex2 |= X86_REX2_X3;
368                         if (arg[1] & 16)
369                                 rex2 |= X86_REX2_X4;
370                         addr_size = 4;
371                         mod = 0x00;
372                         rm = 0x4;
373                         sib = ((arg[0] - ARG_ADDRESS_1) << 6) | ((arg[1] & 7) << 3) | 0x5;
374                         goto gen;
375                 }
376                 if (arg[0] >= ARG_ADDRESS_2 && arg[0] <= ARG_ADDRESS_2_8) {
377                         if (unlikely(arg[2] == R_SP))
378                                 internal(file_line, "cgen_rm_insn: attemptint to scale SP");
379                         if (arg[1] & 8)
380                                 rex2 |= X86_REX2_B3;
381                         if (arg[1] & 16)
382                                 rex2 |= X86_REX2_B4;
383                         if (arg[2] & 8)
384                                 rex2 |= X86_REX2_X3;
385                         if (arg[2] & 16)
386                                 rex2 |= X86_REX2_X4;
387                         rm = 0x4;
388                         sib = ((arg[0] - ARG_ADDRESS_2) << 6) | ((arg[2] & 7) << 3) | (arg[1] & 7);
389                         goto gen;
390                 }
391                 internal(file_line, "cgen_rm_insn: invalid argument %02x", arg[0]);
392         }
394 gen:
395         if (unlikely(sse_prefix >= 0)) {
396                 if (likely(cpu_test_feature(CPU_FEATURE_avx)) || (sse_prefix & (force_vex | force_evex | force_ndd))) {
397                         if (rex2 & 0xf0 || sse_prefix & 0x1000 || sse_prefix & (force_evex | force_ndd) || test_evex) {
398                                 /*debug("evex: %02x, %02x, %02x", reg, (sse_prefix >> 8) & 0x1f, arg[0]);*/
399                                 if (!(sse_prefix & (force_vex | force_ndd))) {
400                                         if (sse_prefix & SSE_PREFIX_W)
401                                                 rex2 |= X86_REX2_W;
402                                         if (addr_size == 1 && imm) {
403                                                 addr_size = 4;
404                                                 mod = (mod & ~0xc0) | 0x80;
405                                         }
406                                         if (sib == -1) {
407                                                 if (rex2 & X86_REX2_B4) {
408                                                         rex2 &= ~X86_REX2_B4;
409                                                         rex2 |= X86_REX2_X3;
410                                                 }
411                                         }
412                                 }
413                                 cgen_one(X86_EVEX);
414                                 cgen_one(((~rex2 & (X86_REX2_R3 | X86_REX2_X3 | X86_REX2_B3)) << 5) | !(rex2 & X86_REX2_R4) << 4 | !!(rex2 & X86_REX2_B4) << 3 | prefix);
415                                 cgen_one((rex2 & X86_REX2_W) << 4 | (~(sse_prefix >> 8) & 0xf) << 3 | !(rex2 & X86_REX2_X4) << 2 | (sse_prefix & 3));
416                                 cgen_one(!!(sse_prefix & force_ndd) << 4 | !((sse_prefix >> 8) & 0x10) << 3);
417                         } else if ((rex2 & (X86_REX2_X3 | X86_REX2_B3 | X86_REX2_W)) == 0 && prefix == PREFIX_0F) {
418                                 cgen_one(X86_VEX_2);
419                                 cgen_one((~rex2 & X86_REX2_R3) << 5 | (~(sse_prefix >> 8) & 0xf) << 3 | (sse_prefix & 3));
420                         } else {
421                                 cgen_one(X86_VEX_3);
422                                 cgen_one((~rex2 & (X86_REX2_R3 | X86_REX2_X3 | X86_REX2_B3)) << 5 | prefix);
423                                 cgen_one((rex2 & X86_REX2_W) << 4 | (~(sse_prefix >> 8) & 0xf) << 3 | (sse_prefix & 3));
424                         }
425                         goto avx_done;
426                 }
427                 switch (sse_prefix & 3) {
428                         case SSE_PREFIX_66:     cgen_one(X86_OP_SIZE); break;
429                         case SSE_PREFIX_F3:     cgen_one(X86_REPE); break;
430                         case SSE_PREFIX_F2:     cgen_one(X86_REPNE); break;
431                 }
432         } else {
433                 if (size == OP_SIZE_2)
434                         cgen_one(X86_OP_SIZE);
435         }
436         need_rex = rex2 != 0;
437         need_rex |= size == OP_SIZE_1 && ((reg_is_reg && !reg_is_fp(reg) && reg >= 4) || (mod == 0xc0 && !reg_is_fp(arg[0]) && arg[0] >= 4));
438         if (prefix == PREFIX_0F && (opcode == X86_0F_MOVZX_R16_RM8 || opcode == X86_0F_MOVSX_R16_RM8)) {
439                 need_rex |= mod == 0xc0 && arg[0] >= 4;
440         }
441         if (rex2 & 0xf0) {
442                 switch (prefix) {
443                         case PREFIX_NONE:
444                                 break;
445                         case PREFIX_0F:
446                                 prefix = PREFIX_NONE;
447                                 rex2 |= X86_REX2_M0;
448                                 break;
449                         default:
450                                 internal(file_line, "cgen_rm_insn: invalid prefix %u", prefix);
451                 }
452         }
453         if (need_rex)
454                 g(cgen_rex2(ctx, rex2));
456         switch (prefix) {
457                 case PREFIX_NONE:
458                         break;
459                 case PREFIX_0F:
460                         cgen_one(X86_0F);
461                         break;
462                 case PREFIX_0F_38:
463                         cgen_one(X86_0F);
464                         cgen_one(X86_0F_38);
465                         break;
466                 case PREFIX_0F_3A:
467                         cgen_one(X86_0F);
468                         cgen_one(X86_0F_3A);
469                         break;
470                 default:
471                         internal(file_line, "cgen_rm_insn: invalid prefix %u", prefix);
472         }
473 avx_done:
474         cgen_one(opcode);
475         cgen_one(mod | ((reg & 7) << 3) | (rm & 7));
476         if (sib >= 0)
477                 cgen_one(sib);
478         switch (addr_size) {
479                 case 1:
480                         cgen_one(imm);
481                         break;
482                 case 4:
483                         cgen_four(imm);
484                         break;
485         }
486         return true;
489 static bool attr_w cgen_sse_insn(struct codegen_context *ctx, unsigned sse_prefix, unsigned sse_op_map, uint8_t opcode, bool wide, uint8_t reg, uint8_t reg2, uint8_t *arg)
491         g(cgen_rm_insn(ctx, sse_prefix + (reg2 << 8), sse_op_map, opcode, !wide ? OP_SIZE_4 : OP_SIZE_8, true, reg, arg));
492         return true;
495 static bool attr_w cgen_push(struct codegen_context *ctx, unsigned aux)
497         uint8_t *arg1 = ctx->code_position;
498         ctx->code_position += arg_size(*arg1);
499         if (likely(R_IS_GPR(arg1[0]))) {
500                 uint8_t rex2 = 0;
501                 if (arg1[0] & 8)
502                         rex2 |= X86_REX2_B3;
503                 if (arg1[0] & 16)
504                         rex2 |= X86_REX2_B4;
505                 if (aux)
506                         rex2 |= X86_REX2_W;
507                 if (aux) {
508                         cgen_one(X86_REX2);
509                         cgen_one(rex2);
510                 } else if (rex2) {
511                         g(cgen_rex2(ctx, rex2));
512                 }
513                 cgen_one(X86_PUSH_R16 + (arg1[0] & 7));
514                 return true;
515         }
516         if (arg1[0] == ARG_IMM) {
517                 int64_t imm;
518                 imm = get_imm(&arg1[1]);
519                 if (unlikely(!imm_is_32bit(imm)))
520                         internal(file_line, "cgen_push: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
521                 if (imm >= -0x80 && imm <= 0x7f) {
522                         cgen_one(X86_PUSH_IMM8);
523                         cgen_one(imm);
524                         return true;
525                 } else {
526                         cgen_one(X86_PUSH_IMM16);
527                         cgen_four(imm);
528                         return true;
529                 }
530         }
531         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_FF, OP_SIZE_4, false, X86_FF_PUSH, arg1));
532         return true;
535 static bool attr_w cgen_pop(struct codegen_context *ctx, unsigned aux)
537         uint8_t *arg1 = ctx->code_position;
538         ctx->code_position += arg_size(*arg1);
539         if (likely(R_IS_GPR(arg1[0]))) {
540                 uint8_t rex2 = 0;
541                 if (arg1[0] & 8)
542                         rex2 |= X86_REX2_B3;
543                 if (arg1[0] & 16)
544                         rex2 |= X86_REX2_B4;
545                 if (aux)
546                         rex2 |= X86_REX2_W;
547                 if (aux) {
548                         cgen_one(X86_REX2);
549                         cgen_one(rex2);
550                 } else if (rex2) {
551                         g(cgen_rex2(ctx, rex2));
552                 }
553                 cgen_one(X86_POP_R16 + (arg1[0] & 7));
554                 return true;
555         }
556         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_8F, OP_SIZE_4, false, X86_8F_POP, arg1));
557         return true;
560 static bool attr_w cgen_push2(struct codegen_context *ctx, unsigned aux)
562         uint8_t *arg1 = ctx->code_position;
563         uint8_t *arg2 = arg1 + arg_size(*arg1);
564         ctx->code_position = arg2 + arg_size(*arg2);
565         g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, X86_FF, !aux ? OP_SIZE_4 : OP_SIZE_8, false, X86_FF_PUSH, arg2));
566         return true;
569 static bool attr_w cgen_pop2(struct codegen_context *ctx, unsigned aux)
571         uint8_t *arg1 = ctx->code_position;
572         uint8_t *arg2 = arg1 + arg_size(*arg1);
573         ctx->code_position = arg2 + arg_size(*arg2);
574         g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, X86_8F, !aux ? OP_SIZE_4 : OP_SIZE_8, false, X86_8F_POP, arg2));
575         return true;
578 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
580         uint8_t *arg1 = ctx->code_position;
581         uint8_t *arg2 = arg1 + arg_size(*arg1);
582         ctx->code_position = arg2 + arg_size(*arg2);
583         if (arg2[0] == ARG_IMM) {
584                 int rex2 = 0;
585                 int64_t imm;
586                 imm = get_imm(&arg2[1]);
587                 if (R_IS_GPR(arg1[0])) {
588                         if (arg1[0] & 8)
589                                 rex2 |= X86_REX2_B3;
590                         if (arg1[0] & 16)
591                                 rex2 |= X86_REX2_B4;
592 #ifndef ARCH_X86_32
593                         if (imm >= 0 && imm < 0x100000000LL)
594 #endif
595                         {
596                                 if (rex2)
597                                         g(cgen_rex2(ctx, rex2));
598                                 cgen_one(X86_MOV_R16_IMM16 + (arg1[0] & 7));
599                                 cgen_four(imm);
600                                 return true;
601                         }
602                         if (imm >= ~(int64_t)0x7fffffff && imm < 0) {
603                                 goto mov_rm;
604                         }
605                         rex2 |= X86_REX2_W;
606                         g(cgen_rex2(ctx, rex2));
607                         cgen_one(X86_MOV_R16_IMM16 + (arg1[0] & 7));
608                         cgen_eight(imm);
609                         return true;
610                 } else {
611                         if (size < OP_SIZE_4) {
612                                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_MOV_RM8_IMM8 : X86_MOV_RM16_IMM16, size, false, X86_MOV_R16_IMM16_REG, arg1));
613                                 if (size == OP_SIZE_1)
614                                         cgen_one(imm);
615                                 else
616                                         cgen_two(imm);
617                                 return true;
618                         }
619 mov_rm:
620                         if (unlikely(!imm_is_32bit(imm)))
621                                 internal(file_line, "cgen_mov: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
622                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_MOV_RM16_IMM16, maximum(size, OP_SIZE_4), false, X86_MOV_R16_IMM16_REG, arg1));
623                         cgen_four(imm);
624                         return true;
625                 }
626         }
627         if (arg1[0] == R_AX && size >= OP_SIZE_4 && arg2[0] == ARG_ADDRESS_0) {
628                 int64_t imm;
629                 imm = get_imm(&arg2[1]);
630                 if (size == OP_SIZE_8)
631                         g(cgen_rex2(ctx, X86_REX2_W));
632                 cgen_one(X86_MOV_AX_M16);
633                 cgen_eight(imm);
634                 return true;
635         }
636         if (arg1[0] == ARG_ADDRESS_0 && arg2[0] == R_AX) {
637                 uint8_t code = size == OP_SIZE_1 ? X86_MOV_M16_AL : X86_MOV_M16_AX;
638                 int64_t imm;
639                 imm = get_imm(&arg1[1]);
640                 if (size == OP_SIZE_2)
641                         cgen_one(X86_OP_SIZE);
642                 if (size == OP_SIZE_8)
643                         g(cgen_rex2(ctx, X86_REX2_W));
644                 cgen_one(code);
645                 cgen_eight(imm);
646                 return true;
647         }
648         if (R_IS_XMM(arg1[0]) && ARG_IS_ADDRESS(arg2[0])) {
649                 if (size == OP_SIZE_2) {
650                         if (cpu_test_feature(CPU_FEATURE_fp16)) {
651                                 g(cgen_sse_insn(ctx, SSE_PREFIX_F3 | force_evex, PREFIX_MAP5, X86_MAP5_MOVSH_X128_M16, false, arg1[0], 0, arg2));
652                                 return true;
653                         } else {
654                                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F, X86_0F_PINSRW_X128_RM16_IMM8, false, arg1[0], R_XMM7, arg2));
655                                 cgen_one(0x00);
656                                 return true;
657                         }
658                 }
659                 if (size == OP_SIZE_16) {
660                         g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, X86_0F_MOVAPS_X128_M128, false, arg1[0], 0, arg2));
661                         return true;
662                 }
663                 g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2 | SSE_PREFIX_W, PREFIX_0F, X86_0F_MOVSS_X128_M32, false, arg1[0], 0, arg2));
664                 return true;
665         }
666         if (ARG_IS_ADDRESS(arg1[0]) && R_IS_XMM(arg2[0])) {
667                 if (size == OP_SIZE_2) {
668                         if (cpu_test_feature(CPU_FEATURE_fp16)) {
669                                 g(cgen_sse_insn(ctx, SSE_PREFIX_F3 | force_evex, PREFIX_MAP5, X86_MAP5_MOVSH_M16_X128, false, arg2[0], 0, arg1));
670                                 return true;
671                         } else {
672                                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F_3A, X86_0F_3A_PEXTRW_RM16_X128_IMM8, false, arg2[0], 0, arg1));
673                                 cgen_one(0x00);
674                                 return true;
675                         }
676                 }
677                 if (size == OP_SIZE_16) {
678                         g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, X86_0F_MOVAPS_M128_X128, false, arg2[0], 0, arg1));
679                         return true;
680                 }
681                 g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2 | SSE_PREFIX_W, PREFIX_0F, X86_0F_MOVSS_M32_X128, false, arg2[0], 0, arg1));
682                 return true;
683         }
684         if (R_IS_XMM(arg1[0]) && R_IS_XMM(arg2[0])) {
685                 g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, X86_0F_MOVAPS_X128_M128, false, arg1[0], 0, arg2));
686                 return true;
687         }
688         if (R_IS_XMM(arg1[0]) && R_IS_GPR(arg2[0])) {
689                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F, X86_0F_MOVD_X128_RM32, size == OP_SIZE_8, arg1[0], 0, arg2));
690                 return true;
691         }
692         if (R_IS_GPR(arg1[0]) && R_IS_XMM(arg2[0])) {
693                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F, X86_0F_MOVD_RM32_X128, size == OP_SIZE_8, arg2[0], 0, arg1));
694                 return true;
695         }
696         if (!R_IS_GPR(arg1[0]) && unlikely(!R_IS_GPR(arg2[0]))) {
697                 /*debug("%s", da(ctx->fn,function)->function_name);*/
698                 internal(file_line, "cgen_mov: two addresses not supported");
699         }
700         if (!R_IS_GPR(arg1[0])) {
701                 uint8_t code = size == OP_SIZE_1 ? X86_MOV_RM8_R8 : X86_MOV_RM16_R16;
702                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg2[0], arg1));
703                 return true;
704         } else if (size >= OP_SIZE_4) {
705                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_MOV_R16_RM16, size, true, arg1[0], arg2));
706                 return true;
707         } else {
708                 uint8_t code = size == OP_SIZE_1 ? X86_0F_MOVZX_R16_RM8 : X86_0F_MOVZX_R16_RM16;
709                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, code, OP_SIZE_4, false, arg1[0], arg2));
710                 return true;
711         }
714 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
716         uint8_t *arg1, *arg2;
717         if (unlikely(size == OP_SIZE_NATIVE)) {
718                 g(cgen_mov(ctx, size));
719                 return true;
720         }
721         arg1 = ctx->code_position;
722         arg2 = arg1 + arg_size(*arg1);
723         ctx->code_position = arg2 + arg_size(*arg2);
724         if (size <= OP_SIZE_2) {
725                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, size == OP_SIZE_1 ? X86_0F_MOVSX_R16_RM8 : X86_0F_MOVSX_R16_RM16, OP_SIZE_NATIVE, true, arg1[0], arg2));
726         } else {
727                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_MOVSXD, OP_SIZE_NATIVE, true, arg1[0], arg2));
728         }
729         return true;
732 static bool attr_w cgen_lea(struct codegen_context *ctx, unsigned size)
734         uint8_t addr[11];
735         uint8_t *arg1, *arg2, *arg3;
737         arg1 = ctx->code_position;
738         arg2 = arg1 + arg_size(*arg1);
739         arg3 = arg2 + arg_size(*arg2);
740         ctx->code_position = arg3 + arg_size(*arg3);
742         if (arg3[0] == ARG_IMM) {
743                 int64_t imm;
744                 if (arg2[0] == ARG_SHIFTED_REGISTER) {
745                         if (unlikely((arg2[1] & ARG_SHIFT_MODE) != ARG_SHIFT_LSL) ||
746                             unlikely((arg2[1] & ARG_SHIFT_AMOUNT) > 3))
747                                 goto invalid;
748                         addr[0] = ARG_ADDRESS_1 + (arg2[1] & ARG_SHIFT_AMOUNT);
749                         addr[1] = arg2[2];
750                 } else {
751                         addr[0] = ARG_ADDRESS_1;
752                         addr[1] = arg2[0];
753                 }
754                 imm = get_imm(&arg3[1]);
755                 memcpy(&addr[2], &imm, 8);
756         } else if (R_IS_GPR(arg3[0])) {
757                 addr[0] = ARG_ADDRESS_2;
758                 addr[1] = arg2[0];
759                 addr[2] = arg3[0];
760                 memset(&addr[3], 0, 8);
761         } else if (arg3[0] == ARG_SHIFTED_REGISTER) {
762                 if (unlikely((arg3[1] & ARG_SHIFT_MODE) != ARG_SHIFT_LSL) ||
763                     unlikely((arg3[1] & ARG_SHIFT_AMOUNT) > 3))
764                         goto invalid;
765                 addr[0] = ARG_ADDRESS_2 + (arg3[1] & ARG_SHIFT_AMOUNT);
766                 addr[1] = arg2[0];
767                 addr[2] = arg3[2];
768                 memset(&addr[3], 0, 8);
769         } else {
770 invalid:
771                 internal(file_line, "cgen_lea: invalid argument %u, %02x, %02x, %02x", size, arg1[0], arg2[0], arg3[0]);
772         }
773         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_LEA_R16_RM16, size, true, arg1[0], addr));
774         return true;
777 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
779         uint8_t *arg1, *arg2, *arg3;
780         if (alu != 7) {
781                 arg1 = ctx->code_position;
782                 arg2 = arg1 + arg_size(*arg1);
783                 arg3 = arg2 + arg_size(*arg2);
784                 ctx->code_position = arg3 + arg_size(*arg3);
785                 if (unlikely(arg_size(*arg1) != arg_size(*arg2)))
786                         internal(file_line, "cgen_alu: three-operand mode not supported");
787                 if (!cpu_test_feature(CPU_FEATURE_apx) && unlikely(memcmp(arg1, arg2, arg_size(*arg1))))
788                         internal(file_line, "cgen_alu: three-operand mode not supported");
789         } else {
790                 arg1 = ctx->code_position;
791                 arg2 = arg1;
792                 arg3 = arg2 + arg_size(*arg2);
793                 ctx->code_position = arg3 + arg_size(*arg3);
794         }
796         if (unlikely(alu == ALU_MUL)) {
797                 if (unlikely(arg3[0] == ARG_IMM)) {
798                         uint8_t code;
799                         int64_t imm;
800                         imm = get_imm(&arg3[1]);
801                         if (unlikely(!imm_is_32bit(imm)))
802                                 internal(file_line, "cgen_alu: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
803                         if (unlikely(size == OP_SIZE_1))
804                                 internal(file_line, "cgen_alu: byte mul with imm not supported");
805                         code = imm_is_8bit(imm) ? X86_IMUL_R16_RM16_IMM8 : X86_IMUL_R16_RM16_IMM16;
806                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg1[0], arg2));
807                         if (code == X86_IMUL_R16_RM16_IMM8) {
808                                 cgen_one(imm);
809                         } else if (size == OP_SIZE_2) {
810                                 cgen_two(imm);
811                         } else {
812                                 cgen_four(imm);
813                         }
814                         return true;
815                 }
816                 if (unlikely(size == OP_SIZE_1)) {
817                         if (unlikely(arg1[0] != R_AX))
818                                 internal(file_line, "cgen_alu: imul with unsupported register");
819                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_F6, size, false, X86_F6_IMUL_RM8, arg3));
820                         return true;
821                 } else {
822                         if (unlikely(!R_IS_GPR(arg1[0])))
823                                 internal(file_line, "cgen_alu: invalid multiply args");
824                         if (arg1[0] == arg2[0] && !test_evex)
825                                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_IMUL_R16_RM16, size, true, arg1[0], arg3));
826                         else
827                                 g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, X86_0F_IMUL_R16_RM16, size, true, arg2[0], arg3));
828                         return true;
829                 }
830         }
832         if (arg3[0] == ARG_IMM) {
833                 uint8_t code;
834                 bool bit8;
835                 int64_t imm;
836                 imm = get_imm(&arg3[1]);
837                 if (unlikely(!imm_is_32bit(imm)))
838                         internal(file_line, "cgen_alu: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
840                 if (!(writes_flags & 2)) {
841                         if ((alu == ALU_ADD && imm == 1) || (alu == ALU_SUB && imm == -1)) {
842 #ifdef ARCH_X86_32
843                                 if (R_IS_GPR(arg1[0]) && size >= OP_SIZE_2) {
844                                         if (size == OP_SIZE_2)
845                                                 cgen_one(X86_OP_SIZE);
846                                         cgen_one(X86_INC_R16 + arg1[0]);
847                                         return true;
848                                 }
849 #endif
850                                 if ((arg1[0] == arg2[0] && !test_evex) || !R_IS_GPR(arg1[0]))
851                                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_FE : X86_FF, size, false, X86_FE_INC_RM8, arg1));
852                                 else
853                                         g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, size == OP_SIZE_1 ? X86_FE : X86_FF, size, false, X86_FE_INC_RM8, arg2));
854                                 return true;
855                         }
856                         if ((alu == ALU_ADD && imm == -1) || (alu == ALU_SUB && imm == 1)) {
857 #ifdef ARCH_X86_32
858                                 if (R_IS_GPR(arg1[0]) && size >= OP_SIZE_2) {
859                                         if (size == OP_SIZE_2)
860                                                 cgen_one(X86_OP_SIZE);
861                                         cgen_one(X86_DEC_R16 + arg1[0]);
862                                         return true;
863                                 }
864 #endif
865                                 if ((arg1[0] == arg2[0] && !test_evex) || !R_IS_GPR(arg1[0]))
866                                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_FE : X86_FF, size, false, X86_FE_DEC_RM8, arg1));
867                                 else
868                                         g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, size == OP_SIZE_1 ? X86_FE : X86_FF, size, false, X86_FE_DEC_RM8, arg2));
869                                 return true;
870                         }
871                 }
873                 if (arg1[0] == R_AX && arg1[0] == arg2[0]) {
874                         if (imm_is_8bit(imm) && size >= OP_SIZE_4)
875                                 goto use_shorter;
876                         bit8 = false;
877                         code = size == OP_SIZE_1 ? X86_ALU_AL_IMM8 : X86_ALU_AX_IMM16;
878                         if (size == OP_SIZE_2)
879                                 cgen_one(X86_OP_SIZE);
880                         if (size == OP_SIZE_8)
881                                 g(cgen_rex2(ctx, X86_REX2_W));
882                         code += alu * 8;
883                         cgen_one(code);
884                 } else {
885 use_shorter:
886                         bit8 = imm_is_8bit(imm);
887                         code = size == OP_SIZE_1 ? X86_ALU_RM8_IMM8 : bit8 ? X86_ALU_RM16_IMM8 : X86_ALU_RM16_IMM16;
888                         if (alu == 7 || (arg1[0] == arg2[0] && !test_evex) || !R_IS_GPR(arg1[0]) || 0)
889                                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, false, alu, arg1));
890                         else
891                                 g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, code, size, false, alu, arg2));
892                 }
893                 if (bit8 || size == OP_SIZE_1) {
894                         cgen_one(imm);
895                 } else if (size == OP_SIZE_2) {
896                         cgen_two(imm);
897                 } else {
898                         cgen_four(imm);
899                 }
900                 return true;
901         }
903         if (R_IS_XMM(arg1[0]) && size == OP_SIZE_16) {
904                 uint8_t code;
905                 switch (alu) {
906                         case ALU_AND:   code = X86_0F_ANDPS_X128_M128; break;
907                         case ALU_ANDN:  code = X86_0F_ANDNPS_X128_M128; break;
908                         case ALU_OR:    code = X86_0F_ORPS_X128_M128; break;
909                         case ALU_XOR:   code = X86_0F_XORPS_X128_M128; break;
910                         default:        internal(file_line, "invalid sse alu: %u", alu);
911                 }
912                 g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, code, false, arg1[0], arg2[0], arg3));
913                 return true;
914         }
916         if (!R_IS_GPR(arg1[0]) && unlikely(!R_IS_GPR(arg3[0])))
917                 internal(file_line, "cgen_alu: two addresses not supported");
919         if (!R_IS_GPR(arg1[0])) {
920                 uint8_t code = size == OP_SIZE_1 ? X86_ALU_RM8_R8 : X86_ALU_RM16_R16;
921                 code += alu * 8;
922                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg3[0], arg1));
923                 return true;
924         } else {
925                 uint8_t code = size == OP_SIZE_1 ? X86_ALU_R8_RM8 : X86_ALU_R16_RM16;
926                 code += alu * 8;
927                 if (alu == 7 || (arg1[0] == arg2[0] && !test_evex))
928                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg1[0], arg3));
929                 else
930                         g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, code, size, true, arg2[0], arg3));
931                 return true;
932         }
935 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned alu)
937         uint8_t rex2;
938         uint8_t *arg1 = ctx->code_position;
939         uint8_t *arg2 = arg1 + arg_size(*arg1);
940         ctx->code_position = arg2 + arg_size(*arg2);
941         if ((!cpu_test_feature(CPU_FEATURE_apx) && (alu == ALU1_NOT || alu == ALU1_NEG)) || alu == ALU1_BSWAP) {
942                 if (unlikely(arg1[0] != arg2[0]))
943                         internal(file_line, "cgen_alu1: arguments mismatch: %x, %x", arg1[0], arg2[0]);
944         }
945         switch (alu) {
946                 case ALU1_NOT:
947                         if ((arg1[0] == arg2[0] && !test_evex) || !R_IS_GPR(arg1[0]))
948                                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_NOT_RM8, arg1));
949                         else
950                                 g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_NOT_RM8, arg2));
951                         return true;
952                 case ALU1_NEG:
953                         if ((arg1[0] == arg2[0] && !test_evex) || !R_IS_GPR(arg1[0]))
954                                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_NEG_RM8, arg1));
955                         else
956                                 g(cgen_rm_insn(ctx, (arg1[0] << 8) | force_ndd, PREFIX_LEGACY_EVEX, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_NEG_RM8, arg2));
957                         return true;
958                 case ALU1_BSWAP:
959                         if (unlikely(size <= OP_SIZE_2))
960                                 internal(file_line, "cgen_alu1: bytes or words not supported with this operation");
961                         rex2 = 0;
962                         if (!R_IS_GPR(arg1[0]))
963                                 internal(file_line, "cgen_alu1: bswap needs a register");
964                         if (arg1[0] & 8)
965                                 rex2 |= X86_REX2_B3;
966                         if (arg1[0] & 16)
967                                 rex2 |= X86_REX2_B4;
968                         if (size == OP_SIZE_8)
969                                 rex2 |= X86_REX2_W;
970                         if (rex2 & 0xf0)
971                                 rex2 |= X86_REX2_M0;
972                         if (rex2)
973                                 g(cgen_rex2(ctx, rex2));
974                         if (!(rex2 & X86_REX2_M0))
975                                 cgen_one(X86_0F);
976                         cgen_one(X86_0F_BSWAP + (arg1[0] & 7));
977                         return true;
978                 case ALU1_BSF:
979                 case ALU1_BSR:
980                 case ALU1_LZCNT:
981                 case ALU1_POPCNT:
982                         if (unlikely(size == OP_SIZE_1))
983                                 internal(file_line, "cgen_alu1: bytes not supported with this operation");
984                         if (alu == ALU1_POPCNT || alu == ALU1_LZCNT)
985                                 cgen_one(X86_REPE);
986                         g(cgen_rm_insn(ctx, -1, PREFIX_0F, alu == ALU1_BSF ? X86_0F_BSF_R16_RM16 : alu == ALU1_BSR || alu == ALU1_LZCNT ? X86_0F_BSR_R16_RM16 : X86_0F_POPCNT_R16_RM16, size, true, arg1[0], arg2));
987                         return true;
988                 default:
989                         internal(file_line, "cgen_alu1: invalid operation %u", alu);
990                         return false;
991         }
994 static bool attr_w cgen_test(struct codegen_context *ctx, unsigned size)
996         uint8_t *arg1, *arg2;
997         arg1 = ctx->code_position;
998         arg2 = arg1 + arg_size(*arg1);
999         ctx->code_position = arg2 + arg_size(*arg2);
1001         if (arg2[0] == ARG_IMM) {
1002                 int64_t imm;
1003                 imm = get_imm(&arg2[1]);
1004                 if (arg1[0] == R_AX) {
1005                         if (size == OP_SIZE_1) {
1006                                 cgen_one(X86_TEST_AL_IMM8);
1007                         } else if (size == OP_SIZE_2) {
1008                                 cgen_one(X86_OP_SIZE);
1009                                 cgen_one(X86_TEST_AX_IMM16);
1010                         } else if (size == OP_SIZE_4) {
1011                                 cgen_one(X86_TEST_AX_IMM16);
1012                         } else {
1013                                 if (unlikely(!imm_is_32bit(imm)))
1014                                         internal(file_line, "cgen_test: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
1015                                 g(cgen_rex2(ctx, X86_REX2_W));
1016                                 cgen_one(X86_TEST_AX_IMM16);
1017                         }
1018                 } else {
1019                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_TEST_RM8_IMM8, arg1));
1020                 }
1021                 if (size == OP_SIZE_1) {
1022                         cgen_one(imm);
1023                 } else if (size == OP_SIZE_2) {
1024                         cgen_two(imm);
1025                 } else if (size == OP_SIZE_4) {
1026                         cgen_four(imm);
1027                 } else {
1028                         if (unlikely(!imm_is_32bit(imm)))
1029                                 internal(file_line, "cgen_test: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
1030                         cgen_four(imm);
1031                 }
1032                 return true;
1033         }
1035         if (!R_IS_GPR(arg1[0]) && unlikely(!R_IS_GPR(arg2[0])))
1036                 internal(file_line, "cgen_test: two addresses not supported");
1038         if (!R_IS_GPR(arg1[0])) {
1039                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_TEST_RM8_R8 : X86_TEST_RM16_R16, size, true, arg2[0], arg1));
1040         } else {
1041                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_TEST_RM8_R8 : X86_TEST_RM16_R16, size, true, arg1[0], arg2));
1042         }
1043         return true;
1046 static bool attr_w cgen_lea3(struct codegen_context *ctx, unsigned size, unsigned shift)
1048         uint8_t addr[11];
1049         uint8_t *arg1, *arg2, *arg3, *arg4;
1051         arg1 = ctx->code_position;
1052         arg2 = arg1 + arg_size(*arg1);
1053         arg3 = arg2 + arg_size(*arg2);
1054         arg4 = arg3 + arg_size(*arg3);
1055         ctx->code_position = arg4 + arg_size(*arg4);
1057         if (unlikely(!R_IS_GPR(arg1[0])) || unlikely(!R_IS_GPR(arg2[0])) || unlikely(!R_IS_GPR(arg3[0])) || unlikely(arg4[0] != ARG_IMM))
1058                 internal(file_line, "cgen_lea3: invalid arguments");
1060         addr[0] = ARG_ADDRESS_2 + shift;
1061         addr[1] = arg2[0];
1062         addr[2] = arg3[0];
1063         memcpy(&addr[3], &arg4[1], 8);
1065         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_LEA_R16_RM16, size, true, arg1[0], addr));
1067         return true;
1070 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, uint8_t rot, unsigned writes_flags)
1072         uint8_t *arg1 = ctx->code_position;
1073         uint8_t *arg2 = arg1 + arg_size(*arg1);
1074         uint8_t *arg3 = arg2 + arg_size(*arg2);
1075         ctx->code_position = arg3 + arg_size(*arg3);
1077         if (cpu_test_feature(CPU_FEATURE_bmi2) && size >= OP_SIZE_4 && arg3[0] != ARG_IMM && !writes_flags && (rot == ROT_SHL || rot == ROT_SHR || rot == ROT_SAR)) {
1078                 int32_t sse_prefix;
1079                 switch (rot) {
1080                         case ROT_SHL:   sse_prefix = SSE_PREFIX_66; break;
1081                         case ROT_SAR:   sse_prefix = SSE_PREFIX_F3; break;
1082                         case ROT_SHR:   sse_prefix = SSE_PREFIX_F2; break;
1083                         default:        internal(file_line, "cgen_rot: invalid rotation %x", rot);
1084                 }
1085                 g(cgen_sse_insn(ctx, sse_prefix + force_vex, PREFIX_0F_38, X86_0F_38_ROTX, size == OP_SIZE_8, arg1[0], arg3[0], arg2));
1086                 return true;
1087         }
1089         if (arg1[0] != arg2[0])
1090                 internal(file_line, "cgen_rot: invalid arguments: %x, %02x, %02x, %02x", rot, arg1[0], arg2[0], arg3[0]);
1092         if (arg3[0] == R_CX) {
1093                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ROT_RM8_CL : X86_ROT_RM16_CL, size, false, rot, arg1));
1094         } else if (likely(arg3[0] == ARG_IMM)) {
1095                 int64_t imm;
1096                 imm = get_imm(&arg3[1]);
1097                 if (imm == 1) {
1098                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ROT_RM8_1 : X86_ROT_RM16_1, size, false, rot, arg1));
1099                 } else {
1100                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ROT_RM8_IMM8 : X86_ROT_RM16_IMM8, size, false, rot, arg1));
1101                         cgen_one(imm);
1102                 }
1103         } else {
1104                 internal(file_line, "cgen_rot: invalid argument %02x", arg3[0]);
1105         }
1106         return true;
1109 static bool attr_w cgen_btxt(struct codegen_context *ctx, unsigned size, uint8_t bt, uint8_t *arg1, uint8_t *arg2)
1111         if (arg2[0] == ARG_IMM) {
1112                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_BTX_RM16_IMM8, size, false, X86_0F_BTX_BT_RM16_IMM8 + bt, arg1));
1113                 cgen_one(arg2[1]);
1114         } else {
1115                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_BT_RM16_R16 + bt * 8, size, true, arg2[0], arg1));
1116         }
1117         return true;
1120 static bool attr_w cgen_bt(struct codegen_context *ctx, unsigned size)
1122         uint8_t *arg1 = ctx->code_position;
1123         uint8_t *arg2 = arg1 + arg_size(*arg1);
1124         ctx->code_position = arg2 + arg_size(*arg2);
1126         return cgen_btxt(ctx, size, BTX_BT, arg1, arg2);
1129 static bool attr_w cgen_btx(struct codegen_context *ctx, unsigned size, uint8_t bt)
1131         uint8_t *arg1 = ctx->code_position;
1132         uint8_t *arg2 = arg1 + arg_size(*arg1);
1133         uint8_t *arg3 = arg2 + arg_size(*arg2);
1134         ctx->code_position = arg3 + arg_size(*arg3);
1136         if (arg1[0] != arg2[0])
1137                 internal(file_line, "cgen_btx: invalid arguments");
1139         return cgen_btxt(ctx, size, bt, arg1, arg3);
1142 static bool attr_w cgen_mul_l(struct codegen_context *ctx, unsigned size, bool sgn)
1144         uint8_t *arg1, *arg2, *arg3, *arg4;
1145         uint32_t reg_up;
1146         arg1 = ctx->code_position;
1147         arg2 = arg1 + arg_size(*arg1);
1148         arg3 = arg2 + arg_size(*arg2);
1149         arg4 = arg3 + arg_size(*arg3);
1150         ctx->code_position = arg4 + arg_size(*arg4);
1151         reg_up = size == OP_SIZE_1 ? R_AX : R_DX;
1152         if (unlikely(arg1[0] != R_AX) || unlikely(arg2[0] != reg_up) || unlikely(arg3[0] != R_AX) || unlikely(arg4[0] == ARG_IMM))
1153                 internal(file_line, "cgen_mul_l: invalid mul arguments");
1155         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, !sgn ? X86_F6_MUL_RM8 : X86_F6_IMUL_RM8, arg4));
1156         return true;
1159 static bool attr_w cgen_div_l(struct codegen_context *ctx, unsigned size, bool sgn)
1161         uint8_t *arg1, *arg2, *arg3, *arg4, *arg5;
1162         uint32_t reg_up;
1163         arg1 = ctx->code_position;
1164         arg2 = arg1 + arg_size(*arg1);
1165         arg3 = arg2 + arg_size(*arg2);
1166         arg4 = arg3 + arg_size(*arg3);
1167         arg5 = arg4 + arg_size(*arg4);
1168         ctx->code_position = arg5 + arg_size(*arg5);
1169         reg_up = size == OP_SIZE_1 ? R_AX : R_DX;
1170         if (unlikely(arg1[0] != R_AX) || unlikely(arg2[0] != reg_up) || unlikely(arg3[0] != R_AX) || unlikely(arg4[0] != reg_up) || unlikely(arg5[0] == ARG_IMM))
1171                 internal(file_line, "cgen_div_l: invalid div arguments");
1173         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, !sgn ? X86_F6_DIV_RM8 : X86_F6_IDIV_RM8, arg5));
1174         return true;
1177 static bool attr_w cgen_cmov(struct codegen_context *ctx, unsigned size, unsigned cond)
1179         uint8_t *arg1 = ctx->code_position;
1180         uint8_t *arg2 = arg1 + arg_size(*arg1);
1181         uint8_t *arg3 = arg2 + arg_size(*arg2);
1182         ctx->code_position = arg3 + arg_size(*arg3);
1183         if (unlikely(arg1[0] != arg2[0]))
1184                 internal(file_line, "cgen_cmov: invalid arguments");
1185         g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_CMOVCC_R16_RM16 + cond, size, true, arg1[0], arg3));
1186         return true;
1189 static bool attr_w cgen_memcpy(struct codegen_context *ctx)
1191         int64_t disp_dest, disp_src;
1192         uint8_t *arg1, *arg2, *arg3;
1193         arg1 = ctx->code_position;
1194         arg2 = arg1 + arg_size(*arg1);
1195         arg3 = arg2 + arg_size(*arg2);
1196         ctx->code_position = arg3 + arg_size(*arg3);
1197         if (unlikely(arg1[0] != ARG_ADDRESS_1_POST_I) || unlikely(arg2[0] != ARG_ADDRESS_1_POST_I) || unlikely(arg3[0] != R_CX))
1198                 goto invl;
1199         if (unlikely(arg1[1] != R_DI) || unlikely(arg2[1] != R_SI))
1200                 goto invl;
1201         disp_dest = get_imm(&arg1[2]);
1202         disp_src = get_imm(&arg2[2]);
1203         if (unlikely(disp_dest != 0) || unlikely(disp_src != 0))
1204                 goto invl;
1206         cgen_one(X86_REPE);
1207         cgen_one(X86_MOVSB);
1208         return true;
1210 invl:
1211         internal(file_line, "cgen_memcpy: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1212         return false;
1215 static bool attr_w cgen_memset(struct codegen_context *ctx)
1217         int64_t disp_dest;
1218         uint8_t *arg1, *arg2, *arg3;
1219         arg1 = ctx->code_position;
1220         arg2 = arg1 + arg_size(*arg1);
1221         arg3 = arg2 + arg_size(*arg2);
1222         ctx->code_position = arg3 + arg_size(*arg3);
1223         if (unlikely(arg1[0] != ARG_ADDRESS_1_POST_I) || unlikely(arg2[0] != R_CX) || unlikely(arg3[0] != R_AX))
1224                 goto invl;
1225         if (unlikely(arg1[1] != R_DI))
1226                 goto invl;
1227         disp_dest = get_imm(&arg1[2]);
1228         if (unlikely(disp_dest != 0))
1229                 goto invl;
1231         cgen_one(X86_REPE);
1232         cgen_one(X86_STOSB);
1233         return true;
1235 invl:
1236         internal(file_line, "cgen_memset: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1237         return false;
1240 static bool attr_w cgen_sse_cmp(struct codegen_context *ctx, unsigned size)
1242         uint8_t *arg1 = ctx->code_position;
1243         uint8_t *arg2 = arg1 + arg_size(*arg1);
1244         ctx->code_position = arg2 + arg_size(*arg2);
1245         if (size == OP_SIZE_2) {
1246                 g(cgen_sse_insn(ctx, SSE_PREFIX_NONE | force_evex, PREFIX_MAP5, X86_MAP5_UCOMISH_X128_RM16, false, arg1[0], 0, arg2));
1247         } else {
1248                 g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_NONE : SSE_PREFIX_66 | SSE_PREFIX_W, PREFIX_0F, X86_0F_UCOMISS_X128_RM32, false, arg1[0], 0, arg2));
1249         }
1250         return true;
1253 static bool attr_w cgen_sse_alu(struct codegen_context *ctx, unsigned size, unsigned alu)
1255         uint8_t opcode;
1256         uint8_t *arg1 = ctx->code_position;
1257         uint8_t *arg2 = arg1 + arg_size(*arg1);
1258         uint8_t *arg3 = arg2 + arg_size(*arg2);
1259         ctx->code_position = arg3 + arg_size(*arg3);
1260         switch (alu) {
1261                 case FP_ALU_ADD:        opcode = X86_0F_ADDPS_X128_M32; break;
1262                 case FP_ALU_SUB:        opcode = X86_0F_SUBPS_X128_M32; break;
1263                 case FP_ALU_MUL:        opcode = X86_0F_MULPS_X128_M32; break;
1264                 case FP_ALU_DIV:        opcode = X86_0F_DIVPS_X128_M32; break;
1265                 default:                internal(file_line, "cgen_sse_alu: invalid alu %u", alu);
1266         }
1267         if (size == OP_SIZE_2) {
1268                 g(cgen_sse_insn(ctx, SSE_PREFIX_F3 | force_evex, PREFIX_MAP5, opcode, false, arg1[0], arg2[0], arg3));
1269         } else {
1270                 g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2 | SSE_PREFIX_W, PREFIX_0F, opcode, false, arg1[0], arg2[0], arg3));
1271         }
1272         return true;
1275 static bool attr_w cgen_sse_alu1(struct codegen_context *ctx, unsigned size, unsigned alu)
1277         uint8_t opcode;
1278         unsigned sse_pfx, sse_op_map;
1279         uint8_t *arg1 = ctx->code_position;
1280         uint8_t *arg2 = arg1 + arg_size(*arg1);
1281         ctx->code_position = arg2 + arg_size(*arg2);
1282         switch (alu) {
1283                 case FP_ALU1_SQRT:      if (size == OP_SIZE_2) {
1284                                                 sse_pfx = SSE_PREFIX_F3 | force_evex;
1285                                                 sse_op_map = PREFIX_MAP5;
1286                                         } else if (size == OP_SIZE_4) {
1287                                                 sse_pfx = SSE_PREFIX_F3;
1288                                                 sse_op_map = PREFIX_0F;
1289                                         } else if (size == OP_SIZE_8) {
1290                                                 sse_pfx = SSE_PREFIX_F2 | SSE_PREFIX_W;
1291                                                 sse_op_map = PREFIX_0F;
1292                                         } else {
1293                                                 goto fail;
1294                                         }
1295                                         opcode = X86_0F_SQRTPS_X128_M32;
1296                                         break;
1297                 case FP_ALU1_ROUND:
1298                 case FP_ALU1_FLOOR:
1299                 case FP_ALU1_CEIL:
1300                 case FP_ALU1_TRUNC:     sse_pfx = SSE_PREFIX_66;
1301                                         sse_op_map = PREFIX_0F_3A;
1302                                         if (size == OP_SIZE_2) {
1303                                                 sse_pfx = SSE_PREFIX_NONE | force_evex;
1304                                                 opcode = X86_0F_3A_RNDSCALESH_X128_M16;
1305                                         } else if (size == OP_SIZE_4) {
1306                                                 opcode = X86_0F_3A_ROUNDSS_X128_M32;
1307                                         } else if (size == OP_SIZE_8) {
1308                                                 opcode = X86_0F_3A_ROUNDSD_X128_M64;
1309                                                 sse_pfx |= SSE_PREFIX_W;
1310                                         } else {
1311                                                 goto fail;
1312                                         }
1313                                         break;
1314                 fail:
1315                 default:                internal(file_line, "cgen_sse_alu1: invalid alu %u, %u", alu, size);
1316         }
1317         g(cgen_sse_insn(ctx, sse_pfx, sse_op_map, opcode, false, arg1[0], arg1[0], arg2));
1318         if (OP_IS_ROUND(alu))
1319                 cgen_one(alu - FP_ALU1_ROUND);
1320         return true;
1323 static bool attr_w cgen_sse_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1325         uint8_t *arg1 = ctx->code_position;
1326         uint8_t *arg2 = arg1 + arg_size(*arg1);
1327         ctx->code_position = arg2 + arg_size(*arg2);
1328         if (fp_op_size == OP_SIZE_2) {
1329                 g(cgen_sse_insn(ctx, SSE_PREFIX_F3 | force_evex, PREFIX_MAP5, X86_MAP5_CVTSI2SH_X128_RM16, int_op_size == OP_SIZE_8, arg1[0], R_XMM7, arg2));
1330         } else {
1331                 g(cgen_sse_insn(ctx, fp_op_size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2 | SSE_PREFIX_W, PREFIX_0F, X86_0F_CVTSI2SS_X128_RM32, int_op_size == OP_SIZE_8, arg1[0], R_XMM7, arg2));
1332         }
1333         return true;
1336 static bool attr_w cgen_sse_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1338         uint8_t *arg1 = ctx->code_position;
1339         uint8_t *arg2 = arg1 + arg_size(*arg1);
1340         ctx->code_position = arg2 + arg_size(*arg2);
1341         if (fp_op_size == OP_SIZE_2) {
1342                 g(cgen_sse_insn(ctx, SSE_PREFIX_F3 | force_evex, PREFIX_MAP5, X86_MAP5_CVTTSH2SI_X128_RM16, int_op_size == OP_SIZE_8, arg1[0], 0, arg2));
1343         } else {
1344                 g(cgen_sse_insn(ctx, fp_op_size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2 | SSE_PREFIX_W, PREFIX_0F, X86_0F_CVTTSS2SI_X128_RM32, int_op_size == OP_SIZE_8, arg1[0], 0, arg2));
1345         }
1346         return true;
1349 static bool attr_w cgen_sse_cvt(struct codegen_context *ctx, unsigned from_op_size, unsigned to_op_size)
1351         uint8_t *arg1 = ctx->code_position;
1352         uint8_t *arg2 = arg1 + arg_size(*arg1);
1353         ctx->code_position = arg2 + arg_size(*arg2);
1354         if (from_op_size == OP_SIZE_2 && to_op_size == OP_SIZE_4) {
1355                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F_38, X86_0F_38_CVTPH2PS_X128_RM64, false, arg1[0], 0, arg2));
1356                 return true;
1357         } else if (from_op_size == OP_SIZE_4 && to_op_size == OP_SIZE_2) {
1358                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F_3A, X86_0F_3A_CVTPS2PH_RM64_X128, false, arg2[0], 0, arg1));
1359                 cgen_one(0x04);
1360                 return true;
1361         }
1362         internal(file_line, "cgen_sse_cvt: unsupported arguments %u, %u", from_op_size, to_op_size);
1363         return false;
1366 static bool attr_w cgen_x87_fld(struct codegen_context *ctx, unsigned size)
1368         unsigned c1, c2;
1369         uint8_t *arg1 = ctx->code_position;
1370         ctx->code_position = arg1 + arg_size(*arg1);
1371         if (arg1[0] >= R_ST0 && arg1[0] <= R_ST7)
1372                 size = OP_SIZE_4;
1373         switch (size) {
1374                 case OP_SIZE_4:
1375                         c1 = X87_FLD_RM32; c2 = X87_FLD_RM32_X; break;
1376                 case OP_SIZE_8:
1377                         c1 = X87_FLD_M64; c2 = X87_FLD_M64_X; break;
1378                 case OP_SIZE_10:
1379                         c1 = X87_FLD_M80; c2 = X87_FLD_M80_X; break;
1380                 default:
1381                         internal(file_line, "cgen_x87_fld: invalid size %u", size);
1382         }
1383         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1384         return true;
1387 static bool attr_w cgen_x87_fild(struct codegen_context *ctx, unsigned size)
1389         unsigned c1, c2;
1390         uint8_t *arg1 = ctx->code_position;
1391         ctx->code_position = arg1 + arg_size(*arg1);
1392         switch (size) {
1393                 case OP_SIZE_2:
1394                         c1 = X87_FILD_M16; c2 = X87_FILD_M16_X; break;
1395                 case OP_SIZE_4:
1396                         c1 = X87_FILD_M32; c2 = X87_FILD_M32_X; break;
1397                 case OP_SIZE_8:
1398                         c1 = X87_FILD_M64; c2 = X87_FILD_M64_X; break;
1399                 default:
1400                         internal(file_line, "cgen_x87_fild: invalid size %u", size);
1401         }
1402         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1403         return true;
1406 static bool attr_w cgen_x87_fstp(struct codegen_context *ctx, unsigned size)
1408         unsigned c1, c2;
1409         uint8_t *arg1 = ctx->code_position;
1410         ctx->code_position = arg1 + arg_size(*arg1);
1411         if (arg1[0] >= R_ST0 && arg1[0] <= R_ST7)
1412                 size = OP_SIZE_8;
1413         switch (size) {
1414                 case OP_SIZE_4:
1415                         c1 = X87_FSTP_M32; c2 = X87_FSTP_M32_X; break;
1416                 case OP_SIZE_8:
1417                         c1 = X87_FSTP_RM64; c2 = X87_FSTP_RM64_X; break;
1418                 case OP_SIZE_10:
1419                         c1 = X87_FSTP_M80; c2 = X87_FSTP_M80_X; break;
1420                 default:
1421                         internal(file_line, "cgen_x87_fstp: invalid size %u", size);
1422         }
1423         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1424         return true;
1427 static bool attr_w cgen_x87_fistp(struct codegen_context *ctx, unsigned size)
1429         unsigned c1, c2;
1430         uint8_t *arg1 = ctx->code_position;
1431         ctx->code_position = arg1 + arg_size(*arg1);
1432         switch (size) {
1433                 case OP_SIZE_2:
1434                         c1 = X87_FISTP_M16; c2 = X87_FISTP_M16_X; break;
1435                 case OP_SIZE_4:
1436                         c1 = X87_FISTP_M32; c2 = X87_FISTP_M32_X; break;
1437                 case OP_SIZE_8:
1438                         c1 = X87_FISTP_M64; c2 = X87_FISTP_M64_X; break;
1439                 default:
1440                         internal(file_line, "cgen_x87_fistp: invalid size %u", size);
1441         }
1442         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1443         return true;
1446 static bool attr_w cgen_x87_fisttp(struct codegen_context *ctx, unsigned size)
1448         unsigned c1, c2;
1449         uint8_t *arg1 = ctx->code_position;
1450         ctx->code_position = arg1 + arg_size(*arg1);
1451         switch (size) {
1452                 case OP_SIZE_2:
1453                         c1 = X87_FISTTP_M16; c2 = X87_FISTTP_M16_X; break;
1454                 case OP_SIZE_4:
1455                         c1 = X87_FISTTP_M32; c2 = X87_FISTTP_M32_X; break;
1456                 case OP_SIZE_8:
1457                         c1 = X87_FISTTP_M64; c2 = X87_FISTTP_M64_X; break;
1458                 default:
1459                         internal(file_line, "cgen_x87_fisttp: invalid size %u", size);
1460         }
1461         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1462         return true;
1465 static bool attr_w cgen_x87_fcomp(struct codegen_context *ctx, unsigned size)
1467         unsigned c1, c2;
1468         uint8_t *arg1 = ctx->code_position;
1469         ctx->code_position = arg1 + arg_size(*arg1);
1470         if (arg1[0] < ARG_REGS_MAX) {
1471                 c1 = X87_FALU_ST_RM32;
1472         } else switch (size) {
1473                 case OP_SIZE_4:
1474                         c1 = X87_FALU_ST_RM32; break;
1475                 case OP_SIZE_8:
1476                         c1 = X87_FALU_ST_M64; break;
1477                 default:
1478                         internal(file_line, "cgen_x87_fcomp: invalid size %u", size);
1479         }
1480         c2 = X87_ALU_FCOMP;
1481         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1482         return true;
1485 static bool attr_w cgen_x87_alu(struct codegen_context *ctx, unsigned size, unsigned aux)
1487         unsigned c1, c2;
1488         uint8_t *arg1 = ctx->code_position;
1489         ctx->code_position = arg1 + arg_size(*arg1);
1490         if (arg1[0] < ARG_REGS_MAX) {
1491                 c1 = X87_FALU_ST_RM32;
1492         } else switch (size) {
1493                 case OP_SIZE_4:
1494                         c1 = X87_FALU_ST_RM32; break;
1495                 case OP_SIZE_8:
1496                         c1 = X87_FALU_ST_M64; break;
1497                 default:
1498                         internal(file_line, "cgen_x87_alu: invalid size %u", size);
1499         }
1500         switch (aux) {
1501                 case FP_ALU_ADD:
1502                         c2 = X87_ALU_ADD; break;
1503                 case FP_ALU_SUB:
1504                         c2 = X87_ALU_SUB; break;
1505                 case FP_ALU_MUL:
1506                         c2 = X87_ALU_MUL; break;
1507                 case FP_ALU_DIV:
1508                         c2 = X87_ALU_DIV; break;
1509                 default:
1510                         internal(file_line, "cgen_x87_fst: invalid operation %u", aux);
1511         }
1512         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1513         return true;
1516 static bool attr_w cgen_x87_alup(struct codegen_context *ctx, unsigned aux)
1518         unsigned c2;
1519         uint8_t *arg1 = ctx->code_position;
1520         ctx->code_position = arg1 + arg_size(*arg1);
1521         switch (aux) {
1522                 case FP_ALU_ADD:
1523                         c2 = X87_ALU_ADD; break;
1524                 case FP_ALU_SUB:
1525                         c2 = X87_ALU_SUB; break;
1526                 case FP_ALU_MUL:
1527                         c2 = X87_ALU_MUL; break;
1528                 case FP_ALU_DIV:
1529                         c2 = X87_ALU_DIV; break;
1530                 default:
1531                         internal(file_line, "cgen_x87_fstp: invalid operation %u", aux);
1532         }
1533         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X87_FALUP_STi_ST0, OP_SIZE_4, false, c2, arg1));
1534         return true;
1537 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1539         int64_t offs = (int64_t)ctx->label_to_pos[reloc->label_id] - (int64_t)(reloc->position + (reloc->length == JMP_SHORT ? 1 : 4));
1540         switch (reloc->length) {
1541                 case JMP_SHORT: {
1542                         int8_t i8;
1543                         if (!imm_is_8bit(offs))
1544                                 return false;
1545                         i8 = offs;
1546                         memcpy(ctx->mcode + reloc->position, &i8, 1);
1547                         return true;
1548                 }
1549                 case JMP_LONG: {
1550                         int32_t i32;
1551                         if (!imm_is_32bit(offs))
1552                                 return false;
1553                         i32 = offs;
1554                         memcpy(ctx->mcode + reloc->position, &i32, 4);
1555                         return true;
1556                 }
1557                 default: {
1558                         internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1559                         return false;
1560                 }
1561         }
1564 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1566         uint8_t imm8;
1567         uint16_t imm16;
1568         /*debug("insn: %08x", insn);*/
1569         switch (insn_opcode(insn)) {
1570                 case INSN_ENTRY:
1571                         g(cgen_entry(ctx));
1572                         return true;
1573                 case INSN_LABEL:
1574                         g(cgen_label(ctx));
1575                         return true;
1576                 case INSN_RET:
1577                         cgen_one(X86_RET);
1578                         return true;
1579                 case INSN_RET_IMM:
1580                         imm16 = cget_two(ctx);
1581                         cgen_one(X86_RET_IMM16);
1582                         cgen_two(imm16);
1583                         return true;
1584                 case INSN_PUSH:
1585                         g(cgen_push(ctx, insn_aux(insn)));
1586                         return true;
1587                 case INSN_POP:
1588                         g(cgen_pop(ctx, insn_aux(insn)));
1589                         return true;
1590                 case INSN_PUSH2:
1591                         g(cgen_push2(ctx, insn_aux(insn)));
1592                         return true;
1593                 case INSN_POP2:
1594                         g(cgen_pop2(ctx, insn_aux(insn)));
1595                         return true;
1596                 case INSN_CALL_INDIRECT:
1597                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_FF, OP_SIZE_4, false, X86_FF_CALL_INDIRECT, ctx->code_position));
1598                         ctx->code_position += arg_size(*ctx->code_position);
1599                         return true;
1600                 case INSN_MOV:
1601                         g(cgen_mov(ctx, insn_op_size(insn)));
1602                         return true;
1603                 case INSN_MOVSX:
1604                         g(cgen_movsx(ctx, insn_op_size(insn)));
1605                         return true;
1606                 case INSN_CMP:
1607                         g(cgen_alu(ctx, insn_op_size(insn), 7, insn_writes_flags(insn)));
1608                         return true;
1609                 case INSN_TEST:
1610                         g(cgen_test(ctx, insn_op_size(insn)));
1611                         return true;
1612                 case INSN_ALU:
1613                 case INSN_ALU_FLAGS:
1614                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1615                                 goto invalid_insn;
1616                         if (!insn_writes_flags(insn) && insn_op_size(insn) <= OP_SIZE_8) {
1617                                 if (unlikely(insn_aux(insn) != ALU_ADD))
1618                                         goto invalid_insn;
1619                                 g(cgen_lea(ctx, insn_op_size(insn)));
1620                                 return true;
1621                         }
1622                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1623                         return true;
1624                 case INSN_ALU_PARTIAL:
1625                 case INSN_ALU_FLAGS_PARTIAL:
1626                         if (unlikely(insn_op_size(insn) >= OP_SIZE_4))
1627                                 goto invalid_insn;
1628                         if (!insn_writes_flags(insn)) {
1629                                 if (unlikely(insn_aux(insn) != ALU_ADD) || insn_op_size(insn) != OP_SIZE_2)
1630                                         goto invalid_insn;
1631                                 g(cgen_lea(ctx, insn_op_size(insn)));
1632                                 return true;
1633                         }
1634                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1635                         return true;
1636                 case INSN_ALU1:
1637                 case INSN_ALU1_FLAGS:
1638                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1639                                 goto invalid_insn;
1640                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1641                         return true;
1642                 case INSN_ALU1_PARTIAL:
1643                 case INSN_ALU1_FLAGS_PARTIAL:
1644                         if (unlikely(insn_op_size(insn) >= OP_SIZE_4))
1645                                 goto invalid_insn;
1646                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1647                         return true;
1648                 case INSN_LEA3:
1649                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1650                                 goto invalid_insn;
1651                         g(cgen_lea3(ctx, insn_op_size(insn), insn_aux(insn)));
1652                         return true;
1653                 case INSN_ROT:
1654                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1655                                 goto invalid_insn;
1656                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1657                         return true;
1658                 case INSN_ROT_PARTIAL:
1659                         if (unlikely(insn_op_size(insn) >= OP_SIZE_4))
1660                                 goto invalid_insn;
1661                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1662                         return true;
1663                 case INSN_BT:
1664                         if (unlikely(insn_op_size(insn) == OP_SIZE_1) || unlikely(!insn_writes_flags(insn)))
1665                                 goto invalid_insn;
1666                         g(cgen_bt(ctx, insn_op_size(insn)));
1667                         return true;
1668                 case INSN_BTX:
1669                         if (unlikely(insn_op_size(insn) == OP_SIZE_1) || unlikely(!insn_writes_flags(insn)))
1670                                 goto invalid_insn;
1671                         g(cgen_btx(ctx, insn_op_size(insn), insn_aux(insn)));
1672                         return true;
1673                 case INSN_MUL_L:
1674                         g(cgen_mul_l(ctx, insn_op_size(insn), insn_aux(insn)));
1675                         return true;
1676                 case INSN_DIV_L:
1677                         g(cgen_div_l(ctx, insn_op_size(insn), insn_aux(insn)));
1678                         return true;
1679                 case INSN_CBW:
1680                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2))
1681                                 goto invalid_insn;
1682                         if (insn_op_size(insn) == OP_SIZE_8)
1683                                 g(cgen_rex2(ctx, X86_REX2_W));
1684                         if (unlikely(cget_one(ctx) != R_AX))
1685                                 goto invalid_insn;
1686                         if (unlikely(cget_one(ctx) != R_AX))
1687                                 goto invalid_insn;
1688                         cgen_one(X86_CBW);
1689                         return true;
1690                 case INSN_CBW_PARTIAL:
1691                         if (unlikely(insn_op_size(insn) != OP_SIZE_2))
1692                                 goto invalid_insn;
1693                         if (unlikely(cget_one(ctx) != R_AX))
1694                                 goto invalid_insn;
1695                         if (unlikely(cget_one(ctx) != R_AX))
1696                                 goto invalid_insn;
1697                         cgen_one(X86_OP_SIZE);
1698                         cgen_one(X86_CBW);
1699                         return true;
1700                 case INSN_CWD:
1701                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2))
1702                                 goto invalid_insn;
1703                         if (unlikely(cget_one(ctx) != R_DX))
1704                                 goto invalid_insn;
1705                         if (unlikely(cget_one(ctx) != R_AX))
1706                                 goto invalid_insn;
1707                         if (insn_op_size(insn) == OP_SIZE_8)
1708                                 g(cgen_rex2(ctx, X86_REX2_W));
1709                         cgen_one(X86_CWD);
1710                         return true;
1711                 case INSN_CWD_PARTIAL:
1712                         if (unlikely(insn_op_size(insn) != OP_SIZE_2))
1713                                 goto invalid_insn;
1714                         if (unlikely(cget_one(ctx) != R_DX))
1715                                 goto invalid_insn;
1716                         if (unlikely(cget_one(ctx) != R_AX))
1717                                 goto invalid_insn;
1718                         if (unlikely(cget_one(ctx) != R_DX))
1719                                 goto invalid_insn;
1720                         cgen_one(X86_OP_SIZE);
1721                         cgen_one(X86_CWD);
1722                         return true;
1723                 case INSN_SET_COND:
1724                         if (insn_op_size(insn) >= OP_SIZE_4) {
1725                                 g(cgen_rm_insn(ctx, SSE_PREFIX_F2 | force_ndd, PREFIX_LEGACY_EVEX, X86_LEGACY_EVEX_SETCC_R64 + (insn_aux(insn) & 0xf), OP_SIZE_8, false, 0, ctx->code_position));
1726                         } else if (insn_op_size(insn) == OP_SIZE_1) {
1727                                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_SETCC_RM8 + (insn_aux(insn) & 0xf), OP_SIZE_1, false, 0, ctx->code_position));
1728                         } else {
1729                                 goto invalid_insn;
1730                         }
1731                         ctx->code_position += arg_size(*ctx->code_position);
1732                         return true;
1733                 case INSN_SET_COND_PARTIAL:
1734                         if (unlikely(insn_op_size(insn) != OP_SIZE_1))
1735                                 goto invalid_insn;
1736                         g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_SETCC_RM8 + (insn_aux(insn) & 0xf), OP_SIZE_1, false, 0, ctx->code_position));
1737                         ctx->code_position += arg_size(*ctx->code_position);
1738                         ctx->code_position += arg_size(*ctx->code_position);
1739                         return true;
1740                 case INSN_CMOV:
1741                 case INSN_CMOV_XCC:
1742                         if (unlikely(insn_op_size(insn) == OP_SIZE_1))
1743                                 goto invalid_insn;
1744                         g(cgen_cmov(ctx, insn_op_size(insn), insn_aux(insn)));
1745                         return true;
1746                 case INSN_MEMCPY:
1747                         g(cgen_memcpy(ctx));
1748                         return true;
1749                 case INSN_MEMSET:
1750                         g(cgen_memset(ctx));
1751                         return true;
1752                 case INSN_FP_CMP:
1753                         g(cgen_sse_cmp(ctx, insn_op_size(insn)));
1754                         return true;
1755                 case INSN_FP_ALU:
1756                         g(cgen_sse_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1757                         return true;
1758                 case INSN_FP_ALU1:
1759                         g(cgen_sse_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1760                         return true;
1761                 case INSN_FP_FROM_INT32:
1762                 case INSN_FP_FROM_INT64:
1763                         g(cgen_sse_from_int(ctx, insn_opcode(insn) == INSN_FP_FROM_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1764                         return true;
1765                 case INSN_FP_TO_INT32:
1766                 case INSN_FP_TO_INT64:
1767                         g(cgen_sse_to_int(ctx, insn_opcode(insn) == INSN_FP_TO_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1768                         return true;
1769                 case INSN_FP_CVT:
1770                         g(cgen_sse_cvt(ctx, insn_op_size(insn), insn_aux(insn)));
1771                         return true;
1772                 case INSN_X87_FLD:
1773                         g(cgen_x87_fld(ctx, insn_op_size(insn)));
1774                         return true;
1775                 case INSN_X87_FILD:
1776                         g(cgen_x87_fild(ctx, insn_op_size(insn)));
1777                         return true;
1778                 case INSN_X87_FSTP:
1779                         g(cgen_x87_fstp(ctx, insn_op_size(insn)));
1780                         return true;
1781                 case INSN_X87_FISTP:
1782                         g(cgen_x87_fistp(ctx, insn_op_size(insn)));
1783                         return true;
1784                 case INSN_X87_FISTTP:
1785                         g(cgen_x87_fisttp(ctx, insn_op_size(insn)));
1786                         return true;
1787                 case INSN_X87_FCOMP:
1788                         g(cgen_x87_fcomp(ctx, insn_op_size(insn)));
1789                         return true;
1790                 case INSN_X87_FCOMPP:
1791                         cgen_one(X87_FCOMPP);
1792                         cgen_one(X87_FCOMPP_2);
1793                         return true;
1794                 case INSN_X87_FCOMIP:
1795                         imm8 = cget_one(ctx);
1796                         cgen_one(X87_FCOMIP);
1797                         cgen_one(X87_FCOMIP_2 + (imm8 & 7));
1798                         return true;
1799                 case INSN_X87_ALU:
1800                         g(cgen_x87_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1801                         return true;
1802                 case INSN_X87_ALUP:
1803                         g(cgen_x87_alup(ctx, insn_aux(insn)));
1804                         return true;
1805                 case INSN_X87_FCHS:
1806                         cgen_one(X87_FCHS);
1807                         cgen_one(X87_FCHS_2);
1808                         return true;
1809                 case INSN_X87_FSQRT:
1810                         cgen_one(X87_FSQRT);
1811                         cgen_one(X87_FSQRT_2);
1812                         return true;
1813                 case INSN_X87_FRNDINT:
1814                         cgen_one(X87_FRNDINT);
1815                         cgen_one(X87_FRNDINT_2);
1816                         return true;
1817                 case INSN_X87_FNSTSW:
1818                         if (unlikely(cget_one(ctx) != R_AX))
1819                                 goto invalid_insn;
1820                         if (unlikely(cget_one(ctx) != R_AX))
1821                                 goto invalid_insn;
1822                         cgen_one(X87_FNSTSW);
1823                         cgen_one(X87_FNSTSW_2);
1824                         return true;
1825                 case INSN_X87_FLDCW:
1826                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X87_FLDCW, OP_SIZE_4, false, X87_FLDCW_X, ctx->code_position));
1827                         ctx->code_position += arg_size(*ctx->code_position);
1828                         return true;
1829                 case INSN_JMP:
1830                         if (insn_jump_size(insn) == JMP_SHORT || insn_jump_size(insn) == JMP_SHORTEST) {
1831                                 cgen_one(X86_JMP_8);
1832                                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1833                                 cgen_one(0);
1834                         } else if (likely(insn_jump_size(insn) == JMP_LONG)) {
1835                                 cgen_one(X86_JMP_16);
1836                                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1837                                 cgen_four(0);
1838                         } else {
1839                                 goto invalid_insn;
1840                         }
1841                         return true;
1842                 case INSN_JMP_COND:
1843                         if (insn_jump_size(insn) == JMP_SHORT || insn_jump_size(insn) == JMP_SHORTEST) {
1844                                 cgen_one(X86_JCC_8 + (insn_aux(insn) & 0xf));
1845                                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1846                                 cgen_one(0);
1847                         } else if (likely(insn_jump_size(insn) == JMP_LONG)) {
1848                                 cgen_one(X86_0F);
1849                                 cgen_one(X86_0F_JCC_16 + (insn_aux(insn) & 0xf));
1850                                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1851                                 cgen_four(0);
1852                         } else {
1853                                 goto invalid_insn;
1854                         }
1855                         return true;
1856                 case INSN_JMP_INDIRECT:
1857                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_FF, OP_SIZE_4, false, X86_FF_JMP_INDIRECT, ctx->code_position));
1858                         ctx->code_position += arg_size(*ctx->code_position);
1859                         return true;
1860                 default:
1861                 invalid_insn:
1862                         internal(file_line, "cgen_insn: invalid insn %08lx", (unsigned long)insn);
1863                         return false;
1864         }