Commit aba9d61e34b9d43b856fd758d70f38e99e026cab

Authored by bellard
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, &reg_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, &reg_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);
... ...