📄 arm9rutinasarm.cpp
字号:
//ORR
__asm {
or eax, ebx ;or
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 BIC (DP)
/*-------------------------------------------------------------------------*/
RUT_bic:
//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
}
//BIC
__asm {
not ebx ;NOT Op2
and eax, ebx ;Rn and NOT Op2
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 TST (DP)
/*-------------------------------------------------------------------------*/
RUT_tst:
//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
}
//TST
__asm {
and eax, ebx ;and
pushf ;guarda los flags en la pila
}
//Guarda los flags
GETFLAGS_SHIFTER
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina TEQ (DP)
/*-------------------------------------------------------------------------*/
RUT_teq:
//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
}
//TEQ
__asm {
xor eax, ebx ;or exlusiva
pushf ;guarda los flags en la pila
}
//Guarda los flags
GETFLAGS_SHIFTER
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina CMP (DP)
/*-------------------------------------------------------------------------*/
RUT_cmp:
//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
}
//CMP
__asm {
mov operando2, ebx ;preserva para el flag de carry
neg ebx
add eax, ebx ;resta
pushf ;guarda los flags en la pila
}
//Guarda los flags
signo2 = signo2 ^ 0x80000000;
GETFLAGS_SUB
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina CMN (DP)
/*-------------------------------------------------------------------------*/
RUT_cmn:
//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
}
//CMN
__asm {
add eax, ebx ;suma
pushf ;guarda los flags en la pila
}
//Guarda los flags
GETFLAGS
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutinas Branch y Branch with link (BBL)
/*-------------------------------------------------------------------------*/
RUT_bbl:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
//Link
l = instruccion.BBL.L;
//Link: Guarda en el registro link la direccion de la instruccion siguiente
if (l)
contexto->bancoRegistros[14].u_word = contexto->PC->u_word;
//El valor del PC al ejecutarse la instruccion de salto es la direccion
//de la instruccion siguiente a la siguiente (por el pipeline segmentado)
//Para emularlo sumamos 4 al calculo de direccion final del salto
contexto->PC->u_word = contexto->PC->u_word + 4 + (instruccion.BBL.offset<<2);
nCiclos-=3;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina Branch and Exchange (BX)
/*-------------------------------------------------------------------------*/
RUT_bx:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
rm = instruccion.BX.Rm;
contexto->PC->u_word = contexto->bancoRegistros[rm].u_word;
nCiclos-=3;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina LDR pre-index (Load single word and unsigned byte)
/*-------------------------------------------------------------------------*/
RUT_ldr_pre:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_SHIFT
//Calcular la dir. efectiva (y guardarla, si eso)
PREINDEX
if (b) {
resultado = unsigned int (core->readMemoriaByte(dirEfectiva));
} else {
dirEfectiva2 = dirEfectiva & 0xFFFFFFFC;
resultado = core->readMemoriaWord(dirEfectiva2);
//Ajusta la palabra cargada
rot = ((dirEfectiva2>>2) - (dirEfectiva>>2));
__asm {
mov eax, resultado
mov ecx, rot
ror eax, cl
mov resultado, eax
}
}
CHK_ABORT
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos-=2;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina STR pre-index (Store single word and unsigned byte)
/*-------------------------------------------------------------------------*/
RUT_str_pre:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_SHIFT
//Calcular la dir. efectiva (y guardarla, si eso)
PREINDEX
if (b) {
core->writeMemoriaByte(contexto->bancoRegistros[rd].u_byte, dirEfectiva);
} else {
dirEfectiva2 = dirEfectiva & 0xFFFFFFFC;
core->writeMemoriaWord(contexto->bancoRegistros[rd].u_word, dirEfectiva2);
}
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina LDR post-index (Load single word and unsigned byte)
/*-------------------------------------------------------------------------*/
RUT_ldr_post:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_SHIFT
if (b) {
resultado = unsigned int (core->readMemoriaByte(operando1));
} else {
dirEfectiva = operando1 & 0xFFFFFFFC;
resultado = core->readMemoriaWord(dirEfectiva);
//Ajusta la palabra cargada
rot = ((dirEfectiva>>2) - (operando1>>2));
__asm {
mov eax, resultado
mov ecx, rot
ror eax, cl
mov resultado, eax
}
}
//Calcular la dir. efectiva (y guardarla)
POSTINDEX
CHK_ABORT
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos-=2;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina STR post-index (Store single word and unsigned byte)
/*-------------------------------------------------------------------------*/
RUT_str_post:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_SHIFT
if (b) {
core->writeMemoriaByte(contexto->bancoRegistros[rd].u_byte, operando1);
} else {
dirEfectiva = operando1 & 0xFFFFFFFC;
core->writeMemoriaWord(contexto->bancoRegistros[rd].u_word, dirEfectiva);
}
//Calcular la dir. efectiva (y guardarla)
POSTINDEX
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina LDR HW/B pre-index (Load half-word / signed byte)
/*-------------------------------------------------------------------------*/
RUT_ldr_hw_pre:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_EXTRAS
//Calcular la dir. efectiva (y guardarla, si eso)
PREINDEX
switch (esSignedHalfword) {
case 2:
resultado = (int8)(core->readMemoriaByte(dirEfectiva));
break;
case 3:
resultado = (int16)(core->readMemoriaHalfword(dirEfectiva));
break;
default:
resultado = unsigned int (core->readMemoriaHalfword(dirEfectiva));
}
CHK_ABORT
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos-=2;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina STR HW pre-index (Store half-word / signed byte)
/*-------------------------------------------------------------------------*/
RUT_str_hw_pre:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_EXTRAS
//Calcular la dir. efectiva (y guardarla, si eso)
PREINDEX
core->writeMemoriaHalfword(contexto->bancoRegistros[rd].u_halfword, dirEfectiva);
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina LDR HW/B post-index (Load half-word / signed byte)
/*-------------------------------------------------------------------------*/
RUT_ldr_hw_post:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_EXTRAS
switch (esSignedHalfword) {
case 2:
resultado = (int8)(core->readMemoriaByte(operando1));
break;
case 3:
resultado = (int16)(core->readMemoriaHalfword(operando1));
break;
default:
resultado = unsigned int (core->readMemoriaHalfword(operando1));
}
//Calcular la dir. efectiva (y guardarla)
POSTINDEX
CHK_ABORT
contexto->bancoRegistros[rd].u_word = resultado;
nCiclos-=2;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina STR HW post-index (Store half-word / signed byte)
/*-------------------------------------------------------------------------*/
RUT_str_hw_post:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LS_EXTRAS
core->writeMemoriaHalfword(contexto->bancoRegistros[rd].u_halfword, operando1);
//Calcular la dir. efectiva (y guardarla)
POSTINDEX
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina LDM pre-index (Load multiple)
/*-------------------------------------------------------------------------*/
RUT_ldm_pre:
//Comprueba el codigo de condicion
COMPROBAR_COND
//Obtiene los operandos
GETOPS_LSM
//Para cada registro, lo transfiere si su bit esta a 1
for ((u==1)? i = 0 : i=15;
(u==1)? (i<16): (i>=0);
(u==1)? i++ : i--) {
if (listaRegistros & (0x1<<i)) {
nCiclos--;
//Pre-indexada
dirEfectiva += dirOffset;
//Lectura de memoria
resultado = core->readMemoriaWord(dirEfectiva);
//Escribe el resultado en el registro correspondiente
LSM_WRITEREGS
}
}
//W=1 (Write-back)
if (w) {
contexto->bancoRegistros[rn].u_word = dirEfectiva;
}
CHK_ABORT
//lsmCPSR (Se restaura el CPSR con el SPSR)
if (lsmCPSR) {
contexto->escribirCPSR(contexto->SPSR[contexto->modo-1].u_word);
}
nCiclos--;
goto LecturaInstruccion;
/*-------------------------------------------------------------------------*/
/* Rutina LDM post-index (Load multiple)
/*-------------------------------------------------------------------------*/
RUT_ldm_post:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -