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

📄 arm9core.cpp

📁 ARM9Core v0.4, 在x86 Win32 下模拟仿真ARM9 微处理器的Library.
💻 CPP
字号:
/*
    ARM9Core
    Copyright (C) 2007 Alberto Huerta Aranda,
	Sergio Hidalgo Serrano, Daniel Sa駏do Vacas

    This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 3 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
	Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
	License along with this library. If not, see <http://www.gnu.org/licenses/>

*/


/**************************************************************************************

  Archivo: ARM9Core.cpp

  Descripcion:

**************************************************************************************/

#include "ARM9Core.h"
#include <stdio.h>


//Constructor
ARM9Core::ARM9Core(){

	numeroContextos = 1;

	contextos = new ARM9Contexto;

	contextoActual = contextos;

	memoria = NULL;

	funcionExterna = NULL;

	excepcionActiva = EXCEP_NONE;
	excepHandler[0] = NULL;
	excepHandler[1] = NULL;
	excepHandler[2] = NULL;
	excepHandler[3] = NULL;
	excepHandler[4] = NULL;
	excepHandler[5] = NULL;

	for (int i = 0; i < 16; i++) {
		listaCoproDP[i] = NULL;
		listaCoproLS[i] = NULL;
		listaCoproRT[i] = NULL;
	}

	running = false;

	calcularFrecuenciaX86();
}


//Constructor
ARM9Core::ARM9Core(int numeroCores){

	numeroContextos = numeroCores;

	contextos = new ARM9Contexto[numeroCores];

	contextoActual = contextos;

	memoria = NULL;

	funcionExterna = NULL;

	excepcionActiva = EXCEP_NONE;
	excepHandler[0] = NULL;
	excepHandler[1] = NULL;
	excepHandler[2] = NULL;
	excepHandler[3] = NULL;
	excepHandler[4] = NULL;
	excepHandler[5] = NULL;

	for (int i = 0; i < 16; i++) {
		listaCoproDP[i] = NULL;
		listaCoproLS[i] = NULL;
		listaCoproRT[i] = NULL;
	}

	running = false;

	calcularFrecuenciaX86();

}


ARM9Core::~ARM9Core(){

	delete[] contextos;
	delete[] memoria;

	running = false;

	contextoActual = NULL;

}
	

//Reset
void ARM9Core::reset(){

	running = false;

	excepcionActiva = EXCEP_NONE;
	contextoActual = contextos;

	//Resetea contextos
	for (int i = 0; i < numeroContextos; i++)
		contextos[i].reset();
}


//Run
void ARM9Core::run(int nCiclos){

	double tiempo, tiempoCiclo, tiempoEstimado;
	int i, ciclosEjecutados;
	int *ciclos = new int[numeroContextos];

	for (i = 0; i < numeroContextos; i++)
		ciclos[i] = nCiclos;

	//Tiempo estimado en ejecutar un ciclo
	tiempoCiclo = (1.0 / frecuenciaARM);

	contextoActual = contextos;
	running = true;

	if (memoria == NULL)
		return;
	
	while (running) {
		tiempoInicio = calcularTiempoX86();
		ciclosEjecutados = nCiclos * numeroContextos;
	
		//Ejecuta un slice
		for (i = 0; i < numeroContextos; i++) {
			while ((ciclos[i] > 0) && (running)) {
				ciclos[i] = rutinasARM.run (this, contextoActual, ciclos[i]);
				tratarExcepciones();
			}

			contextoActual++;
			ciclosEjecutados-=ciclos[i];
		}

		tiempo = calcularTiempoX86() - tiempoInicio;
		tiempoEstimado = tiempoCiclo * (double)(ciclosEjecutados);

		//Sincronizamos
		while (tiempo < tiempoEstimado) {
			Sleep(0);
			tiempo = calcularTiempoX86() - tiempoInicio;
		}
		
		
		for (i = 0; i < numeroContextos; i++)
			ciclos[i] = ciclos[i] + nCiclos;


		contextoActual = contextos;
		funcionExterna();

	}

	delete []ciclos;
}


//Step
void ARM9Core::step(){

	running = true;

	if (memoria == NULL)
		return;

	contextoActual = contextos;

	for (int i = 0; (i < numeroContextos) && running; i++) {
		rutinasARM.run (this, contextoActual, 1);
		tratarExcepciones();

		contextoActual++;
	}

	contextoActual = contextos;
	funcionExterna();

}




//Stop
void ARM9Core::stop(){

	running = false;

}


void ARM9Core::marcarExcepcion (ARM9Exception excepcion, int param) {

	if (excepcion > excepcionActiva) {
		excepcionActiva = excepcion;
		paramExcepcion = param;
	}

}


