📄 arm9rutinasarm.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: ARM9RutinasARM.cpp
Descripcion: Codigo de las rutinas del modo ARM
**************************************************************************************/
#include "ARM9RutinasARM.h"
#include "ARM9Core.h"
#include <stdio.h>
ARM9RutinasARM::ARM9RutinasARM () {
tablaGenerada = 0;
int aux[] = {0x0F0F, 0xF0F0, 0x3333, 0xCCCC, 0x00FF, 0xFF00,
0x5555, 0xAAAA, 0x3030, 0xCFCF, 0xAA55, 0x55AA,
0xA050, 0x5FAF, 0xFFFF, 0xFFFF};
//Genera la tabla precalculada de condiciones
for (int i = 0; i < 16; i++) {
tablaCond[i][0] = (aux[i] & 0x8000) != 0;
tablaCond[i][1] = (aux[i] & 0x4000) != 0;
tablaCond[i][2] = (aux[i] & 0x2000) != 0;
tablaCond[i][3] = (aux[i] & 0x1000) != 0;
tablaCond[i][4] = (aux[i] & 0x0800) != 0;
tablaCond[i][5] = (aux[i] & 0x0400) != 0;
tablaCond[i][6] = (aux[i] & 0x0200) != 0;
tablaCond[i][7] = (aux[i] & 0x0100) != 0;
tablaCond[i][8] = (aux[i] & 0x0080) != 0;
tablaCond[i][9] = (aux[i] & 0x0040) != 0;
tablaCond[i][10] = (aux[i] & 0x0020) != 0;
tablaCond[i][11] = (aux[i] & 0x0010) != 0;
tablaCond[i][12] = (aux[i] & 0x0008) != 0;
tablaCond[i][13] = (aux[i] & 0x0004) != 0;
tablaCond[i][14] = (aux[i] & 0x0002) != 0;
tablaCond[i][15] = (aux[i] & 0x0001) != 0;
}
}
int ARM9RutinasARM::run (ARM9Core *core, ARM9Contexto *contexto, int nCiclos) {
ARM9Instruccion32 instruccion;
void *dir;
this->core = core;
this->contexto = contexto;
int rn, rd, rs, rm, rot, operando1, operando2, acumulador, acumulador2, resultado;
int signo1, signo2;
int shift, tipoShift;
int l, s, c, shifterCarryOut, a, v, esDPI, esLSRO, dirOffset;
uint32 dirEfectiva, dirEfectiva2;
int u, b, w, i, j, esSignedHalfword, listaRegistros, lsmUserMode, lsmCPSR;
int resultado2, esMISR, r, mascara;
int64 var1_64, var2_64; uint64 uvar1_64, uvar2_64;
/*-------------------------------------------------------------------------*/
/* Tabla de saltos
/*-------------------------------------------------------------------------*/
#include "ARM9TablaARM.h"
/*-------------------------------------------------------------------------*/
/* Lectura de la siguiente instrucci髇
/*-------------------------------------------------------------------------*/
LecturaInstruccion:
//Antes de leer, comprobamos el numero de ciclos restantes
if ((nCiclos <= 0) || (core->getExcepcionActiva() != EXCEP_NONE))
return nCiclos;
//Lee la siguiente instruccion
instruccion.u_word = core->readInstruccion (contexto->PC->u_word);
contexto->PC->u_word += 0x4; //+4 bytes
if (core->getExcepcionActiva() != EXCEP_NONE)
return nCiclos;
//Obtenemos la direccion de la subrutina a partir del codigo de la
//tabla de saltos (bits 27-20)
dir = tablaSaltos[instruccion.comunes.codigoTabla][instruccion.comunes.codigoTabla2];
//Salta a la subrutina
__asm jmp dir
/*-------------------------------------------------------------------------*/
/* Rutina ADD (DP)
/*-------------------------------------------------------------------------*/
RUT_add:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT
}
//ADD
__asm {
add eax, ebx ;suma
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
GETFLAGS
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina ADC (DP)
/*-------------------------------------------------------------------------*/
RUT_adc:
//Comprueba el codigo de condicion
COMPROBAR_COND
c = contexto->flags.c;
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT
}
//ADC
__asm {
add eax, ebx ;suma
add eax, c
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
GETFLAGS
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina SUB (DP)
/*-------------------------------------------------------------------------*/
RUT_sub:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT
}
//SUB
__asm {
mov operando2, ebx ;preserva para el flag de carry
neg ebx
add eax, ebx ;resta
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
signo2 = signo2 ^ 0x80000000;
GETFLAGS_SUB
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina SBC (DP)
/*-------------------------------------------------------------------------*/
RUT_sbc:
//Comprueba el codigo de condicion
COMPROBAR_COND
c = contexto->flags.c;
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT
}
//SBC
__asm {
add eax, c
sub eax, 1
mov operando1, eax ;preserva para el flag de carry
mov operando2, ebx
neg ebx
add eax, ebx ;resta
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
signo2 = signo2 ^ 0x80000000;
GETFLAGS_SUB
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina RSB (DP)
/*-------------------------------------------------------------------------*/
RUT_rsb:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT
}
//RSB
__asm {
mov operando1, ebx ;preserva para el flag de carry
mov operando2, eax
neg eax
add ebx, eax ;resta
pushf ;guarda los flags en la pila
mov resultado, ebx ;guarda el resultado
}
//Guarda los flags
signo1 = signo1 ^ 0x80000000;
GETFLAGS_SUB
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina RSC (DP)
/*-------------------------------------------------------------------------*/
RUT_rsc:
//Comprueba el codigo de condicion
COMPROBAR_COND
c = contexto->flags.c;
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT
}
//RSC
__asm {
add ebx, c
sub ebx, 1
mov operando2, eax ;preserva para el flag de carry
mov operando1, ebx
neg eax
add ebx, eax ;resta
pushf ;guarda los flags en la pila
mov resultado, ebx ;guarda el resultado
}
//Guarda los flags
signo1 = signo1 ^ 0x80000000;
GETFLAGS_SUB
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina MOV (DP)
/*-------------------------------------------------------------------------*/
RUT_mov:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT_CARRY
}
//MOV
__asm {
or ebx, 0 ;OR 0 para obtener los flags (el x86 no lo hace con move)
pushf ;guarda los flags en la pila
mov resultado, ebx ;guarda el resultado
}
//Guarda los flags
GETFLAGS_SHIFTER
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina MVN (DP)
/*-------------------------------------------------------------------------*/
RUT_mvn:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT_CARRY
}
//MVN
__asm {
mov eax, 0FFFFFFFFh
xor eax, ebx ;XOR con eax para obtener los flags (el x86 no lo hace con move)
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
GETFLAGS_SHIFTER
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina AND (DP)
/*-------------------------------------------------------------------------*/
RUT_and:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT_CARRY
}
//AND
__asm {
and eax, ebx ;and
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
GETFLAGS_SHIFTER
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina EOR (DP)
/*-------------------------------------------------------------------------*/
RUT_eor:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT_CARRY
}
//EOR
__asm {
xor eax, ebx ;or exclusiva
pushf ;guarda los flags en la pila
mov resultado, eax ;guarda el resultado
}
//Guarda los flags
GETFLAGS_SHIFTER
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina ORR (DP)
/*-------------------------------------------------------------------------*/
RUT_orr:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_DP
if (esDPI) {
//Rota (expande) el operando inmediato
ROTATE_DPI
}else{
//Desplaza el operando 2
SHIFT_CARRY
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -