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

📄 armemu.c

📁 这是Skyeye 0.9 版本的源代码
💻 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"
//chy 2003-07-11: for debug instrs
//extern int skyeye_instr_debug;
extern FILE *skyeye_logfd;

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 (*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;                                            		\
}

/*ywc 2005-03-31*/
//teawater add for arm2x86 2005.02.17-------------------------------------------
#include "dbct/tb.h"
#ifndef NO_DBCT
#include "dbct/arm2x86_self.h"
#endif
//AJ2D--------------------------------------------------------------------------


/* EMULATION of ARM6.  */

/* The PC pipeline value depends on whether ARM
   or Thumb instructions are being executed.  */
ARMword isize;

#ifdef MODE32
/*
void chy_debug()
{
	printf("SkyEye chy_deubeg begin\n");
}
*/
ARMword
ARMul_Emulate32 (ARMul_State * state)
#else
ARMword
ARMul_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;
	  //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU>
	  state->AbortAddr = 1;

	  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;
	  //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU>
	  state->AbortAddr = 1;

	  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);
//2003-07-11 chy: for test
      if (skyeye_config.log.logon >= 1)
	{
	  if (state->NumInstrs >= skyeye_config.log.start &&
	      state->NumInstrs <= skyeye_config.log.end)
	    {
	      static int mybegin = 0;
	      static int myinstrnum = 0;
	      if (mybegin == 0)
		mybegin = 1;
#if 0
	      if (state->NumInstrs == 3695)
		{
		  printf ("***********SKYEYE: numinstr = 3695\n");
		}
	      static int mybeg2 = 0;
	      static int mybeg3 = 0;
	      static int mybeg4 = 0;
	      static int mybeg5 = 0;

	      if (pc == 0xa0008000)
		{
		  //mybegin=1;
		  printf
		    ("************SKYEYE: real vmlinux begin now  numinstr is %llu  ****************\n",
		     state->NumInstrs);
		}

	      //chy 2003-09-02 test fiq
	      if (state->NumInstrs == 67347000)
		{
		  printf
		    ("***********SKYEYE: numinstr = 67347000, begin log\n");
		  mybegin = 1;
		}
	      if (pc == 0xc00087b4)
		{		//numinstr=67348714
		  mybegin = 1;
		  printf
		    ("************SKYEYE: test irq now  numinstr is %llu  ****************\n",
		     state->NumInstrs);
		}
	      if (pc == 0xc00087b8)
		{		//in start_kernel::sti()
		  mybeg4 = 1;
		  printf
		    ("************SKYEYE: startkerenl: sti now  numinstr is %llu  ********\n",
		     state->NumInstrs);
		}
	      //if(pc==0xc001e4f4||pc==0xc001e4f8||pc==0xc001e4fc||pc==0xc001e500||pc==0xffff0004) { //MRA instr
	      if (pc == 0xc001e500)
		{		//MRA instr
		  mybeg5 = 1;
		  printf
		    ("************SKYEYE: MRA instr now  numinstr is %llu  ********\n",
		     state->NumInstrs);
		}
	      if (pc >= 0xc0000000 && mybeg2 == 0)
		{
		  mybeg2 = 1;
		  printf
		    ("************SKYEYE: enable mmu&cache, now numinstr is %llu **************\n",
		     state->NumInstrs);
		  SKYEYE_OUTREGS (stderr);
		  printf
		    ("************************************************************************\n");
		}
	      //chy 2003-09-01 test after tlb-flush 
	      if (pc == 0xc00261ac)
		{
		  //sleep(2);
		  mybeg3 = 1;
		  printf
		    ("************SKYEYE: after tlb-flush  numinstr is %llu  ****************\n",
		     state->NumInstrs);
		}
	      if (mybeg3 == 1)
		{
		  SKYEYE_OUTREGS (skyeye_logfd);
		  SKYEYE_OUTMOREREGS (skyeye_logfd);
		  fprintf (skyeye_logfd, "\n");
		}
#endif
	      if (mybegin == 1)
		{
		  //fprintf(skyeye_logfd,"p %x,i %x,d %x,l %x,",pc,instr,decoded,loaded);
		  //chy for test 20050729
		  /*if(state->NumInstrs>=3302294) {
		     if(pc==0x100c9d4 && instr==0xe1b0f00e){
		     chy_debug();
		     printf("*********************************************\n");
		     printf("******SKYEYE N %llx :p %x,i %x\n  SKYEYE******\n",state->NumInstrs,pc,instr);
		     printf("*********************************************\n");
		     }
		   */
		  if (skyeye_config.log.logon >= 1)
		    fprintf (skyeye_logfd, "N %llx :p %x,i %x,",
			     state->NumInstrs, pc, instr);
		  if (skyeye_config.log.logon >= 2)
		    SKYEYE_OUTREGS (skyeye_logfd);
		  if (skyeye_config.log.logon >= 3)
		    SKYEYE_OUTMOREREGS (skyeye_logfd);
		  fprintf (skyeye_logfd, "\n");
		  if (skyeye_config.log.length > 0)

⌨️ 快捷键说明

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