Example #1
0
int reiserfs_on_disk_super_in_proc( char *buffer, char **start, off_t offset,
				    int count, int *eof, void *data )
{
	struct super_block *sb;
	struct reiserfs_sb_info *sb_info;
	struct reiserfs_super_block *rs;
	int hash_code;
	int len = 0;
    
	sb = procinfo_prologue( ( kdev_t ) ( long ) data );
	if( sb == NULL )
		return -ENOENT;
	sb_info = &sb->u.reiserfs_sb;
	rs = sb_info -> s_rs;
	hash_code = DFL( s_hash_function_code );

	len += sprintf( &buffer[ len ], 
			"block_count: \t%i\n"
			"free_blocks: \t%i\n"
			"root_block: \t%i\n"
			"blocksize: \t%i\n"
			"oid_maxsize: \t%i\n"
			"oid_cursize: \t%i\n"
			"umount_state: \t%i\n"
			"magic: \t%10.10s\n"
			"fs_state: \t%i\n"
			"hash: \t%s\n"
			"tree_height: \t%i\n"
			"bmap_nr: \t%i\n"
			"version: \t%i\n"
			"reserved_for_journal: \t%i\n"
			"inode_generation: \t%i\n"
			"flags: \t%x[%s]\n",

			DFL( s_block_count ),
			DFL( s_free_blocks ),
			DFL( s_root_block ),
			DF( s_blocksize ),
			DF( s_oid_maxsize ),
			DF( s_oid_cursize ),
			DF( s_umount_state ),
			rs -> s_v1.s_magic,
			DF( s_fs_state ),
			hash_code == TEA_HASH ? "tea" :
			( hash_code == YURA_HASH ) ? "rupasov" :
			( hash_code == R5_HASH ) ? "r5" :
			( hash_code == UNSET_HASH ) ? "unset" : "unknown",
			DF( s_tree_height ),
			DF( s_bmap_nr ),
			DF( s_version ),
			DF( s_reserved_for_journal ),
			DPL( s_inode_generation ),
			DPL( s_flags ),
			(DPL( s_flags ) & reiserfs_attrs_cleared 
			? "attrs_cleared" : "" ));

	procinfo_epilogue( sb );
	return reiserfs_proc_tail( len, buffer, start, offset, count, eof );
}
static void i80286_data_descriptor_full(i80286_state *cpustate, int reg, UINT16 selector, int cpl, UINT32 trap, UINT16 offset, int size)
{
	if (PM) {
		UINT16 desc[3];
		UINT8 r;
		UINT32 addr;
		/* selector format
           15..3 number/address in descriptor table
           2: 0 global, 1 local descriptor table
           1,0: requested privileg level
           must be higher or same as current privileg level in code selector */
		if ((reg != SS) && !IDXTBL(selector)) {
			cpustate->sregs[reg]=0;
			cpustate->limit[reg]=0;
			cpustate->base[reg]=0;
			cpustate->rights[reg]=0;
			cpustate->valid[reg]=0;
			return;
		}

		if ((addr = i80286_selector_address(cpustate,selector)) == -1) throw trap;

		desc[0] = ReadWord(addr);
		desc[1] = ReadWord(addr+2);
		desc[2] = ReadWord(addr+4);
		r = RIGHTS(desc);
		if (!SEGDESC(r)) throw trap;
		if (reg == SS) {
			if (!IDXTBL(selector)) throw trap;
			if (DPL(r)!=cpl) throw trap;
			if (RPL(selector)!=cpl) throw trap;
			if (!RW(r) || CODE(r)) throw trap;
			if (!PRES(r)) throw TRAP(STACK_FAULT,(IDXTBL(selector)+(trap&1)));
		} else {
			if ((DPL(r) < PMAX(cpl,RPL(selector))) && (!CODE(r) || (CODE(r) && !CONF(r)))) throw trap;
			if (CODE(r) && !READ(r)) throw trap;
			if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(selector)+(trap&1)));
		}
		if (offset+size) {
			if ((CODE(r) || !EXPDOWN(r)) && ((offset+size-1) > LIMIT(desc))) throw (reg==SS)?TRAP(STACK_FAULT,(trap&1)):trap;
			if (!CODE(r) && EXPDOWN(r) && ((offset <= LIMIT(desc)) || ((offset+size-1) > 0xffff))) throw (reg==SS)?TRAP(STACK_FAULT,(trap&1)):trap;
		}

		SET_ACC(desc);
		WriteWord(addr+4, desc[2]);
		cpustate->sregs[reg]=selector;
		cpustate->limit[reg]=LIMIT(desc);
		cpustate->base[reg]=BASE(desc);
		cpustate->rights[reg]=RIGHTS(desc);
	} else {
		cpustate->sregs[reg]=selector;
		cpustate->base[reg]=selector<<4;
	}
	cpustate->valid[reg]=1;
}
struct POINT GetInflectionPoint(int LorR) {
	int z;
	struct POINT tmpReturn;
	int tmp = 0;
	int max = 0;
	tmpReturn = edgePoint[LorR][edgeStartZ[LorR]];