void ARM9Core::tratarExcepciones () {
	bool enable = true;
	ARM9Mode nuevoModo, modo;
	uint32 nuevaDir;
	uint32 codigoModo;

	modo = contextoActual->modo;

	switch (excepcionActiva) {
	case EXCEP_RESET:
		reset();
		return;
		break;

	case EXCEP_UNDEFINED:
		nuevoModo = UNDEF_MODE;
		codigoModo = 0x1B;
		nuevaDir = 0x4;
		
		break;

	case EXCEP_SWI:
		nuevoModo = SVC_MODE;
		codigoModo = 0x13;
		nuevaDir = 0x8;
		
		break;

	case EXCEP_PREFETCH_ABORT:
		nuevoModo = ABORT_MODE;
		codigoModo = 0x17;
		nuevaDir = 0xC;
		
		break;

	case EXCEP_DATA_ABORT:
		nuevoModo = ABORT_MODE;
		codigoModo = 0x17;
		nuevaDir = 0x10;
		
		break;

	case EXCEP_IRQ:
		nuevoModo = IRQ_MODE;
		codigoModo = 0x12;
		nuevaDir = 0x18;
		if (contextoActual->irqDis != 0)
			enable = false;
		break;

	case EXCEP_FIQ:
		nuevoModo = FIQ_MODE;
		codigoModo = 0x11;
		nuevaDir = 0x1C;
		if (contextoActual->fiqDis != 0)
			enable = false;
		break;

	default:
		enable = false;
	}


	if (enable && excepHandler[excepcionActiva-1] == NULL) {

		//Guarda el PC en r14 del nuevo modo
		if ((excepcionActiva == EXCEP_DATA_ABORT) || (excepcionActiva == EXCEP_IRQ) ||
			(excepcionActiva == EXCEP_FIQ)) {
			contextoActual->tablaPunteros[nuevoModo][1] = contextoActual->bancoRegistros[15];
			contextoActual->tablaPunteros[nuevoModo][1].u_word += 0x4;
		}else
			contextoActual->tablaPunteros[nuevoModo][1] = contextoActual->bancoRegistros[15];

		//Guarda el CPSR en SPSR del nuevo modo
		uint32 cpsr = contextoActual->leerCPSR(); 
		contextoActual->SPSR[nuevoModo - 1].u_word = cpsr;

		//Cambia al nuevo modo supervisor y desactiva las IRQs
		cpsr = (cpsr & 0xFFFFFF60) | codigoModo;
		//Si es FIQ, se desactivan tambien
		if (excepcionActiva == EXCEP_FIQ)
			cpsr = (cpsr & 0xFFFFFFBF);

		contextoActual->escribirCPSR(cpsr);

		//Salta a la nueva direccion
		contextoActual->PC->u_word = nuevaDir;


	} else if (enable) {
		excepHandler[excepcionActiva-1](paramExcepcion);
	}

	excepcionActiva = EXCEP_NONE;
}


bool ARM9Core::addMemoria (int nRegiones, ARM9MemRegion *lista) {
	if (memoria != NULL)
		delete[] memoria;

	this->nRegiones = nRegiones;

	memoria = new ARM9MemRegion[nRegiones];
	for (int i = 0; i < nRegiones; i++) {
		memoria[i] = lista[i];
	}

	for (i = 0; i < nRegiones; i++) {
		for (int j = i+1; j < nRegiones; j++) {
			if (((memoria[i].inferior <= memoria[j].inferior) && 
			   (memoria[i].superior >= memoria[j].inferior)) ||
			   ((memoria[i].inferior <= memoria[j].superior) &&
			   (memoria[i].superior >= memoria[j].superior))) {

				return false;
			}
		}
	}

	return true;
}


uint32 ARM9Core::readInstruccion(uint32 direccion) {
	
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & ((contextoActual->modo == USER_MODE)?USR_READ_PERM:PRIV_READ_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerRead32 != NULL) {
					return ((readHandler32)(r->handlerRead32))(direccion - r->inferior);

				//Si no, se usa el buffer
				}else {
					return *((uint32*)(r->buffer + direccion - r->inferior));
				}

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_PREFETCH_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}

	marcarExcepcion (EXCEP_PREFETCH_ABORT, direccion);
	return 0;
}


uint32 ARM9Core::readMemoriaWord(uint32 direccion) {
	
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & ((contextoActual->modo == USER_MODE)?USR_READ_PERM:PRIV_READ_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerRead32 != NULL) {
					return ((readHandler32)(r->handlerRead32))(direccion - r->inferior);

				//Si no, se usa el buffer
				}else {
					return *((uint32*)(r->buffer + direccion - r->inferior));
				}

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_DATA_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}

	marcarExcepcion (EXCEP_DATA_ABORT, direccion);
	return 0;
}


