⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tms9900.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
字号:
/*******************************************************
 *
 *      Portable TMS9900 emulator
 *
 *      Based on original TI99/4A TMS9900 engine by Ton Brouwer
 *	Adapted for use with DJGPP\MAME by Andy Jones
 *
 *******************************************************/

#define VERBOSE

#ifdef  VERBOSE
#include <stdio.h>
#include "driver.h"
#endif

#include "memory.h"
#include "tms9900/tms9900.h"
#include "tms9900/tms9900c.h"

static  TMS9900_Regs I;

int     TMS9900_ICount = 0;

#define RDMEMW(addr)		( ( cpu_readmem16((addr)) << 8 ) + cpu_readmem16((addr)+1))
#define WRMEMW(addr,data)	{ cpu_writemem16((addr), (data)>>8 );cpu_writemem16((addr)+1, (data)&0xff ) ;}
#define RDMEMB(addr)		( cpu_readmem16((addr)) << 8)
#define WRMEMB(addr,data)	{ cpu_writemem16((addr),(data)>>8) ; }

/********************************************************************************/
/* Standard MAME cpu interface functions.                                       */
/********************************************************************************/

void    TMS9900_Reset(void)
{
	I.STATUS=I.IR=0;
	I.WP=RDMEMW(0);
	I.PC=RDMEMW(2);


}

int     TMS9900_Execute(int cycles)
{
        TMS9900_ICount = cycles;



        do
        {

#ifdef  MAME_DEBUG
		{
		        extern int mame_debug;

                	if (mame_debug) MAME_Debug();
		}
#endif

		I.IR=RDMEMW(I.PC);		/* fetch instruction		*/


		I.PC+=2;                  	/* update program counter 	*/
		(*opcode_table[I.IR>>8])();	/* execute instruction 		*/

		TMS9900_ICount -= 12 ; /* Fudge : I have no idea of instruction timings */

	} while (TMS9900_ICount > 0);



        return cycles - TMS9900_ICount;
}

void    TMS9900_GetRegs(TMS9900_Regs * regs)
{
	I.STATUS = get_status();



        *regs = I;
}

void    TMS9900_SetRegs(TMS9900_Regs * regs)
{
        I = *regs;

	set_status (I.STATUS);


}

int     TMS9900_GetPC(void)
{


        return I.PC;
}


void    TMS9900_Cause_Interrupt(int intlevel)
{
	if (intlevel <= IMASK)
	{

		word oldwp;

		oldwp=I.WP;
		I.STATUS = get_status();	/* Make sure status us uptodate before we store it */
		I.WP=RDMEMW(intlevel*4);	/* get new workspace */
		WRMEMW(R13,oldwp);        	/* store old WP in new R13 */
		WRMEMW(R14,I.PC);		/* store old PC in new R14 */
		WRMEMW(R15,I.STATUS);		/* store old STATUS in R15 */

		set_mask((IMASK&0xF)-1);	/* Decrement the interupt mask */

		I.STATUS = get_status();	/* Update the status again */

		I.PC=RDMEMW((intlevel*4)+2);	/* get new PC */
	}
}

void    TMS9900_Clear_Pending_Interrupts(void)
{
}

/********************************************************************************/
/* Low opcodes jump redirection                                                 */
/********************************************************************************/

void TAB2(void)
{
	(*low_opcode_table[I.IR>>5])();
}

/********************************************************************************/
/* This part provides the operands for the different types of opcodes.          */
/********************************************************************************/

void typeIoperands(void)
{
	get_source_operand();
	get_dest_operand();
	if (BYTE_OPERATION)
        {


		SourceVal=RDMEMB(SourceOpAdr);
	        DestVal=RDMEMB(DestOpAdr);
	}
	else
	{
		SourceOpAdr&=0xFFFE;
		DestOpAdr&=0xFFFE;

		SourceVal=RDMEMW(SourceOpAdr);
	        DestVal=RDMEMW(DestOpAdr);
	}
}

