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_B(0x00) /* ADD Eb,Gb */ 00020 RMEbGb(ADDB);break; 00021 CASE_W(0x01) /* ADD Ew,Gw */ 00022 RMEwGw(ADDW);break; 00023 CASE_B(0x02) /* ADD Gb,Eb */ 00024 RMGbEb(ADDB);break; 00025 CASE_W(0x03) /* ADD Gw,Ew */ 00026 RMGwEw(ADDW);break; 00027 CASE_B(0x04) /* ADD AL,Ib */ 00028 ALIb(ADDB);break; 00029 CASE_W(0x05) /* ADD AX,Iw */ 00030 AXIw(ADDW);break; 00031 CASE_W(0x06) /* PUSH ES */ 00032 Push_16(SegValue(es));break; 00033 CASE_W(0x07) /* POP ES */ 00034 if (CPU_PopSeg(es,false)) RUNEXCEPTION(); 00035 break; 00036 CASE_B(0x08) /* OR Eb,Gb */ 00037 RMEbGb(ORB);break; 00038 CASE_W(0x09) /* OR Ew,Gw */ 00039 RMEwGw(ORW);break; 00040 CASE_B(0x0a) /* OR Gb,Eb */ 00041 RMGbEb(ORB);break; 00042 CASE_W(0x0b) /* OR Gw,Ew */ 00043 RMGwEw(ORW);break; 00044 CASE_B(0x0c) /* OR AL,Ib */ 00045 ALIb(ORB);break; 00046 CASE_W(0x0d) /* OR AX,Iw */ 00047 AXIw(ORW);break; 00048 CASE_W(0x0e) /* PUSH CS */ 00049 Push_16(SegValue(cs));break; 00050 CASE_B(0x0f) /* 2 byte opcodes*/ 00051 #if CPU_CORE < CPU_ARCHTYPE_286 00052 if (CPU_ArchitectureType < CPU_ARCHTYPE_286) { 00053 /* 8086 emulation: treat as "POP CS" */ 00054 if (CPU_PopSeg(cs,false)) RUNEXCEPTION(); 00055 break; 00056 } 00057 else 00058 #endif 00059 { 00060 core.opcode_index|=OPCODE_0F; 00061 goto restart_opcode; 00062 } break; 00063 CASE_B(0x10) /* ADC Eb,Gb */ 00064 RMEbGb(ADCB);break; 00065 CASE_W(0x11) /* ADC Ew,Gw */ 00066 RMEwGw(ADCW);break; 00067 CASE_B(0x12) /* ADC Gb,Eb */ 00068 RMGbEb(ADCB);break; 00069 CASE_W(0x13) /* ADC Gw,Ew */ 00070 RMGwEw(ADCW);break; 00071 CASE_B(0x14) /* ADC AL,Ib */ 00072 ALIb(ADCB);break; 00073 CASE_W(0x15) /* ADC AX,Iw */ 00074 AXIw(ADCW);break; 00075 CASE_W(0x16) /* PUSH SS */ 00076 Push_16(SegValue(ss));break; 00077 CASE_W(0x17) /* POP SS */ 00078 if (CPU_PopSeg(ss,false)) RUNEXCEPTION(); 00079 CPU_Cycles++; //Always do another instruction 00080 break; 00081 CASE_B(0x18) /* SBB Eb,Gb */ 00082 RMEbGb(SBBB);break; 00083 CASE_W(0x19) /* SBB Ew,Gw */ 00084 RMEwGw(SBBW);break; 00085 CASE_B(0x1a) /* SBB Gb,Eb */ 00086 RMGbEb(SBBB);break; 00087 CASE_W(0x1b) /* SBB Gw,Ew */ 00088 RMGwEw(SBBW);break; 00089 CASE_B(0x1c) /* SBB AL,Ib */ 00090 ALIb(SBBB);break; 00091 CASE_W(0x1d) /* SBB AX,Iw */ 00092 AXIw(SBBW);break; 00093 CASE_W(0x1e) /* PUSH DS */ 00094 Push_16(SegValue(ds));break; 00095 CASE_W(0x1f) /* POP DS */ 00096 if (CPU_PopSeg(ds,false)) RUNEXCEPTION(); 00097 break; 00098 CASE_B(0x20) /* AND Eb,Gb */ 00099 RMEbGb(ANDB);break; 00100 CASE_W(0x21) /* AND Ew,Gw */ 00101 RMEwGw(ANDW);break; 00102 CASE_B(0x22) /* AND Gb,Eb */ 00103 RMGbEb(ANDB);break; 00104 CASE_W(0x23) /* AND Gw,Ew */ 00105 RMGwEw(ANDW);break; 00106 CASE_B(0x24) /* AND AL,Ib */ 00107 ALIb(ANDB);break; 00108 CASE_W(0x25) /* AND AX,Iw */ 00109 AXIw(ANDW);break; 00110 CASE_B(0x26) /* SEG ES: */ 00111 DO_PREFIX_SEG(es);break; 00112 CASE_B(0x27) /* DAA */ 00113 DAA();break; 00114 CASE_B(0x28) /* SUB Eb,Gb */ 00115 RMEbGb(SUBB);break; 00116 CASE_W(0x29) /* SUB Ew,Gw */ 00117 RMEwGw(SUBW);break; 00118 CASE_B(0x2a) /* SUB Gb,Eb */ 00119 RMGbEb(SUBB);break; 00120 CASE_W(0x2b) /* SUB Gw,Ew */ 00121 RMGwEw(SUBW);break; 00122 CASE_B(0x2c) /* SUB AL,Ib */ 00123 ALIb(SUBB);break; 00124 CASE_W(0x2d) /* SUB AX,Iw */ 00125 AXIw(SUBW);break; 00126 CASE_B(0x2e) /* SEG CS: */ 00127 DO_PREFIX_SEG(cs);break; 00128 CASE_B(0x2f) /* DAS */ 00129 DAS();break; 00130 CASE_B(0x30) /* XOR Eb,Gb */ 00131 RMEbGb(XORB);break; 00132 CASE_W(0x31) /* XOR Ew,Gw */ 00133 RMEwGw(XORW);break; 00134 CASE_B(0x32) /* XOR Gb,Eb */ 00135 RMGbEb(XORB);break; 00136 CASE_W(0x33) /* XOR Gw,Ew */ 00137 RMGwEw(XORW);break; 00138 CASE_B(0x34) /* XOR AL,Ib */ 00139 ALIb(XORB);break; 00140 CASE_W(0x35) /* XOR AX,Iw */ 00141 AXIw(XORW);break; 00142 CASE_B(0x36) /* SEG SS: */ 00143 DO_PREFIX_SEG(ss);break; 00144 CASE_B(0x37) /* AAA */ 00145 AAA();break; 00146 CASE_B(0x38) /* CMP Eb,Gb */ 00147 RMEbGb(CMPB);break; 00148 CASE_W(0x39) /* CMP Ew,Gw */ 00149 RMEwGw(CMPW);break; 00150 CASE_B(0x3a) /* CMP Gb,Eb */ 00151 RMGbEb(CMPB);break; 00152 CASE_W(0x3b) /* CMP Gw,Ew */ 00153 RMGwEw(CMPW);break; 00154 CASE_B(0x3c) /* CMP AL,Ib */ 00155 ALIb(CMPB);break; 00156 CASE_W(0x3d) /* CMP AX,Iw */ 00157 AXIw(CMPW);break; 00158 CASE_B(0x3e) /* SEG DS: */ 00159 DO_PREFIX_SEG(ds);break; 00160 CASE_B(0x3f) /* AAS */ 00161 AAS();break; 00162 CASE_W(0x40) /* INC AX */ 00163 INCW(reg_ax,LoadRw,SaveRw);break; 00164 CASE_W(0x41) /* INC CX */ 00165 INCW(reg_cx,LoadRw,SaveRw);break; 00166 CASE_W(0x42) /* INC DX */ 00167 INCW(reg_dx,LoadRw,SaveRw);break; 00168 CASE_W(0x43) /* INC BX */ 00169 INCW(reg_bx,LoadRw,SaveRw);break; 00170 CASE_W(0x44) /* INC SP */ 00171 INCW(reg_sp,LoadRw,SaveRw);break; 00172 CASE_W(0x45) /* INC BP */ 00173 INCW(reg_bp,LoadRw,SaveRw);break; 00174 CASE_W(0x46) /* INC SI */ 00175 INCW(reg_si,LoadRw,SaveRw);break; 00176 CASE_W(0x47) /* INC DI */ 00177 INCW(reg_di,LoadRw,SaveRw);break; 00178 CASE_W(0x48) /* DEC AX */ 00179 DECW(reg_ax,LoadRw,SaveRw);break; 00180 CASE_W(0x49) /* DEC CX */ 00181 DECW(reg_cx,LoadRw,SaveRw);break; 00182 CASE_W(0x4a) /* DEC DX */ 00183 DECW(reg_dx,LoadRw,SaveRw);break; 00184 CASE_W(0x4b) /* DEC BX */ 00185 DECW(reg_bx,LoadRw,SaveRw);break; 00186 CASE_W(0x4c) /* DEC SP */ 00187 DECW(reg_sp,LoadRw,SaveRw);break; 00188 CASE_W(0x4d) /* DEC BP */ 00189 DECW(reg_bp,LoadRw,SaveRw);break; 00190 CASE_W(0x4e) /* DEC SI */ 00191 DECW(reg_si,LoadRw,SaveRw);break; 00192 CASE_W(0x4f) /* DEC DI */ 00193 DECW(reg_di,LoadRw,SaveRw);break; 00194 CASE_W(0x50) /* PUSH AX */ 00195 Push_16(reg_ax);break; 00196 CASE_W(0x51) /* PUSH CX */ 00197 Push_16(reg_cx);break; 00198 CASE_W(0x52) /* PUSH DX */ 00199 Push_16(reg_dx);break; 00200 CASE_W(0x53) /* PUSH BX */ 00201 Push_16(reg_bx);break; 00202 CASE_W(0x54) /* PUSH SP */ 00203 if (CPU_ArchitectureType >= CPU_ARCHTYPE_286) 00204 Push_16(reg_sp); 00205 else /* 8086 decrements SP then pushes it */ 00206 Push_16(reg_sp-2u); 00207 break; 00208 CASE_W(0x55) /* PUSH BP */ 00209 Push_16(reg_bp);break; 00210 CASE_W(0x56) /* PUSH SI */ 00211 Push_16(reg_si);break; 00212 CASE_W(0x57) /* PUSH DI */ 00213 Push_16(reg_di);break; 00214 CASE_W(0x58) /* POP AX */ 00215 reg_ax=Pop_16();break; 00216 CASE_W(0x59) /* POP CX */ 00217 reg_cx=Pop_16();break; 00218 CASE_W(0x5a) /* POP DX */ 00219 reg_dx=Pop_16();break; 00220 CASE_W(0x5b) /* POP BX */ 00221 reg_bx=Pop_16();break; 00222 CASE_W(0x5c) /* POP SP */ 00223 reg_sp=Pop_16();break; 00224 CASE_W(0x5d) /* POP BP */ 00225 reg_bp=Pop_16();break; 00226 CASE_W(0x5e) /* POP SI */ 00227 reg_si=Pop_16();break; 00228 CASE_W(0x5f) /* POP DI */ 00229 reg_di=Pop_16();break; 00230 CASE_W(0x60) /* PUSHA */ 00231 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00232 { 00233 Bit32u old_esp = reg_esp; 00234 try { 00235 Bit16u old_sp = (CPU_ArchitectureType >= CPU_ARCHTYPE_286 ? reg_sp : (reg_sp-10)); 00236 Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx); 00237 Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di); 00238 } 00239 catch (GuestPageFaultException &pf) { 00240 (void)pf; 00241 LOG_MSG("PUSHA interrupted by page fault"); 00242 reg_esp = old_esp; 00243 throw; 00244 } 00245 } break; 00246 CASE_W(0x61) /* POPA */ 00247 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00248 { 00249 Bit32u old_esp = reg_esp; 00250 try { 00251 reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP 00252 reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16(); 00253 } 00254 catch (GuestPageFaultException &pf) { 00255 (void)pf; 00256 LOG_MSG("POPA interrupted by page fault"); 00257 reg_esp = old_esp; 00258 throw; 00259 } 00260 } break; 00261 CASE_W(0x62) /* BOUND */ 00262 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00263 { 00264 Bit16s bound_min, bound_max; 00265 GetRMrw;GetEAa; 00266 bound_min=(Bit16s)LoadMw(eaa); 00267 bound_max=(Bit16s)LoadMw(eaa+2u); 00268 if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) { 00269 EXCEPTION(5); 00270 } 00271 } 00272 break; 00273 CASE_W(0x63) /* ARPL Ew,Rw */ 00274 if (CPU_ArchitectureType<CPU_ARCHTYPE_286) goto illegal_opcode; 00275 { 00276 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 00277 GetRMrw; 00278 if (rm >= 0xc0 ) { 00279 GetEArw;Bitu new_sel=*earw; 00280 CPU_ARPL(new_sel,*rmrw); 00281 *earw=(Bit16u)new_sel; 00282 } else { 00283 GetEAa;Bitu new_sel=LoadMw(eaa); 00284 CPU_ARPL(new_sel,*rmrw); 00285 SaveMw(eaa,(Bit16u)new_sel); 00286 } 00287 } 00288 break; 00289 CASE_B(0x64) /* SEG FS: */ 00290 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00291 DO_PREFIX_SEG(fs);break; 00292 CASE_B(0x65) /* SEG GS: */ 00293 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00294 DO_PREFIX_SEG(gs);break; 00295 #if CPU_CORE >= CPU_ARCHTYPE_386 00296 CASE_B(0x66) /* Operand Size Prefix (386+) */ 00297 core.opcode_index=(cpu.code.big^0x1u)*0x200u; 00298 goto restart_opcode; 00299 #endif 00300 #if CPU_CORE >= CPU_ARCHTYPE_386 00301 CASE_B(0x67) /* Address Size Prefix (386+) */ 00302 DO_PREFIX_ADDR(); 00303 #endif 00304 CASE_W(0x68) /* PUSH Iw */ 00305 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00306 Push_16(Fetchw());break; 00307 CASE_W(0x69) /* IMUL Gw,Ew,Iw */ 00308 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00309 RMGwEwOp3(DIMULW,Fetchws()); 00310 break; 00311 CASE_W(0x6a) /* PUSH Ib */ 00312 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00313 Push_16((Bit16u)Fetchbs()); 00314 break; 00315 CASE_W(0x6b) /* IMUL Gw,Ew,Ib */ 00316 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00317 RMGwEwOp3(DIMULW,Fetchbs()); 00318 break; 00319 CASE_B(0x6c) /* INSB */ 00320 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00321 if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); 00322 DoString(R_INSB);break; 00323 CASE_W(0x6d) /* INSW */ 00324 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00325 if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); 00326 DoString(R_INSW);break; 00327 CASE_B(0x6e) /* OUTSB */ 00328 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00329 if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); 00330 DoString(R_OUTSB);break; 00331 CASE_W(0x6f) /* OUTSW */ 00332 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00333 if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); 00334 DoString(R_OUTSW);break; 00335 CASE_W(0x70) /* JO */ 00336 JumpCond16_b(TFLG_O);break; 00337 CASE_W(0x71) /* JNO */ 00338 JumpCond16_b(TFLG_NO);break; 00339 CASE_W(0x72) /* JB */ 00340 JumpCond16_b(TFLG_B);break; 00341 CASE_W(0x73) /* JNB */ 00342 JumpCond16_b(TFLG_NB);break; 00343 CASE_W(0x74) /* JZ */ 00344 JumpCond16_b(TFLG_Z);break; 00345 CASE_W(0x75) /* JNZ */ 00346 JumpCond16_b(TFLG_NZ);break; 00347 CASE_W(0x76) /* JBE */ 00348 JumpCond16_b(TFLG_BE);break; 00349 CASE_W(0x77) /* JNBE */ 00350 JumpCond16_b(TFLG_NBE);break; 00351 CASE_W(0x78) /* JS */ 00352 JumpCond16_b(TFLG_S);break; 00353 CASE_W(0x79) /* JNS */ 00354 JumpCond16_b(TFLG_NS);break; 00355 CASE_W(0x7a) /* JP */ 00356 JumpCond16_b(TFLG_P);break; 00357 CASE_W(0x7b) /* JNP */ 00358 JumpCond16_b(TFLG_NP);break; 00359 CASE_W(0x7c) /* JL */ 00360 JumpCond16_b(TFLG_L);break; 00361 CASE_W(0x7d) /* JNL */ 00362 JumpCond16_b(TFLG_NL);break; 00363 CASE_W(0x7e) /* JLE */ 00364 JumpCond16_b(TFLG_LE);break; 00365 CASE_W(0x7f) /* JNLE */ 00366 JumpCond16_b(TFLG_NLE);break; 00367 CASE_B(0x80) /* Grpl Eb,Ib */ 00368 CASE_B(0x82) /* Grpl Eb,Ib Mirror instruction*/ 00369 { 00370 GetRM;Bitu which=(rm>>3)&7; 00371 if (rm>= 0xc0) { 00372 GetEArb;Bit8u ib=Fetchb(); 00373 switch (which) { 00374 case 0x00:ADDB(*earb,ib,LoadRb,SaveRb);break; 00375 case 0x01: ORB(*earb,ib,LoadRb,SaveRb);break; 00376 case 0x02:ADCB(*earb,ib,LoadRb,SaveRb);break; 00377 case 0x03:SBBB(*earb,ib,LoadRb,SaveRb);break; 00378 case 0x04:ANDB(*earb,ib,LoadRb,SaveRb);break; 00379 case 0x05:SUBB(*earb,ib,LoadRb,SaveRb);break; 00380 case 0x06:XORB(*earb,ib,LoadRb,SaveRb);break; 00381 case 0x07:CMPB(*earb,ib,LoadRb,SaveRb);break; 00382 } 00383 } else { 00384 GetEAa;Bit8u ib=Fetchb(); 00385 switch (which) { 00386 case 0x00:ADDB(eaa,ib,LoadMb,SaveMb);break; 00387 case 0x01: ORB(eaa,ib,LoadMb,SaveMb);break; 00388 case 0x02:ADCB(eaa,ib,LoadMb,SaveMb);break; 00389 case 0x03:SBBB(eaa,ib,LoadMb,SaveMb);break; 00390 case 0x04:ANDB(eaa,ib,LoadMb,SaveMb);break; 00391 case 0x05:SUBB(eaa,ib,LoadMb,SaveMb);break; 00392 case 0x06:XORB(eaa,ib,LoadMb,SaveMb);break; 00393 case 0x07:CMPB(eaa,ib,LoadMb,SaveMb);break; 00394 } 00395 } 00396 break; 00397 } 00398 CASE_W(0x81) /* Grpl Ew,Iw */ 00399 { 00400 GetRM;Bitu which=(rm>>3)&7; 00401 if (rm>= 0xc0) { 00402 GetEArw;Bit16u iw=Fetchw(); 00403 switch (which) { 00404 case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; 00405 case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break; 00406 case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break; 00407 case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break; 00408 case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break; 00409 case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break; 00410 case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break; 00411 case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break; 00412 } 00413 } else { 00414 GetEAa;Bit16u iw=Fetchw(); 00415 switch (which) { 00416 case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; 00417 case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break; 00418 case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break; 00419 case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break; 00420 case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break; 00421 case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break; 00422 case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break; 00423 case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break; 00424 } 00425 } 00426 break; 00427 } 00428 CASE_W(0x83) /* Grpl Ew,Ix */ 00429 { 00430 GetRM;Bitu which=(rm>>3)&7; 00431 if (rm>= 0xc0) { 00432 GetEArw;Bit16u iw=(Bit16u)Fetchbs(); 00433 switch (which) { 00434 case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; 00435 case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break; 00436 case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break; 00437 case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break; 00438 case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break; 00439 case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break; 00440 case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break; 00441 case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break; 00442 } 00443 } else { 00444 GetEAa;Bit16u iw=(Bit16u)Fetchbs(); 00445 switch (which) { 00446 case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; 00447 case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break; 00448 case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break; 00449 case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break; 00450 case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break; 00451 case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break; 00452 case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break; 00453 case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break; 00454 } 00455 } 00456 break; 00457 } 00458 CASE_B(0x84) /* TEST Eb,Gb */ 00459 RMEbGb(TESTB); 00460 break; 00461 CASE_W(0x85) /* TEST Ew,Gw */ 00462 RMEwGw(TESTW); 00463 break; 00464 CASE_B(0x86) /* XCHG Eb,Gb */ 00465 { 00466 GetRMrb;Bit8u oldrmrb=*rmrb; 00467 if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb=oldrmrb;} 00468 else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,oldrmrb);} 00469 break; 00470 } 00471 CASE_W(0x87) /* XCHG Ew,Gw */ 00472 { 00473 GetRMrw;Bit16u oldrmrw=*rmrw; 00474 if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw=oldrmrw;} 00475 else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,oldrmrw);} 00476 break; 00477 } 00478 CASE_B(0x88) /* MOV Eb,Gb */ 00479 { 00480 GetRMrb; 00481 if (rm >= 0xc0 ) {GetEArb;*earb=*rmrb;} 00482 else { 00483 if (cpu.pmode) { 00484 if (GCC_UNLIKELY((rm==0x05) && (!cpu.code.big))) { 00485 Descriptor desc; 00486 cpu.gdt.GetDescriptor(SegValue(core.base_val_ds),desc); 00487 if ((desc.Type()==DESC_CODE_R_NC_A) || (desc.Type()==DESC_CODE_R_NC_NA)) { 00488 CPU_Exception(EXCEPTION_GP,SegValue(core.base_val_ds) & 0xfffc); 00489 continue; 00490 } 00491 } 00492 } 00493 GetEAa;SaveMb(eaa,*rmrb); 00494 } 00495 break; 00496 } 00497 CASE_W(0x89) /* MOV Ew,Gw */ 00498 { 00499 GetRMrw; 00500 if (rm >= 0xc0 ) {GetEArw;*earw=*rmrw;} 00501 else {GetEAa;SaveMw(eaa,*rmrw);} 00502 break; 00503 } 00504 CASE_B(0x8a) /* MOV Gb,Eb */ 00505 { 00506 GetRMrb; 00507 if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;} 00508 else {GetEAa;*rmrb=LoadMb(eaa);} 00509 break; 00510 } 00511 CASE_W(0x8b) /* MOV Gw,Ew */ 00512 { 00513 GetRMrw; 00514 if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} 00515 else {GetEAa;*rmrw=LoadMw(eaa);} 00516 break; 00517 } 00518 CASE_W(0x8c) /* Mov Ew,Sw */ 00519 { 00520 GetRM;Bit16u val;Bitu which=(rm>>3)&7; 00521 switch (which) { 00522 case 0x00: /* MOV Ew,ES */ 00523 val=SegValue(es);break; 00524 case 0x01: /* MOV Ew,CS */ 00525 val=SegValue(cs);break; 00526 case 0x02: /* MOV Ew,SS */ 00527 val=SegValue(ss);break; 00528 case 0x03: /* MOV Ew,DS */ 00529 val=SegValue(ds);break; 00530 case 0x04: /* MOV Ew,FS */ 00531 val=SegValue(fs);break; 00532 case 0x05: /* MOV Ew,GS */ 00533 val=SegValue(gs);break; 00534 default: 00535 LOG(LOG_CPU,LOG_ERROR)("CPU:8c:Illegal RM Byte"); 00536 goto illegal_opcode; 00537 } 00538 if (rm >= 0xc0 ) {GetEArw;*earw=val;} 00539 else {GetEAa;SaveMw(eaa,val);} 00540 break; 00541 } 00542 CASE_W(0x8d) /* LEA Gw */ 00543 { 00544 //Little hack to always use segprefixed version 00545 BaseDS=BaseSS=0; 00546 GetRMrw; 00547 if (TEST_PREFIX_ADDR) { 00548 *rmrw=(Bit16u)(*EATable[256+rm])(); 00549 } else { 00550 *rmrw=(Bit16u)(*EATable[rm])(); 00551 } 00552 break; 00553 } 00554 CASE_B(0x8e) /* MOV Sw,Ew */ 00555 { 00556 GetRM;Bit16u val;Bitu which=(rm>>3)&7; 00557 if (rm >= 0xc0 ) {GetEArw;val=*earw;} 00558 else {GetEAa;val=LoadMw(eaa);} 00559 switch (which) { 00560 #if CPU_CORE <= CPU_ARCHTYPE_8086 00561 case 0x01: /* MOV CS,Ew (8086 only) */ 00562 #endif 00563 case 0x02: /* MOV SS,Ew */ 00564 CPU_Cycles++; //Always do another instruction 00565 case 0x00: /* MOV ES,Ew */ 00566 case 0x03: /* MOV DS,Ew */ 00567 case 0x05: /* MOV GS,Ew */ 00568 case 0x04: /* MOV FS,Ew */ 00569 if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION(); 00570 break; 00571 default: 00572 goto illegal_opcode; 00573 } 00574 break; 00575 } 00576 CASE_W(0x8f) /* POP Ew */ 00577 { 00578 Bit32u old_esp = reg_esp; 00579 00580 try { 00581 Bit16u val=Pop_16(); 00582 GetRM; 00583 if (rm >= 0xc0 ) {GetEArw;*earw=val;} 00584 else {GetEAa;SaveMw(eaa,val);} 00585 } 00586 catch (GuestPageFaultException &pf) { 00587 (void)pf; 00588 reg_esp = old_esp; 00589 throw; 00590 } 00591 } break; 00592 CASE_B(0x90) /* NOP */ 00593 break; 00594 CASE_W(0x91) /* XCHG CX,AX */ 00595 { Bit16u temp=reg_ax;reg_ax=reg_cx;reg_cx=temp; } 00596 break; 00597 CASE_W(0x92) /* XCHG DX,AX */ 00598 { Bit16u temp=reg_ax;reg_ax=reg_dx;reg_dx=temp; } 00599 break; 00600 CASE_W(0x93) /* XCHG BX,AX */ 00601 { Bit16u temp=reg_ax;reg_ax=reg_bx;reg_bx=temp; } 00602 break; 00603 CASE_W(0x94) /* XCHG SP,AX */ 00604 { Bit16u temp=reg_ax;reg_ax=reg_sp;reg_sp=temp; } 00605 break; 00606 CASE_W(0x95) /* XCHG BP,AX */ 00607 { Bit16u temp=reg_ax;reg_ax=reg_bp;reg_bp=temp; } 00608 break; 00609 CASE_W(0x96) /* XCHG SI,AX */ 00610 { Bit16u temp=reg_ax;reg_ax=reg_si;reg_si=temp; } 00611 break; 00612 CASE_W(0x97) /* XCHG DI,AX */ 00613 { Bit16u temp=reg_ax;reg_ax=reg_di;reg_di=temp; } 00614 break; 00615 CASE_W(0x98) /* CBW */ 00616 reg_ax=(Bit16u)((Bit8s)reg_al);break; 00617 CASE_W(0x99) /* CWD */ 00618 if (reg_ax & 0x8000) reg_dx=0xffff;else reg_dx=0; 00619 break; 00620 CASE_W(0x9a) /* CALL Ap */ 00621 { 00622 FillFlags(); 00623 Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); 00624 CPU_CALL(false,newcs,newip,GETIP); 00625 #if CPU_TRAP_CHECK 00626 if (GETFLAG(TF)) { 00627 cpudecoder=CPU_Core_Normal_Trap_Run; 00628 return CBRET_NONE; 00629 } 00630 #endif 00631 continue; 00632 } 00633 CASE_B(0x9b) /* WAIT */ 00634 break; /* No waiting here */ 00635 CASE_W(0x9c) /* PUSHF */ 00636 if (CPU_PUSHF(false)) RUNEXCEPTION(); 00637 break; 00638 CASE_W(0x9d) /* POPF */ 00639 if (CPU_POPF(false)) RUNEXCEPTION(); 00640 #if CPU_TRAP_CHECK 00641 if (GETFLAG(TF)) { 00642 cpudecoder=CPU_Core_Normal_Trap_Run; 00643 goto decode_end; 00644 } 00645 #endif 00646 #if CPU_PIC_CHECK 00647 if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; 00648 #endif 00649 break; 00650 CASE_B(0x9e) /* SAHF */ 00651 SETFLAGSb(reg_ah); 00652 break; 00653 CASE_B(0x9f) /* LAHF */ 00654 FillFlags(); 00655 reg_ah=reg_flags&0xff; 00656 break; 00657 CASE_B(0xa0) /* MOV AL,Ob */ 00658 { /* NTS: GetEADirect may jump instead to the GP# trigger code if the offset exceeds the segment limit. 00659 For whatever reason, NOT signalling GP# in that condition prevents Windows 95 OSR2 from starting a DOS VM. Weird. */ 00660 GetEADirect(1); 00661 reg_al=LoadMb(eaa); 00662 } 00663 break; 00664 CASE_W(0xa1) /* MOV AX,Ow */ 00665 { /* NTS: GetEADirect may jump instead to the GP# trigger code if the offset exceeds the segment limit. 00666 For whatever reason, NOT signalling GP# in that condition prevents Windows 95 OSR2 from starting a DOS VM. Weird. */ 00667 GetEADirect(2); 00668 reg_ax=LoadMw(eaa); 00669 } 00670 break; 00671 CASE_B(0xa2) /* MOV Ob,AL */ 00672 { /* NTS: GetEADirect may jump instead to the GP# trigger code if the offset exceeds the segment limit. 00673 For whatever reason, NOT signalling GP# in that condition prevents Windows 95 OSR2 from starting a DOS VM. Weird. */ 00674 GetEADirect(1); 00675 SaveMb(eaa,reg_al); 00676 } 00677 break; 00678 CASE_W(0xa3) /* MOV Ow,AX */ 00679 { /* NTS: GetEADirect may jump instead to the GP# trigger code if the offset exceeds the segment limit. 00680 For whatever reason, NOT signalling GP# in that condition prevents Windows 95 OSR2 from starting a DOS VM. Weird. */ 00681 GetEADirect(2); 00682 SaveMw(eaa,reg_ax); 00683 } 00684 break; 00685 CASE_B(0xa4) /* MOVSB */ 00686 DoString(R_MOVSB);break; 00687 CASE_W(0xa5) /* MOVSW */ 00688 DoString(R_MOVSW);break; 00689 CASE_B(0xa6) /* CMPSB */ 00690 DoString(R_CMPSB);break; 00691 CASE_W(0xa7) /* CMPSW */ 00692 DoString(R_CMPSW);break; 00693 CASE_B(0xa8) /* TEST AL,Ib */ 00694 ALIb(TESTB);break; 00695 CASE_W(0xa9) /* TEST AX,Iw */ 00696 AXIw(TESTW);break; 00697 CASE_B(0xaa) /* STOSB */ 00698 DoString(R_STOSB);break; 00699 CASE_W(0xab) /* STOSW */ 00700 DoString(R_STOSW);break; 00701 CASE_B(0xac) /* LODSB */ 00702 DoString(R_LODSB);break; 00703 CASE_W(0xad) /* LODSW */ 00704 DoString(R_LODSW);break; 00705 CASE_B(0xae) /* SCASB */ 00706 DoString(R_SCASB);break; 00707 CASE_W(0xaf) /* SCASW */ 00708 DoString(R_SCASW);break; 00709 CASE_B(0xb0) /* MOV AL,Ib */ 00710 reg_al=Fetchb();break; 00711 CASE_B(0xb1) /* MOV CL,Ib */ 00712 reg_cl=Fetchb();break; 00713 CASE_B(0xb2) /* MOV DL,Ib */ 00714 reg_dl=Fetchb();break; 00715 CASE_B(0xb3) /* MOV BL,Ib */ 00716 reg_bl=Fetchb();break; 00717 CASE_B(0xb4) /* MOV AH,Ib */ 00718 reg_ah=Fetchb();break; 00719 CASE_B(0xb5) /* MOV CH,Ib */ 00720 reg_ch=Fetchb();break; 00721 CASE_B(0xb6) /* MOV DH,Ib */ 00722 reg_dh=Fetchb();break; 00723 CASE_B(0xb7) /* MOV BH,Ib */ 00724 reg_bh=Fetchb();break; 00725 CASE_W(0xb8) /* MOV AX,Iw */ 00726 reg_ax=Fetchw();break; 00727 CASE_W(0xb9) /* MOV CX,Iw */ 00728 reg_cx=Fetchw();break; 00729 CASE_W(0xba) /* MOV DX,Iw */ 00730 reg_dx=Fetchw();break; 00731 CASE_W(0xbb) /* MOV BX,Iw */ 00732 reg_bx=Fetchw();break; 00733 CASE_W(0xbc) /* MOV SP,Iw */ 00734 reg_sp=Fetchw();break; 00735 CASE_W(0xbd) /* MOV BP.Iw */ 00736 reg_bp=Fetchw();break; 00737 CASE_W(0xbe) /* MOV SI,Iw */ 00738 reg_si=Fetchw();break; 00739 CASE_W(0xbf) /* MOV DI,Iw */ 00740 reg_di=Fetchw();break; 00741 #if CPU_CORE >= CPU_ARCHTYPE_80186 00742 CASE_B(0xc0) /* GRP2 Eb,Ib */ 00743 if (CPU_ArchitectureType < CPU_ARCHTYPE_80186) abort(); 00744 GRP2B(Fetchb());break; 00745 CASE_W(0xc1) /* GRP2 Ew,Ib */ 00746 if (CPU_ArchitectureType < CPU_ARCHTYPE_80186) abort(); 00747 GRP2W(Fetchb());break; 00748 #endif 00749 CASE_W(0xc2) /* RETN Iw */ 00750 { 00751 Bit32u old_esp = reg_esp; 00752 00753 try { 00754 /* this is structured either to complete RET or leave registers unmodified if interrupted by page fault */ 00755 Bit32u new_eip = Pop_16(); 00756 reg_esp += Fetchw(); 00757 reg_eip = new_eip; 00758 } 00759 catch (GuestPageFaultException &pf) { 00760 (void)pf; 00761 reg_esp = old_esp; /* restore stack pointer */ 00762 throw; 00763 } 00764 } continue; 00765 CASE_W(0xc3) /* RETN */ 00766 reg_eip=Pop_16(); 00767 continue; 00768 CASE_W(0xc4) /* LES */ 00769 { 00770 GetRMrw; 00771 if (rm >= 0xc0) goto illegal_opcode; 00772 GetEAa; 00773 if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION(); 00774 *rmrw=LoadMw(eaa); 00775 break; 00776 } 00777 CASE_W(0xc5) /* LDS */ 00778 { 00779 GetRMrw; 00780 if (rm >= 0xc0) goto illegal_opcode; 00781 GetEAa; 00782 if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION(); 00783 *rmrw=LoadMw(eaa); 00784 break; 00785 } 00786 CASE_B(0xc6) /* MOV Eb,Ib */ 00787 { 00788 GetRM; 00789 if (rm >= 0xc0) {GetEArb;*earb=Fetchb();} 00790 else {GetEAa;SaveMb(eaa,Fetchb());} 00791 break; 00792 } 00793 CASE_W(0xc7) /* MOV EW,Iw */ 00794 { 00795 GetRM; 00796 if (rm >= 0xc0) {GetEArw;*earw=Fetchw();} 00797 else {GetEAa;SaveMw(eaa,Fetchw());} 00798 break; 00799 } 00800 CASE_W(0xc8) /* ENTER Iw,Ib */ 00801 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00802 { 00803 Bitu bytes=Fetchw(); 00804 Bitu level=Fetchb(); 00805 CPU_ENTER(false,bytes,level); 00806 } 00807 break; 00808 CASE_W(0xc9) /* LEAVE */ 00809 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegal_opcode; 00810 { 00811 Bit32u old_esp = reg_esp; 00812 00813 reg_esp &= cpu.stack.notmask; 00814 reg_esp |= reg_ebp&cpu.stack.mask; 00815 try { 00816 reg_bp = Pop_16(); 00817 } 00818 catch (GuestPageFaultException &pf) { 00819 (void)pf; 00820 reg_esp = old_esp; 00821 throw; 00822 } 00823 } break; 00824 CASE_W(0xca) /* RETF Iw */ 00825 { 00826 Bitu words=Fetchw(); 00827 FillFlags(); 00828 CPU_RET(false,words,GETIP); 00829 continue; 00830 } 00831 CASE_W(0xcb) /* RETF */ 00832 FillFlags(); 00833 CPU_RET(false,0,GETIP); 00834 continue; 00835 CASE_B(0xcc) /* INT3 */ 00836 #if C_DEBUG 00837 FillFlags(); 00838 if (DEBUG_Breakpoint()) 00839 return (Bits)debugCallback; 00840 if (DEBUG_IntBreakpoint(3)) 00841 return (Bits)debugCallback; 00842 #endif 00843 CPU_SW_Interrupt_NoIOPLCheck(3,GETIP); 00844 #if CPU_TRAP_CHECK 00845 cpu.trap_skip=true; 00846 #endif 00847 continue; 00848 CASE_B(0xcd) /* INT Ib */ 00849 { 00850 Bit8u num=Fetchb(); 00851 #if C_DEBUG 00852 FillFlags(); 00853 if (DEBUG_IntBreakpoint(num)) { 00854 return (Bits)debugCallback; 00855 } 00856 #endif 00857 CPU_SW_Interrupt(num,GETIP); 00858 #if CPU_TRAP_CHECK 00859 cpu.trap_skip=true; 00860 #endif 00861 continue; 00862 } 00863 CASE_B(0xce) /* INTO */ 00864 if (get_OF()) { 00865 CPU_SW_Interrupt(4,GETIP); 00866 #if CPU_TRAP_CHECK 00867 cpu.trap_skip=true; 00868 #endif 00869 continue; 00870 } 00871 break; 00872 CASE_W(0xcf) /* IRET */ 00873 { 00874 CPU_IRET(false,GETIP); 00875 #if CPU_TRAP_CHECK 00876 if (GETFLAG(TF)) { 00877 cpudecoder=CPU_Core_Normal_Trap_Run; 00878 return CBRET_NONE; 00879 } 00880 #endif 00881 #if CPU_PIC_CHECK 00882 if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; 00883 #endif 00884 continue; 00885 } 00886 CASE_B(0xd0) /* GRP2 Eb,1 */ 00887 GRP2B(1);break; 00888 CASE_W(0xd1) /* GRP2 Ew,1 */ 00889 GRP2W(1);break; 00890 CASE_B(0xd2) /* GRP2 Eb,CL */ 00891 GRP2B(reg_cl);break; 00892 CASE_W(0xd3) /* GRP2 Ew,CL */ 00893 GRP2W(reg_cl);break; 00894 CASE_B(0xd4) /* AAM Ib */ 00895 AAM(Fetchb());break; 00896 CASE_B(0xd5) /* AAD Ib */ 00897 AAD(Fetchb());break; 00898 CASE_B(0xd6) /* SALC */ 00899 reg_al = get_CF() ? 0xFF : 0; 00900 break; 00901 CASE_B(0xd7) /* XLAT */ 00902 if (TEST_PREFIX_ADDR) { 00903 reg_al=LoadMb(BaseDS+(Bit32u)(reg_ebx+reg_al)); 00904 } else { 00905 reg_al=LoadMb(BaseDS+(Bit16u)(reg_bx+reg_al)); 00906 } 00907 break; 00908 #ifdef CPU_FPU 00909 CASE_B(0xd8) /* FPU ESC 0 */ 00910 if (enable_fpu) { 00911 FPU_ESC(0); 00912 } 00913 else { 00914 Bit8u rm=Fetchb(); 00915 if (rm<0xc0) { GetEAa; (void)eaa; } 00916 } 00917 break; 00918 CASE_B(0xd9) /* FPU ESC 1 */ 00919 if (enable_fpu) { 00920 FPU_ESC(1); 00921 } 00922 else { 00923 Bit8u rm=Fetchb(); 00924 if (rm<0xc0) { GetEAa; (void)eaa; } 00925 } 00926 break; 00927 CASE_B(0xda) /* FPU ESC 2 */ 00928 if (enable_fpu) { 00929 FPU_ESC(2); 00930 } 00931 else { 00932 Bit8u rm=Fetchb(); 00933 if (rm<0xc0) { GetEAa; (void)eaa; } 00934 } 00935 break; 00936 CASE_B(0xdb) /* FPU ESC 3 */ 00937 if (enable_fpu) { 00938 FPU_ESC(3); 00939 } 00940 else { 00941 Bit8u rm=Fetchb(); 00942 if (rm<0xc0) { GetEAa; (void)eaa; } 00943 } 00944 break; 00945 CASE_B(0xdc) /* FPU ESC 4 */ 00946 if (enable_fpu) { 00947 FPU_ESC(4); 00948 } 00949 else { 00950 Bit8u rm=Fetchb(); 00951 if (rm<0xc0) { GetEAa; (void)eaa; } 00952 } 00953 break; 00954 CASE_B(0xdd) /* FPU ESC 5 */ 00955 if (enable_fpu) { 00956 FPU_ESC(5); 00957 } 00958 else { 00959 Bit8u rm=Fetchb(); 00960 if (rm<0xc0) { GetEAa; (void)eaa; } 00961 } 00962 break; 00963 CASE_B(0xde) /* FPU ESC 6 */ 00964 if (enable_fpu) { 00965 FPU_ESC(6); 00966 } 00967 else { 00968 Bit8u rm=Fetchb(); 00969 if (rm<0xc0) { GetEAa; (void)eaa; } 00970 } 00971 break; 00972 CASE_B(0xdf) /* FPU ESC 7 */ 00973 if (enable_fpu) { 00974 FPU_ESC(7); 00975 } 00976 else { 00977 Bit8u rm=Fetchb(); 00978 if (rm<0xc0) { GetEAa; (void)eaa; } 00979 } 00980 break; 00981 #else 00982 CASE_B(0xd8) /* FPU ESC 0 */ 00983 CASE_B(0xd9) /* FPU ESC 1 */ 00984 CASE_B(0xda) /* FPU ESC 2 */ 00985 CASE_B(0xdb) /* FPU ESC 3 */ 00986 CASE_B(0xdc) /* FPU ESC 4 */ 00987 CASE_B(0xdd) /* FPU ESC 5 */ 00988 CASE_B(0xde) /* FPU ESC 6 */ 00989 CASE_B(0xdf) /* FPU ESC 7 */ 00990 { 00991 LOG(LOG_CPU,LOG_NORMAL)("FPU used"); 00992 Bit8u rm=Fetchb(); 00993 if (rm<0xc0) GetEAa; 00994 } 00995 break; 00996 #endif 00997 CASE_W(0xe0) /* LOOPNZ */ 00998 if (TEST_PREFIX_ADDR) { 00999 JumpCond16_b(--reg_ecx && !get_ZF()); 01000 } else { 01001 JumpCond16_b(--reg_cx && !get_ZF()); 01002 } 01003 break; 01004 CASE_W(0xe1) /* LOOPZ */ 01005 if (TEST_PREFIX_ADDR) { 01006 JumpCond16_b(--reg_ecx && get_ZF()); 01007 } else { 01008 JumpCond16_b(--reg_cx && get_ZF()); 01009 } 01010 break; 01011 CASE_W(0xe2) /* LOOP */ 01012 if (TEST_PREFIX_ADDR) { 01013 JumpCond16_b(--reg_ecx); 01014 } else { 01015 JumpCond16_b(--reg_cx); 01016 } 01017 break; 01018 CASE_W(0xe3) /* JCXZ */ 01019 JumpCond16_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR])); 01020 break; 01021 CASE_B(0xe4) /* IN AL,Ib */ 01022 { 01023 Bitu port=Fetchb(); 01024 if (CPU_IO_Exception(port,1)) RUNEXCEPTION(); 01025 reg_al=IO_ReadB(port); 01026 break; 01027 } 01028 CASE_W(0xe5) /* IN AX,Ib */ 01029 { 01030 Bitu port=Fetchb(); 01031 if (CPU_IO_Exception(port,2)) RUNEXCEPTION(); 01032 reg_ax=IO_ReadW(port); 01033 break; 01034 } 01035 CASE_B(0xe6) /* OUT Ib,AL */ 01036 { 01037 Bitu port=Fetchb(); 01038 if (CPU_IO_Exception(port,1)) RUNEXCEPTION(); 01039 IO_WriteB(port,reg_al); 01040 break; 01041 } 01042 CASE_W(0xe7) /* OUT Ib,AX */ 01043 { 01044 Bitu port=Fetchb(); 01045 if (CPU_IO_Exception(port,2)) RUNEXCEPTION(); 01046 IO_WriteW(port,reg_ax); 01047 break; 01048 } 01049 CASE_W(0xe8) /* CALL Jw */ 01050 { 01051 /* must not adjust (E)IP until we have completed the instruction. 01052 * if interrupted by a page fault, EIP must be unmodified. */ 01053 Bit16u addip=(Bit16u)Fetchws(); 01054 Bit16u here=GETIP; 01055 Push_16(here); 01056 reg_eip=(Bit16u)(addip+here); 01057 continue; 01058 } 01059 CASE_W(0xe9) /* JMP Jw */ 01060 { 01061 Bit16u addip=(Bit16u)Fetchws(); 01062 SAVEIP; 01063 reg_eip=(Bit16u)(reg_eip+addip); 01064 continue; 01065 } 01066 CASE_W(0xea) /* JMP Ap */ 01067 { 01068 Bit16u newip=Fetchw(); 01069 Bit16u newcs=Fetchw(); 01070 FillFlags(); 01071 CPU_JMP(false,newcs,newip,GETIP); 01072 #if CPU_TRAP_CHECK 01073 if (GETFLAG(TF)) { 01074 cpudecoder=CPU_Core_Normal_Trap_Run; 01075 return CBRET_NONE; 01076 } 01077 #endif 01078 continue; 01079 } 01080 CASE_W(0xeb) /* JMP Jb */ 01081 { 01082 Bit16s addip=Fetchbs(); 01083 SAVEIP; 01084 reg_eip=(Bit16u)(reg_eip+(Bit32u)addip); 01085 continue; 01086 } 01087 CASE_B(0xec) /* IN AL,DX */ 01088 if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); 01089 reg_al=IO_ReadB(reg_dx); 01090 break; 01091 CASE_W(0xed) /* IN AX,DX */ 01092 if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); 01093 reg_ax=IO_ReadW(reg_dx); 01094 break; 01095 CASE_B(0xee) /* OUT DX,AL */ 01096 if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); 01097 IO_WriteB(reg_dx,reg_al); 01098 break; 01099 CASE_W(0xef) /* OUT DX,AX */ 01100 if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); 01101 IO_WriteW(reg_dx,reg_ax); 01102 break; 01103 CASE_B(0xf0) /* LOCK */ 01104 // todo: make an option to show this 01105 // LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); /* FIXME: see case D_LOCK in core_full/load.h */ 01106 break; 01107 CASE_B(0xf1) /* ICEBP */ 01108 CPU_SW_Interrupt_NoIOPLCheck(1,GETIP); 01109 #if CPU_TRAP_CHECK 01110 cpu.trap_skip=true; 01111 #endif 01112 continue; 01113 CASE_B(0xf2) /* REPNZ */ 01114 DO_PREFIX_REP(false); 01115 break; 01116 CASE_B(0xf3) /* REPZ */ 01117 DO_PREFIX_REP(true); 01118 break; 01119 CASE_B(0xf4) /* HLT */ 01120 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 01121 FillFlags(); 01122 CPU_HLT(GETIP); 01123 return CBRET_NONE; //Needs to return for hlt cpu core 01124 CASE_B(0xf5) /* CMC */ 01125 FillFlags(); 01126 SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); 01127 break; 01128 CASE_B(0xf6) /* GRP3 Eb(,Ib) */ 01129 { 01130 GetRM;Bitu which=(rm>>3)&7; 01131 switch (which) { 01132 case 0x00: /* TEST Eb,Ib */ 01133 case 0x01: /* TEST Eb,Ib Undocumented*/ 01134 { 01135 if (rm >= 0xc0 ) {GetEArb;TESTB(*earb,Fetchb(),LoadRb,0)} 01136 else {GetEAa;TESTB(eaa,Fetchb(),LoadMb,0);} 01137 break; 01138 } 01139 case 0x02: /* NOT Eb */ 01140 { 01141 if (rm >= 0xc0 ) {GetEArb;*earb=~*earb;} 01142 else {GetEAa;SaveMb(eaa,~LoadMb(eaa));} 01143 break; 01144 } 01145 case 0x03: /* NEG Eb */ 01146 { 01147 lflags.type=t_NEGb; 01148 if (rm >= 0xc0 ) { 01149 GetEArb;lf_var1b=*earb;lf_resb=0-lf_var1b; 01150 *earb=lf_resb; 01151 } else { 01152 GetEAa;lf_var1b=LoadMb(eaa);lf_resb=0-lf_var1b; 01153 SaveMb(eaa,lf_resb); 01154 } 01155 break; 01156 } 01157 case 0x04: /* MUL AL,Eb */ 01158 RMEb(MULB); 01159 break; 01160 case 0x05: /* IMUL AL,Eb */ 01161 RMEb(IMULB); 01162 break; 01163 case 0x06: /* DIV Eb */ 01164 RMEb(DIVB); 01165 break; 01166 case 0x07: /* IDIV Eb */ 01167 RMEb(IDIVB); 01168 break; 01169 } 01170 break; 01171 } 01172 CASE_W(0xf7) /* GRP3 Ew(,Iw) */ 01173 { 01174 GetRM;Bitu which=(rm>>3)&7; 01175 switch (which) { 01176 case 0x00: /* TEST Ew,Iw */ 01177 case 0x01: /* TEST Ew,Iw Undocumented*/ 01178 { 01179 if (rm >= 0xc0 ) {GetEArw;TESTW(*earw,Fetchw(),LoadRw,SaveRw);} 01180 else {GetEAa;TESTW(eaa,Fetchw(),LoadMw,SaveMw);} 01181 break; 01182 } 01183 case 0x02: /* NOT Ew */ 01184 { 01185 if (rm >= 0xc0 ) {GetEArw;*earw=~*earw;} 01186 else {GetEAa;SaveMw(eaa,(Bitu)(~LoadMw(eaa)));} 01187 break; 01188 } 01189 case 0x03: /* NEG Ew */ 01190 { 01191 lflags.type=t_NEGw; 01192 if (rm >= 0xc0 ) { 01193 GetEArw;lf_var1w=*earw;lf_resw=0-lf_var1w; 01194 *earw=lf_resw; 01195 } else { 01196 GetEAa;lf_var1w=LoadMw(eaa);lf_resw=0-lf_var1w; 01197 SaveMw(eaa,lf_resw); 01198 } 01199 break; 01200 } 01201 case 0x04: /* MUL AX,Ew */ 01202 RMEw(MULW); 01203 break; 01204 case 0x05: /* IMUL AX,Ew */ 01205 RMEw(IMULW) 01206 break; 01207 case 0x06: /* DIV Ew */ 01208 RMEw(DIVW) 01209 break; 01210 case 0x07: /* IDIV Ew */ 01211 RMEw(IDIVW) 01212 break; 01213 } 01214 break; 01215 } 01216 CASE_B(0xf8) /* CLC */ 01217 FillFlags(); 01218 SETFLAGBIT(CF,false); 01219 break; 01220 CASE_B(0xf9) /* STC */ 01221 FillFlags(); 01222 SETFLAGBIT(CF,true); 01223 break; 01224 CASE_B(0xfa) /* CLI */ 01225 do_cli: if (CPU_CLI()) RUNEXCEPTION(); 01226 break; 01227 CASE_B(0xfb) /* STI */ 01228 if (CPU_STI()) RUNEXCEPTION(); 01229 #if CPU_PIC_CHECK 01230 if (GETFLAG(IF) && PIC_IRQCheck) { 01231 // NTS: Do not immmediately break execution, but set the cycle count to a minimal 01232 // value so that if a CLI follows immediately the interrupt will be ignored. 01233 // 01234 // It turns out on a 486 that STI+CLI (right next to each other) does not 01235 // trigger the CPU to process interrupts. Like this: 01236 // 01237 // STI 01238 // CLI 01239 // 01240 // The FM music driver for the PC-98 version of Peret em Heru appears to have 01241 // STI+CLI sequences for some reason in certain subroutines within the FM 01242 // music interrupt handler, which should not be trigger points to process 01243 // interrupts because the FM interrupt is non-reentrant and Peret is also 01244 // calling another entry point to the FM driver from IRQ 2 (vsync). If 01245 // IRQ 2 is processed while the FM interrupt is processing at the STI, the 01246 // stack switch will overwrite the first and the FM interrupt will return 01247 // by stale data and crash. 01248 // 01249 // [https://github.com/joncampbell123/dosbox-x/issues/1162] 01250 // 01251 // NTS: The prior fix that set CPU_Cycles = 4 causes the normal core to get stuck 01252 // and never break out (hanging DOSBox-X) when running PC-98 game Night Slave, 01253 // so that isn't a long-term option. 01254 { 01255 Bit8u b = FetchPeekb(); 01256 if (b == 0xFAu) { 01257 /* if the next opcode is CLI, then do CLI right here before the normal core 01258 * has any chance to break and handle interrupts */ 01259 FetchDiscardb(); // discard opcode we peeked, and then go execute it 01260 CPU_Cycles--; // we're executing another instruction, which should eat one CPU cycle 01261 goto do_cli; 01262 } 01263 } 01264 // otherwise, break for interrupt handling as normal 01265 if (CPU_Cycles > 2) { 01266 CPU_CycleLeft += CPU_Cycles - 2; 01267 CPU_Cycles = 2; 01268 } 01269 else { 01270 goto decode_end; 01271 } 01272 } 01273 #endif 01274 break; 01275 CASE_B(0xfc) /* CLD */ 01276 SETFLAGBIT(DF,false); 01277 cpu.direction=1; 01278 break; 01279 CASE_B(0xfd) /* STD */ 01280 SETFLAGBIT(DF,true); 01281 cpu.direction=-1; 01282 break; 01283 CASE_B(0xfe) /* GRP4 Eb */ 01284 { 01285 GetRM;Bitu which=(rm>>3)&7; 01286 switch (which) { 01287 case 0x00: /* INC Eb */ 01288 RMEb(INCB); 01289 break; 01290 case 0x01: /* DEC Eb */ 01291 RMEb(DECB); 01292 break; 01293 case 0x07: /* CallBack */ 01294 { 01295 Bitu cb=Fetchw(); 01296 FillFlags();SAVEIP; 01297 return (Bits)cb; 01298 } 01299 default: 01300 LOG(LOG_CPU,LOG_DEBUG)("Illegal GRP4 Call %d",(rm>>3) & 7); 01301 goto illegal_opcode; 01302 } 01303 break; 01304 } 01305 CASE_W(0xff) /* GRP5 Ew */ 01306 { 01307 GetRM;Bitu which=(rm>>3)&7; 01308 switch (which) { 01309 case 0x00: /* INC Ew */ 01310 RMEw(INCW); 01311 break; 01312 case 0x01: /* DEC Ew */ 01313 RMEw(DECW); 01314 break; 01315 case 0x02: /* CALL Ev */ 01316 { /* either EIP is set to the call address or EIP does not change if interrupted by PF */ 01317 Bit16u new_eip; 01318 if (rm >= 0xc0 ) {GetEArw;new_eip=*earw;} 01319 else {GetEAa;new_eip=LoadMw(eaa);} 01320 Push_16(GETIP); /* <- PF may happen here */ 01321 reg_eip = new_eip; 01322 } 01323 continue; 01324 case 0x03: /* CALL Ep */ 01325 { 01326 if (rm >= 0xc0) goto illegal_opcode; 01327 GetEAa; 01328 Bit16u newip=LoadMw(eaa); 01329 Bit16u newcs=LoadMw(eaa+2); 01330 FillFlags(); 01331 CPU_CALL(false,newcs,newip,GETIP); 01332 #if CPU_TRAP_CHECK 01333 if (GETFLAG(TF)) { 01334 cpudecoder=CPU_Core_Normal_Trap_Run; 01335 return CBRET_NONE; 01336 } 01337 #endif 01338 continue; 01339 } 01340 break; 01341 case 0x04: /* JMP Ev */ 01342 if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} 01343 else {GetEAa;reg_eip=LoadMw(eaa);} 01344 continue; 01345 case 0x05: /* JMP Ep */ 01346 { 01347 if (rm >= 0xc0) goto illegal_opcode; 01348 GetEAa; 01349 Bit16u newip=LoadMw(eaa); 01350 Bit16u newcs=LoadMw(eaa+2); 01351 FillFlags(); 01352 CPU_JMP(false,newcs,newip,GETIP); 01353 #if CPU_TRAP_CHECK 01354 if (GETFLAG(TF)) { 01355 cpudecoder=CPU_Core_Normal_Trap_Run; 01356 return CBRET_NONE; 01357 } 01358 #endif 01359 continue; 01360 } 01361 break; 01362 case 0x06: /* PUSH Ev */ 01363 if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);} 01364 else {GetEAa;Push_16(LoadMw(eaa));} 01365 break; 01366 default: 01367 goto illegal_opcode; 01368 } 01369 break; 01370 } 01371 01372 01373 01374