Example #1
0
static void i80286_data_descriptor(i80286_state *cpustate,int reg, UINT16 selector)
{
	if (PM) {
		UINT16 help;
		/* 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 (selector&4) { /* local descriptor table */
			if (selector>cpustate->ldtr.limit) i80286_trap2(cpustate,GENERAL_PROTECTION_FAULT);
			cpustate->sregs[reg]=selector;
			cpustate->limit[reg]=ReadWord(cpustate->ldtr.base+(selector&~7));
			cpustate->base[reg]=ReadWord(cpustate->ldtr.base+(selector&~7)+2)
				|(ReadWord(cpustate->ldtr.base+(selector&~7)+4)<<16);
			cpustate->rights[reg]=cpustate->base[reg]>>24;
			cpustate->base[reg]&=0xffffff;
		} else { /* global descriptor table */
			if (!(selector&~7)||(selector>cpustate->gdtr.limit)) i80286_trap2(cpustate,GENERAL_PROTECTION_FAULT);
			cpustate->sregs[reg]=selector;
			cpustate->limit[reg]=ReadWord(cpustate->gdtr.base+(selector&~7));
			cpustate->base[reg]=ReadWord(cpustate->gdtr.base+(selector&~7)+2);
			help=ReadWord(cpustate->gdtr.base+(selector&~7)+4);
			cpustate->rights[reg]=help>>8;
			cpustate->base[reg]|=(help&0xff)<<16;
		}
	} else {
static void i80286_trap2(i80286_state *cpustate,UINT32 error)
{
	int error_code = error & 0xffff;
	UINT16 number = error >> 16;
	if(error_code == 0xffff) error_code = -1;
	cpustate->pc = cpustate->prevpc;
	try {
		switch(number) {
		case DIVIDE_BY_ZERO:
		case INVALID_TSS:
		case SEG_NOT_PRESENT:
		case STACK_FAULT:
		case GENERAL_PROTECTION_FAULT:
			cpustate->trap_level++;
			if(cpustate->trap_level == 2) throw TRAP(DOUBLE_FAULT,0);
			if(cpustate->trap_level == 3) break;
			i80286_interrupt_descriptor(cpustate,number,1,error_code);
			break;
		case DOUBLE_FAULT:
			i80286_interrupt_descriptor(cpustate,number,1,0);
			break;
		default:
			i80286_interrupt_descriptor(cpustate,number,1,-1);
		}
	} catch(UINT32 e) { i80286_trap2(cpustate, e); }
	if(cpustate->trap_level == 3)
		// this is supposed to triggered by support hardware
		// create a shutdown output line that causes a reset
		// NMI can wake processor without reset
		device_set_input_line(cpustate->device, INPUT_LINE_RESET, PULSE_LINE);
	cpustate->trap_level = 0;
}