575 |
if (s->addseg && override < 0) |
if (s->addseg && override < 0) |
576 |
override = R_DS; |
override = R_DS; |
577 |
if (override >= 0) { |
if (override >= 0) { |
578 |
gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
579 |
index = 3 + ot; |
index = 3 + ot; |
580 |
} else { |
} else { |
581 |
index = ot; |
index = ot; |
583 |
} else { |
} else { |
584 |
if (override < 0) |
if (override < 0) |
585 |
override = R_DS; |
override = R_DS; |
586 |
gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
587 |
/* 16 address, always override */ |
/* 16 address, always override */ |
588 |
index = 6 + ot; |
index = 6 + ot; |
589 |
} |
} |
878 |
else |
else |
879 |
override = R_DS; |
override = R_DS; |
880 |
} |
} |
881 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
882 |
} |
} |
883 |
} else { |
} else { |
884 |
switch (mod) { |
switch (mod) { |
944 |
else |
else |
945 |
override = R_DS; |
override = R_DS; |
946 |
} |
} |
947 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
948 |
} |
} |
949 |
} |
} |
950 |
|
|
1146 |
if (!s->vm86) |
if (!s->vm86) |
1147 |
gen_op_movl_seg_T0(seg_reg, cur_eip); |
gen_op_movl_seg_T0(seg_reg, cur_eip); |
1148 |
else |
else |
1149 |
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]), |
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
|
offsetof(CPUX86State,seg_cache[seg_reg].base)); |
|
1150 |
if (!s->addseg && seg_reg < R_FS) |
if (!s->addseg && seg_reg < R_FS) |
1151 |
s->is_jmp = 2; /* abort translation because the register may |
s->is_jmp = 2; /* abort translation because the register may |
1152 |
have a non zero base */ |
have a non zero base */ |
1229 |
gen_op_andl_A0_ffff(); |
gen_op_andl_A0_ffff(); |
1230 |
gen_op_movl_T1_A0(); |
gen_op_movl_T1_A0(); |
1231 |
if (s->addseg) |
if (s->addseg) |
1232 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
1233 |
} |
} |
1234 |
|
|
1235 |
/* NOTE: wrap around in 16 bit not fully handled */ |
/* NOTE: wrap around in 16 bit not fully handled */ |
1242 |
gen_op_andl_A0_ffff(); |
gen_op_andl_A0_ffff(); |
1243 |
gen_op_movl_T1_A0(); |
gen_op_movl_T1_A0(); |
1244 |
if (s->addseg) |
if (s->addseg) |
1245 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
1246 |
for(i = 0;i < 8; i++) { |
for(i = 0;i < 8; i++) { |
1247 |
gen_op_mov_TN_reg[OT_LONG][0][7 - i](); |
gen_op_mov_TN_reg[OT_LONG][0][7 - i](); |
1248 |
gen_op_st_T0_A0[OT_WORD + s->dflag](); |
gen_op_st_T0_A0[OT_WORD + s->dflag](); |
1261 |
gen_op_movl_T1_A0(); |
gen_op_movl_T1_A0(); |
1262 |
gen_op_addl_T1_im(16 << s->dflag); |
gen_op_addl_T1_im(16 << s->dflag); |
1263 |
if (s->addseg) |
if (s->addseg) |
1264 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
1265 |
for(i = 0;i < 8; i++) { |
for(i = 0;i < 8; i++) { |
1266 |
/* ESP is not reloaded */ |
/* ESP is not reloaded */ |
1267 |
if (i != 3) { |
if (i != 3) { |
1290 |
gen_op_andl_A0_ffff(); |
gen_op_andl_A0_ffff(); |
1291 |
gen_op_movl_T1_A0(); |
gen_op_movl_T1_A0(); |
1292 |
if (s->addseg) |
if (s->addseg) |
1293 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); |
1294 |
/* push bp */ |
/* push bp */ |
1295 |
gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); |
gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); |
1296 |
gen_op_st_T0_A0[ot](); |
gen_op_st_T0_A0[ot](); |
1713 |
gen_op_ld_T1_A0[ot](); |
gen_op_ld_T1_A0[ot](); |
1714 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
1715 |
gen_op_lduw_T0_A0(); |
gen_op_lduw_T0_A0(); |
1716 |
gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); |
if (!s->vm86) { |
1717 |
gen_op_movl_T0_T1(); |
/* we compute EIP to handle the exception case */ |
1718 |
gen_op_jmp_T0(); |
gen_op_jmp_im(pc_start - s->cs_base); |
1719 |
|
gen_op_ljmp_T0_T1(); |
1720 |
|
} else { |
1721 |
|
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
1722 |
|
gen_op_movl_T0_T1(); |
1723 |
|
gen_op_jmp_T0(); |
1724 |
|
} |
1725 |
s->is_jmp = 1; |
s->is_jmp = 1; |
1726 |
break; |
break; |
1727 |
case 6: /* push Ev */ |
case 6: /* push Ev */ |
2090 |
override = R_DS; |
override = R_DS; |
2091 |
} |
} |
2092 |
if (must_add_seg) { |
if (must_add_seg) { |
2093 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
2094 |
} |
} |
2095 |
} |
} |
2096 |
if ((b & 2) == 0) { |
if ((b & 2) == 0) { |
2118 |
override = R_DS; |
override = R_DS; |
2119 |
} |
} |
2120 |
if (must_add_seg) { |
if (must_add_seg) { |
2121 |
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); |
gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); |
2122 |
} |
} |
2123 |
} |
} |
2124 |
gen_op_ldub_T0_A0(); |
gen_op_ldub_T0_A0(); |
2624 |
break; |
break; |
2625 |
case 0x1c: |
case 0x1c: |
2626 |
switch(rm) { |
switch(rm) { |
2627 |
|
case 0: /* feni (287 only, just do nop here) */ |
2628 |
|
break; |
2629 |
|
case 1: /* fdisi (287 only, just do nop here) */ |
2630 |
|
break; |
2631 |
case 2: /* fclex */ |
case 2: /* fclex */ |
2632 |
gen_op_fclex(); |
gen_op_fclex(); |
2633 |
break; |
break; |
2634 |
case 3: /* fninit */ |
case 3: /* fninit */ |
2635 |
gen_op_fninit(); |
gen_op_fninit(); |
2636 |
break; |
break; |
2637 |
|
case 4: /* fsetpm (287 only, just do nop here) */ |
2638 |
|
break; |
2639 |
default: |
default: |
2640 |
goto illegal_op; |
goto illegal_op; |
2641 |
} |
} |
3022 |
|
|
3023 |
/* change cs and pc */ |
/* change cs and pc */ |
3024 |
gen_op_movl_T0_im(selector); |
gen_op_movl_T0_im(selector); |
3025 |
gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); |
if (!s->vm86) { |
3026 |
gen_op_jmp_im((unsigned long)offset); |
/* we compute EIP to handle the exception case */ |
3027 |
|
gen_op_jmp_im(pc_start - s->cs_base); |
3028 |
|
gen_op_movl_T1_im(offset); |
3029 |
|
gen_op_ljmp_T0_T1(); |
3030 |
|
} else { |
3031 |
|
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
3032 |
|
gen_op_jmp_im((unsigned long)offset); |
3033 |
|
} |
3034 |
s->is_jmp = 1; |
s->is_jmp = 1; |
3035 |
} |
} |
3036 |
break; |
break; |
3361 |
/* XXX: if cpl == 0, then should do something else */ |
/* XXX: if cpl == 0, then should do something else */ |
3362 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3363 |
break; |
break; |
3364 |
|
case 0x100: |
3365 |
|
modrm = ldub(s->pc++); |
3366 |
|
mod = (modrm >> 6) & 3; |
3367 |
|
op = (modrm >> 3) & 7; |
3368 |
|
switch(op) { |
3369 |
|
case 0: /* sldt */ |
3370 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector)); |
3371 |
|
ot = OT_WORD; |
3372 |
|
if (mod == 3) |
3373 |
|
ot += s->dflag; |
3374 |
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
3375 |
|
break; |
3376 |
|
case 2: /* lldt */ |
3377 |
|
if (s->cpl != 0) { |
3378 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3379 |
|
} else { |
3380 |
|
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
3381 |
|
gen_op_jmp_im(pc_start - s->cs_base); |
3382 |
|
gen_op_lldt_T0(); |
3383 |
|
} |
3384 |
|
break; |
3385 |
|
case 1: /* str */ |
3386 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector)); |
3387 |
|
ot = OT_WORD; |
3388 |
|
if (mod == 3) |
3389 |
|
ot += s->dflag; |
3390 |
|
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
3391 |
|
break; |
3392 |
|
case 3: /* ltr */ |
3393 |
|
if (s->cpl != 0) { |
3394 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3395 |
|
} else { |
3396 |
|
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
3397 |
|
gen_op_jmp_im(pc_start - s->cs_base); |
3398 |
|
gen_op_ltr_T0(); |
3399 |
|
} |
3400 |
|
break; |
3401 |
|
case 4: /* verr */ |
3402 |
|
case 5: /* verw */ |
3403 |
|
default: |
3404 |
|
goto illegal_op; |
3405 |
|
} |
3406 |
|
break; |
3407 |
|
case 0x101: |
3408 |
|
modrm = ldub(s->pc++); |
3409 |
|
mod = (modrm >> 6) & 3; |
3410 |
|
op = (modrm >> 3) & 7; |
3411 |
|
switch(op) { |
3412 |
|
case 0: /* sgdt */ |
3413 |
|
case 1: /* sidt */ |
3414 |
|
if (mod == 3) |
3415 |
|
goto illegal_op; |
3416 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
3417 |
|
if (op == 0) |
3418 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit)); |
3419 |
|
else |
3420 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); |
3421 |
|
gen_op_stw_T0_A0(); |
3422 |
|
gen_op_addl_A0_im(2); |
3423 |
|
if (op == 0) |
3424 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); |
3425 |
|
else |
3426 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); |
3427 |
|
if (!s->dflag) |
3428 |
|
gen_op_andl_T0_im(0xffffff); |
3429 |
|
gen_op_stl_T0_A0(); |
3430 |
|
break; |
3431 |
|
case 2: /* lgdt */ |
3432 |
|
case 3: /* lidt */ |
3433 |
|
if (mod == 3) |
3434 |
|
goto illegal_op; |
3435 |
|
if (s->cpl != 0) { |
3436 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3437 |
|
} else { |
3438 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
3439 |
|
gen_op_lduw_T1_A0(); |
3440 |
|
gen_op_addl_A0_im(2); |
3441 |
|
gen_op_ldl_T0_A0(); |
3442 |
|
if (!s->dflag) |
3443 |
|
gen_op_andl_T0_im(0xffffff); |
3444 |
|
if (op == 2) { |
3445 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base)); |
3446 |
|
gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit)); |
3447 |
|
} else { |
3448 |
|
gen_op_movl_env_T0(offsetof(CPUX86State,idt.base)); |
3449 |
|
gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit)); |
3450 |
|
} |
3451 |
|
} |
3452 |
|
break; |
3453 |
|
case 4: /* smsw */ |
3454 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,cr[0])); |
3455 |
|
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1); |
3456 |
|
break; |
3457 |
|
case 6: /* lmsw */ |
3458 |
|
if (s->cpl != 0) { |
3459 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3460 |
|
} else { |
3461 |
|
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
3462 |
|
gen_op_lmsw_T0(); |
3463 |
|
} |
3464 |
|
break; |
3465 |
|
default: |
3466 |
|
goto illegal_op; |
3467 |
|
} |
3468 |
|
break; |
3469 |
case 0x102: /* lar */ |
case 0x102: /* lar */ |
3470 |
case 0x103: /* lsl */ |
case 0x103: /* lsl */ |
3471 |
if (s->vm86) |
if (s->vm86) |
3484 |
s->cc_op = CC_OP_EFLAGS; |
s->cc_op = CC_OP_EFLAGS; |
3485 |
gen_op_mov_reg_T1[ot][reg](); |
gen_op_mov_reg_T1[ot][reg](); |
3486 |
break; |
break; |
3487 |
|
case 0x118: |
3488 |
|
modrm = ldub(s->pc++); |
3489 |
|
mod = (modrm >> 6) & 3; |
3490 |
|
op = (modrm >> 3) & 7; |
3491 |
|
switch(op) { |
3492 |
|
case 0: /* prefetchnta */ |
3493 |
|
case 1: /* prefetchnt0 */ |
3494 |
|
case 2: /* prefetchnt0 */ |
3495 |
|
case 3: /* prefetchnt0 */ |
3496 |
|
if (mod == 3) |
3497 |
|
goto illegal_op; |
3498 |
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
3499 |
|
/* nothing more to do */ |
3500 |
|
break; |
3501 |
|
default: |
3502 |
|
goto illegal_op; |
3503 |
|
} |
3504 |
|
break; |
3505 |
|
case 0x120: /* mov reg, crN */ |
3506 |
|
case 0x122: /* mov crN, reg */ |
3507 |
|
if (s->cpl != 0) { |
3508 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3509 |
|
} else { |
3510 |
|
modrm = ldub(s->pc++); |
3511 |
|
if ((modrm & 0xc0) != 0xc0) |
3512 |
|
goto illegal_op; |
3513 |
|
rm = modrm & 7; |
3514 |
|
reg = (modrm >> 3) & 7; |
3515 |
|
switch(reg) { |
3516 |
|
case 0: |
3517 |
|
case 2: |
3518 |
|
case 3: |
3519 |
|
case 4: |
3520 |
|
if (b & 2) { |
3521 |
|
gen_op_mov_TN_reg[OT_LONG][0][rm](); |
3522 |
|
gen_op_movl_crN_T0(reg); |
3523 |
|
s->is_jmp = 2; |
3524 |
|
} else { |
3525 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg])); |
3526 |
|
gen_op_mov_reg_T0[OT_LONG][rm](); |
3527 |
|
} |
3528 |
|
break; |
3529 |
|
default: |
3530 |
|
goto illegal_op; |
3531 |
|
} |
3532 |
|
} |
3533 |
|
break; |
3534 |
|
case 0x121: /* mov reg, drN */ |
3535 |
|
case 0x123: /* mov drN, reg */ |
3536 |
|
if (s->cpl != 0) { |
3537 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3538 |
|
} else { |
3539 |
|
modrm = ldub(s->pc++); |
3540 |
|
if ((modrm & 0xc0) != 0xc0) |
3541 |
|
goto illegal_op; |
3542 |
|
rm = modrm & 7; |
3543 |
|
reg = (modrm >> 3) & 7; |
3544 |
|
/* XXX: do it dynamically with CR4.DE bit */ |
3545 |
|
if (reg == 4 || reg == 5) |
3546 |
|
goto illegal_op; |
3547 |
|
if (b & 2) { |
3548 |
|
gen_op_mov_TN_reg[OT_LONG][0][rm](); |
3549 |
|
gen_op_movl_drN_T0(reg); |
3550 |
|
s->is_jmp = 2; |
3551 |
|
} else { |
3552 |
|
gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg])); |
3553 |
|
gen_op_mov_reg_T0[OT_LONG][rm](); |
3554 |
|
} |
3555 |
|
} |
3556 |
|
break; |
3557 |
|
case 0x106: /* clts */ |
3558 |
|
if (s->cpl != 0) { |
3559 |
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3560 |
|
} else { |
3561 |
|
gen_op_clts(); |
3562 |
|
} |
3563 |
|
break; |
3564 |
default: |
default: |
3565 |
goto illegal_op; |
goto illegal_op; |
3566 |
} |
} |
4059 |
eflags & CC_P ? 'P' : '-', |
eflags & CC_P ? 'P' : '-', |
4060 |
eflags & CC_C ? 'C' : '-'); |
eflags & CC_C ? 'C' : '-'); |
4061 |
fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", |
fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", |
4062 |
env->segs[R_CS], |
env->segs[R_CS].selector, |
4063 |
env->segs[R_SS], |
env->segs[R_SS].selector, |
4064 |
env->segs[R_DS], |
env->segs[R_DS].selector, |
4065 |
env->segs[R_ES], |
env->segs[R_ES].selector, |
4066 |
env->segs[R_FS], |
env->segs[R_FS].selector, |
4067 |
env->segs[R_GS]); |
env->segs[R_GS].selector); |
4068 |
if (flags & X86_DUMP_CCOP) { |
if (flags & X86_DUMP_CCOP) { |
4069 |
if ((unsigned)env->cc_op < CC_OP_NB) |
if ((unsigned)env->cc_op < CC_OP_NB) |
4070 |
strcpy(cc_op_name, cc_op_str[env->cc_op]); |
strcpy(cc_op_name, cc_op_str[env->cc_op]); |