DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 CASE_D(0x01) /* ADD Ed,Gd */ 00020 RMEdGd(ADDD);break; 00021 CASE_D(0x03) /* ADD Gd,Ed */ 00022 RMGdEd(ADDD);break; 00023 CASE_D(0x05) /* ADD EAX,Id */ 00024 EAXId(ADDD);break; 00025 CASE_D(0x06) /* PUSH ES */ 00026 Push_32(SegValue(es));break; 00027 CASE_D(0x07) /* POP ES */ 00028 if (CPU_PopSeg(es,true)) RUNEXCEPTION(); 00029 break; 00030 CASE_D(0x09) /* OR Ed,Gd */ 00031 RMEdGd(ORD);break; 00032 CASE_D(0x0b) /* OR Gd,Ed */ 00033 RMGdEd(ORD);break; 00034 CASE_D(0x0d) /* OR EAX,Id */ 00035 EAXId(ORD);break; 00036 CASE_D(0x0e) /* PUSH CS */ 00037 Push_32(SegValue(cs));break; 00038 CASE_D(0x11) /* ADC Ed,Gd */ 00039 RMEdGd(ADCD);break; 00040 CASE_D(0x13) /* ADC Gd,Ed */ 00041 RMGdEd(ADCD);break; 00042 CASE_D(0x15) /* ADC EAX,Id */ 00043 EAXId(ADCD);break; 00044 CASE_D(0x16) /* PUSH SS */ 00045 Push_32(SegValue(ss));break; 00046 CASE_D(0x17) /* POP SS */ 00047 if (CPU_PopSeg(ss,true)) RUNEXCEPTION(); 00048 CPU_Cycles++; 00049 break; 00050 CASE_D(0x19) /* SBB Ed,Gd */ 00051 RMEdGd(SBBD);break; 00052 CASE_D(0x1b) /* SBB Gd,Ed */ 00053 RMGdEd(SBBD);break; 00054 CASE_D(0x1d) /* SBB EAX,Id */ 00055 EAXId(SBBD);break; 00056 CASE_D(0x1e) /* PUSH DS */ 00057 Push_32(SegValue(ds));break; 00058 CASE_D(0x1f) /* POP DS */ 00059 if (CPU_PopSeg(ds,true)) RUNEXCEPTION(); 00060 break; 00061 CASE_D(0x21) /* AND Ed,Gd */ 00062 RMEdGd(ANDD);break; 00063 CASE_D(0x23) /* AND Gd,Ed */ 00064 RMGdEd(ANDD);break; 00065 CASE_D(0x25) /* AND EAX,Id */ 00066 EAXId(ANDD);break; 00067 CASE_D(0x29) /* SUB Ed,Gd */ 00068 RMEdGd(SUBD);break; 00069 CASE_D(0x2b) /* SUB Gd,Ed */ 00070 RMGdEd(SUBD);break; 00071 CASE_D(0x2d) /* SUB EAX,Id */ 00072 EAXId(SUBD);break; 00073 CASE_D(0x31) /* XOR Ed,Gd */ 00074 RMEdGd(XORD);break; 00075 CASE_D(0x33) /* XOR Gd,Ed */ 00076 RMGdEd(XORD);break; 00077 CASE_D(0x35) /* XOR EAX,Id */ 00078 EAXId(XORD);break; 00079 CASE_D(0x39) /* CMP Ed,Gd */ 00080 RMEdGd(CMPD);break; 00081 CASE_D(0x3b) /* CMP Gd,Ed */ 00082 RMGdEd(CMPD);break; 00083 CASE_D(0x3d) /* CMP EAX,Id */ 00084 EAXId(CMPD);break; 00085 CASE_D(0x40) /* INC EAX */ 00086 INCD(reg_eax,LoadRd,SaveRd);break; 00087 CASE_D(0x41) /* INC ECX */ 00088 INCD(reg_ecx,LoadRd,SaveRd);break; 00089 CASE_D(0x42) /* INC EDX */ 00090 INCD(reg_edx,LoadRd,SaveRd);break; 00091 CASE_D(0x43) /* INC EBX */ 00092 INCD(reg_ebx,LoadRd,SaveRd);break; 00093 CASE_D(0x44) /* INC ESP */ 00094 INCD(reg_esp,LoadRd,SaveRd);break; 00095 CASE_D(0x45) /* INC EBP */ 00096 INCD(reg_ebp,LoadRd,SaveRd);break; 00097 CASE_D(0x46) /* INC ESI */ 00098 INCD(reg_esi,LoadRd,SaveRd);break; 00099 CASE_D(0x47) /* INC EDI */ 00100 INCD(reg_edi,LoadRd,SaveRd);break; 00101 CASE_D(0x48) /* DEC EAX */ 00102 DECD(reg_eax,LoadRd,SaveRd);break; 00103 CASE_D(0x49) /* DEC ECX */ 00104 DECD(reg_ecx,LoadRd,SaveRd);break; 00105 CASE_D(0x4a) /* DEC EDX */ 00106 DECD(reg_edx,LoadRd,SaveRd);break; 00107 CASE_D(0x4b) /* DEC EBX */ 00108 DECD(reg_ebx,LoadRd,SaveRd);break; 00109 CASE_D(0x4c) /* DEC ESP */ 00110 DECD(reg_esp,LoadRd,SaveRd);break; 00111 CASE_D(0x4d) /* DEC EBP */ 00112 DECD(reg_ebp,LoadRd,SaveRd);break; 00113 CASE_D(0x4e) /* DEC ESI */ 00114 DECD(reg_esi,LoadRd,SaveRd);break; 00115 CASE_D(0x4f) /* DEC EDI */ 00116 DECD(reg_edi,LoadRd,SaveRd);break; 00117 CASE_D(0x50) /* PUSH EAX */ 00118 Push_32(reg_eax);break; 00119 CASE_D(0x51) /* PUSH ECX */ 00120 Push_32(reg_ecx);break; 00121 CASE_D(0x52) /* PUSH EDX */ 00122 Push_32(reg_edx);break; 00123 CASE_D(0x53) /* PUSH EBX */ 00124 Push_32(reg_ebx);break; 00125 CASE_D(0x54) /* PUSH ESP */ 00126 Push_32(reg_esp);break; 00127 CASE_D(0x55) /* PUSH EBP */ 00128 Push_32(reg_ebp);break; 00129 CASE_D(0x56) /* PUSH ESI */ 00130 Push_32(reg_esi);break; 00131 CASE_D(0x57) /* PUSH EDI */ 00132 Push_32(reg_edi);break; 00133 CASE_D(0x58) /* POP EAX */ 00134 reg_eax=Pop_32();break; 00135 CASE_D(0x59) /* POP ECX */ 00136 reg_ecx=Pop_32();break; 00137 CASE_D(0x5a) /* POP EDX */ 00138 reg_edx=Pop_32();break; 00139 CASE_D(0x5b) /* POP EBX */ 00140 reg_ebx=Pop_32();break; 00141 CASE_D(0x5c) /* POP ESP */ 00142 reg_esp=Pop_32();break; 00143 CASE_D(0x5d) /* POP EBP */ 00144 reg_ebp=Pop_32();break; 00145 CASE_D(0x5e) /* POP ESI */ 00146 reg_esi=Pop_32();break; 00147 CASE_D(0x5f) /* POP EDI */ 00148 reg_edi=Pop_32();break; 00149 CASE_D(0x60) /* PUSHAD */ 00150 { 00151 Bit32u old_esp = reg_esp; 00152 try { 00153 Bit32u tmpesp = reg_esp; 00154 Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx); 00155 Push_32(tmpesp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); 00156 } 00157 catch (GuestPageFaultException &pf) { 00158 (void)pf; 00159 LOG_MSG("PUSHAD interrupted by page fault"); 00160 reg_esp = old_esp; 00161 throw; 00162 } 00163 } break; 00164 CASE_D(0x61) /* POPAD */ 00165 { 00166 Bit32u old_esp = reg_esp; 00167 try { 00168 reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP 00169 reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); 00170 } 00171 catch (GuestPageFaultException &pf) { 00172 (void)pf; 00173 LOG_MSG("POPAD interrupted by page fault"); 00174 reg_esp = old_esp; 00175 throw; 00176 } 00177 } break; 00178 CASE_D(0x62) /* BOUND Ed */ 00179 { 00180 Bit32s bound_min, bound_max; 00181 GetRMrd;GetEAa; 00182 bound_min=(Bit32s)LoadMd(eaa); 00183 bound_max=(Bit32s)LoadMd(eaa+4); 00184 if ( (((Bit32s)*rmrd) < bound_min) || (((Bit32s)*rmrd) > bound_max) ) { 00185 EXCEPTION(5); 00186 } 00187 } 00188 break; 00189 CASE_D(0x63) /* ARPL Ed,Rd */ 00190 { 00191 if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode; 00192 GetRMrw; 00193 if (rm >= 0xc0 ) { 00194 GetEArd;Bitu new_sel=(Bit16u)*eard; 00195 CPU_ARPL(new_sel,*rmrw); 00196 *eard=(Bit32u)new_sel; 00197 } else { 00198 GetEAa;Bitu new_sel=LoadMw(eaa); 00199 CPU_ARPL(new_sel,*rmrw); 00200 SaveMd(eaa,(Bit32u)new_sel); 00201 } 00202 } 00203 break; 00204 CASE_D(0x68) /* PUSH Id */ 00205 Push_32(Fetchd());break; 00206 CASE_D(0x69) /* IMUL Gd,Ed,Id */ 00207 RMGdEdOp3(DIMULD,Fetchds()); 00208 break; 00209 CASE_D(0x6a) /* PUSH Ib */ 00210 Push_32((Bit32u)Fetchbs());break; 00211 CASE_D(0x6b) /* IMUL Gd,Ed,Ib */ 00212 RMGdEdOp3(DIMULD,Fetchbs()); 00213 break; 00214 CASE_D(0x6d) /* INSD */ 00215 if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION(); 00216 DoString(R_INSD);break; 00217 CASE_D(0x6f) /* OUTSD */ 00218 if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION(); 00219 DoString(R_OUTSD);break; 00220 CASE_D(0x70) /* JO */ 00221 JumpCond32_b(TFLG_O);break; 00222 CASE_D(0x71) /* JNO */ 00223 JumpCond32_b(TFLG_NO);break; 00224 CASE_D(0x72) /* JB */ 00225 JumpCond32_b(TFLG_B);break; 00226 CASE_D(0x73) /* JNB */ 00227 JumpCond32_b(TFLG_NB);break; 00228 CASE_D(0x74) /* JZ */ 00229 JumpCond32_b(TFLG_Z);break; 00230 CASE_D(0x75) /* JNZ */ 00231 JumpCond32_b(TFLG_NZ);break; 00232 CASE_D(0x76) /* JBE */ 00233 JumpCond32_b(TFLG_BE);break; 00234 CASE_D(0x77) /* JNBE */ 00235 JumpCond32_b(TFLG_NBE);break; 00236 CASE_D(0x78) /* JS */ 00237 JumpCond32_b(TFLG_S);break; 00238 CASE_D(0x79) /* JNS */ 00239 JumpCond32_b(TFLG_NS);break; 00240 CASE_D(0x7a) /* JP */ 00241 JumpCond32_b(TFLG_P);break; 00242 CASE_D(0x7b) /* JNP */ 00243 JumpCond32_b(TFLG_NP);break; 00244 CASE_D(0x7c) /* JL */ 00245 JumpCond32_b(TFLG_L);break; 00246 CASE_D(0x7d) /* JNL */ 00247 JumpCond32_b(TFLG_NL);break; 00248 CASE_D(0x7e) /* JLE */ 00249 JumpCond32_b(TFLG_LE);break; 00250 CASE_D(0x7f) /* JNLE */ 00251 JumpCond32_b(TFLG_NLE);break; 00252 CASE_D(0x81) /* Grpl Ed,Id */ 00253 { 00254 GetRM;Bitu which=(rm>>3)&7; 00255 if (rm >= 0xc0) { 00256 GetEArd;Bit32u id=Fetchd(); 00257 switch (which) { 00258 case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; 00259 case 0x01: ORD(*eard,id,LoadRd,SaveRd);break; 00260 case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break; 00261 case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break; 00262 case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break; 00263 case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break; 00264 case 0x06:XORD(*eard,id,LoadRd,SaveRd);break; 00265 case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break; 00266 } 00267 } else { 00268 GetEAa;Bit32u id=Fetchd(); 00269 switch (which) { 00270 case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; 00271 case 0x01: ORD(eaa,id,LoadMd,SaveMd);break; 00272 case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break; 00273 case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break; 00274 case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break; 00275 case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break; 00276 case 0x06:XORD(eaa,id,LoadMd,SaveMd);break; 00277 case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break; 00278 } 00279 } 00280 } 00281 break; 00282 CASE_D(0x83) /* Grpl Ed,Ix */ 00283 { 00284 GetRM;Bitu which=(rm>>3)&7; 00285 if (rm >= 0xc0) { 00286 GetEArd;Bit32u id=(Bit32u)Fetchbs(); 00287 switch (which) { 00288 case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; 00289 case 0x01: ORD(*eard,id,LoadRd,SaveRd);break; 00290 case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break; 00291 case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break; 00292 case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break; 00293 case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break; 00294 case 0x06:XORD(*eard,id,LoadRd,SaveRd);break; 00295 case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break; 00296 } 00297 } else { 00298 GetEAa;Bit32u id=(Bit32u)Fetchbs(); 00299 switch (which) { 00300 case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; 00301 case 0x01: ORD(eaa,id,LoadMd,SaveMd);break; 00302 case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break; 00303 case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break; 00304 case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break; 00305 case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break; 00306 case 0x06:XORD(eaa,id,LoadMd,SaveMd);break; 00307 case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break; 00308 } 00309 } 00310 } 00311 break; 00312 CASE_D(0x85) /* TEST Ed,Gd */ 00313 RMEdGd(TESTD);break; 00314 CASE_D(0x87) /* XCHG Ed,Gd */ 00315 { 00316 GetRMrd;Bit32u oldrmrd=*rmrd; 00317 if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;} 00318 else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);} 00319 break; 00320 } 00321 CASE_D(0x89) /* MOV Ed,Gd */ 00322 { 00323 GetRMrd; 00324 if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;} 00325 else {GetEAa;SaveMd(eaa,*rmrd);} 00326 break; 00327 } 00328 CASE_D(0x8b) /* MOV Gd,Ed */ 00329 { 00330 GetRMrd; 00331 if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;} 00332 else {GetEAa;*rmrd=LoadMd(eaa);} 00333 break; 00334 } 00335 CASE_D(0x8c) /* Mov Ew,Sw */ 00336 { 00337 GetRM;Bit16u val;Bitu which=(rm>>3)&7; 00338 switch (which) { 00339 case 0x00: /* MOV Ew,ES */ 00340 val=SegValue(es);break; 00341 case 0x01: /* MOV Ew,CS */ 00342 val=SegValue(cs);break; 00343 case 0x02: /* MOV Ew,SS */ 00344 val=SegValue(ss);break; 00345 case 0x03: /* MOV Ew,DS */ 00346 val=SegValue(ds);break; 00347 case 0x04: /* MOV Ew,FS */ 00348 val=SegValue(fs);break; 00349 case 0x05: /* MOV Ew,GS */ 00350 val=SegValue(gs);break; 00351 default: 00352 LOG(LOG_CPU,LOG_ERROR)("CPU:8c:Illegal RM Byte"); 00353 goto illegal_opcode; 00354 } 00355 if (rm >= 0xc0 ) {GetEArd;*eard=val;} 00356 else {GetEAa;SaveMw(eaa,val);} 00357 break; 00358 } 00359 CASE_D(0x8d) /* LEA Gd */ 00360 { 00361 //Little hack to always use segprefixed version 00362 GetRMrd; 00363 BaseDS=BaseSS=0; 00364 if (TEST_PREFIX_ADDR) { 00365 *rmrd=(Bit32u)(*EATable[256+rm])(); 00366 } else { 00367 *rmrd=(Bit32u)(*EATable[rm])(); 00368 } 00369 break; 00370 } 00371 CASE_D(0x8f) /* POP Ed */ 00372 { 00373 Bit32u old_esp = reg_esp; 00374 00375 try { 00376 Bit32u val=Pop_32(); 00377 GetRM; 00378 if (rm >= 0xc0 ) {GetEArd;*eard=val;} 00379 else {GetEAa;SaveMd(eaa,val);} 00380 } 00381 catch (GuestPageFaultException &pf) { 00382 (void)pf; 00383 reg_esp = old_esp; 00384 throw; 00385 } 00386 } break; 00387 CASE_D(0x91) /* XCHG ECX,EAX */ 00388 { Bit32u temp=reg_eax;reg_eax=reg_ecx;reg_ecx=temp;break;} 00389 CASE_D(0x92) /* XCHG EDX,EAX */ 00390 { Bit32u temp=reg_eax;reg_eax=reg_edx;reg_edx=temp;break;} 00391 break; 00392 CASE_D(0x93) /* XCHG EBX,EAX */ 00393 { Bit32u temp=reg_eax;reg_eax=reg_ebx;reg_ebx=temp;break;} 00394 break; 00395 CASE_D(0x94) /* XCHG ESP,EAX */ 00396 { Bit32u temp=reg_eax;reg_eax=reg_esp;reg_esp=temp;break;} 00397 break; 00398 CASE_D(0x95) /* XCHG EBP,EAX */ 00399 { Bit32u temp=reg_eax;reg_eax=reg_ebp;reg_ebp=temp;break;} 00400 break; 00401 CASE_D(0x96) /* XCHG ESI,EAX */ 00402 { Bit32u temp=reg_eax;reg_eax=reg_esi;reg_esi=temp;break;} 00403 break; 00404 CASE_D(0x97) /* XCHG EDI,EAX */ 00405 { Bit32u temp=reg_eax;reg_eax=reg_edi;reg_edi=temp;break;} 00406 break; 00407 CASE_D(0x98) /* CWDE */ 00408 reg_eax=(Bit32u)((Bit16s)reg_ax);break; 00409 CASE_D(0x99) /* CDQ */ 00410 if (reg_eax & 0x80000000) reg_edx=0xffffffff; 00411 else reg_edx=0; 00412 break; 00413 CASE_D(0x9a) /* CALL FAR Ad */ 00414 { 00415 Bit32u newip=Fetchd();Bit16u newcs=Fetchw(); 00416 FillFlags(); 00417 CPU_CALL(true,newcs,newip,GETIP); 00418 #if CPU_TRAP_CHECK 00419 if (GETFLAG(TF)) { 00420 cpudecoder=CPU_TRAP_DECODER; 00421 return CBRET_NONE; 00422 } 00423 #endif 00424 continue; 00425 } 00426 CASE_D(0x9c) /* PUSHFD */ 00427 if (CPU_PUSHF(true)) RUNEXCEPTION(); 00428 break; 00429 CASE_D(0x9d) /* POPFD */ 00430 if (CPU_POPF(true)) RUNEXCEPTION(); 00431 #if CPU_TRAP_CHECK 00432 if (GETFLAG(TF)) { 00433 cpudecoder=CPU_TRAP_DECODER; 00434 goto decode_end; 00435 } 00436 #endif 00437 #if CPU_PIC_CHECK 00438 if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; 00439 #endif 00440 break; 00441 CASE_D(0xa1) /* MOV EAX,Od */ 00442 { /* NTS: GetEADirect may jump instead to the GP# trigger code if the offset exceeds the segment limit. 00443 For whatever reason, NOT signalling GP# in that condition prevents Windows 95 OSR2 from starting a DOS VM. Weird. */ 00444 GetEADirect(4); 00445 reg_eax=LoadMd(eaa); 00446 } 00447 break; 00448 CASE_D(0xa3) /* MOV Od,EAX */ 00449 { 00450 GetEADirect(4); 00451 SaveMd(eaa,reg_eax); 00452 } 00453 break; 00454 CASE_D(0xa5) /* MOVSD */ 00455 DoString(R_MOVSD);break; 00456 CASE_D(0xa7) /* CMPSD */ 00457 DoString(R_CMPSD);break; 00458 CASE_D(0xa9) /* TEST EAX,Id */ 00459 EAXId(TESTD);break; 00460 CASE_D(0xab) /* STOSD */ 00461 DoString(R_STOSD);break; 00462 CASE_D(0xad) /* LODSD */ 00463 DoString(R_LODSD);break; 00464 CASE_D(0xaf) /* SCASD */ 00465 DoString(R_SCASD);break; 00466 CASE_D(0xb8) /* MOV EAX,Id */ 00467 reg_eax=Fetchd();break; 00468 CASE_D(0xb9) /* MOV ECX,Id */ 00469 reg_ecx=Fetchd();break; 00470 CASE_D(0xba) /* MOV EDX,Iw */ 00471 reg_edx=Fetchd();break; 00472 CASE_D(0xbb) /* MOV EBX,Id */ 00473 reg_ebx=Fetchd();break; 00474 CASE_D(0xbc) /* MOV ESP,Id */ 00475 reg_esp=Fetchd();break; 00476 CASE_D(0xbd) /* MOV EBP.Id */ 00477 reg_ebp=Fetchd();break; 00478 CASE_D(0xbe) /* MOV ESI,Id */ 00479 reg_esi=Fetchd();break; 00480 CASE_D(0xbf) /* MOV EDI,Id */ 00481 reg_edi=Fetchd();break; 00482 CASE_D(0xc1) /* GRP2 Ed,Ib */ 00483 GRP2D(Fetchb());break; 00484 CASE_D(0xc2) /* RETN Iw */ 00485 { 00486 Bit32u old_esp = reg_esp; 00487 00488 try { 00489 /* this is structured either to complete RET or leave registers unmodified if interrupted by page fault */ 00490 Bit32u new_eip = Pop_32(); 00491 reg_esp += Fetchw(); 00492 reg_eip = new_eip; 00493 } 00494 catch (GuestPageFaultException &pf) { 00495 (void)pf; 00496 reg_esp = old_esp; /* restore stack pointer */ 00497 throw; 00498 } 00499 } continue; 00500 CASE_D(0xc3) /* RETN */ 00501 reg_eip=Pop_32(); 00502 continue; 00503 CASE_D(0xc4) /* LES */ 00504 { 00505 GetRMrd; 00506 if (rm >= 0xc0) goto illegal_opcode; 00507 GetEAa; 00508 if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION(); 00509 *rmrd=LoadMd(eaa); 00510 break; 00511 } 00512 CASE_D(0xc5) /* LDS */ 00513 { 00514 GetRMrd; 00515 if (rm >= 0xc0) goto illegal_opcode; 00516 GetEAa; 00517 if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION(); 00518 *rmrd=LoadMd(eaa); 00519 break; 00520 } 00521 CASE_D(0xc7) /* MOV Ed,Id */ 00522 { 00523 GetRM; 00524 if (rm >= 0xc0) {GetEArd;*eard=Fetchd();} 00525 else {GetEAa;SaveMd(eaa,Fetchd());} 00526 break; 00527 } 00528 CASE_D(0xc8) /* ENTER Iw,Ib */ 00529 { 00530 Bitu bytes=Fetchw(); 00531 Bitu level=Fetchb(); 00532 CPU_ENTER(true,bytes,level); 00533 } 00534 break; 00535 CASE_D(0xc9) /* LEAVE */ 00536 { 00537 Bit32u old_esp = reg_esp; 00538 00539 reg_esp &= cpu.stack.notmask; 00540 reg_esp |= reg_ebp&cpu.stack.mask; 00541 try { 00542 reg_ebp = Pop_32(); 00543 } 00544 catch (GuestPageFaultException &pf) { 00545 (void)pf; 00546 reg_esp = old_esp; 00547 throw; 00548 } 00549 } break; 00550 CASE_D(0xca) /* RETF Iw */ 00551 { 00552 Bitu words=Fetchw(); 00553 FillFlags(); 00554 CPU_RET(true,words,GETIP); 00555 continue; 00556 } 00557 CASE_D(0xcb) /* RETF */ 00558 { 00559 FillFlags(); 00560 CPU_RET(true,0,GETIP); 00561 continue; 00562 } 00563 CASE_D(0xcf) /* IRET */ 00564 { 00565 CPU_IRET(true,GETIP); 00566 #if CPU_TRAP_CHECK 00567 if (GETFLAG(TF)) { 00568 cpudecoder=CPU_TRAP_DECODER; 00569 return CBRET_NONE; 00570 } 00571 #endif 00572 #if CPU_PIC_CHECK 00573 if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; 00574 #endif 00575 continue; 00576 } 00577 CASE_D(0xd1) /* GRP2 Ed,1 */ 00578 GRP2D(1);break; 00579 CASE_D(0xd3) /* GRP2 Ed,CL */ 00580 GRP2D(reg_cl);break; 00581 CASE_D(0xe0) /* LOOPNZ */ 00582 if (TEST_PREFIX_ADDR) { 00583 JumpCond32_b(--reg_ecx && !get_ZF()); 00584 } else { 00585 JumpCond32_b(--reg_cx && !get_ZF()); 00586 } 00587 break; 00588 CASE_D(0xe1) /* LOOPZ */ 00589 if (TEST_PREFIX_ADDR) { 00590 JumpCond32_b(--reg_ecx && get_ZF()); 00591 } else { 00592 JumpCond32_b(--reg_cx && get_ZF()); 00593 } 00594 break; 00595 CASE_D(0xe2) /* LOOP */ 00596 if (TEST_PREFIX_ADDR) { 00597 JumpCond32_b(--reg_ecx); 00598 } else { 00599 JumpCond32_b(--reg_cx); 00600 } 00601 break; 00602 CASE_D(0xe3) /* JCXZ */ 00603 JumpCond32_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR])); 00604 break; 00605 CASE_D(0xe5) /* IN EAX,Ib */ 00606 { 00607 Bitu port=Fetchb(); 00608 if (CPU_IO_Exception(port,4)) RUNEXCEPTION(); 00609 reg_eax=IO_ReadD(port); 00610 break; 00611 } 00612 CASE_D(0xe7) /* OUT Ib,EAX */ 00613 { 00614 Bitu port=Fetchb(); 00615 if (CPU_IO_Exception(port,4)) RUNEXCEPTION(); 00616 IO_WriteD(port,reg_eax); 00617 break; 00618 } 00619 CASE_D(0xe8) /* CALL Jd */ 00620 { 00621 /* must not adjust (E)IP until we have completed the instruction. 00622 * if interrupted by a page fault, EIP must be unmodified. */ 00623 Bit32s addip=Fetchds(); 00624 Bit32u here=GETIP; 00625 Push_32(here); 00626 reg_eip=(Bit32u)((Bit32u)addip+here); 00627 continue; 00628 } 00629 CASE_D(0xe9) /* JMP Jd */ 00630 { 00631 Bit32s addip=Fetchds(); 00632 SAVEIP; 00633 reg_eip+=(Bit32u)addip; 00634 continue; 00635 } 00636 CASE_D(0xea) /* JMP Ad */ 00637 { 00638 Bit32u newip=Fetchd(); 00639 Bit16u newcs=Fetchw(); 00640 FillFlags(); 00641 CPU_JMP(true,newcs,newip,GETIP); 00642 #if CPU_TRAP_CHECK 00643 if (GETFLAG(TF)) { 00644 cpudecoder=CPU_TRAP_DECODER; 00645 return CBRET_NONE; 00646 } 00647 #endif 00648 continue; 00649 } 00650 CASE_D(0xeb) /* JMP Jb */ 00651 { 00652 Bit32s addip=Fetchbs(); 00653 SAVEIP; 00654 reg_eip+=(Bit32u)addip; 00655 continue; 00656 } 00657 CASE_D(0xed) /* IN EAX,DX */ 00658 reg_eax=IO_ReadD(reg_dx); 00659 break; 00660 CASE_D(0xef) /* OUT DX,EAX */ 00661 IO_WriteD(reg_dx,reg_eax); 00662 break; 00663 CASE_D(0xf7) /* GRP3 Ed(,Id) */ 00664 { 00665 GetRM;Bitu which=(rm>>3)&7; 00666 switch (which) { 00667 case 0x00: /* TEST Ed,Id */ 00668 case 0x01: /* TEST Ed,Id Undocumented*/ 00669 { 00670 if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);} 00671 else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);} 00672 break; 00673 } 00674 case 0x02: /* NOT Ed */ 00675 { 00676 if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;} 00677 else {GetEAa;SaveMd(eaa,~LoadMd(eaa));} 00678 break; 00679 } 00680 case 0x03: /* NEG Ed */ 00681 { 00682 lflags.type=t_NEGd; 00683 if (rm >= 0xc0 ) { 00684 GetEArd;lf_var1d=*eard;lf_resd=0-lf_var1d; 00685 *eard=lf_resd; 00686 } else { 00687 GetEAa;lf_var1d=LoadMd(eaa);lf_resd=0-lf_var1d; 00688 SaveMd(eaa,lf_resd); 00689 } 00690 break; 00691 } 00692 case 0x04: /* MUL EAX,Ed */ 00693 RMEd(MULD); 00694 break; 00695 case 0x05: /* IMUL EAX,Ed */ 00696 RMEd(IMULD); 00697 break; 00698 case 0x06: /* DIV Ed */ 00699 RMEd(DIVD); 00700 break; 00701 case 0x07: /* IDIV Ed */ 00702 RMEd(IDIVD); 00703 break; 00704 } 00705 break; 00706 } 00707 CASE_D(0xff) /* GRP 5 Ed */ 00708 { 00709 GetRM;Bitu which=(rm>>3)&7; 00710 switch (which) { 00711 case 0x00: /* INC Ed */ 00712 RMEd(INCD); 00713 break; 00714 case 0x01: /* DEC Ed */ 00715 RMEd(DECD); 00716 break; 00717 case 0x02: /* CALL NEAR Ed */ 00718 { /* either EIP is set to the call address or EIP does not change if interrupted by PF */ 00719 Bit32u new_eip; 00720 if (rm >= 0xc0 ) {GetEArd;new_eip=*eard;} 00721 else {GetEAa;new_eip=LoadMd(eaa);} 00722 Push_32(GETIP); /* <- PF can happen here */ 00723 reg_eip = new_eip; 00724 } 00725 continue; 00726 case 0x03: /* CALL FAR Ed */ 00727 { 00728 if (rm >= 0xc0) goto illegal_opcode; 00729 GetEAa; 00730 Bit32u newip=LoadMd(eaa); 00731 Bit16u newcs=LoadMw(eaa+4); 00732 FillFlags(); 00733 CPU_CALL(true,newcs,newip,GETIP); 00734 #if CPU_TRAP_CHECK 00735 if (GETFLAG(TF)) { 00736 cpudecoder=CPU_TRAP_DECODER; 00737 return CBRET_NONE; 00738 } 00739 #endif 00740 continue; 00741 } 00742 case 0x04: /* JMP NEAR Ed */ 00743 if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} 00744 else {GetEAa;reg_eip=LoadMd(eaa);} 00745 continue; 00746 case 0x05: /* JMP FAR Ed */ 00747 { 00748 if (rm >= 0xc0) goto illegal_opcode; 00749 GetEAa; 00750 Bit32u newip=LoadMd(eaa); 00751 Bit16u newcs=LoadMw(eaa+4); 00752 FillFlags(); 00753 CPU_JMP(true,newcs,newip,GETIP); 00754 #if CPU_TRAP_CHECK 00755 if (GETFLAG(TF)) { 00756 cpudecoder=CPU_TRAP_DECODER; 00757 return CBRET_NONE; 00758 } 00759 #endif 00760 continue; 00761 } 00762 break; 00763 case 0x06: /* Push Ed */ 00764 if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);} 00765 else {GetEAa;Push_32(LoadMd(eaa));} 00766 break; 00767 default: 00768 LOG(LOG_CPU,LOG_ERROR)("CPU:66:GRP5:Illegal call %2X",(int)which); 00769 goto illegal_opcode; 00770 } 00771 break; 00772 } 00773 00774