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_0F_W(0x00) /* GRP 6 Exxx */ 00020 if (CPU_ArchitectureType<CPU_ARCHTYPE_286) goto illegal_opcode; 00021 { 00022 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 00023 GetRM;Bitu which=(rm>>3)&7; 00024 switch (which) { 00025 case 0x00: /* SLDT */ 00026 case 0x01: /* STR */ 00027 { 00028 Bitu saveval; 00029 if (!which) saveval=CPU_SLDT(); 00030 else saveval=CPU_STR(); 00031 if (rm >= 0xc0) {GetEArw;*earw=(Bit16u)saveval;} 00032 else {GetEAa;SaveMw(eaa,(Bit16u)saveval);} 00033 } 00034 break; 00035 case 0x02:case 0x03:case 0x04:case 0x05: 00036 { 00037 Bitu loadval; 00038 if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} 00039 else {GetEAa;loadval=LoadMw(eaa);} 00040 switch (which) { 00041 case 0x02: 00042 if (cpu.cpl) EXCEPTION(EXCEPTION_GP); 00043 if (CPU_LLDT(loadval)) RUNEXCEPTION(); 00044 break; 00045 case 0x03: 00046 if (cpu.cpl) EXCEPTION(EXCEPTION_GP); 00047 if (CPU_LTR(loadval)) RUNEXCEPTION(); 00048 break; 00049 case 0x04: 00050 CPU_VERR(loadval); 00051 break; 00052 case 0x05: 00053 CPU_VERW(loadval); 00054 break; 00055 } 00056 } 00057 break; 00058 default: 00059 goto illegal_opcode; 00060 } 00061 } 00062 break; 00063 CASE_0F_W(0x01) /* Group 7 Ew */ 00064 if (CPU_ArchitectureType<CPU_ARCHTYPE_286) goto illegal_opcode; 00065 { 00066 GetRM;Bitu which=(rm>>3)&7; 00067 if (rm < 0xc0) { //First ones all use EA 00068 GetEAa;Bitu limit; 00069 switch (which) { 00070 /* NTS: The 286 is documented to write 0xFF in the most significant byte of the 6-byte field, 00071 * while 386 and later is documented to write 0x00 (or the MSB of the base if 32-bit form). 00072 * Some programs, including Microsoft Windows 3.0, execute SGDT and then compare the most 00073 * significant byte against 0xFF. It does NOT use the standard Intel detection process. */ 00074 case 0x00: /* SGDT */ 00075 SaveMw(eaa,(Bit16u)CPU_SGDT_limit()); 00076 SaveMd(eaa+2,(Bit32u)(CPU_SGDT_base()|(CPU_ArchitectureType<CPU_ARCHTYPE_386?0xFF000000UL:0))); 00077 break; 00078 /* NTS: Same comments for SIDT as SGDT */ 00079 case 0x01: /* SIDT */ 00080 SaveMw(eaa,(Bit16u)CPU_SIDT_limit()); 00081 SaveMd(eaa+2,(Bit32u)(CPU_SIDT_base()|(CPU_ArchitectureType<CPU_ARCHTYPE_386?0xFF000000UL:0))); 00082 break; 00083 case 0x02: /* LGDT */ 00084 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00085 CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); 00086 break; 00087 case 0x03: /* LIDT */ 00088 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00089 CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); 00090 break; 00091 case 0x04: /* SMSW */ 00092 SaveMw(eaa,(Bit16u)CPU_SMSW()); 00093 break; 00094 case 0x06: /* LMSW */ 00095 limit=LoadMw(eaa); 00096 if (CPU_LMSW(limit)) RUNEXCEPTION(); 00097 break; 00098 case 0x07: /* INVLPG */ 00099 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00100 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00101 PAGING_ClearTLB(); 00102 break; 00103 } 00104 } else { 00105 GetEArw; 00106 switch (which) { 00107 case 0x02: /* LGDT */ 00108 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00109 goto illegal_opcode; 00110 case 0x03: /* LIDT */ 00111 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00112 goto illegal_opcode; 00113 case 0x04: /* SMSW */ 00114 *earw=(Bit16u)CPU_SMSW(); 00115 break; 00116 case 0x06: /* LMSW */ 00117 if (CPU_LMSW(*earw)) RUNEXCEPTION(); 00118 break; 00119 default: 00120 goto illegal_opcode; 00121 } 00122 } 00123 } 00124 break; 00125 CASE_0F_W(0x02) /* LAR Gw,Ew */ 00126 if (CPU_ArchitectureType<CPU_ARCHTYPE_286) goto illegal_opcode; 00127 { 00128 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 00129 GetRMrw;Bitu ar=*rmrw; 00130 if (rm >= 0xc0) { 00131 GetEArw;CPU_LAR(*earw,ar); 00132 } else { 00133 GetEAa;CPU_LAR(LoadMw(eaa),ar); 00134 } 00135 *rmrw=(Bit16u)ar; 00136 } 00137 break; 00138 CASE_0F_W(0x03) /* LSL Gw,Ew */ 00139 if (CPU_ArchitectureType<CPU_ARCHTYPE_286) goto illegal_opcode; 00140 { 00141 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 00142 GetRMrw;Bitu limit=*rmrw; 00143 if (rm >= 0xc0) { 00144 GetEArw;CPU_LSL(*earw,limit); 00145 } else { 00146 GetEAa;CPU_LSL(LoadMw(eaa),limit); 00147 } 00148 *rmrw=(Bit16u)limit; 00149 } 00150 break; 00151 CASE_0F_B(0x06) /* CLTS */ 00152 if (CPU_ArchitectureType<CPU_ARCHTYPE_286) goto illegal_opcode; 00153 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00154 cpu.cr0&=(~CR0_TASKSWITCH); 00155 break; 00156 CASE_0F_B(0x08) /* INVD */ 00157 CASE_0F_B(0x09) /* WBINVD */ 00158 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00159 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00160 break; 00161 CASE_0F_B(0x20) /* MOV Rd.CRx */ 00162 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00163 { 00164 GetRM; 00165 Bitu which=(rm >> 3) & 7; 00166 if (rm < 0xc0 ) { 00167 rm |= 0xc0; 00168 LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",(int)which); 00169 } 00170 GetEArd; 00171 Bit32u crx_value; 00172 if (CPU_READ_CRX(which,crx_value)) RUNEXCEPTION(); 00173 *eard=crx_value; 00174 } 00175 break; 00176 CASE_0F_B(0x21) /* MOV Rd,DRx */ 00177 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00178 { 00179 GetRM; 00180 Bitu which=(rm >> 3) & 7; 00181 if (rm < 0xc0 ) { 00182 rm |= 0xc0; 00183 LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR%u with non-register",(int)which); 00184 } 00185 GetEArd; 00186 Bit32u drx_value; 00187 if (CPU_READ_DRX(which,drx_value)) RUNEXCEPTION(); 00188 *eard=drx_value; 00189 } 00190 break; 00191 CASE_0F_B(0x22) /* MOV CRx,Rd */ 00192 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00193 { 00194 GetRM; 00195 Bitu which=(rm >> 3) & 7; 00196 if (rm < 0xc0 ) { 00197 rm |= 0xc0; 00198 LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",(int)which); 00199 } 00200 GetEArd; 00201 if (CPU_WRITE_CRX(which,*eard)) RUNEXCEPTION(); 00202 } 00203 break; 00204 CASE_0F_B(0x23) /* MOV DRx,Rd */ 00205 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00206 { 00207 GetRM; 00208 Bitu which=(rm >> 3) & 7; 00209 if (rm < 0xc0 ) { 00210 rm |= 0xc0; 00211 LOG(LOG_CPU,LOG_ERROR)("MOV DR%u,XXX with non-register",(int)which); 00212 } 00213 GetEArd; 00214 if (CPU_WRITE_DRX(which,*eard)) RUNEXCEPTION(); 00215 } 00216 break; 00217 CASE_0F_B(0x24) /* MOV Rd,TRx */ 00218 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00219 { 00220 GetRM; 00221 Bitu which=(rm >> 3) & 7; 00222 if (rm < 0xc0 ) { 00223 rm |= 0xc0; 00224 LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR%u with non-register",(int)which); 00225 } 00226 GetEArd; 00227 Bit32u trx_value; 00228 if (CPU_READ_TRX(which,trx_value)) RUNEXCEPTION(); 00229 *eard=trx_value; 00230 } 00231 break; 00232 CASE_0F_B(0x26) /* MOV TRx,Rd */ 00233 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00234 { 00235 GetRM; 00236 Bitu which=(rm >> 3) & 7; 00237 if (rm < 0xc0 ) { 00238 rm |= 0xc0; 00239 LOG(LOG_CPU,LOG_ERROR)("MOV TR%u,XXX with non-register",(int)which); 00240 } 00241 GetEArd; 00242 if (CPU_WRITE_TRX(which,*eard)) RUNEXCEPTION(); 00243 } 00244 break; 00245 CASE_0F_B(0x30) /* WRMSR */ 00246 { 00247 if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUM) goto illegal_opcode; 00248 if (!CPU_WRMSR()) goto illegal_opcode; 00249 } 00250 break; 00251 CASE_0F_B(0x31) /* RDTSC */ 00252 { 00253 if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUM) goto illegal_opcode; 00254 /* Use a fixed number when in auto cycles mode as else the reported value changes constantly */ 00255 Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double) (CPU_CycleAutoAdjust?70000:CPU_CycleMax)); 00256 reg_edx=(Bit32u)(tsc>>32); 00257 reg_eax=(Bit32u)(tsc&0xffffffff); 00258 } 00259 break; 00260 00261 // Pentium Pro Conditional Moves 00262 CASE_0F_W(0x40) /* CMOVO */ 00263 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00264 MoveCond16(TFLG_O); break; 00265 CASE_0F_W(0x41) /* CMOVNO */ 00266 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00267 MoveCond16(TFLG_NO); break; 00268 CASE_0F_W(0x42) /* CMOVB */ 00269 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00270 MoveCond16(TFLG_B); break; 00271 CASE_0F_W(0x43) /* CMOVNB */ 00272 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00273 MoveCond16(TFLG_NB); break; 00274 CASE_0F_W(0x44) /* CMOVZ */ 00275 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00276 MoveCond16(TFLG_Z); break; 00277 CASE_0F_W(0x45) /* CMOVNZ */ 00278 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00279 MoveCond16(TFLG_NZ); break; 00280 CASE_0F_W(0x46) /* CMOVBE */ 00281 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00282 MoveCond16(TFLG_BE); break; 00283 CASE_0F_W(0x47) /* CMOVNBE */ 00284 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00285 MoveCond16(TFLG_NBE); break; 00286 CASE_0F_W(0x48) /* CMOVS */ 00287 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00288 MoveCond16(TFLG_S); break; 00289 CASE_0F_W(0x49) /* CMOVNS */ 00290 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00291 MoveCond16(TFLG_NS); break; 00292 CASE_0F_W(0x4A) /* CMOVP */ 00293 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00294 MoveCond16(TFLG_P); break; 00295 CASE_0F_W(0x4B) /* CMOVNP */ 00296 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00297 MoveCond16(TFLG_NP); break; 00298 CASE_0F_W(0x4C) /* CMOVL */ 00299 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00300 MoveCond16(TFLG_L); break; 00301 CASE_0F_W(0x4D) /* CMOVNL */ 00302 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00303 MoveCond16(TFLG_NL); break; 00304 CASE_0F_W(0x4E) /* CMOVLE */ 00305 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00306 MoveCond16(TFLG_LE); break; 00307 CASE_0F_W(0x4F) /* CMOVNLE */ 00308 if (CPU_ArchitectureType<CPU_ARCHTYPE_PPROSLOW) goto illegal_opcode; 00309 MoveCond16(TFLG_NLE); break; 00310 00311 CASE_0F_B(0x32) /* RDMSR */ 00312 { 00313 if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUM) goto illegal_opcode; 00314 if (!CPU_RDMSR()) goto illegal_opcode; 00315 } 00316 break; 00317 #if CPU_CORE >= CPU_ARCHTYPE_386 00318 CASE_0F_W(0x80) /* JO */ 00319 JumpCond16_w(TFLG_O);break; 00320 CASE_0F_W(0x81) /* JNO */ 00321 JumpCond16_w(TFLG_NO);break; 00322 CASE_0F_W(0x82) /* JB */ 00323 JumpCond16_w(TFLG_B);break; 00324 CASE_0F_W(0x83) /* JNB */ 00325 JumpCond16_w(TFLG_NB);break; 00326 CASE_0F_W(0x84) /* JZ */ 00327 JumpCond16_w(TFLG_Z);break; 00328 CASE_0F_W(0x85) /* JNZ */ 00329 JumpCond16_w(TFLG_NZ);break; 00330 CASE_0F_W(0x86) /* JBE */ 00331 JumpCond16_w(TFLG_BE);break; 00332 CASE_0F_W(0x87) /* JNBE */ 00333 JumpCond16_w(TFLG_NBE);break; 00334 CASE_0F_W(0x88) /* JS */ 00335 JumpCond16_w(TFLG_S);break; 00336 CASE_0F_W(0x89) /* JNS */ 00337 JumpCond16_w(TFLG_NS);break; 00338 CASE_0F_W(0x8a) /* JP */ 00339 JumpCond16_w(TFLG_P);break; 00340 CASE_0F_W(0x8b) /* JNP */ 00341 JumpCond16_w(TFLG_NP);break; 00342 CASE_0F_W(0x8c) /* JL */ 00343 JumpCond16_w(TFLG_L);break; 00344 CASE_0F_W(0x8d) /* JNL */ 00345 JumpCond16_w(TFLG_NL);break; 00346 CASE_0F_W(0x8e) /* JLE */ 00347 JumpCond16_w(TFLG_LE);break; 00348 CASE_0F_W(0x8f) /* JNLE */ 00349 JumpCond16_w(TFLG_NLE);break; 00350 CASE_0F_B(0x90) /* SETO */ 00351 SETcc(TFLG_O);break; 00352 CASE_0F_B(0x91) /* SETNO */ 00353 SETcc(TFLG_NO);break; 00354 CASE_0F_B(0x92) /* SETB */ 00355 SETcc(TFLG_B);break; 00356 CASE_0F_B(0x93) /* SETNB */ 00357 SETcc(TFLG_NB);break; 00358 CASE_0F_B(0x94) /* SETZ */ 00359 SETcc(TFLG_Z);break; 00360 CASE_0F_B(0x95) /* SETNZ */ 00361 SETcc(TFLG_NZ); break; 00362 CASE_0F_B(0x96) /* SETBE */ 00363 SETcc(TFLG_BE);break; 00364 CASE_0F_B(0x97) /* SETNBE */ 00365 SETcc(TFLG_NBE);break; 00366 CASE_0F_B(0x98) /* SETS */ 00367 SETcc(TFLG_S);break; 00368 CASE_0F_B(0x99) /* SETNS */ 00369 SETcc(TFLG_NS);break; 00370 CASE_0F_B(0x9a) /* SETP */ 00371 SETcc(TFLG_P);break; 00372 CASE_0F_B(0x9b) /* SETNP */ 00373 SETcc(TFLG_NP);break; 00374 CASE_0F_B(0x9c) /* SETL */ 00375 SETcc(TFLG_L);break; 00376 CASE_0F_B(0x9d) /* SETNL */ 00377 SETcc(TFLG_NL);break; 00378 CASE_0F_B(0x9e) /* SETLE */ 00379 SETcc(TFLG_LE);break; 00380 CASE_0F_B(0x9f) /* SETNLE */ 00381 SETcc(TFLG_NLE);break; 00382 #endif 00383 CASE_0F_W(0xa0) /* PUSH FS */ 00384 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00385 Push_16(SegValue(fs));break; 00386 CASE_0F_W(0xa1) /* POP FS */ 00387 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00388 if (CPU_PopSeg(fs,false)) RUNEXCEPTION(); 00389 break; 00390 CASE_0F_B(0xa2) /* CPUID */ 00391 if (!CPU_CPUID()) goto illegal_opcode; 00392 break; 00393 CASE_0F_W(0xa3) /* BT Ew,Gw */ 00394 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00395 { 00396 FillFlags();GetRMrw; 00397 Bit16u mask=1u << (*rmrw & 15u); 00398 if (rm >= 0xc0 ) { 00399 GetEArw; 00400 SETFLAGBIT(CF,(*earw & mask)); 00401 } else { 00402 GetEAa;eaa+=(PhysPt)((((Bit16s)*rmrw)>>4)*2); 00403 Bit16u old=LoadMw(eaa); 00404 SETFLAGBIT(CF,(old & mask)); 00405 } 00406 break; 00407 } 00408 CASE_0F_W(0xa4) /* SHLD Ew,Gw,Ib */ 00409 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00410 RMEwGwOp3(DSHLW,Fetchb()); 00411 break; 00412 CASE_0F_W(0xa5) /* SHLD Ew,Gw,CL */ 00413 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00414 RMEwGwOp3(DSHLW,reg_cl); 00415 break; 00416 CASE_0F_W(0xa8) /* PUSH GS */ 00417 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00418 Push_16(SegValue(gs));break; 00419 CASE_0F_W(0xa9) /* POP GS */ 00420 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00421 if (CPU_PopSeg(gs,false)) RUNEXCEPTION(); 00422 break; 00423 CASE_0F_W(0xab) /* BTS Ew,Gw */ 00424 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00425 { 00426 FillFlags();GetRMrw; 00427 Bit16u mask=1u << (*rmrw & 15u); 00428 if (rm >= 0xc0 ) { 00429 GetEArw; 00430 SETFLAGBIT(CF,(*earw & mask)); 00431 *earw|=mask; 00432 } else { 00433 GetEAa;eaa+=(PhysPt)((((Bit16s)*rmrw)>>4)*2); 00434 Bit16u old=LoadMw(eaa); 00435 SETFLAGBIT(CF,(old & mask)); 00436 SaveMw(eaa,old | mask); 00437 } 00438 break; 00439 } 00440 CASE_0F_W(0xac) /* SHRD Ew,Gw,Ib */ 00441 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00442 RMEwGwOp3(DSHRW,Fetchb()); 00443 break; 00444 CASE_0F_W(0xad) /* SHRD Ew,Gw,CL */ 00445 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00446 RMEwGwOp3(DSHRW,reg_cl); 00447 break; 00448 CASE_0F_W(0xaf) /* IMUL Gw,Ew */ 00449 RMGwEwOp3(DIMULW,*rmrw); 00450 break; 00451 CASE_0F_B(0xb0) /* cmpxchg Eb,Gb */ 00452 { 00453 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00454 FillFlags(); 00455 GetRMrb; 00456 if (rm >= 0xc0 ) { 00457 GetEArb; 00458 if (reg_al == *earb) { 00459 *earb=*rmrb; 00460 SETFLAGBIT(ZF,1); 00461 } else { 00462 reg_al = *earb; 00463 SETFLAGBIT(ZF,0); 00464 } 00465 } else { 00466 GetEAa; 00467 Bit8u val = LoadMb(eaa); 00468 if (reg_al == val) { 00469 SaveMb(eaa,*rmrb); 00470 SETFLAGBIT(ZF,1); 00471 } else { 00472 SaveMb(eaa,val); // cmpxchg always issues a write 00473 reg_al = val; 00474 SETFLAGBIT(ZF,0); 00475 } 00476 } 00477 break; 00478 } 00479 CASE_0F_W(0xb1) /* cmpxchg Ew,Gw */ 00480 { 00481 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00482 FillFlags(); 00483 GetRMrw; 00484 if (rm >= 0xc0 ) { 00485 GetEArw; 00486 if(reg_ax == *earw) { 00487 *earw = *rmrw; 00488 SETFLAGBIT(ZF,1); 00489 } else { 00490 reg_ax = *earw; 00491 SETFLAGBIT(ZF,0); 00492 } 00493 } else { 00494 GetEAa; 00495 Bit16u val = LoadMw(eaa); 00496 if(reg_ax == val) { 00497 SaveMw(eaa,*rmrw); 00498 SETFLAGBIT(ZF,1); 00499 } else { 00500 SaveMw(eaa,val); // cmpxchg always issues a write 00501 reg_ax = val; 00502 SETFLAGBIT(ZF,0); 00503 } 00504 } 00505 break; 00506 } 00507 00508 CASE_0F_W(0xb2) /* LSS Ew */ 00509 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00510 { 00511 GetRMrw; 00512 if (rm >= 0xc0) goto illegal_opcode; 00513 GetEAa; 00514 if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION(); 00515 *rmrw=LoadMw(eaa); 00516 break; 00517 } 00518 CASE_0F_W(0xb3) /* BTR Ew,Gw */ 00519 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00520 { 00521 FillFlags();GetRMrw; 00522 Bit16u mask=1u << (*rmrw & 15u); 00523 if (rm >= 0xc0 ) { 00524 GetEArw; 00525 SETFLAGBIT(CF,(*earw & mask)); 00526 *earw&= ~mask; 00527 } else { 00528 GetEAa;eaa+=(PhysPt)((((Bit16s)*rmrw)>>4)*2); 00529 Bit16u old=LoadMw(eaa); 00530 SETFLAGBIT(CF,(old & mask)); 00531 SaveMw(eaa,old & ~mask); 00532 } 00533 break; 00534 } 00535 CASE_0F_W(0xb4) /* LFS Ew */ 00536 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00537 { 00538 GetRMrw; 00539 if (rm >= 0xc0) goto illegal_opcode; 00540 GetEAa; 00541 if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION(); 00542 *rmrw=LoadMw(eaa); 00543 break; 00544 } 00545 CASE_0F_W(0xb5) /* LGS Ew */ 00546 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00547 { 00548 GetRMrw; 00549 if (rm >= 0xc0) goto illegal_opcode; 00550 GetEAa; 00551 if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION(); 00552 *rmrw=LoadMw(eaa); 00553 break; 00554 } 00555 CASE_0F_W(0xb6) /* MOVZX Gw,Eb */ 00556 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00557 { 00558 GetRMrw; 00559 if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;} 00560 else {GetEAa;*rmrw=LoadMb(eaa);} 00561 break; 00562 } 00563 CASE_0F_W(0xb7) /* MOVZX Gw,Ew */ 00564 CASE_0F_W(0xbf) /* MOVSX Gw,Ew */ 00565 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00566 { 00567 GetRMrw; 00568 if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} 00569 else {GetEAa;*rmrw=LoadMw(eaa);} 00570 break; 00571 } 00572 CASE_0F_W(0xba) /* GRP8 Ew,Ib */ 00573 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00574 { 00575 FillFlags();GetRM; 00576 if (rm >= 0xc0 ) { 00577 GetEArw; 00578 Bit16u mask=1 << (Fetchb() & 15); 00579 SETFLAGBIT(CF,(*earw & mask)); 00580 switch (rm & 0x38) { 00581 case 0x20: /* BT */ 00582 break; 00583 case 0x28: /* BTS */ 00584 *earw|=mask; 00585 break; 00586 case 0x30: /* BTR */ 00587 *earw&= ~mask; 00588 break; 00589 case 0x38: /* BTC */ 00590 *earw^=mask; 00591 break; 00592 default: 00593 E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); 00594 } 00595 } else { 00596 GetEAa;Bit16u old=LoadMw(eaa); 00597 Bit16u mask=1 << (Fetchb() & 15); 00598 SETFLAGBIT(CF,(old & mask)); 00599 switch (rm & 0x38) { 00600 case 0x20: /* BT */ 00601 break; 00602 case 0x28: /* BTS */ 00603 SaveMw(eaa,old|mask); 00604 break; 00605 case 0x30: /* BTR */ 00606 SaveMw(eaa,old & ~mask); 00607 break; 00608 case 0x38: /* BTC */ 00609 SaveMw(eaa,old ^ mask); 00610 break; 00611 default: 00612 E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); 00613 } 00614 } 00615 break; 00616 } 00617 CASE_0F_W(0xbb) /* BTC Ew,Gw */ 00618 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00619 { 00620 FillFlags();GetRMrw; 00621 Bit16u mask=1u << (*rmrw & 15u); 00622 if (rm >= 0xc0 ) { 00623 GetEArw; 00624 SETFLAGBIT(CF,(*earw & mask)); 00625 *earw^=mask; 00626 } else { 00627 GetEAa;eaa+=(PhysPt)((((Bit16s)*rmrw)>>4)*2); 00628 Bit16u old=LoadMw(eaa); 00629 SETFLAGBIT(CF,(old & mask)); 00630 SaveMw(eaa,old ^ mask); 00631 } 00632 break; 00633 } 00634 CASE_0F_W(0xbc) /* BSF Gw,Ew */ 00635 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00636 { 00637 GetRMrw; 00638 Bit16u value; 00639 if (rm >= 0xc0) { GetEArw; value=*earw; } 00640 else { GetEAa; value=LoadMw(eaa); } 00641 if (value==0) { 00642 SETFLAGBIT(ZF,true); 00643 } else { 00644 Bit16u result = 0; 00645 while ((value & 0x01)==0) { result++; value>>=1; } 00646 SETFLAGBIT(ZF,false); 00647 *rmrw = result; 00648 } 00649 lflags.type=t_UNKNOWN; 00650 break; 00651 } 00652 CASE_0F_W(0xbd) /* BSR Gw,Ew */ 00653 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00654 { 00655 GetRMrw; 00656 Bit16u value; 00657 if (rm >= 0xc0) { GetEArw; value=*earw; } 00658 else { GetEAa; value=LoadMw(eaa); } 00659 if (value==0) { 00660 SETFLAGBIT(ZF,true); 00661 } else { 00662 Bit16u result = 15; // Operandsize-1 00663 while ((value & 0x8000)==0) { result--; value<<=1; } 00664 SETFLAGBIT(ZF,false); 00665 *rmrw = result; 00666 } 00667 lflags.type=t_UNKNOWN; 00668 break; 00669 } 00670 CASE_0F_W(0xbe) /* MOVSX Gw,Eb */ 00671 if (CPU_ArchitectureType<CPU_ARCHTYPE_386) goto illegal_opcode; 00672 { 00673 GetRMrw; 00674 if (rm >= 0xc0 ) {GetEArb;*rmrw=(Bit16u)(*(Bit8s *)earb);} 00675 else {GetEAa;*rmrw=(Bit16u)LoadMbs(eaa);} 00676 break; 00677 } 00678 CASE_0F_B(0xc0) /* XADD Gb,Eb */ 00679 { 00680 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00681 GetRMrb;Bit8u oldrmrb=*rmrb; 00682 if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb+=oldrmrb;} 00683 else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,LoadMb(eaa)+oldrmrb);} 00684 break; 00685 } 00686 CASE_0F_W(0xc1) /* XADD Gw,Ew */ 00687 { 00688 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00689 GetRMrw;Bit16u oldrmrw=*rmrw; 00690 if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw+=oldrmrw;} 00691 else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,LoadMw(eaa)+oldrmrw);} 00692 break; 00693 } 00694 CASE_0F_W(0xc7) 00695 { 00696 extern bool enable_cmpxchg8b; 00697 void CPU_CMPXCHG8B(PhysPt eaa); 00698 00699 if (!enable_cmpxchg8b || CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUM) goto illegal_opcode; 00700 GetRM; 00701 if (((rm >> 3) & 7) == 1) { // CMPXCHG8B /1 r/m 00702 if (rm >= 0xc0 ) goto illegal_opcode; 00703 GetEAa; 00704 CPU_CMPXCHG8B(eaa); 00705 } 00706 else { 00707 goto illegal_opcode; 00708 } 00709 break; 00710 } 00711 CASE_0F_W(0xc8) /* BSWAP AX */ 00712 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00713 BSWAPW(reg_ax);break; 00714 CASE_0F_W(0xc9) /* BSWAP CX */ 00715 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00716 BSWAPW(reg_cx);break; 00717 CASE_0F_W(0xca) /* BSWAP DX */ 00718 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00719 BSWAPW(reg_dx);break; 00720 CASE_0F_W(0xcb) /* BSWAP BX */ 00721 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00722 BSWAPW(reg_bx);break; 00723 CASE_0F_W(0xcc) /* BSWAP SP */ 00724 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00725 BSWAPW(reg_sp);break; 00726 CASE_0F_W(0xcd) /* BSWAP BP */ 00727 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00728 BSWAPW(reg_bp);break; 00729 CASE_0F_W(0xce) /* BSWAP SI */ 00730 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00731 BSWAPW(reg_si);break; 00732 CASE_0F_W(0xcf) /* BSWAP DI */ 00733 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLD) goto illegal_opcode; 00734 BSWAPW(reg_di);break; 00735 #if C_FPU 00736 #define CASE_0F_MMX(x) CASE_0F_W(x) 00737 #include "prefix_0f_mmx.h" 00738 #undef CASE_0F_MMX 00739 #endif