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

📄 pxa_io.cpp

📁 這是一個arm模擬器 以C++實做 主要模擬ARM9架構
💻 CPP
字号:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include "pxa_io.h"

#define F_CORE (100 * 1024 * 1024)	//core frequence
#define F_RTC 32768		//RTC
#define F_OS	3686400		//OS timer
#define RT_SCALE (F_CORE / F_RTC) / 50
#define OS_SCALE (F_CORE / F_OS / 10) / 50

#define FF_SCALE	200	//FF UART


using namespace simit;

enum
{
	RTC_ALARM_IRQ = (1 << 31),
	RTC_HZ_IRQ = (1 << 30),
	OS_IRQ_SHF = 26,
	FFUART_IRQ = (1 << 22),
};

enum
{
	ICIP = 0x40D00000,	/* Interrupt Controller IRQ Pending Register */
	ICMR = 0x40D00004,	/* Interrupt Controller Mask Register */
	ICLR = 0x40D00008,	/* Interrupt Controller Level Register */
	ICFP = 0x40D0000C,	/* Interrupt Controller FIQ Pending Register */
	ICPR = 0x40D00010,	/* Interrupt Controller Pending Register */
	ICCR = 0x40D00014,	/* Interrupt Controller Control Register */

	RCNR = 0x40900000,	/* RTC Count Register */
	RTAR = 0x40900004,	/* RTC Alarm Register */
	RTSR = 0x40900008,	/* RTC Status Register */
	RTTR = 0x4090000C,	/* RTC Timer Trim Register */

	OSMR0 = 0x40A00000,
	OSMR1 = 0x40A00004,
	OSMR2 = 0x40A00008,
	OSMR3 = 0x40A0000C,
	OSCR = 0x40A00010,	/* OS Timer Counter Register */
	OSSR = 0x40A00014,	/* OS Timer Status Register */
	OWER = 0x40A00018,	/* OS Timer Watchdog Enable Register */
	OIER = 0x40A0001C,	/* OS Timer Interrupt Enable Register */


	/*Full Function UART */
	FFRBR = 0x40100000,	/* Receive Buffer Register (read only) */
	FFTHR = 0x40100000,	/* Transmit Holding Register (write only) */
	FFIER = 0x40100004,	/* Interrupt Enable Register (read/write) */
	FFIIR = 0x40100008,	/* Interrupt ID Register (read only) */
	FFFCR = 0x40100008,	/* FIFO Control Register (write only) */
	FFLCR = 0x4010000C,	/* Line Control Register (read/write) */
	FFMCR = 0x40100010,	/* Modem Control Register (read/write) */
	FFLSR = 0x40100014,	/* Line Status Register (read only) */
	FFMSR = 0x40100018,	/* Reserved */
	FFSPR = 0x4010001C,	/* Scratch Pad Register (read/write) */
	FFISR = 0x40100020,	/* Infrared Selection Register (read/write) */
	FFDLL = 0x40100000,	/* Divisor Latch Low Register (DLAB = 1) (read/write) */
	FFDLH = 0x40100004,	/* Divisor Latch High Register (DLAB = 1) (read/write) */
	/*Standard UART */
	BTRBR = 0x40200000,	/* Receive Buffer Register (read only) */
	BTTHR = 0x40200000,	/* Transmit Holding Register (write only) */
	BTIER = 0x40200004,	/* Interrupt Enable Register (read/write) */
	BTIIR = 0x40200008,	/* Interrupt ID Register (read only) */
	BTFCR = 0x40200008,	/* FIFO Control Register (write only) */
	BTLCR = 0x4020000C,	/* Line Control Register (read/write) */
	BTMCR = 0x40200010,	/* Modem Control Register (read/write) */
	BTLSR = 0x40200014,	/* Line Status Register (read only) */
	BTMSR = 0x40200018,	/* Reserved */
	BTSPR = 0x4020001C,	/* Scratch Pad Register (read/write) */
	BTISR = 0x40200020,	/* Infrared Selection Register (read/write) */
	BTDLL = 0x40200000,	/* Divisor Latch Low Register (DLAB = 1) (read/write) */
	BTDLH = 0x40200004,	/* Divisor Latch High Register (DLAB = 1) (read/write) */
	/*Standard UART */
	STRBR = 0x40700000,	/* Receive Buffer Register (read only) */
	STTHR = 0x40700000,	/* Transmit Holding Register (write only) */
	STIER = 0x40700004,	/* Interrupt Enable Register (read/write) */
	STIIR = 0x40700008,	/* Interrupt ID Register (read only) */
	STFCR = 0x40700008,	/* FIFO Control Register (write only) */
	STLCR = 0x4070000C,	/* Line Control Register (read/write) */
	STMCR = 0x40700010,	/* Modem Control Register (read/write) */
	STLSR = 0x40700014,	/* Line Status Register (read only) */
	STMSR = 0x40700018,	/* Reserved */
	STSPR = 0x4070001C,	/* Scratch Pad Register (read/write) */
	STISR = 0x40700020,	/* Infrared Selection Register (read/write) */
	STDLL = 0x40700000,	/* Divisor Latch Low Register (DLAB = 1) (read/write) */
	STDLH = 0x40700004,	/* Divisor Latch High Register (DLAB = 1) (read/write) */

	//core clock regs
	CCCR = 0x41300000,	/* Core Clock Configuration Register */
	CKEN = 0x41300004,	/* Clock Enable Register */
	OSCC = 0x41300008,	/* Oscillator Configuration Register */

	//ywc,2004-11-30, add LCD control register
	LCCR0 = 0x44000000,
	LCCR1 = 0x44000004,
	LCCR2 = 0x44000008,
	LCCR3 = 0x4400000C,

	FDADR0 = 0x44000200,
	FSADR0 = 0x44000204,
	FIDR0 = 0x44000208,
	LDCMD0 = 0x4400020C,

	FDADR1 = 0x44000210,
	FSADR1 = 0x44000214,
	FIDR1 = 0x44000218,
	LDCMD1 = 0x4400021C
	//ywc,2004-11-30, add LCD control register,end
};


void pxa_io::reset ()
{
	icpr = 0;
	icip = 0;
	icfp = 0;
	icmr = 0;
	iccr = 0;
	iclr = 0;

	rcnr = 0;
	rtar = 0;
	rtsr = 0;
	rttr = 0;

	rt_scale = 0;
	rt_count = 0;

	/*os timer */
	oscr = 0;
	osmr0 = osmr1 = osmr2 = osmr3 = 0;
	ower = 0;
	ossr = 0;
	oier = 0;

	os_scale = 0;


	/*full function uart controller */
	ffrbr = 0;
	ffthr = 0;
	ffier = 0;
	ffiir = 0;
	fffcr = 0;
	fflcr = 0;
	ffmcr = 0;
	fflsr = 0;
	ffmsr = 0;
	ffspr = 0;
	ffisr = 0;
	ffdll = 0;
	ffdlh = 0;

	ff_scale = 0;

	oscc = 0;

	fdadr0 = 0;
	fdadr1 = 0;

	fsadr0 = 0;
	fsadr1 = 0;


	cccr = 0x121;	// 1 0010 0001
	cken = 0x17def;

}

pxa_io::pxa_io (arm_emulator *emu) : arm_io(emu)
{
	reset();
}

pxa_io::~pxa_io ()
{
}

void pxa_io::do_cycle ()
{
	/*RTC*/ 
	if (++rt_scale >= RT_SCALE) {
		rt_scale = 0;
		if (rt_count++ == (rttr & 0xffff)) {
			rt_count = 0;

			if (rcnr++ == rtar) {
				if (rtsr & 0x4) {
					rtsr |= 0x1;
				};
			}
			if (rtsr & 0x8) {
				rtsr |= 0x2;
			}
		}
		if ((rtsr & 0x1) && (rtsr & 0x4))
			icpr |= RTC_ALARM_IRQ;
		if ((rtsr & 0x2) && (rtsr & 0x8))
			icpr |= RTC_HZ_IRQ;
	}

	/*OS timer */
	if (++os_scale >= OS_SCALE) {
		unsigned mask = 0;
		unsigned count;


		os_scale = 0;
		count = oscr++;

		if (count == osmr0)
			mask = 1;
		if (count == osmr1)
			mask |= 0x2;
		if (count == osmr2)
			mask |= 0x4;
		if (count == osmr3) {
			mask |= 0x8;
			if (ower & 1) {
				emu->raise_reset_signal();
			}
		}
		ossr |= mask;
		mask = oier & ossr;
		icpr |= (mask << OS_IRQ_SHF);
	}

	/*FF UART */

	if (++ff_scale >= FF_SCALE) {
		ff_scale = 0;
		if (!(FFUART_IRQ & icpr)) {
			fd_set rset;
			struct timeval tv;

			FD_ZERO (&rset);
			FD_SET (0, &rset);
			tv.tv_sec = 0;
			tv.tv_usec = 0;
			if (select (1, &rset, NULL, NULL, &tv) == 1) {
				
				unsigned char c;
				read (0, &c, 1);

				ffrbr = (int) c;
				ffiir |= 0x4;	//Rx idle
				fflsr |= 0x01;	//Data ready

			}
			if ((ffier & 0x1) && (ffiir & 0x4)) {
				icpr |= FFUART_IRQ;
				ffiir &= ~0x1;
			}
			/*chy 2004-07-21 from luzhetao: produce a IRQ and ox2 should clean by OS driver */
			if (ffier & 0x2) {
				icpr |= FFUART_IRQ;
				ffiir |= 0x2;
				ffiir &= ~0x1;
				fflsr |= 0x60;
			}
		}

	}

	icip = (icmr & icpr) & ~iclr;
	icfp = (icmr & icpr) & iclr;
	if (icip) emu->raise_irq_signal(); else emu->clear_irq_signal();
	if (icfp) emu->raise_fiq_signal(); else emu->clear_fiq_signal();

}

memory_fault_t pxa_io::read_word(target_addr_t addr, word_t *p)
{
	word_t data = 0;

	switch (addr) {
	 /*RTC*/ 
	case RCNR:
		data = rcnr;
		break;
	case RTAR:
		data = rtar;
		break;
	case RTSR:
		data = rtsr;
		break;
	case RTTR:
		data = rttr;
		break;
	/*OS timer */
	case OSCR:
		data = oscr;
		break;
	case OSMR0:
		data = osmr0;
		break;
	case OSMR1:
		data = osmr1;
		break;
	case OSMR2:
		data = osmr2;
		break;
	case OSMR3:
		data = osmr3;
		break;
	case OWER:
		data = ower;
		break;
	case OSSR:
		data = ossr;
		break;
	case OIER:
		data = oier;
		break;

		/*interrupt controler */
	case ICPR:
		data = icpr;
		break;
	case ICIP:
		data = (icmr & icpr) & ~iclr;
		break;
	case ICFP:
		data = (icmr & icpr) & iclr;
		break;
	case ICMR:
		data = icmr;
		break;
	case ICLR:
		data = iclr;
		break;
	/* ffuart control */
	case FFRBR:		
		{
			
			data = ffrbr & 0xff;
			icpr &= ~FFUART_IRQ;
			icip &= ~FFUART_IRQ;
			ffiir &= ~0x4;
			ffiir |= 0x1;
			fflsr &= ~0x1;

		};
		break;
	case FFIER:
		data = ffier;
		break;
	case FFIIR:		//read only
		data = ffiir & 0xcf;
		icpr &= ~FFUART_IRQ;
		icip &= ~FFUART_IRQ;
		break;
	case FFLCR:
		data = fflcr;
		break;
	case FFLSR:		//read only 
		fflsr |= 0x60;
		data = fflsr & 0xff;
		break;
		// core clock 
	case CCCR:
		data = cccr;
		break;
	case CKEN:
		data = cken;
		break;
	case OSCC:
		data = oscc;
		break;

	default:
		data = 0;
		break;	
	};

	*p = data;
	return MEM_NO_FAULT;
};

memory_fault_t pxa_io::write_word(target_addr_t addr, word_t data)
{

	switch (addr) {
	 /*RTC*/ 
	case RCNR:
		rcnr = data;
		break;
	case RTAR:
		rtar = data;
		break;
	case RTSR:
		rtsr |= (data & 0xc);
		rtsr &= ~(data & 0x3);
		break;
	case RTTR:
		rttr = data & 0x3ffffff;
		break;
	/*OS timer */
	case OSCR:
		oscr = data;
		break;
	case OSMR0:
		osmr0 = data;
		break;
	case OSMR1:
		osmr1 = data;
		break;
	case OSMR2:
		osmr2 = data;
		break;
	case OSMR3:
		osmr3 = data;
		break;
	case OWER:
		ower |= data & 0x1;
		break;
	case OSSR:
		ossr &= ~(data & 0xf);
		break;
	case OIER:
		oier = data & 0xf;
		break;

		/*interrupt control */
		//ywc,2004-11-30,for touchscreen use ICPR
	case ICPR:
		icpr = data;
		//printf("\n write ICPR=%x",icpr);
		//printf("\n");
		break;
		//ywc,2004-11-30,for touchscreen use ICPR,end

		//case ICIP:
		//case ICFP:
		/*read only */
		//      break;
	case ICMR:
		icmr = data;
		icpr &= ~data;
		break;
	case ICLR:
		iclr = data;
		break;
	//ffuart control
	case FFTHR:
		{
			unsigned char c = data;
			write (1, &c, 1);
			
			ffiir &= ~0x2;
			ffiir |= 0x1;
			fflsr &= ~0x60;
		}
		break;
	case FFIER:
		ffier = data & 0xff;
		break;
	case FFFCR:		//write only
		fffcr = data & 0xc7;
		break;
	case FFLCR:
		fflcr = data & 0xff;
		break;

	//core clock 
	case CCCR:
		cccr = data & 0x3ff;
		break;
	case CKEN:
		cken = data & 0x17def;
		break;
	case OSCC:
		oscc = data & 0x3;
		break;

	default:
		return MEM_NO_FAULT;
	};
	return MEM_NO_FAULT;
}

⌨️ 快捷键说明

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