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

📄 addressing.c

📁 SkyEye是一个可以运行嵌入式操作系统的硬件仿真工具
💻 C
字号:
/**********************************//*                                *//*  Copyright 2000, David Grant   *//*                                *//*  see LICENSE for more details  *//*                                *//**********************************/#include "coldfire.h"/* Addressing Mode  Mode   Register        Dy          000    memory_core.dnum        Ay          001    memory_core.anum       (Ay)         010    memory_core.anum       (Ay)+        011    memory_core.anum      -(Ay)         100    memory_core.anum     (d16,Ay)       101    memory_core.anum    (d8,Ay,Xi)      110    memory_core.anum     (xxx).W        111    000     (xxx).L        111    001     #<data>        111    100     (d16,PC)       111    010    (d8,PC,Xi)      111    011*//* FUNCTION: Retrives the value in memory based on the supplied Mode and              Register       ARGS: Size=8,16,32, we are careful with this because an 8 bit retrive for                  a Dx, or Ax is the LSB, but for memory addressing, it is the 8                  bits where the pointer is pointing to.             Mode=the mode from the instruction             Register=the register from the instruction             EAValue=if true, we return the address.. not what is at the address...                      this means that we can't use Dx,Ay, and some others (because they                     don't have an EA     RETURNS: The value requested, or the EA if EAValue is turned on    COMMENTS:  *//* -------------------------------------*/    int Addressing_Print(short Size, char Mode, char Register, char *Str){	unsigned int Result=0;	short Scale;	struct _InstructionExtensionWord *EWordPtr = (void *)&Result;	switch(Mode) {	case 0: /* Dy */		sprintf(Str, "D%d", Register);		break;	case 1: /* Ay */		sprintf(Str, "A%d", Register);		break;	case 2: /* (Ay) */		sprintf(Str, "(A%d)", Register);		break;	case 3: /* (Ay)+ */		sprintf(Str, "(A%d)+", Register);		break;	case 4: /* -(Ay) */		sprintf(Str, "-(A%d)", Register);		break;	case 5: /* (d16,Ay) */		Memory_RetrWordFromPC(&Result);		sprintf(Str, "%hd(A%d)",(short)Result,Register);		break;	case 6: /* (d8,Ax,Xi) */		Memory_RetrWordFromPC(&Result);		if(EWordPtr->Scale == 0) Scale=1;		else if(EWordPtr->Scale == 1) Scale=2;		else if(EWordPtr->Scale == 2) Scale=4;		else Scale=1;		sprintf(Str, "%d(A%d,%c%d.L*%d)",EWordPtr->Displacement, 			Register, EWordPtr->AD ? 'A' : 'D', EWordPtr->Register, Scale);		break;	case 7: /* Direct modes */		switch(Register) {		case 0: /* word addressing */			Memory_RetrWordFromPC(&Result);			sprintf(Str, "(0x%04hX.W)", (short)Result);			break;		case 1: /* long addressing */			Memory_RetrLongWordFromPC(&Result);			sprintf(Str, "(0x%08lX.L)", Result);			break;		case 2: /* (d16,PC) */			Memory_RetrWordFromPC(&Result);			sprintf(Str, "%hd(PC)",(short)Result);			break;		case 3: /* (d8,PC,Xi) */			Memory_RetrWordFromPC(&Result);			if(EWordPtr->Scale == 0) Scale=1;			else if(EWordPtr->Scale == 1) Scale=2;			else if(EWordPtr->Scale == 2) Scale=4;			else Scale=1;			sprintf(Str, "%d(PC,%c%d.L*%d)",EWordPtr->Displacement, 				EWordPtr->AD ? 'A' : 'D', EWordPtr->Register, Scale);			break;		case 4:			if(Size==8) {				Memory_RetrByteFromPC(&Result);/*				if( (char)Result < 0)					sprintf(Str, "#%d", (char)Result);				else*/					sprintf(Str, "#0x%02lX", Result);			} else if(Size==16) {				Memory_RetrWordFromPC(&Result);/*				if( (short)Result < 0)					sprintf(Str, "#%d", (short)Result);				else if((short)Result == 0)					sprintf(Str, "#0");				else*/					sprintf(Str, "#0x%04lX", Result);			} else if(Size==32) {				Memory_RetrLongWordFromPC(&Result);/*				if( (int)Result < 0)					sprintf(Str, "#%ld", (int)Result);				else*/					sprintf(Str, "#0x%08lX", Result);			}			break;		default:			sprintf(Str, "---");			break;		}	}	return 0;}/* This gets an address, and all useful information about an address from * the PC.  Once the address is retrieved, it can be used (multiple times) * to write to, read from, etc.  This allows us to only need to access the * PC once during instruction operand fetch.  So if the destionation is (say) * an immediate address, we already have it.. we don't need to do any PC  * magic to reset it, and re-read the address.  I don't know if this is  * actally how the Coldfire works (what happens if you write to the address * you're fetching from.. does the board re-fetch the operand, or just use * the value of the address it pulled the source from?) *//* It also lets us do things like auto increment, and autodecrement.. and * stores the original address in a place where we can use it again */char EA_GetFromPC(struct _Address *Addr, short Size, char Mode, char Register) {	struct _InstructionExtensionWord *EWordPtr = (struct _InstructionExtensionWord *)&Addr->Data;	short Scale;	Addr->Mode=Mode;	Addr->Register=Register;	Addr->Data=0;	/* This is for storing operands that are in the instruction */	Addr->Address = 0xdeadbeef;	Addr->Size=Size;#ifdef MEMORY_STATS	/* FIXME: this could be moved to the EA_GetValue, GetEA, and PutValue functions,	 * it might give a more accurate representation there (some instructions do a direct	 * read from the PC if they know what they are reading, but usually they go through	 * the EA_* routines), and would let things be split into reads/writes. */	Stats_Build_EA(Register, Mode);#endif /* MEMORY_STATS */	switch(Mode) {	case 0: /* Dy */		return 1;	case 1: /* Ay */		return 1;	case 2: /* (Ay) */		Addr->Address = memory_core.a[(int)Register];		return 1;	case 3: /* (Ay)+ */		Addr->Address = memory_core.a[(int)Register];		memory_core.a[(int)Register]+=Size>>3;		return 1;	case 4: /* -(Ay) */		memory_core.a[(int)Register]-=Size>>3;		Addr->Address = memory_core.a[(int)Register];		return 1;	case 5:	/* (d16,Ay) */		if(!Memory_RetrWordFromPC(&Addr->Data)) return 0;		Addr->Address = memory_core.a[(int)Register]+(short)Addr->Data;		return 1;	case 6:	/* (d8,An,Xi) */		if(!Memory_RetrWordFromPC(&Addr->Data)) return 0;		if(EWordPtr->Scale == 0) Scale=1;		else if(EWordPtr->Scale == 1) Scale=2;		else if(EWordPtr->Scale == 2) Scale=4;		else Scale=1;			EWordPtr->Displacement, EWordPtr->AD ? "A" : "D", 			EWordPtr->Register, EWordPtr->AD ? memory_core.a[EWordPtr->Register] : memory_core.d[EWordPtr->Register], 		Addr->Address = memory_core.a[(int)Register] + EWordPtr->Displacement;		/* EWordPtr->AD == 0 for memory_core.dister */		if(EWordPtr->AD==0)			Addr->Address += memory_core.d[(int)EWordPtr->Register] * Scale;			else 			Addr->Address += memory_core.a[(int)EWordPtr->Register] * Scale;		return 1;				case 7: /* Direct modes */		switch(Register) {		case 0: /* word addressing */			if(!Memory_RetrWordFromPC(&Addr->Data)) return 0;			Addr->Address = Addr->Data;			return 1;		case 1: /* long addressing */			if (!Memory_RetrLongWordFromPC(&Addr->Data)) return 0;			Addr->Address = Addr->Data;			return 1;		case 2: /* (d16,PC) */			/* This uses the value of the PC as the address of				the extenstion word, we are already there */			Addr->Address = memory_core.pc;			/* Now alter the PC to get the extension word */			if(!Memory_RetrWordFromPC(&Addr->Data)) return 0;			Addr->Address += (short)Addr->Data;			return 1;		case 3: /* (d8,PC,Xi) */			/* This uses the value of the PC as the address of				the extenstion word, we are already there */			Addr->Address = memory_core.pc;			/* Now alter the PC to get the extension word */			if(!Memory_RetrWordFromPC(&Addr->Data)) return 0;			if(EWordPtr->Scale == 0) Scale=1;						else if(EWordPtr->Scale == 1) Scale=2;			else if(EWordPtr->Scale == 2) Scale=4;			else Scale=1;				EWordPtr->Displacement, EWordPtr->AD ? "A" : "D", 				EWordPtr->Register, EWordPtr->AD ? memory_core.a[EWordPtr->Register] : memory_core.d[EWordPtr->Register], 			Addr->Address += EWordPtr->Displacement;			/* EWordPtr->AD == 0 for memory_core.dister */			if(EWordPtr->AD==0)				Addr->Address += memory_core.d[(int)EWordPtr->Register] * Scale;			else 					Addr->Address += memory_core.a[(int)EWordPtr->Register] * Scale;			return 1;		case 4:			if(!Memory_RetrFromPC(&Addr->Data, Size)) return 0;			Addr->Address = 0xdeadbeef;			if(Size==8) {			} else if(Size==16) {			} else {			}			return 1;		}		/* Should never get here */		break;	}	return 0;}/* Takes an address, (that we build from EA_GetFromPC), and returns the  * value associated with it (with proper masking of bits) * This sign extends the return so it can be used directly for math ops * or for negative compares without worrying about actual size */char EA_GetValue(unsigned int *Result, struct _Address *Addr){	char ReturnValue = 1;	switch(Addr->Mode) {	case 0: /* Dy */		*Result = memory_core.d[(int)Addr->Register];		break;	case 1: /* Ay */		*Result = memory_core.a[(int)Addr->Register];		break;	case 2: /* (Ay) */	case 3: /* (Ay)+ */	case 4: /* -(Ay) */	case 5:	/* (d16,Ay) */	case 6:	/* (d8,An,Xi) */		ReturnValue = Memory_Retr(Result, Addr->Size,Addr->Address);		break;				case 7: /* Direct modes */		switch(Addr->Register) {		case 0: /* word addressing */		case 1: /* long addressing */		case 2: /* (d16,PC) */		case 3: /* (d8,PC,Xi) */			ReturnValue = Memory_Retr(Result, Addr->Size,Addr->Address);			break;		case 4:			*Result = Addr->Data;			break;		}		break;	}	/* Now mask it through the size ..             eg  & 0x000000FF for 8bit, etc. */	if(Addr->Size & 0x0020) return 1;	if(Addr->Size & 0x0010) *Result = (short)*Result;	else			*Result = (char)*Result;	return ReturnValue;}/* This is used by instructions that play with effective addresses (EAs) * instead of getting the value at an addrss, we get the actual address */char EA_GetEA(unsigned int *Result, struct _Address *Addr){	switch(Addr->Mode) {	case 0: /* Dy */	case 1: /* Ay */	case 3: /* (Ay)+ */	case 4: /* -(Ay) */		//ERR("Can't get the EA of a register..\n");		return 0;	case 2: /* (Ay) */	case 5:	/* (d16,Ay) */	case 6:	/* (d8,An,Xi) */		*Result = Addr->Address;		break;				case 7: /* Direct modes */		switch(Addr->Register) {		case 0: /* word addressing */		case 1: /* long addressing */		case 2: /* (d16,PC) */		case 3: /* (d8,PC,Xi) */			*Result = Addr->Address;			break;		case 4:			return 0;		}		break;	}	return 1;}/* Given a value, and an address, this puts that value */void EA_PutValue(struct _Address *Addr, unsigned int Value){	/* Value is long, sign extended */		switch(Addr->Mode) {	case 0: /* Dy */		/* Coldfire preserves the bits not written to when writing		 *  to a D register */		if(Addr->Size & 0x0020) {			memory_core.d[(int)Addr->Register] = Value;			return;		} else if(Addr->Size & 0x0010) {			memory_core.d[(int)Addr->Register] &= 0xFFFF0000;			memory_core.d[(int)Addr->Register] |= Value & 0x0000FFFF;			return;		} else {			memory_core.d[(int)Addr->Register] &= 0xFFFFFF00;			memory_core.d[(int)Addr->Register] |= Value & 0x000000FF;			return;		}		return;	case 1: /* Ay */		/* for both word and long writes to the A register, we 		 * store the long sign extended value, but for byte writes, 		 * we only overwrite the lowest byte. */		if(Addr->Size & 0x0030) {			memory_core.a[(int)Addr->Register] = Value;			return;/*		} else if(Addr->Size & 0x0010) {			memory_core.a[(int)Addr->Register] &= 0xFFFF0000;			memory_core.a[(int)Addr->Register] |= Value & 0x0000FFFF;			return;*/		} else {			memory_core.a[(int)Addr->Register] &= 0xFFFFFF00;			memory_core.a[(int)Addr->Register] |= Value & 0x000000FF;			return;		}				return;	case 2: /* (Ay) */	case 3: /* (Ay)+ */	case 4: /* -(Ay) */	case 5:	/* (d16,Ay) */	case 6:	/* (d8,An,Xi) */		if(Addr->Size & 0x0020);		else if(Addr->Size & 0x0010) 	Value = (unsigned short)Value;		else				Value = (unsigned char)Value;		Memory_Stor(Addr->Size,Addr->Address,Value);		return;				case 7: /* Direct modes */		switch(Addr->Register) {		case 0: /* word addressing */		case 1: /* long addressing */			if(Addr->Size & 0x0020);			else if(Addr->Size & 0x0010) 	Value = (unsigned short)Value;			else				Value = (unsigned char)Value;			Memory_Stor(Addr->Size,Addr->Address,Value);			return;		case 2: /* (d16,PC) */		case 3: /* (d8,PC,Xi) */		case 4:			//ERR("Can't write to the PC, go away.\n");			return;		}		/* Shouldn't get here */		break;	}}void Stack_Push(short Size, unsigned int Value){	struct _Address Dest;	EA_GetFromPC(&Dest, Size, 4, 7);	EA_PutValue(&Dest, Value);}unsigned int Stack_Pop(short Size){	struct _Address Dest;	unsigned int Value;	EA_GetFromPC(&Dest, Size, 3, 7);	EA_GetValue(&Value, &Dest);	return Value;}

⌨️ 快捷键说明

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