Commit aba9d61e34b9d43b856fd758d70f38e99e026cab
1 parent
a6f37988
lcall and ljmp fixes in 64 bit mode - sysret fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1375 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
18 deletions
target-i386/translate.c
| @@ -2231,6 +2231,16 @@ static void gen_movtl_T1_im(target_ulong val) | @@ -2231,6 +2231,16 @@ static void gen_movtl_T1_im(target_ulong val) | ||
| 2231 | #endif | 2231 | #endif |
| 2232 | } | 2232 | } |
| 2233 | 2233 | ||
| 2234 | +static void gen_add_A0_im(DisasContext *s, int val) | ||
| 2235 | +{ | ||
| 2236 | +#ifdef TARGET_X86_64 | ||
| 2237 | + if (CODE64(s)) | ||
| 2238 | + gen_op_addq_A0_im(val); | ||
| 2239 | + else | ||
| 2240 | +#endif | ||
| 2241 | + gen_op_addl_A0_im(val); | ||
| 2242 | +} | ||
| 2243 | + | ||
| 2234 | static GenOpFunc1 *gen_ldq_env_A0[3] = { | 2244 | static GenOpFunc1 *gen_ldq_env_A0[3] = { |
| 2235 | gen_op_ldq_raw_env_A0, | 2245 | gen_op_ldq_raw_env_A0, |
| 2236 | #ifndef CONFIG_USER_ONLY | 2246 | #ifndef CONFIG_USER_ONLY |
| @@ -3382,9 +3392,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3382,9 +3392,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 3382 | goto illegal_op; | 3392 | goto illegal_op; |
| 3383 | } | 3393 | } |
| 3384 | if (CODE64(s)) { | 3394 | if (CODE64(s)) { |
| 3385 | - if (op >= 2 && op <= 5) { | 3395 | + if (op == 2 || op == 4) { |
| 3386 | /* operand size for jumps is 64 bit */ | 3396 | /* operand size for jumps is 64 bit */ |
| 3387 | ot = OT_QUAD; | 3397 | ot = OT_QUAD; |
| 3398 | + } else if (op == 3 || op == 5) { | ||
| 3399 | + /* for call calls, the operand is 16 or 32 bit, even | ||
| 3400 | + in long mode */ | ||
| 3401 | + ot = dflag ? OT_LONG : OT_WORD; | ||
| 3388 | } else if (op == 6) { | 3402 | } else if (op == 6) { |
| 3389 | /* default push size is 64 bit */ | 3403 | /* default push size is 64 bit */ |
| 3390 | ot = dflag ? OT_QUAD : OT_WORD; | 3404 | ot = dflag ? OT_QUAD : OT_WORD; |
| @@ -3425,14 +3439,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3425,14 +3439,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 3425 | break; | 3439 | break; |
| 3426 | case 3: /* lcall Ev */ | 3440 | case 3: /* lcall Ev */ |
| 3427 | gen_op_ld_T1_A0[ot + s->mem_index](); | 3441 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| 3428 | - gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 3442 | + gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); |
| 3429 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); | 3443 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
| 3430 | do_lcall: | 3444 | do_lcall: |
| 3431 | if (s->pe && !s->vm86) { | 3445 | if (s->pe && !s->vm86) { |
| 3432 | if (s->cc_op != CC_OP_DYNAMIC) | 3446 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3433 | gen_op_set_cc_op(s->cc_op); | 3447 | gen_op_set_cc_op(s->cc_op); |
| 3434 | gen_jmp_im(pc_start - s->cs_base); | 3448 | gen_jmp_im(pc_start - s->cs_base); |
| 3435 | - gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base); | 3449 | + gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start); |
| 3436 | } else { | 3450 | } else { |
| 3437 | gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base); | 3451 | gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base); |
| 3438 | } | 3452 | } |
| @@ -3446,14 +3460,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3446,14 +3460,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 3446 | break; | 3460 | break; |
| 3447 | case 5: /* ljmp Ev */ | 3461 | case 5: /* ljmp Ev */ |
| 3448 | gen_op_ld_T1_A0[ot + s->mem_index](); | 3462 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| 3449 | - gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 3463 | + gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); |
| 3450 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); | 3464 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
| 3451 | do_ljmp: | 3465 | do_ljmp: |
| 3452 | if (s->pe && !s->vm86) { | 3466 | if (s->pe && !s->vm86) { |
| 3453 | if (s->cc_op != CC_OP_DYNAMIC) | 3467 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3454 | gen_op_set_cc_op(s->cc_op); | 3468 | gen_op_set_cc_op(s->cc_op); |
| 3455 | gen_jmp_im(pc_start - s->cs_base); | 3469 | gen_jmp_im(pc_start - s->cs_base); |
| 3456 | - gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base); | 3470 | + gen_op_ljmp_protected_T0_T1(s->pc - pc_start); |
| 3457 | } else { | 3471 | } else { |
| 3458 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); | 3472 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
| 3459 | gen_op_movl_T0_T1(); | 3473 | gen_op_movl_T0_T1(); |
| @@ -4043,7 +4057,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -4043,7 +4057,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 4043 | goto illegal_op; | 4057 | goto illegal_op; |
| 4044 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 4058 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 4045 | gen_op_ld_T1_A0[ot + s->mem_index](); | 4059 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| 4046 | - gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | 4060 | + gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); |
| 4047 | /* load the segment first to handle exceptions properly */ | 4061 | /* load the segment first to handle exceptions properly */ |
| 4048 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); | 4062 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
| 4049 | gen_movl_seg_T0(s, op, pc_start - s->cs_base); | 4063 | gen_movl_seg_T0(s, op, pc_start - s->cs_base); |
| @@ -5182,7 +5196,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5182,7 +5196,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5182 | gen_op_into(s->pc - pc_start); | 5196 | gen_op_into(s->pc - pc_start); |
| 5183 | break; | 5197 | break; |
| 5184 | case 0xf1: /* icebp (undocumented, exits to external debugger) */ | 5198 | case 0xf1: /* icebp (undocumented, exits to external debugger) */ |
| 5199 | +#if 1 | ||
| 5185 | gen_debug(s, pc_start - s->cs_base); | 5200 | gen_debug(s, pc_start - s->cs_base); |
| 5201 | +#else | ||
| 5202 | + /* start debug */ | ||
| 5203 | + tb_flush(cpu_single_env); | ||
| 5204 | + cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM); | ||
| 5205 | +#endif | ||
| 5186 | break; | 5206 | break; |
| 5187 | case 0xfa: /* cli */ | 5207 | case 0xfa: /* cli */ |
| 5188 | if (!s->vm86) { | 5208 | if (!s->vm86) { |
| @@ -5363,6 +5383,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5363,6 +5383,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5363 | } | 5383 | } |
| 5364 | gen_jmp_im(pc_start - s->cs_base); | 5384 | gen_jmp_im(pc_start - s->cs_base); |
| 5365 | gen_op_sysret(s->dflag); | 5385 | gen_op_sysret(s->dflag); |
| 5386 | + /* condition codes are modified only in long mode */ | ||
| 5387 | + if (s->lma) | ||
| 5388 | + s->cc_op = CC_OP_EFLAGS; | ||
| 5366 | gen_eob(s); | 5389 | gen_eob(s); |
| 5367 | } | 5390 | } |
| 5368 | break; | 5391 | break; |
| @@ -5458,12 +5481,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5458,12 +5481,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5458 | else | 5481 | else |
| 5459 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); | 5482 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); |
| 5460 | gen_op_st_T0_A0[OT_WORD + s->mem_index](); | 5483 | gen_op_st_T0_A0[OT_WORD + s->mem_index](); |
| 5461 | -#ifdef TARGET_X86_64 | ||
| 5462 | - if (CODE64(s)) | ||
| 5463 | - gen_op_addq_A0_im(2); | ||
| 5464 | - else | ||
| 5465 | -#endif | ||
| 5466 | - gen_op_addl_A0_im(2); | 5484 | + gen_add_A0_im(s, 2); |
| 5467 | if (op == 0) | 5485 | if (op == 0) |
| 5468 | gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base)); | 5486 | gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base)); |
| 5469 | else | 5487 | else |
| @@ -5481,12 +5499,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5481,12 +5499,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 5481 | } else { | 5499 | } else { |
| 5482 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | 5500 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 5483 | gen_op_ld_T1_A0[OT_WORD + s->mem_index](); | 5501 | gen_op_ld_T1_A0[OT_WORD + s->mem_index](); |
| 5484 | -#ifdef TARGET_X86_64 | ||
| 5485 | - if (CODE64(s)) | ||
| 5486 | - gen_op_addq_A0_im(2); | ||
| 5487 | - else | ||
| 5488 | -#endif | ||
| 5489 | - gen_op_addl_A0_im(2); | 5502 | + gen_add_A0_im(s, 2); |
| 5490 | gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); | 5503 | gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); |
| 5491 | if (!s->dflag) | 5504 | if (!s->dflag) |
| 5492 | gen_op_andl_T0_im(0xffffff); | 5505 | gen_op_andl_T0_im(0xffffff); |