uint8 ARM9Core::readMemoriaByte(uint32 direccion) {
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & (contextoActual->modo == USER_MODE?USR_READ_PERM:PRIV_READ_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerRead8 != NULL) {
					return ((readHandler8)(r->handlerRead8))(direccion - r->inferior);

				//Si no, se usa el buffer
				}else
					return r->buffer[direccion - r->inferior];

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_DATA_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}

	marcarExcepcion (EXCEP_DATA_ABORT, direccion);
	return 0;
}


uint16 ARM9Core::readMemoriaHalfword(uint32 direccion) {
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & (contextoActual->modo == USER_MODE?USR_READ_PERM:PRIV_READ_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerRead16 != NULL) {
					return ((readHandler16)(r->handlerRead16))(direccion - r->inferior);

				//Si no, se usa el buffer
				}else
					return *((uint16*)(r->buffer + direccion - r->inferior));

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_DATA_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}

	marcarExcepcion (EXCEP_DATA_ABORT, direccion);
	return 0;
}
	

void ARM9Core::writeMemoriaWord(uint32 datos, uint32 direccion){
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & (contextoActual->modo == USER_MODE?USR_WRITE_PERM:PRIV_WRITE_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerWrite32 != NULL) {
					((writeHandler32)(r->handlerWrite32))(datos, direccion - r->inferior);
					return;

				//Si no, se usa el buffer
				}else {
					*((uint32*)(&(r->buffer[direccion - r->inferior]))) = datos;
					return;
				}

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_DATA_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}

}


void ARM9Core::writeMemoriaByte(uint8 datos, uint32 direccion){
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & (contextoActual->modo == USER_MODE?USR_WRITE_PERM:PRIV_WRITE_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerWrite8 != NULL) {
					((writeHandler8)(r->handlerWrite8))(datos, direccion - r->inferior);
					return;

				//Si no, se usa el buffer
				}else {
					r->buffer[direccion - r->inferior] = datos;
					return;
				}

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_DATA_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}

}


void ARM9Core::writeMemoriaHalfword(uint16 datos, uint32 direccion){
	ARM9MemRegion *r;
	
	int i=0;
	r = &memoria[i++];
	
	while (i <= nRegiones) {

		//Region correcta
		if ((direccion >= r->inferior) && (direccion <= r->superior)) {
			
			//Comprobacion de permisos
			if (r->permisos & (contextoActual->modo == USER_MODE?USR_WRITE_PERM:PRIV_WRITE_PERM)) {

				//Si hay handler definido, se invoca
				if (r->handlerWrite16 != NULL) {
					((writeHandler16)(r->handlerWrite16))(datos, direccion - r->inferior);
					return;

				//Si no, se usa el buffer
				}else {
					*((uint16*)(&(r->buffer[direccion - r->inferior]))) = datos;
					return;
				}

			} else {

				//Permisos incorrectos, lanzar abort
				marcarExcepcion (EXCEP_DATA_ABORT, direccion);
			}
		}

		r = &memoria[i++];
	}


}

void ARM9Core::setFrecuenciaARM (double f) {
	frecuenciaARM = f*1000000.0;
}


void ARM9Core::calcularFrecuenciaX86() {

	//Obtenemos la frecuencia
	LARGE_INTEGER f;
	QueryPerformanceFrequency (&f);
	frecuenciaX86 = f.QuadPart;
}


double ARM9Core::calcularTiempoX86 () {

	LARGE_INTEGER t;

	QueryPerformanceCounter (&t);
	return t.QuadPart / (double)frecuenciaX86;
}


//getters y setters
void ARM9Core::setCores(int numeroContextos){

	stop();

	delete[] contextos;
	
	this->numeroContextos = numeroContextos;

	contextos = new ARM9Contexto[numeroContextos];

	contextoActual = contextos;

	reset();
}

void ARM9Core::setExcepHandler (ARM9Exception ex, void (*handler)(int n)) {

	excepHandler[ex-1] = handler;
}

void (*ARM9Core::getExcepHandler(ARM9Exception ex))(int n) {

	return excepHandler[ex-1];
}

void ARM9Core::setFuncionExterna (void (*func)(void)) {
	funcionExterna = func;
}

void (*ARM9Core::getFuncionExterna())(void) {
	return funcionExterna;
}

void ARM9Core::setCopro (int cpn, coproDP fdp, coproLS fls, coproRT frt) {
	if (cpn >= 0 && cpn < 16) {
		listaCoproDP[cpn] = fdp;
		listaCoproLS[cpn] = fls;
		listaCoproRT[cpn] = frt;
	}
}


coproDP ARM9Core::getCoproDP (int cpn) {
	return listaCoproDP[cpn];
}


coproLS ARM9Core::getCoproLS (int cpn) {
	return listaCoproLS[cpn];
}


coproRT ARM9Core::getCoproRT (int cpn) {
	return listaCoproRT[cpn];
}


bool ARM9Core::getRunning(){
	
	return running;
}


ARM9Contexto *ARM9Core::getContexto(int num) {

	return &(contextos[num]);

}

⌨️ 快捷键说明

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