cpu.cpp
1 #include <stdio.h> 2 #include <stdint.h> 3 //#include <SPIRAM24.h> 4 //#include <avr/progmem.h> 5 #include "emu.h" 6 #include "rom.h" 7 8 extern void portout(uint16_t portnum, uint16_t value); 9 extern uint16_t portin(uint16_t portnum); 10 11 extern void readdisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount); 12 extern void insertdisk(); 13 14 extern void doirq(uint8_t irqnum); 15 extern uint8_t nextintr(); 16 extern struct structpic { 17 uint8_t imr; //mask register 18 uint8_t irr; //request register 19 uint8_t isr; //service register 20 uint8_t icwstep; //used during initialization to keep track of which ICW we're at 21 uint8_t icw[5]; 22 uint8_t intoffset; //interrupt vector offset 23 uint8_t priority; //which IRQ has highest priority 24 uint8_t autoeoi; //automatic EOI mode 25 uint8_t readmode; //remember what to return on read register from OCW3 26 uint8_t enabled; 27 } i8259; 28 29 extern uint8_t curkey; 30 void intcall86(uint8_t intnum); 31 32 uint64_t curtimer, lasttimer, timerfreq; 33 34 char *biosfile = NULL; 35 uint8_t byteregtable[8] = { regal, regcl, regdl, regbl, regah, regch, regdh, regbh }; 36 37 uint8_t parity[0x100]; 38 39 _bytewordregs_ regs; 40 41 uint16_t segregs[6]; 42 uint8_t opcode, segoverride, reptype, bootdrive, hdcount = 0; 43 uint16_t savecs, saveip, ip, useseg, oldsp; 44 uint8_t tempcf, oldcf, cf, pf, af, zf, sf, tf, ifl, df, of, nt, iopriv, mode, reg, rm, msw = 0; 45 uint16_t oper1, oper2, res16, disp16, temp16, dummy, stacksize, frametemp; 46 uint8_t oper1b, oper2b, res8, disp8, temp8, nestlev, addrbyte; 47 uint16_t cr0 = 0, cr1 = 0, cr2 = 0, cr3 = 0; 48 uint32_t ldtr = 0, gdtr = 0, gdtlimit = 0, idtr = 0, idtlimit = 0; 49 uint32_t temp1, temp2, temp3, temp4, temp5, temp32, tempaddr32, ea; 50 int32_t result, speed = 0; 51 uint32_t totalexec; 52 uint32_t ips[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 53 uint16_t *tempwordptr; 54 55 uint8_t vidmode, cgabg, blankattr, vidgfxmode, vidcolor; 56 uint16_t cursx, cursy, cols, rows, vgapage, cursorposition, cursorvisible; 57 uint8_t updatedscreen, port3da, port6, portout16; 58 //uint16_t VGA_SC[0xFF], VGA_CRTC[0xFF], VGA_ATTR[0xFF], VGA_GC[0xFF]; 59 uint32_t videobase, textbase, x, y; 60 61 uint8_t debugmode, showcsip, verbose, mouseemu; 62 63 64 extern uint8_t * RAM; 65 extern uint8_t * LORAM; //LORAM[]; 66 67 void write86(uint32_t addr32, uint8_t value) { 68 if (addr32 < NATIVE_RAM) { 69 LORAM[addr32] = value; 70 return; 71 } 72 else if (addr32 < RAM_SIZE) { 73 RAM[addr32] = value; 74 return; 75 } 76 else if ((addr32 >= 0xB8000) && (addr32 < 0xC0000)) { 77 VRAM_write(addr32 - 0xB8000UL, value); 78 } 79 } 80 81 #define writew86(addr32,value) {write86((addr32),(uint8_t)(value));write86((addr32)+1,(uint8_t)((uint16_t)(value)>>8));} 82 83 uint8_t read86(uint32_t addr32) { 84 if (addr32 < NATIVE_RAM) { 85 switch (addr32) { //some hardcoded values for the BIOS data area 86 case 0x410: //0040:0010 is the equipment word 87 #ifdef VGA 88 return (0x41); //video type (0x41 is VGA/EGA, 0x61 is CGA, 0x31 = MDA) 89 #else 90 return (0x61); //video type (0x41 is VGA/EGA, 0x61 is CGA, 0x31 = MDA) 91 #endif 92 case 0x475: //hard drive count 93 return (hdcount); 94 default: 95 return LORAM[addr32]; 96 } 97 } 98 else if (addr32 < RAM_SIZE) { 99 return RAM[addr32]; 100 } 101 else if ((addr32 >= 0xB8000) && (addr32 < 0xC0000)) { 102 addr32 -= 0xB8000UL; 103 return VRAM_read(addr32); 104 } 105 else if (addr32 >= 0xFE000UL) { 106 addr32 -= 0xFE000UL; 107 return ROM_READ(BIOS, addr32); //BIOS[addr32]; 108 } 109 else if ((addr32 >= 0xD0000) && (addr32 < 0xD0640)) { 110 return net_read_ram(addr32 - 0xD0000); 111 } 112 else if ((addr32 >= 0xE0000) && (addr32 < 0xE0006)) { 113 return net_mac[addr32 - 0xE0000]; 114 } 115 #ifdef INCLUDE_ROM_BASIC 116 else if ((addr32 >= 0xF6000UL) && (addr32 < 0xFA000UL)) { 117 addr32 -= 0xF6000UL; 118 return ROM_READ(BASICL, addr32); //BASICL[addr32]; 119 } else if ((addr32 >= 0xFA000UL) && (addr32 < 0xFE000UL)) { 120 addr32 -= 0xFA000UL; 121 return ROM_READ(BASICH, addr32); //BASICH[addr32]; 122 } 123 #endif 124 else return 0; 125 } 126 127 128 129 #define readw86(addr32) ((uint16_t)read86((addr32))|((uint16_t)read86((addr32)+1)<<8)) 130 131 //inline void flag_szp8(uint8_t value) { 132 #define flag_szp8(value) {\ 133 if (!(value)) zf = 1; else zf = 0;\ 134 if ((value) & 0x80) sf = 1; else sf = 0;\ 135 pf = parity[value];\ 136 } 137 138 //inline void flag_szp16(uint16_t value) { 139 #define flag_szp16(value) {\ 140 if (!(value)) zf = 1; else zf = 0;\ 141 if (value & 0x8000) sf = 1; else sf = 0;\ 142 pf = parity[(uint8_t)value];\ 143 } 144 145 //inline void flag_log8(uint8_t value) { 146 #define flag_log8(value) {\ 147 flag_szp8(value);\ 148 cf = 0; of = 0;\ 149 } 150 151 //inline void flag_log16(uint16_t value) { 152 #define flag_log16(value) {\ 153 flag_szp16(value);\ 154 cf = 0; of = 0;\ 155 } 156 157 //inline void flag_adc8(uint8_t v1, uint8_t v2, uint8_t v3) { //v1 = destination operand, v2 = source operand, v3 = carry flag 158 #define flag_adc8(v1, v2, v3) {\ 159 uint16_t dst;\ 160 dst = (uint16_t)(v1) + (uint16_t)(v2) + (uint16_t)(v3);\ 161 flag_szp8((uint8_t)dst);\ 162 if (((dst ^ (v1)) & (dst ^ (v2)) & 0x80) == 0x80) of = 1; else of = 0;\ 163 if (dst & 0xFF00) cf = 1; else cf = 0;\ 164 if ((((v1) ^ (v2) ^ dst) & 0x10) == 0x10) af = 1; else af = 0;\ 165 } 166 167 //inline void flag_adc16(uint16_t v1, uint16_t v2, uint16_t v3) { //v1 = destination operand, v2 = source operand, v3 = carry flag 168 #define flag_adc16(v1, v2, v3) {\ 169 uint32_t dst;\ 170 dst = (uint32_t)(v1) + (uint32_t)(v2) + (uint32_t)(v3);\ 171 flag_szp16((uint16_t)dst);\ 172 if ((((dst ^ (v1)) & (dst ^ (v2))) & 0x8000) == 0x8000) of = 1; else of = 0;\ 173 if (dst & 0xFFFF0000UL) cf = 1; else cf = 0;\ 174 if ((((v1) ^ (v2) ^ dst) & 0x10) == 0x10) af = 1; else af = 0;\ 175 } 176 177 //inline void flag_add8(uint8_t v1, uint8_t v2) { //v1 = destination operand, v2 = source operand 178 #define flag_add8(v1, v2) {\ 179 uint16_t dst;\ 180 dst = (uint16_t)(v1) + (uint16_t)(v2);\ 181 flag_szp8((uint8_t)dst);\ 182 if (dst & 0xFF00) cf = 1; else cf = 0;\ 183 if (((dst ^ (v1)) & (dst ^ (v2)) & 0x80) == 0x80) of = 1; else of = 0;\ 184 if ((((v1) ^ (v2) ^ dst) & 0x10) == 0x10) af = 1; else af = 0;\ 185 } 186 187 //inline void flag_add16(uint16_t v1, uint16_t v2) { //v1 = destination operand, v2 = source operand 188 #define flag_add16(v1, v2) {\ 189 uint32_t dst;\ 190 dst = (uint32_t)(v1) + (uint32_t)(v2);\ 191 flag_szp16((uint16_t)dst);\ 192 if (dst & 0xFFFF0000UL) cf = 1; else cf = 0;\ 193 if (((dst ^ (v1)) & (dst ^ (v2)) & 0x8000) == 0x8000) of = 1; else of = 0;\ 194 if ((((v1) ^ (v2) ^ dst) & 0x10) == 0x10) af = 1; else af = 0;\ 195 } 196 197 //inline void flag_sbb8(uint8_t v1, uint8_t v2, uint8_t v3) { //v1 = destination operand, v2 = source operand, v3 = carry flag 198 #define flag_sbb8(v1, v2, v3) {\ 199 uint16_t dst;\ 200 uint16_t newv2;\ 201 newv2 = (uint16_t)(v2) + (uint16_t)(v3);\ 202 dst = (uint16_t)(v1) - (uint16_t)newv2;\ 203 flag_szp8((uint8_t)dst);\ 204 if (dst & 0xFF00) cf = 1; else cf = 0;\ 205 if ((dst ^ (v1)) & ((v1) ^ newv2) & 0x80) of = 1; else of = 0;\ 206 if (((v1) ^ newv2 ^ dst) & 0x10) af = 1; else af = 0;\ 207 } 208 209 //inline void flag_sbb16(uint16_t v1, uint16_t v2, uint16_t v3) { //v1 = destination operand, v2 = source operand, v3 = carry flag 210 #define flag_sbb16(v1, v2, v3){\ 211 uint32_t dst;\ 212 uint32_t newv2;\ 213 newv2 = (uint32_t)(v2) + (uint32_t)(v3);\ 214 dst = (uint32_t)v1 - newv2;\ 215 flag_szp16((uint16_t)dst);\ 216 if (dst & 0xFFFF0000UL) cf = 1; else cf = 0;\ 217 if ((dst ^ (v1)) & (v1 ^ newv2) & 0x8000) of = 1; else of = 0;\ 218 if (((v1) ^ newv2 ^ dst) & 0x10) af = 1; else af = 0;\ 219 } 220 221 //inline void flag_sub8(uint8_t v1, uint8_t v2) { //v1 = destination operand, v2 = source operand 222 #define flag_sub8(v1, v2) {\ 223 uint16_t dst;\ 224 dst = (uint16_t)(v1) - (uint16_t)(v2);\ 225 flag_szp8((uint8_t)dst);\ 226 if (dst & 0xFF00) cf = 1; else cf = 0;\ 227 if ((dst ^ (v1)) & ((v1) ^ (v2)) & 0x80) of = 1; else of = 0;\ 228 if (((v1) ^ (v2) ^ dst) & 0x10) af = 1; else af = 0;\ 229 } 230 231 //inline void flag_sub16(uint16_t v1, uint16_t v2) { //v1 = destination operand, v2 = source operand 232 #define flag_sub16(v1, v2) {\ 233 uint32_t dst;\ 234 dst = (uint32_t)(v1) - (uint32_t)(v2);\ 235 flag_szp16((uint16_t)dst);\ 236 if (dst & 0xFFFF0000UL) cf = 1; else cf = 0;\ 237 if ((dst ^ (v1)) & ((v1) ^ (v2)) & 0x8000) of = 1; else of = 0;\ 238 if (((v1) ^ (v2) ^ dst) & 0x10) af = 1; else af = 0;\ 239 } 240 241 //inline void op_adc8() { 242 #define op_adc8() {\ 243 res8 = oper1b + oper2b + cf;\ 244 flag_adc8(oper1b, oper2b, cf);\ 245 } 246 247 //inline void op_adc16() { 248 #define op_adc16() {\ 249 res16 = oper1 + oper2 + cf;\ 250 flag_adc16(oper1, oper2, cf);\ 251 } 252 253 //inline void op_add8() { 254 #define op_add8() {\ 255 res8 = oper1b + oper2b;\ 256 flag_add8(oper1b, oper2b);\ 257 } 258 259 //inline void op_add16() { 260 #define op_add16() {\ 261 res16 = oper1 + oper2;\ 262 flag_add16(oper1, oper2);\ 263 } 264 265 //inline void op_and8() { 266 #define op_and8() {\ 267 res8 = oper1b & oper2b;\ 268 flag_log8(res8);\ 269 } 270 271 //inline void op_and16() { 272 #define op_and16() {\ 273 res16 = oper1 & oper2;\ 274 flag_log16(res16);\ 275 } 276 277 //inline void op_or8() { 278 #define op_or8() {\ 279 res8 = oper1b | oper2b;\ 280 flag_log8(res8);\ 281 } 282 283 //inline void op_or16() { 284 #define op_or16() {\ 285 res16 = oper1 | oper2;\ 286 flag_log16(res16);\ 287 } 288 289 //inline void op_xor8() { 290 #define op_xor8() {\ 291 res8 = oper1b ^ oper2b;\ 292 flag_log8(res8);\ 293 } 294 295 //inline void op_xor16() { 296 #define op_xor16() {\ 297 res16 = oper1 ^ oper2;\ 298 flag_log16(res16);\ 299 } 300 301 //inline void op_sub8() { 302 #define op_sub8() {\ 303 res8 = oper1b - oper2b;\ 304 flag_sub8(oper1b, oper2b);\ 305 } 306 307 //inline void op_sub16() { 308 #define op_sub16() {\ 309 res16 = oper1 - oper2;\ 310 flag_sub16(oper1, oper2);\ 311 } 312 313 //inline void op_sbb8() { 314 #define op_sbb8() {\ 315 res8 = oper1b - (oper2b + cf);\ 316 flag_sbb8(oper1b, oper2b, cf);\ 317 } 318 319 //inline void op_sbb16() { 320 #define op_sbb16() {\ 321 res16 = oper1 - (oper2 + cf);\ 322 flag_sbb16(oper1, oper2, cf);\ 323 } 324 325 //inline void modregrm() { 326 #define modregrm() {\ 327 addrbyte = getmem8(segregs[regcs], ip); StepIP(1);\ 328 mode = addrbyte >> 6;\ 329 reg = (addrbyte >> 3) & 7;\ 330 rm = addrbyte & 7;\ 331 switch (mode) {\ 332 case 0:\ 333 if (rm == 6) {\ 334 disp16 = getmem16(segregs[regcs], ip);\ 335 StepIP(2);\ 336 }\ 337 if (((rm == 2) || (rm == 3)) && !segoverride) useseg = segregs[regss]; break;\ 338 case 1:\ 339 disp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1);\ 340 if (((rm == 2) || (rm == 3) || (rm == 6)) && !segoverride) useseg = segregs[regss]; break;\ 341 case 2:\ 342 disp16 = getmem16(segregs[regcs], ip); StepIP(2);\ 343 if (((rm == 2) || (rm == 3) || (rm == 6)) && !segoverride) useseg = segregs[regss]; break;\ 344 default:\ 345 disp8 = 0; disp16 = 0;\ 346 }\ 347 if (mode < 3) getea(rm);\ 348 } 349 350 //inline void getea(uint8_t rmval) { 351 #define getea(rmval) {\ 352 uint32_t tempea;\ 353 tempea = 0;\ 354 switch (mode) {\ 355 case 0:\ 356 switch (rmval) {\ 357 case 0: tempea = regs.wordregs[regbx] + regs.wordregs[regsi]; break;\ 358 case 1: tempea = regs.wordregs[regbx] + regs.wordregs[regdi]; break;\ 359 case 2: tempea = regs.wordregs[regbp] + regs.wordregs[regsi]; break;\ 360 case 3: tempea = regs.wordregs[regbp] + regs.wordregs[regdi]; break;\ 361 case 4: tempea = regs.wordregs[regsi]; break;\ 362 case 5: tempea = regs.wordregs[regdi]; break;\ 363 case 6: tempea = disp16; break;\ 364 case 7: tempea = regs.wordregs[regbx]; break;\ 365 } break;\ 366 case 1: case 2:\ 367 switch (rmval) {\ 368 case 0: tempea = regs.wordregs[regbx] + regs.wordregs[regsi] + disp16; break;\ 369 case 1: tempea = regs.wordregs[regbx] + regs.wordregs[regdi] + disp16; break;\ 370 case 2: tempea = regs.wordregs[regbp] + regs.wordregs[regsi] + disp16; break;\ 371 case 3: tempea = regs.wordregs[regbp] + regs.wordregs[regdi] + disp16; break;\ 372 case 4: tempea = regs.wordregs[regsi] + disp16; break;\ 373 case 5: tempea = regs.wordregs[regdi] + disp16; break;\ 374 case 6: tempea = regs.wordregs[regbp] + disp16; break;\ 375 case 7: tempea = regs.wordregs[regbx] + disp16; break;\ 376 } break;\ 377 }\ 378 ea = useseg;\ 379 ea <<= 4;\ 380 ea += (tempea & 0xFFFF);\ 381 } 382 383 inline void push(uint16_t pushval) { 384 putreg16(regsp, getreg16(regsp) - 2); 385 //printf(" %04X:%04X PUSH\n", segregs[regss], getreg16(regsp)); 386 putmem16(segregs[regss], getreg16(regsp), pushval); 387 } 388 389 inline uint16_t pop() { 390 uint16_t tempval; 391 //printf(" %04X:%04X POP\n", segregs[regss], getreg16(regsp)); 392 tempval = getmem16(segregs[regss], getreg16(regsp)); 393 putreg16(regsp, getreg16(regsp) + 2); 394 return (tempval); 395 } 396 397 void reset86() { 398 uint16_t i, cnt, bitcount; 399 segregs[regcs] = 0xFFFF; 400 ip = 0x0000; 401 segregs[regss] = 0x0000; 402 regs.wordregs[regsp] = 0xFFFE; 403 404 //generate parity lookup table 405 for (i = 0; i < 256; i++) { 406 bitcount = 0; 407 for (cnt = 0; cnt < 8; cnt++) 408 bitcount += ((i >> cnt) & 1); 409 if (bitcount & 1) parity[i] = 0; else parity[i] = 1; 410 } 411 } 412 413 /*inline uint16_t readrm16(uint8_t rmval) { 414 if (mode < 3) { 415 getea(rmval); 416 return (read86(ea) | ((uint16_t)read86(ea + 1) << 8)); 417 } else { 418 return (getreg16(rmval)); 419 } 420 }*/ 421 422 #define readrm16(rmval) ( (mode < 3) ? (read86(ea) | ((uint16_t)read86(ea + 1) << 8)) : (getreg16(rmval)) ) 423 424 /*inline uint8_t readrm8(uint8_t rmval) { 425 if (mode < 3) { 426 //getea(rmval); 427 return (read86(ea)); 428 } else { 429 return (getreg8(rmval)); 430 } 431 }*/ 432 433 #define readrm8(rmval) ( (mode < 3) ? read86(ea) : getreg8(rmval) ) 434 435 inline void writerm16(uint8_t rmval, uint16_t value) { 436 //#define writerm16(rmval, value) { 437 if (mode < 3) {\ 438 /*getea(rmval);*/\ 439 write86(ea, value & 0xFF);\ 440 write86(ea + 1, value >> 8);\ 441 } else {\ 442 putreg16(rmval, value);\ 443 }\ 444 } 445 446 inline void writerm8(uint8_t rmval, uint8_t value) { 447 //#define writerm8(rmval, value) { 448 if (mode < 3) {\ 449 /*getea(rmval);*/\ 450 write86(ea, value);\ 451 } else {\ 452 putreg8(rmval, value);\ 453 }\ 454 } 455 456 inline uint8_t op_grp2_8(uint8_t cnt) { 457 uint16_t s, oldcf, msb; 458 uint8_t shift; 459 s = oper1b; 460 oldcf = cf; 461 switch (reg) { 462 case 0: //ROL r/m8 463 for (shift = 1; shift <= cnt; shift++) { 464 if (s & 0x80) cf = 1; else cf = 0; 465 s = s << 1; 466 s = s | cf; 467 } 468 if (cnt == 1) of = cf ^ ((s >> 7) & 1); 469 break; 470 471 case 1: //ROR r/m8 472 for (shift = 1; shift <= cnt; shift++) { 473 cf = s & 1; 474 s = (s >> 1) | (cf << 7); 475 } 476 if (cnt == 1) of = (s >> 7) ^ ((s >> 6) & 1); 477 break; 478 479 case 2: //RCL r/m8 480 for (shift = 1; shift <= cnt; shift++) { 481 oldcf = cf; 482 if (s & 0x80) cf = 1; else cf = 0; 483 s = s << 1; 484 s = s | oldcf; 485 } 486 if (cnt == 1) of = cf ^ ((s >> 7) & 1); 487 break; 488 489 case 3: //RCR r/m8 490 for (shift = 1; shift <= cnt; shift++) { 491 oldcf = cf; 492 cf = s & 1; 493 s = (s >> 1) | (oldcf << 7); 494 } 495 if (cnt == 1) of = (s >> 7) ^ ((s >> 6) & 1); 496 break; 497 498 case 4: case 6: //SHL r/m8 499 for (shift = 1; shift <= cnt; shift++) { 500 if (s & 0x80) cf = 1; else cf = 0; 501 s = (s << 1) & 0xFF; 502 } 503 if ((cnt == 1) && (cf == (s >> 7))) of = 0; else of = 1; 504 flag_szp8((uint8_t)s); break; 505 506 case 5: //SHR r/m8 507 if ((cnt == 1) && (s & 0x80)) of = 1; else of = 0; 508 for (shift = 1; shift <= cnt; shift++) { 509 cf = s & 1; 510 s = s >> 1; 511 } 512 flag_szp8((uint8_t)s); break; 513 514 case 7: //SAR r/m8 515 for (shift = 1; shift <= cnt; shift++) { 516 msb = s & 0x80; 517 cf = s & 1; 518 s = (s >> 1) | msb; 519 } 520 of = 0; 521 flag_szp8((uint8_t)s); break; 522 523 } 524 return (s & 0xFF); 525 } 526 527 inline uint16_t op_grp2_16(uint8_t cnt) { 528 uint32_t s, oldcf, msb; 529 uint8_t shift; 530 s = oper1; 531 oldcf = cf; 532 switch (reg) { 533 case 0: //ROL r/m8 534 for (shift = 1; shift <= cnt; shift++) { 535 if (s & 0x8000) cf = 1; else cf = 0; 536 s = s << 1; 537 s = s | cf; 538 } 539 if (cnt == 1) of = cf ^ ((s >> 15) & 1); 540 break; 541 542 case 1: //ROR r/m8 543 for (shift = 1; shift <= cnt; shift++) { 544 cf = s & 1; 545 s = (s >> 1) | (cf << 15); 546 } 547 if (cnt == 1) of = (s >> 15) ^ ((s >> 14) & 1); 548 break; 549 550 case 2: //RCL r/m8 551 for (shift = 1; shift <= cnt; shift++) { 552 oldcf = cf; 553 if (s & 0x8000) cf = 1; else cf = 0; 554 s = s << 1; 555 s = s | oldcf; 556 } 557 if (cnt == 1) of = cf ^ ((s >> 15) & 1); 558 break; 559 560 case 3: //RCR r/m8 561 for (shift = 1; shift <= cnt; shift++) { 562 oldcf = cf; 563 cf = s & 1; 564 s = (s >> 1) | (oldcf << 15); 565 } 566 if (cnt == 1) of = (s >> 15) ^ ((s >> 14) & 1); 567 break; 568 569 case 4: case 6: //SHL r/m8 570 for (shift = 1; shift <= cnt; shift++) { 571 if (s & 0x8000) cf = 1; else cf = 0; 572 s = (uint16_t)(s << 1); 573 } 574 if ((cnt == 1) && (cf == (s >> 15))) of = 0; else of = 1; 575 flag_szp16((uint16_t)s); break; 576 577 case 5: //SHR r/m8 578 if ((cnt == 1) && (s & 0x8000)) of = 1; else of = 0; 579 for (shift = 1; shift <= cnt; shift++) { 580 cf = s & 1; 581 s = s >> 1; 582 } 583 flag_szp16((uint16_t)s); break; 584 585 case 7: //SAR r/m8 586 for (shift = 1; shift <= cnt; shift++) { 587 msb = s & 0x8000; 588 cf = s & 1; 589 s = (s >> 1) | msb; 590 } 591 of = 0; 592 flag_szp16((uint16_t)s); break; 593 594 } 595 return ((uint16_t)s); 596 } 597 598 inline void op_div8(uint16_t valdiv, uint8_t divisor) { 599 if (divisor == 0) { 600 intcall86(0); 601 return; 602 } 603 if ((valdiv / (uint16_t)divisor) > 0xFF) { 604 intcall86(0); 605 return; 606 } 607 regs.byteregs[regah] = valdiv % (uint16_t)divisor; 608 regs.byteregs[regal] = valdiv / (uint16_t)divisor; 609 } 610 611 inline void op_idiv8(uint16_t valdiv, uint8_t divisor) { 612 uint16_t s1, s2, d1, d2, sign; 613 if (divisor == 0) { 614 intcall86(0); 615 return; 616 } 617 s1 = valdiv; 618 s2 = divisor; 619 sign = (((s1 ^ s2) & 0x8000) != 0); 620 s1 = (s1 < 0x8000) ? s1 : (uint16_t)(~s1 + 1); 621 s2 = (s2 < 0x8000) ? s2 : (uint16_t)(~s2 + 1); 622 d1 = s1 / s2; 623 d2 = s1 % s2; 624 if (d1 & 0xFF00) { 625 intcall86(0); 626 return; 627 } 628 if (sign) { 629 d1 = (~d1 + 1) & 0xff; 630 d2 = (~d2 + 1) & 0xff; 631 } 632 regs.byteregs[regah] = d2; 633 regs.byteregs[regal] = d1; 634 } 635 636 inline void op_grp3_8() { 637 oper1 = signext(oper1b); oper2 = signext(oper2b); 638 switch (reg) { 639 case 0: case 1: //TEST 640 flag_log8(oper1b & getmem8(segregs[regcs], ip)); StepIP(1); 641 break; 642 643 case 2: //NOT 644 res8 = ~oper1b; break; 645 646 case 3: //NEG 647 res8 = (~oper1b) + 1; 648 flag_sub8(0, oper1b); 649 if (res8 == 0) cf = 0; else cf = 1; 650 break; 651 652 case 4: //MUL 653 temp1 = (uint32_t)oper1b * (uint32_t)regs.byteregs[regal]; 654 putreg16(regax, (uint16_t)temp1); 655 flag_szp8((uint8_t)temp1); 656 if (regs.byteregs[regah]) { 657 cf = 1; 658 of = 1; 659 } else { 660 cf = 0; 661 of = 0; 662 } 663 break; 664 665 case 5: //IMUL 666 oper1 = signext(oper1b); 667 temp1 = signext(regs.byteregs[regal]); 668 temp2 = oper1; 669 if ((temp1 & 0x80) == 0x80) temp1 = temp1 | 0xFFFFFF00UL; 670 if ((temp2 & 0x80) == 0x80) temp2 = temp2 | 0xFFFFFF00UL; 671 temp3 = (uint16_t)(temp1 * temp2); 672 putreg16(regax, (uint16_t)temp3); 673 if (regs.byteregs[regah]) { 674 cf = 1; 675 of = 1; 676 } else { 677 cf = 0; 678 of = 0; 679 } 680 break; 681 682 case 6: //DIV 683 op_div8(getreg16(regax), oper1b); 684 break; 685 686 case 7: //IDIV 687 op_idiv8(getreg16(regax), oper1b); 688 break; 689 } 690 } 691 692 void op_div16(uint32_t valdiv, uint16_t divisor) { 693 if (divisor == 0) { 694 intcall86(0); 695 return; 696 } 697 if ((valdiv / (uint32_t)divisor) > 0xFFFF) { 698 intcall86(0); 699 return; 700 } 701 putreg16(regdx, valdiv % (uint32_t)divisor); 702 putreg16(regax, valdiv / (uint32_t)divisor); 703 } 704 705 void op_idiv16(uint32_t valdiv, uint16_t divisor) { 706 uint32_t d1, d2, s1, s2, sign; 707 if (divisor == 0) { 708 intcall86(0); 709 return; 710 } 711 s1 = valdiv; 712 s2 = divisor; 713 s2 = (s2 & 0x8000) ? (s2 | 0xffff0000UL) : s2; 714 sign = (((s1 ^ s2) & 0x80000000UL) != 0); 715 s1 = (s1 < 0x80000000UL) ? s1 : ((~s1 + 1) & 0xffffffffUL); 716 s2 = (s2 < 0x80000000UL) ? s2 : ((~s2 + 1) & 0xffffffffUL); 717 d1 = s1 / s2; 718 d2 = s1 % s2; 719 if (d1 & 0xFFFF0000UL) { 720 intcall86(0); 721 return; 722 } 723 if (sign) { 724 d1 = (uint16_t)(~d1 + 1); 725 d2 = (uint16_t)(~d2 + 1); 726 } 727 putreg16(regax, d1); 728 putreg16(regdx, d2); 729 } 730 731 inline void op_grp3_16() { 732 switch (reg) { 733 case 0: case 1: //TEST 734 flag_log16(oper1 & getmem16(segregs[regcs], ip)); StepIP(2); break; 735 case 2: //NOT 736 res16 = ~oper1; break; 737 case 3: //NEG 738 res16 = (~oper1) + 1; 739 flag_sub16(0, oper1); 740 if (res16) cf = 1; else cf = 0; 741 break; 742 case 4: //MUL 743 temp1 = (uint32_t)oper1 * (uint32_t)getreg16(regax); 744 putreg16(regax, (uint16_t)temp1); 745 putreg16(regdx, temp1 >> 16); 746 flag_szp16((uint16_t)temp1); 747 if (getreg16(regdx)) { 748 cf = 1; 749 of = 1; 750 } else { 751 cf = 0; 752 of = 0; 753 } 754 break; 755 case 5: //IMUL 756 temp1 = getreg16(regax); 757 temp2 = oper1; 758 if (temp1 & 0x8000) temp1 |= 0xFFFF0000UL; 759 if (temp2 & 0x8000) temp2 |= 0xFFFF0000UL; 760 temp3 = temp1 * temp2; 761 putreg16(regax, (uint16_t)temp3); //into register ax 762 putreg16(regdx, temp3 >> 16); //into register dx 763 if (getreg16(regdx)) { 764 cf = 1; 765 of = 1; 766 } else { 767 cf = 0; 768 of = 0; 769 } 770 break; 771 case 6: //DIV 772 op_div16(((uint32_t)getreg16(regdx) << 16) + (uint32_t)getreg16(regax), oper1); break; 773 case 7: //DIV 774 op_idiv16(((uint32_t)getreg16(regdx) << 16) + (uint32_t)getreg16(regax), oper1); break; 775 } 776 } 777 778 //inline void op_grp5() { 779 #define op_grp5() {\ 780 switch (reg) {\ 781 case 0: /*INC Ev*/\ 782 oper2 = 1;\ 783 tempcf = cf;\ 784 op_add16();\ 785 cf = tempcf;\ 786 writerm16(rm, res16); break;\ 787 case 1: /*DEC Ev*/\ 788 oper2 = 1;\ 789 tempcf = cf;\ 790 op_sub16();\ 791 cf = tempcf;\ 792 writerm16(rm, res16); break;\ 793 case 2: /*CALL Ev*/\ 794 push(ip);\ 795 ip = oper1; break;\ 796 case 3: /*CALL Mp*/\ 797 push(segregs[regcs]); push(ip);\ 798 /*getea(rm);*/\ 799 ip = (uint16_t)read86(ea) + ((uint16_t)read86(ea + 1) << 8);\ 800 segregs[regcs] = (uint16_t)read86(ea + 2) + ((uint16_t)read86(ea + 3) << 8); break;\ 801 case 4: /*JMP Ev*/\ 802 ip = oper1; break;\ 803 case 5: /*JMP Mp*/\ 804 /*getea(rm);*/\ 805 ip = (uint16_t)read86(ea) + ((uint16_t)read86(ea + 1) << 8);\ 806 segregs[regcs] = (uint16_t)read86(ea + 2) + ((uint16_t)read86(ea + 3) << 8); break;\ 807 case 6: /*PUSH Ev*/\ 808 push(oper1); break;\ 809 }\ 810 } 811 812 uint8_t didintr = 0; 813 814 void intcall86(uint8_t intnum) { 815 didintr = 1; 816 817 switch (intnum) { 818 case 0x10: //video services 819 if (regs.byteregs[regah] == 0) { //video mode set 820 #ifdef ADVANCED_CLIENT 821 Serial.write(0xFF); 822 Serial.write(0x02); 823 Serial.write(regs.byteregs[regal]); 824 Serial.write(regs.byteregs[regal]); //duplicate for checksum 825 Serial.write(0xFE); 826 Serial.write(0x02); 827 #endif 828 #ifdef USE_DISPLAY 829 if (vidmode != regs.byteregs[regal]) clear_display(); 830 palettereset(); 831 #endif 832 vidmode = regs.byteregs[regal]; 833 //Serial.print("vidmode = "); Serial.println(vidmode); 834 } 835 break; 836 case 0x13: //disk services 837 diskhandler(); 838 return; 839 case 0x19: //bootstrap 840 //Serial.println("Bootstrap!"); 841 if (bootdrive < 255) { //read first sector of boot drive into 07C0:0000 and execute it 842 regs.byteregs[regdl] = bootdrive; 843 readdisk((bootdrive & 0x80) ? bootdrive - 126 : bootdrive, 0x07C0, 0x0000, 0, 1, 0, 1); 844 segregs[regcs] = 0x0000; ip = 0x7C00; 845 } else { 846 segregs[regcs] = 0xF600; //start ROM BASIC at bootstrap if requested 847 ip = 0x0000; 848 } 849 return; 850 case 0xFC: 851 net_handler(); 852 return; 853 default: 854 break; 855 } 856 857 push(makeflagsword()); 858 push(segregs[regcs]); 859 push(ip); 860 segregs[regcs] = getmem16(0, ((uint16_t)intnum << 2) + 2); 861 ip = getmem16(0, (uint16_t)intnum << 2); 862 ifl = 0; 863 tf = 0; 864 } 865 866 uint64_t frametimer = 0, didwhen = 0, didticks = 0; 867 uint32_t makeupticks = 0; 868 extern float timercomp; 869 uint64_t timerticks = 0, realticks = 0; 870 uint64_t lastcountertimer = 0, counterticks = 10000; 871 872 #ifdef PROFILING 873 uint32_t startmicros, endmicros; 874 uint32_t instrtime[0x100]; 875 #endif 876 877 #ifdef PS2_KEYBOARD 878 extern uint8_t kbloop; 879 #endif 880 881 extern volatile uint8_t timerTick; 882 883 void exec86(uint32_t execloops) { 884 uint32_t loopcount; 885 uint8_t docontinue; 886 static uint16_t firstip, trap_toggle = 0; 887 888 for (loopcount = 0; loopcount < execloops; loopcount++) { 889 /*Serial.print(segregs[regcs], HEX); 890 Serial.write(':'); 891 Serial.println(ip, HEX);*/ 892 #ifdef PS2_KEYBOARD 893 if (kbloop) { 894 uint32_t msnow; 895 msnow = micros(); 896 while ((micros() - msnow) < 20000) { } 897 kbloop = 0; 898 ps2poll(); 899 } 900 #endif 901 902 if (timerTick) { 903 //printf("isr\n"); 904 timerTick = 0; 905 doirq(0); 906 } 907 908 if (trap_toggle) intcall86(1); 909 if (tf) trap_toggle = 1; 910 else trap_toggle = 0; 911 if (!trap_toggle && (ifl && (i8259.irr & (~i8259.imr)))) intcall86(nextintr()); //get next interrupt from the i8259, if any 912 reptype = 0; segoverride = 0; 913 useseg = segregs[regds]; docontinue = 0; 914 firstip = ip; 915 while (!docontinue) { 916 segregs[regcs] = segregs[regcs] & 0xFFFF; ip = ip & 0xFFFF; 917 savecs = segregs[regcs]; saveip = ip; 918 opcode = getmem8(segregs[regcs], ip); StepIP(1); 919 920 switch (opcode) { 921 //segment prefix check 922 case 0x2E: //segment segregs[regcs] 923 useseg = segregs[regcs]; segoverride = 1; break; 924 case 0x3E: //segment segregs[regds] 925 useseg = segregs[regds]; segoverride = 1; break; 926 case 0x26: //segment segregs[reges] 927 useseg = segregs[reges]; segoverride = 1; break; 928 case 0x36: //segment segregs[regss] 929 useseg = segregs[regss]; segoverride = 1; break; 930 931 //repetition prefix check 932 case 0xF3: //REP/REPE/REPZ 933 reptype = 1; break; 934 case 0xF2: //REPNE/REPNZ 935 reptype = 2; break; 936 default: 937 docontinue = 1; 938 break; 939 } 940 } 941 totalexec++; 942 //printf("%04X:%04X %02X\n", segregs[regcs], ip, opcode); 943 //if ((segregs[regcs]==0xF000) && (ip < 0xE000)) exit(0); 944 945 #ifdef PROFILING 946 startmicros = micros(); 947 #endif 948 switch (opcode) { 949 case 0x0: //00 ADD Eb Gb 950 modregrm(); 951 oper1b = readrm8(rm); oper2b = getreg8(reg); 952 op_add8(); 953 writerm8(rm, res8); 954 break; 955 case 0x1: //01 ADD Ev Gv 956 modregrm(); 957 oper1 = readrm16(rm); oper2 = getreg16(reg); 958 op_add16(); 959 writerm16(rm, res16); 960 break; 961 case 0x2: //02 ADD Gb Eb 962 modregrm(); 963 oper1b = getreg8(reg); oper2b = readrm8(rm); 964 op_add8(); 965 putreg8(reg, res8); 966 break; 967 case 0x3: //03 ADD Gv Ev 968 modregrm(); 969 oper1 = getreg16(reg); oper2 = readrm16(rm); 970 op_add16(); 971 putreg16(reg, res16); 972 break; 973 case 0x4: //04 ADD regs.byteregs[regal] Ib 974 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 975 op_add8(); 976 regs.byteregs[regal] = res8; 977 break; 978 case 0x5: //05 ADD eAX Iv 979 oper1 = (getreg16(regax)); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 980 op_add16(); 981 putreg16(regax, res16); 982 break; 983 case 0x6: //06 PUSH segregs[reges] 984 push(segregs[reges]); 985 break; 986 case 0x7: //07 POP segregs[reges] 987 segregs[reges] = pop(); 988 break; 989 case 0x8: //08 OR Eb Gb 990 modregrm(); 991 oper1b = readrm8(rm); oper2b = getreg8(reg); 992 op_or8(); 993 writerm8(rm, res8); 994 break; 995 case 0x9: //09 OR Ev Gv 996 modregrm(); 997 oper1 = readrm16(rm); oper2 = getreg16(reg); 998 op_or16(); 999 writerm16(rm, res16); 1000 break; 1001 case 0xA: //0A OR Gb Eb 1002 modregrm(); 1003 oper1b = getreg8(reg); oper2b = readrm8(rm); 1004 op_or8(); 1005 putreg8(reg, res8); 1006 break; 1007 case 0xB: //0B OR Gv Ev 1008 modregrm(); 1009 oper1 = getreg16(reg); oper2 = readrm16(rm); 1010 op_or16(); 1011 if ((oper1 == 0xF802) && (oper2 == 0xF802)) sf = 0; //cheap hack to make Wolf 3D think we're a 286 so it plays 1012 putreg16(reg, res16); 1013 break; 1014 case 0xC: //0C OR regs.byteregs[regal] Ib 1015 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1016 op_or8(); 1017 regs.byteregs[regal] = res8; 1018 break; 1019 case 0xD: //0D OR eAX Iv 1020 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1021 op_or16(); 1022 putreg16(regax, res16); 1023 break; 1024 case 0xE: //0E PUSH segregs[regcs] 1025 push(segregs[regcs]); 1026 break; 1027 case 0xF: //0F POP CS 1028 segregs[regcs] = pop(); 1029 break; 1030 /*case 0xF: //0F 80286+ extended opcodes 1031 segregs[regcs] = segregs[regcs] & 0xFFFF; ip = ip & 0xFFFF; 1032 savecs = segregs[regcs]; saveip = ip; 1033 opcode = getmem8(segregs[regcs], ip); StepIP(1); 1034 op_286(); 1035 break;*/ 1036 case 0x10: //10 ADC Eb Gb 1037 modregrm(); 1038 oper1b = readrm8(rm); oper2b = getreg8(reg); 1039 op_adc8(); 1040 writerm8(rm, res8); 1041 break; 1042 case 0x11: //11 ADC Ev Gv 1043 modregrm(); 1044 oper1 = readrm16(rm); oper2 = getreg16(reg); 1045 op_adc16(); 1046 writerm16(rm, res16); 1047 break; 1048 case 0x12: //12 ADC Gb Eb 1049 modregrm(); 1050 oper1b = getreg8(reg); oper2b = readrm8(rm); 1051 op_adc8(); 1052 putreg8(reg, res8); 1053 break; 1054 case 0x13: //13 ADC Gv Ev 1055 modregrm(); 1056 oper1 = getreg16(reg); oper2 = readrm16(rm); 1057 op_adc16(); 1058 putreg16(reg, res16); 1059 break; 1060 case 0x14: //14 ADC regs.byteregs[regal] Ib 1061 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1062 op_adc8(); 1063 regs.byteregs[regal] = res8; 1064 break; 1065 case 0x15: //15 ADC eAX Iv 1066 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1067 op_adc16(); 1068 putreg16(regax, res16); 1069 break; 1070 case 0x16: //16 PUSH segregs[regss] 1071 push(segregs[regss]); 1072 break; 1073 case 0x17: //17 POP segregs[regss] 1074 segregs[regss] = pop(); 1075 break; 1076 case 0x18: //18 SBB Eb Gb 1077 modregrm(); 1078 oper1b = readrm8(rm); oper2b = getreg8(reg); 1079 op_sbb8(); 1080 writerm8(rm, res8); 1081 break; 1082 case 0x19: //19 SBB Ev Gv 1083 modregrm(); 1084 oper1 = readrm16(rm); oper2 = getreg16(reg); 1085 op_sbb16(); 1086 writerm16(rm, res16); 1087 break; 1088 case 0x1A: //1A SBB Gb Eb 1089 modregrm(); 1090 oper1b = getreg8(reg); oper2b = readrm8(rm); 1091 op_sbb8(); 1092 putreg8(reg, res8); 1093 break; 1094 case 0x1B: //1B SBB Gv Ev 1095 modregrm(); 1096 oper1 = getreg16(reg); oper2 = readrm16(rm); 1097 op_sbb16(); 1098 putreg16(reg, res16); 1099 break; 1100 case 0x1C: //1C SBB regs.byteregs[regal] Ib; 1101 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1102 op_sbb8(); 1103 regs.byteregs[regal] = res8; 1104 break; 1105 case 0x1D: //1D SBB eAX Iv 1106 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1107 op_sbb16(); 1108 putreg16(regax, res16); 1109 break; 1110 case 0x1E: //1E PUSH segregs[regds] 1111 push(segregs[regds]); 1112 break; 1113 case 0x1F: //1F POP segregs[regds] 1114 segregs[regds] = pop(); 1115 break; 1116 case 0x20: //20 AND Eb Gb 1117 modregrm(); 1118 oper1b = readrm8(rm); oper2b = getreg8(reg); 1119 op_and8(); 1120 writerm8(rm, res8); 1121 break; 1122 case 0x21: //21 AND Ev Gv 1123 modregrm(); 1124 oper1 = readrm16(rm); oper2 = getreg16(reg); 1125 op_and16(); 1126 writerm16(rm, res16); 1127 break; 1128 case 0x22: //22 AND Gb Eb 1129 modregrm(); 1130 oper1b = getreg8(reg); oper2b = readrm8(rm); 1131 op_and8(); 1132 putreg8(reg, res8); 1133 break; 1134 case 0x23: //23 AND Gv Ev 1135 modregrm(); 1136 oper1 = getreg16(reg); oper2 = readrm16(rm); 1137 op_and16(); 1138 putreg16(reg, res16); 1139 break; 1140 case 0x24: //24 AND regs.byteregs[regal] Ib 1141 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1142 op_and8(); 1143 regs.byteregs[regal] = res8; 1144 break; 1145 case 0x25: //25 AND eAX Iv 1146 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1147 op_and16(); 1148 putreg16(regax, res16); 1149 break; 1150 case 0x27: //27 DAA 1151 if (((regs.byteregs[regal] & 0xF) > 9) || (af == 1)) { 1152 oper1 = regs.byteregs[regal] + 6; 1153 regs.byteregs[regal] = oper1 & 255; 1154 if (oper1 & 0xFF00) cf = 1; else cf = 0; 1155 af = 1; 1156 } else af = 0; 1157 if (((regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1)) { 1158 regs.byteregs[regal] = regs.byteregs[regal] + 0x60; 1159 cf = 1; 1160 } else cf = 0; 1161 regs.byteregs[regal] = regs.byteregs[regal] & 255; 1162 flag_szp8(regs.byteregs[regal]); 1163 break; 1164 case 0x28: //28 SUB Eb Gb 1165 modregrm(); 1166 oper1b = readrm8(rm); oper2b = getreg8(reg); 1167 op_sub8(); 1168 writerm8(rm, res8); 1169 break; 1170 case 0x29: //29 SUB Ev Gv 1171 modregrm(); 1172 oper1 = readrm16(rm); oper2 = getreg16(reg); 1173 op_sub16(); 1174 writerm16(rm, res16); 1175 break; 1176 case 0x2A: //2A SUB Gb Eb 1177 modregrm(); 1178 oper1b = getreg8(reg); oper2b = readrm8(rm); 1179 op_sub8(); 1180 putreg8(reg, res8); 1181 break; 1182 case 0x2B: //2B SUB Gv Ev 1183 modregrm(); 1184 oper1 = getreg16(reg); oper2 = readrm16(rm); 1185 op_sub16(); 1186 putreg16(reg, res16); 1187 break; 1188 case 0x2C: //2C SUB regs.byteregs[regal] Ib 1189 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1190 op_sub8(); 1191 regs.byteregs[regal] = res8; 1192 break; 1193 case 0x2D: //2D SUB eAX Iv 1194 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1195 op_sub16(); 1196 putreg16(regax, res16); 1197 break; 1198 case 0x2F: //2F DAS 1199 if (((regs.byteregs[regal] & 15) > 9) || (af == 1)) { 1200 oper1 = regs.byteregs[regal] - 6; 1201 regs.byteregs[regal] = oper1 & 255; 1202 if (oper1 & 0xFF00) cf = 1; else cf = 0; 1203 af = 1; 1204 } else af = 0; 1205 if (((regs.byteregs[regal] & 0xF0) > 0x90) || (cf == 1)) { 1206 regs.byteregs[regal] = regs.byteregs[regal] - 0x60; 1207 cf = 1; 1208 } else cf = 0; 1209 flag_szp8(regs.byteregs[regal]); 1210 break; 1211 case 0x30: //30 XOR Eb Gb 1212 modregrm(); 1213 oper1b = readrm8(rm); oper2b = getreg8(reg); 1214 op_xor8(); 1215 writerm8(rm, res8); 1216 break; 1217 case 0x31: //31 XOR Ev Gv 1218 modregrm(); 1219 oper1 = readrm16(rm); oper2 = getreg16(reg); 1220 op_xor16(); 1221 writerm16(rm, res16); 1222 break; 1223 case 0x32: //32 XOR Gb Eb 1224 modregrm(); 1225 oper1b = getreg8(reg); oper2b = readrm8(rm); 1226 op_xor8(); 1227 putreg8(reg, res8); 1228 break; 1229 case 0x33: //33 XOR Gv Ev 1230 modregrm(); 1231 oper1 = getreg16(reg); oper2 = readrm16(rm); 1232 op_xor16(); 1233 putreg16(reg, res16); 1234 break; 1235 case 0x34: //34 XOR regs.byteregs[regal] Ib 1236 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1237 op_xor8(); 1238 regs.byteregs[regal] = res8; 1239 break; 1240 case 0x35: //35 XOR eAX Iv 1241 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1242 op_xor16(); 1243 putreg16(regax, res16); 1244 break; 1245 case 0x37: //37 AAA ASCII 1246 if (((regs.byteregs[regal] & 0xF) > 9) || (af == 1)) { 1247 regs.byteregs[regal] = regs.byteregs[regal] + 6; 1248 regs.byteregs[regah] = regs.byteregs[regah] + 1; 1249 af = 1; 1250 cf = 1; 1251 } else { 1252 af = 0; 1253 cf = 0; 1254 } 1255 regs.byteregs[regal] = regs.byteregs[regal] & 0xF; 1256 break; 1257 case 0x38: //38 CMP Eb Gb 1258 modregrm(); 1259 oper1b = readrm8(rm); oper2b = getreg8(reg); 1260 flag_sub8(oper1b, oper2b); 1261 break; 1262 case 0x39: //39 CMP Ev Gv 1263 modregrm(); 1264 oper1 = readrm16(rm); oper2 = getreg16(reg); 1265 flag_sub16(oper1, oper2); 1266 break; 1267 case 0x3A: //3A CMP Gb Eb 1268 modregrm(); 1269 oper1b = getreg8(reg); oper2b = readrm8(rm); 1270 flag_sub8(oper1b, oper2b); 1271 break; 1272 case 0x3B: //3B CMP Gv Ev 1273 modregrm(); 1274 oper1 = getreg16(reg); oper2 = readrm16(rm); 1275 flag_sub16(oper1, oper2); 1276 break; 1277 case 0x3C: //3C CMP regs.byteregs[regal] Ib 1278 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1279 flag_sub8(oper1b, oper2b); 1280 break; 1281 case 0x3D: //3D CMP eAX Iv 1282 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1283 flag_sub16(oper1, oper2); 1284 break; 1285 case 0x3F: //3F AAS ASCII 1286 if (((regs.byteregs[regal] & 0xF) > 9) || (af == 1)) { 1287 regs.byteregs[regal] = regs.byteregs[regal] - 6; 1288 regs.byteregs[regah] = regs.byteregs[regah] - 1; 1289 af = 1; 1290 cf = 1; 1291 } else { 1292 af = 0; 1293 cf = 0; 1294 } 1295 regs.byteregs[regal] = regs.byteregs[regal] & 0xF; 1296 break; 1297 case 0x40: //40 INC eAX 1298 oldcf = cf; 1299 oper1 = getreg16(regax); oper2 = 1; 1300 op_add16(); 1301 cf = oldcf; 1302 putreg16(regax, res16); 1303 break; 1304 case 0x41: //41 INC eCX 1305 oldcf = cf; 1306 oper1 = getreg16(regcx); oper2 = 1; 1307 op_add16(); 1308 cf = oldcf; 1309 putreg16(regcx, res16); 1310 break; 1311 case 0x42: //42 INC eDX 1312 oldcf = cf; 1313 oper1 = getreg16(regdx); oper2 = 1; 1314 op_add16(); 1315 cf = oldcf; 1316 putreg16(regdx, res16); 1317 break; 1318 case 0x43: //43 INC eBX 1319 oldcf = cf; 1320 oper1 = getreg16(regbx); oper2 = 1; 1321 op_add16(); 1322 cf = oldcf; 1323 putreg16(regbx, res16); 1324 break; 1325 case 0x44: //44 INC eSP 1326 oldcf = cf; 1327 oper1 = getreg16(regsp); oper2 = 1; 1328 op_add16(); 1329 cf = oldcf; 1330 putreg16(regsp, res16); 1331 break; 1332 case 0x45: //45 INC eBP 1333 oldcf = cf; 1334 oper1 = getreg16(regbp); oper2 = 1; 1335 op_add16(); 1336 cf = oldcf; 1337 putreg16(regbp, res16); 1338 break; 1339 case 0x46: //46 INC eSI 1340 oldcf = cf; 1341 oper1 = getreg16(regsi); oper2 = 1; 1342 op_add16(); 1343 cf = oldcf; 1344 putreg16(regsi, res16); 1345 break; 1346 case 0x47: //47 INC eDI 1347 oldcf = cf; 1348 oper1 = getreg16(regdi); oper2 = 1; 1349 op_add16(); 1350 cf = oldcf; 1351 putreg16(regdi, res16); 1352 break; 1353 case 0x48: //48 DEC eAX 1354 oldcf = cf; 1355 oper1 = getreg16(regax); oper2 = 1; 1356 op_sub16(); 1357 cf = oldcf; 1358 putreg16(regax, res16); 1359 break; 1360 case 0x49: //49 DEC eCX 1361 oldcf = cf; 1362 oper1 = getreg16(regcx); oper2 = 1; 1363 op_sub16(); 1364 cf = oldcf; 1365 putreg16(regcx, res16); 1366 break; 1367 case 0x4A: //4A DEC eDX 1368 oldcf = cf; 1369 oper1 = getreg16(regdx); oper2 = 1; 1370 op_sub16(); 1371 cf = oldcf; 1372 putreg16(regdx, res16); 1373 break; 1374 case 0x4B: //4B DEC eBX 1375 oldcf = cf; 1376 oper1 = getreg16(regbx); oper2 = 1; 1377 op_sub16(); 1378 cf = oldcf; 1379 putreg16(regbx, res16); 1380 break; 1381 case 0x4C: //4C DEC eSP 1382 oldcf = cf; 1383 oper1 = getreg16(regsp); oper2 = 1; 1384 op_sub16(); 1385 cf = oldcf; 1386 putreg16(regsp, res16); 1387 break; 1388 case 0x4D: //4D DEC eBP 1389 oldcf = cf; 1390 oper1 = getreg16(regbp); oper2 = 1; 1391 op_sub16(); 1392 cf = oldcf; 1393 putreg16(regbp, res16); 1394 break; 1395 case 0x4E: //4E DEC eSI 1396 oldcf = cf; 1397 oper1 = getreg16(regsi); oper2 = 1; 1398 op_sub16(); 1399 cf = oldcf; 1400 putreg16(regsi, res16); 1401 break; 1402 case 0x4F: //4F DEC eDI 1403 oldcf = cf; 1404 oper1 = getreg16(regdi); oper2 = 1; 1405 op_sub16(); 1406 cf = oldcf; 1407 putreg16(regdi, res16); 1408 break; 1409 case 0x50: //50 PUSH eAX 1410 push (getreg16(regax)); 1411 break; 1412 case 0x51: //51 PUSH eCX 1413 push (getreg16(regcx)); 1414 break; 1415 case 0x52: //52 PUSH eDX 1416 push (getreg16(regdx)); 1417 break; 1418 case 0x53: //53 PUSH eBX 1419 push (getreg16(regbx)); 1420 break; 1421 case 0x54: //54 PUSH eSP 1422 push (getreg16(regsp) - 2); 1423 break; 1424 case 0x55: //55 PUSH eBP 1425 push (getreg16(regbp)); 1426 break; 1427 case 0x56: //56 PUSH eSI 1428 push (getreg16(regsi)); 1429 break; 1430 case 0x57: //57 PUSH eDI 1431 push (getreg16(regdi)); 1432 break; 1433 case 0x58: //58 POP eAX 1434 putreg16(regax, pop()); 1435 break; 1436 case 0x59: //59 POP eCX 1437 putreg16(regcx, pop()); 1438 break; 1439 case 0x5A: //5A POP eDX 1440 putreg16(regdx, pop()); 1441 break; 1442 case 0x5B: //5B POP eBX 1443 putreg16(regbx, pop()); 1444 break; 1445 case 0x5C: //5C POP eSP 1446 putreg16(regsp, pop()); 1447 break; 1448 case 0x5D: //5D POP eBP 1449 putreg16(regbp, pop()); 1450 break; 1451 case 0x5E: //5E POP eSI 1452 putreg16(regsi, pop()); 1453 break; 1454 case 0x5F: //5F POP eDI 1455 putreg16(regdi, pop()); 1456 break; 1457 case 0x60: //60 PUSHA (80186+) 1458 oldsp = getreg16(regsp); 1459 push(getreg16(regax)); 1460 push(getreg16(regcx)); 1461 push(getreg16(regdx)); 1462 push(getreg16(regbx)); 1463 push(oldsp); 1464 push(getreg16(regbp)); 1465 push(getreg16(regsi)); 1466 push(getreg16(regdi)); 1467 break; 1468 case 0x61: //61 POPA (80186+) 1469 putreg16(regdi, pop()); 1470 putreg16(regsi, pop()); 1471 putreg16(regbp, pop()); 1472 dummy = pop(); 1473 putreg16(regbx, pop()); 1474 putreg16(regdx, pop()); 1475 putreg16(regcx, pop()); 1476 putreg16(regax, pop()); 1477 break; 1478 case 0x68: //68 PUSH Iv (80186+) 1479 push(getmem16(segregs[regcs], ip)); StepIP(2); 1480 break; 1481 case 0x69: //69 IMUL Gv Ev Iv (80186+) 1482 //print("WE HIT 69h IMUL\r\n"); 1483 modregrm(); 1484 temp1 = readrm16(rm); 1485 temp2 = getmem16(segregs[regcs], ip); StepIP(2); 1486 if ((temp1 & 0x8000L) == 0x8000L) temp1 = temp1 | 0xFFFF0000L; 1487 if ((temp2 & 0x8000L) == 0x8000L) temp2 = temp2 | 0xFFFF0000L; 1488 temp3 = temp1 * temp2; 1489 putreg16(reg, temp3 & 0xFFFFL); 1490 if (temp3 & 0xFFFF0000L) { 1491 cf = 1; 1492 of = 1; 1493 } else { 1494 cf = 0; 1495 of = 0; 1496 } 1497 break; 1498 case 0x6A: //6A PUSH Ib (80186+) 1499 push(getmem8(segregs[regcs], ip)); StepIP(1); 1500 break; 1501 case 0x6B: //6B IMUL Gv Eb Ib (80186+) 1502 //print("WE HIT 6Bh IMUL\r\n"); 1503 modregrm(); 1504 temp1 = readrm16(rm); 1505 temp2 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1506 if ((temp1 & 0x8000L) == 0x8000L) temp1 = temp1 | 0xFFFF0000L; 1507 if ((temp2 & 0x8000L) == 0x8000L) temp2 = temp2 | 0xFFFF0000L; 1508 temp3 = temp1 * temp2; 1509 putreg16(reg, temp3 & 0xFFFFL); 1510 if (temp3 & 0xFFFF0000L) { 1511 cf = 1; 1512 of = 1; 1513 } else { 1514 cf = 0; 1515 of = 0; 1516 } 1517 break; 1518 //case 0x6C ... 0x6F: //80186 port operations, just act as if they//re NOPs for now... 1519 // StepIP(1); //they have a modregrm(); byte we must skip... i may properly emulate these later. 1520 // break; 1521 case 0x6E: //6E OUTSB 1522 if (reptype && (getreg16(regcx) == 0)) break; 1523 portout16 = 0; 1524 portout(regs.wordregs[regdx], getmem16(useseg, getreg16(regsi))); 1525 if (df) { 1526 putreg16(regsi, getreg16(regsi) - 1); 1527 putreg16(regdi, getreg16(regdi) - 1); 1528 } 1529 else { 1530 putreg16(regsi, getreg16(regsi) + 1); 1531 putreg16(regdi, getreg16(regdi) + 1); 1532 } 1533 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1534 if (!reptype) break; 1535 ip = firstip; 1536 break; 1537 case 0x6F: //6F OUTSW 1538 if (reptype && (getreg16(regcx) == 0)) break; 1539 portout16 = 1; 1540 portout(regs.wordregs[regdx], getmem16(useseg, getreg16(regsi))); 1541 if (df) { 1542 putreg16(regsi, getreg16(regsi) - 2); 1543 putreg16(regdi, getreg16(regdi) - 2); 1544 } 1545 else { 1546 putreg16(regsi, getreg16(regsi) + 2); 1547 putreg16(regdi, getreg16(regdi) + 2); 1548 } 1549 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1550 if (!reptype) break; 1551 ip = firstip; 1552 break; 1553 1554 case 0x70: //70 JO Jb 1555 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1556 if (of) ip = ip + temp16; 1557 break; 1558 case 0x71: //71 JNO Jb 1559 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1560 if (!of) ip = ip + temp16; 1561 break; 1562 case 0x72: //72 JB Jb 1563 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1564 if (cf) ip = ip + temp16; 1565 break; 1566 case 0x73: //73 JNB Jb 1567 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1568 if (!cf) ip = ip + temp16; 1569 break; 1570 case 0x74: //74 JZ Jb 1571 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1572 if (zf) ip = ip + temp16; 1573 break; 1574 case 0x75: //75 JNZ Jb 1575 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1576 if (!zf) ip = ip + temp16; 1577 break; 1578 case 0x76: //76 JBE Jb 1579 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1580 if (cf || zf) ip = ip + temp16; 1581 break; 1582 case 0x77: //77 JA Jb 1583 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1584 if (!cf && !zf) ip = ip + temp16; 1585 break; 1586 case 0x78: //78 JS Jb 1587 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1588 if (sf) ip = ip + temp16; 1589 break; 1590 case 0x79: //79 JNS Jb 1591 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1592 if (!sf) ip = ip + temp16; 1593 break; 1594 case 0x7A: //7A JPE Jb 1595 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1596 if (pf) ip = ip + temp16; 1597 break; 1598 case 0x7B: //7B JPO Jb 1599 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1600 if (!pf) ip = ip + temp16; 1601 break; 1602 case 0x7C: //7C JL Jb 1603 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1604 if (sf != of) ip = ip + temp16; 1605 break; 1606 case 0x7D: //7D JGE Jb 1607 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1608 if (sf == of) ip = ip + temp16; 1609 break; 1610 case 0x7E: //7E JLE Jb 1611 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1612 if ((sf != of) || zf) ip = ip + temp16; 1613 break; 1614 case 0x7F: //7F JG Jb 1615 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1616 if (!zf && (sf == of)) ip = ip + temp16; 1617 break; 1618 case 0x80: case 0x82: //80/82 GRP1 Eb Ib 1619 modregrm(); 1620 oper1b = readrm8(rm); 1621 oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1622 switch (reg) { 1623 case 0: op_add8(); break; 1624 case 1: op_or8(); break; 1625 case 2: op_adc8(); break; 1626 case 3: op_sbb8(); break; 1627 case 4: op_and8(); break; 1628 case 5: op_sub8(); break; 1629 case 6: op_xor8(); break; 1630 case 7: flag_sub8(oper1b, oper2b); break; 1631 default: break; //to avoid compiler warnings 1632 } 1633 if (reg < 7) writerm8(rm, res8); 1634 break; 1635 case 0x81: //81 GRP1 Ev Iv 1636 case 0x83: //83 GRP1 Ev Ib 1637 modregrm(); 1638 oper1 = readrm16(rm); 1639 if (opcode == 0x81) { 1640 oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1641 } else { 1642 oper2 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 1643 } 1644 switch (reg) { 1645 case 0: op_add16(); break; 1646 case 1: op_or16(); break; 1647 case 2: op_adc16(); break; 1648 case 3: op_sbb16(); break; 1649 case 4: op_and16(); break; 1650 case 5: op_sub16(); break; 1651 case 6: op_xor16(); break; 1652 case 7: flag_sub16(oper1, oper2); break; 1653 default: break; //to avoid compiler warnings 1654 } 1655 if (reg < 7) writerm16(rm, res16); 1656 break; 1657 case 0x84: //84 TEST Gb Eb 1658 modregrm(); 1659 oper1b = getreg8(reg); oper2b = readrm8(rm); 1660 flag_log8(oper1b & oper2b); 1661 break; 1662 case 0x85: //85 TEST Gv Ev 1663 modregrm(); 1664 oper1 = getreg16(reg); oper2 = readrm16(rm); 1665 flag_log16(oper1 & oper2); 1666 break; 1667 case 0x86: //86 XCHG Gb Eb 1668 modregrm(); 1669 oper1b = getreg8(reg); 1670 putreg8(reg, readrm8(rm)); 1671 writerm8(rm, oper1b); 1672 break; 1673 case 0x87: //87 XCHG Gv Ev 1674 modregrm(); 1675 oper1 = getreg16(reg); 1676 putreg16(reg, readrm16(rm)); 1677 writerm16(rm, oper1); 1678 break; 1679 case 0x88: //88 MOV Eb Gb 1680 modregrm(); 1681 writerm8(rm, getreg8(reg)); 1682 break; 1683 case 0x89: //89 MOV Ev Gv 1684 modregrm(); 1685 writerm16(rm, getreg16(reg)); 1686 break; 1687 case 0x8A: //8A MOV Gb Eb 1688 modregrm(); 1689 putreg8(reg, readrm8(rm)); 1690 break; 1691 case 0x8B: //8B MOV Gv Ev 1692 modregrm(); 1693 putreg16(reg, readrm16(rm)); 1694 break; 1695 case 0x8C: //8C MOV Ew Sw 1696 modregrm(); 1697 writerm16(rm, getsegreg(reg)); 1698 break; 1699 case 0x8D: //8D LEA Gv M 1700 modregrm(); 1701 //getea(rm); 1702 putreg16(reg, ea - segbase(useseg)); 1703 break; 1704 case 0x8E: //8E MOV Sw Ew 1705 modregrm(); 1706 putsegreg(reg, readrm16(rm)); 1707 break; 1708 case 0x8F: //8F POP Ev 1709 modregrm(); 1710 writerm16(rm, pop()); 1711 break; 1712 case 0x90: //90 NOP 1713 break; 1714 case 0x91: //91 XCHG eCX eAX 1715 oper1 = getreg16(regcx); 1716 putreg16(regcx, getreg16(regax)); 1717 putreg16(regax, oper1); 1718 break; 1719 case 0x92: //92 XCHG eDX eAX 1720 oper1 = getreg16(regdx); 1721 putreg16(regdx, getreg16(regax)); 1722 putreg16(regax, oper1); 1723 break; 1724 case 0x93: //93 XCHG eBX eAX 1725 oper1 = getreg16(regbx); 1726 putreg16(regbx, getreg16(regax)); 1727 putreg16(regax, oper1); 1728 break; 1729 case 0x94: //94 XCHG eSP eAX 1730 oper1 = getreg16(regsp); 1731 putreg16(regsp, getreg16(regax)); 1732 putreg16(regax, oper1); 1733 break; 1734 case 0x95: //95 XCHG eBP eAX 1735 oper1 = getreg16(regbp); 1736 putreg16(regbp, getreg16(regax)); 1737 putreg16(regax, oper1); 1738 break; 1739 case 0x96: //96 XCHG eSI eAX 1740 oper1 = getreg16(regsi); 1741 putreg16(regsi, getreg16(regax)); 1742 putreg16(regax, oper1); 1743 break; 1744 case 0x97: //97 XCHG eDI eAX 1745 oper1 = getreg16(regdi); 1746 putreg16(regdi, getreg16(regax)); 1747 putreg16(regax, oper1); 1748 break; 1749 case 0x98: //98 CBW 1750 if ((regs.byteregs[regal] & 0x80) == 0x80) regs.byteregs[regah] = 0xFF; else regs.byteregs[regah] = 0; 1751 break; 1752 case 0x99: //99 CWD 1753 if ((regs.byteregs[regah] & 0x80) == 0x80) putreg16(regdx, 0xFFFF); else putreg16(regdx, 0); 1754 break; 1755 case 0x9A: //9A CALL Ap 1756 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 1757 oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1758 push(segregs[regcs]); push(ip); ip = oper1; segregs[regcs] = oper2; 1759 break; 1760 case 0x9B: //9B WAIT 1761 break; 1762 case 0x9C: //9C PUSHF 1763 push(makeflagsword() | 0xF800); 1764 break; 1765 case 0x9D: //9D POPF 1766 temp16 = pop(); 1767 decodeflagsword(temp16); 1768 break; 1769 case 0x9E: //9E SAHF 1770 decodeflagsword ((makeflagsword() & 0xFF00) | regs.byteregs[regah]); 1771 break; 1772 case 0x9F: //9F LAHF 1773 regs.byteregs[regah] = makeflagsword() & 0xFF; 1774 break; 1775 case 0xA0: //A0 MOV regs.byteregs[regal] Ob 1776 regs.byteregs[regal] = getmem8(useseg, getmem16(segregs[regcs], ip)); StepIP(2); 1777 break; 1778 case 0xA1: //A1 MOV eAX Ov 1779 oper1 = getmem16(useseg, getmem16(segregs[regcs], ip)); StepIP(2); 1780 putreg16(regax, oper1); 1781 break; 1782 case 0xA2: //A2 MOV Ob regs.byteregs[regal] 1783 putmem8(useseg, getmem16(segregs[regcs], ip), regs.byteregs[regal]); StepIP(2); 1784 break; 1785 case 0xA3: //A3 MOV Ov eAX 1786 putmem16(useseg, getmem16(segregs[regcs], ip), getreg16(regax)); StepIP(2); 1787 break; 1788 case 0xA4: //A4 MOVSB 1789 if (reptype && (getreg16(regcx) == 0)) break; 1790 putmem8(segregs[reges], getreg16(regdi), getmem8(useseg, getreg16(regsi))); 1791 if (df) { 1792 putreg16(regsi, getreg16(regsi) - 1); 1793 putreg16(regdi, getreg16(regdi) - 1); 1794 } 1795 else { 1796 putreg16(regsi, getreg16(regsi) + 1); 1797 putreg16(regdi, getreg16(regdi) + 1); 1798 } 1799 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1800 if (!reptype) break; 1801 ip = firstip; 1802 break; 1803 case 0xA5: //A5 MOVSW 1804 if (reptype && (getreg16(regcx) == 0)) break; 1805 putmem16(segregs[reges], getreg16(regdi), getmem16(useseg, getreg16(regsi))); 1806 if (df) { 1807 putreg16(regsi, getreg16(regsi) - 2); 1808 putreg16(regdi, getreg16(regdi) - 2); 1809 } 1810 else { 1811 putreg16(regsi, getreg16(regsi) + 2); 1812 putreg16(regdi, getreg16(regdi) + 2); 1813 } 1814 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1815 if (!reptype) break; 1816 ip = firstip; 1817 break; 1818 case 0xA6: //A6 CMPSB 1819 if (reptype && (getreg16(regcx) == 0)) break; 1820 oper1b = getmem8(useseg, getreg16(regsi)); oper2b = getmem8(segregs[reges], getreg16(regdi)); 1821 if (df) { 1822 putreg16(regsi, getreg16(regsi) - 1); 1823 putreg16(regdi, getreg16(regdi) - 1); 1824 } 1825 else { 1826 putreg16(regsi, getreg16(regsi) + 1); 1827 putreg16(regdi, getreg16(regdi) + 1); 1828 } 1829 flag_sub8(oper1b, oper2b); 1830 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1831 if ((reptype == 1) && !zf) break; 1832 else if ((reptype == 2) && (zf == 1)) break; 1833 if (!reptype) break; 1834 ip = firstip; 1835 break; 1836 case 0xA7: //A7 CMPSW 1837 if (reptype && (getreg16(regcx) == 0)) break; 1838 oper1 = getmem16(useseg, getreg16(regsi)); oper2 = getmem16(segregs[reges], getreg16(regdi)); 1839 if (df) { 1840 putreg16(regsi, getreg16(regsi) - 2); 1841 putreg16(regdi, getreg16(regdi) - 2); 1842 } 1843 else { 1844 putreg16(regsi, getreg16(regsi) + 2); 1845 putreg16(regdi, getreg16(regdi) + 2); 1846 } 1847 flag_sub16(oper1, oper2); 1848 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1849 if ((reptype == 1) && !zf) break; 1850 if ((reptype == 2) && (zf == 1)) break; 1851 if (!reptype) break; 1852 ip = firstip; 1853 break; 1854 case 0xA8: //A8 TEST regs.byteregs[regal] Ib 1855 oper1b = regs.byteregs[regal]; oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1856 flag_log8(oper1b & oper2b); 1857 break; 1858 case 0xA9: //A9 TEST eAX Iv 1859 oper1 = getreg16(regax); oper2 = getmem16(segregs[regcs], ip); StepIP(2); 1860 flag_log16(oper1 & oper2); 1861 break; 1862 case 0xAA: //AA STOSB 1863 if (reptype && (getreg16(regcx) == 0)) break; 1864 putmem8(segregs[reges], getreg16(regdi), regs.byteregs[regal]); 1865 if (df) putreg16(regdi, getreg16(regdi) - 1); 1866 else putreg16(regdi, getreg16(regdi) + 1); 1867 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1868 if (!reptype) break; 1869 ip = firstip; 1870 break; 1871 case 0xAB: //AB STOSW 1872 if (reptype && (getreg16(regcx) == 0)) break; 1873 putmem16(segregs[reges], getreg16(regdi), getreg16(regax)); 1874 if (df) putreg16(regdi, getreg16(regdi) - 2); 1875 else putreg16(regdi, getreg16(regdi) + 2); 1876 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1877 if (!reptype) break; 1878 ip = firstip; 1879 break; 1880 case 0xAC: //AC LODSB 1881 if (reptype && (getreg16(regcx) == 0)) break; 1882 regs.byteregs[regal] = getmem8(useseg, getreg16(regsi)); 1883 if (df) putreg16(regsi, getreg16(regsi) - 1); 1884 else putreg16(regsi, getreg16(regsi) + 1); 1885 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1886 if (!reptype) break; 1887 ip = firstip; 1888 break; 1889 case 0xAD: //AD LODSW 1890 if (reptype && (getreg16(regcx) == 0)) break; 1891 oper1 = getmem16(useseg, getreg16(regsi)); 1892 putreg16(regax, oper1); 1893 if (df) putreg16(regsi, getreg16(regsi) - 2); 1894 else putreg16(regsi, getreg16(regsi) + 2); 1895 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1896 if (!reptype) break; 1897 ip = firstip; 1898 break; 1899 case 0xAE: //AE SCASB 1900 if (reptype && (getreg16(regcx) == 0)) break; 1901 oper1b = getmem8(segregs[reges], getreg16(regdi)); oper2b = regs.byteregs[regal]; 1902 flag_sub8(oper1b, oper2b); 1903 if (df) putreg16(regdi, getreg16(regdi) - 1); 1904 else putreg16(regdi, getreg16(regdi) + 1); 1905 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1906 if ((reptype == 1) && !zf) break; 1907 else if ((reptype == 2) && (zf == 1)) break; 1908 if (!reptype) break; 1909 ip = firstip; 1910 break; 1911 case 0xAF: //AF SCASW 1912 if (reptype && (getreg16(regcx) == 0)) break; 1913 oper1 = getmem16(segregs[reges], getreg16(regdi)); oper2 = getreg16(regax); 1914 flag_sub16(oper1, oper2); 1915 if (df) putreg16(regdi, getreg16(regdi) - 2); 1916 else putreg16(regdi, getreg16(regdi) + 2); 1917 if (reptype) putreg16(regcx, getreg16(regcx) - 1); 1918 if ((reptype == 1) && !zf) break; 1919 else if ((reptype == 2) & (zf == 1)) break; 1920 if (!reptype) break; 1921 ip = firstip; 1922 break; 1923 case 0xB0: //B0 MOV regs.byteregs[regal] Ib 1924 regs.byteregs[regal] = getmem8(segregs[regcs], ip); StepIP(1); 1925 break; 1926 case 0xB1: //B1 MOV regs.byteregs[regcl] Ib 1927 regs.byteregs[regcl] = getmem8(segregs[regcs], ip); StepIP(1); 1928 break; 1929 case 0xB2: //B2 MOV regs.byteregs[regdl] Ib 1930 regs.byteregs[regdl] = getmem8(segregs[regcs], ip); StepIP(1); 1931 break; 1932 case 0xB3: //B3 MOV regs.byteregs[regbl] Ib 1933 regs.byteregs[regbl] = getmem8(segregs[regcs], ip); StepIP(1); 1934 break; 1935 case 0xB4: //B4 MOV regs.byteregs[regah] Ib 1936 regs.byteregs[regah] = getmem8(segregs[regcs], ip); StepIP(1); 1937 break; 1938 case 0xB5: //B5 MOV regs.byteregs[regch] Ib 1939 regs.byteregs[regch] = getmem8(segregs[regcs], ip); StepIP(1); 1940 break; 1941 case 0xB6: //B6 MOV regs.byteregs[regdh] Ib 1942 regs.byteregs[regdh] = getmem8(segregs[regcs], ip); StepIP(1); 1943 break; 1944 case 0xB7: //B7 MOV regs.byteregs[regbh] Ib 1945 regs.byteregs[regbh] = getmem8(segregs[regcs], ip); StepIP(1); 1946 break; 1947 case 0xB8: //B8 MOV eAX Iv 1948 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 1949 putreg16(regax, oper1); 1950 break; 1951 case 0xB9: //B9 MOV eCX Iv 1952 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 1953 putreg16(regcx, oper1); 1954 break; 1955 case 0xBA: //BA MOV eDX Iv 1956 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 1957 putreg16(regdx, oper1); 1958 break; 1959 case 0xBB: //BB MOV eBX Iv 1960 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 1961 putreg16(regbx, oper1); 1962 break; 1963 case 0xBC: //BC MOV eSP Iv 1964 putreg16(regsp, getmem16(segregs[regcs], ip)); StepIP(2); 1965 break; 1966 case 0xBD: //BD MOV eBP Iv 1967 putreg16(regbp, getmem16(segregs[regcs], ip)); StepIP(2); 1968 break; 1969 case 0xBE: //BE MOV eSI Iv 1970 putreg16(regsi, getmem16(segregs[regcs], ip)); StepIP(2); 1971 break; 1972 case 0xBF: //BF MOV eDI Iv 1973 putreg16(regdi, getmem16(segregs[regcs], ip)); StepIP(2); 1974 break; 1975 case 0xC0: //C0 GRP2 byte imm8 (80186+) 1976 modregrm(); 1977 oper1b = readrm8(rm); 1978 oper2b = getmem8(segregs[regcs], ip); StepIP(1); 1979 writerm8(rm, op_grp2_8(oper2b)); 1980 break; 1981 case 0xC1: //C1 GRP2 word imm8 (80186+) 1982 modregrm(); 1983 oper1 = readrm16(rm); 1984 oper2 = getmem8(segregs[regcs], ip); StepIP(1); 1985 writerm16(rm, op_grp2_16(oper2)); 1986 break; 1987 case 0xC2: //C2 RET Iw 1988 oper1 = getmem16(segregs[regcs], ip); 1989 ip = pop(); 1990 putreg16(regsp, getreg16(regsp) + oper1); 1991 break; 1992 case 0xC3: //C3 RET 1993 ip = pop(); 1994 break; 1995 case 0xC4: //C4 LES Gv Mp 1996 modregrm(); 1997 //getea(rm); 1998 putreg16(reg, read86(ea) + ((uint16_t)read86(ea + 1) << 8)); 1999 segregs[reges] = read86(ea + 2) + ((uint16_t)read86(ea + 3) << 8); 2000 break; 2001 case 0xC5: //C5 LDS Gv Mp 2002 modregrm(); 2003 //getea(rm); 2004 putreg16(reg, read86(ea) + ((uint16_t)read86(ea + 1) << 8)); 2005 segregs[regds] = read86(ea + 2) + ((uint16_t)read86(ea + 3) << 8); 2006 break; 2007 case 0xC6: //C6 MOV Eb Ib 2008 modregrm(); 2009 writerm8(rm, getmem8(segregs[regcs], ip)); StepIP(1); 2010 break; 2011 case 0xC7: //C7 MOV Ev Iv 2012 modregrm(); 2013 writerm16(rm, getmem16(segregs[regcs], ip)); StepIP(2); 2014 break; 2015 case 0xC8: //C8 ENTER (80186+) 2016 stacksize = getmem16(segregs[regcs], ip); StepIP(2); 2017 nestlev = getmem8(segregs[regcs], ip); StepIP(1); 2018 push(getreg16(regbp)); 2019 frametemp = getreg16(regsp); 2020 if (nestlev) { 2021 for (temp16 = 1; temp16 < nestlev; temp16++) { 2022 putreg16(regbp, getreg16(regbp) - 2); 2023 push(getreg16(regbp)); 2024 } 2025 push(getreg16(regsp)); 2026 } 2027 putreg16(regbp, frametemp); 2028 putreg16(regsp, getreg16(regbp) - stacksize); 2029 2030 break; 2031 case 0xC9: //C9 LEAVE (80186+) 2032 putreg16(regsp, getreg16(regbp)); 2033 putreg16(regbp, pop()); 2034 2035 break; 2036 case 0xCA: //CA RETF Iw 2037 oper1 = getmem16(segregs[regcs], ip); 2038 ip = pop(); segregs[regcs] = pop(); 2039 putreg16(regsp, getreg16(regsp) + oper1); 2040 break; 2041 case 0xCB: //CB RETF 2042 ip = pop();; segregs[regcs] = pop(); 2043 break; 2044 case 0xCC: //CC INT 3 2045 intcall86(3); 2046 break; 2047 case 0xCD: //CD INT Ib 2048 oper1 = getmem8(segregs[regcs], ip); StepIP(1); 2049 intcall86(oper1); 2050 break; 2051 case 0xCE: //CE INTO 2052 if (of) intcall86(4); 2053 break; 2054 case 0xCF: //CF IRET 2055 ip = pop(); segregs[regcs] = pop(); 2056 decodeflagsword(pop()); 2057 //if (net.enabled) net.canrecv = 1; 2058 break; 2059 case 0xD0: //D0 GRP2 Eb 1 2060 modregrm(); 2061 oper1b = readrm8(rm); 2062 writerm8(rm, op_grp2_8(1)); 2063 break; 2064 case 0xD1: //D1 GRP2 Ev 1 2065 modregrm(); 2066 oper1 = readrm16(rm); 2067 writerm16(rm, op_grp2_16(1)); 2068 break; 2069 case 0xD2: //D2 GRP2 Eb regs.byteregs[regcl] 2070 modregrm(); 2071 oper1b = readrm8(rm); 2072 writerm8(rm, op_grp2_8(regs.byteregs[regcl])); 2073 break; 2074 case 0xD3: //D3 GRP2 Ev regs.byteregs[regcl] 2075 modregrm(); 2076 oper1 = readrm16(rm); 2077 writerm16(rm, op_grp2_16(regs.byteregs[regcl])); 2078 break; 2079 case 0xD4: //D4 AAM I0 2080 oper1 = getmem8(segregs[regcs], ip); StepIP(1); 2081 if (!oper1) { 2082 intcall86(0); //division by zero 2083 return; 2084 } 2085 regs.byteregs[regah] = (regs.byteregs[regal] / oper1) & 255; 2086 regs.byteregs[regal] = (regs.byteregs[regal] % oper1) & 255; 2087 flag_szp16 (getreg16(regax)); 2088 break; 2089 case 0xD5: //D5 AAD I0 2090 oper1 = getmem8(segregs[regcs], ip); StepIP(1); 2091 regs.byteregs[regal] = (regs.byteregs[regah] * oper1 + regs.byteregs[regal]) & 255; 2092 regs.byteregs[regah] = 0; 2093 flag_szp16(regs.byteregs[regah] * oper1 + regs.byteregs[regal]); 2094 sf = 0; 2095 break; 2096 case 0xD6: //D6 XLAT on V20/V30, SALC on 8086/8088 2097 regs.byteregs[regal] = cf; 2098 break; 2099 case 0xD7: //D7 XLAT 2100 putreg8(regal, read86(segbase(useseg) + (uint32_t)getreg16(regbx) + (uint32_t)getreg8(regal))); 2101 break; 2102 case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDE: case 0xDD: case 0xDF: //escape 2103 StepIP(1); 2104 break; 2105 case 0xE0: //E0 LOOPNZ Jb 2106 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 2107 putreg16(regcx, getreg16(regcx) - 1); 2108 if ((getreg16(regcx)) && !zf) ip = ip + temp16; 2109 break; 2110 case 0xE1: //E1 LOOPZ Jb 2111 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 2112 putreg16(regcx, (getreg16(regcx)) - 1); 2113 if ((getreg16(regcx)) && (zf == 1)) ip = ip + temp16; 2114 break; 2115 case 0xE2: //E2 LOOP Jb 2116 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 2117 putreg16(regcx, (getreg16(regcx)) - 1); 2118 if (getreg16(regcx)) ip = ip + temp16; 2119 break; 2120 case 0xE3: //E3 JCXZ Jb 2121 temp16 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 2122 if (!(getreg16(regcx))) ip = ip + temp16; 2123 break; 2124 case 0xE4: //E4 IN regs.byteregs[regal] Ib 2125 oper1b = getmem8(segregs[regcs], ip); 2126 StepIP(1); 2127 regs.byteregs[regal] = portin(oper1b); 2128 break; 2129 case 0xE5: //E5 IN eAX Ib 2130 oper1b = getmem8(segregs[regcs], ip); 2131 StepIP(1); 2132 putreg16(regax, portin(oper1b)); 2133 break; 2134 case 0xE6: //E6 OUT Ib regs.byteregs[regal] 2135 oper1b = getmem8(segregs[regcs], ip); 2136 StepIP(1); 2137 portout16 = 0; 2138 portout(oper1b, regs.byteregs[regal]); 2139 break; 2140 case 0xE7: //E7 OUT Ib eAX 2141 oper1b = getmem8(segregs[regcs], ip); 2142 StepIP(1); 2143 portout16 = 1; 2144 portout(oper1b, (getreg16(regax))); 2145 break; 2146 case 0xE8: //E8 CALL Jv 2147 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 2148 push(ip); 2149 ip = ip + oper1; 2150 break; 2151 case 0xE9: //E9 JMP Jv 2152 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 2153 ip = ip + oper1; 2154 break; 2155 case 0xEA: //EA JMP Ap 2156 oper1 = getmem16(segregs[regcs], ip); StepIP(2); 2157 oper2 = getmem16(segregs[regcs], ip); 2158 ip = oper1; segregs[regcs] = oper2; 2159 break; 2160 case 0xEB: //EB JMP Jb 2161 oper1 = signext(getmem8(segregs[regcs], ip)); StepIP(1); 2162 ip = ip + oper1; 2163 break; 2164 case 0xEC: //EC IN regs.byteregs[regal] regdx 2165 oper1 = (getreg16(regdx)); 2166 regs.byteregs[regal] = portin(oper1); 2167 break; 2168 case 0xED: //ED IN eAX regdx 2169 oper1 = (getreg16(regdx)); 2170 putreg16(regax, portin(oper1)); 2171 break; 2172 case 0xEE: //EE OUT regdx regs.byteregs[regal] 2173 oper1 = (getreg16(regdx)); 2174 portout16 = 0; 2175 portout(oper1, regs.byteregs[regal]); 2176 break; 2177 case 0xEF: //EF OUT regdx eAX 2178 oper1 = (getreg16(regdx)); 2179 portout16 = 1; 2180 portout(oper1, (getreg16(regax))); 2181 break; 2182 case 0xF0: //F0 LOCK 2183 case 0xF4: //F4 HLT 2184 break; 2185 case 0xF5: //F5 CMC 2186 if (!cf) cf = 1; else cf = 0; 2187 break; 2188 case 0xF6: //F6 GRP3a Eb 2189 modregrm(); 2190 oper1b = readrm8(rm); 2191 op_grp3_8(); 2192 if ((reg > 1) && (reg < 4)) writerm8(rm, res8); 2193 2194 break; 2195 case 0xF7: //F7 GRP3b Ev 2196 modregrm(); 2197 oper1 = readrm16(rm); 2198 op_grp3_16(); 2199 if ((reg > 1) && (reg < 4)) writerm16(rm, res16); 2200 break; 2201 case 0xF8: //F8 CLC 2202 cf = 0; 2203 break; 2204 case 0xF9: //F9 STC 2205 cf = 1; 2206 break; 2207 case 0xFA: //FA CLI 2208 ifl = 0; 2209 break; 2210 case 0xFB: //FB STI 2211 ifl = 1; 2212 break; 2213 case 0xFC: //FC CLD 2214 df = 0; 2215 break; 2216 case 0xFD: //FD STD 2217 df = 1; 2218 break; 2219 case 0xFE: //FE GRP4 Eb 2220 modregrm(); 2221 oper1b = readrm8(rm); oper2b = 1; 2222 if (!reg) { 2223 tempcf = cf; 2224 res8 = oper1b + oper2b; 2225 flag_add8(oper1b, oper2b); 2226 cf = tempcf; writerm8(rm, res8); 2227 } else { 2228 tempcf = cf; 2229 res8 = oper1b - oper2b; 2230 flag_sub8(oper1b, oper2b); 2231 cf = tempcf; writerm8(rm, res8); 2232 } 2233 break; 2234 case 0xFF: //FF GRP5 Ev 2235 modregrm(); 2236 oper1 = readrm16(rm); 2237 op_grp5(); 2238 break; 2239 default: 2240 intcall86(6); //trip invalid opcode exception (this occurs on the 80186+, 8086/8088 CPUs treat them as NOPs 2241 if (verbose) { 2242 //if (opcode==0xF) sprintf(msg, "Illegal opcode: %02X @ %04X:%04X\n", opcode, savecs, saveip); 2243 //else 2244 //sprintf(msg, "Illegal opcode: %02X %02X @ %04X:%04X\n", opcode, getmem8(savecs, saveip + 1), savecs, saveip); 2245 } 2246 2247 break; 2248 } 2249 #ifdef PROFILING 2250 endmicros = micros(); 2251 if (instrtime[opcode]) { 2252 instrtime[opcode] = (instrtime[opcode] + (endmicros - startmicros)) >> 1; 2253 } else { 2254 instrtime[opcode] = endmicros - startmicros; 2255 } 2256 #endif 2257 //if (!running) return; 2258 } 2259 } 2260 2261 void testmem() { 2262 2263 } 2264