/* Functions to deal with the AWE32's I/O ports */ static inline void write_word(int reg,int channel,int port,int data) { int out_port=_emu8k_baseport; switch(port) { case 0: out_port+=0x0000; break; case 1: out_port+=0x0400; break; case 2: out_port+=0x0402; break; case 3: out_port+=0x0800; break; default: return; } outportw(_emu8k_baseport+0x802,(reg<<5)+(channel&0x1f)); outportw(out_port,data); }
void screenStatus(boolean Enabled) { if(Enabled == TRUE) { outportw(0x3c4, 1); /*Turns monitor on*/ outportw(0x3c5, 0x00); } else { outportw(0x3c4, 1); /*Turns monitor off*/ outportw(0x3c5, inportb(0x3c5) | 0x20); } screenEnabled = Enabled; }
void pci_write_conf16(uint8 bus, uint8 dev, uint8 func, uint8 reg, uint16 val) { uint32 port = (0x80000000U)|(bus<<16)|(dev<<11)|(func<<8)|(reg); outportl(0xcf8, port); outportw((uint16)(0xcfc + (reg&2)), val); }
void pci_write_word(uint8_t bus, uint8_t slot, uint8_t func, uint32_t offset, uint16_t word) { uint32_t id = ((bus) << 16) | ((slot) << 11) | ((func) << 8); uint32_t addr = 0x80000000 | id | (offset & 0xfc); outportl(0xCF8, addr); outportw(0xCFC + (offset & 0x02), word); }
/* xtended_init: * Selects the unchained 640x400 mode. */ static BITMAP *xtended_init(int w, int h, int v_w, int v_h, int color_depth) { unsigned long addr; BITMAP *b; /* Do not continue if this version of Allegro was built in C-only mode. * The bank switchers assume asm-mode calling conventions, but the * library would try to call them with C calling conventions. */ #ifdef ALLEGRO_NO_ASM return NULL; #endif /* see modexsms.c */ _split_modex_screen_ptr = really_split_modex_screen; /* check it is a valid resolution */ if (color_depth != 8) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Xtended mode only supports 8 bit color")); return NULL; } if ((w != 640) || (h != 400) || (v_w > 640) || (v_h > 400)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Xtended mode only supports 640x400")); return NULL; } /* lock everything that is used to draw mouse pointers */ LOCK_VARIABLE(__modex_vtable); LOCK_FUNCTION(_x_draw_sprite); LOCK_FUNCTION(_x_blit_from_memory); LOCK_FUNCTION(_x_blit_to_memory); /* set VESA mode 0x100 */ addr = _set_vga_mode(0x100); if (!addr) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VESA mode 0x100 not available")); return NULL; } outportw(0x3C4, 0x0604); /* disable chain-4 */ /* we only use 1/4th of the width for the bitmap line pointers */ b = _make_bitmap(640/4, 400, addr, &gfx_xtended, 8, 640/4); if (!b) return NULL; b->w = b->cr = 640; b->vtable = &__modex_vtable; b->id |= BMP_ID_PLANAR; setup_x_magic(b); return b; }
static inline unsigned int read_word(int reg,int channel,int port) { int in_port=_emu8k_baseport; switch(port) { case 0: in_port+=0x0000; break; case 1: in_port+=0x0400; break; case 2: in_port+=0x0402; break; case 3: in_port+=0x0800; break; default: return 0; } outportw(_emu8k_baseport+0x802,(reg<<5)+(channel&0x1f)); return inportw(in_port); }
static int driver_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags) { int depth = MAX(8, depth_arg); int i; fb_dos_detect(); if (flags & DRIVER_OPENGL) return -1; if ((w != 320) || (h != 240) || (depth != 8)) { return -1; } /* set base video mode */ fb_dos.regs.x.ax = 0x13; __dpmi_int(0x10, &fb_dos.regs); /* tweak to Mode X */ outportw(SC_INDEX, 0x0604); /* disable chain4 */ outportw(SC_INDEX, 0x0100); /* synchronous reset */ outportb(MISC_OUTPUT, 0xE3); /* select 25 MHz dot clock & 60 Hz scanning rate */ outportw(SC_INDEX, 0x0300); /* undo reset (restart sequencer) */ outportb(CRTC_INDEX, 0x11); /* VSync End reg contains register write protect bit */ outportb(CRTC_INDEX+1, inportb(CRTC_INDEX+1) & 0x7F); /* remove write protect on various CRTC registers */ for (i = 0; i < CRT_PARM_LENGTH; i++) { outportw(CRTC_INDEX, CRTParams[i]); } refresh_rate = 60; fb_dos.update = driver_update; fb_dos.update_len = (unsigned int)end_of_driver_update - (unsigned int)driver_update; fb_dos.set_palette = fb_dos_vga_set_palette; return fb_dos_init(title, w, h, depth, refresh_rate, flags); }
/* * Mode-X masked line stretcher. */ static void stretch_masked_linex(uintptr_t dptr, unsigned char *sptr) { int plane; int dw = _al_stretch.linesize; int first_xc = _al_stretch.xcstart; ASSERT(dptr); ASSERT(sptr); for (plane = 0; plane < 4; plane++) { int xc = first_xc; unsigned char *s = sptr; uintptr_t d = dptr / 4; uintptr_t dend = (dptr + dw) / 4; outportw(0x3C4, (0x100 << (dptr & 3)) | 2); for (; d < dend; d++, s += 4 * _al_stretch.sxinc) { unsigned long color = *s; if (color != 0) bmp_write8(d, color); if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; if (xc <= 0) s++, xc += _al_stretch.xcinc; else xc -= _al_stretch.xcdec; } /* Move to the beginning of next plane. */ if (first_xc <= 0) { sptr++; first_xc += _al_stretch.xcinc; } else first_xc -= _al_stretch.xcdec; dptr++; sptr += _al_stretch.sxinc; dw--; } }
static void load(Vga* vga, Ctlr* ctlr) { ushort advfunc; s3generic.load(vga, ctlr); vgaxo(Crtx, 0x60, vga->crt[0x60]); vgaxo(Crtx, 0x61, vga->crt[0x61]); vgaxo(Crtx, 0x62, vga->crt[0x62]); advfunc = 0x0000; if(ctlr->flag & Uenhanced){ if(vga->mode->x == 1024 || vga->mode->x == 800) advfunc = 0x0057; else advfunc = 0x0053; } outportw(0x4AE8, advfunc); }
void shutdown() { // Questa è l'istruzione vecchia che spegneva solo la macchina virtuale QEMU! //asm volatile ("outw %1, %0" : : "dN" ((unsigned short)0xB004), "a" ((unsigned short)0x2000)); // Questa è quella nuova che spegne tutte le VM, ma non quelle reali! asm volatile ("cli"); for ( ; ; ) { // Funziona per QEMU e Bochs outportw (0xB004, 0x2000); // Magic shutdown per Bochs e QEMU for (const char *s = "Shutdown"; *s; ++s) outportb (0x8900, *s); // Magic code per VMWare asm volatile ("cli; hlt"); } }
/* * write a block at the logical block number indicated. */ int write_sector(unsigned char *buf, int drive_num, unsigned int lba, unsigned int num_sectors) { int i; unsigned short *wordbuf; /* Initialize the command block registers */ outportb(IDE_SECTOR_COUNT, num_sectors); outportb(IDE_SECTOR_NUMBER, LBA_LOW_BYTE(lba)); outportb(IDE_CYLINDER_LOW, LBA_HIGH_BYTE(lba)); outportb(IDE_CYLINDER_HIGH, LBA_EXTENDED_LOW_BYTE(lba)); if (drive_num == 0) outportb(IDE_DRIVE_HEAD, IDE_DRIVE0 | LBA_EXTENDED_HIGH_BYTE(lba)); else if (drive_num == 1) outportb(IDE_DRIVE_HEAD, IDE_DRIVE1 | LBA_EXTENDED_HIGH_BYTE(lba)); /* Load command register with the write command code */ outportb(IDE_COMMAND, IDE_CMD_WRITE_SECTORS_RETRY); while (inportb(IDE_STATUS) & IDE_STATUS_BUSY) /* wait for the drive */ ; wordbuf = (unsigned short *) buf; for (i = 0; i < 256 * num_sectors; i++) wordbuf[i] = outportw(IDE_DATA_PORT); /* wait for the drive */ while (inportb(IDE_STATUS) & IDE_STATUS_BUSY); if (inportb(IDE_STATUS) & IDE_STATUS_ERROR) return IDE_ERR_IO_ERROR; return IDE_ERR_NOERROR; }
static void driver_update(void) { int plane; unsigned long screen; unsigned char *buffer; int x, y; _farsetsel(_dos_ds); for (plane = 0; plane < 4; plane++) { buffer = (unsigned char *)__fb_gfx->framebuffer + plane; outportw(SC_INDEX, (0x100 << plane) | 0x02); /* set write plane */ screen = 0xA0000; for (y = 0; y < fb_dos.h; y++) { if (__fb_gfx->dirty[y]) { for (x = 0; x < fb_dos.w; x += 4, screen++) { _farnspokeb(screen, buffer[x]); } } else { screen += fb_dos.w / 4; } buffer += fb_dos.w; } } }
inline uint16_t regin(uint16_t reg){ outportw(0x01CE,reg); return inportw(0x01CF); }
inline void regout(uint16_t reg,uint16_t data){ outportw(0x01CE,reg); outportw(0x01CF,data); }
void convert_image_to_allegro_templ(const Image* image, BITMAP* bmp, int _x, int _y, const Palette* palette) { const LockImageBits<ImageTraits> bits(image); typename LockImageBits<ImageTraits>::const_iterator src_it = bits.begin(); #ifdef _DEBUG typename LockImageBits<ImageTraits>::const_iterator src_end = bits.end(); #endif int depth = bitmap_color_depth(bmp); int x, y, w = image->width(), h = image->height(); unsigned long bmp_address; bmp_select(bmp); switch (depth) { case 8: #if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX if (is_planar_bitmap (bmp)) { for (y=0; y<h; ++y) { bmp_address = (unsigned long)bmp->line[_y]; for (x=0; x<w; ++x) { ASSERT(src_it != src_end); outportw(0x3C4, (0x100<<((_x+x)&3))|2); bmp_write8(bmp_address+((_x+x)>>2), (convert_color_to_allegro<ImageTraits, 8>(*src_it, palette))); ++src_it; address++; } _y++; } } else { #endif for (y=0; y<h; ++y) { bmp_address = bmp_write_line(bmp, _y)+_x; for (x=0; x<w; ++x) { ASSERT(src_it != src_end); bmp_write8(bmp_address, (convert_color_to_allegro<ImageTraits, 8>(*src_it, palette))); ++bmp_address; ++src_it; } _y++; } #if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX } #endif break; case 15: _x <<= 1; for (y=0; y<h; y++) { bmp_address = bmp_write_line(bmp, _y)+_x; for (x=0; x<w; ++x) { ASSERT(src_it != src_end); bmp_write15(bmp_address, (convert_color_to_allegro<ImageTraits, 15>(*src_it, palette))); bmp_address += 2; ++src_it; } _y++; } break; case 16: _x <<= 1; for (y=0; y<h; ++y) { bmp_address = bmp_write_line(bmp, _y)+_x; for (x=0; x<w; ++x) { ASSERT(src_it != src_end); bmp_write16(bmp_address, (convert_color_to_allegro<ImageTraits, 16>(*src_it, palette))); bmp_address += 2; ++src_it; } _y++; } break; case 24: _x *= 3; for (y=0; y<h; ++y) { bmp_address = bmp_write_line(bmp, _y)+_x; for (x=0; x<w; ++x) { ASSERT(src_it != src_end); bmp_write24(bmp_address, (convert_color_to_allegro<ImageTraits, 24>(*src_it, palette))); bmp_address += 3; ++src_it; } _y++; } break; case 32: _x <<= 2; for (y=0; y<h; ++y) { bmp_address = bmp_write_line(bmp, _y)+_x; for (x=0; x<w; ++x) { ASSERT(src_it != src_end); bmp_write32(bmp_address, (convert_color_to_allegro<ImageTraits, 32>(*src_it, palette))); bmp_address += 4; ++src_it; } _y++; } break; }
uint64 init_nic_pcnet(struct pci_dev *d) { uint32 io = d->bars[0].addr; uint16 t16; uint32 i; struct pcnet_private *priv = NULL; struct eth_dev *eth; priv = (struct pcnet_private *)kmalloc_align(sizeof(struct pcnet_private), "pcnet_private", NULL); if(priv == NULL) { printf("init_nic: cannot allocate pcnet_private\n"); goto fail; } priv->dev = d; priv->init = (struct pcnet_init_32 *)kmalloc_align(sizeof(struct pcnet_init_32), "pcnet_init", NULL); if(priv->init == NULL) { printf("init_nic: cannot allocate pcnet_init\n"); goto fail_free_private; } priv->rx = (struct pcnet_rx_32 *)kmalloc_align(sizeof(struct pcnet_rx_32) * DRE_COUNT, "pcnet_rx", NULL); if(priv->rx == NULL) { printf("init_nic: cannot allocate pcnet_rx\n"); goto fail_free_init; } priv->tx = (struct pcnet_tx_32 *)kmalloc_align(sizeof(struct pcnet_tx_32) * DRE_COUNT, "pcnet_tx", NULL); if(priv->tx == NULL) { printf("init_nic: cannot allocate pcnet_tx\n"); goto fail_free_rx; } eth = eth_alloc(priv, &pcnet_ops); if(eth == NULL) { printf("init_nic: failed to allocate eth\n"); goto fail_free_tx; } priv->eth = eth; t16 = pci_read_conf16(d->bus, d->dev, d->func, PCI_CMD_REG); if(!(t16 & PCI_CMD_MASTER)) { t16 |= PCI_CMD_MASTER|PCI_CMD_IO|PCI_CMD_MEMORY; pci_write_conf16(d->bus, d->dev, d->func, PCI_CMD_REG, t16); t16 = pci_read_conf16(d->bus, d->dev, d->func, PCI_CMD_REG); printf("init_nic: enabling PCI master bit\n"); } //writeCSR(io, 0, 0x04); // this switches to 32bit too early printf("init_nic: eth%x mac_addr=", eth->unit); for (i=0; i<6; i++) { printf("%x", eth->addr[i] = priv->init->PADR[i] = inportb(io+i)); if(i!=5) printf(":"); //else printf("\n"); } // Put the NIC in STOP outportw(io + 0x12, 0); outportw(io + 0x10, CSR0_STOP); // Reset the NIC inportw(io + 0x14); // Switch to DWORD mode outportl(io + 0x10, 0x00); // Switch to 32bit and PCNET_PCI_II style writeBCR(io, 20, CSR58_SSIZE32|CSR58_PCNET_PCII); // Obtain the chip version(s) priv->chip_version_lo = readCSR(io, 88); printf(" ver=%x:", priv->chip_version_lo); priv->chip_version_up = (readCSR(io, 89) & 0x0000ffff); printf("%x", priv->chip_version_up); // Set-up the initialisation block priv->init->MODE = 0; priv->init->RLEN = TX_TLEN; priv->init->TLEN = RX_RLEN; priv->init->LADRF = 0x0; priv->init->RDRA = (uint32)(uint64)priv->rx; priv->init->TDRA = (uint32)(uint64)priv->tx; for(i=0; i<DRE_COUNT; i++) { priv->rx[i].RBADR = (uint32)(uint64)kmalloc_align(1544, "pcnet rx", NULL); priv->rx[i].BCNT = SECOND_COMP(1544); priv->rx[i].ones = 0xf; priv->rx[i].OWN = 1; priv->tx[i].TBADR = 0; priv->tx[i].ones = 0xf; } // Tell the NIC where the init block is writeCSR(io, 1, ((uint32)(uint64)priv->init) & 0x0000ffff); writeCSR(io, 2, (((uint32)(uint64)priv->init) & 0xffff0000) >> 16); // Switch NIC state to INIT writeCSR(io, 0, (readCSR(io, 0) | CSR0_INIT) & ~ CSR0_STOP); printf(" INIT"); writeCSR(io, 4, (readCSR(io, 4)|CSR4_DMA_PLUSA|CSR4_APAD_XMIT|CSR4_TXSTRTM) & ~CSR4_DPOLL); writeBCR(io, 2, readBCR(io, 2)|BCR2_ASEL); //writeCSR(io, 3, (readCSR(io, 3)) & ~CSR3_ALL_INTS); //writeCSR(io, 4, (readCSR(io, 4)) & ~CSR4_ALL_INTS); // Switch NIC state to START, enable RX/TX, disable STOP and enable interrupts writeCSR(io, 0, (readCSR(io, 0)|CSR0_STRT|/*CSR0_IENA|*/CSR0_RXON|CSR0_TXON) & ~CSR0_STOP); printf(" STRT\n"); return 0; //fail_free_eth: // eth_free(eth); fail_free_tx: kfree(priv->tx); fail_free_rx: kfree(priv->rx); fail_free_init: kfree(priv->init); fail_free_private: kfree(priv); fail: return -1; }
void pci_write16(uint32_t id, uint32_t reg, uint16_t data) { uint32_t address = 0x80000000 | id | (reg & 0xfc); outportl(PCI_CONFIG_ADDR, address); outportw(PCI_CONFIG_DATA + (reg & 0x02), data); }
/* modex_init: * Selects a tweaked VGA mode and creates a screen bitmap for it. */ static BITMAP *modex_init(int w, int h, int v_w, int v_h, int color_depth) { TWEAKED_MODE *mode = xmodes; VGA_REGISTER *reg; BITMAP *b; unsigned long addr; int c; /* Do not continue if this version of Allegro was built in C-only mode. * The bank switchers assume asm-mode calling conventions, but the * library would try to call them with C calling conventions. */ #ifdef ALLEGRO_NO_ASM return NULL; #endif /* see modexsms.c */ _split_modex_screen_ptr = really_split_modex_screen; /* check it is a valid resolution */ if (color_depth != 8) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Mode-X only supports 8 bit color")); return NULL; } /* search the mode table for the requested resolution */ while ((mode->regs) && ((mode->w != w) || (mode->h != h))) mode++; if (!mode->regs) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not a VGA mode-X resolution")); return NULL; } /* round up virtual size if required (v_w must be a multiple of eight) */ v_w = MAX(w, (v_w+7) & 0xFFF8); v_h = MAX(h, v_h); if (v_h > 0x40000/v_w) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen size too large")); return NULL; } /* calculate virtual height = vram / width */ v_h = 0x40000 / v_w; /* lock everything that is used to draw mouse pointers */ LOCK_VARIABLE(__modex_vtable); LOCK_FUNCTION(_x_draw_sprite); LOCK_FUNCTION(_x_blit_from_memory); LOCK_FUNCTION(_x_blit_to_memory); /* set the base video mode, then start tweaking things */ addr = _set_vga_mode(mode->parent); if (!addr) return NULL; outportw(0x3C4, 0x0100); /* synchronous reset */ outportb(0x3D4, 0x11); /* enable crtc regs 0-7 */ outportb(0x3D5, inportb(0x3D5) & 0x7F); outportw(0x3C4, 0x0604); /* disable chain-4 */ for (reg=mode->regs; reg->port; reg++) { /* set the VGA registers */ if (reg->port == 0x3C0) { inportb(0x3DA); outportb(0x3C0, reg->index | 0x20); outportb(0x3C0, reg->value); } else if (reg->port == 0x3C2) { outportb(reg->port, reg->value); } else { outportb(reg->port, reg->index); outportb(reg->port+1, reg->value); } } if (mode->hrs) { outportb(0x3D4, 0x11); outportb(0x3D5, inportb(0x3D5)&0x7F); outportb(0x3D4, 0x04); outportb(0x3D5, inportb(0x3D5)+mode->hrs); outportb(0x3D4, 0x11); outportb(0x3D5,inportb(0x3D5)|0x80); } if (mode->shift) { outportb(0x3CE, 0x05); outportb(0x3CF, (inportb(0x3CF)&0x60)|0x40); inportb(0x3DA); outportb(0x3C0, 0x30); outportb(0x3C0, inportb(0x3C1)|0x40); for (c=0; c<16; c++) { outportb(0x3C0, c); outportb(0x3C0, c); } outportb(0x3C0, 0x20); } if (mode->repeat) { outportb(0x3D4, 0x09); outportb(0x3D5,(inportb(0x3D5)&0x60)|mode->repeat); } outportb(0x3D4, 0x13); /* set scanline length */ outportb(0x3D5, v_w/8); outportw(0x3C4, 0x0300); /* restart sequencer */ /* We only use 1/4th of the real width for the bitmap line pointers, * so they can be used directly for writing to vram, eg. the address * for pixel(x,y) is bmp->line[y]+(x/4). Divide the x coordinate, but * not the line pointer. The clipping position and bitmap width are * stored in the linear pixel format, though, not as mode-X planes. */ b = _make_bitmap(v_w/4, v_h, addr, &gfx_modex, 8, v_w/4); if (!b) return NULL; b->w = b->cr = v_w; b->vtable = &__modex_vtable; b->id |= BMP_ID_PLANAR; setup_x_magic(b); gfx_modex.w = w; gfx_modex.h = h; if (_timer_use_retrace) { gfx_modex.request_scroll = request_modex_scroll; gfx_modex.poll_scroll = poll_modex_scroll; } else { gfx_modex.request_scroll = NULL; gfx_modex.poll_scroll = NULL; } #ifdef ALLEGRO_LINUX b->vtable->acquire = __al_linux_acquire_bitmap; b->vtable->release = __al_linux_release_bitmap; #endif return b; }
static void load(Vga* vga, Ctlr*) { outportw(Pixmask, 0x00); outportw(Subsys, 0x8000|0x1000); outportw(Subsys, 0x4000|0x1000); outportw(Pixmask, 0xFF); outportw(FrgdMix, 0x47); outportw(BkgdMix, 0x07); outportw(Multifunc, ScissorsT|0x000); outportw(Multifunc, ScissorsL|0x000); outportw(Multifunc, ScissorsB|(vga->vmz/vga->mode->x-1)); outportw(Multifunc, ScissorsR|(vga->mode->x-1)); outportw(WrtMask, 0xFFFF); outportw(Multifunc, PixCntl|0x0000); }
/* x_write: * Inline helper for the C drawing functions: writes a pixel onto a * mode-X bitmap, performing clipping but ignoring the drawing mode. */ static INLINE void x_write(BITMAP *bmp, int x, int y, int color) { if ((x >= bmp->cl) && (x < bmp->cr) && (y >= bmp->ct) && (y < bmp->cb)) { outportw(0x3C4, (0x100<<(x&3))|2); bmp_write8((unsigned long)bmp->line[y]+(x>>2), color); }
static void wrdm16(CMI8738_Driver_t* ds, uint32_t offset, uint16_t value) { outportw(ds->base_addr + offset, value); }
void VBE_Write(uint16_t index, uint16_t value) { outportw(VBE_DISPI_IOPORT_INDEX, index); outportw(VBE_DISPI_IOPORT_DATA, value); }
// ------------------------------------------------------------------------------------------------ void PciWrite16(uint32 id, uint32 reg, uint16 data) { uint32 address = 0x80000000 | id | (reg & 0xfc); IoWrite32(PCI_CONFIG_ADDR, address); outportw(PCI_CONFIG_DATA + (reg & 0x02), data); }
int vm86_emulate(struct vm86_context *vm86ctx) { int eaten = 1; int data32 = 0, addr32 = 0, rep = 0, segp = 0; int done = 0; uint16_t ip = LOWORD(vm86ctx->eip), sp = LOWORD(vm86ctx->esp); do { switch(*(uint8_t *)LADDR(vm86ctx->cs, ip)) { case 0x66: /*32-bit data*/ data32=1; break; case 0x67: /*32-bit addr*/ addr32=1; break; case 0xf2: /*REPNZ/REPNE*/ rep=1; break; case 0xf3: /*REP/REPZ/REPE*/ rep=1; break; case 0x2e: /*CS*/ segp=56; break; case 0x3e: /*DS*/ segp=76; break; case 0x26: /*ES*/ segp=72; break; case 0x36: /*SS*/ segp=68; break; case 0x65: /*GS*/ segp=84; break; case 0x64: /*FS*/ segp=80; break; case 0xf0: /*LOCK*/ break; default: done = 1; break; } if(done) break; ip++; } while(1); switch(*(uint8_t *)LADDR(vm86ctx->cs, ip)) { case 0xfa: /*CLI*/ vm86ctx->eflags &= ~EFLAGS_IF; ip++; break; case 0xfb: /*STI*/ vm86ctx->eflags |= EFLAGS_IF; ip++; break; case 0x9c: /*PUSHF*/ if(data32) { sp -= 4; *(uint32_t *)LADDR(vm86ctx->ss, sp) = vm86ctx->eflags & 0x001cffff; } else { sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = (uint16_t)vm86ctx->eflags; } ip++; break; case 0x9d: /*POPF*/ if(data32) { uint32_t eflags = *(uint32_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0x1b3000/*VM, RF, IOPL, VIP, VIF*/; eflags &= ~0x1b3000; vm86ctx->eflags |= eflags; sp += 4; } else { uint32_t eflags = *(uint16_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0xffff3000/*IOPL*/; eflags &= ~0xffff3000; vm86ctx->eflags |= eflags; sp += 2; } ip++; break; case 0xcd: /*INT*/ sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = (uint16_t)vm86ctx->eflags; sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = vm86ctx->cs; sp -= 2; *(uint16_t *)LADDR(vm86ctx->ss, sp) = ip + 2; { uint16_t *ivt = (uint16_t *)0; uint8_t x = *(uint8_t *)LADDR(vm86ctx->cs, ip + 1); ip = ivt[x * 2 + 0]; vm86ctx->cs = ivt[x * 2 + 1]; } break; case 0xcf: /*IRET*/ if(data32) { ip = *(uint32_t *)LADDR(vm86ctx->ss, sp); sp += 4; vm86ctx->cs = *(uint32_t *)LADDR(vm86ctx->ss, sp); sp += 4; uint32_t eflags = *(uint32_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0x1a3000/*VM, IOPL, VIP, VIF*/; eflags &= ~0x1a3000; vm86ctx->eflags |= eflags; sp += 4; } else { ip = *(uint16_t *)LADDR(vm86ctx->ss, sp); sp += 2; vm86ctx->cs = *(uint16_t *)LADDR(vm86ctx->ss, sp); sp += 2; uint32_t eflags = *(uint16_t *)LADDR(vm86ctx->ss, sp); vm86ctx->eflags &= 0xffff3000/*IOPL*/; eflags &= ~0xffff3000; vm86ctx->eflags |= eflags; sp += 2; } break; case 0xe6:/*OUT imm8, AL*/ outportb(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1), LOBYTE(LOWORD(vm86ctx->eax))); ip += 2; break; case 0xe7:/*OUT imm8, (E)AX*/ if(data32) { outportl(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1), vm86ctx->eax); } else { outportw(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1), LOWORD(vm86ctx->eax)); } ip += 2; break; case 0xee:/*OUT DX, AL*/ outportb(LOWORD(vm86ctx->edx), LOBYTE(LOWORD(vm86ctx->eax))); ip++; break; case 0xef:/*OUT DX, (E)AX*/ if(data32) { outportl(LOWORD(vm86ctx->edx), vm86ctx->eax); } else { outportw(LOWORD(vm86ctx->edx), LOWORD(vm86ctx->eax)); } ip++; break; case 0xe4:/*IN AL, imm8*/ { uint8_t al = inportb(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1)); vm86ctx->eax = (vm86ctx->eax & 0xffffff00) | al; } ip += 2; break; case 0xe5:/*IN (E)AX, imm8*/ if(data32) { vm86ctx->eax = inportl(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1)); } else { uint16_t ax = inportw(*(uint8_t *)LADDR(vm86ctx->cs, ip + 1)); vm86ctx->eax = (vm86ctx->eax & 0xffff0000) | ax; } ip += 2; break; case 0xec:/*IN AL, DX*/ { uint8_t al = inportb(LOWORD(vm86ctx->edx)); vm86ctx->eax = (vm86ctx->eax & 0xffffff00) | al; } ip += 1; break; case 0xed:/*IN (E)AX, DX*/ if(data32) { vm86ctx->eax = inportl(LOWORD(vm86ctx->edx)); } else { uint16_t ax = inportw(LOWORD(vm86ctx->edx)); vm86ctx->eax = (vm86ctx->eax & 0xffff0000) | ax; } ip++; break; case 0x6c:/*INSB; INS m8, DX*/ { if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { *(uint8_t *)LADDR(vm86ctx->es, vm86ctx->edi/*XXX*/) = inportb(LOWORD(vm86ctx->edx)); ecx--; vm86ctx->edi += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, di=LOWORD(vm86ctx->edi); while(cx) { *(uint8_t *)LADDR(vm86ctx->es, di) = inportb(LOWORD(vm86ctx->edx)); cx--; di += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->edi = (vm86ctx->edi & 0xffff0000) | di; } } ip++; break; case 0x6d:/*INSW; INSD; INS m16/m32, DX*/ { if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { if(data32) { *(uint32_t *)LADDR(vm86ctx->es, vm86ctx->edi/*XXX*/) = inportl(LOWORD(vm86ctx->edx)); vm86ctx->edi += (vm86ctx->eflags & 0x400)?-4:4; } else { *(uint16_t *)LADDR(vm86ctx->es, vm86ctx->edi/*XXX*/) = inportw(LOWORD(vm86ctx->edx)); vm86ctx->edi += (vm86ctx->eflags & 0x400)?-2:2; } ecx--; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, di=LOWORD(vm86ctx->edi); while(cx) { if(data32) { *(uint32_t *)LADDR(vm86ctx->es, di) = inportl(LOWORD(vm86ctx->edx)); di += (vm86ctx->eflags & 0x400)?-4:4; } else { *(uint16_t *)LADDR(vm86ctx->es, di) = inportw(LOWORD(vm86ctx->edx)); di += (vm86ctx->eflags & 0x400)?-2:2; } cx--; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->edi = (vm86ctx->edi & 0xffff0000) | di; } } ip++; break; case 0x6e:/*OUTSB; OUTS DX, m8*/ { uint16_t seg = vm86ctx->ds; if(segp) seg = *(uint16_t *)(((uint8_t *)vm86ctx)+segp); if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { outportb(LOWORD(vm86ctx->edx), *(uint8_t *)LADDR(seg, vm86ctx->esi/*XXX*/)); ecx--; vm86ctx->esi += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, si=LOWORD(vm86ctx->esi); while(cx) { outportb(LOWORD(vm86ctx->edx), *(uint8_t *)LADDR(seg, si)); cx--; si += (vm86ctx->eflags & 0x400)?-1:1; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->esi = (vm86ctx->esi & 0xffff0000) | si; } } ip++; break; case 0x6f:/*OUTSW; OUTSD; OUTS DX, m16/32*/ { uint16_t seg = vm86ctx->ds; if(segp) seg = *(uint16_t *)(((uint8_t *)vm86ctx)+segp); if(addr32) { uint32_t ecx = rep ? vm86ctx->ecx : 1; while(ecx) { if(data32) { outportl(LOWORD(vm86ctx->edx), *(uint32_t *)LADDR(seg, vm86ctx->esi/*XXX*/)); vm86ctx->esi += (vm86ctx->eflags & 0x400)?-4:4; } else { outportw(LOWORD(vm86ctx->edx), *(uint16_t *)LADDR(seg, vm86ctx->esi/*XXX*/)); vm86ctx->esi += (vm86ctx->eflags & 0x400)?-2:2; } ecx--; } if(rep) vm86ctx->ecx = ecx; } else { uint16_t cx=rep ? LOWORD(vm86ctx->ecx) : 1, si=LOWORD(vm86ctx->esi); while(cx) { if(data32) { outportl(LOWORD(vm86ctx->edx), *(uint32_t *)LADDR(seg, si)); si += (vm86ctx->eflags & 0x400)?-4:4; } else { outportw(LOWORD(vm86ctx->edx), *(uint16_t *)LADDR(seg, si)); si += (vm86ctx->eflags & 0x400)?-2:2; } cx--; } if(rep) vm86ctx->ecx = (vm86ctx->ecx & 0xffff0000) | cx; vm86ctx->esi = (vm86ctx->esi & 0xffff0000) | si; } } ip++; break; default: eaten = 0; break; } vm86ctx->eip = (vm86ctx->eip & 0xffff0000) | ip; vm86ctx->esp = (vm86ctx->esp & 0xffff0000) | sp; return eaten; }