Commit f631ef9bd262796779dd2b18741cf924831dab54

Authored by bellard
1 parent f7341ff4

better vm86 support - added iret - fixed push/pop fs/gs


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@68 c046a42c-6fe2-441c-8c8c-71466251a162
op-i386.c
... ... @@ -611,6 +611,35 @@ void OPPROTO op_into(void)
611 611 }
612 612 }
613 613  
  614 +/* XXX: add IOPL/CPL tests */
  615 +void OPPROTO op_cli(void)
  616 +{
  617 + raise_exception(EXCP0D_GPF);
  618 +}
  619 +
  620 +/* XXX: add IOPL/CPL tests */
  621 +void OPPROTO op_sti(void)
  622 +{
  623 + raise_exception(EXCP0D_GPF);
  624 +}
  625 +
  626 +/* vm86plus instructions */
  627 +
  628 +void OPPROTO op_cli_vm(void)
  629 +{
  630 + env->eflags &= ~VIF_MASK;
  631 +}
  632 +
  633 +void OPPROTO op_sti_vm(void)
  634 +{
  635 + env->eflags |= VIF_MASK;
  636 + if (env->eflags & VIP_MASK) {
  637 + EIP = PARAM1;
  638 + raise_exception(EXCP0D_GPF);
  639 + }
  640 + FORCE_RET();
  641 +}
  642 +
614 643 void OPPROTO op_boundw(void)
615 644 {
616 645 int low, high, v;
... ... @@ -1234,7 +1263,8 @@ void OPPROTO op_set_cc_op(void)
1234 1263 CC_OP = PARAM1;
1235 1264 }
1236 1265  
1237   -#define FL_UPDATE_MASK (TF_MASK | AC_MASK | ID_MASK)
  1266 +#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
  1267 +#define FL_UPDATE_MASK16 (TF_MASK)
1238 1268  
1239 1269 void OPPROTO op_movl_eflags_T0(void)
1240 1270 {
... ... @@ -1243,7 +1273,56 @@ void OPPROTO op_movl_eflags_T0(void)
1243 1273 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1244 1274 DF = 1 - (2 * ((eflags >> 10) & 1));
1245 1275 /* we also update some system flags as in user mode */
1246   - env->eflags = (env->eflags & ~FL_UPDATE_MASK) | (eflags & FL_UPDATE_MASK);
  1276 + env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
  1277 +}
  1278 +
  1279 +void OPPROTO op_movw_eflags_T0(void)
  1280 +{
  1281 + int eflags;
  1282 + eflags = T0;
  1283 + CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
  1284 + DF = 1 - (2 * ((eflags >> 10) & 1));
  1285 + /* we also update some system flags as in user mode */
  1286 + env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
  1287 +}
  1288 +
  1289 +/* vm86 version */
  1290 +void OPPROTO op_movw_eflags_T0_vm(void)
  1291 +{
  1292 + int eflags;
  1293 + eflags = T0;
  1294 + CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
  1295 + DF = 1 - (2 * ((eflags >> 10) & 1));
  1296 + /* we also update some system flags as in user mode */
  1297 + env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
  1298 + (eflags & FL_UPDATE_MASK16);
  1299 + if (eflags & IF_MASK) {
  1300 + env->eflags |= VIF_MASK;
  1301 + if (env->eflags & VIP_MASK) {
  1302 + EIP = PARAM1;
  1303 + raise_exception(EXCP0D_GPF);
  1304 + }
  1305 + }
  1306 + FORCE_RET();
  1307 +}
  1308 +
  1309 +void OPPROTO op_movl_eflags_T0_vm(void)
  1310 +{
  1311 + int eflags;
  1312 + eflags = T0;
  1313 + CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
  1314 + DF = 1 - (2 * ((eflags >> 10) & 1));
  1315 + /* we also update some system flags as in user mode */
  1316 + env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
  1317 + (eflags & FL_UPDATE_MASK32);
  1318 + if (eflags & IF_MASK) {
  1319 + env->eflags |= VIF_MASK;
  1320 + if (env->eflags & VIP_MASK) {
  1321 + EIP = PARAM1;
  1322 + raise_exception(EXCP0D_GPF);
  1323 + }
  1324 + }
  1325 + FORCE_RET();
1247 1326 }
1248 1327  
1249 1328 /* XXX: compute only O flag */
... ... @@ -1263,6 +1342,18 @@ void OPPROTO op_movl_T0_eflags(void)
1263 1342 T0 = eflags;
1264 1343 }
1265 1344  
  1345 +/* vm86 version */
  1346 +void OPPROTO op_movl_T0_eflags_vm(void)
  1347 +{
  1348 + int eflags;
  1349 + eflags = cc_table[CC_OP].compute_all();
  1350 + eflags |= (DF & DF_MASK);
  1351 + eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
  1352 + if (env->eflags & VIF_MASK)
  1353 + eflags |= IF_MASK;
  1354 + T0 = eflags;
  1355 +}
  1356 +
