リビジョン | b9f9c5b41aab06479cb1695990b7cca98ef84fc7 (tree) |
---|---|
日時 | 2016-03-15 02:53:07 |
作者 | Richard Henderson <rth@twid...> |
コミッター | Richard Henderson |
target-i386: Dump unknown opcodes with -d unimp
We discriminate here between opcodes that are illegal in the current
cpu mode or with illegal arguments (such as modrm.mod == 3) and
encodings that are unknown (such as an unimplemented isa extension).
Signed-off-by: Richard Henderson <rth@twiddle.net>
@@ -99,6 +99,7 @@ typedef struct DisasContext { | ||
99 | 99 | int prefix; |
100 | 100 | TCGMemOp aflag; |
101 | 101 | TCGMemOp dflag; |
102 | + target_ulong pc_start; | |
102 | 103 | target_ulong pc; /* pc = eip + cs_base */ |
103 | 104 | int is_jmp; /* 1 = means jump (stop translation), 2 means CPU |
104 | 105 | static state change (stop translation) */ |
@@ -2368,6 +2369,30 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) | ||
2368 | 2369 | s->is_jmp = DISAS_TB_JUMP; |
2369 | 2370 | } |
2370 | 2371 | |
2372 | +/* Generate #UD for the current instruction. The assumption here is that | |
2373 | + the instruction is known, but it isn't allowed in the current cpu mode. */ | |
2374 | +static void gen_illegal_opcode(DisasContext *s) | |
2375 | +{ | |
2376 | + gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base); | |
2377 | +} | |
2378 | + | |
2379 | +/* Similarly, except that the assumption here is that we don't decode | |
2380 | + the instruction at all -- either a missing opcode, an unimplemented | |
2381 | + feature, or just a bogus instruction stream. */ | |
2382 | +static void gen_unknown_opcode(CPUX86State *env, DisasContext *s) | |
2383 | +{ | |
2384 | + gen_illegal_opcode(s); | |
2385 | + | |
2386 | + if (qemu_loglevel_mask(LOG_UNIMP)) { | |
2387 | + target_ulong pc = s->pc_start, end = s->pc; | |
2388 | + qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc); | |
2389 | + for (; pc < end; ++pc) { | |
2390 | + qemu_log(" %02x", cpu_ldub_code(env, pc)); | |
2391 | + } | |
2392 | + qemu_log("\n"); | |
2393 | + } | |
2394 | +} | |
2395 | + | |
2371 | 2396 | /* an interrupt is different from an exception because of the |
2372 | 2397 | privilege checks */ |
2373 | 2398 | static void gen_interrupt(DisasContext *s, int intno, |
@@ -2887,7 +2912,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
2887 | 2912 | b1 = 0; |
2888 | 2913 | sse_fn_epp = sse_op_table1[b][b1]; |
2889 | 2914 | if (!sse_fn_epp) { |
2890 | - goto illegal_op; | |
2915 | + goto unknown_op; | |
2891 | 2916 | } |
2892 | 2917 | if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) { |
2893 | 2918 | is_xmm = 1; |
@@ -2906,15 +2931,19 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
2906 | 2931 | } |
2907 | 2932 | if (s->flags & HF_EM_MASK) { |
2908 | 2933 | illegal_op: |
2909 | - gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); | |
2934 | + gen_illegal_opcode(s); | |
2910 | 2935 | return; |
2911 | 2936 | } |
2912 | - if (is_xmm && !(s->flags & HF_OSFXSR_MASK)) | |
2913 | - if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA)) | |
2914 | - goto illegal_op; | |
2937 | + if (is_xmm | |
2938 | + && !(s->flags & HF_OSFXSR_MASK) | |
2939 | + && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) { | |
2940 | + goto unknown_op; | |
2941 | + } | |
2915 | 2942 | if (b == 0x0e) { |
2916 | - if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) | |
2917 | - goto illegal_op; | |
2943 | + if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) { | |
2944 | + /* If we were fully decoding this we might use illegal_op. */ | |
2945 | + goto unknown_op; | |
2946 | + } | |
2918 | 2947 | /* femms */ |
2919 | 2948 | gen_helper_emms(cpu_env); |
2920 | 2949 | return; |
@@ -2939,8 +2968,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
2939 | 2968 | b |= (b1 << 8); |
2940 | 2969 | switch(b) { |
2941 | 2970 | case 0x0e7: /* movntq */ |
2942 | - if (mod == 3) | |
2971 | + if (mod == 3) { | |
2943 | 2972 | goto illegal_op; |
2973 | + } | |
2944 | 2974 | gen_lea_modrm(env, s, modrm); |
2945 | 2975 | gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); |
2946 | 2976 | break; |
@@ -3266,7 +3296,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
3266 | 3296 | case 0x172: |
3267 | 3297 | case 0x173: |
3268 | 3298 | if (b1 >= 2) { |
3269 | - goto illegal_op; | |
3299 | + goto unknown_op; | |
3270 | 3300 | } |
3271 | 3301 | val = cpu_ldub_code(env, s->pc++); |
3272 | 3302 | if (is_xmm) { |
@@ -3285,7 +3315,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
3285 | 3315 | sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 + |
3286 | 3316 | (((modrm >> 3)) & 7)][b1]; |
3287 | 3317 | if (!sse_fn_epp) { |
3288 | - goto illegal_op; | |
3318 | + goto unknown_op; | |
3289 | 3319 | } |
3290 | 3320 | if (is_xmm) { |
3291 | 3321 | rm = (modrm & 7) | REX_B(s); |
@@ -3509,12 +3539,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
3509 | 3539 | reg = ((modrm >> 3) & 7) | rex_r; |
3510 | 3540 | mod = (modrm >> 6) & 3; |
3511 | 3541 | if (b1 >= 2) { |
3512 | - goto illegal_op; | |
3542 | + goto unknown_op; | |
3513 | 3543 | } |
3514 | 3544 | |
3515 | 3545 | sse_fn_epp = sse_op_table6[b].op[b1]; |
3516 | 3546 | if (!sse_fn_epp) { |
3517 | - goto illegal_op; | |
3547 | + goto unknown_op; | |
3518 | 3548 | } |
3519 | 3549 | if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask)) |
3520 | 3550 | goto illegal_op; |
@@ -3564,7 +3594,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
3564 | 3594 | } |
3565 | 3595 | } |
3566 | 3596 | if (sse_fn_epp == SSE_SPECIAL) { |
3567 | - goto illegal_op; | |
3597 | + goto unknown_op; | |
3568 | 3598 | } |
3569 | 3599 | |
3570 | 3600 | tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
@@ -3932,12 +3962,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
3932 | 3962 | break; |
3933 | 3963 | |
3934 | 3964 | default: |
3935 | - goto illegal_op; | |
3965 | + goto unknown_op; | |
3936 | 3966 | } |
3937 | 3967 | break; |
3938 | 3968 | |
3939 | 3969 | default: |
3940 | - goto illegal_op; | |
3970 | + goto unknown_op; | |
3941 | 3971 | } |
3942 | 3972 | break; |
3943 | 3973 |
@@ -3949,12 +3979,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
3949 | 3979 | reg = ((modrm >> 3) & 7) | rex_r; |
3950 | 3980 | mod = (modrm >> 6) & 3; |
3951 | 3981 | if (b1 >= 2) { |
3952 | - goto illegal_op; | |
3982 | + goto unknown_op; | |
3953 | 3983 | } |
3954 | 3984 | |
3955 | 3985 | sse_fn_eppi = sse_op_table7[b].op[b1]; |
3956 | 3986 | if (!sse_fn_eppi) { |
3957 | - goto illegal_op; | |
3987 | + goto unknown_op; | |
3958 | 3988 | } |
3959 | 3989 | if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask)) |
3960 | 3990 | goto illegal_op; |
@@ -4156,12 +4186,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
4156 | 4186 | break; |
4157 | 4187 | |
4158 | 4188 | default: |
4159 | - goto illegal_op; | |
4189 | + goto unknown_op; | |
4160 | 4190 | } |
4161 | 4191 | break; |
4162 | 4192 | |
4163 | 4193 | default: |
4164 | - goto illegal_op; | |
4194 | + unknown_op: | |
4195 | + gen_unknown_opcode(env, s); | |
4196 | + return; | |
4165 | 4197 | } |
4166 | 4198 | } else { |
4167 | 4199 | /* generic MMX or SSE operation */ |
@@ -4237,11 +4269,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
4237 | 4269 | } |
4238 | 4270 | switch(b) { |
4239 | 4271 | case 0x0f: /* 3DNow! data insns */ |
4240 | - if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) | |
4241 | - goto illegal_op; | |
4242 | 4272 | val = cpu_ldub_code(env, s->pc++); |
4243 | 4273 | sse_fn_epp = sse_op_table5[val]; |
4244 | 4274 | if (!sse_fn_epp) { |
4275 | + goto unknown_op; | |
4276 | + } | |
4277 | + if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) { | |
4245 | 4278 | goto illegal_op; |
4246 | 4279 | } |
4247 | 4280 | tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
@@ -4261,7 +4294,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, | ||
4261 | 4294 | /* compare insns */ |
4262 | 4295 | val = cpu_ldub_code(env, s->pc++); |
4263 | 4296 | if (val >= 8) |
4264 | - goto illegal_op; | |
4297 | + goto unknown_op; | |
4265 | 4298 | sse_fn_epp = sse_op_table4[val][b1]; |
4266 | 4299 | |
4267 | 4300 | tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
@@ -4306,7 +4339,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
4306 | 4339 | target_ulong next_eip, tval; |
4307 | 4340 | int rex_w, rex_r; |
4308 | 4341 | |
4309 | - s->pc = pc_start; | |
4342 | + s->pc_start = s->pc = pc_start; | |
4310 | 4343 | prefixes = 0; |
4311 | 4344 | s->override = -1; |
4312 | 4345 | rex_w = -1; |
@@ -4419,7 +4452,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
4419 | 4452 | b = 0x13a; |
4420 | 4453 | break; |
4421 | 4454 | default: /* Reserved for future use. */ |
4422 | - goto illegal_op; | |
4455 | + goto unknown_op; | |
4423 | 4456 | } |
4424 | 4457 | } |
4425 | 4458 | s->vex_v = (~vex3 >> 3) & 0xf; |
@@ -4769,7 +4802,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
4769 | 4802 | } |
4770 | 4803 | break; |
4771 | 4804 | default: |
4772 | - goto illegal_op; | |
4805 | + goto unknown_op; | |
4773 | 4806 | } |
4774 | 4807 | break; |
4775 | 4808 |
@@ -4782,7 +4815,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
4782 | 4815 | rm = (modrm & 7) | REX_B(s); |
4783 | 4816 | op = (modrm >> 3) & 7; |
4784 | 4817 | if (op >= 2 && b == 0xfe) { |
4785 | - goto illegal_op; | |
4818 | + goto unknown_op; | |
4786 | 4819 | } |
4787 | 4820 | if (CODE64(s)) { |
4788 | 4821 | if (op == 2 || op == 4) { |
@@ -4875,7 +4908,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
4875 | 4908 | gen_push_v(s, cpu_T0); |
4876 | 4909 | break; |
4877 | 4910 | default: |
4878 | - goto illegal_op; | |
4911 | + goto unknown_op; | |
4879 | 4912 | } |
4880 | 4913 | break; |
4881 | 4914 |
@@ -5744,7 +5777,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5744 | 5777 | gen_helper_fpop(cpu_env); |
5745 | 5778 | break; |
5746 | 5779 | default: |
5747 | - goto illegal_op; | |
5780 | + goto unknown_op; | |
5748 | 5781 | } |
5749 | 5782 | } else { |
5750 | 5783 | /* register float ops */ |
@@ -5768,7 +5801,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5768 | 5801 | gen_helper_fwait(cpu_env); |
5769 | 5802 | break; |
5770 | 5803 | default: |
5771 | - goto illegal_op; | |
5804 | + goto unknown_op; | |
5772 | 5805 | } |
5773 | 5806 | break; |
5774 | 5807 | case 0x0c: /* grp d9/4 */ |
@@ -5787,7 +5820,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5787 | 5820 | gen_helper_fxam_ST0(cpu_env); |
5788 | 5821 | break; |
5789 | 5822 | default: |
5790 | - goto illegal_op; | |
5823 | + goto unknown_op; | |
5791 | 5824 | } |
5792 | 5825 | break; |
5793 | 5826 | case 0x0d: /* grp d9/5 */ |
@@ -5822,7 +5855,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5822 | 5855 | gen_helper_fldz_ST0(cpu_env); |
5823 | 5856 | break; |
5824 | 5857 | default: |
5825 | - goto illegal_op; | |
5858 | + goto unknown_op; | |
5826 | 5859 | } |
5827 | 5860 | } |
5828 | 5861 | break; |
@@ -5922,7 +5955,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5922 | 5955 | gen_helper_fpop(cpu_env); |
5923 | 5956 | break; |
5924 | 5957 | default: |
5925 | - goto illegal_op; | |
5958 | + goto unknown_op; | |
5926 | 5959 | } |
5927 | 5960 | break; |
5928 | 5961 | case 0x1c: |
@@ -5940,7 +5973,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5940 | 5973 | case 4: /* fsetpm (287 only, just do nop here) */ |
5941 | 5974 | break; |
5942 | 5975 | default: |
5943 | - goto illegal_op; | |
5976 | + goto unknown_op; | |
5944 | 5977 | } |
5945 | 5978 | break; |
5946 | 5979 | case 0x1d: /* fucomi */ |
@@ -5992,7 +6025,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
5992 | 6025 | gen_helper_fpop(cpu_env); |
5993 | 6026 | break; |
5994 | 6027 | default: |
5995 | - goto illegal_op; | |
6028 | + goto unknown_op; | |
5996 | 6029 | } |
5997 | 6030 | break; |
5998 | 6031 | case 0x38: /* ffreep sti, undocumented op */ |
@@ -6007,7 +6040,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
6007 | 6040 | gen_op_mov_reg_v(MO_16, R_EAX, cpu_T0); |
6008 | 6041 | break; |
6009 | 6042 | default: |
6010 | - goto illegal_op; | |
6043 | + goto unknown_op; | |
6011 | 6044 | } |
6012 | 6045 | break; |
6013 | 6046 | case 0x3d: /* fucomip */ |
@@ -6053,7 +6086,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
6053 | 6086 | } |
6054 | 6087 | break; |
6055 | 6088 | default: |
6056 | - goto illegal_op; | |
6089 | + goto unknown_op; | |
6057 | 6090 | } |
6058 | 6091 | } |
6059 | 6092 | break; |
@@ -6524,7 +6557,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
6524 | 6557 | val = cpu_ldub_code(env, s->pc++); |
6525 | 6558 | tcg_gen_movi_tl(cpu_T1, val); |
6526 | 6559 | if (op < 4) |
6527 | - goto illegal_op; | |
6560 | + goto unknown_op; | |
6528 | 6561 | op -= 4; |
6529 | 6562 | goto bt_op; |
6530 | 6563 | case 0x1a3: /* bt Gv, Ev */ |
@@ -7035,7 +7068,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
7035 | 7068 | set_cc_op(s, CC_OP_EFLAGS); |
7036 | 7069 | break; |
7037 | 7070 | default: |
7038 | - goto illegal_op; | |
7071 | + goto unknown_op; | |
7039 | 7072 | } |
7040 | 7073 | break; |
7041 | 7074 |
@@ -7349,7 +7382,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
7349 | 7382 | break; |
7350 | 7383 | |
7351 | 7384 | default: |
7352 | - goto illegal_op; | |
7385 | + goto unknown_op; | |
7353 | 7386 | } |
7354 | 7387 | break; |
7355 | 7388 |
@@ -7718,7 +7751,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
7718 | 7751 | } |
7719 | 7752 | break; |
7720 | 7753 | default: |
7721 | - goto illegal_op; | |
7754 | + goto unknown_op; | |
7722 | 7755 | } |
7723 | 7756 | } |
7724 | 7757 | break; |
@@ -7940,7 +7973,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
7940 | 7973 | } |
7941 | 7974 | break; |
7942 | 7975 | } |
7943 | - goto illegal_op; | |
7976 | + goto unknown_op; | |
7944 | 7977 | |
7945 | 7978 | case 0xf8: /* sfence / pcommit */ |
7946 | 7979 | if (prefixes & PREFIX_DATA) { |
@@ -7962,7 +7995,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
7962 | 7995 | break; |
7963 | 7996 | |
7964 | 7997 | default: |
7965 | - goto illegal_op; | |
7998 | + goto unknown_op; | |
7966 | 7999 | } |
7967 | 8000 | break; |
7968 | 8001 |
@@ -8018,7 +8051,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
8018 | 8051 | gen_sse(env, s, b, pc_start, rex_r); |
8019 | 8052 | break; |
8020 | 8053 | default: |
8021 | - goto illegal_op; | |
8054 | + goto unknown_op; | |
8022 | 8055 | } |
8023 | 8056 | /* lock generation */ |
8024 | 8057 | if (s->prefix & PREFIX_LOCK) |
@@ -8028,7 +8061,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
8028 | 8061 | if (s->prefix & PREFIX_LOCK) |
8029 | 8062 | gen_helper_unlock(); |
8030 | 8063 | /* XXX: ensure that no lock was generated */ |
8031 | - gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); | |
8064 | + gen_illegal_opcode(s); | |
8065 | + return s->pc; | |
8066 | + unknown_op: | |
8067 | + if (s->prefix & PREFIX_LOCK) | |
8068 | + gen_helper_unlock(); | |
8069 | + /* XXX: ensure that no lock was generated */ | |
8070 | + gen_unknown_opcode(env, s); | |
8032 | 8071 | return s->pc; |
8033 | 8072 | } |
8034 | 8073 |