DWord TStringStack::popdw(){ DWord _RetDWord=0; if (!String) return (DWord)0; _RetDWord=(DWord)popw(); _RetDWord+=(DWord)popw()<<16; return _RetDWord; }
static void do_retf(struct RealModeCallStructure *rmreg, int rmask) { unsigned int ssp, sp; ssp = SEGOFF2LINEAR(READ_RMREG(ss, rmask), 0); sp = READ_RMREG(sp, rmask); RMREG(ip) = popw(ssp, sp); RMREG(cs) = popw(ssp, sp); RMREG(sp) += 4; }
void handle_v86_fault( Virtual86Regs_s * regs, uint32 nErrorCode ) { unsigned char *csp, *ssp; unsigned long ip, sp; int nInst; // if ( 0xffff == (regs->eip & 0xffff) && 0xffff == regs->cs ) { // return_to_32bit( regs, 0 ); // return; // } csp = ( unsigned char * )( regs->cs << 4 ); ssp = ( unsigned char * )( regs->ss << 4 ); sp = regs->esp & 0xffff; ip = regs->eip & 0xffff; nInst = popb( csp, ip ); switch ( nInst ) { /* Operand size override */ case 0x66: printk( "WARNING : 32 bit code run in v86 mode! Flags are not handled properly!\n" ); nInst = popb( csp, ip ); switch ( nInst ) { /* pushfd */ case 0x9c: regs->esp = ( regs->esp - 4 ) & 0xffff; regs->eip = ( regs->eip + 2 ) & 0xffff; pushl( ssp, sp, regs->eflags ); return; /* popfd */ case 0x9d: regs->esp = ( regs->esp + 4 ) & 0xffff; regs->eip = ( regs->eip + 2 ) & 0xffff; regs->eflags = popl( ssp, sp ); return; /* iretd */ case 0xcf: regs->esp = ( regs->esp + 12 ) & 0xffff; regs->eip = ( uint16 )( popl( ssp, sp ) & 0xffff ); regs->cs = ( uint16 )popl( ssp, sp ); return; /* need this to avoid a fallthrough */ default: printk( "ERROR : unknown v86 32 bit instruction %x\n", nInst ); return_to_32bit( regs, -EFAULT ); } /* pushf */ case 0x9c: regs->esp = ( regs->esp - 2 ) & 0xffff; regs->eip = ( regs->eip + 1 ) & 0xffff; pushw( ssp, sp, regs->eflags & 0xffff ); return; /* popf */ case 0x9d: regs->esp = ( regs->esp + 2 ) & 0xffff; regs->eip = ( regs->eip + 1 ) & 0xffff; regs->eflags = ( regs->eflags & 0xffff0000 ) | ( popw( ssp, sp ) & 0xffff ); return; /* int xx */ case 0xcd: { int intno = popb( csp, ip ); regs->eip = ( regs->eip + 2 ) & 0xffff; do_int( regs, intno, ssp, sp ); return; } /* iret */ case 0xcf: regs->esp = ( regs->esp + 6 ) & 0xffff; regs->eip = popw( ssp, sp ) & 0xffff; regs->cs = popw( ssp, sp ); regs->eflags = ( regs->eflags & 0xffff0000 ) | ( popw( ssp, sp ) & 0xffff ); if ( 0xffff == ( regs->eip & 0xffff ) && 0xffff == regs->cs ) { return_to_32bit( regs, 0 ); } return; /* cli */ case 0xfa: regs->eip = ( regs->eip + 1 ) & 0xffff; regs->eflags &= ~EFLG_IF; return; /* sti */ case 0xfb: /* The interrupts should actually be restored after the NEXT instruction! * Hope this works. As long as no DOS/BIOS code swaps the stack, * nothing bad should happen. */ regs->eip = ( regs->eip + 1 ) & 0xffff; regs->eflags |= EFLG_IF; return; default: printk( "ERROR : unknown v86 16 bit instruction %x\n", nInst ); return_to_32bit( regs, -EFAULT ); } }