OLD | NEW |
1 /* | 1 /* |
2 * x86 identifier recognition and instruction handling | 2 * x86 identifier recognition and instruction handling |
3 * | 3 * |
4 * Copyright (C) 2002-2007 Peter Johnson | 4 * Copyright (C) 2002-2007 Peter Johnson |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' | 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE | 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * POSSIBILITY OF SUCH DAMAGE. | 25 * POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 #include <ctype.h> | 27 #include <ctype.h> |
28 #include <util.h> | 28 #include <util.h> |
29 RCSID("$Id: x86id.c 2279 2010-01-19 07:57:43Z peter $"); | |
30 | 29 |
31 #include <libyasm.h> | 30 #include <libyasm.h> |
32 #include <libyasm/phash.h> | 31 #include <libyasm/phash.h> |
33 | 32 |
34 #include "modules/arch/x86/x86arch.h" | 33 #include "modules/arch/x86/x86arch.h" |
35 | 34 |
36 | 35 |
37 static const char *cpu_find_reverse(unsigned int cpu0, unsigned int cpu1, | 36 static const char *cpu_find_reverse(unsigned int cpu0, unsigned int cpu1, |
38 unsigned int cpu2); | 37 unsigned int cpu2); |
39 | 38 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 */ | 103 */ |
105 OPT_MemOffs = 21, | 104 OPT_MemOffs = 21, |
106 OPT_Imm1 = 22, /* immediate, value=1 (for special-case shift) */ | 105 OPT_Imm1 = 22, /* immediate, value=1 (for special-case shift) */ |
107 /* immediate, does not contain SEG:OFF (for jmp/call) */ | 106 /* immediate, does not contain SEG:OFF (for jmp/call) */ |
108 OPT_ImmNotSegOff = 23, | 107 OPT_ImmNotSegOff = 23, |
109 OPT_XMM0 = 24, /* XMM0 */ | 108 OPT_XMM0 = 24, /* XMM0 */ |
110 /* AX/EAX/RAX memory operand only (EA) [special case for SVM opcodes] | 109 /* AX/EAX/RAX memory operand only (EA) [special case for SVM opcodes] |
111 */ | 110 */ |
112 OPT_MemrAX = 25, | 111 OPT_MemrAX = 25, |
113 /* EAX memory operand only (EA) [special case for SVM skinit opcode] */ | 112 /* EAX memory operand only (EA) [special case for SVM skinit opcode] */ |
114 OPT_MemEAX = 26 | 113 OPT_MemEAX = 26, |
| 114 /* XMM VSIB memory operand */ |
| 115 OPT_MemXMMIndex = 27, |
| 116 /* YMM VSIB memory operand */ |
| 117 OPT_MemYMMIndex = 28 |
115 }; | 118 }; |
116 | 119 |
117 enum x86_operand_size { | 120 enum x86_operand_size { |
118 /* any size acceptable/no size spec acceptable (dep. on strict) */ | 121 /* any size acceptable/no size spec acceptable (dep. on strict) */ |
119 OPS_Any = 0, | 122 OPS_Any = 0, |
120 /* 8/16/32/64/80/128/256 bits (from user or reg size) */ | 123 /* 8/16/32/64/80/128/256 bits (from user or reg size) */ |
121 OPS_8 = 1, | 124 OPS_8 = 1, |
122 OPS_16 = 2, | 125 OPS_16 = 2, |
123 OPS_32 = 3, | 126 OPS_32 = 3, |
124 OPS_64 = 4, | 127 OPS_64 = 4, |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 x86_id_insn_finalize, | 343 x86_id_insn_finalize, |
341 NULL, | 344 NULL, |
342 yasm_bc_calc_len_common, | 345 yasm_bc_calc_len_common, |
343 yasm_bc_expand_common, | 346 yasm_bc_expand_common, |
344 yasm_bc_tobytes_common, | 347 yasm_bc_tobytes_common, |
345 YASM_BC_SPECIAL_INSN | 348 YASM_BC_SPECIAL_INSN |
346 }; | 349 }; |
347 | 350 |
348 #include "x86insns.c" | 351 #include "x86insns.c" |
349 | 352 |
| 353 /* Looks for the first SIMD register match for the purposes of VSIB matching. |
| 354 * Full legality checking is performed in EA code. |
| 355 */ |
| 356 static int |
| 357 x86_expr_contains_simd_cb(const yasm_expr__item *ei, void *d) |
| 358 { |
| 359 int ymm = *((int *)d); |
| 360 if (ei->type != YASM_EXPR_REG) |
| 361 return 0; |
| 362 switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) { |
| 363 case X86_XMMREG: |
| 364 if (!ymm) |
| 365 return 1; |
| 366 break; |
| 367 case X86_YMMREG: |
| 368 if (ymm) |
| 369 return 1; |
| 370 break; |
| 371 default: |
| 372 break; |
| 373 } |
| 374 return 0; |
| 375 } |
| 376 |
| 377 static int |
| 378 x86_expr_contains_simd(const yasm_expr *e, int ymm) |
| 379 { |
| 380 return yasm_expr__traverse_leaves_in_const(e, &ymm, |
| 381 x86_expr_contains_simd_cb); |
| 382 } |
| 383 |
350 static void | 384 static void |
351 x86_finalize_common(x86_common *common, const x86_insn_info *info, | 385 x86_finalize_common(x86_common *common, const x86_insn_info *info, |
352 unsigned int mode_bits) | 386 unsigned int mode_bits) |
353 { | 387 { |
354 common->addrsize = 0; | 388 common->addrsize = 0; |
355 common->opersize = info->opersize; | 389 common->opersize = info->opersize; |
356 common->lockrep_pre = 0; | 390 common->lockrep_pre = 0; |
357 common->mode_bits = (unsigned char)mode_bits; | 391 common->mode_bits = (unsigned char)mode_bits; |
358 } | 392 } |
359 | 393 |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 break; | 878 break; |
845 } | 879 } |
846 case OPT_MemEAX: { | 880 case OPT_MemEAX: { |
847 const uintptr_t *regp; | 881 const uintptr_t *regp; |
848 if (op->type != YASM_INSN__OPERAND_MEMORY || | 882 if (op->type != YASM_INSN__OPERAND_MEMORY || |
849 !(regp = yasm_expr_get_reg(&op->data.ea->disp.abs, 0)) |
| | 883 !(regp = yasm_expr_get_reg(&op->data.ea->disp.abs, 0)) |
| |
850 *regp != (X86_REG32 | 0)) | 884 *regp != (X86_REG32 | 0)) |
851 mismatch = 1; | 885 mismatch = 1; |
852 break; | 886 break; |
853 } | 887 } |
| 888 case OPT_MemXMMIndex: |
| 889 if (op->type != YASM_INSN__OPERAND_MEMORY || |
| 890 !x86_expr_contains_simd(op->data.ea->disp.abs, 0)) |
| 891 mismatch = 1; |
| 892 break; |
| 893 case OPT_MemYMMIndex: |
| 894 if (op->type != YASM_INSN__OPERAND_MEMORY || |
| 895 !x86_expr_contains_simd(op->data.ea->disp.abs, 1)) |
| 896 mismatch = 1; |
| 897 break; |
854 default: | 898 default: |
855 yasm_internal_error(N_("invalid operand type")); | 899 yasm_internal_error(N_("invalid operand type")); |
856 } | 900 } |
857 | 901 |
858 if (mismatch) | 902 if (mismatch) |
859 break; | 903 break; |
860 | 904 |
861 /* Check operand size */ | 905 /* Check operand size */ |
862 size = size_lookup[info_ops[i].size]; | 906 size = size_lookup[info_ops[i].size]; |
863 if (id_insn->parser == X86_PARSER_GAS) { | 907 if (id_insn->parser == X86_PARSER_GAS) { |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 yasm_internal_error( | 1268 yasm_internal_error( |
1225 N_("invalid operand conversion")); | 1269 N_("invalid operand conversion")); |
1226 case YASM_INSN__OPERAND_MEMORY: | 1270 case YASM_INSN__OPERAND_MEMORY: |
1227 if (op->seg) | 1271 if (op->seg) |
1228 yasm_error_set(YASM_ERROR_VALUE, | 1272 yasm_error_set(YASM_ERROR_VALUE, |
1229 N_("invalid segment in effective address")); | 1273 N_("invalid segment in effective address")); |
1230 insn->x86_ea = (x86_effaddr *)op->data.ea; | 1274 insn->x86_ea = (x86_effaddr *)op->data.ea; |
1231 if (info_ops[i].type == OPT_MemOffs) | 1275 if (info_ops[i].type == OPT_MemOffs) |
1232 /* Special-case for MOV MemOffs instruction */ | 1276 /* Special-case for MOV MemOffs instruction */ |
1233 yasm_x86__ea_set_disponly(insn->x86_ea); | 1277 yasm_x86__ea_set_disponly(insn->x86_ea); |
1234 else if (id_insn->default_rel && | 1278 else if (info_ops[i].type == OPT_MemXMMIndex) { |
1235 !op->data.ea->not_pc_rel && | 1279 /* Remember VSIB mode */ |
1236 op->data.ea->segreg != 0x6404 && | 1280 insn->x86_ea->vsib_mode = 1; |
1237 op->data.ea->segreg != 0x6505 && | 1281 insn->x86_ea->need_sib = 1; |
1238 !yasm_expr__contains( | 1282 } else if (info_ops[i].type == OPT_MemYMMIndex) { |
1239 op->data.ea->disp.abs, YASM_EXPR_REG)) | 1283 /* Remember VSIB mode */ |
| 1284 insn->x86_ea->vsib_mode = 2; |
| 1285 insn->x86_ea->need_sib = 1; |
| 1286 } else if (id_insn->default_rel && |
| 1287 !op->data.ea->not_pc_rel && |
| 1288 op->data.ea->segreg != 0x6404 && |
| 1289 op->data.ea->segreg != 0x6505 && |
| 1290 !yasm_expr__contains( |
| 1291 op->data.ea->disp.abs, YASM_EXPR_REG)) |
1240 /* Enable default PC-rel if no regs and segreg | 1292 /* Enable default PC-rel if no regs and segreg |
1241 * is not FS or GS. | 1293 * is not FS or GS. |
1242 */ | 1294 */ |
1243 insn->x86_ea->ea.pc_rel = 1; | 1295 insn->x86_ea->ea.pc_rel = 1; |
1244 break; | 1296 break; |
1245 case YASM_INSN__OPERAND_IMM: | 1297 case YASM_INSN__OPERAND_IMM: |
1246 insn->x86_ea = | 1298 insn->x86_ea = |
1247 yasm_x86__ea_create_imm(insn->x86_ea, | 1299 yasm_x86__ea_create_imm(insn->x86_ea, |
1248 op->data.val, | 1300 op->data.val, |
1249 size_lookup[info_ops[i].size]); | 1301 size_lookup[info_ops[i].size]); |
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 id_insn->mode_bits = arch_x86->mode_bits; | 1940 id_insn->mode_bits = arch_x86->mode_bits; |
1889 id_insn->suffix = (PARSER(arch_x86) == X86_PARSER_GAS) ? SUF_Z : 0; | 1941 id_insn->suffix = (PARSER(arch_x86) == X86_PARSER_GAS) ? SUF_Z : 0; |
1890 id_insn->misc_flags = 0; | 1942 id_insn->misc_flags = 0; |
1891 id_insn->parser = PARSER(arch_x86); | 1943 id_insn->parser = PARSER(arch_x86); |
1892 id_insn->force_strict = arch_x86->force_strict != 0; | 1944 id_insn->force_strict = arch_x86->force_strict != 0; |
1893 id_insn->default_rel = arch_x86->default_rel != 0; | 1945 id_insn->default_rel = arch_x86->default_rel != 0; |
1894 | 1946 |
1895 return yasm_bc_create_common(&x86_id_insn_callback, id_insn, line); | 1947 return yasm_bc_create_common(&x86_id_insn_callback, id_insn, line); |
1896 } | 1948 } |
1897 | 1949 |
OLD | NEW |