📄 armemu.c
字号:
/* 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 "skyeye2gdb.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);static inthandle_v6_insn (ARMul_State * state, ARMword instr);#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 int 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;extern int debugmode;#ifdef MODE32//chy 2006-04-12, for ICE debugint ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr){ int i; if(debugmode){ if (instr == ARMul_ABORTWORD) return 0; for (i=0;i<skyeye_ice.num_bps;i++){ if(skyeye_ice.bps[i] == addr){ //for test //printf("SKYEYE: ICE_debug bps [%d]== 0x%x\n", i,addr); state->EndCondition = 0; state->Emulate = STOP; return 1; } } if (skyeye_ice.tps_status==TRACE_STARTED) { for (i=0;i<skyeye_ice.num_tps;i++) { if (((skyeye_ice.tps[i].tp_address==addr)&&(skyeye_ice.tps[i].status==TRACEPOINT_ENABLED))||(skyeye_ice.tps[i].status==TRACEPOINT_STEPPING)) { handle_tracepoint(i); } } } } return 0;}/*void chy_debug(){ printf("SkyEye chy_deubeg begin\n");}*/ARMwordARMul_Emulate32 (ARMul_State * state)#elseARMwordARMul_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; ARMword decoded_addr=0; ARMword loaded_addr=0; ARMword have_bp=0; static unsigned remote_interrupt_test_time=0; /* Execute the next instruction. */ if (state->NextInstr < PRIMEPIPE) { decoded = state->decoded; loaded = state->loaded; pc = state->pc; //chy 2006-04-12, for ICE debug decoded_addr=state->decoded_addr; loaded_addr=state->loaded_addr; } 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; //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,decoded_addr); decoded = loaded; decoded_addr=loaded_addr; loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); loaded_addr=pc + (isize * 2); if(have_bp) goto TEST_EMULATE; break; case NONSEQ: /* Advance the pipeline, and an N cycle. */ state->Reg[15] += isize; pc += isize; instr = decoded; //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,decoded_addr); decoded = loaded; decoded_addr=loaded_addr; loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize); loaded_addr=pc + (isize * 2); NORMALCYCLE; if(have_bp) goto TEST_EMULATE; break; case PCINCEDSEQ: /* Program counter advanced, and an S cycle. */ pc += isize; instr = decoded; //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,decoded_addr); decoded = loaded; decoded_addr=loaded_addr; loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); loaded_addr=pc + (isize * 2); NORMALCYCLE; if(have_bp) goto TEST_EMULATE; break; case PCINCEDNONSEQ: /* Program counter advanced, and an N cycle. */ pc += isize; instr = decoded; //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,decoded_addr); decoded = loaded; decoded_addr=loaded_addr; loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize); loaded_addr=pc + (isize * 2); NORMALCYCLE; if(have_bp) goto TEST_EMULATE; 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); //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,pc); decoded = ARMul_ReLoadInstr (state, pc + isize, isize); decoded_addr=pc+isize; loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize); loaded_addr=pc + isize * 2; NORMALCYCLE; if(have_bp) goto TEST_EMULATE; 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); //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,pc); decoded = ARMul_LoadInstrS (state, pc + (isize), isize); decoded_addr=pc+isize; loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); loaded_addr=pc + isize * 2; NORMALCYCLE; if(have_bp) goto TEST_EMULATE; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -