parisc: fix a bug that we tried to generate moves between general
[ajla.git] / c2-x86.inc
blob4948a3c34bc6ce6a64d40e2a34e7062e9ff5371d
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 X86_ALU_RM8_R8                  0x00
20 #define X86_ALU_RM16_R16                0x01
21 #define X86_ALU_R8_RM8                  0x02
22 #define X86_ALU_R16_RM16                0x03
23 #define X86_ALU_AL_IMM8                 0x04
24 #define X86_ALU_AX_IMM16                0x05
25 #define X86_0F                          0x0f
26 #define X86_REX                         0x40
27 #define  X86_REX_B                              0x01
28 #define  X86_REX_X                              0x02
29 #define  X86_REX_R                              0x04
30 #define  X86_REX_W                              0x08
31 #define X86_INC_R16                     0x40
32 #define X86_DEC_R16                     0x48
33 #define X86_PUSH_R16                    0x50
34 #define X86_POP_R16                     0x58
35 #define X86_MOVSXD                      0x63
36 #define X86_OP_SIZE                     0x66
37 #define X86_PUSH_IMM16                  0x68
38 #define X86_IMUL_R16_RM16_IMM16         0x69
39 #define X86_PUSH_IMM8                   0x6a
40 #define X86_IMUL_R16_RM16_IMM8          0x6b
41 #define X86_JCC_8                       0x70
42 #define X86_ALU_RM8_IMM8                0x80
43 #define X86_ALU_RM16_IMM16              0x81
44 #define X86_ALU_RM16_IMM8               0x83
45 #define X86_TEST_RM8_R8                 0x84
46 #define X86_TEST_RM16_R16               0x85
47 #define X86_MOV_RM8_R8                  0x88
48 #define X86_MOV_RM16_R16                0x89
49 #define X86_MOV_R8_RM8                  0x8a
50 #define X86_MOV_R16_RM16                0x8b
51 #define X86_LEA_R16_RM16                0x8d
52 #define X86_CBW                         0x98
53 #define X86_CWD                         0x99
54 #define X86_MOV_AL_M16                  0xa0
55 #define X86_MOV_AX_M16                  0xa1
56 #define X86_MOV_M16_AL                  0xa2
57 #define X86_MOV_M16_AX                  0xa3
58 #define X86_MOVSB                       0xa4
59 #define X86_TEST_AL_IMM8                0xa8
60 #define X86_TEST_AX_IMM16               0xa9
61 #define X86_STOSB                       0xaa
62 #define X86_MOV_R16_IMM16               0xb8
63 #define X86_ROT_RM8_IMM8                0xc0
64 #define X86_ROT_RM16_IMM8               0xc1
65 #define X86_RET_IMM16                   0xc2
66 #define X86_RET                         0xc3
67 #define X86_VEX_3                       0xc4
68 #define X86_VEX_2                       0xc5
69 #define X86_MOV_RM8_IMM8                0xc6
70 #define X86_MOV_RM16_IMM16              0xc7
71 #define  X86_MOV_R16_IMM16_REG                  0x0
72 #define X86_8F                          0x8f
73 #define  X86_8F_POP                             0x0
74 #define X86_ROT_RM8_1                   0xd0
75 #define X86_ROT_RM16_1                  0xd1
76 #define X86_ROT_RM8_CL                  0xd2
77 #define X86_ROT_RM16_CL                 0xd3
78 #define X86_JMP_16                      0xe9
79 #define X86_JMP_8                       0xeb
80 #define X86_REPNE                       0xf2
81 #define X86_REPE                        0xf3
82 #define X86_F6                          0xf6
83 #define  X86_F6_TEST_RM8_IMM8                   0x0
84 #define  X86_F6_NOT_RM8                         0x2
85 #define  X86_F6_NEG_RM8                         0x3
86 #define  X86_F6_MUL_RM8                         0x4
87 #define  X86_F6_IMUL_RM8                        0x5
88 #define  X86_F6_DIV_RM8                         0x6
89 #define  X86_F6_IDIV_RM8                        0x7
90 #define X86_F7                          0xf7
91 #define  X86_F7_TEST_RM16_IMM16                 0x0
92 #define  X86_F7_NOT_RM16                        0x2
93 #define  X86_F7_NEG_RM16                        0x3
94 #define  X86_F7_MUL_RM16                        0x4
95 #define  X86_F7_IMUL_RM16                       0x5
96 #define  X86_F7_DIV_RM16                        0x6
97 #define  X86_F7_IDIV_RM16                       0x7
98 #define X86_FE                          0xfe
99 #define  X86_FE_INC_RM8                         0x0
100 #define  X86_FE_DEC_RM8                         0x1
101 #define X86_FF                          0xff
102 #define  X86_FF_INC_RM16                        0x0
103 #define  X86_FF_DEC_RM16                        0x1
104 #define  X86_FF_CALL_INDIRECT                   0x2
105 #define  X86_FF_JMP_INDIRECT                    0x4
106 #define  X86_FF_PUSH                            0x6
108 #define X86_0F_MOVSS_X128_M32           0x10
109 #define X86_0F_MOVSS_M32_X128           0x11
110 #define X86_0F_MOVAPS_X128_M128         0x28
111 #define X86_0F_MOVAPS_M128_X128         0x29
112 #define X86_0F_CVTSI2SS_X128_RM32       0x2a
113 #define X86_0F_CVTTSS2SI_X128_RM32      0x2c
114 #define X86_0F_UCOMISS_X128_RM32        0x2e
115 #define X86_0F_38                       0x38
116 #define X86_0F_3A                       0x3a
117 #define X86_0F_CMOVCC_R16_RM16          0x40
118 #define X86_0F_SQRTPS_X128_M32          0x51
119 #define X86_0F_ANDPS_X128_M128          0x54
120 #define X86_0F_ANDNPS_X128_M128         0x55
121 #define X86_0F_ORPS_X128_M128           0x56
122 #define X86_0F_XORPS_X128_M128          0x57
123 #define X86_0F_ADDPS_X128_M32           0x58
124 #define X86_0F_MULPS_X128_M32           0x59
125 #define X86_0F_SUBPS_X128_M32           0x5c
126 #define X86_0F_DIVPS_X128_M32           0x5e
127 #define X86_0F_JCC_16                   0x80
128 #define X86_0F_SETCC_RM8                0x90
129 #define X86_0F_BT_RM16_R16              0xa3
130 #define X86_0F_BTS_RM16_R16             0xab
131 #define X86_0F_BTR_RM16_R16             0xb3
132 #define X86_0F_BTX_RM16_IMM8            0xba
133 #define  X86_0F_BTX_BT_RM16_IMM8                0x4
134 #define  X86_0F_BTX_BTS_RM16_IMM8               0x5
135 #define  X86_0F_BTX_BTR_RM16_IMM8               0x6
136 #define  X86_0F_BTX_BTC_RM16_IMM8               0x7
137 #define X86_0F_BSWAP                    0xc8
138 #define X86_0F_BTC_RM16_R16             0xbb
139 #define X86_0F_IMUL_R16_RM16            0xaf
140 #define X86_0F_MOVZX_R16_RM8            0xb6
141 #define X86_0F_MOVZX_R16_RM16           0xb7
142 #define X86_0F_POPCNT_R16_RM16          0xb8
143 #define X86_0F_BSF_R16_RM16             0xbc
144 #define X86_0F_BSR_R16_RM16             0xbd
145 #define X86_0F_MOVSX_R16_RM8            0xbe
146 #define X86_0F_MOVSX_R16_RM16           0xbf
147 #define X86_0F_PINSRW_X128_RM16_IMM8    0xc4
149 #define X86_0F_38_CVTPH2PS_X128_RM64    0x13
151 #define X86_0F_3A_ROUNDSS_X128_M32      0x0a
152 #define X86_0F_3A_ROUNDSD_X128_M64      0x0b
153 #define X86_0F_3A_PEXTRW_RM16_X128_IMM8 0x15
154 #define X86_0F_3A_CVTPS2PH_RM64_X128    0x1d
156 #define X87_FLD_RM32                    0xd9
157 #define  X87_FLD_RM32_X                         0x0
158 #define X87_FLDCW                       0xd9
159 #define  X87_FLDCW_X                            0x5
160 #define X87_FILD_M32                    0xdb
161 #define  X87_FILD_M32_X                         0x0
162 #define X87_FISTTP_M32                  0xdb
163 #define  X87_FISTTP_M32_X                       0x1
164 #define X87_FISTP_M32                   0xdb
165 #define  X87_FISTP_M32_X                        0x3
166 #define X87_FLD_M80                     0xdb
167 #define  X87_FLD_M80_X                          0x5
168 #define X87_FLD_M64                     0xdd
169 #define  X87_FLD_M64_X                          0x0
170 #define X87_FSTP_M32                    0xd9
171 #define  X87_FSTP_M32_X                         0x3
172 #define X87_FSTP_M80                    0xdb
173 #define  X87_FSTP_M80_X                         0x7
174 #define X87_FSTP_RM64                   0xdd
175 #define  X87_FSTP_RM64_X                        0x3
176 #define X87_FALU_ST_RM32                0xd8
177 #define X87_FCHS                        0xd9
178 #define  X87_FCHS_2                             0xe0
179 #define X87_FSQRT                       0xd9
180 #define  X87_FSQRT_2                            0xfa
181 #define X87_FRNDINT                     0xd9
182 #define  X87_FRNDINT_2                          0xfc
183 #define X87_FALU_ST_M64                 0xdc
184 #define X87_FALU_STi_ST                 0xdc
185 #define X87_FISTTP_M64                  0xdd
186 #define  X87_FISTTP_M64_X                       0x1
187 #define X87_FALUP_STi_ST0               0xde
188 #define  X87_ALU_ADD                            0x0
189 #define  X87_ALU_MUL                            0x1
190 #define  X87_ALU_FCOM                           0x2
191 #define  X87_ALU_FCOMP                          0x3
192 #define  X87_ALU_SUBR                           0x4
193 #define  X87_ALU_SUB                            0x5
194 #define  X87_ALU_DIVR                           0x6
195 #define  X87_ALU_DIV                            0x7
196 #define X87_FCOMPP                      0xde
197 #define  X87_FCOMPP_2                           0xd9
198 #define X87_FILD_M16                    0xdf
199 #define  X87_FILD_M16_X                         0x0
200 #define X87_FISTTP_M16                  0xdf
201 #define  X87_FISTTP_M16_X                       0x1
202 #define X87_FISTP_M16                   0xdf
203 #define  X87_FISTP_M16_X                        0x3
204 #define X87_FILD_M64                    0xdf
205 #define  X87_FILD_M64_X                         0x5
206 #define X87_FISTP_M64                   0xdf
207 #define  X87_FISTP_M64_X                        0x7
208 #define X87_FNSTSW                      0xdf
209 #define  X87_FNSTSW_2                           0xe0
210 #define X87_FCOMIP                      0xdf
211 #define  X87_FCOMIP_2                           0xf0
213 #define SSE_PREFIX_NONE                 0
214 #define SSE_PREFIX_66                   1
215 #define SSE_PREFIX_F3                   2
216 #define SSE_PREFIX_F2                   3
218 #define PREFIX_NONE                     0
219 #define PREFIX_0F                       1
220 #define PREFIX_0F_38                    2
221 #define PREFIX_0F_3A                    3
223 #ifdef ARCH_X86_32
224 #define cgen_rex(rex)           internal(file_line, "cgen_rex: attempting to generate rex in 32-bit mode: %02x", rex)
225 #else
226 #define cgen_rex(rex)           cgen_one(rex)
227 #endif
229 static bool attr_w cgen_rm_insn(struct codegen_context *ctx, int16_t sse_prefix, uint8_t prefix, uint8_t opcode, unsigned size, bool reg_is_reg, uint8_t reg, uint8_t *arg)
231         uint8_t rex, mod, rm;
232         int16_t sib;
233         int64_t imm = 0;        /* avoid warning */
234         uint8_t addr_size;
235         uint8_t arg_reg;
237         if (unlikely(R_IS_XMM(reg)))
238                 reg -= R_XMM0;
239         if (unlikely(R_IS_XMM(arg[0]))) {
240                 arg_reg = arg[0] - R_XMM0;
241                 arg = &arg_reg;
242         }
243         if (unlikely(!R_IS_GPR(reg)))
244                 internal(file_line, "cgen_rm_insn: invalid register %02x", reg);
246         sib = -1;
247         rex = X86_REX;
248         if (size == OP_SIZE_8)
249                 rex |= X86_REX_W;
250         if (reg & 8)
251                 rex |= X86_REX_R;
252         if (arg[0] < 0x40) {
253                 if (arg[0] & 8)
254                         rex |= X86_REX_B;
255                 mod = 0xc0;
256                 rm = arg[0] & 7;
257                 addr_size = 0;
258         } else {
259                 uint8_t *imm_ptr = arg + arg_size(arg[0]) - 8;
260                 imm = get_imm(imm_ptr);
261                 if (unlikely(!imm_is_32bit(imm)))
262                         internal(file_line, "cgen_rm_insn: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
263                 if (arg[0] == ARG_ADDRESS_0) {
264                         addr_size = 4;
265                         mod = 0x00;
266                         rm = 0x4;
267                         sib = 0x25;
268                         goto gen;
269                 }
270                 if (!imm) {
271                         addr_size = 0;
272                 } else if (imm >= -0x80 && imm <= 0x7f) {
273                         addr_size = 1;
274                 } else {
275                         addr_size = 4;
276                 }
277                 if ((arg[1] & 7) == 0x5 && addr_size == 0)
278                         addr_size = 1;
279                 if (addr_size == 0)
280                         mod = 0x00;
281                 else if (addr_size == 1)
282                         mod = 0x40;
283                 else
284                         mod = 0x80;
285                 if (arg[0] == ARG_ADDRESS_1) {
286                         if (arg[1] & 8)
287                                 rex |= X86_REX_B;
288                         if ((arg[1] & 7) == 0x4) {
289                                 rm = 0x4;
290                                 sib = 0x24;
291                                 goto gen;
292                         }
293                         rm = arg[1] & 7;
294                         goto gen;
295                 }
296                 if (arg[0] >= ARG_ADDRESS_1_2 && arg[0] <= ARG_ADDRESS_1_8) {
297                         if (unlikely(arg[1] == R_SP))
298                                 internal(file_line, "cgen_rm_insn: attemptint to scale SP");
299                         if (arg[1] & 8)
300                                 rex |= X86_REX_X;
301                         addr_size = 4;
302                         mod = 0x00;
303                         rm = 0x4;
304                         sib = ((arg[0] - ARG_ADDRESS_1) << 6) | ((arg[1] & 7) << 3) | 0x5;
305                         goto gen;
306                 }
307                 if (arg[0] >= ARG_ADDRESS_2 && arg[0] <= ARG_ADDRESS_2_8) {
308                         if (unlikely(arg[2] == R_SP))
309                                 internal(file_line, "cgen_rm_insn: attemptint to scale SP");
310                         if (arg[1] & 8)
311                                 rex |= X86_REX_B;
312                         if (arg[2] & 8)
313                                 rex |= X86_REX_X;
314                         rm = 0x4;
315                         sib = ((arg[0] - ARG_ADDRESS_2) << 6) | ((arg[2] & 7) << 3) | (arg[1] & 7);
316                         goto gen;
317                 }
318                 internal(file_line, "cgen_rm_insn: invalid argument %02x", arg[0]);
319         }
321 gen:
322         if (unlikely(sse_prefix >= 0)) {
323                 if (likely(cpu_test_feature(CPU_FEATURE_avx))) {
324                         if ((rex & (X86_REX_X | X86_REX_B | X86_REX_W)) == 0 && prefix == PREFIX_0F) {
325                                 cgen_one(X86_VEX_2);
326                                 cgen_one((~rex & X86_REX_R) << 5 | (~(sse_prefix >> 8) & 0xf) << 3 | (sse_prefix & 3));
327                         } else {
328                                 cgen_one(X86_VEX_3);
329                                 cgen_one((~rex & (X86_REX_R | X86_REX_X | X86_REX_B)) << 5 | prefix);
330                                 cgen_one((rex & X86_REX_W) << 4 | (~(sse_prefix >> 8) & 0xf) << 3 | (sse_prefix & 3));
331                         }
332                         goto avx_done;
333                 }
334                 switch (sse_prefix & 3) {
335                         case SSE_PREFIX_66:     cgen_one(X86_OP_SIZE); break;
336                         case SSE_PREFIX_F3:     cgen_one(X86_REPE); break;
337                         case SSE_PREFIX_F2:     cgen_one(X86_REPNE); break;
338                 }
339         } else {
340                 if (size == OP_SIZE_2)
341                         cgen_one(X86_OP_SIZE);
342         }
343         if (rex != X86_REX || (size == OP_SIZE_1 && ((reg_is_reg && !reg_is_fp(reg) && reg >= 4) || (mod == 0xc0 && !reg_is_fp(arg[0]) && arg[0] >= 4))))
344                 cgen_rex(rex);
346         switch (prefix) {
347                 case PREFIX_NONE:
348                         break;
349                 case PREFIX_0F:
350                         cgen_one(X86_0F);
351                         break;
352                 case PREFIX_0F_38:
353                         cgen_one(X86_0F);
354                         cgen_one(X86_0F_38);
355                         break;
356                 case PREFIX_0F_3A:
357                         cgen_one(X86_0F);
358                         cgen_one(X86_0F_3A);
359                         break;
360                 default:
361                         internal(file_line, "cgen_rm_insn: invalid prefix %u", prefix);
362         }
363 avx_done:
364         cgen_one(opcode);
365         cgen_one(mod | ((reg & 7) << 3) | (rm & 7));
366         if (sib >= 0)
367                 cgen_one(sib);
368         switch (addr_size) {
369                 case 1:
370                         cgen_one(imm);
371                         break;
372                 case 4:
373                         cgen_four(imm);
374                         break;
375         }
376         return true;
379 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)
381         g(cgen_rm_insn(ctx, sse_prefix + (reg2 << 8), sse_op_map, opcode, !wide ? OP_SIZE_4 : OP_SIZE_8, true, reg, arg));
382         return true;
385 static bool attr_w cgen_push(struct codegen_context *ctx)
387         uint8_t *arg1 = ctx->code_position;
388         ctx->code_position += arg_size(*arg1);
389         if (likely(R_IS_GPR(arg1[0]))) {
390                 if (arg1[0] & 8)
391                         cgen_rex(X86_REX | X86_REX_B);
392                 cgen_one(X86_PUSH_R16 + (arg1[0] & 7));
393                 return true;
394         }
395         if (arg1[0] == ARG_IMM) {
396                 int64_t imm;
397                 imm = get_imm(&arg1[1]);
398                 if (unlikely(!imm_is_32bit(imm)))
399                         internal(file_line, "cgen_push: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
400                 if (imm >= -0x80 && imm <= 0x7f) {
401                         cgen_one(X86_PUSH_IMM8);
402                         cgen_one(imm);
403                         return true;
404                 } else {
405                         cgen_one(X86_PUSH_IMM16);
406                         cgen_four(imm);
407                         return true;
408                 }
409         }
410         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_FF, OP_SIZE_4, false, X86_FF_PUSH, arg1));
411         return true;
414 static bool attr_w cgen_pop(struct codegen_context *ctx)
416         uint8_t *arg1 = ctx->code_position;
417         ctx->code_position += arg_size(*arg1);
418         if (likely(R_IS_GPR(arg1[0]))) {
419                 if (arg1[0] & 8)
420                         cgen_rex(X86_REX | X86_REX_B);
421                 cgen_one(X86_POP_R16 + (arg1[0] & 7));
422                 return true;
423         }
424         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_8F, OP_SIZE_4, false, X86_8F_POP, arg1));
425         return true;
428 static bool attr_w cgen_mov(struct codegen_context *ctx, unsigned size)
430         uint8_t *arg1 = ctx->code_position;
431         uint8_t *arg2 = arg1 + arg_size(*arg1);
432         ctx->code_position = arg2 + arg_size(*arg2);
433         if (arg2[0] == ARG_IMM) {
434                 int rex = X86_REX;
435                 int64_t imm;
436                 imm = get_imm(&arg2[1]);
437                 if (R_IS_GPR(arg1[0])) {
438                         if (arg1[0] & 8)
439                                 rex |= X86_REX_B;
440 #ifndef ARCH_X86_32
441                         if (imm >= 0 && imm < 0x100000000LL)
442 #endif
443                         {
444                                 if (rex != X86_REX)
445                                         cgen_rex(rex);
446                                 cgen_one(X86_MOV_R16_IMM16 + (arg1[0] & 7));
447                                 cgen_four(imm);
448                                 return true;
449                         }
450                         if (imm >= ~(int64_t)0x7fffffff && imm < 0) {
451                                 goto mov_rm;
452                         }
453                         rex |= X86_REX_W;
454                         cgen_rex(rex);
455                         cgen_one(X86_MOV_R16_IMM16 + (arg1[0] & 7));
456                         cgen_eight(imm);
457                         return true;
458                 } else {
459                         if (size < OP_SIZE_4) {
460                                 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));
461                                 if (size == OP_SIZE_1)
462                                         cgen_one(imm);
463                                 else
464                                         cgen_two(imm);
465                                 return true;
466                         }
467 mov_rm:
468                         if (unlikely(!imm_is_32bit(imm)))
469                                 internal(file_line, "cgen_mov: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
470                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_MOV_RM16_IMM16, maximum(size, OP_SIZE_4), false, X86_MOV_R16_IMM16_REG, arg1));
471                         cgen_four(imm);
472                         return true;
473                 }
474         }
475         if (arg1[0] == R_AX && size >= OP_SIZE_4 && arg2[0] == ARG_ADDRESS_0) {
476                 int64_t imm;
477                 imm = get_imm(&arg2[1]);
478                 if (size == OP_SIZE_8)
479                         cgen_rex(X86_REX | X86_REX_W);
480                 cgen_one(X86_MOV_AX_M16);
481                 cgen_eight(imm);
482                 return true;
483         }
484         if (arg1[0] == ARG_ADDRESS_0 && arg2[0] == R_AX) {
485                 uint8_t code = size == OP_SIZE_1 ? X86_MOV_M16_AL : X86_MOV_M16_AX;
486                 int64_t imm;
487                 imm = get_imm(&arg1[1]);
488                 if (size == OP_SIZE_2)
489                         cgen_one(X86_OP_SIZE);
490                 if (size == OP_SIZE_8)
491                         cgen_rex(X86_REX | X86_REX_W);
492                 cgen_one(code);
493                 cgen_eight(imm);
494                 return true;
495         }
496         if (R_IS_XMM(arg1[0]) && ARG_IS_ADDRESS(arg2[0])) {
497                 if (size == OP_SIZE_2) {
498                         g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F, X86_0F_PINSRW_X128_RM16_IMM8, false, arg1[0], R_XMM7, arg2));
499                         cgen_one(0x00);
500                         return true;
501                 }
502                 if (size == OP_SIZE_16) {
503                         g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, X86_0F_MOVAPS_X128_M128, false, arg1[0], 0, arg2));
504                         return true;
505                 }
506                 g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2, PREFIX_0F, X86_0F_MOVSS_X128_M32, false, arg1[0], 0, arg2));
507                 return true;
508         }
509         if (ARG_IS_ADDRESS(arg1[0]) && R_IS_XMM(arg2[0])) {
510                 if (size == OP_SIZE_2) {
511                         g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F_3A, X86_0F_3A_PEXTRW_RM16_X128_IMM8, false, arg2[0], 0, arg1));
512                         cgen_one(0x00);
513                         return true;
514                 }
515                 if (size == OP_SIZE_16) {
516                         g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, X86_0F_MOVAPS_M128_X128, false, arg2[0], 0, arg1));
517                         return true;
518                 }
519                 g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2, PREFIX_0F, X86_0F_MOVSS_M32_X128, false, arg2[0], 0, arg1));
520                 return true;
521         }
522         if (R_IS_XMM(arg1[0]) && R_IS_XMM(arg2[0])) {
523                 g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, X86_0F_MOVAPS_X128_M128, false, arg1[0], 0, arg2));
524                 return true;
525         }
526         if (!R_IS_GPR(arg1[0]) && unlikely(!R_IS_GPR(arg2[0]))) {
527                 /*debug("%s", da(ctx->fn,function)->function_name);*/
528                 internal(file_line, "cgen_mov: two addresses not supported");
529         }
530         if (!R_IS_GPR(arg1[0])) {
531                 uint8_t code = size == OP_SIZE_1 ? X86_MOV_RM8_R8 : X86_MOV_RM16_R16;
532                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg2[0], arg1));
533                 return true;
534         } else if (size >= OP_SIZE_4) {
535                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_MOV_R16_RM16, size, true, arg1[0], arg2));
536                 return true;
537         } else {
538                 uint8_t code = size == OP_SIZE_1 ? X86_0F_MOVZX_R16_RM8 : X86_0F_MOVZX_R16_RM16;
539                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, code, size, false, arg1[0], arg2));
540                 return true;
541         }
544 static bool attr_w cgen_movsx(struct codegen_context *ctx, unsigned size)
546         uint8_t *arg1, *arg2;
547         if (unlikely(size == OP_SIZE_NATIVE)) {
548                 g(cgen_mov(ctx, size));
549                 return true;
550         }
551         arg1 = ctx->code_position;
552         arg2 = arg1 + arg_size(*arg1);
553         ctx->code_position = arg2 + arg_size(*arg2);
554         if (size <= OP_SIZE_2) {
555                 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));
556         } else {
557                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_MOVSXD, OP_SIZE_NATIVE, true, arg1[0], arg2));
558         }
559         return true;
562 static bool attr_w cgen_lea(struct codegen_context *ctx, unsigned size)
564         uint8_t addr[11];
565         uint8_t *arg1, *arg2, *arg3;
567         arg1 = ctx->code_position;
568         arg2 = arg1 + arg_size(*arg1);
569         arg3 = arg2 + arg_size(*arg2);
570         ctx->code_position = arg3 + arg_size(*arg3);
572         if (arg3[0] == ARG_IMM) {
573                 if (arg2[0] == ARG_SHIFTED_REGISTER) {
574                         if (unlikely((arg2[1] & ARG_SHIFT_MODE) != ARG_SHIFT_LSL) ||
575                             unlikely((arg2[1] & ARG_SHIFT_AMOUNT) > 3))
576                                 goto invalid;
577                         addr[0] = ARG_ADDRESS_1 + (arg2[1] & ARG_SHIFT_AMOUNT);
578                         addr[1] = arg2[2];
579                         memcpy(&addr[2], &arg3[1], 8);
580                 } else {
581                         addr[0] = ARG_ADDRESS_1;
582                         addr[1] = arg2[0];
583                         memcpy(&addr[2], &arg3[1], 8);
584                 }
585         } else if (R_IS_GPR(arg3[0])) {
586                 addr[0] = ARG_ADDRESS_2;
587                 addr[1] = arg2[0];
588                 addr[2] = arg3[0];
589                 memset(&addr[3], 0, 8);
590         } else if (arg3[0] == ARG_SHIFTED_REGISTER) {
591                 if (unlikely((arg3[1] & ARG_SHIFT_MODE) != ARG_SHIFT_LSL) ||
592                     unlikely((arg3[1] & ARG_SHIFT_AMOUNT) > 3))
593                         goto invalid;
594                 addr[0] = ARG_ADDRESS_2 + (arg3[1] & ARG_SHIFT_AMOUNT);
595                 addr[1] = arg2[0];
596                 addr[2] = arg3[2];
597                 memset(&addr[3], 0, 8);
598         } else {
599 invalid:
600                 internal(file_line, "cgen_lea: invalid argument %02x, %02x, %02x", arg1[0], arg2[0], arg3[0]);
601         }
602         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_LEA_R16_RM16, size, true, arg1[0], addr));
603         return true;
606 static bool attr_w cgen_alu(struct codegen_context *ctx, unsigned size, unsigned alu)
608         uint8_t *arg1, *arg2, *arg3;
609         if (alu != 7) {
610                 arg1 = ctx->code_position;
611                 arg2 = arg1 + arg_size(*arg1);
612                 arg3 = arg2 + arg_size(*arg2);
613                 ctx->code_position = arg3 + arg_size(*arg3);
614                 if (unlikely(arg_size(*arg1) != arg_size(*arg2)))
615                         internal(file_line, "cgen_alu: three-operand mode not supported");
616                 if (unlikely(memcmp(arg1, arg2, arg_size(*arg1))))
617                         internal(file_line, "cgen_alu: three-operand mode not supported");
618         } else {
619                 arg1 = ctx->code_position;
620                 arg2 = arg1;
621                 arg3 = arg2 + arg_size(*arg2);
622                 ctx->code_position = arg3 + arg_size(*arg3);
623         }
625         if (unlikely(alu == ALU_MUL)) {
626                 if (unlikely(arg3[0] == ARG_IMM)) {
627                         uint8_t code;
628                         int64_t imm;
629                         imm = get_imm(&arg3[1]);
630                         if (unlikely(!imm_is_32bit(imm)))
631                                 internal(file_line, "cgen_alu: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
632                         code = imm_is_8bit(imm) ? X86_IMUL_R16_RM16_IMM8 : X86_IMUL_R16_RM16_IMM16;
633                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg1[0], arg2));
634                         if (code == X86_IMUL_R16_RM16_IMM8) {
635                                 cgen_one(imm);
636                         } else if (size == OP_SIZE_2) {
637                                 cgen_two(imm);
638                         } else {
639                                 cgen_four(imm);
640                         }
641                         return true;
642                 }
643                 if (unlikely(size == OP_SIZE_1)) {
644                         if (unlikely(arg1[0] != R_AX))
645                                 internal(file_line, "cgen_alu: imul with unsupported register");
646                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_F6, size, false, X86_F6_IMUL_RM8, arg3));
647                         return true;
648                 } else {
649                         if (unlikely(!R_IS_GPR(arg1[0])))
650                                 internal(file_line, "cgen_alu: invalid multiply args");
651                         g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_IMUL_R16_RM16, size, true, arg1[0], arg3));
652                         return true;
653                 }
654         }
656         if (arg3[0] == ARG_IMM) {
657                 uint8_t code;
658                 bool bit8;
659                 int64_t imm;
660                 imm = get_imm(&arg3[1]);
661                 if (unlikely(!imm_is_32bit(imm)))
662                         internal(file_line, "cgen_alu: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
664                 if (arg1[0] == R_AX) {
665                         if (imm_is_8bit(imm) && size >= OP_SIZE_4)
666                                 goto use_shorter;
667                         bit8 = false;
668                         code = size == OP_SIZE_1 ? X86_ALU_AL_IMM8 : X86_ALU_AX_IMM16;
669                         if (size == OP_SIZE_2)
670                                 cgen_one(X86_OP_SIZE);
671                         if (size == OP_SIZE_8)
672                                 cgen_rex(X86_REX | X86_REX_W);
673                         code += alu * 8;
674                         cgen_one(code);
675                 } else {
676 use_shorter:
677                         bit8 = imm_is_8bit(imm);
678                         code = size == OP_SIZE_1 ? X86_ALU_RM8_IMM8 : bit8 ? X86_ALU_RM16_IMM8 : X86_ALU_RM16_IMM16;
679                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, false, alu, arg1));
680                 }
681                 if (bit8 || size == OP_SIZE_1) {
682                         cgen_one(imm);
683                 } else if (size == OP_SIZE_2) {
684                         cgen_two(imm);
685                 } else {
686                         cgen_four(imm);
687                 }
688                 return true;
689         }
691         if (R_IS_XMM(arg1[0]) && size == OP_SIZE_16) {
692                 uint8_t code;
693                 switch (alu) {
694                         case ALU_AND:   code = X86_0F_ANDPS_X128_M128; break;
695                         case ALU_ANDN:  code = X86_0F_ANDNPS_X128_M128; break;
696                         case ALU_OR:    code = X86_0F_ORPS_X128_M128; break;
697                         case ALU_XOR:   code = X86_0F_XORPS_X128_M128; break;
698                         default:        internal(file_line, "invalid sse alu: %u", alu);
699                 }
700                 g(cgen_sse_insn(ctx, SSE_PREFIX_NONE, PREFIX_0F, code, false, arg1[0], arg2[0], arg3));
701                 return true;
702         }
704         if (!R_IS_GPR(arg1[0]) && unlikely(!R_IS_GPR(arg3[0])))
705                 internal(file_line, "cgen_alu: two addresses not supported");
707         if (!R_IS_GPR(arg1[0])) {
708                 uint8_t code = size == OP_SIZE_1 ? X86_ALU_RM8_R8 : X86_ALU_RM16_R16;
709                 code += alu * 8;
710                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg3[0], arg1));
711                 return true;
712         } else {
713                 uint8_t code = size == OP_SIZE_1 ? X86_ALU_R8_RM8 : X86_ALU_R16_RM16;
714                 code += alu * 8;
715                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, code, size, true, arg1[0], arg3));
716                 return true;
717         }
720 static bool attr_w cgen_alu1(struct codegen_context *ctx, unsigned size, unsigned alu, unsigned writes_flags)
722         uint8_t rex;
723         uint8_t *arg1 = ctx->code_position;
724         uint8_t *arg2 = arg1 + arg_size(*arg1);
725         ctx->code_position = arg2 + arg_size(*arg2);
726         if (alu == ALU1_NOT || alu == ALU1_NEG || alu == ALU1_INC || alu == ALU1_DEC || alu == ALU1_BSWAP) {
727                 if (unlikely(arg1[0] != arg2[0]))
728                         internal(file_line, "cgen_alu1: arguments mismatch");
729         }
730         switch (alu) {
731                 case ALU1_NOT:
732                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_NOT_RM8, arg1));
733                         return true;
734                 case ALU1_NEG:
735                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_NEG_RM8, arg1));
736                         return true;
737                 case ALU1_INC:
738                         if (writes_flags & 2) {
739                                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ALU_RM8_IMM8 : X86_ALU_RM16_IMM8, size, false, ALU_ADD, arg1));
740                                 cgen_one(1);
741                                 return true;
742                         }
743 #ifdef ARCH_X86_32
744                         if (R_IS_GPR(arg1[0]) && size >= OP_SIZE_2) {
745                                 if (size == OP_SIZE_2)
746                                         cgen_one(X86_OP_SIZE);
747                                 cgen_one(X86_INC_R16 + arg1[0]);
748                                 return true;
749                         }
750 #endif
751                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_FE : X86_FF, size, false, X86_FE_INC_RM8, arg1));
752                         return true;
753                 case ALU1_DEC:
754                         if (writes_flags & 2) {
755                                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ALU_RM8_IMM8 : X86_ALU_RM16_IMM8, size, false, ALU_SUB, arg1));
756                                 cgen_one(1);
757                                 return true;
758                         }
759 #ifdef ARCH_X86_32
760                         if (R_IS_GPR(arg1[0]) && size >= OP_SIZE_2) {
761                                 if (size == OP_SIZE_2)
762                                         cgen_one(X86_OP_SIZE);
763                                 cgen_one(X86_DEC_R16 + arg1[0]);
764                                 return true;
765                         }
766 #endif
767                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_FE : X86_FF, size, false, X86_FE_DEC_RM8, arg1));
768                         return true;
769                 case ALU1_BSWAP:
770                         if (unlikely(size <= OP_SIZE_2))
771                                 internal(file_line, "cgen_alu1: bytes or words not supported with this operation");
772                         rex = X86_REX;
773                         if (!R_IS_GPR(arg1[0]))
774                                 internal(file_line, "cgen_alu1: bswap needs a register");
775                         if (arg1[0] & 8)
776                                 rex |= X86_REX_B;
777                         if (size == OP_SIZE_8)
778                                 rex |= X86_REX_W;
779                         if (rex != X86_REX)
780                                 cgen_rex(rex);
781                         cgen_one(X86_0F);
782                         cgen_one(X86_0F_BSWAP + (arg1[0] & 7));
783                         return true;
784                 case ALU1_BSF:
785                 case ALU1_BSR:
786                 case ALU1_LZCNT:
787                 case ALU1_POPCNT:
788                         if (unlikely(size == OP_SIZE_1))
789                                 internal(file_line, "cgen_alu1: bytes not supported with this operation");
790                         if (alu == ALU1_POPCNT || alu == ALU1_LZCNT)
791                                 cgen_one(X86_REPE);
792                         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));
793                         return true;
794                 default:
795                         internal(file_line, "cgen_alu1: invalid operation %u", alu);
796                         return false;
797         }
800 static bool attr_w cgen_test(struct codegen_context *ctx, unsigned size)
802         uint8_t *arg1, *arg2;
803         arg1 = ctx->code_position;
804         arg2 = arg1 + arg_size(*arg1);
805         ctx->code_position = arg2 + arg_size(*arg2);
807         if (arg2[0] == ARG_IMM) {
808                 int64_t imm;
809                 imm = get_imm(&arg2[1]);
810                 if (arg1[0] == R_AX) {
811                         if (size == OP_SIZE_1) {
812                                 cgen_one(X86_TEST_AL_IMM8);
813                         } else if (size == OP_SIZE_2) {
814                                 cgen_one(X86_OP_SIZE);
815                                 cgen_one(X86_TEST_AX_IMM16);
816                         } else if (size == OP_SIZE_4) {
817                                 cgen_one(X86_TEST_AX_IMM16);
818                         } else {
819                                 if (unlikely(!imm_is_32bit(imm)))
820                                         internal(file_line, "cgen_Test: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
821                                 cgen_rex(X86_REX | X86_REX_W);
822                                 cgen_one(X86_TEST_AX_IMM16);
823                         }
824                 } else {
825                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_F6 : X86_F7, size, false, X86_F6_TEST_RM8_IMM8, arg1));
826                 }
827                 if (size == OP_SIZE_1) {
828                         cgen_one(imm);
829                 } else if (size == OP_SIZE_2) {
830                         cgen_two(imm);
831                 } else if (size == OP_SIZE_4) {
832                         cgen_four(imm);
833                 } else {
834                         if (unlikely(!imm_is_32bit(imm)))
835                                 internal(file_line, "cgen_Test: immediate out of range: %"PRIxMAX"", (uintmax_t)imm);
836                         cgen_four(imm);
837                 }
838                 return true;
839         }
841         if (!R_IS_GPR(arg1[0]) && unlikely(!R_IS_GPR(arg2[0])))
842                 internal(file_line, "cgen_test: two addresses not supported");
844         if (!R_IS_GPR(arg1[0])) {
845                 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));
846         } else {
847                 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));
848         }
849         return true;
852 static bool attr_w cgen_lea3(struct codegen_context *ctx, unsigned size, unsigned shift)
854         uint8_t addr[11];
855         uint8_t *arg1, *arg2, *arg3, *arg4;
857         arg1 = ctx->code_position;
858         arg2 = arg1 + arg_size(*arg1);
859         arg3 = arg2 + arg_size(*arg2);
860         arg4 = arg3 + arg_size(*arg3);
861         ctx->code_position = arg4 + arg_size(*arg4);
863         if (unlikely(!R_IS_GPR(arg1[0])) || unlikely(!R_IS_GPR(arg2[0])) || unlikely(!R_IS_GPR(arg3[0])) || unlikely(arg4[0] != ARG_IMM))
864                 internal(file_line, "cgen_lea3: invalid arguments");
866         addr[0] = ARG_ADDRESS_2 + shift;
867         addr[1] = arg2[0];
868         addr[2] = arg3[0];
869         memcpy(&addr[3], &arg4[1], 8);
871         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_LEA_R16_RM16, size, true, arg1[0], addr));
873         return true;
876 static bool attr_w cgen_rot(struct codegen_context *ctx, unsigned size, uint8_t rot)
878         uint8_t *arg1 = ctx->code_position;
879         uint8_t *arg2 = arg1 + arg_size(*arg1);
880         uint8_t *arg3 = arg2 + arg_size(*arg2);
881         ctx->code_position = arg3 + arg_size(*arg3);
883         if (arg1[0] != arg2[0])
884                 internal(file_line, "cgen_rot: invalid arguments: %x, %02x, %02x, %02x", rot, arg1[0], arg2[0], arg3[0]);
886         if (arg3[0] == R_CX) {
887                 g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ROT_RM8_CL : X86_ROT_RM16_CL, size, false, rot, arg1));
888         } else if (likely(arg3[0] == ARG_IMM)) {
889                 int64_t imm;
890                 imm = get_imm(&arg1[3]);
891                 if (imm == 1) {
892                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ROT_RM8_1 : X86_ROT_RM16_1, size, false, rot, arg1));
893                 } else {
894                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, size == OP_SIZE_1 ? X86_ROT_RM8_IMM8 : X86_ROT_RM16_IMM8, size, false, rot, arg1));
895                         cgen_one(imm);
896                 }
897         } else {
898                 internal(file_line, "cgen_rot: invalid argument %02x", arg3[0]);
899         }
900         return true;
903 static bool attr_w cgen_btxt(struct codegen_context *ctx, unsigned size, uint8_t bt, uint8_t *arg1, uint8_t *arg2)
905         if (arg2[0] == ARG_IMM) {
906                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_BTX_RM16_IMM8, size, false, X86_0F_BTX_BT_RM16_IMM8 + bt, arg1));
907                 cgen_one(arg2[1]);
908         } else {
909                 g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_BT_RM16_R16 + bt * 8, size, true, arg2[0], arg1));
910         }
911         return true;
914 static bool attr_w cgen_bt(struct codegen_context *ctx, unsigned size)
916         uint8_t *arg1 = ctx->code_position;
917         uint8_t *arg2 = arg1 + arg_size(*arg1);
918         ctx->code_position = arg2 + arg_size(*arg2);
920         return cgen_btxt(ctx, size, BTX_BT, arg1, arg2);
923 static bool attr_w cgen_btx(struct codegen_context *ctx, unsigned size, uint8_t bt)
925         uint8_t *arg1 = ctx->code_position;
926         uint8_t *arg2 = arg1 + arg_size(*arg1);
927         uint8_t *arg3 = arg2 + arg_size(*arg2);
928         ctx->code_position = arg3 + arg_size(*arg3);
930         if (arg1[0] != arg2[0])
931                 internal(file_line, "cgen_btx: invalid arguments");
933         return cgen_btxt(ctx, size, bt, arg1, arg3);
936 static bool attr_w cgen_mul_l(struct codegen_context *ctx, unsigned size, bool sgn)
938         uint8_t *arg1, *arg2, *arg3, *arg4;
939         uint32_t reg_up;
940         arg1 = ctx->code_position;
941         arg2 = arg1 + arg_size(*arg1);
942         arg3 = arg2 + arg_size(*arg2);
943         arg4 = arg3 + arg_size(*arg3);
944         ctx->code_position = arg4 + arg_size(*arg4);
945         reg_up = size == OP_SIZE_1 ? R_AX : R_DX;
946         if (unlikely(arg1[0] != R_AX) || unlikely(arg2[0] != reg_up) || unlikely(arg3[0] != R_AX) || unlikely(arg4[0] == ARG_IMM))
947                 internal(file_line, "cgen_mul_l: invalid mul arguments");
949         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));
950         return true;
953 static bool attr_w cgen_div_l(struct codegen_context *ctx, unsigned size, bool sgn)
955         uint8_t *arg1, *arg2, *arg3, *arg4, *arg5;
956         uint32_t reg_up;
957         arg1 = ctx->code_position;
958         arg2 = arg1 + arg_size(*arg1);
959         arg3 = arg2 + arg_size(*arg2);
960         arg4 = arg3 + arg_size(*arg3);
961         arg5 = arg4 + arg_size(*arg4);
962         ctx->code_position = arg5 + arg_size(*arg5);
963         reg_up = size == OP_SIZE_1 ? R_AX : R_DX;
964         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))
965                 internal(file_line, "cgen_div_l: invalid div arguments");
967         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));
968         return true;
971 static bool attr_w cgen_cmov(struct codegen_context *ctx, unsigned size, unsigned cond)
973         uint8_t *arg1 = ctx->code_position;
974         uint8_t *arg2 = arg1 + arg_size(*arg1);
975         uint8_t *arg3 = arg2 + arg_size(*arg2);
976         ctx->code_position = arg3 + arg_size(*arg3);
977         if (unlikely(arg1[0] != arg2[0]))
978                 internal(file_line, "cgen_cmov: invalid arguments");
979         g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_CMOVCC_R16_RM16 + cond, size, true, arg1[0], arg3));
980         return true;
983 static bool attr_w cgen_memcpy(struct codegen_context *ctx)
985         int64_t disp_dest, disp_src;
986         uint8_t *arg1, *arg2, *arg3;
987         arg1 = ctx->code_position;
988         arg2 = arg1 + arg_size(*arg1);
989         arg3 = arg2 + arg_size(*arg2);
990         ctx->code_position = arg3 + arg_size(*arg3);
991         if (unlikely(arg1[0] != ARG_ADDRESS_1_POST_I) || unlikely(arg2[0] != ARG_ADDRESS_1_POST_I) || unlikely(arg3[0] != R_CX))
992                 goto invl;
993         if (unlikely(arg1[1] != R_DI) || unlikely(arg2[1] != R_SI))
994                 goto invl;
995         disp_dest = get_imm(&arg1[2]);
996         disp_src = get_imm(&arg2[2]);
997         if (unlikely(disp_dest != 0) || unlikely(disp_src != 0))
998                 goto invl;
1000         cgen_one(X86_REPE);
1001         cgen_one(X86_MOVSB);
1002         return true;
1004 invl:
1005         internal(file_line, "cgen_memcpy: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1006         return false;
1009 static bool attr_w cgen_memset(struct codegen_context *ctx)
1011         int64_t disp_dest;
1012         uint8_t *arg1, *arg2, *arg3;
1013         arg1 = ctx->code_position;
1014         arg2 = arg1 + arg_size(*arg1);
1015         arg3 = arg2 + arg_size(*arg2);
1016         ctx->code_position = arg3 + arg_size(*arg3);
1017         if (unlikely(arg1[0] != ARG_ADDRESS_1_POST_I) || unlikely(arg2[0] != R_CX) || unlikely(arg3[0] != R_AX))
1018                 goto invl;
1019         if (unlikely(arg1[1] != R_DI))
1020                 goto invl;
1021         disp_dest = get_imm(&arg1[2]);
1022         if (unlikely(disp_dest != 0))
1023                 goto invl;
1025         cgen_one(X86_REPE);
1026         cgen_one(X86_STOSB);
1027         return true;
1029 invl:
1030         internal(file_line, "cgen_memset: invalid arguments %02x, %02x, %02x", *arg1, *arg2, *arg3);
1031         return false;
1034 static bool attr_w cgen_sse_cmp(struct codegen_context *ctx, unsigned size)
1036         uint8_t *arg1 = ctx->code_position;
1037         uint8_t *arg2 = arg1 + arg_size(*arg1);
1038         ctx->code_position = arg2 + arg_size(*arg2);
1039         g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_NONE: SSE_PREFIX_66, PREFIX_0F, X86_0F_UCOMISS_X128_RM32, false, arg1[0], 0, arg2));
1040         return true;
1043 static bool attr_w cgen_sse_alu(struct codegen_context *ctx, unsigned size, unsigned alu)
1045         uint8_t opcode;
1046         uint8_t *arg1 = ctx->code_position;
1047         uint8_t *arg2 = arg1 + arg_size(*arg1);
1048         uint8_t *arg3 = arg2 + arg_size(*arg2);
1049         ctx->code_position = arg3 + arg_size(*arg3);
1050         switch (alu) {
1051                 case FP_ALU_ADD:        opcode = X86_0F_ADDPS_X128_M32; break;
1052                 case FP_ALU_SUB:        opcode = X86_0F_SUBPS_X128_M32; break;
1053                 case FP_ALU_MUL:        opcode = X86_0F_MULPS_X128_M32; break;
1054                 case FP_ALU_DIV:        opcode = X86_0F_DIVPS_X128_M32; break;
1055                 default:                internal(file_line, "cgen_sse_alu: invalid alu %u", alu);
1056         }
1057         g(cgen_sse_insn(ctx, size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2, PREFIX_0F, opcode, false, arg1[0], arg2[0], arg3));
1058         return true;
1061 static bool attr_w cgen_sse_alu1(struct codegen_context *ctx, unsigned size, unsigned alu)
1063         uint8_t opcode;
1064         unsigned sse_pfx, sse_op_map;
1065         uint8_t *arg1 = ctx->code_position;
1066         uint8_t *arg2 = arg1 + arg_size(*arg1);
1067         ctx->code_position = arg2 + arg_size(*arg2);
1068         switch (alu) {
1069                 case FP_ALU1_SQRT:      if (size == OP_SIZE_4) {
1070                                                 sse_pfx = SSE_PREFIX_F3;
1071                                         } else if (size == OP_SIZE_8) {
1072                                                 sse_pfx = SSE_PREFIX_F2;
1073                                         } else {
1074                                                 goto fail;
1075                                         }
1076                                         sse_op_map = PREFIX_0F;
1077                                         opcode = X86_0F_SQRTPS_X128_M32;
1078                                         break;
1079                 case FP_ALU1_ROUND:
1080                 case FP_ALU1_FLOOR:
1081                 case FP_ALU1_CEIL:
1082                 case FP_ALU1_TRUNC:     sse_pfx = SSE_PREFIX_66;
1083                                         sse_op_map = PREFIX_0F_3A;
1084                                         if (size == OP_SIZE_4) {
1085                                                 opcode = X86_0F_3A_ROUNDSS_X128_M32;
1086                                         } else if (size == OP_SIZE_8) {
1087                                                 opcode = X86_0F_3A_ROUNDSD_X128_M64;
1088                                         } else {
1089                                                 goto fail;
1090                                         }
1091                                         break;
1092                 fail:
1093                 default:                internal(file_line, "cgen_sse_alu1: invalid alu %u, %u", alu, size);
1094         }
1095         g(cgen_sse_insn(ctx, sse_pfx, sse_op_map, opcode, false, arg1[0], arg1[0], arg2));
1096         if (OP_IS_ROUND(alu))
1097                 cgen_one(alu - FP_ALU1_ROUND);
1098         return true;
1101 static bool attr_w cgen_sse_from_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1103         uint8_t *arg1 = ctx->code_position;
1104         uint8_t *arg2 = arg1 + arg_size(*arg1);
1105         ctx->code_position = arg2 + arg_size(*arg2);
1106         g(cgen_sse_insn(ctx, fp_op_size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2, PREFIX_0F, X86_0F_CVTSI2SS_X128_RM32, int_op_size == OP_SIZE_8, arg1[0], R_XMM7, arg2));
1107         return true;
1110 static bool attr_w cgen_sse_to_int(struct codegen_context *ctx, unsigned int_op_size, unsigned fp_op_size)
1112         uint8_t *arg1 = ctx->code_position;
1113         uint8_t *arg2 = arg1 + arg_size(*arg1);
1114         ctx->code_position = arg2 + arg_size(*arg2);
1115         g(cgen_sse_insn(ctx, fp_op_size == OP_SIZE_4 ? SSE_PREFIX_F3 : SSE_PREFIX_F2, PREFIX_0F, X86_0F_CVTTSS2SI_X128_RM32, int_op_size == OP_SIZE_8, arg1[0], 0, arg2));
1116         return true;
1119 static bool attr_w cgen_sse_cvt(struct codegen_context *ctx, unsigned from_op_size, unsigned to_op_size)
1121         uint8_t *arg1 = ctx->code_position;
1122         uint8_t *arg2 = arg1 + arg_size(*arg1);
1123         ctx->code_position = arg2 + arg_size(*arg2);
1124         if (from_op_size == OP_SIZE_2 && to_op_size == OP_SIZE_4) {
1125                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F_38, X86_0F_38_CVTPH2PS_X128_RM64, false, arg1[0], 0, arg2));
1126                 return true;
1127         } else if (from_op_size == OP_SIZE_4 && to_op_size == OP_SIZE_2) {
1128                 g(cgen_sse_insn(ctx, SSE_PREFIX_66, PREFIX_0F_3A, X86_0F_3A_CVTPS2PH_RM64_X128, false, arg2[0], 0, arg1));
1129                 cgen_one(0x04);
1130                 return true;
1131         }
1132         internal(file_line, "cgen_sse_cvt: unsupported arguments %u, %u", from_op_size, to_op_size);
1133         return false;
1136 static bool attr_w cgen_x87_fld(struct codegen_context *ctx, unsigned size)
1138         unsigned c1, c2;
1139         uint8_t *arg1 = ctx->code_position;
1140         ctx->code_position = arg1 + arg_size(*arg1);
1141         if (arg1[0] >= R_ST0 && arg1[0] <= R_ST7)
1142                 size = OP_SIZE_4;
1143         switch (size) {
1144                 case OP_SIZE_4:
1145                         c1 = X87_FLD_RM32; c2 = X87_FLD_RM32_X; break;
1146                 case OP_SIZE_8:
1147                         c1 = X87_FLD_M64; c2 = X87_FLD_M64_X; break;
1148                 case OP_SIZE_10:
1149                         c1 = X87_FLD_M80; c2 = X87_FLD_M80_X; break;
1150                 default:
1151                         internal(file_line, "cgen_x87_fld: invalid size %u", size);
1152         }
1153         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1154         return true;
1157 static bool attr_w cgen_x87_fild(struct codegen_context *ctx, unsigned size)
1159         unsigned c1, c2;
1160         uint8_t *arg1 = ctx->code_position;
1161         ctx->code_position = arg1 + arg_size(*arg1);
1162         switch (size) {
1163                 case OP_SIZE_2:
1164                         c1 = X87_FILD_M16; c2 = X87_FILD_M16_X; break;
1165                 case OP_SIZE_4:
1166                         c1 = X87_FILD_M32; c2 = X87_FILD_M32_X; break;
1167                 case OP_SIZE_8:
1168                         c1 = X87_FILD_M64; c2 = X87_FILD_M64_X; break;
1169                 default:
1170                         internal(file_line, "cgen_x87_fild: invalid size %u", size);
1171         }
1172         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1173         return true;
1176 static bool attr_w cgen_x87_fstp(struct codegen_context *ctx, unsigned size)
1178         unsigned c1, c2;
1179         uint8_t *arg1 = ctx->code_position;
1180         ctx->code_position = arg1 + arg_size(*arg1);
1181         if (arg1[0] >= R_ST0 && arg1[0] <= R_ST7)
1182                 size = OP_SIZE_8;
1183         switch (size) {
1184                 case OP_SIZE_4:
1185                         c1 = X87_FSTP_M32; c2 = X87_FSTP_M32_X; break;
1186                 case OP_SIZE_8:
1187                         c1 = X87_FSTP_RM64; c2 = X87_FSTP_RM64_X; break;
1188                 case OP_SIZE_10:
1189                         c1 = X87_FSTP_M80; c2 = X87_FSTP_M80_X; break;
1190                 default:
1191                         internal(file_line, "cgen_x87_fstp: invalid size %u", size);
1192         }
1193         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1194         return true;
1197 static bool attr_w cgen_x87_fistp(struct codegen_context *ctx, unsigned size)
1199         unsigned c1, c2;
1200         uint8_t *arg1 = ctx->code_position;
1201         ctx->code_position = arg1 + arg_size(*arg1);
1202         switch (size) {
1203                 case OP_SIZE_2:
1204                         c1 = X87_FISTP_M16; c2 = X87_FISTP_M16_X; break;
1205                 case OP_SIZE_4:
1206                         c1 = X87_FISTP_M32; c2 = X87_FISTP_M32_X; break;
1207                 case OP_SIZE_8:
1208                         c1 = X87_FISTP_M64; c2 = X87_FISTP_M64_X; break;
1209                 default:
1210                         internal(file_line, "cgen_x87_fistp: invalid size %u", size);
1211         }
1212         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1213         return true;
1216 static bool attr_w cgen_x87_fisttp(struct codegen_context *ctx, unsigned size)
1218         unsigned c1, c2;
1219         uint8_t *arg1 = ctx->code_position;
1220         ctx->code_position = arg1 + arg_size(*arg1);
1221         switch (size) {
1222                 case OP_SIZE_2:
1223                         c1 = X87_FISTTP_M16; c2 = X87_FISTTP_M16_X; break;
1224                 case OP_SIZE_4:
1225                         c1 = X87_FISTTP_M32; c2 = X87_FISTTP_M32_X; break;
1226                 case OP_SIZE_8:
1227                         c1 = X87_FISTTP_M64; c2 = X87_FISTTP_M64_X; break;
1228                 default:
1229                         internal(file_line, "cgen_x87_fisttp: invalid size %u", size);
1230         }
1231         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1232         return true;
1235 static bool attr_w cgen_x87_fcomp(struct codegen_context *ctx, unsigned size)
1237         unsigned c1, c2;
1238         uint8_t *arg1 = ctx->code_position;
1239         ctx->code_position = arg1 + arg_size(*arg1);
1240         if (arg1[0] < ARG_REGS_MAX) {
1241                 c1 = X87_FALU_ST_RM32;
1242         } else switch (size) {
1243                 case OP_SIZE_4:
1244                         c1 = X87_FALU_ST_RM32; break;
1245                 case OP_SIZE_8:
1246                         c1 = X87_FALU_ST_M64; break;
1247                 default:
1248                         internal(file_line, "cgen_x87_fcomp: invalid size %u", size);
1249         }
1250         c2 = X87_ALU_FCOMP;
1251         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1252         return true;
1255 static bool attr_w cgen_x87_alu(struct codegen_context *ctx, unsigned size, unsigned aux)
1257         unsigned c1, c2;
1258         uint8_t *arg1 = ctx->code_position;
1259         ctx->code_position = arg1 + arg_size(*arg1);
1260         if (arg1[0] < ARG_REGS_MAX) {
1261                 c1 = X87_FALU_ST_RM32;
1262         } else switch (size) {
1263                 case OP_SIZE_4:
1264                         c1 = X87_FALU_ST_RM32; break;
1265                 case OP_SIZE_8:
1266                         c1 = X87_FALU_ST_M64; break;
1267                 default:
1268                         internal(file_line, "cgen_x87_alu: invalid size %u", size);
1269         }
1270         switch (aux) {
1271                 case FP_ALU_ADD:
1272                         c2 = X87_ALU_ADD; break;
1273                 case FP_ALU_SUB:
1274                         c2 = X87_ALU_SUB; break;
1275                 case FP_ALU_MUL:
1276                         c2 = X87_ALU_MUL; break;
1277                 case FP_ALU_DIV:
1278                         c2 = X87_ALU_DIV; break;
1279                 default:
1280                         internal(file_line, "cgen_x87_fst: invalid operation %u", aux);
1281         }
1282         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, c1, OP_SIZE_4, false, c2, arg1));
1283         return true;
1286 static bool attr_w cgen_x87_alup(struct codegen_context *ctx, unsigned aux)
1288         unsigned c2;
1289         uint8_t *arg1 = ctx->code_position;
1290         ctx->code_position = arg1 + arg_size(*arg1);
1291         switch (aux) {
1292                 case FP_ALU_ADD:
1293                         c2 = X87_ALU_ADD; break;
1294                 case FP_ALU_SUB:
1295                         c2 = X87_ALU_SUB; break;
1296                 case FP_ALU_MUL:
1297                         c2 = X87_ALU_MUL; break;
1298                 case FP_ALU_DIV:
1299                         c2 = X87_ALU_DIV; break;
1300                 default:
1301                         internal(file_line, "cgen_x87_fstp: invalid operation %u", aux);
1302         }
1303         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X87_FALUP_STi_ST0, OP_SIZE_4, false, c2, arg1));
1304         return true;
1307 static bool attr_w resolve_relocation(struct codegen_context *ctx, struct relocation *reloc)
1309         int64_t offs = (int64_t)ctx->label_to_pos[reloc->label_id] - (int64_t)(reloc->position + (reloc->length == JMP_SHORT ? 1 : 4));
1310         switch (reloc->length) {
1311                 case JMP_SHORT: {
1312                         int8_t i8;
1313                         if (!imm_is_8bit(offs))
1314                                 return false;
1315                         i8 = offs;
1316                         memcpy(ctx->mcode + reloc->position, &i8, 1);
1317                         return true;
1318                 }
1319                 case JMP_LONG: {
1320                         int32_t i32;
1321                         if (!imm_is_32bit(offs))
1322                                 return false;
1323                         i32 = offs;
1324                         memcpy(ctx->mcode + reloc->position, &i32, 4);
1325                         return true;
1326                 }
1327                 default: {
1328                         internal(file_line, "resolve_relocation: invalid relocation length %u", reloc->length);
1329                         return false;
1330                 }
1331         }
1334 static bool attr_w cgen_insn(struct codegen_context *ctx, uint32_t insn)
1336         uint8_t imm8;
1337         uint16_t imm16;
1338         /*debug("insn: %08x", insn);*/
1339         switch (insn_opcode(insn)) {
1340                 case INSN_ENTRY:
1341                         g(cgen_entry(ctx));
1342                         return true;
1343                 case INSN_LABEL:
1344                         g(cgen_label(ctx));
1345                         return true;
1346                 case INSN_RET:
1347                         cgen_one(X86_RET);
1348                         return true;
1349                 case INSN_RET_IMM:
1350                         imm16 = cget_two(ctx);
1351                         cgen_one(X86_RET_IMM16);
1352                         cgen_two(imm16);
1353                         return true;
1354                 case INSN_PUSH:
1355                         g(cgen_push(ctx));
1356                         return true;
1357                 case INSN_POP:
1358                         g(cgen_pop(ctx));
1359                         return true;
1360                 case INSN_CALL_INDIRECT:
1361                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_FF, OP_SIZE_4, false, X86_FF_CALL_INDIRECT, ctx->code_position));
1362                         ctx->code_position += arg_size(*ctx->code_position);
1363                         return true;
1364                 case INSN_MOV:
1365                         g(cgen_mov(ctx, insn_op_size(insn)));
1366                         return true;
1367                 case INSN_MOVSX:
1368                         g(cgen_movsx(ctx, insn_op_size(insn)));
1369                         return true;
1370                 case INSN_CMP:
1371                         g(cgen_alu(ctx, insn_op_size(insn), 7));
1372                         return true;
1373                 case INSN_TEST:
1374                         g(cgen_test(ctx, insn_op_size(insn)));
1375                         return true;
1376                 case INSN_ALU:
1377                 case INSN_ALU_FLAGS:
1378                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1379                                 goto invalid_insn;
1380                         if (!insn_writes_flags(insn) && insn_op_size(insn) <= OP_SIZE_8) {
1381                                 if (unlikely(insn_aux(insn) != ALU_ADD))
1382                                         goto invalid_insn;
1383                                 g(cgen_lea(ctx, insn_op_size(insn)));
1384                                 return true;
1385                         }
1386                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1387                         return true;
1388                 case INSN_ALU_PARTIAL:
1389                 case INSN_ALU_FLAGS_PARTIAL:
1390                         if (unlikely(insn_op_size(insn) >= OP_SIZE_4))
1391                                 goto invalid_insn;
1392                         g(cgen_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1393                         return true;
1394                 case INSN_ALU1:
1395                 case INSN_ALU1_FLAGS:
1396                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1397                                 goto invalid_insn;
1398                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1399                         return true;
1400                 case INSN_ALU1_PARTIAL:
1401                 case INSN_ALU1_FLAGS_PARTIAL:
1402                         if (unlikely(insn_op_size(insn) >= OP_SIZE_4))
1403                                 goto invalid_insn;
1404                         g(cgen_alu1(ctx, insn_op_size(insn), insn_aux(insn), insn_writes_flags(insn)));
1405                         return true;
1406                 case INSN_LEA3:
1407                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1408                                 goto invalid_insn;
1409                         g(cgen_lea3(ctx, insn_op_size(insn), insn_aux(insn)));
1410                         return true;
1411                 case INSN_ROT:
1412                         if (unlikely(insn_op_size(insn) < OP_SIZE_4))
1413                                 goto invalid_insn;
1414                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1415                         return true;
1416                 case INSN_ROT_PARTIAL:
1417                         if (unlikely(insn_op_size(insn) >= OP_SIZE_4))
1418                                 goto invalid_insn;
1419                         g(cgen_rot(ctx, insn_op_size(insn), insn_aux(insn)));
1420                         return true;
1421                 case INSN_BT:
1422                         if (unlikely(insn_op_size(insn) == OP_SIZE_1) || unlikely(!insn_writes_flags(insn)))
1423                                 goto invalid_insn;
1424                         g(cgen_bt(ctx, insn_op_size(insn)));
1425                         return true;
1426                 case INSN_BTX:
1427                         if (unlikely(insn_op_size(insn) == OP_SIZE_1) || unlikely(!insn_writes_flags(insn)))
1428                                 goto invalid_insn;
1429                         g(cgen_btx(ctx, insn_op_size(insn), insn_aux(insn)));
1430                         return true;
1431                 case INSN_MUL_L:
1432                         g(cgen_mul_l(ctx, insn_op_size(insn), insn_aux(insn)));
1433                         return true;
1434                 case INSN_DIV_L:
1435                         g(cgen_div_l(ctx, insn_op_size(insn), insn_aux(insn)));
1436                         return true;
1437                 case INSN_CBW:
1438                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2))
1439                                 goto invalid_insn;
1440                         if (insn_op_size(insn) == OP_SIZE_8)
1441                                 cgen_rex(X86_REX | X86_REX_W);
1442                         if (unlikely(cget_one(ctx) != R_AX))
1443                                 goto invalid_insn;
1444                         if (unlikely(cget_one(ctx) != R_AX))
1445                                 goto invalid_insn;
1446                         cgen_one(X86_CBW);
1447                         return true;
1448                 case INSN_CBW_PARTIAL:
1449                         if (unlikely(insn_op_size(insn) != OP_SIZE_2))
1450                                 goto invalid_insn;
1451                         if (unlikely(cget_one(ctx) != R_AX))
1452                                 goto invalid_insn;
1453                         if (unlikely(cget_one(ctx) != R_AX))
1454                                 goto invalid_insn;
1455                         cgen_one(X86_OP_SIZE);
1456                         cgen_one(X86_CBW);
1457                         return true;
1458                 case INSN_CWD:
1459                         if (unlikely(insn_op_size(insn) <= OP_SIZE_2))
1460                                 goto invalid_insn;
1461                         if (unlikely(cget_one(ctx) != R_DX))
1462                                 goto invalid_insn;
1463                         if (unlikely(cget_one(ctx) != R_AX))
1464                                 goto invalid_insn;
1465                         if (insn_op_size(insn) == OP_SIZE_8)
1466                                 cgen_rex(X86_REX | X86_REX_W);
1467                         cgen_one(X86_CWD);
1468                         return true;
1469                 case INSN_CWD_PARTIAL:
1470                         if (unlikely(insn_op_size(insn) != OP_SIZE_2))
1471                                 goto invalid_insn;
1472                         if (unlikely(cget_one(ctx) != R_DX))
1473                                 goto invalid_insn;
1474                         if (unlikely(cget_one(ctx) != R_AX))
1475                                 goto invalid_insn;
1476                         if (unlikely(cget_one(ctx) != R_DX))
1477                                 goto invalid_insn;
1478                         cgen_one(X86_OP_SIZE);
1479                         cgen_one(X86_CWD);
1480                         return true;
1481                 case INSN_SET_COND:
1482                         if (unlikely(insn_op_size(insn) != OP_SIZE_1))
1483                                 goto invalid_insn;
1484                         g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_SETCC_RM8 + (insn_aux(insn) & 0xf), OP_SIZE_1, false, 0, ctx->code_position));
1485                         ctx->code_position += arg_size(*ctx->code_position);
1486                         return true;
1487                 case INSN_SET_COND_PARTIAL:
1488                         if (unlikely(insn_op_size(insn) != OP_SIZE_1))
1489                                 goto invalid_insn;
1490                         g(cgen_rm_insn(ctx, -1, PREFIX_0F, X86_0F_SETCC_RM8 + (insn_aux(insn) & 0xf), OP_SIZE_1, false, 0, ctx->code_position));
1491                         ctx->code_position += arg_size(*ctx->code_position);
1492                         ctx->code_position += arg_size(*ctx->code_position);
1493                         return true;
1494                 case INSN_CMOV:
1495                 case INSN_CMOV_XCC:
1496                         if (unlikely(insn_op_size(insn) == OP_SIZE_1))
1497                                 goto invalid_insn;
1498                         g(cgen_cmov(ctx, insn_op_size(insn), insn_aux(insn)));
1499                         return true;
1500                 case INSN_MEMCPY:
1501                         g(cgen_memcpy(ctx));
1502                         return true;
1503                 case INSN_MEMSET:
1504                         g(cgen_memset(ctx));
1505                         return true;
1506                 case INSN_FP_CMP:
1507                         g(cgen_sse_cmp(ctx, insn_op_size(insn)));
1508                         return true;
1509                 case INSN_FP_ALU:
1510                         g(cgen_sse_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1511                         return true;
1512                 case INSN_FP_ALU1:
1513                         g(cgen_sse_alu1(ctx, insn_op_size(insn), insn_aux(insn)));
1514                         return true;
1515                 case INSN_FP_FROM_INT32:
1516                 case INSN_FP_FROM_INT64:
1517                         g(cgen_sse_from_int(ctx, insn_opcode(insn) == INSN_FP_FROM_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1518                         return true;
1519                 case INSN_FP_TO_INT32:
1520                 case INSN_FP_TO_INT64:
1521                         g(cgen_sse_to_int(ctx, insn_opcode(insn) == INSN_FP_TO_INT32 ? OP_SIZE_4 : OP_SIZE_8, insn_op_size(insn)));
1522                         return true;
1523                 case INSN_FP_CVT:
1524                         g(cgen_sse_cvt(ctx, insn_op_size(insn), insn_aux(insn)));
1525                         return true;
1526                 case INSN_X87_FLD:
1527                         g(cgen_x87_fld(ctx, insn_op_size(insn)));
1528                         return true;
1529                 case INSN_X87_FILD:
1530                         g(cgen_x87_fild(ctx, insn_op_size(insn)));
1531                         return true;
1532                 case INSN_X87_FSTP:
1533                         g(cgen_x87_fstp(ctx, insn_op_size(insn)));
1534                         return true;
1535                 case INSN_X87_FISTP:
1536                         g(cgen_x87_fistp(ctx, insn_op_size(insn)));
1537                         return true;
1538                 case INSN_X87_FISTTP:
1539                         g(cgen_x87_fisttp(ctx, insn_op_size(insn)));
1540                         return true;
1541                 case INSN_X87_FCOMP:
1542                         g(cgen_x87_fcomp(ctx, insn_op_size(insn)));
1543                         return true;
1544                 case INSN_X87_FCOMPP:
1545                         cgen_one(X87_FCOMPP);
1546                         cgen_one(X87_FCOMPP_2);
1547                         return true;
1548                 case INSN_X87_FCOMIP:
1549                         imm8 = cget_one(ctx);
1550                         cgen_one(X87_FCOMIP);
1551                         cgen_one(X87_FCOMIP_2 + (imm8 & 7));
1552                         return true;
1553                 case INSN_X87_ALU:
1554                         g(cgen_x87_alu(ctx, insn_op_size(insn), insn_aux(insn)));
1555                         return true;
1556                 case INSN_X87_ALUP:
1557                         g(cgen_x87_alup(ctx, insn_aux(insn)));
1558                         return true;
1559                 case INSN_X87_FCHS:
1560                         cgen_one(X87_FCHS);
1561                         cgen_one(X87_FCHS_2);
1562                         return true;
1563                 case INSN_X87_FSQRT:
1564                         cgen_one(X87_FSQRT);
1565                         cgen_one(X87_FSQRT_2);
1566                         return true;
1567                 case INSN_X87_FRNDINT:
1568                         cgen_one(X87_FRNDINT);
1569                         cgen_one(X87_FRNDINT_2);
1570                         return true;
1571                 case INSN_X87_FNSTSW:
1572                         if (unlikely(cget_one(ctx) != R_AX))
1573                                 goto invalid_insn;
1574                         if (unlikely(cget_one(ctx) != R_AX))
1575                                 goto invalid_insn;
1576                         cgen_one(X87_FNSTSW);
1577                         cgen_one(X87_FNSTSW_2);
1578                         return true;
1579                 case INSN_X87_FLDCW:
1580                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X87_FLDCW, OP_SIZE_4, false, X87_FLDCW_X, ctx->code_position));
1581                         ctx->code_position += arg_size(*ctx->code_position);
1582                         return true;
1583                 case INSN_JMP:
1584                         if (insn_jump_size(insn) == JMP_SHORT || insn_jump_size(insn) == JMP_SHORTEST) {
1585                                 cgen_one(X86_JMP_8);
1586                                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1587                                 cgen_one(0);
1588                         } else if (likely(insn_jump_size(insn) == JMP_LONG)) {
1589                                 cgen_one(X86_JMP_16);
1590                                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1591                                 cgen_four(0);
1592                         } else {
1593                                 goto invalid_insn;
1594                         }
1595                         return true;
1596                 case INSN_JMP_COND:
1597                         if (insn_jump_size(insn) == JMP_SHORT || insn_jump_size(insn) == JMP_SHORTEST) {
1598                                 cgen_one(X86_JCC_8 + (insn_aux(insn) & 0xf));
1599                                 g(add_relocation(ctx, JMP_SHORT, 0, NULL));
1600                                 cgen_one(0);
1601                         } else if (likely(insn_jump_size(insn) == JMP_LONG)) {
1602                                 cgen_one(X86_0F);
1603                                 cgen_one(X86_0F_JCC_16 + (insn_aux(insn) & 0xf));
1604                                 g(add_relocation(ctx, JMP_LONG, 0, NULL));
1605                                 cgen_four(0);
1606                         } else {
1607                                 goto invalid_insn;
1608                         }
1609                         return true;
1610                 case INSN_JMP_INDIRECT:
1611                         g(cgen_rm_insn(ctx, -1, PREFIX_NONE, X86_FF, OP_SIZE_4, false, X86_FF_JMP_INDIRECT, ctx->code_position));
1612                         ctx->code_position += arg_size(*ctx->code_position);
1613                         return true;
1614                 default:
1615                 invalid_insn:
1616                         internal(file_line, "cgen_insn: invalid insn %08lx", (unsigned long)insn);
1617                         return false;
1618         }