void typeIIIoperands(void)
{
	get_source_operand();
	SourceVal=RDMEMW(SourceOpAdr&0xFFFE);
	DestOpAdr=I.WP+((I.IR>>5)&0x1e);
	DestVal=RDMEMW(DestOpAdr);
}

void typeIVoperands(void)
{
	get_source_operand();
	SourceVal=RDMEMW(SourceOpAdr&=0xFFFE);
	DestVal=(I.IR>>6)&0xF;
	CRUBaseAdr = ((RDMEMW(R12)&0x1FFE)>>1);
}

void typeVoperands(void)
{
	SourceOpAdr=I.WP+((I.IR&0xF)<<1);
	SourceVal=RDMEMW(SourceOpAdr);
	DestVal=(I.IR>>4)&0xF;
	if (!DestVal)
	{
		DestVal=RDMEMW(I.WP)&0xF;
		if (!DestVal) DestVal=16;
	}
}

void typeVIoperands(void)
{
	get_source_operand();
	SourceVal=RDMEMW(SourceOpAdr&=0xFFFE);
}

void typeVIIIoperands(void)
{
	SourceOpAdr=I.WP+((I.IR&0xF)<<1);
	SourceVal=RDMEMW(SourceOpAdr);
	DestVal=RDMEMW(I.PC);
	I.PC+=2;
}

void typeIXoperands(void)
{
	SourceOpAdr=I.WP+((I.IR&0xF)<<1);
}

void typeXoperands(void)
{
	SourceVal=RDMEMW(I.PC);
	I.PC+=2;
}

/********************************************************************************/
/* Decode the source operand. Use address modification indicated by bit 2 and 3 */
/* of the instruction register.                                                 */
/********************************************************************************/

void get_source_operand(void)
{
	switch((I.IR>>4)&3)
	{

 /* WS Register direct - (Contents of register) */

	    case 0: 	SourceOpAdr=I.WP+((I.IR&0xF)<<1);
			break;

 /* Indirect WS Register (Contents of memory location pointed to by register)*/

	    case 1: 	SourceOpAdr=RDMEMW(I.WP+((I.IR&0xF)<<1));
			break;

/* Direct (Contents of memory address specified) */
/* Indexed ('Direct' address + contents of WS register - when not R0) */

	    case 2: 	SourceOpAdr=RDMEMW(I.PC); I.PC+=2;
			if (I.IR&0xF) SourceOpAdr+=RDMEMW(I.WP+((I.IR&0xF)<<1));
			break;

/* Indirect WS Register Auto Increment (as '1' but increment register contents afterwards) */

	    case 3:	SourceOpAdr=RDMEMW(I.WP+((I.IR&0xF)<<1));
			WRMEMW(I.WP+((I.IR&0xF)<<1),SourceOpAdr+((BYTE_OPERATION) ? 1:2));
			break;
	}



}

void get_dest_operand(void)
{
	switch((I.IR>>10)&3)
	{
	case 0: 	DestOpAdr=I.WP+((I.IR>>5)&0x1E); /* Register direct */
			break;
	case 1: 	DestOpAdr=RDMEMW(I.WP+((I.IR>>5)&0x1E));
			break;
	case 2: 	DestOpAdr=RDMEMW(I.PC); I.PC+=2;
			if (I.IR&0x3c0) DestOpAdr+=RDMEMW(I.WP+((I.IR>>5)&0x1E));
			break;
	case 3: 	DestOpAdr=RDMEMW(I.WP+((I.IR>>5)&0x1E));
			WRMEMW(I.WP+((I.IR>>5)&0x1E),DestOpAdr+((BYTE_OPERATION) ? 1:2));
			break;
	}


}

/********************************************************************************/
/* Instruction bodies.                                                          */
/********************************************************************************/

void SRA()
{
	typeVoperands();
	if (DestVal>1) SourceVal=(signed short int)SourceVal>>(DestVal-1);
	CY=SourceVal&1;
	SourceVal=(signed short int)SourceVal>>1;
	set_status(SourceVal);
	WRMEMW(SourceOpAdr,SourceVal);
	TMS9900_ICount -= TMS9900_CYCLES_SRA ;
}

