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 | 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 | 2244 | static GenOpFunc1 *gen_ldq_env_A0[3] = { |
2235 | 2245 | gen_op_ldq_raw_env_A0, |
2236 | 2246 | #ifndef CONFIG_USER_ONLY |
... | ... | @@ -3382,9 +3392,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
3382 | 3392 | goto illegal_op; |
3383 | 3393 | } |
3384 | 3394 | if (CODE64(s)) { |
3385 | - if (op >= 2 && op <= 5) { | |
3395 | + if (op == 2 || op == 4) { | |
3386 | 3396 | /* operand size for jumps is 64 bit */ |
3387 | 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 | 3402 | } else if (op == 6) { |
3389 | 3403 | /* default push size is 64 bit */ |
3390 | 3404 | ot = dflag ? OT_QUAD : OT_WORD; |
... | ... | @@ -3425,14 +3439,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
3425 | 3439 | break; |
3426 | 3440 | case 3: /* lcall Ev */ |
3427 | 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 | 3443 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
3430 | 3444 | do_lcall: |
3431 | 3445 | if (s->pe && !s->vm86) { |
3432 | 3446 | if (s->cc_op != CC_OP_DYNAMIC) |
3433 | 3447 | gen_op_set_cc_op(s->cc_op); |
3434 | 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 | 3450 | } else { |
3437 | 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 | 3460 | break; |
3447 | 3461 | case 5: /* ljmp Ev */ |
3448 | 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 | 3464 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
3451 | 3465 | do_ljmp: |
3452 | 3466 | if (s->pe && !s->vm86) { |
3453 | 3467 | if (s->cc_op != CC_OP_DYNAMIC) |
3454 | 3468 | gen_op_set_cc_op(s->cc_op); |
3455 | 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 | 3471 | } else { |
3458 | 3472 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
3459 | 3473 | gen_op_movl_T0_T1(); |
... | ... | @@ -4043,7 +4057,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
4043 | 4057 | goto illegal_op; |
4044 | 4058 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
4045 | 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 | 4061 | /* load the segment first to handle exceptions properly */ |
4048 | 4062 | gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
4049 | 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 | 5196 | gen_op_into(s->pc - pc_start); |
5183 | 5197 | break; |
5184 | 5198 | case 0xf1: /* icebp (undocumented, exits to external debugger) */ |
5199 | +#if 1 | |
5185 | 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 | 5206 | break; |
5187 | 5207 | case 0xfa: /* cli */ |
5188 | 5208 | if (!s->vm86) { |
... | ... | @@ -5363,6 +5383,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5363 | 5383 | } |
5364 | 5384 | gen_jmp_im(pc_start - s->cs_base); |
5365 | 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 | 5389 | gen_eob(s); |
5367 | 5390 | } |
5368 | 5391 | break; |
... | ... | @@ -5458,12 +5481,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5458 | 5481 | else |
5459 | 5482 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); |
5460 | 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 | 5485 | if (op == 0) |
5468 | 5486 | gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base)); |
5469 | 5487 | else |
... | ... | @@ -5481,12 +5499,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5481 | 5499 | } else { |
5482 | 5500 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
5483 | 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 | 5503 | gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); |
5491 | 5504 | if (!s->dflag) |
5492 | 5505 | gen_op_andl_T0_im(0xffffff); | ... | ... |