📄 arm9core.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 + -