/* $bd JSR extended ----- */ INLINE void jsr_ex( void ) { EXTENDED; PUSHWORD(pPC); PC = EA; CHANGE_PC(); }
/* $20 BRA relative ----- */ INLINE void bra( void ) { UINT8 t; IMMBYTE(t);PC+=SIGNED(t);CHANGE_PC(); /* speed up busy loops */ if (t==0xfe) EAT_CYCLES; }
/* $9d JSR direct ----- */ INLINE void jsr_di( void ) { DIRECT; PUSHWORD(pPC); PC = EA; CHANGE_PC(); }
/* $ad JSR indexed ----- */ INLINE void jsr_ix( void ) { INDEXED; PUSHWORD(pPC); PC = EA; CHANGE_PC(); }
/* $8d BSR ----- */ INLINE void bsr( void ) { UINT8 t; IMMBYTE(t); PUSHWORD(pPC); PC += SIGNED(t); CHANGE_PC(); /* TS 971002 */ }
static void tms_set_context(void *src) { /* copy the context */ if (src) tms = *(TMS_REGS *)src; CHANGE_PC(tms.pc); }
/* $3b RTI inherent ##### */ INLINE void rti( void ) { PULLBYTE(CC); PULLBYTE(B); PULLBYTE(A); PULLWORD(pX); PULLWORD(pPC); CHANGE_PC(); CHECK_IRQ_LINES(); /* HJB 990417 */ }
/* $3f SWI absolute indirect ----- */ INLINE void swi( void ) { PUSHWORD(pPC); PUSHWORD(pX); PUSHBYTE(A); PUSHBYTE(B); PUSHBYTE(CC); SEI; PCD = RM16(0xfffa); CHANGE_PC(); }
static CPU_RESET( tms ) { tms32051_state *cpustate = get_safe_token(device); // reset registers cpustate->st0.intm = 1; cpustate->st0.ov = 0; cpustate->st1.c = 1; cpustate->st1.cnf = 0; cpustate->st1.hm = 1; cpustate->st1.pm = 0; cpustate->st1.sxm = 1; cpustate->st1.xf = 1; cpustate->pmst.avis = 0; cpustate->pmst.braf = 0; cpustate->pmst.iptr = 0; cpustate->pmst.ndx = 0; cpustate->pmst.ovly = 0; cpustate->pmst.ram = 0; cpustate->pmst.mpmc = 0; // TODO: this is set to logical pin state at reset cpustate->pmst.trm = 0; cpustate->ifr = 0; cpustate->cbcr = 0; cpustate->rptc = -1; // simulate internal rom boot loader (can be removed when the dsp rom(s) is dumped) cpustate->st0.intm = 1; cpustate->st1.cnf = 1; cpustate->pmst.ram = 1; cpustate->pmst.ovly = 0; int i; UINT16 src, dst, length; src = 0x7800; dst = DM_READ16(cpustate, src++); length = DM_READ16(cpustate, src++); CHANGE_PC(cpustate, dst); /* TODO: if you soft reset on Taito JC it tries to do a 0x7802->0x9007 (0xff00) transfer. */ for (i=0; i < (length & 0x7ff); i++) { UINT16 data = DM_READ16(cpustate, src++); PM_WRITE16(cpustate, dst++, data); } }
bool I386::write_debug_reg(const _TCHAR *reg, uint32_t data) { i386_state *cpustate = (i386_state *)opaque; if(_tcsicmp(reg, _T("IP")) == 0) { cpustate->eip = data & 0xffff; CHANGE_PC(cpustate, cpustate->eip); } else if(_tcsicmp(reg, _T("AX")) == 0) { REG16(AX) = data; } else if(_tcsicmp(reg, _T("BX")) == 0) { REG16(BX) = data; } else if(_tcsicmp(reg, _T("CX")) == 0) { REG16(CX) = data; } else if(_tcsicmp(reg, _T("DX")) == 0) { REG16(DX) = data; } else if(_tcsicmp(reg, _T("SP")) == 0) { REG16(SP) = data; } else if(_tcsicmp(reg, _T("BP")) == 0) { REG16(BP) = data; } else if(_tcsicmp(reg, _T("SI")) == 0) { REG16(SI) = data; } else if(_tcsicmp(reg, _T("DI")) == 0) { REG16(DI) = data; } else if(_tcsicmp(reg, _T("AL")) == 0) { REG8(AL) = data; } else if(_tcsicmp(reg, _T("AH")) == 0) { REG8(AH) = data; } else if(_tcsicmp(reg, _T("BL")) == 0) { REG8(BL) = data; } else if(_tcsicmp(reg, _T("BH")) == 0) { REG8(BH) = data; } else if(_tcsicmp(reg, _T("CL")) == 0) { REG8(CL) = data; } else if(_tcsicmp(reg, _T("CH")) == 0) { REG8(CH) = data; } else if(_tcsicmp(reg, _T("DL")) == 0) { REG8(DL) = data; } else if(_tcsicmp(reg, _T("DH")) == 0) { REG8(DH) = data; } else { return false; } return false; }
static void check_interrupts(void) { int i; if ((sharc.imask & sharc.irq_active) && (sharc.mode1 & MODE1_IRPTEN) && !interrupt_active) { int which = 0; for (i=0; i < 32; i++) { if (sharc.irq_active & (1 << i)) { break; } which++; } if (sharc.idle) { PUSH_PC(sharc.pc+1); } else { PUSH_PC(sharc.daddr); } sharc.irptl |= 1 << which; if (which >= 6 && which <= 8) { PUSH_STATUS_STACK(); } CHANGE_PC(0x20000 + (which * 0x4)); /* TODO: alter IMASKP */ sharc.active_irq_num = which; sharc.irq_active &= ~(1 << which); interrupt_active = 1; } }
static CPU_RESET( tms ) { tms32051_state *cpustate = get_safe_token(device); int i; UINT16 src, dst, length; src = 0x7800; dst = DM_READ16(cpustate, src++); length = DM_READ16(cpustate, src++); CHANGE_PC(cpustate, dst); /* TODO: if you soft reset on Taito JC it tries to do a 0x7802->0x9007 (0xff00) transfer. */ for (i=0; i < (length & 0x7ff); i++) { UINT16 data = DM_READ16(cpustate, src++); PM_WRITE16(cpustate, dst++, data); } cpustate->st0.intm = 1; cpustate->st0.ov = 0; cpustate->st1.c = 1; cpustate->st1.cnf = 0; cpustate->st1.hm = 1; cpustate->st1.pm = 0; cpustate->st1.sxm = 1; cpustate->st1.xf = 1; cpustate->pmst.avis = 0; cpustate->pmst.braf = 0; cpustate->pmst.iptr = 0; cpustate->pmst.ndx = 0; cpustate->pmst.ovly = 0; cpustate->pmst.ram = 0; cpustate->pmst.trm = 0; cpustate->ifr = 0; cpustate->cbcr = 0; cpustate->rptc = -1; }
static CPU_RESET( tms ) { tms32051_state *cpustate = get_safe_token(device); int i; UINT16 src, dst, length; src = 0x7800; dst = DM_READ16(cpustate, src++); length = DM_READ16(cpustate, src++); CHANGE_PC(cpustate, dst); for (i=0; i < length; i++) { UINT16 data = DM_READ16(cpustate, src++); PM_WRITE16(cpustate, dst++, data); } cpustate->st0.intm = 1; cpustate->st0.ov = 0; cpustate->st1.c = 1; cpustate->st1.cnf = 0; cpustate->st1.hm = 1; cpustate->st1.pm = 0; cpustate->st1.sxm = 1; cpustate->st1.xf = 1; cpustate->pmst.avis = 0; cpustate->pmst.braf = 0; cpustate->pmst.iptr = 0; cpustate->pmst.ndx = 0; cpustate->pmst.ovly = 0; cpustate->pmst.ram = 0; cpustate->pmst.trm = 0; cpustate->ifr = 0; cpustate->cbcr = 0; cpustate->rptc = -1; }
static void tms_reset(void) { int i; UINT16 src, dst, length; src = 0x7800; dst = DM_READ16(src++); length = DM_READ16(src++); CHANGE_PC(dst); for (i=0; i < length; i++) { UINT16 data = DM_READ16(src++); PM_WRITE16(dst++, data); } tms.st0.intm = 1; tms.st0.ov = 0; tms.st1.c = 1; tms.st1.cnf = 0; tms.st1.hm = 1; tms.st1.pm = 0; tms.st1.sxm = 1; tms.st1.xf = 1; tms.pmst.avis = 0; tms.pmst.braf = 0; tms.pmst.iptr = 0; tms.pmst.ndx = 0; tms.pmst.ovly = 0; tms.pmst.ram = 0; tms.pmst.trm = 0; tms.ifr = 0; tms.cbcr = 0; tms.rptc = -1; }
static int tms_execute(int num_cycles) { tms_icount = num_cycles; while(tms_icount > 0) { UINT16 ppc; // handle block repeat if (tms.pmst.braf) { if (tms.pc == tms.paer) { if (tms.brcr > 0) { CHANGE_PC(tms.pasr); } tms.brcr--; if (tms.brcr <= 0) { tms.pmst.braf = 0; } } } ppc = tms.pc; CALL_DEBUGGER(tms.pc); tms.op = ROPCODE(); tms32051_opcode_table[tms.op >> 8](); // handle single repeat if (tms.rptc > 0) { if (ppc == tms.rpt_end) { CHANGE_PC(tms.rpt_start); tms.rptc--; } } else { tms.rptc = 0; } tms.timer.psc--; if (tms.timer.psc <= 0) { tms.timer.psc = tms.timer.tddr; tms.timer.tim--; if (tms.timer.tim <= 0) { // reset timer tms.timer.tim = tms.timer.prd; tms_interrupt(INTERRUPT_TINT); } } } return num_cycles - tms_icount; }
static int sharc_execute(int cycles) { sharc_icount = cycles; if (sharc.idle && sharc.irq_active == 0) { // handle pending DMA transfers if (dmaop_cycles > 0) { dmaop_cycles -= cycles; if (dmaop_cycles <= 0) { dmaop_cycles = 0; dma_op(dmaop_src, dmaop_dst, dmaop_src_modifier, dmaop_dst_modifier, dmaop_src_count, dmaop_dst_count, dmaop_pmode); if (dmaop_chain_ptr != 0) { schedule_chained_dma_op(dmaop_channel, dmaop_chain_ptr, dmaop_chained_direction); } } } sharc_icount = 0; CALL_MAME_DEBUG; return cycles; } if (sharc.irq_active != 0) { check_interrupts(); sharc.idle = 0; } // fill the initial pipeline // next executed instruction sharc.opcode = ROPCODE(sharc.daddr); sharc.opcode_handler = sharc_op[(sharc.opcode >> 39) & 0x1ff]; // next decoded instruction sharc.fetch_opcode = ROPCODE(sharc.faddr); while (sharc_icount > 0 && !sharc.idle) { sharc.pc = sharc.daddr; sharc.daddr = sharc.faddr; sharc.faddr = sharc.nfaddr; sharc.nfaddr++; sharc.decode_opcode = sharc.fetch_opcode; // fetch next instruction sharc.fetch_opcode = ROPCODE(sharc.faddr); CALL_MAME_DEBUG; // handle looping if (sharc.pc == (sharc.laddr & 0xffffff)) { switch (sharc.laddr >> 30) { case 0: // arithmetic condition-based { int condition = (sharc.laddr >> 24) & 0x1f; if (DO_CONDITION_CODE(condition)) { POP_LOOP(); POP_PC(); } else { CHANGE_PC(TOP_PC()); } break; } case 1: // counter-based, length 1 { //fatalerror("SHARC: counter-based loop, length 1 at %08X", sharc.pc); //break; } case 2: // counter-based, length 2 { //fatalerror("SHARC: counter-based loop, length 2 at %08X", sharc.pc); //break; } case 3: // counter-based, length >2 { --sharc.lcstack[sharc.lstkp]; --sharc.curlcntr; if (sharc.curlcntr == 0) { POP_LOOP(); POP_PC(); } else { CHANGE_PC(TOP_PC()); } } } } // execute current instruction sharc.opcode_handler(); // decode next instruction sharc.opcode = sharc.decode_opcode; sharc.opcode_handler = sharc_op[(sharc.opcode >> 39) & 0x1ff]; // System register latency effect if (systemreg_latency_cycles > 0) { --systemreg_latency_cycles; if (systemreg_latency_cycles <= 0) { systemreg_write_latency_effect(); } } // IOP register latency effect if (iop_latency_cycles > 0) { --iop_latency_cycles; if (iop_latency_cycles <= 0) { iop_write_latency_effect(); } } // DMA transfer if (dmaop_cycles > 0) { --dmaop_cycles; if (dmaop_cycles <= 0) { dma_op(dmaop_src, dmaop_dst, dmaop_src_modifier, dmaop_dst_modifier, dmaop_src_count, dmaop_dst_count, dmaop_pmode); if (dmaop_chain_ptr != 0) { schedule_chained_dma_op(dmaop_channel, dmaop_chain_ptr, dmaop_chained_direction); } } } --sharc_icount; }; return cycles - sharc_icount; }
static CPU_EXECUTE( tms ) { tms32051_state *cpustate = get_safe_token(device); while(cpustate->icount > 0) { UINT16 ppc; // handle block repeat if (cpustate->pmst.braf) { if (cpustate->pc == cpustate->paer) { if (cpustate->brcr > 0) { CHANGE_PC(cpustate, cpustate->pasr); } cpustate->brcr--; if (cpustate->brcr <= 0) { cpustate->pmst.braf = 0; } } } ppc = cpustate->pc; debugger_instruction_hook(device, cpustate->pc); cpustate->op = ROPCODE(cpustate); tms32051_opcode_table[cpustate->op >> 8](cpustate); // handle single repeat if (cpustate->rptc > 0) { if (ppc == cpustate->rpt_end) { CHANGE_PC(cpustate, cpustate->rpt_start); cpustate->rptc--; } } else { cpustate->rptc = 0; } cpustate->timer.psc--; if (cpustate->timer.psc <= 0) { cpustate->timer.psc = cpustate->timer.tddr; cpustate->timer.tim--; if (cpustate->timer.tim <= 0) { // reset timer cpustate->timer.tim = cpustate->timer.prd; tms_interrupt(cpustate, INTERRUPT_TINT); } } } }
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))); } }
/* $7e JMP extended ----- */ INLINE void jmp_ex( void ) { EXTENDED; PC=EA; CHANGE_PC(); /* TS 971002 */ }
/* $6e JMP indexed ----- */ INLINE void jmp_ix( void ) { INDEXED; PC=EA; CHANGE_PC(); }
/* $39 RTS inherent ----- */ INLINE void rts( void ) { PULLWORD(pPC); CHANGE_PC(); }