got rid of 'src' folders in each sub-project

This commit is contained in:
bunnei 2014-04-08 19:25:03 -04:00
parent 03c245345e
commit 63e46abdb8
148 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,86 @@
/**
* Copyright (C) 2013 Citrus Emulator
*
* @file arm_interpreter.h
* @author bunnei
* @date 2014-04-04
* @brief ARM interface instance for SkyEye interprerer
*
* @section LICENSE
* 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 at
* http://www.gnu.org/copyleft/gpl.html
*
* Official project repository can be found at:
* http://code.google.com/p/gekko-gc-emu/
*/
#include "arm_interpreter.h"
const static cpu_config_t s_arm11_cpu_info = {
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
};
ARM_Interpreter::ARM_Interpreter() {
state = new ARMul_State;
ARMul_EmulateInit();
ARMul_NewState(state);
state->abort_model = 0;
state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
state->bigendSig = LOW;
ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
state->lateabtSig = LOW;
mmu_init(state);
// Reset the core to initial state
ARMul_Reset(state);
state->NextInstr = 0;
state->Emulate = 3;
state->pc = state->Reg[15] = 0x00000000;
state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
}
void ARM_Interpreter::SetPC(u32 pc) {
state->pc = state->Reg[15] = pc;
}
u32 ARM_Interpreter::PC() {
return state->pc;
}
u32 ARM_Interpreter::Reg(int index){
return state->Reg[index];
}
u32 ARM_Interpreter::CPSR() {
return state->Cpsr;
}
ARM_Interpreter::~ARM_Interpreter() {
delete state;
}
void ARM_Interpreter::ExecuteInstruction() {
state->step++;
state->cycle++;
state->EndCondition = 0;
state->stop_simulator = 0;
state->NextInstr = RESUME;
state->last_pc = state->Reg[15];
state->Reg[15] = ARMul_DoInstr(state);
state->Cpsr = ((state->Cpsr & 0x0fffffdf) | (state->NFlag << 31) | (state->ZFlag << 30) |
(state->CFlag << 29) | (state->VFlag << 28) | (state->TFlag << 5));
FLUSHPIPE;
}

View file

@ -0,0 +1,57 @@
/**
* Copyright (C) 2013 Citrus Emulator
*
* @file arm_interpreter.h
* @author bunnei
* @date 2014-04-04
* @brief ARM interface instance for SkyEye interprerer
*
* @section LICENSE
* 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 at
* http://www.gnu.org/copyleft/gpl.html
*
* Official project repository can be found at:
* http://code.google.com/p/gekko-gc-emu/
*/
#pragma once
#include "common.h"
#include "common_types.h"
#include "arm/arm_interface.h"
#include "arm/interpreter/armdefs.h"
#include "arm/interpreter/armemu.h"
class ARM_Interpreter : virtual public ARM_Interface {
public:
ARM_Interpreter();
~ARM_Interpreter();
void ExecuteInstruction();
void SetPC(u32 pc);
u32 PC();
u32 Reg(int index);
u32 CPSR();
u64 GetTicks() {
return ARMul_Time(state);
}
private:
ARMul_State* state;
DISALLOW_COPY_AND_ASSIGN(ARM_Interpreter);
};

View file

@ -0,0 +1,103 @@
#ifndef __ARM_REGFORMAT_H__
#define __ARM_REGFORMAT_H__
enum arm_regno{
R0 = 0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
R13,
LR,
R15, //PC,
CPSR_REG,
SPSR_REG,
#if 1
PHYS_PC,
R13_USR,
R14_USR,
R13_SVC,
R14_SVC,
R13_ABORT,
R14_ABORT,
R13_UNDEF,
R14_UNDEF,
R13_IRQ,
R14_IRQ,
R8_FIRQ,
R9_FIRQ,
R10_FIRQ,
R11_FIRQ,
R12_FIRQ,
R13_FIRQ,
R14_FIRQ,
SPSR_INVALID1,
SPSR_INVALID2,
SPSR_SVC,
SPSR_ABORT,
SPSR_UNDEF,
SPSR_IRQ,
SPSR_FIRQ,
MODE_REG, /* That is the cpsr[4 : 0], just for calculation easily */
BANK_REG,
EXCLUSIVE_TAG,
EXCLUSIVE_STATE,
EXCLUSIVE_RESULT,
CP15_BASE,
CP15_C0 = CP15_BASE,
CP15_C0_C0 = CP15_C0,
CP15_MAIN_ID = CP15_C0_C0,
CP15_CACHE_TYPE,
CP15_TCM_STATUS,
CP15_TLB_TYPE,
CP15_C0_C1,
CP15_PROCESSOR_FEATURE_0 = CP15_C0_C1,
CP15_PROCESSOR_FEATURE_1,
CP15_DEBUG_FEATURE_0,
CP15_AUXILIARY_FEATURE_0,
CP15_C1_C0,
CP15_CONTROL = CP15_C1_C0,
CP15_AUXILIARY_CONTROL,
CP15_COPROCESSOR_ACCESS_CONTROL,
CP15_C2,
CP15_C2_C0 = CP15_C2,
CP15_TRANSLATION_BASE = CP15_C2_C0,
CP15_TRANSLATION_BASE_TABLE_0 = CP15_TRANSLATION_BASE,
CP15_TRANSLATION_BASE_TABLE_1,
CP15_TRANSLATION_BASE_CONTROL,
CP15_DOMAIN_ACCESS_CONTROL,
CP15_RESERVED,
/* Fault status */
CP15_FAULT_STATUS,
CP15_INSTR_FAULT_STATUS,
CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
CP15_INST_FSR,
/* Fault Address register */
CP15_FAULT_ADDRESS,
CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
CP15_WFAR,
CP15_IFAR,
CP15_PID,
CP15_CONTEXT_ID,
CP15_THREAD_URO,
CP15_TLB_FAULT_ADDR, /* defined by SkyEye */
CP15_TLB_FAULT_STATUS, /* defined by SkyEye */
/* VFP registers */
VFP_BASE,
VFP_FPSID = VFP_BASE,
VFP_FPSCR,
VFP_FPEXC,
#endif
MAX_REG_NUM,
};
#define VFP_OFFSET(x) (x - VFP_BASE)
#endif

View file

@ -0,0 +1,83 @@
/*
* arm
* armcpu.h
*
* Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ARM_CPU_H__
#define __ARM_CPU_H__
//#include <skyeye_thread.h>
//#include <skyeye_obj.h>
//#include <skyeye_mach.h>
//#include <skyeye_exec.h>
#include <stddef.h>
#include <stdio.h>
#include "thread.h"
typedef struct ARM_CPU_State_s {
ARMul_State * core;
uint32_t core_num;
/* The core id that boot from
*/
uint32_t boot_core_id;
}ARM_CPU_State;
//static ARM_CPU_State* get_current_cpu(){
// machine_config_t* mach = get_current_mach();
// /* Casting a conf_obj_t to ARM_CPU_State type */
// ARM_CPU_State* cpu = (ARM_CPU_State*)mach->cpu_data->obj;
//
// return cpu;
//}
/**
* @brief Get the core instance boot from
*
* @return
*/
//static ARMul_State* get_boot_core(){
// ARM_CPU_State* cpu = get_current_cpu();
// return &cpu->core[cpu->boot_core_id];
//}
/**
* @brief Get the instance of running core
*
* @return the core instance
*/
//static ARMul_State* get_current_core(){
// /* Casting a conf_obj_t to ARM_CPU_State type */
// int id = Common::CurrentThreadId();
// /* If thread is not in running mode, we should give the boot core */
// if(get_thread_state(id) != Running_state){
// return get_boot_core();
// }
// /* Judge if we are running in paralell or sequenial */
// if(thread_exist(id)){
// conf_object_t* conf_obj = get_current_exec_priv(id);
// return (ARMul_State*)get_cast_conf_obj(conf_obj, "arm_core_t");
// }
//
// return NULL;
//}
#define CURRENT_CORE get_current_core()
#endif

View file

@ -0,0 +1,934 @@
/* armdefs.h -- ARMulator common definitions: 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. */
#ifndef _ARMDEFS_H_
#define _ARMDEFS_H_
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#if EMU_PLATFORM == PLATFORM_WINDOWS
#include <windows.h>
#endif
//teawater add for arm2x86 2005.02.14-------------------------------------------
// koodailar remove it for mingw 2005.12.18----------------
//anthonylee modify it for portable 2007.01.30
//#include "portable/mman.h"
#include "arm_regformat.h"
#include "platform.h"
#include "skyeye_defs.h"
//AJ2D--------------------------------------------------------------------------
//teawater add for arm2x86 2005.07.03-------------------------------------------
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if EMU_PLATFORM == PLATFORM_LINUX
#include <unistd.h>
#endif
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <memory_space.h>
//AJ2D--------------------------------------------------------------------------
#if 0
#if 0
#define DIFF_STATE 1
#define __FOLLOW_MODE__ 0
#else
#define DIFF_STATE 0
#define __FOLLOW_MODE__ 1
#endif
#endif
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
#define LOW 0
#define HIGH 1
#define LOWHIGH 1
#define HIGHLOW 2
#ifndef u8
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
#define u64 unsigned long long
#endif /*u8 */
//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
#include <signal.h>
#include "platform.h"
#if EMU_PLATFORM == PLATFORM_LINUX
#include <sys/time.h>
#endif
//#define DBCT_TEST_SPEED
#define DBCT_TEST_SPEED_SEC 10
//AJ2D--------------------------------------------------------------------------
//teawater add compile switch for DBCT GDB RSP function 2005.10.21--------------
//#define DBCT_GDBRSP
//AJ2D--------------------------------------------------------------------------
//#include <skyeye_defs.h>
//#include <skyeye_types.h>
#define ARM_BYTE_TYPE 0
#define ARM_HALFWORD_TYPE 1
#define ARM_WORD_TYPE 2
//the define of cachetype
#define NONCACHE 0
#define DATACACHE 1
#define INSTCACHE 2
#ifndef __STDC__
typedef char *VoidStar;
#endif
typedef unsigned long long ARMdword; /* must be 64 bits wide */
typedef unsigned int ARMword; /* must be 32 bits wide */
typedef unsigned char ARMbyte; /* must be 8 bits wide */
typedef unsigned short ARMhword; /* must be 16 bits wide */
typedef struct ARMul_State ARMul_State;
typedef struct ARMul_io ARMul_io;
typedef struct ARMul_Energy ARMul_Energy;
//teawater add for arm2x86 2005.06.24-------------------------------------------
#include <stdint.h>
//AJ2D--------------------------------------------------------------------------
/*
//chy 2005-05-11
#ifndef __CYGWIN__
//teawater add for arm2x86 2005.02.14-------------------------------------------
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int u32;
#if defined (__x86_64__)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
////AJ2D--------------------------------------------------------------------------
#endif
*/
#include "armmmu.h"
//#include "lcd/skyeye_lcd.h"
//#include "skyeye.h"
//#include "skyeye_device.h"
//#include "net/skyeye_net.h"
//#include "skyeye_config.h"
typedef unsigned ARMul_CPInits (ARMul_State * state);
typedef unsigned ARMul_CPExits (ARMul_State * state);
typedef unsigned ARMul_LDCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword value);
typedef unsigned ARMul_STCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value);
typedef unsigned ARMul_MRCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value);
typedef unsigned ARMul_MCRs (ARMul_State * state, unsigned type,
ARMword instr, ARMword value);
typedef unsigned ARMul_MRRCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value1, ARMword * value2);
typedef unsigned ARMul_MCRRs (ARMul_State * state, unsigned type,
ARMword instr, ARMword value1, ARMword value2);
typedef unsigned ARMul_CDPs (ARMul_State * state, unsigned type,
ARMword instr);
typedef unsigned ARMul_CPReads (ARMul_State * state, unsigned reg,
ARMword * value);
typedef unsigned ARMul_CPWrites (ARMul_State * state, unsigned reg,
ARMword value);
//added by ksh,2004-3-5
struct ARMul_io
{
ARMword *instr; //to display the current interrupt state
ARMword *net_flag; //to judge if network is enabled
ARMword *net_int; //netcard interrupt
//ywc,2004-04-01
ARMword *ts_int;
ARMword *ts_is_enable;
ARMword *ts_addr_begin;
ARMword *ts_addr_end;
ARMword *ts_buffer;
};
/* added by ksh,2004-11-26,some energy profiling */
struct ARMul_Energy
{
int energy_prof; /* <tktan> BUG200103282109 : for energy profiling */
int enable_func_energy; /* <tktan> BUG200105181702 */
char *func_energy;
int func_display; /* <tktan> BUG200103311509 : for function call display */
int func_disp_start; /* <tktan> BUG200104191428 : to start func profiling */
char *start_func; /* <tktan> BUG200104191428 */
FILE *outfile; /* <tktan> BUG200105201531 : direct console to file */
long long tcycle, pcycle;
float t_energy;
void *cur_task; /* <tktan> BUG200103291737 */
long long t_mem_cycle, t_idle_cycle, t_uart_cycle;
long long p_mem_cycle, p_idle_cycle, p_uart_cycle;
long long p_io_update_tcycle;
/*record CCCR,to get current core frequency */
ARMword cccr;
};
#if 0
#define MAX_BANK 8
#define MAX_STR 1024
typedef struct mem_bank
{
ARMword (*read_byte) (ARMul_State * state, ARMword addr);
void (*write_byte) (ARMul_State * state, ARMword addr, ARMword data);
ARMword (*read_halfword) (ARMul_State * state, ARMword addr);
void (*write_halfword) (ARMul_State * state, ARMword addr,
ARMword data);
ARMword (*read_word) (ARMul_State * state, ARMword addr);
void (*write_word) (ARMul_State * state, ARMword addr, ARMword data);
unsigned int addr, len;
char filename[MAX_STR];
unsigned type; //chy 2003-09-21: maybe io,ram,rom
} mem_bank_t;
typedef struct
{
int bank_num;
int current_num; /*current num of bank */
mem_bank_t mem_banks[MAX_BANK];
} mem_config_t;
#endif
#define VFP_REG_NUM 64
struct ARMul_State
{
ARMword Emulate; /* to start and stop emulation */
unsigned EndCondition; /* reason for stopping */
unsigned ErrorCode; /* type of illegal instruction */
/* Order of the following register should not be modified */
ARMword Reg[16]; /* the current register file */
ARMword Cpsr; /* the current psr */
ARMword Spsr_copy;
ARMword phys_pc;
ARMword Reg_usr[2];
ARMword Reg_svc[2]; /* R13_SVC R14_SVC */
ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */
ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */
ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */
ARMword Reg_firq[7]; /* R8---R14 FIRQ */
ARMword Spsr[7]; /* the exception psr's */
ARMword Mode; /* the current mode */
ARMword Bank; /* the current register bank */
ARMword exclusive_tag;
ARMword exclusive_state;
ARMword exclusive_result;
ARMword CP15[VFP_BASE - CP15_BASE];
ARMword VFP[3]; /* FPSID, FPSCR, and FPEXC */
/* VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
and only 32 singleword registers are accessible (S0-S31). */
ARMword ExtReg[VFP_REG_NUM];
/* ---- End of the ordered registers ---- */
ARMword RegBank[7][16]; /* all the registers */
//chy:2003-08-19, used in arm xscale
/* 40 bit accumulator. We always keep this 64 bits wide,
and move only 40 bits out of it in an MRA insn. */
ARMdword Accumulator;
ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */
unsigned long long int icounter, debug_icounter, kernel_icounter;
unsigned int shifter_carry_out;
//ARMword translate_pc;
/* add armv6 flags dyf:2010-08-09 */
ARMword GEFlag, EFlag, AFlag, QFlags;
//chy:2003-08-19, used in arm v5e|xscale
ARMword SFlag;
#ifdef MODET
ARMword TFlag; /* Thumb state */
#endif
ARMword instr, pc, temp; /* saved register state */
ARMword loaded, decoded; /* saved pipeline state */
//chy 2006-04-12 for ICE breakpoint
ARMword loaded_addr, decoded_addr; /* saved pipeline state addr*/
unsigned int NumScycles, NumNcycles, NumIcycles, NumCcycles, NumFcycles; /* emulated cycles used */
unsigned long long NumInstrs; /* the number of instructions executed */
unsigned NextInstr;
unsigned VectorCatch; /* caught exception mask */
unsigned CallDebug; /* set to call the debugger */
unsigned CanWatch; /* set by memory interface if its willing to suffer the
overhead of checking for watchpoints on each memory
access */
unsigned int StopHandle;
char *CommandLine; /* Command Line from ARMsd */
ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */
ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */
ARMul_LDCs *LDC[16]; /* LDC instruction */
ARMul_STCs *STC[16]; /* STC instruction */
ARMul_MRCs *MRC[16]; /* MRC instruction */
ARMul_MCRs *MCR[16]; /* MCR instruction */
ARMul_MRRCs *MRRC[16]; /* MRRC instruction */
ARMul_MCRRs *MCRR[16]; /* MCRR instruction */
ARMul_CDPs *CDP[16]; /* CDP instruction */
ARMul_CPReads *CPRead[16]; /* Read CP register */
ARMul_CPWrites *CPWrite[16]; /* Write CP register */
unsigned char *CPData[16]; /* Coprocessor data */
unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */
unsigned EventSet; /* the number of events in the queue */
unsigned int Now; /* time to the nearest cycle */
struct EventNode **EventPtr; /* the event list */
unsigned Debug; /* show instructions as they are executed */
unsigned NresetSig; /* reset the processor */
unsigned NfiqSig;
unsigned NirqSig;
unsigned abortSig;
unsigned NtransSig;
unsigned bigendSig;
unsigned prog32Sig;
unsigned data32Sig;
unsigned syscallSig;
/* 2004-05-09 chy
----------------------------------------------------------
read ARM Architecture Reference Manual
2.6.5 Data Abort
There are three Abort Model in ARM arch.
Early Abort Model: used in some ARMv3 and earlier implementations. In this
model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
the base register was unchanged for all other instructions. (oldest)
Base Restored Abort Model: If a Data Abort occurs in an instruction which
specifies base register writeback, the value in the base register is
unchanged. (strongarm, xscale)
Base Updated Abort Model: If a Data Abort occurs in an instruction which
specifies base register writeback, the base register writeback still occurs.
(arm720T)
read PART B
chap2 The System Control Coprocessor CP15
2.4 Register1:control register
L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
processor could be configured:
0=early Abort Model Selected(now obsolete)
1=Late Abort Model selceted(same as Base Updated Abort Model)
on later processors, this bit reads as 1 and ignores writes.
-------------------------------------------------------------
So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
if lateabtSig=0, then it means Base Restored Abort Model
*/
unsigned lateabtSig;
ARMword Vector; /* synthesize aborts in cycle modes */
ARMword Aborted; /* sticky flag for aborts */
ARMword Reseted; /* sticky flag for Reset */
ARMword Inted, LastInted; /* sticky flags for interrupts */
ARMword Base; /* extra hand for base writeback */
ARMword AbortAddr; /* to keep track of Prefetch aborts */
const struct Dbg_HostosInterface *hostif;
int verbose; /* non-zero means print various messages like the banner */
mmu_state_t mmu;
int mmu_inited;
//mem_state_t mem;
/*remove io_state to skyeye_mach_*.c files */
//io_state_t io;
/* point to a interrupt pending register. now for skyeye-ne2k.c
* later should move somewhere. e.g machine_config_t*/
//chy: 2003-08-11, for different arm core type
unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */
unsigned is_v5; /* Are we emulating a v5 architecture ? */
unsigned is_v5e; /* Are we emulating a v5e architecture ? */
unsigned is_v6; /* Are we emulating a v6 architecture ? */
unsigned is_v7; /* Are we emulating a v7 architecture ? */
unsigned is_XScale; /* Are we emulating an XScale architecture ? */
unsigned is_iWMMXt; /* Are we emulating an iWMMXt co-processor ? */
unsigned is_ep9312; /* Are we emulating a Cirrus Maverick co-processor ? */
//chy 2005-09-19
unsigned is_pxa27x; /* Are we emulating a Intel PXA27x co-processor ? */
//chy: seems only used in xscale's CP14
unsigned int LastTime; /* Value of last call to ARMul_Time() */
ARMword CP14R0_CCD; /* used to count 64 clock cycles with CP14 R0 bit 3 set */
//added by ksh:for handle different machs io 2004-3-5
ARMul_io mach_io;
/*added by ksh,2004-11-26,some energy profiling*/
ARMul_Energy energy;
//teawater add for next_dis 2004.10.27-----------------------
int disassemble;
//AJ2D------------------------------------------
//teawater add for arm2x86 2005.02.15-------------------------------------------
u32 trap;
u32 tea_break_addr;
u32 tea_break_ok;
int tea_pc;
//AJ2D--------------------------------------------------------------------------
//teawater add for arm2x86 2005.07.03-------------------------------------------
/*
* 2007-01-24 removed the term-io functions by Anthony Lee,
* moved to "device/uart/skyeye_uart_stdio.c".
*/
//AJ2D--------------------------------------------------------------------------
//teawater add for arm2x86 2005.07.05-------------------------------------------
//arm_arm A2-18
int abort_model; //0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
//AJ2D--------------------------------------------------------------------------
//teawater change for return if running tb dirty 2005.07.09---------------------
void *tb_now;
//AJ2D--------------------------------------------------------------------------
//teawater add for record reg value to ./reg.txt 2005.07.10---------------------
FILE *tea_reg_fd;
//AJ2D--------------------------------------------------------------------------
/*added by ksh in 2005-10-1*/
cpu_config_t *cpu;
//mem_config_t *mem_bank;
/* added LPC remap function */
int vector_remap_flag;
u32 vector_remap_addr;
u32 vector_remap_size;
u32 step;
u32 cycle;
int stop_simulator;
conf_object_t *dyncom_cpu;
//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
#ifdef DBCT_TEST_SPEED
uint64_t instr_count;
#endif //DBCT_TEST_SPEED
// FILE * state_log;
//diff log
//#if DIFF_STATE
FILE * state_log;
//#endif
/* monitored memory for exclusice access */
ARMword exclusive_tag_array[128];
/* 1 means exclusive access and 0 means open access */
ARMword exclusive_access_state;
memory_space_intf space;
u32 CurrInstr;
u32 last_pc; /* the last pc executed */
u32 last_instr; /* the last inst executed */
u32 WriteAddr[17];
u32 WriteData[17];
u32 WritePc[17];
u32 CurrWrite;
};
#define DIFF_WRITE 0
typedef ARMul_State arm_core_t;
#define ResetPin NresetSig
#define FIQPin NfiqSig
#define IRQPin NirqSig
#define AbortPin abortSig
#define TransPin NtransSig
#define BigEndPin bigendSig
#define Prog32Pin prog32Sig
#define Data32Pin data32Sig
#define LateAbortPin lateabtSig
/***************************************************************************\
* Types of ARM we know about *
\***************************************************************************/
/* The bitflags */
#define ARM_Fix26_Prop 0x01
#define ARM_Nexec_Prop 0x02
#define ARM_Debug_Prop 0x10
#define ARM_Isync_Prop ARM_Debug_Prop
#define ARM_Lock_Prop 0x20
//chy 2003-08-11
#define ARM_v4_Prop 0x40
#define ARM_v5_Prop 0x80
/*jeff.du 2010-08-05 */
#define ARM_v6_Prop 0xc0
#define ARM_v5e_Prop 0x100
#define ARM_XScale_Prop 0x200
#define ARM_ep9312_Prop 0x400
#define ARM_iWMMXt_Prop 0x800
//chy 2005-09-19
#define ARM_PXA27X_Prop 0x1000
#define ARM_v7_Prop 0x2000
/* ARM2 family */
#define ARM2 (ARM_Fix26_Prop)
#define ARM2as ARM2
#define ARM61 ARM2
#define ARM3 ARM2
#ifdef ARM60 /* previous definition in armopts.h */
#undef ARM60
#endif
/* ARM6 family */
#define ARM6 (ARM_Lock_Prop)
#define ARM60 ARM6
#define ARM600 ARM6
#define ARM610 ARM6
#define ARM620 ARM6
/***************************************************************************\
* Macros to extract instruction fields *
\***************************************************************************/
#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */
#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */
#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */
/***************************************************************************\
* The hardware vector addresses *
\***************************************************************************/
#define ARMResetV 0L
#define ARMUndefinedInstrV 4L
#define ARMSWIV 8L
#define ARMPrefetchAbortV 12L
#define ARMDataAbortV 16L
#define ARMAddrExceptnV 20L
#define ARMIRQV 24L
#define ARMFIQV 28L
#define ARMErrorV 32L /* This is an offset, not an address ! */
#define ARMul_ResetV ARMResetV
#define ARMul_UndefinedInstrV ARMUndefinedInstrV
#define ARMul_SWIV ARMSWIV
#define ARMul_PrefetchAbortV ARMPrefetchAbortV
#define ARMul_DataAbortV ARMDataAbortV
#define ARMul_AddrExceptnV ARMAddrExceptnV
#define ARMul_IRQV ARMIRQV
#define ARMul_FIQV ARMFIQV
/***************************************************************************\
* Mode and Bank Constants *
\***************************************************************************/
#define USER26MODE 0L
#define FIQ26MODE 1L
#define IRQ26MODE 2L
#define SVC26MODE 3L
#define USER32MODE 16L
#define FIQ32MODE 17L
#define IRQ32MODE 18L
#define SVC32MODE 19L
#define ABORT32MODE 23L
#define UNDEF32MODE 27L
//chy 2006-02-15 add system32 mode
#define SYSTEM32MODE 31L
#define ARM32BITMODE (state->Mode > 3)
#define ARM26BITMODE (state->Mode <= 3)
#define ARMMODE (state->Mode)
#define ARMul_MODEBITS 0x1fL
#define ARMul_MODE32BIT ARM32BITMODE
#define ARMul_MODE26BIT ARM26BITMODE
#define USERBANK 0
#define FIQBANK 1
#define IRQBANK 2
#define SVCBANK 3
#define ABORTBANK 4
#define UNDEFBANK 5
#define DUMMYBANK 6
#define SYSTEMBANK USERBANK
#define BANK_CAN_ACCESS_SPSR(bank) \
((bank) != USERBANK && (bank) != SYSTEMBANK && (bank) != DUMMYBANK)
/***************************************************************************\
* Definitons of things in the emulator *
\***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
extern void ARMul_EmulateInit (void);
extern void ARMul_Reset (ARMul_State * state);
#ifdef __cplusplus
}
#endif
extern ARMul_State *ARMul_NewState (ARMul_State * state);
extern ARMword ARMul_DoProg (ARMul_State * state);
extern ARMword ARMul_DoInstr (ARMul_State * state);
/***************************************************************************\
* Definitons of things for event handling *
\***************************************************************************/
extern void ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
unsigned (*func) ());
extern void ARMul_EnvokeEvent (ARMul_State * state);
extern unsigned int ARMul_Time (ARMul_State * state);
/***************************************************************************\
* Useful support routines *
\***************************************************************************/
extern ARMword ARMul_GetReg (ARMul_State * state, unsigned mode,
unsigned reg);
extern void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
ARMword value);
extern ARMword ARMul_GetPC (ARMul_State * state);
extern ARMword ARMul_GetNextPC (ARMul_State * state);
extern void ARMul_SetPC (ARMul_State * state, ARMword value);
extern ARMword ARMul_GetR15 (ARMul_State * state);
extern void ARMul_SetR15 (ARMul_State * state, ARMword value);
extern ARMword ARMul_GetCPSR (ARMul_State * state);
extern void ARMul_SetCPSR (ARMul_State * state, ARMword value);
extern ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
extern void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
/***************************************************************************\
* Definitons of things to handle aborts *
\***************************************************************************/
extern void ARMul_Abort (ARMul_State * state, ARMword address);
#ifdef MODET
#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */
#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
state->AbortAddr = (address & (state->TFlag ? ~1L : ~3L))
#else
#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */
#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
state->AbortAddr = (address & ~3L)
#endif
#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \
state->Aborted = ARMul_DataAbortV ;
#define ARMul_CLEARABORT state->abortSig = LOW
/***************************************************************************\
* Definitons of things in the memory interface *
\***************************************************************************/
extern unsigned ARMul_MemoryInit (ARMul_State * state,
unsigned int initmemsize);
extern void ARMul_MemoryExit (ARMul_State * state);
extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address,
ARMword isize);
extern ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address,
ARMword isize);
#ifdef __cplusplus
extern "C" {
#endif
extern ARMword ARMul_ReLoadInstr (ARMul_State * state, ARMword address,
ARMword isize);
#ifdef __cplusplus
}
#endif
extern ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadByte (ARMul_State * state, ARMword address);
extern void ARMul_StoreWordS (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreWordN (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreHalfWord (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreByte (ARMul_State * state, ARMword address,
ARMword data);
extern ARMword ARMul_SwapWord (ARMul_State * state, ARMword address,
ARMword data);
extern ARMword ARMul_SwapByte (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_Icycles (ARMul_State * state, unsigned number,
ARMword address);
extern void ARMul_Ccycles (ARMul_State * state, unsigned number,
ARMword address);
extern ARMword ARMul_ReadWord (ARMul_State * state, ARMword address);
extern ARMword ARMul_ReadByte (ARMul_State * state, ARMword address);
extern void ARMul_WriteWord (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_WriteByte (ARMul_State * state, ARMword address,
ARMword data);
extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,
ARMword, ARMword, ARMword, ARMword, ARMword,
ARMword, ARMword, ARMword);
/***************************************************************************\
* Definitons of things in the co-processor interface *
\***************************************************************************/
#define ARMul_FIRST 0
#define ARMul_TRANSFER 1
#define ARMul_BUSY 2
#define ARMul_DATA 3
#define ARMul_INTERRUPT 4
#define ARMul_DONE 0
#define ARMul_CANT 1
#define ARMul_INC 3
#define ARMul_CP13_R0_FIQ 0x1
#define ARMul_CP13_R0_IRQ 0x2
#define ARMul_CP13_R8_PMUS 0x1
#define ARMul_CP14_R0_ENABLE 0x0001
#define ARMul_CP14_R0_CLKRST 0x0004
#define ARMul_CP14_R0_CCD 0x0008
#define ARMul_CP14_R0_INTEN0 0x0010
#define ARMul_CP14_R0_INTEN1 0x0020
#define ARMul_CP14_R0_INTEN2 0x0040
#define ARMul_CP14_R0_FLAG0 0x0100
#define ARMul_CP14_R0_FLAG1 0x0200
#define ARMul_CP14_R0_FLAG2 0x0400
#define ARMul_CP14_R10_MOE_IB 0x0004
#define ARMul_CP14_R10_MOE_DB 0x0008
#define ARMul_CP14_R10_MOE_BT 0x000c
#define ARMul_CP15_R1_ENDIAN 0x0080
#define ARMul_CP15_R1_ALIGN 0x0002
#define ARMul_CP15_R5_X 0x0400
#define ARMul_CP15_R5_ST_ALIGN 0x0001
#define ARMul_CP15_R5_IMPRE 0x0406
#define ARMul_CP15_R5_MMU_EXCPT 0x0400
#define ARMul_CP15_DBCON_M 0x0100
#define ARMul_CP15_DBCON_E1 0x000c
#define ARMul_CP15_DBCON_E0 0x0003
extern unsigned ARMul_CoProInit (ARMul_State * state);
extern void ARMul_CoProExit (ARMul_State * state);
extern void ARMul_CoProAttach (ARMul_State * state, unsigned number,
ARMul_CPInits * init, ARMul_CPExits * exit,
ARMul_LDCs * ldc, ARMul_STCs * stc,
ARMul_MRCs * mrc, ARMul_MCRs * mcr,
ARMul_MRRCs * mrrc, ARMul_MCRRs * mcrr,
ARMul_CDPs * cdp,
ARMul_CPReads * read, ARMul_CPWrites * write);
extern void ARMul_CoProDetach (ARMul_State * state, unsigned number);
/***************************************************************************\
* Definitons of things in the host environment *
\***************************************************************************/
extern unsigned ARMul_OSInit (ARMul_State * state);
extern void ARMul_OSExit (ARMul_State * state);
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
#ifdef __cplusplus
}
#endif
extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,
ARMword pc);
extern int rdi_log;
/***************************************************************************\
* Host-dependent stuff *
\***************************************************************************/
#ifdef macintosh
pascal void SpinCursor (short increment); /* copied from CursorCtl.h */
# define HOURGLASS SpinCursor( 1 )
# define HOURGLASS_RATE 1023 /* 2^n - 1 */
#endif
//teawater add for arm2x86 2005.02.14-------------------------------------------
/*ywc 2005-03-31*/
/*
#include "arm2x86.h"
#include "arm2x86_dp.h"
#include "arm2x86_movl.h"
#include "arm2x86_psr.h"
#include "arm2x86_shift.h"
#include "arm2x86_mem.h"
#include "arm2x86_mul.h"
#include "arm2x86_test.h"
#include "arm2x86_other.h"
#include "list.h"
#include "tb.h"
*/
#define EQ 0
#define NE 1
#define CS 2
#define CC 3
#define MI 4
#define PL 5
#define VS 6
#define VC 7
#define HI 8
#define LS 9
#define GE 10
#define LT 11
#define GT 12
#define LE 13
#define AL 14
#define NV 15
#ifndef NFLAG
#define NFLAG state->NFlag
#endif //NFLAG
#ifndef ZFLAG
#define ZFLAG state->ZFlag
#endif //ZFLAG
#ifndef CFLAG
#define CFLAG state->CFlag
#endif //CFLAG
#ifndef VFLAG
#define VFLAG state->VFlag
#endif //VFLAG
#ifndef IFLAG
#define IFLAG (state->IFFlags >> 1)
#endif //IFLAG
#ifndef FFLAG
#define FFLAG (state->IFFlags & 1)
#endif //FFLAG
#ifndef IFFLAGS
#define IFFLAGS state->IFFlags
#endif //VFLAG
#define FLAG_MASK 0xf0000000
#define NBIT_SHIFT 31
#define ZBIT_SHIFT 30
#define CBIT_SHIFT 29
#define VBIT_SHIFT 28
#ifdef DBCT
//teawater change for local tb branch directly jump 2005.10.18------------------
#include "dbct/list.h"
#include "dbct/arm2x86.h"
#include "dbct/arm2x86_dp.h"
#include "dbct/arm2x86_movl.h"
#include "dbct/arm2x86_psr.h"
#include "dbct/arm2x86_shift.h"
#include "dbct/arm2x86_mem.h"
#include "dbct/arm2x86_mul.h"
#include "dbct/arm2x86_test.h"
#include "dbct/arm2x86_other.h"
#include "dbct/arm2x86_coproc.h"
#include "dbct/tb.h"
#endif
//AJ2D--------------------------------------------------------------------------
//AJ2D--------------------------------------------------------------------------
#define SKYEYE_OUTREGS(fd) { fprintf ((fd), "R %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,C %x,S %x,%x,%x,%x,%x,%x,%x,M %x,B %x,E %x,I %x,P %x,T %x,L %x,D %x,",\
state->Reg[0],state->Reg[1],state->Reg[2],state->Reg[3], \
state->Reg[4],state->Reg[5],state->Reg[6],state->Reg[7], \
state->Reg[8],state->Reg[9],state->Reg[10],state->Reg[11], \
state->Reg[12],state->Reg[13],state->Reg[14],state->Reg[15], \
state->Cpsr, state->Spsr[0], state->Spsr[1], state->Spsr[2],\
state->Spsr[3],state->Spsr[4], state->Spsr[5], state->Spsr[6],\
state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\
state->temp,state->loaded,state->decoded);}
#define SKYEYE_OUTMOREREGS(fd) { fprintf ((fd),"\
RUs %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
RF %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
RI %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
RS %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
RA %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\
state->RegBank[0][0],state->RegBank[0][1],state->RegBank[0][2],state->RegBank[0][3], \
state->RegBank[0][4],state->RegBank[0][5],state->RegBank[0][6],state->RegBank[0][7], \
state->RegBank[0][8],state->RegBank[0][9],state->RegBank[0][10],state->RegBank[0][11], \
state->RegBank[0][12],state->RegBank[0][13],state->RegBank[0][14],state->RegBank[0][15], \
state->RegBank[1][0],state->RegBank[1][1],state->RegBank[1][2],state->RegBank[1][3], \
state->RegBank[1][4],state->RegBank[1][5],state->RegBank[1][6],state->RegBank[1][7], \
state->RegBank[1][8],state->RegBank[1][9],state->RegBank[1][10],state->RegBank[1][11], \
state->RegBank[1][12],state->RegBank[1][13],state->RegBank[1][14],state->RegBank[1][15], \
state->RegBank[2][0],state->RegBank[2][1],state->RegBank[2][2],state->RegBank[2][3], \
state->RegBank[2][4],state->RegBank[2][5],state->RegBank[2][6],state->RegBank[2][7], \
state->RegBank[2][8],state->RegBank[2][9],state->RegBank[2][10],state->RegBank[2][11], \
state->RegBank[2][12],state->RegBank[2][13],state->RegBank[2][14],state->RegBank[2][15], \
state->RegBank[3][0],state->RegBank[3][1],state->RegBank[3][2],state->RegBank[3][3], \
state->RegBank[3][4],state->RegBank[3][5],state->RegBank[3][6],state->RegBank[3][7], \
state->RegBank[3][8],state->RegBank[3][9],state->RegBank[3][10],state->RegBank[3][11], \
state->RegBank[3][12],state->RegBank[3][13],state->RegBank[3][14],state->RegBank[3][15], \
state->RegBank[4][0],state->RegBank[4][1],state->RegBank[4][2],state->RegBank[4][3], \
state->RegBank[4][4],state->RegBank[4][5],state->RegBank[4][6],state->RegBank[4][7], \
state->RegBank[4][8],state->RegBank[4][9],state->RegBank[4][10],state->RegBank[4][11], \
state->RegBank[4][12],state->RegBank[4][13],state->RegBank[4][14],state->RegBank[4][15], \
state->RegBank[5][0],state->RegBank[5][1],state->RegBank[5][2],state->RegBank[5][3], \
state->RegBank[5][4],state->RegBank[5][5],state->RegBank[5][6],state->RegBank[5][7], \
state->RegBank[5][8],state->RegBank[5][9],state->RegBank[5][10],state->RegBank[5][11], \
state->RegBank[5][12],state->RegBank[5][13],state->RegBank[5][14],state->RegBank[5][15] \
);}
#define SA1110 0x6901b110
#define SA1100 0x4401a100
#define PXA250 0x69052100
#define PXA270 0x69054110
//#define PXA250 0x69052903
// 0x69052903; //PXA250 B1 from intel 278522-001.pdf
extern void ARMul_UndefInstr (ARMul_State *, ARMword);
extern void ARMul_FixCPSR (ARMul_State *, ARMword, ARMword);
extern void ARMul_FixSPSR (ARMul_State *, ARMword, ARMword);
extern void ARMul_ConsolePrint (ARMul_State *, const char *, ...);
extern void ARMul_SelectProcessor (ARMul_State *, unsigned);
#define DIFF_LOG 0
#define SAVE_LOG 0
#endif /* _ARMDEFS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,659 @@
/* armemu.h -- ARMulator emulation macros: 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. */
#ifndef __ARMEMU_H__
#define __ARMEMU_H__
#include "common.h"
#include "armdefs.h"
//#include "skyeye.h"
extern ARMword isize;
/* Condition code values. */
#define EQ 0
#define NE 1
#define CS 2
#define CC 3
#define MI 4
#define PL 5
#define VS 6
#define VC 7
#define HI 8
#define LS 9
#define GE 10
#define LT 11
#define GT 12
#define LE 13
#define AL 14
#define NV 15
/* Shift Opcodes. */
#define LSL 0
#define LSR 1
#define ASR 2
#define ROR 3
/* Macros to twiddle the status flags and mode. */
#define NBIT ((unsigned)1L << 31)
#define ZBIT (1L << 30)
#define CBIT (1L << 29)
#define VBIT (1L << 28)
#define SBIT (1L << 27)
#define IBIT (1L << 7)
#define FBIT (1L << 6)
#define IFBITS (3L << 6)
#define R15IBIT (1L << 27)
#define R15FBIT (1L << 26)
#define R15IFBITS (3L << 26)
#define POS(i) ( (~(i)) >> 31 )
#define NEG(i) ( (i) >> 31 )
#ifdef MODET /* Thumb support. */
/* ??? This bit is actually in the low order bit of the PC in the hardware.
It isn't clear if the simulator needs to model that or not. */
#define TBIT (1L << 5)
#define TFLAG state->TFlag
#define SETT state->TFlag = 1
#define CLEART state->TFlag = 0
#define ASSIGNT(res) state->TFlag = res
#define INSN_SIZE (TFLAG ? 2 : 4)
#else
#define TBIT (1L << 5)
#define INSN_SIZE 4
#define TFLAG 0
#endif
/*add armv6 CPSR feature*/
#define EFLAG state->EFlag
#define SETE state->EFlag = 1
#define CLEARE state->EFlag = 0
#define ASSIGNE(res) state->NFlag = res
#define AFLAG state->AFlag
#define SETA state->AFlag = 1
#define CLEARA state->AFlag = 0
#define ASSIGNA(res) state->NFlag = res
#define QFLAG state->QFlag
#define SETQ state->QFlag = 1
#define CLEARQ state->AFlag = 0
#define ASSIGNQ(res) state->QFlag = res
/* add end */
#define NFLAG state->NFlag
#define SETN state->NFlag = 1
#define CLEARN state->NFlag = 0
#define ASSIGNN(res) state->NFlag = res
#define ZFLAG state->ZFlag
#define SETZ state->ZFlag = 1
#define CLEARZ state->ZFlag = 0
#define ASSIGNZ(res) state->ZFlag = res
#define CFLAG state->CFlag
#define SETC state->CFlag = 1
#define CLEARC state->CFlag = 0
#define ASSIGNC(res) state->CFlag = res
#define VFLAG state->VFlag
#define SETV state->VFlag = 1
#define CLEARV state->VFlag = 0
#define ASSIGNV(res) state->VFlag = res
#define SFLAG state->SFlag
#define SETS state->SFlag = 1
#define CLEARS state->SFlag = 0
#define ASSIGNS(res) state->SFlag = res
#define IFLAG (state->IFFlags >> 1)
#define FFLAG (state->IFFlags & 1)
#define IFFLAGS state->IFFlags
#define ASSIGNINT(res) state->IFFlags = (((res) >> 6) & 3)
#define ASSIGNR15INT(res) state->IFFlags = (((res) >> 26) & 3) ;
#define PSR_FBITS (0xff000000L)
#define PSR_SBITS (0x00ff0000L)
#define PSR_XBITS (0x0000ff00L)
#define PSR_CBITS (0x000000ffL)
#if defined MODE32 || defined MODET
#define CCBITS (0xf8000000L)
#else
#define CCBITS (0xf0000000L)
#endif
#define INTBITS (0xc0L)
#if defined MODET && defined MODE32
#define PCBITS (0xffffffffL)
#else
#define PCBITS (0xfffffffcL)
#endif
#define MODEBITS (0x1fL)
#define R15INTBITS (3L << 26)
#if defined MODET && defined MODE32
#define R15PCBITS (0x03ffffffL)
#else
#define R15PCBITS (0x03fffffcL)
#endif
#define R15PCMODEBITS (0x03ffffffL)
#define R15MODEBITS (0x3L)
#ifdef MODE32
#define PCMASK PCBITS
#define PCWRAP(pc) (pc)
#else
#define PCMASK R15PCBITS
#define PCWRAP(pc) ((pc) & R15PCBITS)
#endif
#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS))
#define R15INT (state->Reg[15] & R15INTBITS)
#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS))
#define R15INTPCMODE (state->Reg[15] & (R15INTBITS | R15PCBITS | R15MODEBITS))
#define R15INTMODE (state->Reg[15] & (R15INTBITS | R15MODEBITS))
#define R15PC (state->Reg[15] & R15PCBITS)
#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
#define R15MODE (state->Reg[15] & R15MODEBITS)
#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27))
#define EINT (IFFLAGS << 6)
#define ER15INT (IFFLAGS << 26)
#define EMODE (state->Mode)
//#ifdef MODET
//#define CPSR (ECC | EINT | EMODE | (TFLAG << 5))
//#else
//#define CPSR (ECC | EINT | EMODE)
//#endif
#ifdef MODE32
#define PATCHR15
#else
#define PATCHR15 state->Reg[15] = ECC | ER15INT | EMODE | R15PC
#endif
#define GETSPSR(bank) (ARMul_GetSPSR (state, EMODE))
#define SETPSR_F(d,s) d = ((d) & ~PSR_FBITS) | ((s) & PSR_FBITS)
#define SETPSR_S(d,s) d = ((d) & ~PSR_SBITS) | ((s) & PSR_SBITS)
#define SETPSR_X(d,s) d = ((d) & ~PSR_XBITS) | ((s) & PSR_XBITS)
#define SETPSR_C(d,s) d = ((d) & ~PSR_CBITS) | ((s) & PSR_CBITS)
#define SETR15PSR(s) \
do \
{ \
if (state->Mode == USER26MODE) \
{ \
state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE; \
ASSIGNN ((state->Reg[15] & NBIT) != 0); \
ASSIGNZ ((state->Reg[15] & ZBIT) != 0); \
ASSIGNC ((state->Reg[15] & CBIT) != 0); \
ASSIGNV ((state->Reg[15] & VBIT) != 0); \
} \
else \
{ \
state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)); \
ARMul_R15Altered (state); \
} \
} \
while (0)
#define SETABORT(i, m, d) \
do \
{ \
int SETABORT_mode = (m); \
\
ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \
ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \
| (i) | SETABORT_mode)); \
state->Reg[14] = temp - (d); \
} \
while (0)
//#ifndef MODE32
#define VECTORS 0x20
#define LEGALADDR 0x03ffffff
#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig)
//#endif
#define INTERNALABORT(address) \
do \
{ \
if (address < VECTORS) \
state->Aborted = ARMul_DataAbortV; \
else \
state->Aborted = ARMul_AddrExceptnV; \
} \
while (0)
#ifdef MODE32
#define TAKEABORT ARMul_Abort (state, ARMul_DataAbortV)
#else
#define TAKEABORT \
do \
{ \
if (state->Aborted == ARMul_AddrExceptnV) \
ARMul_Abort (state, ARMul_AddrExceptnV); \
else \
ARMul_Abort (state, ARMul_DataAbortV); \
} \
while (0)
#endif
#define CPTAKEABORT \
do \
{ \
if (!state->Aborted) \
ARMul_Abort (state, ARMul_UndefinedInstrV); \
else if (state->Aborted == ARMul_AddrExceptnV) \
ARMul_Abort (state, ARMul_AddrExceptnV); \
else \
ARMul_Abort (state, ARMul_DataAbortV); \
} \
while (0);
/* Different ways to start the next instruction. */
#define SEQ 0
#define NONSEQ 1
#define PCINCEDSEQ 2
#define PCINCEDNONSEQ 3
#define PRIMEPIPE 4
#define RESUME 8
/************************************/
/* shenoubang 2012-3-11 */
/* for armv7 DBG DMB DSB instr*/
/************************************/
#define MBReqTypes_Writes 0
#define MBReqTypes_All 1
#define NORMALCYCLE state->NextInstr = 0
#define BUSUSEDN state->NextInstr |= 1 /* The next fetch will be an N cycle. */
#define BUSUSEDINCPCS \
do \
{ \
if (! state->is_v4) \
{ \
/* A standard PC inc and an S cycle. */ \
state->Reg[15] += isize; \
state->NextInstr = (state->NextInstr & 0xff) | 2; \
} \
} \
while (0)
#define BUSUSEDINCPCN \
do \
{ \
if (state->is_v4) \
BUSUSEDN; \
else \
{ \
/* A standard PC inc and an N cycle. */ \
state->Reg[15] += isize; \
state->NextInstr |= 3; \
} \
} \
while (0)
#define INCPC \
do \
{ \
/* A standard PC inc. */ \
state->Reg[15] += isize; \
state->NextInstr |= 2; \
} \
while (0)
#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
/* Cycle based emulation. */
#define OUTPUTCP(i,a,b)
#define NCYCLE
#define SCYCLE
#define ICYCLE
#define CCYCLE
#define NEXTCYCLE(c)
/* Macros to extract parts of instructions. */
#define DESTReg (BITS (12, 15))
#define LHSReg (BITS (16, 19))
#define RHSReg (BITS ( 0, 3))
#define DEST (state->Reg[DESTReg])
#ifdef MODE32
#ifdef MODET
#define LHS ((LHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[LHSReg]))
#define RHS ((RHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[RHSReg]))
#else
#define LHS (state->Reg[LHSReg])
#define RHS (state->Reg[RHSReg])
#endif
#else
#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg]))
#define RHS ((RHSReg == 15) ? R15PC : (state->Reg[RHSReg]))
#endif
#define MULDESTReg (BITS (16, 19))
#define MULLHSReg (BITS ( 0, 3))
#define MULRHSReg (BITS ( 8, 11))
#define MULACCReg (BITS (12, 15))
#define DPImmRHS (ARMul_ImmedTable[BITS(0, 11)])
#define DPSImmRHS temp = BITS(0,11) ; \
rhs = ARMul_ImmedTable[temp] ; \
if (temp > 255) /* There was a shift. */ \
ASSIGNC (rhs >> 31) ;
#ifdef MODE32
#define DPRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
: GetDPRegRHS (state, instr))
#define DPSRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
: GetDPSRegRHS (state, instr))
#else
#define DPRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
: GetDPRegRHS (state, instr))
#define DPSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
: GetDPSRegRHS (state, instr))
#endif
#define LSBase state->Reg[LHSReg]
#define LSImmRHS (BITS(0,11))
#ifdef MODE32
#define LSRegRHS ((BITS (4, 11) == 0) ? state->Reg[RHSReg] \
: GetLSRegRHS (state, instr))
#else
#define LSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
: GetLSRegRHS (state, instr))
#endif
#define LSMNumRegs ((ARMword) ARMul_BitList[BITS (0, 7)] + \
(ARMword) ARMul_BitList[BITS (8, 15)] )
#define LSMBaseFirst ((LHSReg == 0 && BIT (0)) || \
(BIT (LHSReg) && BITS (0, LHSReg - 1) == 0))
#define SWAPSRC (state->Reg[RHSReg])
#define LSCOff (BITS (0, 7) << 2)
#define CPNum BITS (8, 11)
/* Determine if access to coprocessor CP is permitted.
The XScale has a register in CP15 which controls access to CP0 - CP13. */
//chy 2003-09-03, new CP_ACCESS_ALLOWED
/*
#define CP_ACCESS_ALLOWED(STATE, CP) \
( ((CP) >= 14) \
|| (! (STATE)->is_XScale) \
|| (read_cp15_reg (15, 0, 1) & (1 << (CP))))
*/
//#define CP_ACCESS_ALLOWED(STATE, CP) \
// (((CP) >= 14) \
// || (!(STATE)->is_XScale) \
// || (xscale_cp15_cp_access_allowed(STATE, 15, CP)))
#define CP_ACCESS_ALLOWED(STATE, CP) false // Disabled coprocessor shit /bunnei
/* Macro to rotate n right by b bits. */
#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
/* Macros to store results of instructions. */
#define WRITEDEST(d) \
do \
{ \
if (DESTReg == 15) \
WriteR15 (state, d); \
else \
DEST = d; \
} \
while (0)
#define WRITESDEST(d) \
do \
{ \
if (DESTReg == 15) \
WriteSR15 (state, d); \
else \
{ \
DEST = d; \
ARMul_NegZero (state, d); \
} \
} \
while (0)
#define WRITEDESTB(d) \
do \
{ \
if (DESTReg == 15){ \
WriteR15Branch (state, d); \
} \
else{ \
DEST = d; \
} \
} \
while (0)
#define BYTETOBUS(data) ((data & 0xff) | \
((data & 0xff) << 8) | \
((data & 0xff) << 16) | \
((data & 0xff) << 24))
#define BUSTOBYTE(address, data) \
do \
{ \
if (state->bigendSig) \
temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff; \
else \
temp = (data >> ((address & 3) << 3)) & 0xff; \
} \
while (0)
#define LOADMULT(instr, address, wb) LoadMult (state, instr, address, wb)
#define LOADSMULT(instr, address, wb) LoadSMult (state, instr, address, wb)
#define STOREMULT(instr, address, wb) StoreMult (state, instr, address, wb)
#define STORESMULT(instr, address, wb) StoreSMult (state, instr, address, wb)
#define POSBRANCH ((instr & 0x7fffff) << 2)
#define NEGBRANCH ((0xff000000 |(instr & 0xffffff)) << 2)
/* Values for Emulate. */
#define STOP 0 /* stop */
#define CHANGEMODE 1 /* change mode */
#define ONCE 2 /* execute just one interation */
#define RUN 3 /* continuous execution */
/* Stuff that is shared across modes. */
extern unsigned ARMul_MultTable[]; /* Number of I cycles for a mult. */
extern ARMword ARMul_ImmedTable[]; /* Immediate DP LHS values. */
extern char ARMul_BitList[]; /* Number of bits in a byte table. */
#define EVENTLISTSIZE 1024L
/* Thumb support. */
typedef enum
{
t_undefined, /* Undefined Thumb instruction. */
t_decoded, /* Instruction decoded to ARM equivalent. */
t_branch /* Thumb branch (already processed). */
}
tdstate;
/*********************************************************************************
* Check all the possible undef or unpredict behavior, Some of them probably is
* out-of-updated with the newer ISA.
* -- Michael.Kang
********************************************************************************/
#define UNDEF_WARNING ERROR_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n");
/* Macros to scrutinize instructions. */
#define UNDEF_Test UNDEF_WARNING
//#define UNDEF_Test
//#define UNDEF_Shift UNDEF_WARNING
#define UNDEF_Shift
//#define UNDEF_MSRPC UNDEF_WARNING
#define UNDEF_MSRPC
//#define UNDEF_MRSPC UNDEF_WARNING
#define UNDEF_MRSPC
#define UNDEF_MULPCDest UNDEF_WARNING
//#define UNDEF_MULPCDest
#define UNDEF_MULDestEQOp1 UNDEF_WARNING
//#define UNDEF_MULDestEQOp1
//#define UNDEF_LSRBPC UNDEF_WARNING
#define UNDEF_LSRBPC
//#define UNDEF_LSRBaseEQOffWb UNDEF_WARNING
#define UNDEF_LSRBaseEQOffWb
//#define UNDEF_LSRBaseEQDestWb UNDEF_WARNING
#define UNDEF_LSRBaseEQDestWb
//#define UNDEF_LSRPCBaseWb UNDEF_WARNING
#define UNDEF_LSRPCBaseWb
//#define UNDEF_LSRPCOffWb UNDEF_WARNING
#define UNDEF_LSRPCOffWb
//#define UNDEF_LSMNoRegs UNDEF_WARNING
#define UNDEF_LSMNoRegs
//#define UNDEF_LSMPCBase UNDEF_WARNING
#define UNDEF_LSMPCBase
//#define UNDEF_LSMUserBankWb UNDEF_WARNING
#define UNDEF_LSMUserBankWb
//#define UNDEF_LSMBaseInListWb UNDEF_WARNING
#define UNDEF_LSMBaseInListWb
#define UNDEF_SWPPC UNDEF_WARNING
//#define UNDEF_SWPPC
#define UNDEF_CoProHS UNDEF_WARNING
//#define UNDEF_CoProHS
#define UNDEF_MCRPC UNDEF_WARNING
//#define UNDEF_MCRPC
//#define UNDEF_LSCPCBaseWb UNDEF_WARNING
#define UNDEF_LSCPCBaseWb
#define UNDEF_UndefNotBounced UNDEF_WARNING
//#define UNDEF_UndefNotBounced
#define UNDEF_ShortInt UNDEF_WARNING
//#define UNDEF_ShortInt
#define UNDEF_IllegalMode UNDEF_WARNING
//#define UNDEF_IllegalMode
#define UNDEF_Prog32SigChange UNDEF_WARNING
//#define UNDEF_Prog32SigChange
#define UNDEF_Data32SigChange UNDEF_WARNING
//#define UNDEF_Data32SigChange
/* Prototypes for exported functions. */
extern unsigned ARMul_NthReg (ARMword, unsigned);
extern int AddOverflow (ARMword, ARMword, ARMword);
extern int SubOverflow (ARMword, ARMword, ARMword);
/* Prototypes for exported functions. */
#ifdef __cplusplus
extern "C" {
#endif
extern ARMword ARMul_Emulate26 (ARMul_State *);
extern ARMword ARMul_Emulate32 (ARMul_State *);
#ifdef __cplusplus
}
#endif
extern unsigned IntPending (ARMul_State *);
extern void ARMul_CPSRAltered (ARMul_State *);
extern void ARMul_R15Altered (ARMul_State *);
extern ARMword ARMul_GetPC (ARMul_State *);
extern ARMword ARMul_GetNextPC (ARMul_State *);
extern ARMword ARMul_GetR15 (ARMul_State *);
extern ARMword ARMul_GetCPSR (ARMul_State *);
extern void ARMul_EnvokeEvent (ARMul_State *);
extern unsigned int ARMul_Time (ARMul_State *);
extern void ARMul_NegZero (ARMul_State *, ARMword);
extern void ARMul_SetPC (ARMul_State *, ARMword);
extern void ARMul_SetR15 (ARMul_State *, ARMword);
extern void ARMul_SetCPSR (ARMul_State *, ARMword);
extern ARMword ARMul_GetSPSR (ARMul_State *, ARMword);
extern void ARMul_Abort26 (ARMul_State *, ARMword);
extern void ARMul_Abort32 (ARMul_State *, ARMword);
extern ARMword ARMul_MRC (ARMul_State *, ARMword);
extern void ARMul_MRRC (ARMul_State *, ARMword, ARMword *, ARMword *);
extern void ARMul_CDP (ARMul_State *, ARMword);
extern void ARMul_LDC (ARMul_State *, ARMword, ARMword);
extern void ARMul_STC (ARMul_State *, ARMword, ARMword);
extern void ARMul_MCR (ARMul_State *, ARMword, ARMword);
extern void ARMul_MCRR (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_SetSPSR (ARMul_State *, ARMword, ARMword);
extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword);
extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);
extern ARMword ARMul_GetReg (ARMul_State *, unsigned, unsigned);
extern void ARMul_SetReg (ARMul_State *, unsigned, unsigned, ARMword);
extern void ARMul_ScheduleEvent (ARMul_State *, unsigned int,
unsigned (*)(ARMul_State *));
/* Coprocessor support functions. */
extern unsigned ARMul_CoProInit (ARMul_State *);
extern void ARMul_CoProExit (ARMul_State *);
extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *,
ARMul_CPExits *, ARMul_LDCs *, ARMul_STCs *,
ARMul_MRCs *, ARMul_MCRs *, ARMul_MRRCs *, ARMul_MCRRs *,
ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *);
extern void ARMul_CoProDetach (ARMul_State *, unsigned);
extern ARMword read_cp15_reg (unsigned, unsigned, unsigned);
extern unsigned DSPLDC4 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMCR4 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMRC4 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPSTC4 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPCDP4 (ARMul_State *, unsigned, ARMword);
extern unsigned DSPMCR5 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMRC5 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPLDC5 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPSTC5 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPCDP5 (ARMul_State *, unsigned, ARMword);
extern unsigned DSPMCR6 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMRC6 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPCDP6 (ARMul_State *, unsigned, ARMword);
#endif

View file

@ -0,0 +1,579 @@
/* arminit.c -- ARMulator initialization: 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 "platform.h"
#if EMU_PLATFORM == PLATFORM_LINUX
#include <unistd.h>
#endif
#include <math.h>
#include "armdefs.h"
#include "armemu.h"
/***************************************************************************\
* Definitions for the emulator architecture *
\***************************************************************************/
void ARMul_EmulateInit (void);
ARMul_State *ARMul_NewState (ARMul_State * state);
void ARMul_Reset (ARMul_State * state);
ARMword ARMul_DoCycle (ARMul_State * state);
unsigned ARMul_DoCoPro (ARMul_State * state);
ARMword ARMul_DoProg (ARMul_State * state);
ARMword ARMul_DoInstr (ARMul_State * state);
void ARMul_Abort (ARMul_State * state, ARMword address);
unsigned ARMul_MultTable[32] =
{ 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16
};
ARMword ARMul_ImmedTable[4096]; /* immediate DP LHS values */
char ARMul_BitList[256]; /* number of bits in a byte table */
//chy 2006-02-22 add test debugmode
extern int debugmode;
extern int remote_interrupt( void );
void arm_dyncom_Abort(ARMul_State * state, ARMword vector)
{
ARMul_Abort(state, vector);
}
/* ahe-ykl : the following code to initialize user mode
code is architecture dependent and probably model dependant. */
//#include "skyeye_arch.h"
//#include "skyeye_pref.h"
//#include "skyeye_exec_info.h"
//#include "bank_defs.h"
#include "armcpu.h"
//#include "skyeye_callback.h"
//void arm_user_mode_init(generic_arch_t * arch_instance)
//{
// sky_pref_t *pref = get_skyeye_pref();
//
// if (pref->user_mode_sim)
// {
// sky_exec_info_t *info = get_skyeye_exec_info();
// info->arch_page_size = 0x1000;
// info->arch_stack_top = 0x1ffffff0;// + 0x401fe7 - 0xff0; /* arbitrary value */
// /* stack initial address specific to architecture may be placed here */
//
// /* we need to mmap the stack space, if we are using skyeye space */
// if (info->mmap_access)
// {
// /* get system stack size */
// size_t stacksize = 0;
// pthread_attr_t attr;
// pthread_attr_init(&attr);
// pthread_attr_getstacksize(&attr, &stacksize);
// if (stacksize > info->arch_stack_top)
// {
// printf("arch_stack_top is too low\n");
// stacksize = info->arch_stack_top;
// }
//
// /* Note: Skyeye is occupating 0x400000 to 0x600000 */
// /* We do a mmap */
// void* ret = mmap( (info->arch_stack_top) - stacksize,
// stacksize + 0x1000 , PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// if (ret == MAP_FAILED){
// /* ideally, we should find an empty space until it works */
// printf("mmap error, stack couldn't be mapped: errno %d\n", errno);
// exit(-1);
// } else {
// memset(ret, '\0', stacksize);
// //printf("stack top has been defined at %x size %x\n", (uint32_t) ret + stacksize, stacksize);
// //info->arch_stack_top = (uint32_t) ret + stacksize;
// }
// }
//
// exec_stack_init();
//
// ARM_CPU_State* cpu = get_current_cpu();
// arm_core_t* core = &cpu->core[0];
//
// uint32_t sp = info->initial_sp;
//
// core->Cpsr = 0x10; /* User mode */
// /* FIXME: may need to add thumb */
// core->Reg[13] = sp;
// core->Reg[10] = info->start_data;
// core->Reg[0] = 0;
// bus_read(32, sp + 4, &(core->Reg[1]));
// bus_read(32, sp + 8, &(core->Reg[2]));
// }
//
//}
/***************************************************************************\
* Call this routine once to set up the emulator's tables. *
\***************************************************************************/
void
ARMul_EmulateInit (void)
{
unsigned int i, j;
for (i = 0; i < 4096; i++) { /* the values of 12 bit dp rhs's */
ARMul_ImmedTable[i] = ROTATER (i & 0xffL, (i >> 7L) & 0x1eL);
}
for (i = 0; i < 256; ARMul_BitList[i++] = 0); /* how many bits in LSM */
for (j = 1; j < 256; j <<= 1)
for (i = 0; i < 256; i++)
if ((i & j) > 0)
ARMul_BitList[i]++;
for (i = 0; i < 256; i++)
ARMul_BitList[i] *= 4; /* you always need 4 times these values */
}
/***************************************************************************\
* Returns a new instantiation of the ARMulator's state *
\***************************************************************************/
ARMul_State *
ARMul_NewState (ARMul_State *state)
{
unsigned i, j;
memset (state, 0, sizeof (ARMul_State));
state->Emulate = RUN;
for (i = 0; i < 16; i++) {
state->Reg[i] = 0;
for (j = 0; j < 7; j++)
state->RegBank[j][i] = 0;
}
for (i = 0; i < 7; i++)
state->Spsr[i] = 0;
state->Mode = 0;
state->CallDebug = FALSE;
state->Debug = FALSE;
state->VectorCatch = 0;
state->Aborted = FALSE;
state->Reseted = FALSE;
state->Inted = 3;
state->LastInted = 3;
state->CommandLine = NULL;
state->EventSet = 0;
state->Now = 0;
state->EventPtr =
(struct EventNode **) malloc ((unsigned) EVENTLISTSIZE *
sizeof (struct EventNode *));
#if DIFF_STATE
state->state_log = fopen("/data/state.log", "w");
printf("create pc log file.\n");
#endif
if (state->EventPtr == NULL) {
printf ("SKYEYE: ARMul_NewState malloc state->EventPtr error\n");
exit(-1);
}
for (i = 0; i < EVENTLISTSIZE; i++)
*(state->EventPtr + i) = NULL;
#if SAVE_LOG
state->state_log = fopen("/tmp/state.log", "w");
printf("create pc log file.\n");
#else
#if DIFF_LOG
state->state_log = fopen("/tmp/state.log", "r");
printf("loaded pc log file.\n");
#endif
#endif
#ifdef ARM61
state->prog32Sig = LOW;
state->data32Sig = LOW;
#else
state->prog32Sig = HIGH;
state->data32Sig = HIGH;
#endif
state->lateabtSig = HIGH;
state->bigendSig = LOW;
//chy:2003-08-19
state->LastTime = 0;
state->CP14R0_CCD = -1;
/* ahe-ykl: common function for interpret and dyncom */
//sky_pref_t *pref = get_skyeye_pref();
//if (pref->user_mode_sim)
// register_callback(arm_user_mode_init, Bootmach_callback);
memset(&state->exclusive_tag_array[0], 0xFF, sizeof(state->exclusive_tag_array[0]) * 128);
state->exclusive_access_state = 0;
//state->cpu = (cpu_config_t *) malloc (sizeof (cpu_config_t));
//state->mem_bank = (mem_config_t *) malloc (sizeof (mem_config_t));
return (state);
}
/***************************************************************************\
* Call this routine to set ARMulator to model a certain processor *
\***************************************************************************/
void
ARMul_SelectProcessor (ARMul_State * state, unsigned properties)
{
if (properties & ARM_Fix26_Prop) {
state->prog32Sig = LOW;
state->data32Sig = LOW;
}
else {
state->prog32Sig = HIGH;
state->data32Sig = HIGH;
}
/* 2004-05-09 chy
below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function
*/
// state->lateabtSig = HIGH;
state->is_v4 =
(properties & (ARM_v4_Prop | ARM_v5_Prop)) ? HIGH : LOW;
state->is_v5 = (properties & ARM_v5_Prop) ? HIGH : LOW;
state->is_v5e = (properties & ARM_v5e_Prop) ? HIGH : LOW;
state->is_XScale = (properties & ARM_XScale_Prop) ? HIGH : LOW;
state->is_iWMMXt = (properties & ARM_iWMMXt_Prop) ? HIGH : LOW;
/* state->is_v6 = LOW */;
/* jeff.du 2010-08-05 */
state->is_v6 = (properties & ARM_v6_Prop) ? HIGH : LOW;
state->is_ep9312 = (properties & ARM_ep9312_Prop) ? HIGH : LOW;
//chy 2005-09-19
state->is_pxa27x = (properties & ARM_PXA27X_Prop) ? HIGH : LOW;
/* shenoubang 2012-3-11 */
state->is_v7 = (properties & ARM_v7_Prop) ? HIGH : LOW;
/* Only initialse the coprocessor support once we
know what kind of chip we are dealing with. */
//ARMul_CoProInit (state); Commented out /bunnei
}
/***************************************************************************\
* Call this routine to set up the initial machine state (or perform a RESET *
\***************************************************************************/
void
ARMul_Reset (ARMul_State * state)
{
//fprintf(stderr,"armul_reset 0: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
state->NextInstr = 0;
if (state->prog32Sig) {
state->Reg[15] = 0;
state->Cpsr = INTBITS | SVC32MODE;
state->Mode = SVC32MODE;
}
else {
state->Reg[15] = R15INTBITS | SVC26MODE;
state->Cpsr = INTBITS | SVC26MODE;
state->Mode = SVC26MODE;
}
//fprintf(stderr,"armul_reset 1: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
ARMul_CPSRAltered (state);
state->Bank = SVCBANK;
FLUSHPIPE;
state->EndCondition = 0;
state->ErrorCode = 0;
//fprintf(stderr,"armul_reset 2: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
state->NresetSig = HIGH;
state->NfiqSig = HIGH;
state->NirqSig = HIGH;
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
state->abortSig = LOW;
state->AbortAddr = 1;
state->NumInstrs = 0;
state->NumNcycles = 0;
state->NumScycles = 0;
state->NumIcycles = 0;
state->NumCcycles = 0;
state->NumFcycles = 0;
//fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
//mmu_reset (state); Commented out /bunnei
//fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
//mem_reset (state); /* move to memory/ram.c */
//fprintf(stderr,"armul_reset 5: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
/*remove later. walimis 03.7.17 */
//io_reset(state);
//lcd_disable(state);
/*ywc 2005-04-07 move from ARMul_NewState , because skyeye_config.no_dbct will
*be configured in skyeye_option_init and it is called after ARMul_NewState*/
state->tea_break_ok = 0;
state->tea_break_addr = 0;
state->tea_pc = 0;
#ifdef DBCT
if (!skyeye_config.no_dbct) {
//teawater add for arm2x86 2005.02.14-------------------------------------------
if (arm2x86_init (state)) {
printf ("SKYEYE: arm2x86_init error\n");
skyeye_exit (-1);
}
//AJ2D--------------------------------------------------------------------------
}
#endif
}
/***************************************************************************\
* Emulate the execution of an entire program. Start the correct emulator *
* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the *
* address of the last instruction that is executed. *
\***************************************************************************/
//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
#ifdef DBCT_TEST_SPEED
static ARMul_State *dbct_test_speed_state = NULL;
static void
dbct_test_speed_sig(int signo)
{
printf("\n0x%llx %llu\n", dbct_test_speed_state->instr_count, dbct_test_speed_state->instr_count);
skyeye_exit(0);
}
#endif //DBCT_TEST_SPEED
//AJ2D--------------------------------------------------------------------------
ARMword
ARMul_DoProg (ARMul_State * state)
{
ARMword pc = 0;
/*
* 2007-01-24 removed the term-io functions by Anthony Lee,
* moved to "device/uart/skyeye_uart_stdio.c".
*/
//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
#ifdef DBCT_TEST_SPEED
{
if (!dbct_test_speed_state) {
//init timer
struct itimerval value;
struct sigaction act;
dbct_test_speed_state = state;
state->instr_count = 0;
act.sa_handler = dbct_test_speed_sig;
act.sa_flags = SA_RESTART;
//cygwin don't support ITIMER_VIRTUAL or ITIMER_PROF
#ifndef __CYGWIN__
if (sigaction(SIGVTALRM, &act, NULL) == -1) {
#else
if (sigaction(SIGALRM, &act, NULL) == -1) {
#endif //__CYGWIN__
fprintf(stderr, "init timer error.\n");
skyeye_exit(-1);
}
if (skyeye_config.dbct_test_speed_sec) {
value.it_value.tv_sec = skyeye_config.dbct_test_speed_sec;
}
else {
value.it_value.tv_sec = DBCT_TEST_SPEED_SEC;
}
printf("dbct_test_speed_sec = %ld\n", value.it_value.tv_sec);
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = 0;
#ifndef __CYGWIN__
if (setitimer(ITIMER_VIRTUAL, &value, NULL) == -1) {
#else
if (setitimer(ITIMER_REAL, &value, NULL) == -1) {
#endif //__CYGWIN__
fprintf(stderr, "init timer error.\n");
skyeye_exit(-1);
}
}
}
#endif //DBCT_TEST_SPEED
//AJ2D--------------------------------------------------------------------------
state->Emulate = RUN;
while (state->Emulate != STOP) {
state->Emulate = RUN;
/*ywc 2005-03-31 */
if (state->prog32Sig && ARMul_MODE32BIT) {
#ifdef DBCT
if (skyeye_config.no_dbct) {
pc = ARMul_Emulate32 (state);
}
else {
pc = ARMul_Emulate32_dbct (state);
}
#else
pc = ARMul_Emulate32 (state);
#endif
}
else {
_dbg_assert_msg_(ARM11, false, "Unsupported ARM 26-bit Mode!");
}
//chy 2006-02-22, should test debugmode first
//chy 2006-04-14, put below codes in ARMul_Emulate
#if 0
if(debugmode)
if(remote_interrupt())
state->Emulate = STOP;
#endif
}
/*
* 2007-01-24 removed the term-io functions by Anthony Lee,
* moved to "device/uart/skyeye_uart_stdio.c".
*/
return (pc);
}
/***************************************************************************\
* Emulate the execution of one instruction. Start the correct emulator *
* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the *
* address of the instruction that is executed. *
\***************************************************************************/
ARMword
ARMul_DoInstr (ARMul_State * state)
{
ARMword pc = 0;
state->Emulate = ONCE;
/*ywc 2005-03-31 */
if (state->prog32Sig && ARMul_MODE32BIT) {
#ifdef DBCT
if (skyeye_config.no_dbct) {
pc = ARMul_Emulate32 (state);
}
else {
//teawater add compile switch for DBCT GDB RSP function 2005.10.21--------------
#ifndef DBCT_GDBRSP
printf("DBCT GDBRSP function switch is off.\n");
printf("To use this function, open \"#define DBCT_GDBRSP\" in arch/arm/common/armdefs.h & recompile skyeye.\n");
skyeye_exit(-1);
#endif //DBCT_GDBRSP
//AJ2D--------------------------------------------------------------------------
pc = ARMul_Emulate32_dbct (state);
}
#else
pc = ARMul_Emulate32 (state);
#endif
}
else {
_dbg_assert_msg_(ARM11, false, "Unsupported ARM 26-bit Mode!");
}
return (pc);
}
/***************************************************************************\
* This routine causes an Abort to occur, including selecting the correct *
* mode, register bank, and the saving of registers. Call with the *
* appropriate vector's memory address (0,4,8 ....) *
\***************************************************************************/
void
ARMul_Abort (ARMul_State * state, ARMword vector)
{
ARMword temp;
int isize = INSN_SIZE;
int esize = (TFLAG ? 0 : 4);
int e2size = (TFLAG ? -4 : 0);
state->Aborted = FALSE;
if (state->prog32Sig)
if (ARMul_MODE26BIT)
temp = R15PC;
else
temp = state->Reg[15];
else
temp = R15PC | ECC | ER15INT | EMODE;
switch (vector) {
case ARMul_ResetV: /* RESET */
SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE,
0);
break;
case ARMul_UndefinedInstrV: /* Undefined Instruction */
SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE,
isize);
break;
case ARMul_SWIV: /* Software Interrupt */
SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE,
isize);
break;
case ARMul_PrefetchAbortV: /* Prefetch Abort */
state->AbortAddr = 1;
SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
esize);
break;
case ARMul_DataAbortV: /* Data Abort */
SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
e2size);
break;
case ARMul_AddrExceptnV: /* Address Exception */
SETABORT (IBIT, SVC26MODE, isize);
break;
case ARMul_IRQV: /* IRQ */
//chy 2003-09-02 the if sentence seems no use
#if 0
if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
|| (temp & ARMul_CP13_R0_IRQ))
#endif
SETABORT (IBIT,
state->prog32Sig ? IRQ32MODE : IRQ26MODE,
esize);
break;
case ARMul_FIQV: /* FIQ */
//chy 2003-09-02 the if sentence seems no use
#if 0
if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
|| (temp & ARMul_CP13_R0_FIQ))
#endif
SETABORT (INTBITS,
state->prog32Sig ? FIQ32MODE : FIQ26MODE,
esize);
break;
}
if (ARMul_MODE32BIT) {
if (state->mmu.control & CONTROL_VECTOR)
vector += 0xffff0000; //for v4 high exception address
if (state->vector_remap_flag)
vector += state->vector_remap_addr; /* support some remap function in LPC processor */
ARMul_SetR15 (state, vector);
}
else
ARMul_SetR15 (state, R15CCINTMODE | vector);
}

View file

@ -0,0 +1,238 @@
/*
armmmu.c - Memory Management Unit emulation.
ARMulator extensions for the ARM7100 family.
Copyright (C) 1999 Ben Williamson
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 <assert.h>
#include <string.h>
#include "armdefs.h"
/* two header for arm disassemble */
//#include "skyeye_arch.h"
#include "armcpu.h"
extern mmu_ops_t xscale_mmu_ops;
exception_t arm_mmu_write(short size, u32 addr, uint32_t *value);
exception_t arm_mmu_read(short size, u32 addr, uint32_t *value);
#define MMU_OPS (state->mmu.ops)
ARMword skyeye_cachetype = -1;
int
mmu_init (ARMul_State * state)
{
int ret;
state->mmu.control = 0x70;
state->mmu.translation_table_base = 0xDEADC0DE;
state->mmu.domain_access_control = 0xDEADC0DE;
state->mmu.fault_status = 0;
state->mmu.fault_address = 0;
state->mmu.process_id = 0;
switch (state->cpu->cpu_val & state->cpu->cpu_mask) {
//case SA1100:
//case SA1110:
// NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
// state->mmu.ops = sa_mmu_ops;
// break;
//case PXA250:
//case PXA270: //xscale
// NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
// state->mmu.ops = xscale_mmu_ops;
// break;
//case 0x41807200: //arm720t
//case 0x41007700: //arm7tdmi
//case 0x41007100: //arm7100
// NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n");
// state->mmu.ops = arm7100_mmu_ops;
// break;
//case 0x41009200:
// NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
// state->mmu.ops = arm920t_mmu_ops;
// break;
//case 0x41069260:
// NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
// state->mmu.ops = arm926ejs_mmu_ops;
// break;
/* case 0x560f5810: */
case 0x0007b000:
NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n");
state->mmu.ops = arm1176jzf_s_mmu_ops;
break;
default:
ERROR_LOG (ARM11,
"SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n",
state->cpu->cpu_val & state->cpu->cpu_mask);
break;
};
ret = state->mmu.ops.init (state);
state->mmu_inited = (ret == 0);
/* initialize mmu_read and mmu_write for disassemble */
//skyeye_config_t *config = get_current_config();
//generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
//arch_instance->mmu_read = arm_mmu_read;
//arch_instance->mmu_write = arm_mmu_write;
return ret;
}
int
mmu_reset (ARMul_State * state)
{
if (state->mmu_inited)
mmu_exit (state);
return mmu_init (state);
}
void
mmu_exit (ARMul_State * state)
{
MMU_OPS.exit (state);
state->mmu_inited = 0;
}
fault_t
mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_byte (state, virt_addr, data);
};
fault_t
mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_halfword (state, virt_addr, data);
};
fault_t
mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_word (state, virt_addr, data);
};
fault_t
mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
//static int count = 0;
//count ++;
fault = MMU_OPS.write_byte (state, virt_addr, data);
return fault;
}
fault_t
mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
//static int count = 0;
//count ++;
fault = MMU_OPS.write_halfword (state, virt_addr, data);
return fault;
}
fault_t
mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
fault = MMU_OPS.write_word (state, virt_addr, data);
/*used for debug for MMU*
if (!fault){
ARMword tmp;
if (mmu_read_word(state, virt_addr, &tmp)){
err_msg("load back\n");
exit(-1);
}else{
if (tmp != data){
err_msg("load back not equal %d %x\n", count, virt_addr);
}
}
}
*/
return fault;
};
fault_t
mmu_load_instr (ARMul_State * state, ARMword virt_addr, ARMword * instr)
{
return MMU_OPS.load_instr (state, virt_addr, instr);
}
ARMword
mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
return MMU_OPS.mrc (state, instr, value);
}
void
mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
MMU_OPS.mcr (state, instr, value);
}
/*ywc 20050416*/
int
mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
{
return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr));
}
//
//
///* dis_mmu_read for disassemble */
//exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
//{
// ARMul_State *state;
// ARM_CPU_State *cpu = get_current_cpu();
// state = &cpu->core[0];
// switch(size){
// case 8:
// MMU_OPS.read_byte (state, addr, value);
// break;
// case 16:
// case 32:
// break;
// default:
// ERROR_LOG(ARM11, "Error size %d", size);
// break;
// }
// return No_exp;
//}
///* dis_mmu_write for disassemble */
//exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
//{
// ARMul_State *state;
// ARM_CPU_State *cpu = get_current_cpu();
// state = &cpu->core[0];
// switch(size){
// case 8:
// MMU_OPS.write_byte (state, addr, value);
// break;
// case 16:
// case 32:
// break;
// default:
// printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
// break;
// }
// return No_exp;
//}

View file

@ -0,0 +1,254 @@
/*
armmmu.c - Memory Management Unit emulation.
ARMulator extensions for the ARM7100 family.
Copyright (C) 1999 Ben Williamson
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
*/
#ifndef _ARMMMU_H_
#define _ARMMMU_H_
#define WORD_SHT 2
#define WORD_SIZE (1<<WORD_SHT)
/* The MMU is accessible with MCR and MRC operations to copro 15: */
#define MMU_COPRO (15)
/* Register numbers in the MMU: */
typedef enum mmu_regnum_t
{
MMU_ID = 0,
MMU_CONTROL = 1,
MMU_TRANSLATION_TABLE_BASE = 2,
MMU_DOMAIN_ACCESS_CONTROL = 3,
MMU_FAULT_STATUS = 5,
MMU_FAULT_ADDRESS = 6,
MMU_CACHE_OPS = 7,
MMU_TLB_OPS = 8,
MMU_CACHE_LOCKDOWN = 9,
MMU_TLB_LOCKDOWN = 10,
MMU_PID = 13,
/*MMU_V4 */
MMU_V4_CACHE_OPS = 7,
MMU_V4_TLB_OPS = 8,
/*MMU_V3 */
MMU_V3_FLUSH_TLB = 5,
MMU_V3_FLUSH_TLB_ENTRY = 6,
MMU_V3_FLUSH_CACHE = 7,
/*MMU Intel SA-1100 */
MMU_SA_RB_OPS = 9,
MMU_SA_DEBUG = 14,
MMU_SA_CP15_R15 = 15,
//chy 2003-08-24
/*Intel xscale CP15 */
XSCALE_CP15_CACHE_TYPE = 0,
XSCALE_CP15_AUX_CONTROL = 1,
XSCALE_CP15_COPRO_ACCESS = 15,
} mmu_regnum_t;
/* Bits in the control register */
#define CONTROL_MMU (1<<0)
#define CONTROL_ALIGN_FAULT (1<<1)
#define CONTROL_CACHE (1<<2)
#define CONTROL_DATA_CACHE (1<<2)
#define CONTROL_WRITE_BUFFER (1<<3)
#define CONTROL_BIG_ENDIAN (1<<7)
#define CONTROL_SYSTEM (1<<8)
#define CONTROL_ROM (1<<9)
#define CONTROL_UNDEFINED (1<<10)
#define CONTROL_BRANCH_PREDICT (1<<11)
#define CONTROL_INSTRUCTION_CACHE (1<<12)
#define CONTROL_VECTOR (1<<13)
#define CONTROL_RR (1<<14)
#define CONTROL_L4 (1<<15)
#define CONTROL_XP (1<<23)
#define CONTROL_EE (1<<25)
/*Macro defines for MMU state*/
#define MMU_CTL (state->mmu.control)
#define MMU_Enabled (state->mmu.control & CONTROL_MMU)
#define MMU_Disabled (!(MMU_Enabled))
#define MMU_Aligned (state->mmu.control & CONTROL_ALIGN_FAULT)
#define MMU_ICacheEnabled (MMU_CTL & CONTROL_INSTRUCTION_CACHE)
#define MMU_ICacheDisabled (!(MMU_ICacheDisabled))
#define MMU_DCacheEnabled (MMU_CTL & CONTROL_DATA_CACHE)
#define MMU_DCacheDisabled (!(MMU_DCacheEnabled))
#define MMU_CacheEnabled (MMU_CTL & CONTROL_CACHE)
#define MMU_CacheDisabled (!(MMU_CacheEnabled))
#define MMU_WBEnabled (MMU_CTL & CONTROL_WRITE_BUFFER)
#define MMU_WBDisabled (!(MMU_WBEnabled))
/*virt_addr exchange according to CP15.R13(process id virtul mapping)*/
#define PID_VA_MAP_MASK 0xfe000000
//#define mmu_pid_va_map(va) ({\
// ARMword ret; \
// if ((va) & PID_VA_MAP_MASK)\
// ret = (va); \
// else \
// ret = ((va) | (state->mmu.process_id & PID_VA_MAP_MASK));\
// ret;\
//})
#define mmu_pid_va_map(va) ((va) & PID_VA_MAP_MASK) ? (va) : ((va) | (state->mmu.process_id & PID_VA_MAP_MASK))
/* FS[3:0] in the fault status register: */
typedef enum fault_t
{
NO_FAULT = 0x0,
ALIGNMENT_FAULT = 0x1,
SECTION_TRANSLATION_FAULT = 0x5,
PAGE_TRANSLATION_FAULT = 0x7,
SECTION_DOMAIN_FAULT = 0x9,
PAGE_DOMAIN_FAULT = 0xB,
SECTION_PERMISSION_FAULT = 0xD,
SUBPAGE_PERMISSION_FAULT = 0xF,
/* defined by skyeye */
TLB_READ_MISS = 0x30,
TLB_WRITE_MISS = 0x40,
} fault_t;
typedef struct mmu_ops_s
{
/*initilization */
int (*init) (ARMul_State * state);
/*free on exit */
void (*exit) (ARMul_State * state);
/*read byte data */
fault_t (*read_byte) (ARMul_State * state, ARMword va,
ARMword * data);
/*write byte data */
fault_t (*write_byte) (ARMul_State * state, ARMword va,
ARMword data);
/*read halfword data */
fault_t (*read_halfword) (ARMul_State * state, ARMword va,
ARMword * data);
/*write halfword data */
fault_t (*write_halfword) (ARMul_State * state, ARMword va,
ARMword data);
/*read word data */
fault_t (*read_word) (ARMul_State * state, ARMword va,
ARMword * data);
/*write word data */
fault_t (*write_word) (ARMul_State * state, ARMword va,
ARMword data);
/*load instr */
fault_t (*load_instr) (ARMul_State * state, ARMword va,
ARMword * instr);
/*mcr */
ARMword (*mcr) (ARMul_State * state, ARMword instr, ARMword val);
/*mrc */
ARMword (*mrc) (ARMul_State * state, ARMword instr, ARMword * val);
/*ywc 2005-04-16 convert virtual address to physics address */
int (*v2p_dbct) (ARMul_State * state, ARMword virt_addr,
ARMword * phys_addr);
} mmu_ops_t;
#include "arm/mmu/tlb.h"
#include "arm/mmu/rb.h"
#include "arm/mmu/wb.h"
#include "arm/mmu/cache.h"
/*special process mmu.h*/
//#include "arm/mmu/sa_mmu.h"
//#include "arm/mmu/arm7100_mmu.h"
//#include "arm/mmu/arm920t_mmu.h"
//#include "arm/mmu/arm926ejs_mmu.h"
#include "arm/mmu/arm1176jzf_s_mmu.h"
//#include "arm/mmu/cortex_a9_mmu.h"
typedef struct mmu_state_t
{
ARMword control;
ARMword translation_table_base;
/* dyf 201-08-11 for arm1176 */
ARMword auxiliary_control;
ARMword coprocessor_access_control;
ARMword translation_table_base0;
ARMword translation_table_base1;
ARMword translation_table_ctrl;
/* arm1176 end */
ARMword domain_access_control;
ARMword fault_status;
ARMword fault_statusi; /* prefetch fault status */
ARMword fault_address;
ARMword last_domain;
ARMword process_id;
ARMword context_id;
ARMword thread_uro_id;
ARMword cache_locked_down;
ARMword tlb_locked_down;
//chy 2003-08-24 for xscale
ARMword cache_type; // 0
ARMword aux_control; // 1
ARMword copro_access; // 15
mmu_ops_t ops;
//union
//{
//sa_mmu_t sa_mmu;
//arm7100_mmu_t arm7100_mmu;
//arm920t_mmu_t arm920t_mmu;
//arm926ejs_mmu_t arm926ejs_mmu;
//} u;
} mmu_state_t;
int mmu_init (ARMul_State * state);
int mmu_reset (ARMul_State * state);
void mmu_exit (ARMul_State * state);
fault_t mmu_read_word (ARMul_State * state, ARMword virt_addr,
ARMword * data);
fault_t mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t mmu_load_instr (ARMul_State * state, ARMword virt_addr,
ARMword * instr);
ARMword mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value);
void mmu_mcr (ARMul_State * state, ARMword instr, ARMword value);
/*ywc 20050416*/
int mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
ARMword * phys_addr);
fault_t
mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t
mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t
mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
#endif /* _ARMMMU_H_ */

View file

@ -0,0 +1,742 @@
/* armos.c -- ARMulator OS interface: 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. */
/* This file contains a model of Demon, ARM Ltd's Debug Monitor,
including all the SWI's required to support the C library. The code in
it is not really for the faint-hearted (especially the abort handling
code), but it is a complete example. Defining NOOS will disable all the
fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
0x11 to halt the emulator. */
//chy 2005-09-12 disable below line
//#include "config.h"
#include <time.h>
#include <errno.h>
#include <string.h>
#include "skyeye_defs.h"
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64 /* When use 64 bit large file need define it! for stat64*/
#endif
#include <fcntl.h>
#include <sys/stat.h>
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_WRONLY
#define O_WRONLY 1
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifdef __STDC__
#define unlink(s) remove(s)
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* For SEEK_SET etc */
#endif
#ifdef __riscos
extern int _fisatty (FILE *);
#define isatty_(f) _fisatty(f)
#else
#ifdef __ZTC__
#include <io.h>
#define isatty_(f) isatty((f)->_file)
#else
#ifdef macintosh
#include <ioctl.h>
#define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
#else
#define isatty_(f) isatty (fileno (f))
#endif
#endif
#endif
#include "armdefs.h"
#include "armos.h"
#include "armemu.h"
#ifndef NOOS
#ifndef VALIDATE
/* #ifndef ASIM */
//chy 2005-09-12 disable below line
//#include "armfpe.h"
/* #endif */
#endif
#endif
#define DUMP_SYSCALL 0
#define dump(...) do { if (DUMP_SYSCALL) printf(__VA_ARGS__); } while(0)
//#define debug(...) printf(__VA_ARGS__);
#define debug(...) ;
extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
#ifndef FOPEN_MAX
#define FOPEN_MAX 64
#endif
/***************************************************************************\
* OS private Information *
\***************************************************************************/
unsigned arm_dyncom_SWI(ARMul_State * state, ARMword number)
{
return ARMul_OSHandleSWI(state, number);
}
//mmap_area_t *mmap_global = NULL;
static int translate_open_mode[] = {
O_RDONLY, /* "r" */
O_RDONLY + O_BINARY, /* "rb" */
O_RDWR, /* "r+" */
O_RDWR + O_BINARY, /* "r+b" */
O_WRONLY + O_CREAT + O_TRUNC, /* "w" */
O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */
O_RDWR + O_CREAT + O_TRUNC, /* "w+" */
O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */
O_WRONLY + O_APPEND + O_CREAT, /* "a" */
O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */
O_RDWR + O_APPEND + O_CREAT, /* "a+" */
O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */
};
//
//static void
//SWIWrite0 (ARMul_State * state, ARMword addr)
//{
// ARMword temp;
//
// //while ((temp = ARMul_ReadByte (state, addr++)) != 0)
// while(1){
// mem_read(8, addr++, &temp);
// if(temp != 0)
// (void) fputc ((char) temp, stdout);
// else
// break;
// }
//}
//
//static void
//WriteCommandLineTo (ARMul_State * state, ARMword addr)
//{
// ARMword temp;
// char *cptr = state->CommandLine;
// if (cptr == NULL)
// cptr = "\0";
// do {
// temp = (ARMword) * cptr++;
// //ARMul_WriteByte (state, addr++, temp);
// mem_write(8, addr++, temp);
// }
// while (temp != 0);
//}
//
//static void
//SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
//{
// char dummy[2000];
// int flags;
// int i;
//
// for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++);
// assert(SWIflags< (sizeof(translate_open_mode)/ sizeof(translate_open_mode[0])));
// /* Now we need to decode the Demon open mode */
// flags = translate_open_mode[SWIflags];
// flags = SWIflags;
//
// /* Filename ":tt" is special: it denotes stdin/out */
// if (strcmp (dummy, ":tt") == 0) {
// if (flags == O_RDONLY) /* opening tty "r" */
// state->Reg[0] = 0; /* stdin */
// else
// state->Reg[0] = 1; /* stdout */
// }
// else {
// state->Reg[0] = (int) open (dummy, flags, 0666);
// }
//}
//
//static void
//SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
//{
// int res;
// int i;
// char *local = (char*) malloc (len);
//
// if (local == NULL) {
// fprintf (stderr,
// "sim: Unable to read 0x%ulx bytes - out of memory\n",
// len);
// return;
// }
//
// res = read (f, local, len);
// if (res > 0)
// for (i = 0; i < res; i++)
// //ARMul_WriteByte (state, ptr + i, local[i]);
// mem_write(8, ptr + i, local[i]);
// free (local);
// //state->Reg[0] = res == -1 ? -1 : len - res;
// state->Reg[0] = res;
//}
//
//static void
//SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
//{
// int res;
// ARMword i;
// char *local = malloc (len);
//
// if (local == NULL) {
// fprintf (stderr,
// "sim: Unable to write 0x%lx bytes - out of memory\n",
// (long unsigned int) len);
// return;
// }
//
// for (i = 0; i < len; i++){
// //local[i] = ARMul_ReadByte (state, ptr + i);
// ARMword data;
// mem_read(8, ptr + i, &data);
// local[i] = data & 0xFF;
// }
//
// res = write (f, local, len);
// //state->Reg[0] = res == -1 ? -1 : len - res;
// state->Reg[0] = res;
// free (local);
//}
//static void
//SWIflen (ARMul_State * state, ARMword fh)
//{
// ARMword addr;
//
// if (fh == 0 || fh > FOPEN_MAX) {
// state->Reg[0] = -1L;
// return;
// }
//
// addr = lseek (fh, 0, SEEK_CUR);
//
// state->Reg[0] = lseek (fh, 0L, SEEK_END);
// (void) lseek (fh, addr, SEEK_SET);
//
//}
/***************************************************************************\
* The emulator calls this routine when a SWI instruction is encuntered. The *
* parameter passed is the SWI number (lower 24 bits of the instruction). *
\***************************************************************************/
/* ahe-ykl information is retrieved from elf header and the starting value of
brk_static is in sky_info_t */
/* brk static hold the value of brk */
static uint32_t brk_static = -1;
unsigned
ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
{
number &= 0xfffff;
ARMword addr, temp;
switch (number) {
// case SWI_Syscall:
// if (state->Reg[7] != 0)
// return ARMul_OSHandleSWI(state, state->Reg[7]);
// else
// return FALSE;
// case SWI_Read:
// SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
// return TRUE;
//
// case SWI_GetUID32:
// state->Reg[0] = getuid();
// return TRUE;
//
// case SWI_GetGID32:
// state->Reg[0] = getgid();
// return TRUE;
//
// case SWI_GetEUID32:
// state->Reg[0] = geteuid();
// return TRUE;
//
// case SWI_GetEGID32:
// state->Reg[0] = getegid();
// return TRUE;
//
// case SWI_Write:
// SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
// return TRUE;
//
// case SWI_Open:
// SWIopen (state, state->Reg[0], state->Reg[1]);
// return TRUE;
//
// case SWI_Close:
// state->Reg[0] = close (state->Reg[0]);
// return TRUE;
//
// case SWI_Seek:{
// /* We must return non-zero for failure */
// state->Reg[0] =
// lseek (state->Reg[0], state->Reg[1],
// SEEK_SET);
// return TRUE;
// }
//
// case SWI_ExitGroup:
// case SWI_Exit:
// {
// struct timeval tv;
// //gettimeofday(&tv,NULL);
// //printf("In %s, %d sec, %d usec\n", __FUNCTION__, tv.tv_sec, tv.tv_usec);
// printf("passed %d sec, %lld usec\n", get_clock_sec(), get_clock_us());
//
// /* quit here */
// run_command("quit");
// return TRUE;
// }
// case SWI_Times:{
// uint32_t dest = state->Reg[0];
// struct tms now;
// struct target_tms32 nowret;
//
// uint32_t ret = times(&now);
//
// if (ret == -1){
// debug("syscall %s error %d\n", "SWI_Times", ret);
// state->Reg[0] = ret;
// return FALSE;
// }
//
// nowret.tms_cstime = now.tms_cstime;
// nowret.tms_cutime = now.tms_cutime;
// nowret.tms_stime = now.tms_stime;
// nowret.tms_utime = now.tms_utime;
//
// uint32_t offset;
// for (offset = 0; offset < sizeof(nowret); offset++) {
// bus_write(8, dest + offset, *((uint8_t *) &nowret + offset));
// }
//
// state->Reg[0] = ret;
// return TRUE;
// }
//
// case SWI_Gettimeofday: {
// uint32_t dest1 = state->Reg[0];
// uint32_t dest2 = state->Reg[1]; // Unsure of this
// struct timeval val;
// struct timezone zone;
// struct target_timeval32 valret;
// struct target_timezone32 zoneret;
//
// uint32_t ret = gettimeofday(&val, &zone);
// valret.tv_sec = val.tv_sec;
// valret.tv_usec = val.tv_usec;
// zoneret.tz_dsttime = zoneret.tz_dsttime;
// zoneret.tz_minuteswest = zoneret.tz_minuteswest;
//
// if (ret == -1){
// debug("syscall %s error %d\n", "SWI_Gettimeofday", ret);
// state->Reg[0] = ret;
// return FALSE;
// }
//
// uint32_t offset;
// if (dest1) {
// for (offset = 0; offset < sizeof(valret); offset++) {
// bus_write(8, dest1 + offset, *((uint8_t *) &valret + offset));
// }
// state->Reg[0] = ret;
// }
// if (dest2) {
// for (offset = 0; offset < sizeof(zoneret); offset++) {
// bus_write(8, dest2 + offset, *((uint8_t *) &zoneret + offset));
// }
// state->Reg[0] = ret;
// }
//
// return TRUE;
// }
// case SWI_Brk:
// /* initialize brk value */
// /* suppose that brk_static doesn't reach 0xffffffff... */
// if (brk_static == -1) {
// brk_static = (get_skyeye_pref()->info).brk;
// }
//
// /* FIXME there might be a need to do a mmap */
//
// if(state->Reg[0]){
// if (get_skyeye_exec_info()->mmap_access) {
// /* if new brk is greater than current brk, allocate memory */
// if (state->Reg[0] > brk_static) {
// uint32_t ret = mmap( (void *) brk_static, state->Reg[0] - brk_static,
// PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0 );
// if (ret != MAP_FAILED)
// brk_static = ret;
// }
// }
// brk_static = state->Reg[0];
// //state->Reg[0] = 0; /* FIXME return value of brk set to be the address on success */
// } else {
// state->Reg[0] = brk_static;
// }
// return TRUE;
//
// case SWI_Break:
// state->Emulate = FALSE;
// return TRUE;
//
// case SWI_Mmap:{
// int addr = state->Reg[0];
// int len = state->Reg[1];
// int prot = state->Reg[2];
// int flag = state->Reg[3];
// int fd = state->Reg[4];
// int offset = state->Reg[5];
// mmap_area_t *area = new_mmap_area(addr, len);
// state->Reg[0] = area->bank.addr;
// //printf("syscall %d mmap(0x%x,%x,0x%x,0x%x,%d,0x%x) = 0x%x\n",\
// SWI_Mmap, addr, len, prot, flag, fd, offset, state->Reg[0]);
// return TRUE;
// }
//
// case SWI_Munmap:
// state->Reg[0] = 0;
// return TRUE;
//
// case SWI_Mmap2:{
// int addr = state->Reg[0];
// int len = state->Reg[1];
// int prot = state->Reg[2];
// int flag = state->Reg[3];
// int fd = state->Reg[4];
// int offset = state->Reg[5] * 4096; /* page offset */
// mmap_area_t *area = new_mmap_area(addr, len);
// state->Reg[0] = area->bank.addr;
//
// return TRUE;
// }
//
// case SWI_Breakpoint:
// //chy 2005-09-12 change below line
// //state->EndCondition = RDIError_BreakpointReached;
// //printf ("SKYEYE: in armos.c : should not come here!!!!\n");
// state->EndCondition = 0;
// /*modified by ksh to support breakpoiont*/
// state->Emulate = STOP;
// return (TRUE);
// case SWI_Uname:
// {
// struct utsname *uts = (uintptr_t) state->Reg[0]; /* uname should write data in this address */
// struct utsname utsbuf;
// //printf("Uname size is %x\n", sizeof(utsbuf));
// char *buf;
// uintptr_t sp ; /* used as a temporary address */
//
//#define COPY_UTS_STRING(addr) \
// buf = addr; \
// while(*buf != NULL) { \
// bus_write(8, sp, *buf); \
// sp++; \
// buf++; \
// }
//#define COPY_UTS(field) /*printf("%s: %s at %p\n", #field, utsbuf.field, uts->field);*/ \
// sp = (uintptr_t) uts->field; \
// COPY_UTS_STRING((&utsbuf)->field);
//
// if (uname(&utsbuf) < 0) {
// printf("syscall uname: utsname error\n");
// state->Reg[0] = -1;
// return FALSE;
// }
//
// /* FIXME for now, this is just the host system call
// Some data should be missing, as it depends on
// the version of utsname */
// COPY_UTS(sysname);
// COPY_UTS(nodename);
// COPY_UTS(release);
// COPY_UTS(version);
// COPY_UTS(machine);
//
// state->Reg[0] = 0;
// return TRUE;
// }
// case SWI_Fcntl:
// {
// uint32_t fd = state->Reg[0];
// uint32_t cmd = state->Reg[1];
// uint32_t arg = state->Reg[2];
// uint32_t ret;
//
// switch(cmd){
// case (F_GETFD):
// {
// ret = fcntl(fd, cmd, arg);
// //printf("syscall fcntl for getfd not implemented, ret %d\n", ret);
// state->Reg[0] = ret;
// return FALSE;
// }
// default:
// break;
// }
//
// printf("syscall fcntl unimplemented fd %x cmd %x\n", fd, cmd);
// state->Reg[0] = -1;
// return FALSE;
//
// }
// case SWI_Fstat64:
// {
// uint32_t dest = state->Reg[1];
// uint32_t fd = state->Reg[0];
// struct stat64 statbuf;
// struct target_stat64 statret;
// memset(&statret, 0, sizeof(struct target_stat64));
// uint32_t ret = fstat64(fd, &statbuf);
//
// if (ret == -1){
// printf("syscall %s returned error\n", "SWI_Fstat");
// state->Reg[0] = ret;
// return FALSE;
// }
//
// /* copy statbuf to the process memory space
// FIXME can't say if endian has an effect here */
// uint32_t offset;
// //printf("Fstat system is size %x\n", sizeof(statbuf));
// //printf("Fstat target is size %x\n", sizeof(statret));
//
// /* we copy system structure data stat64 into arm fixed size structure target_stat64 */
// statret.st_dev = statbuf.st_dev;
// statret.st_ino = statbuf.st_ino;
// statret.st_mode = statbuf.st_mode;
// statret.st_nlink = statbuf.st_nlink;
// statret.st_uid = statbuf.st_uid;
// statret.st_gid = statbuf.st_gid;
// statret.st_rdev = statbuf.st_rdev;
// statret.st_size = statbuf.st_size;
// statret.st_blksize = statbuf.st_blksize;
// statret.st_blocks = statbuf.st_blocks;
// statret.st32_atime = statbuf.st_atime;
// statret.st32_mtime = statbuf.st_mtime;
// statret.st32_ctime = statbuf.st_ctime;
//
// for (offset = 0; offset < sizeof(statret); offset++) {
// bus_write(8, dest + offset, *((uint8_t *) &statret + offset));
// }
//
// state->Reg[0] = ret;
// return TRUE;
// }
// case SWI_Set_tls:
// {
// //printf("syscall set_tls unimplemented\n");
// state->mmu.thread_uro_id = state->Reg[0];
// state->CP15[CP15_THREAD_URO - CP15_BASE] = state->Reg[0];
// state->Reg[0] = 0;
// return FALSE;
// }
//#if 0
// case SWI_Clock:
// /* return number of centi-seconds... */
// state->Reg[0] =
//#ifdef CLOCKS_PER_SEC
// (CLOCKS_PER_SEC >= 100)
// ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
// : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
//#else
// /* presume unix... clock() returns microseconds */
// (ARMword) (clock () / 10000);
//#endif
// return (TRUE);
//
// case SWI_Time:
// state->Reg[0] = (ARMword) time (NULL);
// return (TRUE);
// case SWI_Flen:
// SWIflen (state, state->Reg[0]);
// return (TRUE);
//
//#endif
default:
_dbg_assert_msg_(ARM11, false, "ImplementMe: ARMul_OSHandleSWI!");
return (FALSE);
}
}
//
///**
// * @brief For mmap syscall.A mmap_area is a memory bank. Get from ppc.
// */
//static mmap_area_t* new_mmap_area(int sim_addr, int len){
// mmap_area_t *area = (mmap_area_t *)malloc(sizeof(mmap_area_t));
// if(area == NULL){
// printf("error, failed %s\n",__FUNCTION__);
// exit(0);
// }
//#if FAST_MEMORY
// if (mmap_next_base == -1)
// {
// mmap_next_base = get_skyeye_exec_info()->brk;
// }
//#endif
//
// memset(area, 0x0, sizeof(mmap_area_t));
// area->bank.addr = mmap_next_base;
// area->bank.len = len;
// area->bank.bank_write = mmap_mem_write;
// area->bank.bank_read = mmap_mem_read;
// area->bank.type = MEMTYPE_RAM;
// area->bank.objname = "mmap";
// addr_mapping(&area->bank);
//
//#if FAST_MEMORY
// if (get_skyeye_exec_info()->mmap_access)
// {
// /* FIXME check proper flags */
// /* FIXME we may delete the need of banks up there */
// uint32_t ret = mmap(mmap_next_base, len, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// mmap_next_base = ret;
// }
// area->mmap_addr = (uint8_t*)get_dma_addr(mmap_next_base);
//#else
// area->mmap_addr = malloc(len);
// if(area->mmap_addr == NULL){
// printf("error mmap malloc\n");
// exit(0);
// }
// memset(area->mmap_addr, 0x0, len);
//#endif
//
// area->next = NULL;
// if(mmap_global){
// area->next = mmap_global->next;
// mmap_global->next = area;
// }else{
// mmap_global = area;
// }
// mmap_next_base = mmap_next_base + len;
// return area;
//}
//
//static mmap_area_t *get_mmap_area(int addr){
// mmap_area_t *tmp = mmap_global;
// while(tmp){
// if ((tmp->bank.addr <= addr) && (tmp->bank.addr + tmp->bank.len > addr)){
// return tmp;
// }
// tmp = tmp->next;
// }
// printf("cannot get mmap area:addr=0x%x\n", addr);
// return NULL;
//}
//
///**
// * @brief the mmap_area bank write function. Get from ppc.
// *
// * @param size size to write, 8/16/32
// * @param addr address to write
// * @param value value to write
// *
// * @return sucess return 1,otherwise 0.
// */
//static char mmap_mem_write(short size, int addr, uint32_t value){
// mmap_area_t *area_tmp = get_mmap_area(addr);
// mem_bank_t *bank_tmp = &area_tmp->bank;
// int offset = addr - bank_tmp->addr;
// switch(size){
// case 8:{
// //uint8_t value_endian = value;
// uint8_t value_endian = (uint8_t)value;
// *(uint8_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
// break;
// }
// case 16:{
// //uint16_t value_endian = half_to_BE((uint16_t)value);
// uint16_t value_endian = ((uint16_t)value);
// *(uint16_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
// break;
// }
// case 32:{
// //uint32_t value_endian = word_to_BE((uint32_t)value);
// uint32_t value_endian = ((uint32_t)value);
// *(uint32_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
// break;
// }
// default:
// printf("invalid size %d\n",size);
// return 0;
// }
// return 1;
//}
//
///**
// * @brief the mmap_area bank read function. Get from ppc.
// *
// * @param size size to read, 8/16/32
// * @param addr address to read
// * @param value value to read
// *
// * @return sucess return 1,otherwise 0.
// */
//static char mmap_mem_read(short size, int addr, uint32_t * value){
// mmap_area_t *area_tmp = get_mmap_area(addr);
// mem_bank_t *bank_tmp = &area_tmp->bank;
// int offset = addr - bank_tmp->addr;
// switch(size){
// case 8:{
// //*(uint8_t *)value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
// *value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
// break;
// }
// case 16:{
// //*(uint16_t *)value = half_from_BE(*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// *value = (*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint16_t*)value);
// break;
// }
// case 32:
// //*value = (uint32_t)word_from_BE(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// *value = (uint32_t)(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
// break;
// default:
// printf("invalid size %d\n",size);
// return 0;
// }
// return 1;
//}

View file

@ -0,0 +1,138 @@
/* armos.h -- ARMulator OS definitions: 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 "bank_defs.h"
//#include "dyncom/defines.h"
//typedef struct mmap_area{
// mem_bank_t bank;
// void *mmap_addr;
// struct mmap_area *next;
//}mmap_area_t;
#if FAST_MEMORY
/* in user mode, mmap_base will be on initial brk,
set at the first mmap request */
#define mmap_base -1
#else
#define mmap_base 0x50000000
#endif
static long mmap_next_base = mmap_base;
//static mmap_area_t* new_mmap_area(int sim_addr, int len);
static char mmap_mem_write(short size, int addr, uint32_t value);
static char mmap_mem_read(short size, int addr, uint32_t * value);
/***************************************************************************\
* SWI numbers *
\***************************************************************************/
#define SWI_Syscall 0x0
#define SWI_Exit 0x1
#define SWI_Read 0x3
#define SWI_Write 0x4
#define SWI_Open 0x5
#define SWI_Close 0x6
#define SWI_Seek 0x13
#define SWI_Rename 0x26
#define SWI_Break 0x11
#define SWI_Times 0x2b
#define SWI_Brk 0x2d
#define SWI_Mmap 0x5a
#define SWI_Munmap 0x5b
#define SWI_Mmap2 0xc0
#define SWI_GetUID32 0xc7
#define SWI_GetGID32 0xc8
#define SWI_GetEUID32 0xc9
#define SWI_GetEGID32 0xca
#define SWI_ExitGroup 0xf8
#if 0
#define SWI_Time 0xd
#define SWI_Clock 0x61
#define SWI_Time 0x63
#define SWI_Remove 0x64
#define SWI_Rename 0x65
#define SWI_Flen 0x6c
#endif
#define SWI_Uname 0x7a
#define SWI_Fcntl 0xdd
#define SWI_Fstat64 0xc5
#define SWI_Gettimeofday 0x4e
#define SWI_Set_tls 0xf0005
#define SWI_Breakpoint 0x180000 /* see gdb's tm-arm.h */
/***************************************************************************\
* SWI structures *
\***************************************************************************/
/* Arm binaries (for now) only support 32 bit, and expect to receive
32-bit compliant structure in return of a systen call. Because
we use host system calls to emulate system calls, the returned
structure can be 32-bit compliant or 64-bit compliant, depending
on the OS running skyeye. Therefore, we need a fixed size structure
adapted to arm.*/
/* Borrowed from qemu */
struct target_stat64 {
unsigned short st_dev;
unsigned char __pad0[10];
uint32_t __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
uint32_t st_uid;
uint32_t st_gid;
unsigned short st_rdev;
unsigned char __pad3[10];
unsigned char __pad31[4];
long long st_size;
uint32_t st_blksize;
unsigned char __pad32[4];
uint32_t st_blocks;
uint32_t __pad4;
uint32_t st32_atime;
uint32_t __pad5;
uint32_t st32_mtime;
uint32_t __pad6;
uint32_t st32_ctime;
uint32_t __pad7;
unsigned long long st_ino;
};// __attribute__((packed));
struct target_tms32 {
uint32_t tms_utime;
uint32_t tms_stime;
uint32_t tms_cutime;
uint32_t tms_cstime;
};
struct target_timeval32 {
uint32_t tv_sec; /* seconds */
uint32_t tv_usec; /* microseconds */
};
struct target_timezone32 {
int32_t tz_minuteswest; /* minutes west of Greenwich */
int32_t tz_dsttime; /* type of DST correction */
};

View file

