📄 arm9macrosarm.h
字号:
/*
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/>
*/
#ifndef ARM9MacrosARMH
#define ARM9MacrosARMH
/**************************************************************************************
Archivo: ARM9MacrosARM.h
Descripcion: Codigo de las macros para las rutinas del modo ARM
**************************************************************************************/
//---MACRO COMPROBAR CODIGO CONDICION---
#define COMPROBAR_COND \
{\
/*Comprueba el codigo de condicion en la tabla*/ \
if (!tablaCond[instruccion.comunes.cond][contexto->condFlags]){ \
/*Salta a la siguiente instruccion*/ \
nCiclos--; \
goto LecturaInstruccion; \
} \
}
//--------------------------
//---MACRO GETOPS DATA PROCESSING---
#define GETOPS_DP \
{\
/*Extraemos los campos*/ \
rn = instruccion.DPI.Rn; \
rd = instruccion.DPI.Rd; \
/*coincide con rs*/ \
rot = instruccion.DPI.rotate; \
operando1 = contexto->bancoRegistros[rn].u_word; \
\
/*Comportamiento del pipeline segmentado*/ \
if (rn == 15) { \
nCiclos-=2; \
operando1 += 4; \
} \
\
signo1 = operando1 & 0x80000000; \
\
operando2 = contexto->bancoRegistros[instruccion.DPRS.Rm].u_word; \
\
/*Comportamiento del pipeline segmentado*/ \
if (instruccion.DPRS.Rm == 15) { \
nCiclos-=2; \
operando2 += 4; \
} \
\
shift = instruccion.DPRS.bit4==1 ? contexto->bancoRegistros[rot].u_word \
: instruccion.DPIS.shifta; \
tipoShift = instruccion.DPRS.shift; \
s = instruccion.DPI.S; \
\
esDPI = (instruccion.u_word & 0x02000000)!=0; \
}
//--------------------------
//----MACRO ROTATE DPI---
#define ROTATE_DPI \
{\
shifterCarryOut = contexto->flags.c; \
{ \
/*edx <- instruccion*/ \
__asm mov edx, instruccion.u_word \
\
__asm mov ebx, edx \
/*operando inmediato*/ \
__asm and ebx, 000000FFh \
__asm mov ecx, rot \
} \
if (rot != 0) { \
/*rotate << 1*/ \
__asm sal ecx, 1 \
/*rota cx veces a la derecha*/ \
__asm ror ebx, cl \
/*obtiene el carry y el signo*/ \
__asm mov eax, ebx \
__asm and eax, 80000000h \
__asm mov shifterCarryOut, eax \
__asm mov signo2, eax \
} else { \
/*obtiene el carry y el signo*/ \
__asm mov eax, ebx \
__asm and eax, 80000000h \
__asm mov signo2, eax \
} \
\
/*eax <- valor del registro rn*/ \
__asm mov eax, operando1 \
}
//--------------------------
//--------MACRO SHIFT-------
#define SHIFT \
{\
/*Si shift = 0 y tipoShift = 0, no hay desplazamiento*/ \
if (instruccion.u_word & 0x00000FE0) { \
nCiclos--; \
switch (tipoShift){ \
/*LSL*/ \
case 0: \
if (shift > 31 && shift < 256) { \
__asm mov ebx, 0 \
}else{\
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm shl ebx, cl \
}\
break; \
\
/*LSR*/ \
case 1: \
if (shift > 31 && shift < 256) { \
__asm mov ebx, 0 \
}else{\
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm shr ebx, cl \
}\
break; \
\
/*ASR*/ \
case 2: \
if (shift > 31 && shift < 256 && operando2 < 0) { \
__asm mov ebx, 0xFFFFFFFF \
}else if (shift > 31 && shift < 256){ \
__asm mov ebx, 0 \
}else{\
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm sar ebx, cl \
}\
break; \
\
/*ROR o RRX*/ \
case 3: \
if (shift != 0) { \
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm ror ebx, cl \
}else{ \
if (contexto->flags.c) { \
__asm stc \
} else { \
__asm clc \
}\
{\
__asm mov ebx, operando2 \
__asm mov ecx, eax \
__asm rcr ebx, 1 \
}\
} \
break; \
} \
} else { \
__asm mov ebx, operando2 \
}\
{\
/*obtiene el signo final*/ \
__asm mov eax, ebx \
__asm and eax, 80000000h \
__asm mov signo2, eax \
\
/*eax <- valor del registro rn*/ \
__asm mov eax, operando1 \
}\
}
//--------------------------
//--------MACRO SHIFT_CARRY-------
#define SHIFT_CARRY \
{\
shifterCarryOut = contexto->flags.c; \
\
/*Si shift = 0 y tipoShift = 0, no hay desplazamiento*/ \
if (instruccion.u_word & 0x00000FE0) { \
nCiclos--; \
switch (tipoShift){ \
/*LSL*/ \
case 0: \
if (shift > 32 && shift < 256) { \
__asm mov ebx, 0 \
__asm mov shifterCarryOut, 0 \
}else if (shift == 32) { \
__asm mov ebx, operando2 \
__asm and ebx, 1 \
__asm mov shifterCarryOut, ebx \
__asm mov ebx, 0 \
}else if (shift == 0) { \
__asm mov ebx, operando2 \
}else{\
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm shl ebx, cl \
__asm mov eax, 0 \
__asm adc eax, 0 \
__asm mov shifterCarryOut, eax \
}\
break; \
\
/*LSR*/ \
case 1: \
if (shift > 32 && shift < 256) { \
__asm mov ebx, 0 \
__asm mov shifterCarryOut, 0 \
}else if (shift == 32) { \
__asm mov ebx, operando2 \
__asm and ebx, 80000000h \
__asm mov shifterCarryOut, ebx \
__asm mov ebx, 0 \
}else if (shift == 0) { \
__asm mov ebx, operando2 \
}else{\
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm shr ebx, cl \
__asm mov eax, 0 \
__asm adc eax, 0 \
__asm mov shifterCarryOut, eax \
}\
break; \
\
/*ASR*/ \
case 2: \
if (shift > 31 && shift < 256 && operando2 < 0) { \
__asm mov ebx, 0xFFFFFFFF \
__asm mov shifterCarryOut, 1 \
}else if (shift > 31 && shift < 256){ \
__asm mov ebx, 0 \
__asm mov shifterCarryOut, 0 \
}else if (shift == 0) { \
__asm mov ebx, operando2 \
}else{\
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm sar ebx, cl \
__asm mov eax, 0 \
__asm adc eax, 0 \
__asm mov shifterCarryOut, eax \
}\
break; \
\
/*ROR o RRX*/ \
case 3: \
if (shift != 0) { \
__asm mov ebx, operando2 \
__asm mov ecx, shift \
__asm ror ebx, cl \
__asm mov eax, 0 \
__asm adc eax, 0 \
__asm mov shifterCarryOut, eax \
}else{ \
if (contexto->flags.c) { \
__asm stc \
} else { \
__asm clc \
}\
{\
__asm mov ebx, operando2 \
__asm mov ecx, eax \
__asm rcr ebx, 1 \
__asm mov eax, 0 \
__asm adc eax, 0 \
__asm mov shifterCarryOut, eax \
}\
} \
break; \
} \
__asm clc \
} else { \
__asm mov ebx, operando2 \
} \
{\
/*obtiene el signo final*/ \
__asm mov eax, ebx \
__asm and eax, 80000000h \
__asm mov signo2, eax \
\
/*eax <- valor del registro rn*/ \
__asm mov eax, operando1 \
}\
}
//--------------------------
//----MACROS FLAGS---
#define GETFLAGS \
if (s == 1) { \
{ \
/*saca los flags en ax*/ \
__asm pop ax \
__asm mov bh, al \
/*bit 7 (SF) y 6 (ZF)*/ \
__asm and bh, 0C0h \
/*lo pone en el bit 3 y 2*/ \
__asm sar bh, 4h \
\
__asm mov ch, al \
/*bit 0 (CF)*/ \
__asm and ch, 1h \
/*lo pone en el bit 1*/ \
__asm sal ch, 1h \
/*lo guarda en bh*/ \
__asm or bh, ch \
\
/*bit 11 (V)*/ \
__asm and ah, 08h \
/*lo pone en el bit 0*/ \
__asm sar ah, 3h \
/*lo guarda en bh*/ \
__asm or bh, ah \
\
__asm mov eax, contexto \
/*guarda los flags en el campo de contexto (172 = offset en bytes)*/ \
__asm mov [eax + 172], bh \
} \
\
if (rd==15){ \
contexto->escribirCPSR(contexto->SPSR[contexto->modo-1].u_word); \
} \
\
} else {\
__asm pop ax \
}
//--------------------------
//----MACRO FLAGS PARA NO ARITMETICAS (No hay carry)---
#define GETFLAGS_SHIFTER \
if (s == 1) { \
{ \
/*saca los flags en ax*/ \
__asm pop ax \
__asm mov bh, al \
/*bit 7 (SF) y 6 (ZF)*/ \
__asm and bh, 0C0h \
/*lo pone en el bit 3 y 2*/ \
__asm sar bh, 4h \
\
/*bit 11 (V)*/ \
__asm and ah, 08h \
/*lo pone en el bit 0*/ \
__asm sar ah, 3h \
/*lo guarda en bh*/ \
__asm or bh, ah \
\
__asm mov eax, contexto \
/*guarda los flags en el campo de contexto (172 = offset en bytes)*/ \
__asm mov [eax + 172], bh \
} \
\
contexto->flags.c = shifterCarryOut!=0?1:0; \
if (rd==15){ \
contexto->escribirCPSR(contexto->SPSR[contexto->modo-1].u_word); \
} \
\
} else {\
__asm pop ax \
}
//--------------------------
//----MACRO FLAGS PARA RESTAS (Correccion Overflow)---
#define GETFLAGS_SUB \
if (s == 1) { \
{ \
/*saca los flags en ax*/ \
__asm pop ax \
__asm mov bh, al \
/*bit 7 (SF) y 6 (ZF)*/ \
__asm and bh, 0C0h \
/*lo pone en el bit 3 y 2*/ \
__asm sar bh, 4h \
\
__asm mov ch, al \
/*bit 0 (CF)*/ \
__asm and ch, 1h \
/*lo pone en el bit 1*/ \
__asm sal ch, 1h \
/*lo guarda en bh*/ \
__asm or bh, ch \
\
__asm mov eax, contexto \
/*guarda los flags en el campo de contexto (172 = offset en bytes)*/ \
__asm mov [eax + 172], bh \
\
} \
/*calcula el flag de overflow (1 si el signo es distinto del correcto)*/ \
if ((signo1 == signo2) && (((signo1 == 0) && (contexto->flags.n != 0)) || \
((signo1 != 0) && (contexto->flags.n == 0)))) { \
contexto->flags.v = 1;\
} else{ \
contexto->flags.v = 0;\
} \
if ((unsigned int)operando2 <= (unsigned int)operando1) { \
contexto->flags.c = 1;\
} else { \
contexto->flags.c = 0;\
} \
\
if (rd==15){ \
contexto->escribirCPSR(contexto->SPSR[contexto->modo-1].u_word); \
} \
\
\
} else {\
__asm pop ax \
}
//--------------------------
//---MACROS GETOPS LOAD STORE---
#define GETOPS_LS \
{\
/*Extraemos los campos*/ \
rn = instruccion.LSRO.Rn; \
rd = instruccion.LSRO.Rd; \
b = instruccion.LSRO.B; \
w = instruccion.LSRO.W; \
u = instruccion.LSRO.U; \
\
operando1 = contexto->bancoRegistros[rn].u_word; \
/*Comportamiento del pipeline segmentado*/ \
if (rn == 15) \
operando1 += 4; \
\
/*Desplazamiento inmediato (LSIO y extras)*/ \
dirOffset = instruccion.LSIO.inmediate; \
\
/*Desplazamiento con registro (LSRO y extras)*/ \
operando2 = contexto->bancoRegistros[instruccion.LSRO.Rm].u_word; \
\
}
#define GETOPS_LS_SHIFT \
{\
GETOPS_LS \
\
/*Desplazamiento (shift) para las LSRO*/\
shift = instruccion.LSRO.shifta; \
tipoShift = instruccion.LSRO.shift; \
\
/*Distingue entre ambos (LSIO, LSRO)*/ \
esLSRO = (instruccion.u_word & 0x02000000)!=0; \
\
/*Si el offset es un registro*/ \
if (esLSRO) { \
/*Desplaza el operando 2*/ \
{ \
__asm mov ebx, operando2 \
} \
SHIFT \
{ \
__asm mov dirOffset, ebx \
} \
} \
}
#define GETOPS_LS_EXTRAS \
{\
GETOPS_LS \
\
/*El bit 6 distingue entre signed y unsigned*/ \
/*El bit 5 distingue entre byte y halfword*/ \
esSignedHalfword = instruccion.LSRO.shift; \
\
/*El bit B es tambien el bit 22, que distingue entre*/ \
/*instrucciones con desp. inmediato (1) o registro (0)*/ \
\
if (b) { \
/*"Montamos" el valor inmediato, que viene separado*/ \
dirOffset = ((dirOffset>>8)<<4) + (dirOffset & 0xF); \
}else{ \
/*En estas instrucciones no se hace shift al registro*/ \
dirOffset = operando2; \
} \
\
}
#define GETOPS_LSM \
{\
GETOPS_LS \
\
/*El offset es siempre de 4 bytes (1 word)*/ \
dirOffset = 4; \
\
/*El bit i a 1 indica que se usa el registro i*/ \
listaRegistros = instruccion.LSM.Rlist; \
\
/*U=1 (Suma), U=0 (Resta)*/\
if (u==0) { \
dirOffset = -dirOffset; \
} \
\
dirEfectiva = operando1 & 0xFFFFFFFC; \
\
/*Si PC est
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -