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

📄 arm9macrosarm.h

📁 ARM9Core v0.4, 在x86 Win32 下模拟仿真ARM9 微处理器的Library.
💻 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 + -