@ -0,0 +1,954 @@
/* 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"
#include "skyeye_defs.h"
unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
unsigned cpnum);
//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. */
ARMword
ARMul_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. */
void
ARMul_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. */
ARMword
ARMul_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. */
ARMword
ARMul_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. */
void
ARMul_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. */
ARMword
ARMul_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. */
void
ARMul_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. */
ARMword
ARMul_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
// NOTE(bunnei): Changed this from [now] commented out macro "CPSR"
return ((ECC | EINT | EMODE | (TFLAG << 5))); //had be tested in old skyeye with gdb5.0-5.3
}
/* This routine sets the value of the CPSR. */
void
ARMul_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. */
void
ARMul_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. */
ARMword
ARMul_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. */
void
ARMul_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. */
void
ARMul_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. */
void
ARMul_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. */
void
ARMul_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. */
ARMword
ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
{
unsigned i;
ARMword oldbank;
ARMword newbank;
static int revision_value = 53;
oldbank = ModeToBank (oldmode);
newbank = state->Bank = ModeToBank (newmode);
/* Do we really need to do it? */
if (oldbank != newbank) {
if (oldbank == 3 && newbank == 2) {
//printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank);
if (state->NumInstrs >= 5832487) {
// printf("%d, ", state->NumInstrs + revision_value);
// printf("revision_value : %d\n", revision_value);
revision_value ++;
}
}
/* 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 ARMword
ModeToBank (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. */
unsigned
ARMul_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. */
void
ARMul_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. */
int
AddOverflow (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. */
int
SubOverflow (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. */
void
ARMul_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
ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNV (AddOverflow (a, b, result));
}
/* Assigns the C flag after an subtraction of a and b to give result. */
void
ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNC ((NEG (a) && POS (b)) ||
(NEG (a) && POS (result)) || (POS (b) && POS (result)));
}
/* Assigns the V flag after an subtraction of a and b to give result. */
void
ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNV (SubOverflow (a, b, result));
}
/* This function does the work of generating the addresses used in an
LDC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
modification. It also handles the Busy-Waiting. */
void
ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
{
unsigned cpab;
ARMword data;
UNDEF_LSCPCBaseWb;
//printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
/*chy 2004-05-23 should update this function in the future,should concern dataabort*/
// chy 2004-05-25 , fix it now,so needn't printf
// printf("SKYEYE ARMul_LDC, should update this function!!!!!\n");
//exit(-1);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
/*
printf
("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
ARMul_UndefInstr (state, instr);
return;
}
if (ADDREXCEPT (address))
INTERNALABORT (address);
cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return;
}
else
cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr,
0);
}
if (cpab == ARMul_CANT) {
/*
printf
("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
CPTAKEABORT;
return;
}
cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
data = ARMul_LoadWordN (state, address);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_ldc_takeabort;
BUSUSEDINCPCN;
//chy 2004-05-25
/*
if (BIT (21))
LSBase = state->Base;
*/
cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
while (cpab == ARMul_INC) {
address += 4;
data = ARMul_LoadWordN (state, address);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_ldc_takeabort;
cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
}
//chy 2004-05-25
L_ldc_takeabort:
if (BIT (21)) {
if (!
((state->abortSig || state->Aborted)
&& state->lateabtSig == LOW))
LSBase = state->Base;
}
if (state->abortSig || state->Aborted)
TAKEABORT;
}
/* This function does the work of generating the addresses used in an
STC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
modification. It also handles the Busy-Waiting. */
void
ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
{
unsigned cpab;
ARMword data;
UNDEF_LSCPCBaseWb;
//printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
/*chy 2004-05-23 should update this function in the future,should concern dataabort */
// skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n");
// chy 2004-05-25 , fix it now,so needn't printf
// printf("SKYEYE ARMul_STC, should update this function!!!!!\n");
//exit(-1);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
/*
printf
("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
ARMul_UndefInstr (state, instr);
return;
}
if (ADDREXCEPT (address) || VECTORACCESS (address))
INTERNALABORT (address);
cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return;
}
else
cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr,
&data);
}
if (cpab == ARMul_CANT) {
/*
printf
("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
CPTAKEABORT;
return;
}
#ifndef MODE32
if (ADDREXCEPT (address) || VECTORACCESS (address))
INTERNALABORT (address);
#endif
BUSUSEDINCPCN;
//chy 2004-05-25
/*
if (BIT (21))
LSBase = state->Base;
*/
cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
ARMul_StoreWordN (state, address, data);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_stc_takeabort;
while (cpab == ARMul_INC) {
address += 4;
cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
ARMul_StoreWordN (state, address, data);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_stc_takeabort;
}
//chy 2004-05-25
L_stc_takeabort:
if (BIT (21)) {
if (!
((state->abortSig || state->Aborted)
&& state->lateabtSig == LOW))
LSBase = state->Base;
}
if (state->abortSig || state->Aborted)
TAKEABORT;
}
/* This function does the Busy-Waiting for an MCR instruction. */
void
ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
{
unsigned cpab;
//printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
//chy 2004-07-19 should fix in the future ????!!!!
//printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source);
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return;
}
else
cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr,
source);
}
if (cpab == ARMul_CANT) {
printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
}
}
/* This function does the Busy-Waiting for an MCRR instruction. */
void
ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2)
{
unsigned cpab;
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT,
instr, 0, 0);
return;
}
else
cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr,
source1, source2);
}
if (cpab == ARMul_CANT) {
printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
}
}
/* This function does the Busy-Waiting for an MRC instruction. */
ARMword
ARMul_MRC (ARMul_State * state, ARMword instr)
{
unsigned cpab;
ARMword result = 0;
//printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
//chy 2004-07-19 should fix in the future????!!!!
//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr);
ARMul_UndefInstr (state, instr);
return -1;
}
cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return (0);
}
else
cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
&result);
}
if (cpab == ARMul_CANT) {
printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
/* Parent will destroy the flags otherwise. */
result = ECC;
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
ARMul_Icycles (state, 1, 0);
}
return result;
}
/* This function does the Busy-Waiting for an MRRC instruction. (to verify) */
void
ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2)
{
unsigned cpab;
ARMword result1 = 0;
ARMword result2 = 0;
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0, 0);
return;
}
else
cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr,
&result1, &result2);
}
if (cpab == ARMul_CANT) {
printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
ARMul_Icycles (state, 1, 0);
}
*dest1 = result1;
*dest2 = result2;
}
/* This function does the Busy-Waiting for an CDP instruction. */
void
ARMul_CDP (ARMul_State * state, ARMword instr)
{
unsigned cpab;
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT,
instr);
return;
}
else
cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
}
if (cpab == ARMul_CANT)
ARMul_Abort (state, ARMul_UndefinedInstrV);
else
BUSUSEDN;
}
/* This function handles Undefined instructions, as CP isntruction. */
void
ARMul_UndefInstr (ARMul_State * state, ARMword instr)
{
ERROR_LOG(ARM11, "Undefined instruction!! Instr: 0x%x", instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
/* Return TRUE if an interrupt is pending, FALSE otherwise. */
unsigned
IntPending (ARMul_State * state)
{
/* Any exceptions. */
if (state->NresetSig == LOW) {
ARMul_Abort (state, ARMul_ResetV);
return TRUE;
}
else if (!state->NfiqSig && !FFLAG) {
ARMul_Abort (state, ARMul_FIQV);
return TRUE;
}
else if (!state->NirqSig && !IFLAG) {
ARMul_Abort (state, ARMul_IRQV);
return TRUE;
}
return FALSE;
}
/* Align a word access to a non word boundary. */
ARMword
ARMul_Align (ARMul_State *state, ARMword address, ARMword data)
{
/* This code assumes the address is really unaligned,
as a shift by 32 is undefined in C. */
address = (address & 3) << 3; /* Get the word address. */
return ((data >> address) | (data << (32 - address))); /* rot right */
}
/* This routine is used to call another routine after a certain number of
cycles have been executed. The first parameter is the number of cycles
delay before the function is called, the second argument is a pointer
to the function. A delay of zero doesn't work, just call the function. */
void
ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
unsigned (*what) (ARMul_State *))
{
unsigned int when;
struct EventNode *event;
if (state->EventSet++ == 0)
state->Now = ARMul_Time (state);
when = (state->Now + delay) % EVENTLISTSIZE;
event = (struct EventNode *) malloc (sizeof (struct EventNode));
_dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n");
event->func = what;
event->next = *(state->EventPtr + when);
*(state->EventPtr + when) = event;
}
/* This routine is called at the beginning of
every cycle, to envoke scheduled events. */
void
ARMul_EnvokeEvent (ARMul_State * state)
{
static unsigned int then;
then = state->Now;
state->Now = ARMul_Time (state) % EVENTLISTSIZE;
if (then < state->Now)
/* Schedule events. */
EnvokeList (state, then, state->Now);
else if (then > state->Now) {
/* Need to wrap around the list. */
EnvokeList (state, then, EVENTLISTSIZE - 1L);
EnvokeList (state, 0L, state->Now);
}
}
/* Envokes all the entries in a range. */
static void
EnvokeList (ARMul_State * state, unsigned int from, unsigned int to)
{
for (; from <= to; from++) {
struct EventNode *anevent;
anevent = *(state->EventPtr + from);
while (anevent) {
(anevent->func) (state);
state->EventSet--;
anevent = anevent->next;
}
*(state->EventPtr + from) = NULL;
}
}
/* This routine is returns the number of clock ticks since the last reset. */
unsigned int
ARMul_Time (ARMul_State * state)
{
return (state->NumScycles + state->NumNcycles +
state->NumIcycles + state->NumCcycles + state->NumFcycles);
}

View file

@ -0,0 +1,680 @@
/* armvirt.c -- ARMulator virtual memory interace: 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. */
/* This file contains a complete ARMulator memory model, modelling a
"virtual memory" system. A much simpler model can be found in armfast.c,
and that model goes faster too, but has a fixed amount of memory. This
model's memory has 64K pages, allocated on demand from a 64K entry page
table. The routines PutWord and GetWord implement this. Pages are never
freed as they might be needed again. A single area of memory may be
defined to generate aborts. */
#include "armdefs.h"
#include "skyeye_defs.h"
//#include "code_cov.h"
#ifdef VALIDATE /* for running the validate suite */
#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
#define ABORTS 1
#endif
/* #define ABORTS */
#ifdef ABORTS /* the memory system will abort */
/* For the old test suite Abort between 32 Kbytes and 32 Mbytes
For the new test suite Abort between 8 Mbytes and 26 Mbytes */
/* #define LOWABORT 32 * 1024
#define HIGHABORT 32 * 1024 * 1024 */
#define LOWABORT 8 * 1024 * 1024
#define HIGHABORT 26 * 1024 * 1024
#endif
#define NUMPAGES 64 * 1024
#define PAGESIZE 64 * 1024
#define PAGEBITS 16
#define OFFSETBITS 0xffff
//chy 2003-08-19: seems no use ????
int SWI_vector_installed = FALSE;
extern ARMword skyeye_cachetype;
/***************************************************************************\
* Get a byte into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetByte (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_byte (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: GetByte fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Get a halfword into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetHalfWord (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_halfword (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: GetHalfWord fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Get a Word from Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetWord (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_word (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
#if 0
/* XXX */ extern int hack;
hack = 1;
#endif
#if 0
printf ("mmu_read_word at 0x%08x: ", address);
switch (fault) {
case ALIGNMENT_FAULT:
printf ("ALIGNMENT_FAULT");
break;
case SECTION_TRANSLATION_FAULT:
printf ("SECTION_TRANSLATION_FAULT");
break;
case PAGE_TRANSLATION_FAULT:
printf ("PAGE_TRANSLATION_FAULT");
break;
case SECTION_DOMAIN_FAULT:
printf ("SECTION_DOMAIN_FAULT");
break;
case SECTION_PERMISSION_FAULT:
printf ("SECTION_PERMISSION_FAULT");
break;
case SUBPAGE_PERMISSION_FAULT:
printf ("SUBPAGE_PERMISSION_FAULT");
break;
default:
printf ("Unrecognized fault number!");
}
printf ("\tpc = 0x%08x\n", state->Reg[15]);
#endif
}
return fault;
}
//2003-07-10 chy: lyh change
/****************************************************************************\
* Load a Instrion Word into Virtual Memory *
\****************************************************************************/
static fault_t
LoadInstr (ARMul_State * state, ARMword address, ARMword * instr)
{
fault_t fault;
fault = mmu_load_instr (state, address, instr);
return fault;
//if (fault)
// log_msg("load_instr fault = %d, address = %x\n", fault, address);
}
/***************************************************************************\
* Put a byte into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_byte (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: PutByte fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Put a halfword into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_halfword (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: PutHalfWord fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Put a Word into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_word (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
#if 0
/* XXX */ extern int hack;
hack = 1;
#endif
#if 0
printf ("mmu_write_word at 0x%08x: ", address);
switch (fault) {
case ALIGNMENT_FAULT:
printf ("ALIGNMENT_FAULT");
break;
case SECTION_TRANSLATION_FAULT:
printf ("SECTION_TRANSLATION_FAULT");
break;
case PAGE_TRANSLATION_FAULT:
printf ("PAGE_TRANSLATION_FAULT");
break;
case SECTION_DOMAIN_FAULT:
printf ("SECTION_DOMAIN_FAULT");
break;
case SECTION_PERMISSION_FAULT:
printf ("SECTION_PERMISSION_FAULT");
break;
case SUBPAGE_PERMISSION_FAULT:
printf ("SUBPAGE_PERMISSION_FAULT");
break;
default:
printf ("Unrecognized fault number!");
}
printf ("\tpc = 0x%08x\n", state->Reg[15]);
#endif
}
return fault;
}
/***************************************************************************\
* Initialise the memory interface *
\***************************************************************************/
unsigned
ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize)
{
return TRUE;
}
/***************************************************************************\
* Remove the memory interface *
\***************************************************************************/
void
ARMul_MemoryExit (ARMul_State * state)
{
}
/***************************************************************************\
* ReLoad Instruction *
\***************************************************************************/
ARMword
ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
{
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
#endif
#if 0
/* do profiling for code coverage */
if (skyeye_config.code_cov.prof_on)
cov_prof(EXEC_FLAG, address);
#endif
#if 1
if ((isize == 2) && (address & 0x2)) {
ARMword lo, hi;
if (!(skyeye_cachetype == INSTCACHE))
fault = GetHalfWord (state, address, &lo);
else
fault = LoadInstr (state, address, &lo);
#if 0
if (!fault) {
if (!(skyeye_cachetype == INSTCACHE))
fault = GetHalfWord (state, address + isize, &hi);
else
fault = LoadInstr (state, address + isize, &hi);
}
#endif
if (fault) {
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return lo;
#if 0
if (state->bigendSig == HIGH)
return (lo << 16) | (hi >> 16);
else
return ((hi & 0xFFFF) << 16) | (lo >> 16);
#endif
}
#endif
if (!(skyeye_cachetype == INSTCACHE))
fault = GetWord (state, address, &data);
else
fault = LoadInstr (state, address, &data);
if (fault) {
/* dyf add for s3c6410 no instcache temporary 2010.9.17 */
if (!(skyeye_cachetype == INSTCACHE)) {
/* set translation fault on prefetch abort */
state->mmu.fault_statusi = fault & 0xFF;
state->mmu.fault_address = address;
}
/* add end */
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Instruction, Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
{
state->NumScycles++;
#ifdef HOURGLASS
if ((state->NumScycles & HOURGLASS_RATE) == 0) {
HOURGLASS;
}
#endif
return ARMul_ReLoadInstr (state, address, isize);
}
/***************************************************************************\
* Load Instruction, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
{
state->NumNcycles++;
return ARMul_ReLoadInstr (state, address, isize);
}
/***************************************************************************\
* Read Word (but don't tell anyone!) *
\***************************************************************************/
ARMword
ARMul_ReadWord (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
#endif
fault = GetWord (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Word, Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadWordS (ARMul_State * state, ARMword address)
{
state->NumScycles++;
return ARMul_ReadWord (state, address);
}
/***************************************************************************\
* Load Word, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadWordN (ARMul_State * state, ARMword address)
{
state->NumNcycles++;
return ARMul_ReadWord (state, address);
}
/***************************************************************************\
* Load Halfword, (Non Sequential Cycle) *
\***************************************************************************/
ARMword
ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
state->NumNcycles++;
fault = GetHalfWord (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Read Byte (but don't tell anyone!) *
\***************************************************************************/
int ARMul_ICE_ReadByte(ARMul_State * state, ARMword address, ARMword *presult)
{
ARMword data;
fault_t fault;
fault = GetByte (state, address, &data);
if (fault) {
*presult=-1; fault=ALIGNMENT_FAULT; return fault;
}else{
*(char *)presult=(unsigned char)(data & 0xff); fault=NO_FAULT; return fault;
}
}
ARMword
ARMul_ReadByte (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
fault = GetByte (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Byte, (Non Sequential Cycle) *
\***************************************************************************/
ARMword
ARMul_LoadByte (ARMul_State * state, ARMword address)
{
state->NumNcycles++;
return ARMul_ReadByte (state, address);
}
/***************************************************************************\
* Write Word (but don't tell anyone!) *
\***************************************************************************/
void
ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
#endif
fault = PutWord (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
/***************************************************************************\
* Store Word, Sequential Cycle *
\***************************************************************************/
void
ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
{
state->NumScycles++;
ARMul_WriteWord (state, address, data);
}
/***************************************************************************\
* Store Word, Non Sequential Cycle *
\***************************************************************************/
void
ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
ARMul_WriteWord (state, address, data);
}
/***************************************************************************\
* Store HalfWord, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
state->NumNcycles++;
fault = PutHalfWord (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
//chy 2006-04-15
int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = PutByte (state, address, data);
if (fault)
return 1;
else
return 0;
}
/***************************************************************************\
* Write Byte (but don't tell anyone!) *
\***************************************************************************/
//chy 2003-07-10, add real write byte fun
void
ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = PutByte (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
/***************************************************************************\
* Store Byte, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
#ifdef VALIDATE
if (address == TUBE) {
if (data == 4)
state->Emulate = FALSE;
else
(void) putc ((char) data, stderr); /* Write Char */
return;
}
#endif
ARMul_WriteByte (state, address, data);
}
/***************************************************************************\
* Swap Word, (Two Non Sequential Cycles) *
\***************************************************************************/
ARMword
ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
{
ARMword temp;
state->NumNcycles++;
temp = ARMul_ReadWord (state, address);
state->NumNcycles++;
PutWord (state, address, data);
return temp;
}
/***************************************************************************\
* Swap Byte, (Two Non Sequential Cycles) *
\***************************************************************************/
ARMword
ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
{
ARMword temp;
temp = ARMul_LoadByte (state, address);
ARMul_StoreByte (state, address, data);
return temp;
}
/***************************************************************************\
* Count I Cycles *
\***************************************************************************/
void
ARMul_Icycles (ARMul_State * state, unsigned number,
ARMword address)
{
state->NumIcycles += number;
ARMul_CLEARABORT;
}
/***************************************************************************\
* Count C Cycles *
\***************************************************************************/
void
ARMul_Ccycles (ARMul_State * state, unsigned number,
ARMword address)
{
state->NumCcycles += number;
ARMul_CLEARABORT;
}

View file

@ -0,0 +1,111 @@
#ifndef CORE_ARM_SKYEYE_DEFS_H_
#define CORE_ARM_SKYEYE_DEFS_H_
#include "common.h"
#define MODE32
#define MODET
typedef struct
{
const char *cpu_arch_name; /*cpu architecture version name.e.g. armv4t */
const char *cpu_name; /*cpu name. e.g. arm7tdmi or arm720t */
u32 cpu_val; /*CPU value; also call MMU ID or processor id;see
ARM Architecture Reference Manual B2-6 */
u32 cpu_mask; /*cpu_val's mask. */
u32 cachetype; /*this cpu has what kind of cache */
} cpu_config_t;
typedef struct conf_object_s{
char* objname;
void* obj;
char* class_name;
}conf_object_t;
typedef enum{
/* No exception */
No_exp = 0,
/* Memory allocation exception */
Malloc_exp,
/* File open exception */
File_open_exp,
/* DLL open exception */
Dll_open_exp,
/* Invalid argument exception */
Invarg_exp,
/* Invalid module exception */
Invmod_exp,
/* wrong format exception for config file parsing */
Conf_format_exp,
/* some reference excess the predefiend range. Such as the index out of array range */
Excess_range_exp,
/* Can not find the desirable result */
Not_found_exp,
/* Unknown exception */
Unknown_exp
}exception_t;
typedef enum {
Align = 0,
UnAlign
}align_t;
typedef enum {
Little_endian = 0,
Big_endian
}endian_t;
//typedef int exception_t;
typedef enum{
Phys_addr = 0,
Virt_addr
}addr_type_t;
typedef exception_t(*read_byte_t)(conf_object_t* target, u32 addr, void *buf, size_t count);
typedef exception_t(*write_byte_t)(conf_object_t* target, u32 addr, const void *buf, size_t count);
typedef struct memory_space{
conf_object_t* conf_obj;
read_byte_t read;
write_byte_t write;
}memory_space_intf;
/*
* a running instance for a specific archteciture.
*/
typedef struct generic_arch_s
{
char* arch_name;
void (*init) (void);
void (*reset) (void);
void (*step_once) (void);
void (*set_pc)(u32 addr);
u32 (*get_pc)(void);
u32 (*get_step)(void);
//chy 2004-04-15
//int (*ICE_write_byte) (u32 addr, uint8_t v);
//int (*ICE_read_byte)(u32 addr, uint8_t *pv);
u32 (*get_regval_by_id)(int id);
u32 (*get_regnum)(void);
char* (*get_regname_by_id)(int id);
exception_t (*set_regval_by_id)(int id, u32 value);
/*
* read a data by virtual address.
*/
exception_t (*mmu_read)(short size, u32 addr, u32 * value);
/*
* write a data by a virtual address.
*/
exception_t (*mmu_write)(short size, u32 addr, u32 value);
/**
* get a signal from external
*/
//exception_t (*signal)(interrupt_signal_t* signal);
endian_t endianess;
align_t alignment;
} generic_arch_t;
#endif

View file

@ -0,0 +1,513 @@
/* thumbemu.c -- Thumb instruction emulation.
Copyright (C) 1996, Cygnus Software Technologies 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. */
/* We can provide simple Thumb simulation by decoding the Thumb
instruction into its corresponding ARM instruction, and using the
existing ARM simulator. */
#include "skyeye_defs.h"
#ifndef MODET /* required for the Thumb instruction support */
#if 1
#error "MODET needs to be defined for the Thumb world to work"
#else
#define MODET (1)
#endif
#endif
#include "armdefs.h"
#include "armemu.h"
#include "armos.h"
/* Decode a 16bit Thumb instruction. The instruction is in the low
16-bits of the tinstr field, with the following Thumb instruction
held in the high 16-bits. Passing in two Thumb instructions allows
easier simulation of the special dual BL instruction. */
tdstate
ARMul_ThumbDecode (
ARMul_State *state,
ARMword pc,
ARMword tinstr,
ARMword *ainstr)
{
tdstate valid = t_decoded; /* default assumes a valid instruction */
ARMword next_instr;
if (state->bigendSig) {
next_instr = tinstr & 0xFFFF;
tinstr >>= 16;
}
else {
next_instr = tinstr >> 16;
tinstr &= 0xFFFF;
}
#if 1 /* debugging to catch non updates */
*ainstr = 0xDEADC0DE;
#endif
switch ((tinstr & 0xF800) >> 11) {
case 0: /* LSL */
case 1: /* LSR */
case 2: /* ASR */
/* Format 1 */
*ainstr = 0xE1B00000 /* base opcode */
| ((tinstr & 0x1800) >> (11 - 5)) /* shift type */
|((tinstr & 0x07C0) << (7 - 6)) /* imm5 */
|((tinstr & 0x0038) >> 3) /* Rs */
|((tinstr & 0x0007) << 12); /* Rd */
break;
case 3: /* ADD/SUB */
/* Format 2 */
{
ARMword subset[4] = {
0xE0900000, /* ADDS Rd,Rs,Rn */
0xE0500000, /* SUBS Rd,Rs,Rn */
0xE2900000, /* ADDS Rd,Rs,#imm3 */
0xE2500000 /* SUBS Rd,Rs,#imm3 */
};
/* It is quicker indexing into a table, than performing switch
or conditionals: */
*ainstr = subset[(tinstr & 0x0600) >> 9] /* base opcode */
|((tinstr & 0x01C0) >> 6) /* Rn or imm3 */
|((tinstr & 0x0038) << (16 - 3)) /* Rs */
|((tinstr & 0x0007) << (12 - 0)); /* Rd */
}
break;
case 4: /* MOV */
case 5: /* CMP */
case 6: /* ADD */
case 7: /* SUB */
/* Format 3 */
{
ARMword subset[4] = {
0xE3B00000, /* MOVS Rd,#imm8 */
0xE3500000, /* CMP Rd,#imm8 */
0xE2900000, /* ADDS Rd,Rd,#imm8 */
0xE2500000, /* SUBS Rd,Rd,#imm8 */
};
*ainstr = subset[(tinstr & 0x1800) >> 11] /* base opcode */
|((tinstr & 0x00FF) >> 0) /* imm8 */
|((tinstr & 0x0700) << (16 - 8)) /* Rn */
|((tinstr & 0x0700) << (12 - 8)); /* Rd */
}
break;
case 8: /* Arithmetic and high register transfers */
/* TODO: Since the subsets for both Format 4 and Format 5
instructions are made up of different ARM encodings, we could
save the following conditional, and just have one large
subset. */
if ((tinstr & (1 << 10)) == 0) {
/* Format 4 */
enum OpcodeType { t_norm, t_shift, t_neg, t_mul };
struct ThumbOpcode {
ARMword opcode;
OpcodeType otype;
};
ThumbOpcode subset[16] = {
{
0xE0100000, t_norm}, /* ANDS Rd,Rd,Rs */
{
0xE0300000, t_norm}, /* EORS Rd,Rd,Rs */
{
0xE1B00010, t_shift}, /* MOVS Rd,Rd,LSL Rs */
{
0xE1B00030, t_shift}, /* MOVS Rd,Rd,LSR Rs */
{
0xE1B00050, t_shift}, /* MOVS Rd,Rd,ASR Rs */
{
0xE0B00000, t_norm}, /* ADCS Rd,Rd,Rs */
{
0xE0D00000, t_norm}, /* SBCS Rd,Rd,Rs */
{
0xE1B00070, t_shift}, /* MOVS Rd,Rd,ROR Rs */
{
0xE1100000, t_norm}, /* TST Rd,Rs */
{
0xE2700000, t_neg}, /* RSBS Rd,Rs,#0 */
{
0xE1500000, t_norm}, /* CMP Rd,Rs */
{
0xE1700000, t_norm}, /* CMN Rd,Rs */
{
0xE1900000, t_norm}, /* ORRS Rd,Rd,Rs */
{
0xE0100090, t_mul}, /* MULS Rd,Rd,Rs */
{
0xE1D00000, t_norm}, /* BICS Rd,Rd,Rs */
{
0xE1F00000, t_norm} /* MVNS Rd,Rs */
};
*ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; /* base */
switch (subset[(tinstr & 0x03C0) >> 6].otype) {
case t_norm:
*ainstr |= ((tinstr & 0x0007) << 16) /* Rn */
|((tinstr & 0x0007) << 12) /* Rd */
|((tinstr & 0x0038) >> 3); /* Rs */
break;
case t_shift:
*ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
|((tinstr & 0x0007) >> 0) /* Rm */
|((tinstr & 0x0038) << (8 - 3)); /* Rs */
break;
case t_neg:
*ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
|((tinstr & 0x0038) << (16 - 3)); /* Rn */
break;
case t_mul:
*ainstr |= ((tinstr & 0x0007) << 16) /* Rd */
|((tinstr & 0x0007) << 8) /* Rs */
|((tinstr & 0x0038) >> 3); /* Rm */
break;
}
}
else {
/* Format 5 */
ARMword Rd = ((tinstr & 0x0007) >> 0);
ARMword Rs = ((tinstr & 0x0038) >> 3);
if (tinstr & (1 << 7))
Rd += 8;
if (tinstr & (1 << 6))
Rs += 8;
switch ((tinstr & 0x03C0) >> 6) {
case 0x1: /* ADD Rd,Rd,Hs */
case 0x2: /* ADD Hd,Hd,Rs */
case 0x3: /* ADD Hd,Hd,Hs */
*ainstr = 0xE0800000 /* base */
| (Rd << 16) /* Rn */
|(Rd << 12) /* Rd */
|(Rs << 0); /* Rm */
break;
case 0x5: /* CMP Rd,Hs */
case 0x6: /* CMP Hd,Rs */
case 0x7: /* CMP Hd,Hs */
*ainstr = 0xE1500000 /* base */
| (Rd << 16) /* Rn */
|(Rd << 12) /* Rd */
|(Rs << 0); /* Rm */
break;
case 0x9: /* MOV Rd,Hs */
case 0xA: /* MOV Hd,Rs */
case 0xB: /* MOV Hd,Hs */
*ainstr = 0xE1A00000 /* base */
| (Rd << 16) /* Rn */
|(Rd << 12) /* Rd */
|(Rs << 0); /* Rm */
break;
case 0xC: /* BX Rs */
case 0xD: /* BX Hs */
*ainstr = 0xE12FFF10 /* base */
| ((tinstr & 0x0078) >> 3); /* Rd */
break;
case 0x0: /* UNDEFINED */
case 0x4: /* UNDEFINED */
case 0x8: /* UNDEFINED */
valid = t_undefined;
break;
case 0xE: /* BLX */
case 0xF: /* BLX */
if (state->is_v5) {
*ainstr = 0xE1200030 /* base */
|(Rs << 0); /* Rm */
} else {
valid = t_undefined;
}
break;
}
}
break;
case 9: /* LDR Rd,[PC,#imm8] */
/* Format 6 */
*ainstr = 0xE59F0000 /* base */
| ((tinstr & 0x0700) << (12 - 8)) /* Rd */
|((tinstr & 0x00FF) << (2 - 0)); /* off8 */
break;
case 10:
case 11:
/* TODO: Format 7 and Format 8 perform the same ARM encoding, so
the following could be merged into a single subset, saving on
the following boolean: */
if ((tinstr & (1 << 9)) == 0) {
/* Format 7 */
ARMword subset[4] = {
0xE7800000, /* STR Rd,[Rb,Ro] */
0xE7C00000, /* STRB Rd,[Rb,Ro] */
0xE7900000, /* LDR Rd,[Rb,Ro] */
0xE7D00000 /* LDRB Rd,[Rb,Ro] */
};
*ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x01C0) >> 6); /* Ro */
}
else {
/* Format 8 */
ARMword subset[4] = {
0xE18000B0, /* STRH Rd,[Rb,Ro] */
0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
0xE19000B0, /* LDRH Rd,[Rb,Ro] */
0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
};
*ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x01C0) >> 6); /* Ro */
}
break;
case 12: /* STR Rd,[Rb,#imm5] */
case 13: /* LDR Rd,[Rb,#imm5] */
case 14: /* STRB Rd,[Rb,#imm5] */
case 15: /* LDRB Rd,[Rb,#imm5] */
/* Format 9 */
{
ARMword subset[4] = {
0xE5800000, /* STR Rd,[Rb,#imm5] */
0xE5900000, /* LDR Rd,[Rb,#imm5] */
0xE5C00000, /* STRB Rd,[Rb,#imm5] */
0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
};
/* The offset range defends on whether we are transferring a
byte or word value: */
*ainstr = subset[(tinstr & 0x1800) >> 11] /* base */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */
}
break;
case 16: /* STRH Rd,[Rb,#imm5] */
case 17: /* LDRH Rd,[Rb,#imm5] */
/* Format 10 */
*ainstr = ((tinstr & (1 << 11)) /* base */
? 0xE1D000B0 /* LDRH */
: 0xE1C000B0) /* STRH */
|((tinstr & 0x0007) << (12 - 0)) /* Rd */
|((tinstr & 0x0038) << (16 - 3)) /* Rb */
|((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */
|((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */
break;
case 18: /* STR Rd,[SP,#imm8] */
case 19: /* LDR Rd,[SP,#imm8] */
/* Format 11 */
*ainstr = ((tinstr & (1 << 11)) /* base */
? 0xE59D0000 /* LDR */
: 0xE58D0000) /* STR */
|((tinstr & 0x0700) << (12 - 8)) /* Rd */
|((tinstr & 0x00FF) << 2); /* off8 */
break;
case 20: /* ADD Rd,PC,#imm8 */
case 21: /* ADD Rd,SP,#imm8 */
/* Format 12 */
if ((tinstr & (1 << 11)) == 0) {
/* NOTE: The PC value used here should by word aligned */
/* We encode shift-left-by-2 in the rotate immediate field,
so no shift of off8 is needed. */
*ainstr = 0xE28F0F00 /* base */
| ((tinstr & 0x0700) << (12 - 8)) /* Rd */
|(tinstr & 0x00FF); /* off8 */
}
else {
/* We encode shift-left-by-2 in the rotate immediate field,
so no shift of off8 is needed. */
*ainstr = 0xE28D0F00 /* base */
| ((tinstr & 0x0700) << (12 - 8)) /* Rd */
|(tinstr & 0x00FF); /* off8 */
}
break;
case 22:
case 23:
if ((tinstr & 0x0F00) == 0x0000) {
/* Format 13 */
/* NOTE: The instruction contains a shift left of 2
equivalent (implemented as ROR #30): */
*ainstr = ((tinstr & (1 << 7)) /* base */
? 0xE24DDF00 /* SUB */
: 0xE28DDF00) /* ADD */
|(tinstr & 0x007F); /* off7 */
}
else if ((tinstr & 0x0F00) == 0x0e00)
*ainstr = 0xEF000000 | SWI_Breakpoint;
else {
/* Format 14 */
ARMword subset[4] = {
0xE92D0000, /* STMDB sp!,{rlist} */
0xE92D4000, /* STMDB sp!,{rlist,lr} */
0xE8BD0000, /* LDMIA sp!,{rlist} */
0xE8BD8000 /* LDMIA sp!,{rlist,pc} */
};
*ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] /* base */
|(tinstr & 0x00FF); /* mask8 */
}
break;
case 24: /* STMIA */
case 25: /* LDMIA */
/* Format 15 */
*ainstr = ((tinstr & (1 << 11)) /* base */
? 0xE8B00000 /* LDMIA */
: 0xE8A00000) /* STMIA */
|((tinstr & 0x0700) << (16 - 8)) /* Rb */
|(tinstr & 0x00FF); /* mask8 */
break;
case 26: /* Bcc */
case 27: /* Bcc/SWI */
if ((tinstr & 0x0F00) == 0x0F00) {
if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
state->AbortAddr == pc) {
*ainstr = ARMul_ABORTWORD;
break;
}
/* Format 17 : SWI */
*ainstr = 0xEF000000;
/* Breakpoint must be handled specially. */
if ((tinstr & 0x00FF) == 0x18)
*ainstr |= ((tinstr & 0x00FF) << 16);
/* New breakpoint value. See gdb/arm-tdep.c */
else if ((tinstr & 0x00FF) == 0xFE)
*ainstr |= SWI_Breakpoint;
else
*ainstr |= (tinstr & 0x00FF);
}
else if ((tinstr & 0x0F00) != 0x0E00) {
/* Format 16 */
int doit = FALSE;
/* TODO: Since we are doing a switch here, we could just add
the SWI and undefined instruction checks into this
switch to same on a couple of conditionals: */
switch ((tinstr & 0x0F00) >> 8) {
case EQ:
doit = ZFLAG;
break;
case NE:
doit = !ZFLAG;
break;
case VS:
doit = VFLAG;
break;
case VC:
doit = !VFLAG;
break;
case MI:
doit = NFLAG;
break;
case PL:
doit = !NFLAG;
break;
case CS:
doit = CFLAG;
break;
case CC:
doit = !CFLAG;
break;
case HI:
doit = (CFLAG && !ZFLAG);
break;
case LS:
doit = (!CFLAG || ZFLAG);
break;
case GE:
doit = ((!NFLAG && !VFLAG)
|| (NFLAG && VFLAG));
break;
case LT:
doit = ((NFLAG && !VFLAG)
|| (!NFLAG && VFLAG));
break;
case GT:
doit = ((!NFLAG && !VFLAG && !ZFLAG)
|| (NFLAG && VFLAG && !ZFLAG));
break;
case LE:
doit = ((NFLAG && !VFLAG)
|| (!NFLAG && VFLAG)) || ZFLAG;
break;
}
if (doit) {
state->Reg[15] = (pc + 4
+ (((tinstr & 0x7F) << 1)
| ((tinstr & (1 << 7)) ?
0xFFFFFF00 : 0)));
FLUSHPIPE;
}
valid = t_branch;
}
else /* UNDEFINED : cc=1110(AL) uses different format */
valid = t_undefined;
break;
case 28: /* B */
/* Format 18 */
state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
| ((tinstr & (1 << 10)) ?
0xFFFFF800 : 0)));
FLUSHPIPE;
valid = t_branch;
break;
case 29:
if(tinstr & 0x1)
valid = t_undefined;
else{
/* BLX 1 for armv5t and above */
ARMword tmp = (pc + 2);
state->Reg[15] =
(state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC;
state->Reg[14] = (tmp | 1);
CLEART;
DEBUG_LOG(ARM11, "In %s, After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
valid = t_branch;
FLUSHPIPE;
}
break;
case 30: /* BL instruction 1 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this Thumb
instruction. To keep the simulation simple (from the user
perspective) we check if the following instruction is the
second half of this BL, and if it is we simulate it
immediately. */
state->Reg[14] = state->Reg[15]
+ (((tinstr & 0x07FF) << 12)
| ((tinstr & (1 << 10)) ? 0xFF800000 : 0));
valid = t_branch; /* in-case we don't have the 2nd half */
//tinstr = next_instr; /* move the instruction down */
//if (((tinstr & 0xF800) >> 11) != 31)
// break; /* exit, since not correct instruction */
/* else we fall through to process the second half of the BL */
//pc += 2; /* point the pc at the 2nd half */
state->Reg[15] = pc + 2;
FLUSHPIPE;
break;
case 31: /* BL instruction 2 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this
instruction. Also, it should only ever be matched with the
fmt19 "BL instruction 1" instruction. However, we do allow
the simulation of it on its own, with undefined results if
r14 is not suitably initialised. */
{
ARMword tmp = (pc + 2);
state->Reg[15] =
(state->Reg[14] + ((tinstr & 0x07FF) << 1));
state->Reg[14] = (tmp | 1);
valid = t_branch;
FLUSHPIPE;
}
break;
}
return valid;
}