1 /* 2 * Copyright (C) 2002-2010 The DOSBox Team 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19 CASE_0F_D(0x00) /* GRP 6 Exxx */ 20 { 21 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 22 GetRM;Bitu which=(rm>>3)&7; 23 switch (which) { 24 case 0x00: /* SLDT */ 25 case 0x01: /* STR */ 26 { 27 Bitu saveval; 28 if (!which) saveval=CPU_SLDT(); 29 else saveval=CPU_STR(); 30 if (rm >= 0xc0) {GetEArw;*earw=(Bit16u)saveval;} 31 else {GetEAa;SaveMw(eaa,saveval);} 32 } 33 break; 34 case 0x02:case 0x03:case 0x04:case 0x05: 35 { 36 /* Just use 16-bit loads since were only using selectors */ 37 Bitu loadval; 38 if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} 39 else {GetEAa;loadval=LoadMw(eaa);} 40 switch (which) { 41 case 0x02: 42 if (cpu.cpl) EXCEPTION(EXCEPTION_GP); 43 if (CPU_LLDT(loadval)) RUNEXCEPTION(); 44 break; 45 case 0x03: 46 if (cpu.cpl) EXCEPTION(EXCEPTION_GP); 47 if (CPU_LTR(loadval)) RUNEXCEPTION(); 48 break; 49 case 0x04: 50 CPU_VERR(loadval); 51 break; 52 case 0x05: 53 CPU_VERW(loadval); 54 break; 55 } 56 } 57 break; 58 default: 59 LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); 60 goto illegal_opcode; 61 } 62 } 63 break; 64 CASE_0F_D(0x01) /* Group 7 Ed */ 65 { 66 GetRM;Bitu which=(rm>>3)&7; 67 if (rm < 0xc0) { //First ones all use EA 68 GetEAa;Bitu limit; 69 switch (which) { 70 case 0x00: /* SGDT */ 71 SaveMw(eaa,(Bit16u)CPU_SGDT_limit()); 72 SaveMd(eaa+2,(Bit32u)CPU_SGDT_base()); 73 break; 74 case 0x01: /* SIDT */ 75 SaveMw(eaa,(Bit16u)CPU_SIDT_limit()); 76 SaveMd(eaa+2,(Bit32u)CPU_SIDT_base()); 77 break; 78 case 0x02: /* LGDT */ 79 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 80 CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2)); 81 break; 82 case 0x03: /* LIDT */ 83 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 84 CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2)); 85 break; 86 case 0x04: /* SMSW */ 87 SaveMw(eaa,(Bit16u)CPU_SMSW()); 88 break; 89 case 0x06: /* LMSW */ 90 limit=LoadMw(eaa); 91 if (CPU_LMSW((Bit16u)limit)) RUNEXCEPTION(); 92 break; 93 case 0x07: /* INVLPG */ 94 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 95 PAGING_ClearTLB(); 96 break; 97 } 98 } else { 99 GetEArd; 100 switch (which) { 101 case 0x02: /* LGDT */ 102 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 103 goto illegal_opcode; 104 case 0x03: /* LIDT */ 105 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 106 goto illegal_opcode; 107 case 0x04: /* SMSW */ 108 *eard=(Bit32u)CPU_SMSW(); 109 break; 110 case 0x06: /* LMSW */ 111 if (CPU_LMSW(*eard)) RUNEXCEPTION(); 112 break; 113 default: 114 LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); 115 goto illegal_opcode; 116 break; 117 } 118 119 } 120 } 121 break; 122 CASE_0F_D(0x02) /* LAR Gd,Ed */ 123 { 124 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 125 GetRMrd;Bitu ar=*rmrd; 126 if (rm >= 0xc0) { 127 GetEArw;CPU_LAR(*earw,ar); 128 } else { 129 GetEAa;CPU_LAR(LoadMw(eaa),ar); 130 } 131 *rmrd=(Bit32u)ar; 132 } 133 break; 134 CASE_0F_D(0x03) /* LSL Gd,Ew */ 135 { 136 if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; 137 GetRMrd;Bitu limit=*rmrd; 138 /* Just load 16-bit values for selectors */ 139 if (rm >= 0xc0) { 140 GetEArw;CPU_LSL(*earw,limit); 141 } else { 142 GetEAa;CPU_LSL(LoadMw(eaa),limit); 143 } 144 *rmrd=(Bit32u)limit; 145 } 146 break; 147 CASE_0F_D(0x80) /* JO */ 148 JumpCond32_d(TFLG_O);break; 149 CASE_0F_D(0x81) /* JNO */ 150 JumpCond32_d(TFLG_NO);break; 151 CASE_0F_D(0x82) /* JB */ 152 JumpCond32_d(TFLG_B);break; 153 CASE_0F_D(0x83) /* JNB */ 154 JumpCond32_d(TFLG_NB);break; 155 CASE_0F_D(0x84) /* JZ */ 156 JumpCond32_d(TFLG_Z);break; 157 CASE_0F_D(0x85) /* JNZ */ 158 JumpCond32_d(TFLG_NZ);break; 159 CASE_0F_D(0x86) /* JBE */ 160 JumpCond32_d(TFLG_BE);break; 161 CASE_0F_D(0x87) /* JNBE */ 162 JumpCond32_d(TFLG_NBE);break; 163 CASE_0F_D(0x88) /* JS */ 164 JumpCond32_d(TFLG_S);break; 165 CASE_0F_D(0x89) /* JNS */ 166 JumpCond32_d(TFLG_NS);break; 167 CASE_0F_D(0x8a) /* JP */ 168 JumpCond32_d(TFLG_P);break; 169 CASE_0F_D(0x8b) /* JNP */ 170 JumpCond32_d(TFLG_NP);break; 171 CASE_0F_D(0x8c) /* JL */ 172 JumpCond32_d(TFLG_L);break; 173 CASE_0F_D(0x8d) /* JNL */ 174 JumpCond32_d(TFLG_NL);break; 175 CASE_0F_D(0x8e) /* JLE */ 176 JumpCond32_d(TFLG_LE);break; 177 CASE_0F_D(0x8f) /* JNLE */ 178 JumpCond32_d(TFLG_NLE);break; 179 180 CASE_0F_D(0xa0) /* PUSH FS */ 181 Push_32(SegValue(fs));break; 182 CASE_0F_D(0xa1) /* POP FS */ 183 if (CPU_PopSeg(fs,true)) RUNEXCEPTION(); 184 break; 185 CASE_0F_D(0xa3) /* BT Ed,Gd */ 186 { 187 FillFlags();GetRMrd; 188 Bit32u mask=1 << (*rmrd & 31); 189 if (rm >= 0xc0 ) { 190 GetEArd; 191 SETFLAGBIT(CF,(*eard & mask)); 192 } else { 193 GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; 194 Bit32u old=LoadMd(eaa); 195 SETFLAGBIT(CF,(old & mask)); 196 } 197 break; 198 } 199 CASE_0F_D(0xa4) /* SHLD Ed,Gd,Ib */ 200 RMEdGdOp3(DSHLD,Fetchb()); 201 break; 202 CASE_0F_D(0xa5) /* SHLD Ed,Gd,CL */ 203 RMEdGdOp3(DSHLD,reg_cl); 204 break; 205 CASE_0F_D(0xa8) /* PUSH GS */ 206 Push_32(SegValue(gs));break; 207 CASE_0F_D(0xa9) /* POP GS */ 208 if (CPU_PopSeg(gs,true)) RUNEXCEPTION(); 209 break; 210 CASE_0F_D(0xab) /* BTS Ed,Gd */ 211 { 212 FillFlags();GetRMrd; 213 Bit32u mask=1 << (*rmrd & 31); 214 if (rm >= 0xc0 ) { 215 GetEArd; 216 SETFLAGBIT(CF,(*eard & mask)); 217 *eard|=mask; 218 } else { 219 GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; 220 Bit32u old=LoadMd(eaa); 221 SETFLAGBIT(CF,(old & mask)); 222 SaveMd(eaa,old | mask); 223 } 224 break; 225 } 226 227 CASE_0F_D(0xac) /* SHRD Ed,Gd,Ib */ 228 RMEdGdOp3(DSHRD,Fetchb()); 229 break; 230 CASE_0F_D(0xad) /* SHRD Ed,Gd,CL */ 231 RMEdGdOp3(DSHRD,reg_cl); 232 break; 233 CASE_0F_D(0xaf) /* IMUL Gd,Ed */ 234 { 235 RMGdEdOp3(DIMULD,*rmrd); 236 break; 237 } 238 CASE_0F_D(0xb1) /* CMPXCHG Ed,Gd */ 239 { 240 if (CPU_ArchitectureType<CPU_ARCHTYPE_486NEWSLOW) goto illegal_opcode; 241 FillFlags(); 242 GetRMrd; 243 if (rm >= 0xc0) { 244 GetEArd; 245 if (*eard==reg_eax) { 246 *eard=*rmrd; 247 SETFLAGBIT(ZF,1); 248 } else { 249 reg_eax=*eard; 250 SETFLAGBIT(ZF,0); 251 } 252 } else { 253 GetEAa; 254 Bit32u val=LoadMd(eaa); 255 if (val==reg_eax) { 256 SaveMd(eaa,*rmrd); 257 SETFLAGBIT(ZF,1); 258 } else { 259 SaveMd(eaa,val); // cmpxchg always issues a write 260 reg_eax=val; 261 SETFLAGBIT(ZF,0); 262 } 263 } 264 break; 265 } 266 CASE_0F_D(0xb2) /* LSS Ed */ 267 { 268 GetRMrd; 269 if (rm >= 0xc0) goto illegal_opcode; 270 GetEAa; 271 if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION(); 272 *rmrd=LoadMd(eaa); 273 break; 274 } 275 CASE_0F_D(0xb3) /* BTR Ed,Gd */ 276 { 277 FillFlags();GetRMrd; 278 Bit32u mask=1 << (*rmrd & 31); 279 if (rm >= 0xc0 ) { 280 GetEArd; 281 SETFLAGBIT(CF,(*eard & mask)); 282 *eard&= ~mask; 283 } else { 284 GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; 285 Bit32u old=LoadMd(eaa); 286 SETFLAGBIT(CF,(old & mask)); 287 SaveMd(eaa,old & ~mask); 288 } 289 break; 290 } 291 CASE_0F_D(0xb4) /* LFS Ed */ 292 { 293 GetRMrd; 294 if (rm >= 0xc0) goto illegal_opcode; 295 GetEAa; 296 if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION(); 297 *rmrd=LoadMd(eaa); 298 break; 299 } 300 CASE_0F_D(0xb5) /* LGS Ed */ 301 { 302 GetRMrd; 303 if (rm >= 0xc0) goto illegal_opcode; 304 GetEAa; 305 if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION(); 306 *rmrd=LoadMd(eaa); 307 break; 308 } 309 CASE_0F_D(0xb6) /* MOVZX Gd,Eb */ 310 { 311 GetRMrd; 312 if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} 313 else {GetEAa;*rmrd=LoadMb(eaa);} 314 break; 315 } 316 CASE_0F_D(0xb7) /* MOVXZ Gd,Ew */ 317 { 318 GetRMrd; 319 if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;} 320 else {GetEAa;*rmrd=LoadMw(eaa);} 321 break; 322 } 323 CASE_0F_D(0xba) /* GRP8 Ed,Ib */ 324 { 325 FillFlags();GetRM; 326 if (rm >= 0xc0 ) { 327 GetEArd; 328 Bit32u mask=1 << (Fetchb() & 31); 329 SETFLAGBIT(CF,(*eard & mask)); 330 switch (rm & 0x38) { 331 case 0x20: /* BT */ 332 break; 333 case 0x28: /* BTS */ 334 *eard|=mask; 335 break; 336 case 0x30: /* BTR */ 337 *eard&=~mask; 338 break; 339 case 0x38: /* BTC */ 340 if (GETFLAG(CF)) *eard&=~mask; 341 else *eard|=mask; 342 break; 343 default: 344 E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); 345 } 346 } else { 347 GetEAa;Bit32u old=LoadMd(eaa); 348 Bit32u mask=1 << (Fetchb() & 31); 349 SETFLAGBIT(CF,(old & mask)); 350 switch (rm & 0x38) { 351 case 0x20: /* BT */ 352 break; 353 case 0x28: /* BTS */ 354 SaveMd(eaa,old|mask); 355 break; 356 case 0x30: /* BTR */ 357 SaveMd(eaa,old & ~mask); 358 break; 359 case 0x38: /* BTC */ 360 if (GETFLAG(CF)) old&=~mask; 361 else old|=mask; 362 SaveMd(eaa,old); 363 break; 364 default: 365 E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); 366 } 367 } 368 break; 369 } 370 CASE_0F_D(0xbb) /* BTC Ed,Gd */ 371 { 372 FillFlags();GetRMrd; 373 Bit32u mask=1 << (*rmrd & 31); 374 if (rm >= 0xc0 ) { 375 GetEArd; 376 SETFLAGBIT(CF,(*eard & mask)); 377 *eard^=mask; 378 } else { 379 GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; 380 Bit32u old=LoadMd(eaa); 381 SETFLAGBIT(CF,(old & mask)); 382 SaveMd(eaa,old ^ mask); 383 } 384 break; 385 } 386 CASE_0F_D(0xbc) /* BSF Gd,Ed */ 387 { 388 GetRMrd; 389 Bit32u result,value; 390 if (rm >= 0xc0) { GetEArd; value=*eard; } 391 else { GetEAa; value=LoadMd(eaa); } 392 if (value==0) { 393 SETFLAGBIT(ZF,true); 394 } else { 395 result = 0; 396 while ((value & 0x01)==0) { result++; value>>=1; } 397 SETFLAGBIT(ZF,false); 398 *rmrd = result; 399 } 400 lflags.type=t_UNKNOWN; 401 break; 402 } 403 CASE_0F_D(0xbd) /* BSR Gd,Ed */ 404 { 405 GetRMrd; 406 Bit32u result,value; 407 if (rm >= 0xc0) { GetEArd; value=*eard; } 408 else { GetEAa; value=LoadMd(eaa); } 409 if (value==0) { 410 SETFLAGBIT(ZF,true); 411 } else { 412 result = 31; // Operandsize-1 413 while ((value & 0x80000000)==0) { result--; value<<=1; } 414 SETFLAGBIT(ZF,false); 415 *rmrd = result; 416 } 417 lflags.type=t_UNKNOWN; 418 break; 419 } 420 CASE_0F_D(0xbe) /* MOVSX Gd,Eb */ 421 { 422 GetRMrd; 423 if (rm >= 0xc0 ) {GetEArb;*rmrd=*(Bit8s *)earb;} 424 else {GetEAa;*rmrd=LoadMbs(eaa);} 425 break; 426 } 427 CASE_0F_D(0xbf) /* MOVSX Gd,Ew */ 428 { 429 GetRMrd; 430 if (rm >= 0xc0 ) {GetEArw;*rmrd=*(Bit16s *)earw;} 431 else {GetEAa;*rmrd=LoadMws(eaa);} 432 break; 433 } 434 CASE_0F_D(0xc1) /* XADD Gd,Ed */ 435 { 436 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 437 GetRMrd;Bit32u oldrmrd=*rmrd; 438 if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard+=oldrmrd;} 439 else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,LoadMd(eaa)+oldrmrd);} 440 break; 441 } 442 CASE_0F_D(0xc8) /* BSWAP EAX */ 443 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 444 BSWAPD(reg_eax);break; 445 CASE_0F_D(0xc9) /* BSWAP ECX */ 446 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 447 BSWAPD(reg_ecx);break; 448 CASE_0F_D(0xca) /* BSWAP EDX */ 449 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 450 BSWAPD(reg_edx);break; 451 CASE_0F_D(0xcb) /* BSWAP EBX */ 452 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 453 BSWAPD(reg_ebx);break; 454 CASE_0F_D(0xcc) /* BSWAP ESP */ 455 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 456 BSWAPD(reg_esp);break; 457 CASE_0F_D(0xcd) /* BSWAP EBP */ 458 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 459 BSWAPD(reg_ebp);break; 460 CASE_0F_D(0xce) /* BSWAP ESI */ 461 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 462 BSWAPD(reg_esi);break; 463 CASE_0F_D(0xcf) /* BSWAP EDI */ 464 if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode; 465 BSWAPD(reg_edi);break; 466