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

📄 armsupp.c

📁 skyeye的开源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  armsupp.c -- ARMulator support code:  ARM6 Instruction Emulator.    Copyright (C) 1994 Advanced RISC Machines Ltd.     This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.     This program 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 General Public License for more details.     You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "armdefs.h"#include "armemu.h"#include "ansidecl.h"//extern int skyeye_instr_debug;/* Definitions for the support routines.  */static ARMword ModeToBank (ARMword);static void EnvokeList (ARMul_State *, unsigned int, unsigned int);struct EventNode{				/* An event list node.  */	unsigned (*func) (ARMul_State *);	/* The function to call.  */	struct EventNode *next;};/* This routine returns the value of a register from a mode.  */ARMwordARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg){	mode &= MODEBITS;	if (mode != state->Mode)		return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);	else		return (state->Reg[reg]);}/* This routine sets the value of a register for a mode.  */voidARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value){	mode &= MODEBITS;	if (mode != state->Mode)		state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;	else		state->Reg[reg] = value;}/* This routine returns the value of the PC, mode independently.  */ARMwordARMul_GetPC (ARMul_State * state){	if (state->Mode > SVC26MODE)		return state->Reg[15];	else		return R15PC;}/* This routine returns the value of the PC, mode independently.  */ARMwordARMul_GetNextPC (ARMul_State * state){	if (state->Mode > SVC26MODE)		return state->Reg[15] + isize;	else		return (state->Reg[15] + isize) & R15PCBITS;}/* This routine sets the value of the PC.  */voidARMul_SetPC (ARMul_State * state, ARMword value){	if (ARMul_MODE32BIT)		state->Reg[15] = value & PCBITS;	else		state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);	FLUSHPIPE;}/* This routine returns the value of register 15, mode independently.  */ARMwordARMul_GetR15 (ARMul_State * state){	if (state->Mode > SVC26MODE)		return (state->Reg[15]);	else		return (R15PC | ECC | ER15INT | EMODE);}/* This routine sets the value of Register 15.  */voidARMul_SetR15 (ARMul_State * state, ARMword value){	if (ARMul_MODE32BIT)		state->Reg[15] = value & PCBITS;	else {		state->Reg[15] = value;		ARMul_R15Altered (state);	}	FLUSHPIPE;}/* This routine returns the value of the CPSR.  */ARMwordARMul_GetCPSR (ARMul_State * state){	//chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator	//return (CPSR | state->Cpsr); for gdb20030716	return (CPSR);		//had be tested in old skyeye with gdb5.0-5.3}/* This routine sets the value of the CPSR.  */voidARMul_SetCPSR (ARMul_State * state, ARMword value){	state->Cpsr = value;	ARMul_CPSRAltered (state);}/* This routine does all the nasty bits involved in a write to the CPSR,   including updating the register bank, given a MSR instruction.  */voidARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs){	state->Cpsr = ARMul_GetCPSR (state);	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode	if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {		/* In user mode, only write flags.  */		if (BIT (16))			SETPSR_C (state->Cpsr, rhs);		if (BIT (17))			SETPSR_X (state->Cpsr, rhs);		if (BIT (18))			SETPSR_S (state->Cpsr, rhs);	}	if (BIT (19))		SETPSR_F (state->Cpsr, rhs);	ARMul_CPSRAltered (state);}/* Get an SPSR from the specified mode.  */ARMwordARMul_GetSPSR (ARMul_State * state, ARMword mode){	ARMword bank = ModeToBank (mode & MODEBITS);	if (!BANK_CAN_ACCESS_SPSR (bank))		return ARMul_GetCPSR (state);	return state->Spsr[bank];}/* This routine does a write to an SPSR.  */voidARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value){	ARMword bank = ModeToBank (mode & MODEBITS);	if (BANK_CAN_ACCESS_SPSR (bank))		state->Spsr[bank] = value;}/* This routine does a write to the current SPSR, given an MSR instruction.  */voidARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs){	if (BANK_CAN_ACCESS_SPSR (state->Bank)) {		if (BIT (16))			SETPSR_C (state->Spsr[state->Bank], rhs);		if (BIT (17))			SETPSR_X (state->Spsr[state->Bank], rhs);		if (BIT (18))			SETPSR_S (state->Spsr[state->Bank], rhs);		if (BIT (19))			SETPSR_F (state->Spsr[state->Bank], rhs);	}}/* This routine updates the state of the emulator after the Cpsr has been   changed.  Both the processor flags and register bank are updated.  */voidARMul_CPSRAltered (ARMul_State * state){	ARMword oldmode;	if (state->prog32Sig == LOW)		state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);	oldmode = state->Mode;	if (state->Mode != (state->Cpsr & MODEBITS)) {		state->Mode =			ARMul_SwitchMode (state, state->Mode,					  state->Cpsr & MODEBITS);		state->NtransSig = (state->Mode & 3) ? HIGH : LOW;	}	//state->Cpsr &= ~MODEBITS;	ASSIGNINT (state->Cpsr & INTBITS);	//state->Cpsr &= ~INTBITS;	ASSIGNN ((state->Cpsr & NBIT) != 0);	//state->Cpsr &= ~NBIT;	ASSIGNZ ((state->Cpsr & ZBIT) != 0);	//state->Cpsr &= ~ZBIT;	ASSIGNC ((state->Cpsr & CBIT) != 0);	//state->Cpsr &= ~CBIT;	ASSIGNV ((state->Cpsr & VBIT) != 0);	//state->Cpsr &= ~VBIT;	ASSIGNS ((state->Cpsr & SBIT) != 0);	//state->Cpsr &= ~SBIT;#ifdef MODET	ASSIGNT ((state->Cpsr & TBIT) != 0);	//state->Cpsr &= ~TBIT;#endif	if (oldmode > SVC26MODE) {		if (state->Mode <= SVC26MODE) {			state->Emulate = CHANGEMODE;			state->Reg[15] = ECC | ER15INT | EMODE | R15PC;		}	}	else {		if (state->Mode > SVC26MODE) {			state->Emulate = CHANGEMODE;			state->Reg[15] = R15PC;		}		else			state->Reg[15] = ECC | ER15INT | EMODE | R15PC;	}}/* This routine updates the state of the emulator after register 15 has   been changed.  Both the processor flags and register bank are updated.   This routine should only be called from a 26 bit mode.  */voidARMul_R15Altered (ARMul_State * state){	if (state->Mode != R15MODE) {		state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);		state->NtransSig = (state->Mode & 3) ? HIGH : LOW;	}	if (state->Mode > SVC26MODE)		state->Emulate = CHANGEMODE;	ASSIGNR15INT (R15INT);	ASSIGNN ((state->Reg[15] & NBIT) != 0);	ASSIGNZ ((state->Reg[15] & ZBIT) != 0);	ASSIGNC ((state->Reg[15] & CBIT) != 0);	ASSIGNV ((state->Reg[15] & VBIT) != 0);}/* This routine controls the saving and restoring of registers across mode   changes.  The regbank matrix is largely unused, only rows 13 and 14 are   used across all modes, 8 to 14 are used for FIQ, all others use the USER   column.  It's easier this way.  old and new parameter are modes numbers.   Notice the side effect of changing the Bank variable.  */ARMwordARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode){	unsigned i;	ARMword oldbank;	ARMword newbank;	oldbank = ModeToBank (oldmode);	newbank = state->Bank = ModeToBank (newmode);	/* Do we really need to do it?  */	if (oldbank != newbank) {		/* Save away the old registers.  */		switch (oldbank) {		case USERBANK:		case IRQBANK:		case SVCBANK:		case ABORTBANK:		case UNDEFBANK:			if (newbank == FIQBANK)				for (i = 8; i < 13; i++)					state->RegBank[USERBANK][i] =						state->Reg[i];			state->RegBank[oldbank][13] = state->Reg[13];			state->RegBank[oldbank][14] = state->Reg[14];			break;		case FIQBANK:			for (i = 8; i < 15; i++)				state->RegBank[FIQBANK][i] = state->Reg[i];			break;		case DUMMYBANK:			for (i = 8; i < 15; i++)				state->RegBank[DUMMYBANK][i] = 0;			break;		default:			abort ();		}		/* Restore the new registers.  */		switch (newbank) {		case USERBANK:		case IRQBANK:		case SVCBANK:		case ABORTBANK:		case UNDEFBANK:			if (oldbank == FIQBANK)				for (i = 8; i < 13; i++)					state->Reg[i] =						state->RegBank[USERBANK][i];			state->Reg[13] = state->RegBank[newbank][13];			state->Reg[14] = state->RegBank[newbank][14];			break;		case FIQBANK:			for (i = 8; i < 15; i++)				state->Reg[i] = state->RegBank[FIQBANK][i];			break;		case DUMMYBANK:			for (i = 8; i < 15; i++)				state->Reg[i] = 0;			break;		default:			abort ();		}	}	return newmode;}/* Given a processor mode, this routine returns the   register bank that will be accessed in that mode.  */static ARMwordModeToBank (ARMword mode){	static ARMword bankofmode[] = {		USERBANK, FIQBANK, IRQBANK, SVCBANK,		DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,		DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,		DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,		USERBANK, FIQBANK, IRQBANK, SVCBANK,		DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,		DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,		DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK	};	if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))		return DUMMYBANK;	return bankofmode[mode];}/* Returns the register number of the nth register in a reg list.  */unsignedARMul_NthReg (ARMword instr, unsigned number){	unsigned bit, upto;	for (bit = 0, upto = 0; upto <= number; bit++)		if (BIT (bit))			upto++;	return (bit - 1);}/* Assigns the N and Z flags depending on the value of result.  */voidARMul_NegZero (ARMul_State * state, ARMword result){	if (NEG (result)) {		SETN;		CLEARZ;	}	else if (result == 0) {		CLEARN;		SETZ;	}	else {		CLEARN;		CLEARZ;	}}/* Compute whether an addition of A and B, giving RESULT, overflowed.  */intAddOverflow (ARMword a, ARMword b, ARMword result){	return ((NEG (a) && NEG (b) && POS (result))		|| (POS (a) && POS (b) && NEG (result)));}/* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */intSubOverflow (ARMword a, ARMword b, ARMword result){	return ((NEG (a) && POS (b) && POS (result))		|| (POS (a) && NEG (b) && NEG (result)));}/* Assigns the C flag after an addition of a and b to give result.  */voidARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result){	ASSIGNC ((NEG (a) && NEG (b)) ||		 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));}/* Assigns the V flag after an addition of a and b to give result.  */void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -