void bootstrap3() { char *p; char error_str[80]; if (getCF()) { /* * Write error on PC screen - assumes reset has positioned the * cursor for us. Note that we can call the video using a BOP since * the video code does not itself use interrupts. */ sprintf(error_str,"DOS boot error - cannot open hard disk file"); p = error_str; while (*p != '\0') { setAH(14); setAL(*p++); bop(BIOS_VIDEO_IO); } } /* * enable hardware interrupts before we jump to DOS */ setIF(1); }
void GFX_FIFOcnt(u32 val) { u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600); //INFO("GFX FIFO: write context 0x%08X (prev 0x%08X)\n", val, gxstat); if (val & (1<<29)) // clear? (homebrew) { // need to flush before??? GFX_FIFOclear(); return; } T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat); if (gxstat & 0xC0000000) { setIF(0, (1<<21)); } }
int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s <program name>\n", argv[0]); exit(0); } filename = argv[1]; FILE* fp = fopen(filename, "rb"); if (fp == 0) error("opening"); ram = (Byte*)malloc(0x10000); memset(ram, 0, 0x10000); if (ram == 0) { fprintf(stderr, "Out of memory\n"); exit(1); } if (fseek(fp, 0, SEEK_END) != 0) error("seeking"); length = ftell(fp); if (length == -1) error("telling"); if (fseek(fp, 0, SEEK_SET) != 0) error("seeking"); if (length > 0x10000 - 0x100) { fprintf(stderr, "%s is too long to be a .com file\n", filename); exit(1); } if (fread(&ram[0x100], length, 1, fp) != 1) error("reading"); fclose(fp); Word segment = 0x1000; setAX(0x0000); setCX(0x00FF); setDX(segment); registers[3] = 0x0000; setSP(0xFFFE); registers[5] = 0x091C; setSI(0x0100); setDI(0xFFFE); for (int i = 0; i < 4; ++i) registers[8 + i] = segment; Byte* byteData = (Byte*)®isters[0]; int bigEndian = (byteData[2] == 0 ? 1 : 0); int byteNumbers[8] = {0, 2, 4, 6, 1, 3, 5, 7}; for (int i = 0 ; i < 8; ++i) byteRegisters[i] = &byteData[byteNumbers[i] ^ bigEndian]; bool prefix = false; for (int i = 0; i < 1000000000; ++i) { if (!repeating) { if (!prefix) { segmentOverride = -1; rep = 0; } prefix = false; opcode = fetchByte(); } wordSize = ((opcode & 1) != 0); bool sourceIsRM = ((opcode & 2) != 0); int operation = (opcode >> 3) & 7; bool jump; switch (opcode) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x10: case 0x11: case 0x12: case 0x13: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x20: case 0x21: case 0x22: case 0x23: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x30: case 0x31: case 0x32: case 0x33: case 0x38: case 0x39: case 0x3a: case 0x3b: // alu rmv,rmv data = readEA(); if (!sourceIsRM) { destination = data; source = getReg(); } else { destination = getReg(); source = data; } aluOperation = operation; doALUOperation(); if (aluOperation != 7) { if (!sourceIsRM) finishWriteEA(data); else setReg(data); } break; case 0x04: case 0x05: case 0x0c: case 0x0d: case 0x14: case 0x15: case 0x1c: case 0x1d: case 0x24: case 0x25: case 0x2c: case 0x2d: case 0x34: case 0x35: case 0x3c: case 0x3d: // alu accum,i destination = getAccum(); source = !wordSize ? fetchByte() : fetchWord(); aluOperation = operation; doALUOperation(); if (aluOperation != 7) setAccum(); break; case 0x06: case 0x0e: case 0x16: case 0x1e: // PUSH segreg push(registers[operation + 8]); break; case 0x07: case 0x17: case 0x1f: // POP segreg registers[operation + 8] = pop(); break; case 0x26: case 0x2e: case 0x36: case 0x3e: // segment override segmentOverride = operation; prefix = true; break; case 0x27: case 0x2f: // DA if (af() || (al() & 0x0f) > 9) { data = al() + (opcode == 0x27 ? 6 : -6); setAL(data); setAF(true); if ((data & 0x100) != 0) setCF(true); } setCF(cf() || al() > 0x9f); if (cf()) setAL(al() + (opcode == 0x27 ? 0x60 : -0x60)); wordSize = false; data = al(); setPZS(); break; case 0x37: case 0x3f: // AA if (af() || (al() & 0xf) > 9) { setAL(al() + (opcode == 0x37 ? 6 : -6)); setAH(ah() + (opcode == 0x37 ? 1 : -1)); setCA(); } else clearCA(); setAL(al() & 0x0f); break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: // incdec rw destination = rw(); wordSize = true; setRW(incdec((opcode & 8) != 0)); break; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: // PUSH rw push(rw()); break; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: // POP rw setRW(pop()); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: case 0xc0: case 0xc1: case 0xc8: case 0xc9: // invalid case 0xcc: case 0xf0: case 0xf1: case 0xf4: // INT 3, LOCK, HLT case 0x9b: case 0xce: case 0x0f: // WAIT, INTO, POP CS case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: // escape case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: // IN, OUT fprintf(stderr, "Invalid opcode %02x", opcode); runtimeError(""); break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: // Jcond cb switch (opcode & 0x0e) { case 0x00: jump = of(); break; case 0x02: jump = cf(); break; case 0x04: jump = zf(); break; case 0x06: jump = cf() || zf(); break; case 0x08: jump = sf(); break; case 0x0a: jump = pf(); break; case 0x0c: jump = sf() != of(); break; default: jump = sf() != of() || zf(); break; } jumpShort(fetchByte(), jump == ((opcode & 1) == 0)); break; case 0x80: case 0x81: case 0x82: case 0x83: // alu rmv,iv destination = readEA(); data = fetch(opcode == 0x81); if (opcode != 0x83) source = data; else source = signExtend(data); aluOperation = modRMReg(); doALUOperation(); if (aluOperation != 7) finishWriteEA(data); break; case 0x84: case 0x85: // TEST rmv,rv data = readEA(); test(data, getReg()); break; case 0x86: case 0x87: // XCHG rmv,rv data = readEA(); finishWriteEA(getReg()); setReg(data); break; case 0x88: case 0x89: // MOV rmv,rv ea(); finishWriteEA(getReg()); break; case 0x8a: case 0x8b: // MOV rv,rmv setReg(readEA()); break; case 0x8c: // MOV rmw,segreg ea(); wordSize = 1; finishWriteEA(registers[modRMReg() + 8]); break; case 0x8d: // LEA address = ea(); if (!useMemory) runtimeError("LEA needs a memory address"); setReg(address); break; case 0x8e: // MOV segreg,rmw wordSize = 1; data = readEA(); registers[modRMReg() + 8] = data; break; case 0x8f: // POP rmw writeEA(pop()); break; case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: // XCHG AX,rw data = ax(); setAX(rw()); setRW(data); break; case 0x98: // CBW setAX(signExtend(al())); break; case 0x99: // CWD setDX((ax() & 0x8000) == 0 ? 0x0000 : 0xffff); break; case 0x9a: // CALL cp savedIP = fetchWord(); savedCS = fetchWord(); farCall(); break; case 0x9c: // PUSHF push((flags & 0x0fd7) | 0xf000); break; case 0x9d: // POPF flags = pop() | 2; break; case 0x9e: // SAHF flags = (flags & 0xff02) | ah(); break; case 0x9f: // LAHF setAH(flags & 0xd7); break; case 0xa0: case 0xa1: // MOV accum,xv data = read(fetchWord()); setAccum(); break; case 0xa2: case 0xa3: // MOV xv,accum write(getAccum(), fetchWord()); break; case 0xa4: case 0xa5: // MOVSv stoS(lodS()); doRep(); break; case 0xa6: case 0xa7: // CMPSv lodDIS(); source = data; sub(); doRep(); break; case 0xa8: case 0xa9: // TEST accum,iv data = fetch(wordSize); test(getAccum(), data); break; case 0xaa: case 0xab: // STOSv stoS(getAccum()); doRep(); break; case 0xac: case 0xad: // LODSv data = lodS(); setAccum(); doRep(); break; case 0xae: case 0xaf: // SCASv lodDIS(); destination = getAccum(); source = data; sub(); doRep(); break; case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: setRB(fetchByte()); break; case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: // MOV rv,iv setRW(fetchWord()); break; case 0xc2: case 0xc3: case 0xca: case 0xcb: // RET savedIP = pop(); savedCS = (opcode & 8) == 0 ? cs() : pop(); if (!wordSize) setSP(sp() + fetchWord()); farJump(); break; case 0xc4: case 0xc5: // LES/LDS ea(); farLoad(); *modRMRW() = savedIP; registers[8 + (!wordSize ? 0 : 3)] = savedCS; break; case 0xc6: case 0xc7: // MOV rmv,iv ea(); finishWriteEA(fetch(wordSize)); break; case 0xcd: data = fetchByte(); if (data != 0x21) { fprintf(stderr, "Unknown interrupt 0x%02x", data); runtimeError(""); } switch (ah()) { case 2: printf("%c", dl()); break; case 0x4c: printf("*** Bytes: %i\n", length); printf("*** Cycles: %i\n", ios); printf("*** EXIT code %i\n", al()); exit(0); break; default: fprintf(stderr, "Unknown DOS call 0x%02x", data); runtimeError(""); } break; case 0xcf: ip = pop(); setCS(pop()); flags = pop() | 2; break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: // rot rmv,n data = readEA(); if ((opcode & 2) == 0) source = 1; else source = cl(); while (source != 0) { destination = data; switch (modRMReg()) { case 0: // ROL data <<= 1; doCF(); data |= (cf() ? 1 : 0); setOFRotate(); break; case 1: // ROR setCF((data & 1) != 0); data >>= 1; if (cf()) data |= (!wordSize ? 0x80 : 0x8000); setOFRotate(); break; case 2: // RCL data = (data << 1) | (cf() ? 1 : 0); doCF(); setOFRotate(); break; case 3: // RCR data >>= 1; if (cf()) data |= (!wordSize ? 0x80 : 0x8000); setCF((destination & 1) != 0); setOFRotate(); break; case 4: // SHL case 6: data <<= 1; doCF(); setOFRotate(); setPZS(); break; case 5: // SHR setCF((data & 1) != 0); data >>= 1; setOFRotate(); setAF(true); setPZS(); break; case 7: // SAR setCF((data & 1) != 0); data >>= 1; if (!wordSize) data |= (destination & 0x80); else data |= (destination & 0x8000); setOFRotate(); setAF(true); setPZS(); break; } --source; } finishWriteEA(data); break; case 0xd4: // AAM data = fetchByte(); if (data == 0) divideOverflow(); setAH(al() / data); setAL(al() % data); wordSize = true; setPZS(); break; case 0xd5: // AAD data = fetchByte(); setAL(al() + ah()*data); setAH(0); setPZS(); break; case 0xd6: // SALC setAL(cf() ? 0xff : 0x00); break; case 0xd7: // XLATB setAL(readByte(bx() + al())); break; case 0xe0: case 0xe1: case 0xe2: // LOOPc cb setCX(cx() - 1); jump = (cx() != 0); switch (opcode) { case 0xe0: if (zf()) jump = false; break; case 0xe1: if (!zf()) jump = false; break; } jumpShort(fetchByte(), jump); break; case 0xe3: // JCXZ cb jumpShort(fetchByte(), cx() == 0); break; case 0xe8: // CALL cw call(ip + fetchWord()); break; case 0xe9: // JMP cw ip += fetchWord(); break; case 0xea: // JMP cp savedIP = fetchWord(); savedCS = fetchWord(); farJump(); break; case 0xeb: // JMP cb jumpShort(fetchByte(), true); break; case 0xf2: case 0xf3: // REP rep = opcode == 0xf2 ? 1 : 2; prefix = true; break; case 0xf5: // CMC flags ^= 1; break; case 0xf6: case 0xf7: // math rmv data = readEA(); switch (modRMReg()) { case 0: case 1: // TEST rmv,iv test(data, fetch(wordSize)); break; case 2: // NOT iv finishWriteEA(~data); break; case 3: // NEG iv source = data; destination = 0; sub(); finishWriteEA(data); break; case 4: case 5: // MUL rmv, IMUL rmv source = data; destination = getAccum(); data = destination; setSF(); setPF(); data *= source; setAX(data); if (!wordSize) { if (modRMReg() == 4) setCF(ah() != 0); else { if ((source & 0x80) != 0) setAH(ah() - destination); if ((destination & 0x80) != 0) setAH(ah() - source); setCF(ah() == ((al() & 0x80) == 0 ? 0 : 0xff)); } } else { setDX(data >> 16); if (modRMReg() == 4) { data |= dx(); setCF(dx() != 0); } else { if ((source & 0x8000) != 0) setDX(dx() - destination); if ((destination & 0x8000) != 0) setDX(dx() - source); data |= dx(); setCF(dx() == ((ax() & 0x8000) == 0 ? 0 : 0xffff)); } } setZF(); setOF(cf()); break; case 6: case 7: // DIV rmv, IDIV rmv source = data; if (source == 0) divideOverflow(); if (!wordSize) { destination = ax(); if (modRMReg() == 6) { div(); if (data > 0xff) divideOverflow(); } else { destination = ax(); if ((destination & 0x8000) != 0) destination |= 0xffff0000; source = signExtend(source); div(); if (data > 0x7f && data < 0xffffff80) divideOverflow(); } setAH(remainder); setAL(data); } else { destination = (dx() << 16) + ax(); div(); if (modRMReg() == 6) { if (data > 0xffff) divideOverflow(); } else { if (data > 0x7fff && data < 0xffff8000) divideOverflow(); } setDX(remainder); setAX(data); } break; } break; case 0xf8: case 0xf9: // STC/CLC setCF(wordSize); break; case 0xfa: case 0xfb: // STI/CLI setIF(wordSize); break; case 0xfc: case 0xfd: // STD/CLD setDF(wordSize); break; case 0xfe: case 0xff: // misc ea(); if ((!wordSize && modRMReg() >= 2 && modRMReg() <= 6) || modRMReg() == 7) { fprintf(stderr, "Invalid instruction %02x %02x", opcode, modRM); runtimeError(""); } switch (modRMReg()) { case 0: case 1: // incdec rmv destination = readEA2(); finishWriteEA(incdec(modRMReg() != 0)); break; case 2: // CALL rmv call(readEA2()); break; case 3: // CALL mp farLoad(); farCall(); break; case 4: // JMP rmw ip = readEA2(); break; case 5: // JMP mp farLoad(); farJump(); break; case 6: // PUSH rmw push(readEA2()); break; } break; } } runtimeError("Timed out"); }
void printer_io() { #ifdef PRINTER half_word time_out, status; word printer_io_address, printer_io_reg, printer_status_reg, printer_control_reg; boolean printer_busy = TRUE; unsigned long time_count; int adapter; #ifdef NTVDM int bopsubfunction = getSI(); switch (bopsubfunction) { #ifdef MONITOR case 0: /* this is the bop to flush 16bit printer buffer */ printer_bop_flush (); return; #endif case 1: case 2: /* this is the bop to track a DOS open/close on LPTn */ printer_bop_openclose (bopsubfunction); return; } #endif setIF(1); adapter = getDX() % NUM_PARALLEL_PORTS; sas_loadw(port_address[adapter], &printer_io_address); printer_io_reg = printer_io_address; printer_status_reg = printer_io_address + 1; printer_control_reg = printer_io_address + 2; sas_load(timeout_address[adapter], &time_out); time_count = time_out * 0xFFFF; if (printer_io_address != 0) { IDLE_comlpt (); switch(getAH()) { case 0: /* Check the port status for busy before sending the character*/ while(printer_busy && time_count > 0) { /* The host_lpt_status() should check for status changes */ /* possibly by calling AsyncEventManager() if it's using */ /* XON /XOFF flow control. */ inb(printer_status_reg, &status); if (status & 0x80) printer_busy = FALSE; else time_count--; } if (printer_busy) { status &= 0xF8; /* clear bottom unused bits */ status |= 1; /* set error flag */ } else { /* Only send the character if the port isn't still busy */ outb(printer_io_reg, getAL()); outb(printer_control_reg, 0x0D); /* strobe low-high */ outb(printer_control_reg, 0x0C); /* strobe high-low */ inb(printer_status_reg, &status); status &= 0xF8; /* clear unused bits */ } status ^= 0x48; /* flip the odd bit */ setAH(status); break; case 1: outb(printer_control_reg, 0x08); /* set init line low */ outb(printer_control_reg, 0x0C); /* set init line high */ inb(printer_status_reg, &status); status &= 0xF8; /* clear unused bits */ status ^= 0x48; /* flip the odd bit */ setAH(status); break; case 2: inb(printer_status_reg, &status); status &= 0xF8; /* clear unused bits */ status ^= 0x48; /* flip the odd bit */ setAH(status); break; default: break; } } #endif }
void rs232_io() { #ifdef BIT_ORDER2 union { half_word all; struct { HALF_WORD_BIT_FIELD word_length:2; HALF_WORD_BIT_FIELD stop_bit:1; HALF_WORD_BIT_FIELD parity:2; HALF_WORD_BIT_FIELD baud_rate:3; } bit; } parameters; #endif #ifdef BIT_ORDER1 union { half_word all; struct { HALF_WORD_BIT_FIELD baud_rate:3; HALF_WORD_BIT_FIELD parity:2; HALF_WORD_BIT_FIELD stop_bit:1; HALF_WORD_BIT_FIELD word_length:2; } bit; } parameters; #endif DIVISOR_LATCH divisor_latch; int j; half_word timeout; sys_addr timeout_location; /* clear com/lpt idle flag */ IDLE_comlpt (); setIF(1); /* * Which adapter? */ switch (getDX ()) { case 0: port = RS232_COM1_PORT_START; timeout_location = RS232_COM1_TIMEOUT; break; case 1: port = RS232_COM2_PORT_START; timeout_location = RS232_COM2_TIMEOUT; break; case 2: port = RS232_COM3_PORT_START; timeout_location = RS232_COM3_TIMEOUT; break; case 3: port = RS232_COM4_PORT_START; timeout_location = RS232_COM4_TIMEOUT; break; default: break; } /* * Determine function */ switch (getAH ()) { case 0: /* * Initialise the communication port */ value = 0x80; /* set DLAB */ outb(port + (io_addr) RS232_LCR, value); /* * Set baud rate */ parameters.all = getAL(); divisor_latch.all = divisors[parameters.bit.baud_rate]; outb(port + (io_addr) RS232_IER, divisor_latch.byte.MSByte); outb(port + (io_addr) RS232_TX_RX, divisor_latch.byte.LSByte); /* * Set word length, stop bits and parity */ parameters.bit.baud_rate = 0; outb(port + (io_addr) RS232_LCR, parameters.all); /* * Disable interrupts */ value = 0; outb(port + (io_addr) RS232_IER, value); return_status(); break; case 1: /* * Send char over the comms line */ /* * Set DTR and RTS */ outb(port + (io_addr) RS232_MCR, 3); /* * Real BIOS checks CTS and DSR - we know DSR ok. * Real BIOS check THRE - we know it's ok. * We only check CTS - this is supported on a few ports, eg. Macintosh. */ /* * Wait for CTS to go high, or timeout */ sas_load(timeout_location, &timeout); for ( j = 0; j < timeout; j++) { inb(port + (io_addr) RS232_MSR, &value); if(value & 0x10)break; /* CTS High, all is well */ } if(j < timeout) { outb(port + (io_addr) RS232_TX_RX, getAL()); /* Send byte */ inb(port + (io_addr) RS232_LSR, &value); setAH(value); /* Return Line Status Reg in AH */ } else { setAH(value | 0x80); /* Indicate time out */ } break; case 2: /* * Receive char over the comms line */ /* * Set DTR */ value = 1; outb(port + (io_addr) RS232_MCR, value); /* * Real BIOS checks DSR - we know it's ok. */ /* * Wait for data to appear, or timeout(just an empirical guess) */ sas_load(timeout_location, &timeout); for ( j = 0; j < timeout; j++) { inb(port + (io_addr) RS232_LSR, &value); if ( (value & 1) == 1 ) { /* * Data ready go read it */ value &= 0x1e; /* keep error bits only */ setAH(value); inb(port + (io_addr) RS232_TX_RX, &value); setAL(value); return; } } /* * Set timeout */ value |= 0x80; setAH(value); break; case 3: /* * Return the communication port status */ return_status(); break; case 4: /* * EXTENDED (PS/2) Initialise the communication port */ value = 0x80; /* set DLAB */ outb(port + (io_addr) RS232_LCR, value); parameters.bit.word_length = getCH(); parameters.bit.stop_bit = getBL(); parameters.bit.parity = getBH(); parameters.bit.baud_rate = getCL(); /* Set baud rate */ divisor_latch.all = divisors[parameters.bit.baud_rate]; outb(port + (io_addr) RS232_IER, divisor_latch.byte.MSByte); outb(port + (io_addr) RS232_TX_RX, divisor_latch.byte.LSByte); /* * Set word length, stop bits and parity */ parameters.bit.baud_rate = 0; outb(port + (io_addr) RS232_LCR, parameters.all); /* * Disable interrupts */ value = 0; outb(port + (io_addr) RS232_IER, value); return_status(); break; case 5: /* EXTENDED Comms Port Control */ switch( getAL() ) { case 0: /* Read modem control register */ inb( port + (io_addr) RS232_MCR, &value); setBL(value); break; case 1: /* Write modem control register */ outb( port + (io_addr) RS232_MCR, getBL()); break; } /* Return the communication port status */ return_status(); break; default: /* ** Yes both XT and AT BIOS's really do this. */ setAH( getAH()-3 ); break; } }