	edgeLimitLines[LorR] = LPP(crctr_BTX[LorR].head, crctr_BTX[LorR].tail);

	for (z = edgeStartZ[LorR]; z < C_activePoint[LorR]; z++) {
		tmp = DPL(edgePoint[LorR][z],edgeLimitLines[LorR]);
		tmp = ABS(tmp);
		if(tmp > max)
		{
			max = tmp;
			tmpReturn = edgePoint[LorR][z];
		}
	}
	return tmpReturn;
}
Example #4
0
SCORE NWDASimple(const ProfPos *PA, unsigned uLengthA, const ProfPos *PB,
  unsigned uLengthB, PWPath &Path)
	{
	assert(uLengthB > 0 && uLengthA > 0);

	const unsigned uPrefixCountA = uLengthA + 1;
	const unsigned uPrefixCountB = uLengthB + 1;

// Allocate DP matrices
	const size_t LM = uPrefixCountA*uPrefixCountB;
	SCORE *DPL_ = new SCORE[LM];
	SCORE *DPM_ = new SCORE[LM];
	SCORE *DPD_ = new SCORE[LM];
	SCORE *DPE_ = new SCORE[LM];
	SCORE *DPI_ = new SCORE[LM];
	SCORE *DPJ_ = new SCORE[LM];

	char *TBM_ = new char[LM];
	char *TBD_ = new char[LM];
	char *TBE_ = new char[LM];
	char *TBI_ = new char[LM];
	char *TBJ_ = new char[LM];

	memset(TBM_, '?', LM);
	memset(TBD_, '?', LM);
	memset(TBE_, '?', LM);
	memset(TBI_, '?', LM);
	memset(TBJ_, '?', LM);

	DPM(0, 0) = 0;
	DPD(0, 0) = MINUS_INFINITY;
	DPE(0, 0) = MINUS_INFINITY;
	DPI(0, 0) = MINUS_INFINITY;
	DPJ(0, 0) = MINUS_INFINITY;

	DPM(1, 0) = MINUS_INFINITY;
	DPD(1, 0) = PA[0].m_scoreGapOpen;
	DPE(1, 0) = PA[0].m_scoreGapOpen2;
	TBD(1, 0) = 'D';
	TBE(1, 0) = 'E';
	DPI(1, 0) = MINUS_INFINITY;
	DPJ(1, 0) = MINUS_INFINITY;

	DPM(0, 1) = MINUS_INFINITY;
	DPD(0, 1) = MINUS_INFINITY;
	DPE(0, 1) = MINUS_INFINITY;
	DPI(0, 1) = PB[0].m_scoreGapOpen;
	DPJ(0, 1) = PB[0].m_scoreGapOpen2;
	TBI(0, 1) = 'I';
	TBJ(0, 1) = 'J';

// Empty prefix of B is special case
	for (unsigned uPrefixLengthA = 2; uPrefixLengthA < uPrefixCountA; ++uPrefixLengthA)
		{
		DPM(uPrefixLengthA, 0) = MINUS_INFINITY;

		DPD(uPrefixLengthA, 0) = DPD(uPrefixLengthA - 1, 0) + g_scoreGapExtend.get();
		DPE(uPrefixLengthA, 0) = DPE(uPrefixLengthA - 1, 0) + g_scoreGapExtend2.get();

		TBD(uPrefixLengthA, 0) = 'D';
		TBE(uPrefixLengthA, 0) = 'E';

		DPI(uPrefixLengthA, 0) = MINUS_INFINITY;
		DPJ(uPrefixLengthA, 0) = MINUS_INFINITY;
		}

// Empty prefix of A is special case
	for (unsigned uPrefixLengthB = 2; uPrefixLengthB < uPrefixCountB; ++uPrefixLengthB)
		{
		DPM(0, uPrefixLengthB) = MINUS_INFINITY;

		DPD(0, uPrefixLengthB) = MINUS_INFINITY;
		DPE(0, uPrefixLengthB) = MINUS_INFINITY;

		DPI(0, uPrefixLengthB) = DPI(0, uPrefixLengthB - 1) + g_scoreGapExtend.get();
		DPJ(0, uPrefixLengthB) = DPJ(0, uPrefixLengthB - 1) + g_scoreGapExtend2.get();

		TBI(0, uPrefixLengthB) = 'I';
		TBJ(0, uPrefixLengthB) = 'J';
		}

// Special case to agree with NWFast, no D-I transitions so...
	DPD(uLengthA, 0) = MINUS_INFINITY;
	DPE(uLengthA, 0) = MINUS_INFINITY;
//	DPI(0, uLengthB) = MINUS_INFINITY;
//	DPJ(0, uLengthB) = MINUS_INFINITY;

// ============
// Main DP loop
// ============
	SCORE scoreGapCloseB = MINUS_INFINITY;
	SCORE scoreGapClose2B = MINUS_INFINITY;
	for (unsigned uPrefixLengthB = 1; uPrefixLengthB < uPrefixCountB; ++uPrefixLengthB)
		{
		const ProfPos &PPB = PB[uPrefixLengthB - 1];

		SCORE scoreGapCloseA = MINUS_INFINITY;
		SCORE scoreGapClose2A = MINUS_INFINITY;
		for (unsigned uPrefixLengthA = 1; uPrefixLengthA < uPrefixCountA; ++uPrefixLengthA)
			{
			const ProfPos &PPA = PA[uPrefixLengthA - 1];

			{
		// Match M=LetterA+LetterB
			SCORE scoreLL = ScoreProfPos2(PPA, PPB);
			DPL(uPrefixLengthA, uPrefixLengthB) = scoreLL;

			SCORE scoreMM = DPM(uPrefixLengthA-1, uPrefixLengthB-1);
			SCORE scoreDM = DPD(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapCloseA;
			SCORE scoreEM = DPE(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapClose2A;
			SCORE scoreIM = DPI(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapCloseB;
			SCORE scoreJM = DPJ(uPrefixLengthA-1, uPrefixLengthB-1) + scoreGapClose2B;

			SCORE scoreBest;
			if (scoreMM >= scoreDM && scoreMM >= scoreEM && scoreMM >= scoreIM && scoreMM >= scoreJM)
				{
				scoreBest = scoreMM;
				TBM(uPrefixLengthA, uPrefixLengthB) = 'M';
				}
			else if (scoreDM >= scoreMM && scoreDM >= scoreEM && scoreDM >= scoreIM && scoreDM >= scoreJM)
				{
				scoreBest = scoreDM;
				TBM(uPrefixLengthA, uPrefixLengthB) = 'D';
				}
			else if (scoreEM >= scoreMM && scoreEM >= scoreDM && scoreEM >= scoreIM && scoreEM >= scoreJM)
				{
				scoreBest = scoreEM;
				TBM(uPrefixLengthA, uPrefixLengthB) = 'E';
				}
			else if (scoreIM >= scoreMM && scoreIM >= scoreDM && scoreIM >= scoreEM && scoreIM >= scoreJM)
				{
				scoreBest = scoreIM;
				TBM(uPrefixLengthA, uPrefixLengthB) = 'I';
				}
			else
				{
				assert(scoreJM >= scoreMM && scoreJM >= scoreDM && scoreJM >= scoreEM && scoreJM >= scoreIM);
				scoreBest = scoreJM;
				TBM(uPrefixLengthA, uPrefixLengthB) = 'J';
				}
			DPM(uPrefixLengthA, uPrefixLengthB) = scoreBest + scoreLL;
			}

			{
		// Delete D=LetterA+GapB
			SCORE scoreMD = DPM(uPrefixLengthA-1, uPrefixLengthB) +
			  PA[uPrefixLengthA-1].m_scoreGapOpen;
			SCORE scoreDD = DPD(uPrefixLengthA-1, uPrefixLengthB) + g_scoreGapExtend.get();

			SCORE scoreBest;
			if (scoreMD >= scoreDD)
				{
				scoreBest = scoreMD;
				TBD(uPrefixLengthA, uPrefixLengthB) = 'M';
				}
			else
				{
				assert(scoreDD >= scoreMD);
				scoreBest = scoreDD;
				TBD(uPrefixLengthA, uPrefixLengthB) = 'D';
				}
			DPD(uPrefixLengthA, uPrefixLengthB) = scoreBest;
			}

			{
		// Delete E=LetterA+GapB
			SCORE scoreME = DPM(uPrefixLengthA-1, uPrefixLengthB) +
			  PA[uPrefixLengthA-1].m_scoreGapOpen2;
			SCORE scoreEE = DPE(uPrefixLengthA-1, uPrefixLengthB) + g_scoreGapExtend2.get();

			SCORE scoreBest;
			if (scoreME >= scoreEE)
				{
				scoreBest = scoreME;
				TBE(uPrefixLengthA, uPrefixLengthB) = 'M';
				}
			else
				{
				assert(scoreEE >= scoreME);
				scoreBest = scoreEE;
				TBE(uPrefixLengthA, uPrefixLengthB) = 'E';
				}
			DPE(uPrefixLengthA, uPrefixLengthB) = scoreBest;
			}

		// Insert I=GapA+LetterB
			{
			SCORE scoreMI = DPM(uPrefixLengthA, uPrefixLengthB-1) +
			  PB[uPrefixLengthB - 1].m_scoreGapOpen;
			SCORE scoreII = DPI(uPrefixLengthA, uPrefixLengthB-1) + g_scoreGapExtend.get();

			SCORE scoreBest;
			if (scoreMI >= scoreII)
				{
				scoreBest = scoreMI;
				TBI(uPrefixLengthA, uPrefixLengthB) = 'M';
				}
			else 
				{
				assert(scoreII > scoreMI);
				scoreBest = scoreII;
				TBI(uPrefixLengthA, uPrefixLengthB) = 'I';
				}
			DPI(uPrefixLengthA, uPrefixLengthB) = scoreBest;
			}

		// Insert J=GapA+LetterB
			{
			SCORE scoreMJ = DPM(uPrefixLengthA, uPrefixLengthB-1) +
			  PB[uPrefixLengthB - 1].m_scoreGapOpen2;
			SCORE scoreJJ = DPJ(uPrefixLengthA, uPrefixLengthB-1) + g_scoreGapExtend2.get();

			SCORE scoreBest;
			if (scoreMJ >= scoreJJ)
				{
				scoreBest = scoreMJ;
				TBJ(uPrefixLengthA, uPrefixLengthB) = 'M';
				}
			else 
				{
				assert(scoreJJ > scoreMJ);
				scoreBest = scoreJJ;
				TBJ(uPrefixLengthA, uPrefixLengthB) = 'J';
				}
			DPJ(uPrefixLengthA, uPrefixLengthB) = scoreBest;
			}

			scoreGapCloseA = PPA.m_scoreGapClose;
			scoreGapClose2A = PPA.m_scoreGapClose2;
			}
		scoreGapCloseB = PPB.m_scoreGapClose;
		scoreGapClose2B = PPB.m_scoreGapClose2;
		}

#if TRACE
	Log("\n");
	Log("DA Simple DPL:\n");
	ListDP(DPL_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple DPM:\n");
	ListDP(DPM_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple DPD:\n");
	ListDP(DPD_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple DPE:\n");
	ListDP(DPE_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple DPI:\n");
	ListDP(DPI_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple DPJ:\n");
	ListDP(DPJ_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple TBM:\n");
	ListTB(TBM_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple TBD:\n");
	ListTB(TBD_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple TBE:\n");
	ListTB(TBE_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple TBI:\n");
	ListTB(TBI_, PA, PB, uPrefixCountA, uPrefixCountB);
	Log("\n");
	Log("DA Simple TBJ:\n");
	ListTB(TBJ_, PA, PB, uPrefixCountA, uPrefixCountB);
#endif

// Trace-back
// ==========
	Path.Clear();

// Find last edge
	SCORE M = DPM(uLengthA, uLengthB);
	SCORE D = DPD(uLengthA, uLengthB) + PA[uLengthA-1].m_scoreGapClose;
	SCORE E = DPE(uLengthA, uLengthB) + PA[uLengthA-1].m_scoreGapClose2;
	SCORE I = DPI(uLengthA, uLengthB) + PB[uLengthB-1].m_scoreGapClose;
	SCORE J = DPJ(uLengthA, uLengthB) + PB[uLengthB-1].m_scoreGapClose2;
	char cEdgeType = '?';

	SCORE BestScore = M;
	cEdgeType = 'M';
	if (D > BestScore)
		{
		cEdgeType = 'D';
		BestScore = D;
		}
	if (E > BestScore)
		{
		cEdgeType = 'E';
		BestScore = E;
		}
	if (I > BestScore)
		{
		cEdgeType = 'I';
		BestScore = I;
		}
	if (J > BestScore)
		{
		cEdgeType = 'J';
		BestScore = J;
		}

#if	TRACE
	Log("DA Simple: MAB=%.4g DAB=%.4g EAB=%.4g IAB=%.4g JAB=%.4g best=%c\n",
	  M, D, E, I, J, cEdgeType);
#endif

	unsigned PLA = uLengthA;
	unsigned PLB = uLengthB;
	for (;;)
		{
		PWEdge Edge;
		Edge.cType = XlatEdgeType(cEdgeType);
		Edge.uPrefixLengthA = PLA;
		Edge.uPrefixLengthB = PLB;
#if	TRACE
		Log("Prepend %c%d.%d\n", Edge.cType, PLA, PLB);
#endif
		Path.PrependEdge(Edge);

		switch (cEdgeType)
			{
		case 'M':
			assert(PLA > 0);
			assert(PLB > 0);
			cEdgeType = TBM(PLA, PLB);
			--PLA;
			--PLB;
			break;

		case 'D':
			assert(PLA > 0);
			cEdgeType = TBD(PLA, PLB);
			--PLA;
			break;

		case 'E':
			assert(PLA > 0);
			cEdgeType = TBE(PLA, PLB);
			--PLA;
			break;

		case 'I':
			assert(PLB > 0);
			cEdgeType = TBI(PLA, PLB);
			--PLB;
			break;
		
		case 'J':
			assert(PLB > 0);
			cEdgeType = TBJ(PLA, PLB);
			--PLB;
			break;

		default:
			Quit("Invalid edge %c", cEdgeType);
			}
		if (0 == PLA && 0 == PLB)
			break;
		}
	Path.Validate();

//	SCORE Score = TraceBack(PA, uLengthA, PB, uLengthB, DPM_, DPD_, DPI_, Path);

#if	TRACE
	SCORE scorePath = FastScorePath2(PA, uLengthA, PB, uLengthB, Path);
	Path.LogMe();
	Log("Score = %s Path = %s\n", LocalScoreToStr(BestScore), LocalScoreToStr(scorePath));
#endif

	if (g_bKeepSimpleDP.get())
		{
		g_DPM.get() = DPM_;
		g_DPD.get() = DPD_;
		g_DPE.get() = DPE_;
		g_DPI.get() = DPI_;
		g_DPJ.get() = DPJ_;

		g_TBM.get() = TBM_;
		g_TBD.get() = TBD_;
		g_TBE.get() = TBE_;
		g_TBI.get() = TBI_;
		g_TBJ.get() = TBJ_;
		}
	else
		{
		delete[] DPM_;
		delete[] DPD_;
		delete[] DPE_;
		delete[] DPI_;
		delete[] DPJ_;

		delete[] TBM_;
		delete[] TBD_;
		delete[] TBE_;
		delete[] TBI_;
		delete[] TBJ_;
		}

	return BestScore;
	}
static UINT16 i80286_far_return(i8086_state *cpustate, int iret, int bytes)
{
	UINT16 sel, off, flags = 0;
	int spaddr;

	if (PM && NT && iret) {
		i80286_switch_task(cpustate, ReadWord(cpustate->tr.base+TSS_BACK*2), IRET);
		return cpustate->flags;
	}

	// must be restartable
	if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], (iret?6:4), I80286_READ);
	spaddr = (cpustate->base[SS] + cpustate->regs.w[SP]) & AMASK;
	off = ReadWord(spaddr);
	sel = ReadWord(spaddr+2);
	if(iret) flags = ReadWord(spaddr+4);

	if(PM) {
		UINT16 desc[3], newsp, newss;
		int addr, r;

		if ((addr = i80286_selector_address(cpustate,sel)) == -1)
			throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));

		if (RPL(sel)<CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
		desc[0] = ReadWord(addr);
		desc[1] = ReadWord(addr+2);
		desc[2] = ReadWord(addr+4);
		r = RIGHTS(desc);

		if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
		if (CONF(r)) { if(DPL(r)>RPL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); }
		else if (DPL(r)!=RPL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));

		if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
		if (off > LIMIT(desc)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
		if (CPL<RPL(sel)) {
			i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]+(iret?6:4)+bytes, 4, I80286_READ);
			newsp = ReadWord(spaddr+((iret?6:4)+bytes));
			newss = ReadWord(spaddr+((iret?8:6)+bytes));
			i80286_data_descriptor_full(cpustate, SS, newss, RPL(sel), TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(newss)), 0, 0);
			cpustate->regs.w[SP] = newsp + bytes;
		} else cpustate->regs.w[SP] += (iret?6:4) + bytes;
		SET_ACC(desc);
		WriteWord(addr+4, desc[2]);
		cpustate->sregs[CS]=sel;
		cpustate->limit[CS]=LIMIT(desc);
		cpustate->base[CS]=BASE(desc);
		cpustate->rights[CS]=RIGHTS(desc);
		cpustate->pc=(cpustate->base[CS]+off)&AMASK;

		// docs say check rpl but windows doesn't like it
		r = cpustate->rights[DS];
		if (i80286_verify(cpustate, cpustate->sregs[DS], I80286_READ, r, 0) || (CODE(r) && CONF(r) ? 0 : (DPL(r) < CPL)))
			i80286_data_descriptor(cpustate, DS, 0);
		r = cpustate->rights[ES];
		if (i80286_verify(cpustate, cpustate->sregs[ES], I80286_READ, r, 0) || (CODE(r) && CONF(r) ? 0 : (DPL(r) < CPL)))
			i80286_data_descriptor(cpustate, ES, 0);
	} else {
		cpustate->regs.w[SP] += (iret?6:4) + bytes;
		cpustate->sregs[CS]=sel;
		cpustate->base[CS]=sel<<4;
		cpustate->rights[CS]=0x9a;
		cpustate->limit[CS]=0xffff;
		cpustate->pc=(cpustate->base[CS]+off)&AMASK;
	}
	CHANGE_PC(cpustate->pc);

	return flags;
}
static void PREFIX286(_0fpre)(i8086_state *cpustate)
{
	unsigned next = FETCHOP;
	UINT16 ModRM, desc[3];
	UINT16 tmp, msw, sel;
	UINT8 r;
	UINT32 addr;

	switch (next) {
	case 0:
		if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
		ModRM=FETCHOP;
		switch (ModRM&0x38) {
		case 0: /* sldt */
			PutRMWord(ModRM, cpustate->ldtr.sel);
			break;
		case 8: /* str */
			PutRMWord(ModRM, cpustate->tr.sel);
			break;
		case 0x10: /* lldt */
			if (CPL!=0) throw TRAP(GENERAL_PROTECTION_FAULT,0);
			sel=GetRMWord(ModRM);
			if (TBL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
			if (IDXTBL(sel)) {
				if (IDX(sel)>=cpustate->gdtr.limit) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
				addr = cpustate->gdtr.base + IDX(sel);
				desc[0] = ReadWord(addr);
				desc[1] = ReadWord(addr+2);
				desc[2] = ReadWord(addr+4);
				r = RIGHTS(desc);
				if (SEGDESC(r) || (GATE(r) != LDTDESC)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
				if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
			} else {
				desc[0] = 0;
				desc[1] = 0;
				desc[2] = 0;
			}
			cpustate->ldtr.sel=sel;
			cpustate->ldtr.limit=LIMIT(desc);
			cpustate->ldtr.base=BASE(desc);
			cpustate->ldtr.rights=RIGHTS(desc);
			break;
		case 0x18: /* ltr */
			if (CPL!=0) throw TRAP(GENERAL_PROTECTION_FAULT,0);
			sel=GetRMWord(ModRM);
			if ((addr = i80286_selector_address(cpustate,sel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
			desc[0] = ReadWord(addr);
			desc[1] = ReadWord(addr+2);
			desc[2] = ReadWord(addr+4);
			r = RIGHTS(desc);
			if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
			if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
			desc[2] |= 0x200; // mark busy
			WriteWord(addr+4, desc[2]);
			cpustate->tr.sel=sel;
			cpustate->tr.limit=LIMIT(desc);
			cpustate->tr.base=BASE(desc);
			cpustate->tr.rights=RIGHTS(desc);
			break;
		case 0x20: /* verr */
			tmp=GetRMWord(ModRM);
			if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
			else {
				desc[2] = ReadWord(addr+4);
				r = RIGHTS(desc);
				cpustate->ZeroVal = i80286_verify(cpustate, tmp, I80286_READ, RIGHTS(desc), 0);
				cpustate->ZeroVal = cpustate->ZeroVal || (CODE(r) && CONF(r) ? 0 : (DPL(r)<PMAX(RPL(tmp),CPL)));
			}
			break;
		case 0x28: /* verw */
			tmp=GetRMWord(ModRM);
			if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
			else {
				desc[2] = ReadWord(addr+4);
				r = RIGHTS(desc);
				cpustate->ZeroVal = i80286_verify(cpustate, tmp, I80286_WRITE, RIGHTS(desc), 0);
				cpustate->ZeroVal = cpustate->ZeroVal || (DPL(r)<PMAX(RPL(tmp),CPL));
			}
			break;
		default:
			throw TRAP(ILLEGAL_INSTRUCTION,-1);
			break;
		}
		break;
	case 1:
		/* lgdt, lldt in protected mode privilege level 0 required else common protection
           failure 0xd */
		ModRM = FETCHOP;
		switch (ModRM&0x38) {
		case 0: /* sgdt */
			PutRMWord(ModRM,cpustate->gdtr.limit);
			PutRMWordOffset(2,cpustate->gdtr.base&0xffff);
			PutRMWordOffset(4,0xff00|cpustate->gdtr.base>>16);
			break;
		case 8: /* sidt */
			PutRMWord(ModRM,cpustate->idtr.limit);
			PutRMWordOffset(2,cpustate->idtr.base&0xffff);
			PutRMWordOffset(4,0xff00|cpustate->idtr.base>>16);
			break;
		case 0x10: /* lgdt */
			if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
			cpustate->gdtr.limit=GetRMWord(ModRM);
			cpustate->gdtr.base=GetRMWordOffset(2)|(GetRMByteOffset(4)<<16);
			break;
		case 0x18: /* lidt */
			if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
			cpustate->idtr.limit=GetRMWord(ModRM);
			cpustate->idtr.base=GetRMWordOffset(2)|(GetRMByteOffset(4)<<16);
			break;
		case 0x20: /* smsw */
			PutRMWord(ModRM, cpustate->msw);
			break;
		case 0x30: /* lmsw */
			if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
			msw = GetRMWord(ModRM);
			if (!PM&&(msw&1)) cpustate->sregs[CS] = IDX(cpustate->sregs[CS]); // cheat and set cpl to 0
			cpustate->msw=(cpustate->msw&1)|msw;
			break;
		default:
			throw TRAP(ILLEGAL_INSTRUCTION,-1);
			break;
		}
		break;
	case 2: /* LAR */
		if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
		ModRM = FETCHOP;
		tmp=GetRMWord(ModRM);
		if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
		else {
			desc[2] = ReadWord(addr+4);
			r = RIGHTS(desc);
			if (DPL(r)>=PMAX(RPL(tmp),CPL)) {
				cpustate->ZeroVal = 0;
				// rights are expected to be in upper byte
				RegWord(ModRM) = r << 8;
			}
			else
				cpustate->ZeroVal = 1;
		}
		break;
	case 3: /* LSL */
		if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
		ModRM = FETCHOP;
		tmp=GetRMWord(ModRM);
		if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
		else {
			desc[2] = ReadWord(addr+4);
			r = RIGHTS(desc);
			if (!SEGDESC(r) && (GATE(r) >= CALLGATE)) cpustate->ZeroVal = 1; // not valid for gates
			else if (DPL(r)>=PMAX(RPL(tmp),CPL)) {
				cpustate->ZeroVal = 0;
				RegWord(ModRM) = ReadWord(addr);
			}
			else
				cpustate->ZeroVal = 1;
		}
		break;
	case 5: /* loadall */
		if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
		cpustate->msw =        (cpustate->msw&1)|ReadWord(0x806);
		cpustate->tr.sel =     ReadWord(0x816);
		tmp =	               ReadWord(0x818);
		ExpandFlags(tmp);
		cpustate->flags = tmp;
		cpustate->flags = CompressFlags();
		cpustate->pc =         ReadWord(0x81a);
		cpustate->ldtr.sel =   ReadWord(0x81c);
		cpustate->sregs[DS] =  ReadWord(0x81e);
		cpustate->sregs[SS] =  ReadWord(0x820);
		cpustate->sregs[CS] =  ReadWord(0x822);
		cpustate->sregs[ES] =  ReadWord(0x824);
		cpustate->regs.w[DI] = ReadWord(0x826);
		cpustate->regs.w[SI] = ReadWord(0x828);
		cpustate->regs.w[BP] = ReadWord(0x82a);
		cpustate->regs.w[SP] = ReadWord(0x82c);
		cpustate->regs.w[BX] = ReadWord(0x82e);
		cpustate->regs.w[DX] = ReadWord(0x830);
		cpustate->regs.w[CX] = ReadWord(0x832);
		cpustate->regs.w[AX] = ReadWord(0x834);
// loadall uses base-rights-limit order
#define LOADDESC(addr, sreg) {  desc[1] = ReadWord(addr); desc[2] = ReadWord(addr+2); desc[0] = ReadWord(addr+4); \
				cpustate->base[sreg] = BASE(desc); cpustate->rights[sreg] = RIGHTS(desc); \
				cpustate->limit[sreg] = LIMIT(desc); }
		LOADDESC(0x836, ES);
		LOADDESC(0x83C, CS);
		LOADDESC(0x842, SS);
		LOADDESC(0x848, DS);
#undef LOADDESC
// void cast supresses warning
#define LOADDESC(addr, reg, r) { desc[1] = ReadWord(addr); desc[2] = ReadWord(addr+2); desc[0] = ReadWord(addr+4); \
				cpustate->reg.base = BASE(desc); (void)(r); cpustate->reg.limit = LIMIT(desc); }
		LOADDESC(0x84e, gdtr, 1);
		LOADDESC(0x854, ldtr, cpustate->ldtr.rights = RIGHTS(desc));
		LOADDESC(0x85a, idtr, 1);
		LOADDESC(0x860, tr,  cpustate->tr.rights = RIGHTS(desc));
#undef LOADDESC
		cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
		CHANGE_PC(cpustate->pc);
		break;

	case 6: /* clts */
		if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
		cpustate->msw&=~8;
		break;
	default:
		throw TRAP(ILLEGAL_INSTRUCTION,-1);
		break;
	}
}
static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, int hwint, int error)
{
	UINT16 desc[3], gatedesc[3]={0,0,0}, gatesel;
	UINT8 r;
	UINT32 addr;

	if(!PM) return PREFIX86(_interrupt)(cpustate, number);

	if ((number<<3)>=cpustate->idtr.limit)
		throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1)));

	desc[0] = ReadWord(cpustate->idtr.base+(number<<3));
	desc[1] = ReadWord(cpustate->idtr.base+(number<<3)+2);
	desc[2] = ReadWord(cpustate->idtr.base+(number<<3)+4);
	r = RIGHTS(desc);
	if (!hwint && (DPL(r)<CPL)) throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1)));
	if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(number*8+2+(hwint&&1)));
	gatesel = GATESEL(desc);

	switch (GATE(r)) {
	case TASKGATE:
		i80286_switch_task(cpustate, gatesel, CALL);
		if((hwint == 1) && (error != -1)) PUSH(error);
		i80286_load_flags(cpustate, cpustate->flags, CPL);
		break;
	case INTGATE:
	case TRAPGATE:
		if ((addr = i80286_selector_address(cpustate,gatesel)) == -1)
			throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
		gatedesc[0] = ReadWord(addr);
		gatedesc[1] = ReadWord(addr+2);
		gatedesc[2] = ReadWord(addr+4);
		r = RIGHTS(gatedesc);
		if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
		if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
		if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(gatesel)+(hwint&&1)));
		if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,(int)(hwint&&1));

		if (!CONF(r)&&(DPL(r)<CPL)) {  // inner call
			UINT16 tss_ss, tss_sp, oldss, oldsp;
			tss_ss = ReadWord(cpustate->tr.base+TSS_SS0*2+(DPL(r)*4));
			tss_sp = ReadWord(cpustate->tr.base+TSS_SP0*2+(DPL(r)*4));

			oldss = cpustate->sregs[SS];
			oldsp = cpustate->regs.w[SP];
			i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,(IDXTBL(tss_ss)+(hwint&&1))), tss_sp-((error != -1)?12:10), (error != -1)?12:10);
			cpustate->regs.w[SP] = tss_sp;
			PUSH(oldss);
			PUSH(oldsp);
		} else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-((error != -1)?8:6), (error != -1)?8:6, I80286_READ);
		SET_ACC(gatedesc);
		WriteWord(addr+4, gatedesc[2]);
		PREFIX(_pushf(cpustate));
		PUSH(cpustate->sregs[CS]);
		PUSH(cpustate->pc-cpustate->base[CS]);
		if((hwint == 1) && (error != -1)) PUSH(error);
		cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r);
		cpustate->limit[CS]=LIMIT(gatedesc);
		cpustate->base[CS]=BASE(gatedesc);
		cpustate->rights[CS]=RIGHTS(gatedesc);
		cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK;
		cpustate->TF = 0;
		cpustate->flags &= ~0x4000;
		if (GATE(RIGHTS(desc)) == INTGATE) cpustate->IF = 0;
		CHANGE_PC(cpustate->pc);
		break;
	default:
		throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1)));
	}
}
static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT16 offset, int gate)
{
	if (PM) {
		UINT16 desc[3];
		UINT8 r;
		UINT32 addr;
		/* selector format
           15..3 number/address in descriptor table
           2: 0 global, 1 local descriptor table
           1,0: requested privileg level
           must be higher or same as current privileg level in code selector */
		if ((addr = i80286_selector_address(cpustate,selector)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
		desc[0] = ReadWord(addr);
		desc[1] = ReadWord(addr+2);
		desc[2] = ReadWord(addr+4);
		r = RIGHTS(desc);

		if (SEGDESC(r)) {
			if (!CODE(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
			if (CONF(r)) { if(DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); }
			else if ((RPL(selector)>CPL) || (DPL(r)!=CPL)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));

			if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(selector));  // this order is important
			if (offset > LIMIT(desc)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
			SET_ACC(desc);
			WriteWord(addr+4, desc[2]);
			cpustate->sregs[CS]=IDXTBL(selector) | CPL;
			cpustate->limit[CS]=LIMIT(desc);
			cpustate->base[CS]=BASE(desc);
			cpustate->rights[CS]=RIGHTS(desc);
			cpustate->pc=cpustate->base[CS]+offset;
		} else { // systemdescriptor
			UINT16 gatedesc[3]={0,0,0};
			UINT16 gatesel = GATESEL(desc);
			if (!gate) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); // tss cs must be segment
			if (DPL(r) < PMAX(CPL,RPL(selector))) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
			if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(selector));

			switch (GATE(r)) {
			case CALLGATE:
				if ((addr = i80286_selector_address(cpustate,gatesel)) == -1)
					throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
				gatedesc[0] = ReadWord(addr);
				gatedesc[1] = ReadWord(addr+2);
				gatedesc[2] = ReadWord(addr+4);
				r = RIGHTS(gatedesc);
				if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
				if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
				if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(gatesel));
				if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,0);

				if (!CONF(r)&&(DPL(r)<CPL)) {  // inner call
					UINT16 tss_ss, tss_sp, oldss, oldsp;
					UINT32 oldstk;
					int i;
					if(gate == JMP) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); // can't jmp to inner
					tss_ss = ReadWord(cpustate->tr.base+TSS_SS0*2+(DPL(r)*4));
					tss_sp = ReadWord(cpustate->tr.base+TSS_SP0*2+(DPL(r)*4));

					oldss = cpustate->sregs[SS];
					oldsp = cpustate->regs.w[SP];
					oldstk = cpustate->base[SS] + oldsp;
					i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,IDXTBL(tss_ss)), tss_sp-8-(GATECNT(desc)*2), 8+(GATECNT(desc)*2));
					cpustate->regs.w[SP] = tss_sp;
					PUSH(oldss);
					PUSH(oldsp);
					for (i = GATECNT(desc)-1; i >= 0; i--)
						PUSH(ReadWord(oldstk+(i*2)));
				} else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-4, 4, I80286_READ);
				SET_ACC(gatedesc);
				WriteWord(addr+4, gatedesc[2]);
				cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r);
				cpustate->limit[CS]=LIMIT(gatedesc);
				cpustate->base[CS]=BASE(gatedesc);
				cpustate->rights[CS]=RIGHTS(gatedesc);
				cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK;
				break;
			case TASKGATE:
				selector = gatesel;
				if ((addr = i80286_selector_address(cpustate,selector)) == -1)
					throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
				desc[2] = ReadWord(addr+4);
				r = RIGHTS(desc);
				if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
			case TSSDESCIDLE:
				i80286_switch_task(cpustate, selector, gate);
				i80286_load_flags(cpustate, cpustate->flags, CPL);
				break;
			default:
				throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
			}
		}
	} else {
		cpustate->sregs[CS]=selector;
		cpustate->base[CS]=selector<<4;
		cpustate->rights[CS]=0x9a;
		cpustate->limit[CS]=0xffff;
		cpustate->pc=(cpustate->base[CS]+offset)&AMASK;
	}
}