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,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 void OPPROTO op_boundw(void) 643 void OPPROTO op_boundw(void)
615 { 644 {
616 int low, high, v; 645 int low, high, v;
@@ -1234,7 +1263,8 @@ void OPPROTO op_set_cc_op(void) @@ -1234,7 +1263,8 @@ void OPPROTO op_set_cc_op(void)
1234 CC_OP = PARAM1; 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 void OPPROTO op_movl_eflags_T0(void) 1269 void OPPROTO op_movl_eflags_T0(void)
1240 { 1270 {
@@ -1243,7 +1273,56 @@ void OPPROTO op_movl_eflags_T0(void) @@ -1243,7 +1273,56 @@ void OPPROTO op_movl_eflags_T0(void)
1243 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 1273 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1244 DF = 1 - (2 * ((eflags >> 10) & 1)); 1274 DF = 1 - (2 * ((eflags >> 10) & 1));
1245 /* we also update some system flags as in user mode */ 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 /* XXX: compute only O flag */ 1328 /* XXX: compute only O flag */
@@ -1263,6 +1342,18 @@ void OPPROTO op_movl_T0_eflags(void) @@ -1263,6 +1342,18 @@ void OPPROTO op_movl_T0_eflags(void)
1263 T0 = eflags; 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 void OPPROTO op_cld(void) 1357 void OPPROTO op_cld(void)
1267 { 1358 {
1268 DF = 1; 1359 DF = 1;
@@ -1377,7 +1468,9 @@ CCTable cc_table[CC_OP_NB] = { @@ -1377,7 +1468,9 @@ CCTable cc_table[CC_OP_NB] = {
1377 [CC_OP_SARL] = { compute_all_sarl, compute_c_shll }, 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 #ifdef USE_X86LDOUBLE 1475 #ifdef USE_X86LDOUBLE
1383 /* use long double functions */ 1476 /* use long double functions */
opc-i386.h
@@ -232,6 +232,10 @@ DEF(jmp_im, 1) @@ -232,6 +232,10 @@ DEF(jmp_im, 1)
232 DEF(int_im, 1) 232 DEF(int_im, 1)
233 DEF(int3, 1) 233 DEF(int3, 1)
234 DEF(into, 0) 234 DEF(into, 0)
  235 +DEF(cli, 0)
  236 +DEF(sti, 0)
  237 +DEF(cli_vm, 0)
  238 +DEF(sti_vm, 1)
235 DEF(boundw, 0) 239 DEF(boundw, 0)
236 DEF(boundl, 0) 240 DEF(boundl, 0)
237 DEF(cmpxchg8b, 0) 241 DEF(cmpxchg8b, 0)
@@ -551,8 +555,12 @@ DEF(setle_T0_cc, 0) @@ -551,8 +555,12 @@ DEF(setle_T0_cc, 0)
551 DEF(xor_T0_1, 0) 555 DEF(xor_T0_1, 0)
552 DEF(set_cc_op, 1) 556 DEF(set_cc_op, 1)
553 DEF(movl_eflags_T0, 0) 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 DEF(movb_eflags_T0, 0) 561 DEF(movb_eflags_T0, 0)
555 DEF(movl_T0_eflags, 0) 562 DEF(movl_T0_eflags, 0)
  563 +DEF(movl_T0_eflags_vm, 0)
556 DEF(cld, 0) 564 DEF(cld, 0)
557 DEF(std, 0) 565 DEF(std, 0)
558 DEF(clc, 0) 566 DEF(clc, 0)
translate-i386.c
@@ -1919,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1919,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1919 break; 1919 break;
1920 case 0x1a0: /* push fs */ 1920 case 0x1a0: /* push fs */
1921 case 0x1a8: /* push gs */ 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 gen_push_T0(s); 1923 gen_push_T0(s);
1924 break; 1924 break;
1925 case 0x07: /* pop es */ 1925 case 0x07: /* pop es */
@@ -1932,7 +1932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1932,7 +1932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1932 case 0x1a1: /* pop fs */ 1932 case 0x1a1: /* pop fs */
1933 case 0x1a9: /* pop gs */ 1933 case 0x1a9: /* pop gs */
1934 gen_pop_T0(s); 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 gen_pop_update(s); 1936 gen_pop_update(s);
1937 break; 1937 break;
1938 1938
@@ -2833,6 +2833,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2833,6 +2833,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2833 s->is_jmp = 1; 2833 s->is_jmp = 1;
2834 break; 2834 break;
2835 case 0xca: /* lret im */ 2835 case 0xca: /* lret im */
  2836 + /* XXX: not restartable */
2836 val = ldsw(s->pc); 2837 val = ldsw(s->pc);
2837 s->pc += 2; 2838 s->pc += 2;
2838 /* pop offset */ 2839 /* pop offset */
@@ -2853,6 +2854,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2853,6 +2854,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2853 s->is_jmp = 1; 2854 s->is_jmp = 1;
2854 break; 2855 break;
2855 case 0xcb: /* lret */ 2856 case 0xcb: /* lret */
  2857 + /* XXX: not restartable */
2856 /* pop offset */ 2858 /* pop offset */
2857 gen_pop_T0(s); 2859 gen_pop_T0(s);
2858 if (s->dflag == 0) 2860 if (s->dflag == 0)
@@ -2865,6 +2867,35 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2865,6 +2867,35 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2865 gen_pop_update(s); 2867 gen_pop_update(s);
2866 s->is_jmp = 1; 2868 s->is_jmp = 1;
2867 break; 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 case 0xe8: /* call im */ 2899 case 0xe8: /* call im */
2869 { 2900 {
2870 unsigned int next_eip; 2901 unsigned int next_eip;
@@ -2978,12 +3009,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2978,12 +3009,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2978 case 0x9c: /* pushf */ 3009 case 0x9c: /* pushf */
2979 if (s->cc_op != CC_OP_DYNAMIC) 3010 if (s->cc_op != CC_OP_DYNAMIC)
2980 gen_op_set_cc_op(s->cc_op); 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 gen_push_T0(s); 3016 gen_push_T0(s);
2983 break; 3017 break;
2984 case 0x9d: /* popf */ 3018 case 0x9d: /* popf */
2985 gen_pop_T0(s); 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 gen_pop_update(s); 3031 gen_pop_update(s);
2988 s->cc_op = CC_OP_EFLAGS; 3032 s->cc_op = CC_OP_EFLAGS;
2989 break; 3033 break;
@@ -3159,6 +3203,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3159,6 +3203,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3159 gen_op_set_cc_op(s->cc_op); 3203 gen_op_set_cc_op(s->cc_op);
3160 gen_op_into(); 3204 gen_op_into();
3161 break; 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 case 0x62: /* bound */ 3218 case 0x62: /* bound */
3163 ot = dflag ? OT_LONG : OT_WORD; 3219 ot = dflag ? OT_LONG : OT_WORD;
3164 modrm = ldub(s->pc++); 3220 modrm = ldub(s->pc++);
@@ -3308,6 +3364,7 @@ static uint16_t opc_read_flags[NB_OPS] = { @@ -3308,6 +3364,7 @@ static uint16_t opc_read_flags[NB_OPS] = {
3308 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, 3364 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3309 3365
3310 [INDEX_op_movl_T0_eflags] = CC_OSZAPC, 3366 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
  3367 + [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC,
3311 [INDEX_op_cmc] = CC_C, 3368 [INDEX_op_cmc] = CC_C,
3312 [INDEX_op_salc] = CC_C, 3369 [INDEX_op_salc] = CC_C,
3313 3370
@@ -3356,7 +3413,10 @@ static uint16_t opc_write_flags[NB_OPS] = { @@ -3356,7 +3413,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
3356 [INDEX_op_daa] = CC_OSZAPC, 3413 [INDEX_op_daa] = CC_OSZAPC,
3357 3414
3358 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, 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 [INDEX_op_movl_eflags_T0] = CC_OSZAPC, 3418 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
  3419 + [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC,
3360 [INDEX_op_clc] = CC_C, 3420 [INDEX_op_clc] = CC_C,
3361 [INDEX_op_stc] = CC_C, 3421 [INDEX_op_stc] = CC_C,
3362 [INDEX_op_cmc] = CC_C, 3422 [INDEX_op_cmc] = CC_C,