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; }