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