got rid of 'src' folders in each sub-project
This commit is contained in:
parent
03c245345e
commit
63e46abdb8
148 changed files with 0 additions and 0 deletions
86
src/core/arm/interpreter/arm_interpreter.cpp
Normal file
86
src/core/arm/interpreter/arm_interpreter.cpp
Normal 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;
|
||||
}
|
57
src/core/arm/interpreter/arm_interpreter.h
Normal file
57
src/core/arm/interpreter/arm_interpreter.h
Normal 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);
|
||||
};
|
103
src/core/arm/interpreter/arm_regformat.h
Normal file
103
src/core/arm/interpreter/arm_regformat.h
Normal 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
|
83
src/core/arm/interpreter/armcpu.h
Normal file
83
src/core/arm/interpreter/armcpu.h
Normal 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
|
||||
|
934
src/core/arm/interpreter/armdefs.h
Normal file
934
src/core/arm/interpreter/armdefs.h
Normal 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_ */
|
6631
src/core/arm/interpreter/armemu.cpp
Normal file
6631
src/core/arm/interpreter/armemu.cpp
Normal file
File diff suppressed because it is too large
Load diff
659
src/core/arm/interpreter/armemu.h
Normal file
659
src/core/arm/interpreter/armemu.h
Normal 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
|
579
src/core/arm/interpreter/arminit.cpp
Normal file
579
src/core/arm/interpreter/arminit.cpp
Normal 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);
|
||||
}
|
238
src/core/arm/interpreter/armmmu.cpp
Normal file
238
src/core/arm/interpreter/armmmu.cpp
Normal 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;
|
||||
//}
|
254
src/core/arm/interpreter/armmmu.h
Normal file
254
src/core/arm/interpreter/armmmu.h
Normal 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_ */
|
742
src/core/arm/interpreter/armos.cpp
Normal file
742
src/core/arm/interpreter/armos.cpp
Normal 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;
|
||||
//}
|
138
src/core/arm/interpreter/armos.h
Normal file
138
src/core/arm/interpreter/armos.h
Normal 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 */
|
||||
};
|
||||
|
954
src/core/arm/interpreter/armsupp.cpp
Normal file
954
src/core/arm/interpreter/armsupp.cpp
Normal 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);
|
||||
}
|
680
src/core/arm/interpreter/armvirt.cpp
Normal file
680
src/core/arm/interpreter/armvirt.cpp
Normal 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;
|
||||
}
|
111
src/core/arm/interpreter/skyeye_defs.h
Normal file
111
src/core/arm/interpreter/skyeye_defs.h
Normal 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
|
513
src/core/arm/interpreter/thumbemu.cpp
Normal file
513
src/core/arm/interpreter/thumbemu.cpp
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue