Exemple #1
0
/* $bd JSR extended ----- */
INLINE void jsr_ex( void )
{
	EXTENDED;
	PUSHWORD(pPC);
    PC = EA;
	CHANGE_PC();
}
Exemple #2
0
/* $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;
}
Exemple #3
0
/* $9d JSR direct ----- */
INLINE void jsr_di( void )
{
	DIRECT;
	PUSHWORD(pPC);
    PC = EA;
	CHANGE_PC();
}
Exemple #4
0
/* $ad JSR indexed ----- */
INLINE void jsr_ix( void )
{
	INDEXED;
	PUSHWORD(pPC);
    PC = EA;
	CHANGE_PC();
}
Exemple #5
0
/* $8d BSR ----- */
INLINE void bsr( void )
{
	UINT8 t;
	IMMBYTE(t);
	PUSHWORD(pPC);
	PC += SIGNED(t);
	CHANGE_PC();	 /* TS 971002 */
}
Exemple #6
0
static void tms_set_context(void *src)
{
	/* copy the context */
	if (src)
		tms = *(TMS_REGS *)src;

	CHANGE_PC(tms.pc);
}
Exemple #7
0
/* $3b RTI inherent ##### */
INLINE void rti( void )
{
	PULLBYTE(CC);
	PULLBYTE(B);
	PULLBYTE(A);
	PULLWORD(pX);
	PULLWORD(pPC);
	CHANGE_PC();
	CHECK_IRQ_LINES(); /* HJB 990417 */
}
Exemple #8
0
/* $3f SWI absolute indirect ----- */
INLINE void swi( void )
{
	PUSHWORD(pPC);
	PUSHWORD(pX);
	PUSHBYTE(A);
	PUSHBYTE(B);
    PUSHBYTE(CC);
    SEI;
	PCD = RM16(0xfffa);
	CHANGE_PC();
}
Exemple #9
0
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;
}
Exemple #11
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
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;
}
Exemple #16
0
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;
}
Exemple #17
0
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)));
	}
}
Exemple #21
0
/* $7e JMP extended ----- */
INLINE void jmp_ex( void )
{
	EXTENDED; PC=EA; CHANGE_PC(); /* TS 971002 */
}
Exemple #22
0
/* $6e JMP indexed ----- */
INLINE void jmp_ix( void )
{
	INDEXED; PC=EA; CHANGE_PC();
}
Exemple #23
0
/* $39 RTS inherent ----- */
INLINE void rts( void )
{
	PULLWORD(pPC);
	CHANGE_PC();
}