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

📄 armemu.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  armemu.c -- Main instruction emulation:  ARM7 Instruction Emulator.    Copyright (C) 1994 Advanced RISC Machines Ltd.    Modifications to add arch. v4 support by <jsmith@cygnus.com>.     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 "armos.h"#include "iwmmxt.h"static ARMword  GetDPRegRHS         (ARMul_State *, ARMword);static ARMword  GetDPSRegRHS        (ARMul_State *, ARMword);static void     WriteR15            (ARMul_State *, ARMword);static void     WriteSR15           (ARMul_State *, ARMword);static void     WriteR15Branch      (ARMul_State *, ARMword);static ARMword  GetLSRegRHS         (ARMul_State *, ARMword);static ARMword  GetLS7RHS           (ARMul_State *, ARMword);static unsigned LoadWord            (ARMul_State *, ARMword, ARMword);static unsigned LoadHalfWord        (ARMul_State *, ARMword, ARMword, int);static unsigned LoadByte            (ARMul_State *, ARMword, ARMword, int);static unsigned StoreWord           (ARMul_State *, ARMword, ARMword);static unsigned StoreHalfWord       (ARMul_State *, ARMword, ARMword);static unsigned StoreByte           (ARMul_State *, ARMword, ARMword);static void     LoadMult            (ARMul_State *, ARMword, ARMword, ARMword);static void     StoreMult           (ARMul_State *, ARMword, ARMword, ARMword);static void     LoadSMult           (ARMul_State *, ARMword, ARMword, ARMword);static void     StoreSMult          (ARMul_State *, ARMword, ARMword, ARMword);static unsigned Multiply64          (ARMul_State *, ARMword, int, int);static unsigned MultiplyAdd64       (ARMul_State *, ARMword, int, int);static void     Handle_Load_Double  (ARMul_State *, ARMword);static void     Handle_Store_Double (ARMul_State *, ARMword);#define LUNSIGNED (0)		/* unsigned operation */#define LSIGNED   (1)		/* signed operation */#define LDEFAULT  (0)		/* default : do nothing */#define LSCC      (1)		/* set condition codes on result */#ifdef NEED_UI_LOOP_HOOK/* How often to run the ui_loop update, when in use.  */#define UI_LOOP_POLL_INTERVAL 0x32000/* Counter for the ui_loop_hook update.  */static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;/* Actual hook to call to run through gdb's gui event loop.  */extern int (*deprecated_ui_loop_hook) (int);#endif /* NEED_UI_LOOP_HOOK */extern int stop_simulator;/* Short-hand macros for LDR/STR.  *//* Store post decrement writeback.  */#define SHDOWNWB()                                      \  lhs = LHS ;                                           \  if (StoreHalfWord (state, instr, lhs))                \     LSBase = lhs - GetLS7RHS (state, instr);/* Store post increment writeback.  */#define SHUPWB()                                        \  lhs = LHS ;                                           \  if (StoreHalfWord (state, instr, lhs))                \     LSBase = lhs + GetLS7RHS (state, instr);/* Store pre decrement.  */#define SHPREDOWN()                                     \  (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));/* Store pre decrement writeback.  */#define SHPREDOWNWB()                                   \  temp = LHS - GetLS7RHS (state, instr);                \  if (StoreHalfWord (state, instr, temp))               \     LSBase = temp;/* Store pre increment.  */#define SHPREUP()                                       \  (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));/* Store pre increment writeback.  */#define SHPREUPWB()                                     \  temp = LHS + GetLS7RHS (state, instr);                \  if (StoreHalfWord (state, instr, temp))               \     LSBase = temp;/* Load post decrement writeback.  */#define LHPOSTDOWN()                                    \{                                                       \  int done = 1;                                        	\  lhs = LHS;						\  temp = lhs - GetLS7RHS (state, instr);		\  							\  switch (BITS (5, 6))					\    {                                  			\    case 1: /* H */                                     \      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \         LSBase = temp;        				\      break;                                           	\    case 2: /* SB */                                    \      if (LoadByte (state, instr, lhs, LSIGNED))        \         LSBase = temp;        				\      break;                                           	\    case 3: /* SH */                                    \      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \         LSBase = temp;        				\      break;                                           	\    case 0: /* SWP handled elsewhere.  */               \    default:                                            \      done = 0;                                        	\      break;                                           	\    }                                                   \  if (done)                                             \     break;                                            	\}/* Load post increment writeback.  */#define LHPOSTUP()                                      \{                                                       \  int done = 1;                                        	\  lhs = LHS;                                           	\  temp = lhs + GetLS7RHS (state, instr);		\  							\  switch (BITS (5, 6))					\    {                                  			\    case 1: /* H */                                     \      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \         LSBase = temp;        				\      break;                                           	\    case 2: /* SB */                                    \      if (LoadByte (state, instr, lhs, LSIGNED))        \         LSBase = temp;        				\      break;                                           	\    case 3: /* SH */                                    \      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \         LSBase = temp;        				\      break;                                           	\    case 0: /* SWP handled elsewhere.  */               \    default:                                            \      done = 0;                                        	\      break;                                           	\    }                                                   \  if (done)                                             \     break;                                            	\}/* Load pre decrement.  */#define LHPREDOWN()                                     	\{                                                       	\  int done = 1;                                        		\								\  temp = LHS - GetLS7RHS (state, instr);                 	\  switch (BITS (5, 6))						\    {                                  				\    case 1: /* H */                                     	\      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);  	\      break;                                           		\    case 2: /* SB */                                    	\      (void) LoadByte (state, instr, temp, LSIGNED);        	\      break;                                           		\    case 3: /* SH */                                    	\      (void) LoadHalfWord (state, instr, temp, LSIGNED);    	\      break;                                           		\    case 0:							\      /* SWP handled elsewhere.  */                 		\    default:                                            	\      done = 0;                                        		\      break;                                           		\    }                                                   	\  if (done)                                             	\     break;                                            		\}/* Load pre decrement writeback.  */#define LHPREDOWNWB()                                   	\{                                                       	\  int done = 1;                                        		\								\  temp = LHS - GetLS7RHS (state, instr);                	\  switch (BITS (5, 6))						\    {                                  				\    case 1: /* H */                                     	\      if (LoadHalfWord (state, instr, temp, LUNSIGNED))     	\         LSBase = temp;                                		\      break;                                           		\    case 2: /* SB */                                    	\      if (LoadByte (state, instr, temp, LSIGNED))           	\         LSBase = temp;                                		\      break;                                           		\    case 3: /* SH */                                    	\      if (LoadHalfWord (state, instr, temp, LSIGNED))       	\         LSBase = temp;                                		\      break;                                           		\    case 0:							\      /* SWP handled elsewhere.  */                 		\    default:                                            	\      done = 0;                                        		\      break;                                           		\    }                                                   	\  if (done)                                             	\     break;                                            		\}/* Load pre increment.  */#define LHPREUP()                                       	\{                                                       	\  int done = 1;                                        		\								\  temp = LHS + GetLS7RHS (state, instr);                 	\  switch (BITS (5, 6))						\    {                                  				\    case 1: /* H */                                     	\      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);  	\      break;                                           		\    case 2: /* SB */                                    	\      (void) LoadByte (state, instr, temp, LSIGNED);        	\      break;                                           		\    case 3: /* SH */                                    	\      (void) LoadHalfWord (state, instr, temp, LSIGNED);    	\      break;                                           		\    case 0:							\      /* SWP handled elsewhere.  */                 		\    default:                                            	\      done = 0;                                        		\      break;                                           		\    }                                                   	\  if (done)                                             	\     break;                                            		\}/* Load pre increment writeback.  */#define LHPREUPWB()                                     	\{                                                       	\  int done = 1;                                        		\								\  temp = LHS + GetLS7RHS (state, instr);                	\  switch (BITS (5, 6))						\    {                                  				\    case 1: /* H */                                     	\      if (LoadHalfWord (state, instr, temp, LUNSIGNED))     	\	LSBase = temp;                                		\      break;                                           		\    case 2: /* SB */                                    	\      if (LoadByte (state, instr, temp, LSIGNED))           	\	LSBase = temp;                                		\      break;                                           		\    case 3: /* SH */                                    	\      if (LoadHalfWord (state, instr, temp, LSIGNED))       	\	LSBase = temp;                                		\      break;                                           		\    case 0:							\      /* SWP handled elsewhere.  */                 		\    default:                                            	\      done = 0;                                        		\      break;                                           		\    }                                                   	\  if (done)                                             	\     break;                                            		\}/* EMULATION of ARM6.  *//* The PC pipeline value depends on whether ARM   or Thumb instructions are being executed.  */ARMword isize;ARMword#ifdef MODE32ARMul_Emulate32 (ARMul_State * state)#elseARMul_Emulate26 (ARMul_State * state)#endif{  ARMword instr;	/* The current instruction.  */  ARMword dest = 0;	/* Almost the DestBus.  */  ARMword temp;		/* Ubiquitous third hand.  */  ARMword pc = 0;	/* The address of the current instruction.  */  ARMword lhs;		/* Almost the ABus and BBus.  */  ARMword rhs;  ARMword decoded = 0;	/* Instruction pipeline.  */  ARMword loaded = 0;	  /* Execute the next instruction.  */  if (state->NextInstr < PRIMEPIPE)    {      decoded = state->decoded;      loaded = state->loaded;      pc = state->pc;    }  do    {      /* Just keep going.  */      isize = INSN_SIZE;      switch (state->NextInstr)	{	case SEQ:	  /* Advance the pipeline, and an S cycle.  */	  state->Reg[15] += isize;	  pc += isize;	  instr = decoded;	  decoded = loaded;	  loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);	  break;	case NONSEQ:	  /* Advance the pipeline, and an N cycle.  */	  state->Reg[15] += isize;	  pc += isize;	  instr = decoded;	  decoded = loaded;	  loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);	  NORMALCYCLE;	  break;	case PCINCEDSEQ:	  /* Program counter advanced, and an S cycle.  */	  pc += isize;	  instr = decoded;	  decoded = loaded;	  loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);	  NORMALCYCLE;	  break;	case PCINCEDNONSEQ:	  /* Program counter advanced, and an N cycle.  */	  pc += isize;	  instr = decoded;	  decoded = loaded;	  loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);	  NORMALCYCLE;	  break;	case RESUME:	  /* The program counter has been changed.  */	  pc = state->Reg[15];#ifndef MODE32	  pc = pc & R15PCBITS;#endif	  state->Reg[15] = pc + (isize * 2);	  state->Aborted = 0;	  instr   = ARMul_ReLoadInstr (state, pc, isize);	  decoded = ARMul_ReLoadInstr (state, pc + isize, isize);	  loaded  = ARMul_ReLoadInstr (state, pc + isize * 2, isize);	  NORMALCYCLE;	  break;	default:	  /* The program counter has been changed.  */	  pc = state->Reg[15];#ifndef MODE32	  pc = pc & R15PCBITS;#endif	  state->Reg[15] = pc + (isize * 2);	  state->Aborted = 0;	  instr   = ARMul_LoadInstrN (state, pc, isize);	  decoded = ARMul_LoadInstrS (state, pc + (isize), isize);	  loaded  = ARMul_LoadInstrS (state, pc + (isize * 2), isize);	  NORMALCYCLE;	  break;	}      if (state->EventSet)	ARMul_EnvokeEvent (state);#if 0 /* Enable this for a helpful bit of debugging when tracing is needed.  */      fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);      if (instr == 0)	abort ();#endif#if 0 /* Enable this code to help track down stack alignment bugs.  */      {	static ARMword old_sp = -1;	if (old_sp != state->Reg[13])	  {	    old_sp = state->Reg[13];	    fprintf (stderr, "pc: %08x: SP set to %08x%s\n",		     pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");	  }      }#endif      if (state->Exception)	{	  /* Any exceptions ?  */	  if (state->NresetSig == LOW)	    {	      ARMul_Abort (state, ARMul_ResetV);	      break;	    }	  else if (!state->NfiqSig && !FFLAG)	    {	      ARMul_Abort (state, ARMul_FIQV);	      break;	    }	  else if (!state->NirqSig && !IFLAG)	    {	      ARMul_Abort (state, ARMul_IRQV);	      break;	    }	}      if (state->CallDebug > 0)	{	  instr = ARMul_Debug (state, pc, instr);	  if (state->Emulate < ONCE)	    {	      state->NextInstr = RESUME;	      break;	    }	  if (state->Debug)	    {	      fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,		       state->Mode);	      (void) fgetc (stdin);	    }	}      else if (state->Emulate < ONCE)	{	  state->NextInstr = RESUME;	  break;	}      state->NumInstrs++;#ifdef MODET      /* Provide Thumb instruction decoding. If the processor is in Thumb         mode, then we can simply decode the Thumb instruction, and map it         to the corresponding ARM instruction (by directly loading the         instr variable, and letting the normal ARM simulator         execute). There are some caveats to ensure that the correct         pipelined PC value is used when executing Thumb code, and also for         dealing with the BL instruction.  */      if (TFLAG)	{	  ARMword new;	  /* Check if in Thumb mode.  */	  switch (ARMul_ThumbDecode (state, pc, instr, &new))	    {	    case t_undefined:	      /* This is a Thumb instruction.  */	      ARMul_UndefInstr (state, instr);	      goto donext;	    case t_branch:	      /* Already processed.  */	      goto donext;	    case t_decoded:	      /* ARM instruction available.  */	      instr = new;	      /* So continue instruction decoding.  */	      break;	    default:	      break;	    }	}#endif      /* Check the condition codes.  */      if ((temp = TOPBITS (28)) == AL)	/* Vile deed in the need for speed.  */	goto mainswitch;      /* Check the condition code.  */      switch ((int) TOPBITS (28))	{	case AL:	  temp = TRUE;	  break;	case NV:	  if (state->is_v5)	    {	      if (BITS (25, 27) == 5) /* BLX(1) */		{		  ARMword dest;		  		  state->Reg[14] = pc + 4;		  		  /* Force entry into Thumb mode.  */		  dest = pc + 8 + 1;		  if (BIT (23))		    dest += (NEGBRANCH + (BIT (24) << 1));		  else		    dest += POSBRANCH + (BIT (24) << 1);		  WriteR15Branch (state, dest);		  goto donext;		}	      else if ((instr & 0xFC70F000) == 0xF450F000)		/* The PLD instruction.  Ignored.  */		goto donext;	      else if (   ((instr & 0xfe500f00) == 0xfc100100)		       || ((instr & 0xfe500f00) == 0xfc000100))		/* wldrw and wstrw are unconditional.  */		goto mainswitch;	      else		/* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2.  */		ARMul_UndefInstr (state, instr);	    }	  temp = FALSE;	  break;	case EQ:	  temp = ZFLAG;	  break;	case NE:	  temp = !ZFLAG;	  break;	case VS:

⌨️ 快捷键说明

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