void SRL()
{
	typeVoperands();
	if (DestVal>1) SourceVal>>=DestVal-1;
	CY=SourceVal&1;
	SourceVal>>=1;
	set_status(SourceVal);
	WRMEMW(SourceOpAdr,SourceVal);
}

void SLA()
{
	typeVoperands();
	OV=((((signed short int)0x8000>>DestVal) &SourceVal)!=0);
	if (DestVal>1) SourceVal<<=DestVal-1;
	CY=((SourceVal&0x8000)!=0);
	SourceVal<<=1;
	set_status(SourceVal);
	WRMEMW(SourceOpAdr,SourceVal);
}

void SRC()
{
	typeVoperands();
	SourceVal=(word)(SourceVal>>DestVal)|(SourceVal<<(16-DestVal));
	CY=((SourceVal&0x8000)!=0);
	set_status(SourceVal);
	WRMEMW(SourceOpAdr,SourceVal);
}

void SZC()
{
	typeIoperands();
	DestVal&=~SourceVal;
	set_status(DestVal);
	WRMEMW(DestOpAdr,DestVal);
}

void SZCB()
{
	typeIoperands();
	DestVal&=(~SourceVal|0xFF);
	set_status(DestVal&0xFF00);
	set_parity(DestVal);
	WRMEMB(DestOpAdr,DestVal);
}

void S()
{
	typeIoperands();
	DestVal=add(DestVal,1+~SourceVal);
	set_status(DestVal);
	WRMEMW(DestOpAdr,DestVal);
}

void SB()
{
	typeIoperands();
	DestVal=(DestVal&0xFF)|add(DestVal&0xFF00,1+~(SourceVal&0xFF00));
	set_status(DestVal&0xFF00);
	set_parity(DestVal);
	WRMEMB(DestOpAdr,DestVal);
}

void C()
{
	typeIoperands();
	compare(SourceVal,DestVal);
}

void CB()
{
	typeIoperands();
	compare(SourceVal&0xFF00,DestVal&0xFF00);
	set_parity(SourceVal);
}

void A()
{
	typeIoperands();
	DestVal=add(SourceVal,DestVal);
	set_status(DestVal);
	WRMEMW(DestOpAdr,DestVal);
}

void AB()
{
	typeIoperands();
	SourceVal=add(SourceVal&0xFF00,DestVal&0xFF00);
	set_status(SourceVal&0xFF00);
	set_parity(SourceVal);
	WRMEMB(DestOpAdr,DestVal);
}

void MOV()
{
	typeIoperands();
	set_status(SourceVal);
	WRMEMW(DestOpAdr,SourceVal);
}

void MOVB()
{
	typeIoperands();
	set_status(SourceVal&0xFF00);
	set_parity(SourceVal);
	WRMEMB(DestOpAdr,SourceVal);
}

void SOC()
{
	typeIoperands();
	DestVal|=SourceVal;
	set_status(DestVal);
	WRMEMW(DestOpAdr,DestVal);
}

void SOCB()
{
	typeIoperands();
	DestVal|=SourceVal&0xFF00;
	set_status(DestVal&0xFF00);
	set_parity(DestVal);
	WRMEMB(DestOpAdr,DestVal);
}

void JMP() { 				do_jmp(); }
void JLT() { if (AGT==0 && EQ==0) 	do_jmp(); }
void JLE() { if (LGT==FALSE || EQ==1) 	do_jmp(); }
void JEQ() { if (EQ==1) 		do_jmp(); }
void JHE() { if (LGT==1 || EQ==1) 	do_jmp(); }
void JGT() { if (AGT==1) 		do_jmp(); }
void JNE() { if (EQ==0) 		do_jmp(); }
void JNC() { if (CY==0) 		do_jmp(); }
void JOC() { if (CY==1) 		do_jmp(); }
void JNO() { if (OV==0) 		do_jmp(); }
void JL()  { if (LGT==0 && EQ==0) 	do_jmp(); }
void JH()  { if (LGT==1) 		do_jmp(); }
void JOP() { if (OP==1) 		do_jmp(); }

void do_jmp(void)
{
	I.PC+=(I.IR&0xFF)<<1;
	if (I.IR&0x0080) I.PC-=0x200;
}

void SBO()
{
	CRUBaseAdr = ((RDMEMW(R12)&0x1FFE)>>1);

}

void SBZ()
{
	CRUBaseAdr = ((RDMEMW(R12)&0x1FFE)>>1);

}

void TB()
{
	CRUBaseAdr = ((RDMEMW(R12)&0x1FFE)>>1);


	EQ=0;
}

void COC()
{
	typeIIIoperands();
	EQ=( (SourceVal&~DestVal)==0 );
}

void CZC()
{
	typeIIIoperands();
	EQ=( (SourceVal&DestVal)==0 );
}

void XOR()
{
	typeIIIoperands();
	DestVal^=SourceVal;
	set_status(DestVal);
	WRMEMW(DestOpAdr,DestVal);
}

void XOP()
{
	word oldwp,oldpc;
	typeIVoperands();
	oldwp=I.WP;
	oldpc=I.PC;
	I.WP=RDMEMW(0x40+(DestVal<<2));
	I.PC=RDMEMW(0x42+(DestVal<<2));
	WRMEMW(R11,SourceVal);
	WRMEMW(R13,oldwp);
	WRMEMW(R14,oldpc);
	I.STATUS = get_status();
	WRMEMW(R15,I.STATUS);
	X=1;
}

void LDCR()
{
	EQ=0;
	typeIVoperands();
	set_status(SourceVal);

}

void STCR()
{
	typeIVoperands();

	WRMEMW(SourceOpAdr,0x0E00);
	set_status(SourceVal);

}

void MPY()
{
	unsigned long int m;
	typeIIIoperands();
	m=(unsigned long int)SourceVal*(unsigned long int)DestVal;
	WRMEMW(DestOpAdr,(word)(m>>16));
	WRMEMW(DestOpAdr+2,(word)(m&0xFFFF));
}

void DIV()
{
	unsigned long int m;
	typeIIIoperands();
	m=((unsigned long int)(DestVal)<<16)+
	  (unsigned long int)RDMEMW(DestOpAdr+2);
	OV=(SourceVal<=DestVal);
	if ((SourceVal)&&!OV)
	{
		WRMEMW(DestOpAdr,(word)(m/SourceVal));
		WRMEMW(DestOpAdr+2,(word)(m%SourceVal));
	}
}

void LI()
{
	typeVIIIoperands();
	WRMEMW(SourceOpAdr,DestVal);
	set_status(DestVal);
}

void AI()
{
	typeVIIIoperands();
	DestVal=add(SourceVal,DestVal);
	WRMEMW(SourceOpAdr,DestVal);
	set_status(DestVal);
}

void ANDI()
{
	typeVIIIoperands();
	DestVal&=SourceVal;
	WRMEMW(SourceOpAdr,DestVal);
	set_status(DestVal);
}

void ORI()
{
	typeVIIIoperands();
	DestVal|=SourceVal;
	WRMEMW(SourceOpAdr,DestVal);
	set_status(DestVal);
}

void CI()
{
	typeVIIIoperands();
	compare(SourceVal,DestVal);
}

void STWP()
{
	typeIXoperands();
	WRMEMW(SourceOpAdr,I.WP);
}

void STST()
{
	typeIXoperands();
	I.STATUS = get_status();
	WRMEMW(SourceOpAdr,I.STATUS);
}

void LWPI()
{
	typeXoperands();
	I.WP=SourceVal;
}

void LIMI()
{
	typeXoperands();
	set_mask(SourceVal);
}

void RTWP()
{
	I.PC = RDMEMW(R14);
	I.STATUS = RDMEMW(R15);
	I.WP = RDMEMW(R13);

	set_status(I.STATUS);				
	set_parity(I.STATUS);				
	set_mask(I.STATUS);				
}

void BLWP()
{
	word oldwp;
	I.STATUS = get_status();
	typeVIoperands();
	oldwp=I.WP;
	I.WP=SourceVal;			/* get new workspace */
	WRMEMW(R13,oldwp);        	/* store old WP in new R13 */
	WRMEMW(R14,I.PC);		/* store old PC in new R14 */
	WRMEMW(R15,I.STATUS);		/* store old STATUS in R15 */
	I.PC=RDMEMW(SourceOpAdr+2);	/* get new PC :-) */
}

void B()
{
	typeVIoperands();
	I.PC=SourceOpAdr;
}

void eX()
{
	typeVIoperands();
	I.IR=SourceVal;
        (*opcode_table[I.IR>>8])();	/* execute instruction */
}

void CLR()
{
	typeVIoperands();
	WRMEMW(SourceOpAdr,0);
}

void NEG()
{
        typeVIoperands();
	DestVal=add(~SourceVal,1);
	set_status(DestVal);
	WRMEMW(SourceOpAdr,DestVal);
}

void INV()
{
	typeVIoperands();
	DestVal=~SourceVal;
	set_status(DestVal);
	WRMEMW(SourceOpAdr,DestVal);
}

void INC()
{
	typeVIoperands();
	DestVal=add(SourceVal,1);
	set_status(DestVal);
	WRMEMW(SourceOpAdr,DestVal);
}

void INCT()
{
	typeVIoperands();
	DestVal=add(SourceVal,2);
	set_status(DestVal);
	WRMEMW(SourceOpAdr,DestVal);
}

void DEC()
{
	typeVIoperands();
	DestVal=add(SourceVal,0xFFFF);
	set_status(DestVal);
	WRMEMW(SourceOpAdr,DestVal);
}

void DECT()
{
	typeVIoperands();
	DestVal=add(SourceVal,0xFFFE);
	set_status(DestVal);
	WRMEMW(SourceOpAdr,DestVal);
}

void BL()
{
	typeVIoperands();
	WRMEMW(R11,I.PC);
	I.PC=SourceOpAdr;
}

void SWPB()
{
	typeVIoperands();
	SourceVal=((SourceVal&0xFF)<<8) | (SourceVal>>8);
	WRMEMW(SourceOpAdr,SourceVal);
}

void SETO()
{
	typeVIoperands();
	WRMEMW(SourceOpAdr,0xFFFF);
}

void ABSv()
{
	typeVIoperands();
	set_status(SourceVal);
	OV=(SourceVal==0x8000);
	if (SourceVal&0x8000) SourceVal=~SourceVal+1;
	WRMEMW(SourceOpAdr,SourceVal);
}

void IDLE()
{
}

void RSET()
{
}

void CKON()
{
}

void CKOF()
{
}

void LREX()
{
}

void ILL()
{
}

/********************************************************************************/
/* This part provides the status register handling                              */
/********************************************************************************/

word get_status(void)
{
	return (LGT<<15)|(AGT<<14)|(EQ<<13)|(CY<<12)|(OV<<11)|(OP<<10)|(X<<9)|(IMASK&0xf);
}

void set_status(word value)
{
	EQ=(value==0);
	LGT=!EQ;
	AGT=LGT && (!(value&SIGN));
}

void set_parity(word value)
{
	OP= ((PARCHECK >> (value>>12)) ^ (PARCHECK >> ((value>>8)&15))) &1;
}

void set_mask(word value)
{
	IMASK = value&0xf;
}

/********************************************************************************/
/* Support functions                                                            */
/********************************************************************************/

void compare(word source,word dest)
{
	LGT=(source>dest);
	EQ=(source==dest);
	AGT=((signed short int)source>(signed short int)dest);
}

word add(word a, word b)
{
	word c;
	c=a+b;
	CY=(((a&b)&SIGN)!=0) || (((a&SIGN) != (b&SIGN)) &&((c&SIGN)==0));
	OV=((~a&~b&c&SIGN) || (a&b&~c&SIGN))!=0;
	return(c);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -