- Timestamp:
- Mar 14, 2007 5:30:12 PM (18 years ago)
- Location:
- trunk/src/recompiler/target-i386
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/recompiler/target-i386/exec.h
r1 r1478 238 238 void OPPROTO op_movl_eflags_T0(void); 239 239 void OPPROTO op_movl_T0_eflags(void); 240 #ifdef VBOX 241 void OPPROTO op_movl_T0_eflags_vme(void); 242 void OPPROTO op_movw_eflags_T0_vme(void); 243 void OPPROTO op_cli_vme(void); 244 void OPPROTO op_sti_vme(void); 245 #endif 240 246 void helper_divl_EAX_T0(void); 241 247 void helper_idivl_EAX_T0(void); -
trunk/src/recompiler/target-i386/helper.c
r1093 r1478 803 803 env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); 804 804 } 805 806 #ifdef VBOX 807 808 /* check if VME interrupt redirection is enabled in TSS */ 809 static inline bool is_vme_irq_redirected(int intno) 810 { 811 int io_offset, intredir_offset; 812 unsigned char val, mask; 813 814 /* TSS must be a valid 32 bit one */ 815 if (!(env->tr.flags & DESC_P_MASK) || 816 ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 || 817 env->tr.limit < 103) 818 goto fail; 819 io_offset = lduw_kernel(env->tr.base + 0x66); 820 /* the virtual interrupt redirection bitmap is located below the io bitmap */ 821 intredir_offset = io_offset - 0x20; 822 823 intredir_offset += (intno >> 3); 824 if ((intredir_offset) > env->tr.limit) 825 goto fail; 826 827 val = ldub_kernel(env->tr.base + intredir_offset); 828 mask = 1 << (unsigned char)(intno & 7); 829 830 /* bit set means no redirection. */ 831 if ((val & mask) != 0) { 832 return false; 833 } 834 return true; 835 836 fail: 837 raise_exception_err(EXCP0D_GPF, 0); 838 return true; 839 } 840 841 /* V86 mode software interrupt with CR4.VME=1 */ 842 static void do_soft_interrupt_vme(int intno, int error_code, unsigned int next_eip) 843 { 844 target_ulong ptr, ssp; 845 int selector; 846 uint32_t offset, esp; 847 uint32_t old_cs, old_eflags; 848 uint32_t iopl; 849 850 iopl = ((env->eflags >> IOPL_SHIFT) & 3); 851 852 if (!is_vme_irq_redirected(intno)) 853 { 854 if (iopl == 3) 855 /* normal protected mode handler call */ 856 return do_interrupt_protected(intno, 1, error_code, next_eip, 0); 857 else 858 raise_exception_err(EXCP0D_GPF, 0); 859 } 860 861 /* virtual mode idt is at linear address 0 */ 862 ptr = 0 + intno * 4; 863 offset = lduw_kernel(ptr); 864 selector = lduw_kernel(ptr + 2); 865 esp = ESP; 866 ssp = env->segs[R_SS].base; 867 old_cs = env->segs[R_CS].selector; 868 869 old_eflags = compute_eflags(); 870 if (iopl < 3) 871 { 872 /* copy VIF into IF and set IOPL to 3 */ 873 if (env->eflags & VIF_MASK) 874 old_eflags |= IF_MASK; 875 else 876 old_eflags &= ~IF_MASK; 877 878 old_eflags |= (3 << IOPL_SHIFT); 879 } 880 881 /* XXX: use SS segment size ? */ 882 PUSHW(ssp, esp, 0xffff, old_eflags); 883 PUSHW(ssp, esp, 0xffff, old_cs); 884 PUSHW(ssp, esp, 0xffff, next_eip); 885 886 /* update processor state */ 887 ESP = (ESP & ~0xffff) | (esp & 0xffff); 888 env->eip = offset; 889 env->segs[R_CS].selector = selector; 890 env->segs[R_CS].base = (selector << 4); 891 env->eflags &= ~(TF_MASK | RF_MASK); 892 893 if (iopl < 3) 894 env->eflags &= ~IF_MASK; 895 else 896 env->eflags &= ~VIF_MASK; 897 } 898 #endif 805 899 806 900 #ifdef TARGET_X86_64 … … 1224 1318 #endif 1225 1319 { 1226 do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); 1320 #ifdef VBOX 1321 /* int xx *, v86 code and VME enabled? */ 1322 if ( !is_hw 1323 && is_int 1324 && env->eip + 1 != next_eip /* single byte int 3 goes straight to the protected mode handler */ 1325 && (env->eflags & VM_MASK) 1326 && (env->cr[4] & CR4_VME_MASK) 1327 ) 1328 do_soft_interrupt_vme(intno, error_code, next_eip); 1329 else 1330 #endif 1331 do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); 1227 1332 } 1228 1333 } else { … … 2009 2114 2010 2115 #ifdef VBOX 2116 bool fVME = false; 2117 2011 2118 remR3TrapClear(env->pVM); 2012 2119 #endif … … 2027 2134 POPW(ssp, sp, sp_mask, new_eflags); 2028 2135 } 2136 #ifdef VBOX 2137 if ( (env->eflags & VM_MASK) 2138 && ((env->eflags >> IOPL_SHIFT) & 3) != 3 2139 && (env->cr[4] & CR4_VME_MASK)) /* implied or else we would fault earlier */ 2140 { 2141 fVME = true; 2142 /* if virtual interrupt pending and (virtual) interrupts will be enabled -> #GP */ 2143 /* if TF will be set -> #GP */ 2144 if ( ((new_eflags & IF_MASK) && (env->eflags & VIP_MASK)) 2145 || (new_eflags & TF_MASK)) 2146 { 2147 raise_exception(EXCP0D_GPF); 2148 } 2149 } 2150 #endif 2151 2029 2152 ESP = (ESP & ~sp_mask) | (sp & sp_mask); 2030 2153 load_seg_vm(R_CS, new_cs); 2031 2154 env->eip = new_eip; 2155 #ifdef VBOX 2156 if (fVME) 2157 eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK; 2158 else 2159 #endif 2032 2160 if (env->eflags & VM_MASK) 2033 2161 eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK; … … 2036 2164 if (shift == 0) 2037 2165 eflags_mask &= 0xffff; 2166 2038 2167 load_eflags(new_eflags, eflags_mask); 2168 2169 #ifdef VBOX 2170 if (fVME) 2171 { 2172 if (new_eflags & IF_MASK) 2173 env->eflags |= VIF_MASK; 2174 else 2175 env->eflags &= ~VIF_MASK; 2176 } 2177 #endif 2039 2178 } 2040 2179 -
trunk/src/recompiler/target-i386/op.c
r1 r1478 721 721 } 722 722 723 #if 0723 #ifdef VBOX 724 724 /* vm86plus instructions */ 725 void OPPROTO op_cli_vm (void)725 void OPPROTO op_cli_vme(void) 726 726 { 727 727 env->eflags &= ~VIF_MASK; 728 728 } 729 729 730 void OPPROTO op_sti_vm (void)731 { 732 env->eflags |= VIF_MASK;730 void OPPROTO op_sti_vme(void) 731 { 732 /* First check, then change eflags according to the AMD manual */ 733 733 if (env->eflags & VIP_MASK) { 734 EIP = PARAM1;735 734 raise_exception(EXCP0D_GPF); 736 735 } 736 env->eflags |= VIF_MASK; 737 737 FORCE_RET(); 738 738 } … … 1463 1463 1464 1464 /* XXX: clear VIF/VIP in all ops ? */ 1465 #ifdef VBOX 1466 /* XXX: AMD docs say they remain unchanged. */ 1467 #endif 1465 1468 1466 1469 void OPPROTO op_movl_eflags_T0(void) … … 1494 1497 } 1495 1498 1499 /* vm86plus version */ 1500 #ifdef VBOX 1501 /* IOPL != 3, CR4.VME=1 */ 1502 void OPPROTO op_movw_eflags_T0_vme(void) 1503 { 1504 unsigned int new_eflags = T0; 1505 1506 /* if virtual interrupt pending and (virtual) interrupts will be enabled -> #GP */ 1507 /* if TF will be set -> #GP */ 1508 if ( ((new_eflags & IF_MASK) && (env->eflags & VIP_MASK)) 1509 || (new_eflags & TF_MASK)) 1510 { 1511 raise_exception(EXCP0D_GPF); 1512 } 1513 else 1514 { 1515 load_eflags(new_eflags, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff); 1516 1517 if (new_eflags & IF_MASK) 1518 env->eflags |= VIF_MASK; 1519 else 1520 env->eflags &= ~VIF_MASK; 1521 } 1522 1523 FORCE_RET(); 1524 } 1525 #endif 1526 1496 1527 #if 0 1497 /* vm86plus version */1498 void OPPROTO op_movw_eflags_T0_vm(void)1499 {1500 int eflags;1501 eflags = T0;1502 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);1503 DF = 1 - (2 * ((eflags >> 10) & 1));1504 /* we also update some system flags as in user mode */1505 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |1506 (eflags & FL_UPDATE_MASK16);1507 if (eflags & IF_MASK) {1508 env->eflags |= VIF_MASK;1509 if (env->eflags & VIP_MASK) {1510 EIP = PARAM1;1511 raise_exception(EXCP0D_GPF);1512 }1513 }1514 FORCE_RET();1515 }1516 1517 1528 void OPPROTO op_movl_eflags_T0_vm(void) 1518 1529 { … … 1553 1564 1554 1565 /* vm86plus version */ 1555 #if 01556 void OPPROTO op_movl_T0_eflags_vm (void)1566 #ifdef VBOX 1567 void OPPROTO op_movl_T0_eflags_vme(void) 1557 1568 { 1558 1569 int eflags; -
trunk/src/recompiler/target-i386/translate.c
r1 r1478 119 119 int f_st; /* currently unused */ 120 120 int vm86; /* vm86 mode */ 121 #ifdef VBOX 122 int vme; /* CR4.VME */ 123 #endif 121 124 int cpl; 122 125 int iopl; … … 4969 4972 s->cc_op = CC_OP_EFLAGS; 4970 4973 } else if (s->vm86) { 4974 #ifdef VBOX 4975 if (s->iopl != 3 && (!s->vme || s->dflag)) { 4976 #else 4971 4977 if (s->iopl != 3) { 4978 #endif 4972 4979 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 4973 4980 } else { … … 5085 5092 /* flags */ 5086 5093 case 0x9c: /* pushf */ 5094 #ifdef VBOX 5095 if (s->vm86 && s->iopl != 3 && (!s->vme || s->dflag)) { 5096 #else 5087 5097 if (s->vm86 && s->iopl != 3) { 5098 #endif 5088 5099 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 5089 5100 } else { 5090 5101 if (s->cc_op != CC_OP_DYNAMIC) 5091 5102 gen_op_set_cc_op(s->cc_op); 5092 gen_op_movl_T0_eflags(); 5103 #ifdef VBOX 5104 if (s->vm86 && s->vme && s->iopl != 3) 5105 gen_op_movl_T0_eflags_vme(); 5106 else 5107 #endif 5108 gen_op_movl_T0_eflags(); 5093 5109 gen_push_T0(s); 5094 5110 } 5095 5111 break; 5096 5112 case 0x9d: /* popf */ 5113 #ifdef VBOX 5114 if (s->vm86 && s->iopl != 3 && (!s->vme || s->dflag)) { 5115 #else 5097 5116 if (s->vm86 && s->iopl != 3) { 5117 #endif 5098 5118 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 5099 5119 } else { … … 5116 5136 gen_op_movl_eflags_T0(); 5117 5137 } else { 5118 gen_op_movw_eflags_T0(); 5138 #ifdef VBOX 5139 if (s->vm86 && s->vme) 5140 gen_op_movw_eflags_T0_vme(); 5141 else 5142 #endif 5143 gen_op_movw_eflags_T0(); 5119 5144 } 5120 5145 } … … 5317 5342 break; 5318 5343 case 0xcc: /* int3 */ 5319 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); 5344 #ifdef VBOX 5345 if (s->vm86 && s->iopl != 3 && !s->vme) { 5346 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 5347 } 5348 else 5349 #endif 5350 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); 5320 5351 break; 5321 5352 case 0xcd: /* int N */ 5322 5353 val = ldub_code(s->pc++); 5354 #ifdef VBOX 5355 if (s->vm86 && s->iopl != 3 && !s->vme) { 5356 #else 5323 5357 if (s->vm86 && s->iopl != 3) { 5358 #endif 5324 5359 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 5325 5360 } else { … … 5348 5383 if (s->iopl == 3) { 5349 5384 gen_op_cli(); 5385 #ifdef VBOX 5386 } else 5387 if (s->iopl != 3 && s->vme) { 5388 gen_op_cli_vme(); 5389 #endif 5350 5390 } else { 5351 5391 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); … … 5372 5412 if (s->iopl == 3) { 5373 5413 goto gen_sti; 5414 #ifdef VBOX 5415 } else 5416 if (s->iopl != 3 && s->vme) { 5417 gen_op_sti_vme(); 5418 /* give a chance to handle pending irqs */ 5419 gen_jmp_im(s->pc - s->cs_base); 5420 gen_eob(s); 5421 #endif 5374 5422 } else { 5375 5423 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); … … 6412 6460 dc->f_st = 0; 6413 6461 dc->vm86 = (flags >> VM_SHIFT) & 1; 6462 #ifdef VBOX 6463 dc->vme = !!(env->cr[4] & CR4_VME_MASK); 6464 #endif 6414 6465 dc->cpl = (flags >> HF_CPL_SHIFT) & 3; 6415 6466 dc->iopl = (flags >> IOPL_SHIFT) & 3;
Note:
See TracChangeset
for help on using the changeset viewer.