1266 1357 void OPPROTO op_cld(void)
1267 1358 {
1268 1359 DF = 1;
... ... @@ -1377,7 +1468,9 @@ CCTable cc_table[CC_OP_NB] = {
1377 1468 [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
1378 1469 };
1379 1470  
1380   -/* floating point support */
  1471 +/* floating point support. Some of the code for complicated x87
  1472 + functions comes from the LGPL'ed x86 emulator found in the Willows
  1473 + TWIN windows emulator. */
1381 1474  
1382 1475 #ifdef USE_X86LDOUBLE
1383 1476 /* use long double functions */
... ...
opc-i386.h
... ... @@ -232,6 +232,10 @@ DEF(jmp_im, 1)
232 232 DEF(int_im, 1)
233 233 DEF(int3, 1)
234 234 DEF(into, 0)
  235 +DEF(cli, 0)
  236 +DEF(sti, 0)
  237 +DEF(cli_vm, 0)
  238 +DEF(sti_vm, 1)
235 239 DEF(boundw, 0)
236 240 DEF(boundl, 0)
237 241 DEF(cmpxchg8b, 0)
... ... @@ -551,8 +555,12 @@ DEF(setle_T0_cc, 0)
551 555 DEF(xor_T0_1, 0)
552 556 DEF(set_cc_op, 1)
553 557 DEF(movl_eflags_T0, 0)
  558 +DEF(movw_eflags_T0, 0)
  559 +DEF(movw_eflags_T0_vm, 1)
  560 +DEF(movl_eflags_T0_vm, 1)
554 561 DEF(movb_eflags_T0, 0)
555 562 DEF(movl_T0_eflags, 0)
  563 +DEF(movl_T0_eflags_vm, 0)
556 564 DEF(cld, 0)
557 565 DEF(std, 0)
558 566 DEF(clc, 0)
... ...
translate-i386.c
... ... @@ -1919,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1919 1919 break;
1920 1920 case 0x1a0: /* push fs */
1921 1921 case 0x1a8: /* push gs */
1922   - gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
  1922 + gen_op_movl_T0_seg((b >> 3) & 7);
1923 1923 gen_push_T0(s);
1924 1924 break;
1925 1925 case 0x07: /* pop es */
... ... @@ -1932,7 +1932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1932 1932 case 0x1a1: /* pop fs */
1933 1933 case 0x1a9: /* pop gs */
1934 1934 gen_pop_T0(s);
1935   - gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
  1935 + gen_movl_seg_T0(s, (b >> 3) & 7);
1936 1936 gen_pop_update(s);
1937 1937 break;
1938 1938  
... ... @@ -2833,6 +2833,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2833 2833 s->is_jmp = 1;
2834 2834 break;
2835 2835 case 0xca: /* lret im */
  2836 + /* XXX: not restartable */
2836 2837 val = ldsw(s->pc);
2837 2838 s->pc += 2;
2838 2839 /* pop offset */
... ... @@ -2853,6 +2854,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2853 2854 s->is_jmp = 1;
2854 2855 break;
2855 2856 case 0xcb: /* lret */
  2857 + /* XXX: not restartable */
2856 2858 /* pop offset */
2857 2859 gen_pop_T0(s);
2858 2860 if (s->dflag == 0)
... ... @@ -2865,6 +2867,35 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2865 2867 gen_pop_update(s);
2866 2868 s->is_jmp = 1;
2867 2869 break;
  2870 + case 0xcf: /* iret */
  2871 + /* XXX: not restartable */
  2872 + /* pop offset */
  2873 + gen_pop_T0(s);
  2874 + if (s->dflag == 0)
  2875 + gen_op_andl_T0_ffff();
  2876 + gen_op_jmp_T0();
  2877 + gen_pop_update(s);
  2878 + /* pop selector */
  2879 + gen_pop_T0(s);
  2880 + gen_movl_seg_T0(s, R_CS);
  2881 + gen_pop_update(s);
  2882 + /* pop eflags */
  2883 + gen_pop_T0(s);
  2884 + if (s->dflag) {
  2885 + if (s->vm86)
  2886 + gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
  2887 + else
  2888 + gen_op_movl_eflags_T0();
  2889 + } else {
  2890 + if (s->vm86)
  2891 + gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
  2892 + else
  2893 + gen_op_movw_eflags_T0();
  2894 + }
  2895 + gen_pop_update(s);
  2896 + s->cc_op = CC_OP_EFLAGS;
  2897 + s->is_jmp = 1;
  2898 + break;
2868 2899 case 0xe8: /* call im */
2869 2900 {
2870 2901 unsigned int next_eip;
... ... @@ -2978,12 +3009,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2978 3009 case 0x9c: /* pushf */
2979 3010 if (s->cc_op != CC_OP_DYNAMIC)
2980 3011 gen_op_set_cc_op(s->cc_op);
2981   - gen_op_movl_T0_eflags();
  3012 + if (s->vm86)
  3013 + gen_op_movl_T0_eflags_vm();
  3014 + else
  3015 + gen_op_movl_T0_eflags();
2982 3016 gen_push_T0(s);
2983 3017 break;
2984 3018 case 0x9d: /* popf */
2985 3019 gen_pop_T0(s);
2986   - gen_op_movl_eflags_T0();
  3020 + if (s->dflag) {
  3021 + if (s->vm86)
  3022 + gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
  3023 + else
  3024 + gen_op_movl_eflags_T0();
  3025 + } else {
  3026 + if (s->vm86)
  3027 + gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
  3028 + else
  3029 + gen_op_movw_eflags_T0();
  3030 + }
2987 3031 gen_pop_update(s);
2988 3032 s->cc_op = CC_OP_EFLAGS;
2989 3033 break;
... ... @@ -3159,6 +3203,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3159 3203 gen_op_set_cc_op(s->cc_op);
3160 3204 gen_op_into();
3161 3205 break;
  3206 + case 0xfa: /* cli */
  3207 + if (s->vm86)
  3208 + gen_op_cli_vm();
  3209 + else
  3210 + gen_op_cli();
  3211 + break;
  3212 + case 0xfb: /* sti */
  3213 + if (s->vm86)
  3214 + gen_op_sti_vm(pc_start - s->cs_base);
  3215 + else
  3216 + gen_op_sti();
  3217 + break;
3162 3218 case 0x62: /* bound */
3163 3219 ot = dflag ? OT_LONG : OT_WORD;
3164 3220 modrm = ldub(s->pc++);
... ... @@ -3308,6 +3364,7 @@ static uint16_t opc_read_flags[NB_OPS] = {
3308 3364 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3309 3365  
3310 3366 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
  3367 + [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
3311 3368 [INDEX_op_cmc] = CC_C,
3312 3369 [INDEX_op_salc] = CC_C,
3313 3370  
... ... @@ -3356,7 +3413,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
3356 3413 [INDEX_op_daa] = CC_OSZAPC,
3357 3414  
3358 3415 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
  3416 + [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
  3417 + [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC,
3359 3418 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
  3419 + [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC,
3360 3420 [INDEX_op_clc] = CC_C,
3361 3421 [INDEX_op_stc] = CC_C,
3362 3422 [INDEX_op_cmc] = CC_C,
... ...