static CPU_SET_INFO( nec ) { nec_state_t *nec_state = get_safe_token(device); switch (state) { /* --- the following bits of info are set as 64-bit signed integers --- */ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(nec_state, 0, info->i); break; case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(nec_state, INPUT_LINE_NMI, info->i); break; case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: set_irq_line(nec_state, NEC_INPUT_LINE_POLL, info->i); break; case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + NEC_PC: if( info->i - (Sreg(PS)<<4) < 0x10000 ) { nec_state->ip = info->i - (Sreg(PS)<<4); } else { Sreg(PS) = info->i >> 4; nec_state->ip = info->i & 0x0000f; } break; case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break; case CPUINFO_INT_SP: if( info->i - (Sreg(SS)<<4) < 0x10000 ) { Wreg(SP) = info->i - (Sreg(SS)<<4); } else { Sreg(SS) = info->i >> 4; Wreg(SP) = info->i & 0x0000f; } break; case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break; case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break; case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break; case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break; case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break; case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break; case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break; case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break; case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break; case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break; case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break; case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break; case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break; } }
static void i80286_load_flags(i8086_state *cpustate, UINT16 flags, int cpl) { cpustate->flags = CompressFlags(); if(PM && cpl) { UINT16 mask = 0x3000; if(cpl>IOPL) mask |= 0x200; flags &= ~mask; flags |= (cpustate->flags & mask); } else if(!PM) (flags &= ~0xf000); ExpandFlags(flags); cpustate->flags = flags; if (cpustate->TF) PREFIX(_trap)(cpustate); /* if the IF is set, and an interrupt is pending, signal an interrupt */ if (cpustate->IF && cpustate->irq_state) i80286_interrupt_descriptor(cpustate, (*cpustate->irq_callback)(cpustate->device, 0), 2, -1); }
void nec_common_device::state_import(const device_state_entry &entry) { switch (entry.index()) { case NEC_PC: if( m_debugger_temp - (Sreg(PS)<<4) < 0x10000 ) { m_ip = m_debugger_temp - (Sreg(PS)<<4); } else { Sreg(PS) = m_debugger_temp >> 4; m_ip = m_debugger_temp & 0x0000f; } break; case NEC_FLAGS: ExpandFlags(m_debugger_temp); break; } }
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; } }