1
0
Fork 0
forked from suyu/suyu

Merge pull request #112 from bunnei/skyeye-dyncom-interpreter

SkyEye dyncom interpreter
This commit is contained in:
bunnei 2014-10-25 14:35:31 -04:00
commit 4615c73d15
53 changed files with 8640 additions and 8645 deletions

View file

@ -9,7 +9,7 @@
#include "core/core.h"
#include "common/break_points.h"
#include "common/symbols.h"
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/disassembler/arm_disasm.h"
DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {

View file

@ -1,27 +1,22 @@
set(SRCS
arm/disassembler/arm_disasm.cpp
arm/disassembler/load_symbol_map.cpp
arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
arm/interpreter/mmu/cache.cpp
arm/interpreter/mmu/maverick.cpp
arm/interpreter/mmu/rb.cpp
arm/interpreter/mmu/sa_mmu.cpp
arm/interpreter/mmu/tlb.cpp
arm/interpreter/mmu/wb.cpp
arm/interpreter/mmu/xscale_copro.cpp
arm/interpreter/vfp/vfp.cpp
arm/interpreter/vfp/vfpdouble.cpp
arm/interpreter/vfp/vfpinstr.cpp
arm/interpreter/vfp/vfpsingle.cpp
arm/dyncom/arm_dyncom.cpp
arm/dyncom/arm_dyncom_dec.cpp
arm/dyncom/arm_dyncom_interpreter.cpp
arm/dyncom/arm_dyncom_run.cpp
arm/dyncom/arm_dyncom_thumb.cpp
arm/interpreter/arm_interpreter.cpp
arm/interpreter/armcopro.cpp
arm/interpreter/armemu.cpp
arm/interpreter/arminit.cpp
arm/interpreter/armmmu.cpp
arm/interpreter/armos.cpp
arm/interpreter/armsupp.cpp
arm/interpreter/armvirt.cpp
arm/interpreter/thumbemu.cpp
arm/skyeye_common/vfp/vfp.cpp
arm/skyeye_common/vfp/vfpdouble.cpp
arm/skyeye_common/vfp/vfpinstr.cpp
arm/skyeye_common/vfp/vfpsingle.cpp
file_sys/archive_romfs.cpp
file_sys/archive_sdmc.cpp
file_sys/file_romfs.cpp
@ -43,7 +38,6 @@ set(SRCS
hle/service/service.cpp
hle/service/srv.cpp
hle/config_mem.cpp
hle/coprocessor.cpp
hle/hle.cpp
hle/svc.cpp
hw/gpu.cpp
@ -63,23 +57,23 @@ set(SRCS
set(HEADERS
arm/disassembler/arm_disasm.h
arm/disassembler/load_symbol_map.h
arm/interpreter/mmu/arm1176jzf_s_mmu.h
arm/interpreter/mmu/cache.h
arm/interpreter/mmu/rb.h
arm/interpreter/mmu/sa_mmu.h
arm/interpreter/mmu/tlb.h
arm/interpreter/mmu/wb.h
arm/interpreter/vfp/asm_vfp.h
arm/interpreter/vfp/vfp.h
arm/interpreter/vfp/vfp_helper.h
arm/dyncom/arm_dyncom.h
arm/dyncom/arm_dyncom_dec.h
arm/dyncom/arm_dyncom_interpreter.h
arm/dyncom/arm_dyncom_run.h
arm/dyncom/arm_dyncom_thumb.h
arm/interpreter/arm_interpreter.h
arm/interpreter/arm_regformat.h
arm/interpreter/armcpu.h
arm/interpreter/armdefs.h
arm/interpreter/armemu.h
arm/interpreter/armmmu.h
arm/interpreter/armos.h
arm/interpreter/skyeye_defs.h
arm/skyeye_common/arm_regformat.h
arm/skyeye_common/armcpu.h
arm/skyeye_common/armdefs.h
arm/skyeye_common/armemu.h
arm/skyeye_common/armmmu.h
arm/skyeye_common/armos.h
arm/skyeye_common/skyeye_defs.h
arm/skyeye_common/skyeye_types.h
arm/skyeye_common/vfp/asm_vfp.h
arm/skyeye_common/vfp/vfp.h
arm/skyeye_common/vfp/vfp_helper.h
arm/arm_interface.h
file_sys/archive.h
file_sys/archive_romfs.h
@ -105,7 +99,6 @@ set(HEADERS
hle/service/service.h
hle/service/srv.h
hle/config_mem.h
hle/coprocessor.h
hle/function_wrappers.h
hle/hle.h
hle/svc.h

View file

@ -0,0 +1,163 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "core/arm/skyeye_common/armcpu.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/arm/dyncom/arm_dyncom.h"
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
const static cpu_config_t s_arm11_cpu_info = {
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
};
ARM_DynCom::ARM_DynCom() : ticks(0) {
state = std::unique_ptr<ARMul_State>(new ARMul_State);
ARMul_EmulateInit();
memset(state.get(), 0, sizeof(ARMul_State));
ARMul_NewState((ARMul_State*)state.get());
state->abort_model = 0;
state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
state->bigendSig = LOW;
ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
state->lateabtSig = LOW;
// Reset the core to initial state
ARMul_CoProInit(state.get());
ARMul_Reset(state.get());
state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
state->Emulate = 3;
state->pc = state->Reg[15] = 0x00000000;
state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
state->servaddr = 0xFFFF0000;
state->NirqSig = HIGH;
VFPInit(state.get()); // Initialize the VFP
ARMul_EmulateInit();
}
ARM_DynCom::~ARM_DynCom() {
}
/**
* Set the Program Counter to an address
* @param addr Address to set PC to
*/
void ARM_DynCom::SetPC(u32 pc) {
state->pc = state->Reg[15] = pc;
}
/*
* Get the current Program Counter
* @return Returns current PC
*/
u32 ARM_DynCom::GetPC() const {
return state->pc;
}
/**
* Get an ARM register
* @param index Register index (0-15)
* @return Returns the value in the register
*/
u32 ARM_DynCom::GetReg(int index) const {
return state->Reg[index];
}
/**
* Set an ARM register
* @param index Register index (0-15)
* @param value Value to set register to
*/
void ARM_DynCom::SetReg(int index, u32 value) {
state->Reg[index] = value;
}
/**
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
u32 ARM_DynCom::GetCPSR() const {
return state->Cpsr;
}
/**
* Set the current CPSR register
* @param cpsr Value to set CPSR to
*/
void ARM_DynCom::SetCPSR(u32 cpsr) {
state->Cpsr = cpsr;
}
/**
* Returns the number of clock ticks since the last reset
* @return Returns number of clock ticks
*/
u64 ARM_DynCom::GetTicks() const {
return ticks;
}
/**
* Executes the given number of instructions
* @param num_instructions Number of instructions to executes
*/
void ARM_DynCom::ExecuteInstructions(int num_instructions) {
ticks += num_instructions;
state->NumInstrsToExecute = num_instructions;
InterpreterMainLoop(state.get());
}
/**
* Saves the current CPU context
* @param ctx Thread context to save
* @todo Do we need to save Reg[15] and NextInstr?
*/
void ARM_DynCom::SaveContext(ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
ctx.sp = state->Reg[13];
ctx.lr = state->Reg[14];
ctx.pc = state->pc;
ctx.cpsr = state->Cpsr;
ctx.fpscr = state->VFP[1];
ctx.fpexc = state->VFP[2];
ctx.reg_15 = state->Reg[15];
ctx.mode = state->NextInstr;
}
/**
* Loads a CPU context
* @param ctx Thread context to load
* @param Do we need to load Reg[15] and NextInstr?
*/
void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
state->Reg[13] = ctx.sp;
state->Reg[14] = ctx.lr;
state->pc = ctx.pc;
state->Cpsr = ctx.cpsr;
state->VFP[1] = ctx.fpscr;
state->VFP[2] = ctx.fpexc;
state->Reg[15] = ctx.reg_15;
state->NextInstr = ctx.mode;
}
/// Prepare core for thread reschedule (if needed to correctly handle state)
void ARM_DynCom::PrepareReschedule() {
state->NumInstrsToExecute = 0;
}

View file

@ -0,0 +1,90 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
#include "core/arm/skyeye_common/armdefs.h"
class ARM_DynCom final : virtual public ARM_Interface {
public:
ARM_DynCom();
~ARM_DynCom();
/**
* Set the Program Counter to an address
* @param addr Address to set PC to
*/
void SetPC(u32 pc);
/*
* Get the current Program Counter
* @return Returns current PC
*/
u32 GetPC() const;
/**
* Get an ARM register
* @param index Register index (0-15)
* @return Returns the value in the register
*/
u32 GetReg(int index) const;
/**
* Set an ARM register
* @param index Register index (0-15)
* @param value Value to set register to
*/
void SetReg(int index, u32 value);
/**
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
u32 GetCPSR() const;
/**
* Set the current CPSR register
* @param cpsr Value to set CPSR to
*/
void SetCPSR(u32 cpsr);
/**
* Returns the number of clock ticks since the last reset
* @return Returns number of clock ticks
*/
u64 GetTicks() const;
/**
* Saves the current CPU context
* @param ctx Thread context to save
*/
void SaveContext(ThreadContext& ctx);
/**
* Loads a CPU context
* @param ctx Thread context to load
*/
void LoadContext(const ThreadContext& ctx);
/// Prepare core for thread reschedule (if needed to correctly handle state)
void PrepareReschedule();
/**
* Executes the given number of instructions
* @param num_instructions Number of instructions to executes
*/
void ExecuteInstructions(int num_instructions);
private:
std::unique_ptr<ARMul_State> state;
u64 ticks;
};

View file

@ -0,0 +1,402 @@
/* Copyright (C)
* 2012 - Michael.Kang blackfin.kang@gmail.com
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/**
* @file arm_dyncom_dec.cpp
* @brief Some common utility for arm decoder
* @author Michael.Kang blackfin.kang@gmail.com
* @version 7849
* @date 2012-03-15
*/
#include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/dyncom/arm_dyncom_dec.h"
const ISEITEM arm_instruction[] = {
#define VFP_DECODE
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_DECODE
{"srs" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005},
{"rfe" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a},
{"bkpt" , 2 , 3 , 20, 31, 0x00000e12, 4, 7, 0x00000007},
{"blx" , 1 , 3 , 25, 31, 0x0000007d},
{"cps" , 3 , 6 , 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000},
{"pld" , 4 , 4 , 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f},
{"setend" , 2 , 6 , 16, 31, 0x0000f101, 4, 7, 0x00000000},
{"clrex" , 1 , 6 , 0, 31, 0xf57ff01f},
{"rev16" , 2 , 6 , 16, 27, 0x000006bf, 4, 11, 0x000000fb},
{"usad8" , 3 , 6 , 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001},
{"sxtb" , 2 , 6 , 16, 27, 0x000006af, 4, 7, 0x00000007},
{"uxtb" , 2 , 6 , 16, 27, 0x000006ef, 4, 7, 0x00000007},
{"sxth" , 2 , 6 , 16, 27, 0x000006bf, 4, 7, 0x00000007},
{"sxtb16" , 2 , 6 , 16, 27, 0x0000068f, 4, 7, 0x00000007},
{"uxth" , 2 , 6 , 16, 27, 0x000006ff, 4, 7, 0x00000007},
{"uxtb16" , 2 , 6 , 16, 27, 0x000006cf, 4, 7, 0x00000007},
{"cpy" , 2 , 6 , 20, 27, 0x0000001a, 4, 11, 0x00000000},
{"uxtab" , 2 , 6 , 20, 27, 0x0000006e, 4, 9, 0x00000007},
{"ssub8" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x0000000f},
{"shsub8" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x0000000f},
{"ssubaddx" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000005},
{"strex" , 2 , 6 , 20, 27, 0x00000018, 4, 7, 0x00000009},
{"strexb" , 2 , 7 , 20, 27, 0x0000001c, 4, 7, 0x00000009},
{"swp" , 2 , 0 , 20, 27, 0x00000010, 4, 7, 0x00000009},
{"swpb" , 2 , 0 , 20, 27, 0x00000014, 4, 7, 0x00000009},
{"ssub16" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000007},
{"ssat16" , 2 , 6 , 20, 27, 0x0000006a, 4, 7, 0x00000003},
{"shsubaddx" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000005},
{"qsubaddx" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000005},
{"shaddsubx" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000003},
{"shadd8" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000009},
{"shadd16" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000001},
{"sel" , 2 , 6 , 20, 27, 0x00000068, 4, 7, 0x0000000b},
{"saddsubx" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000003},
{"sadd8" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000009},
{"sadd16" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000001},
{"shsub16" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000007},
{"umaal" , 2 , 6 , 20, 27, 0x00000004, 4, 7, 0x00000009},
{"uxtab16" , 2 , 6 , 20, 27, 0x0000006c, 4, 7, 0x00000007},
{"usubaddx" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000005},
{"usub8" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x0000000f},
{"usub16" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000007},
{"usat16" , 2 , 6 , 20, 27, 0x0000006e, 4, 7, 0x00000003},
{"usada8" , 2 , 6 , 20, 27, 0x00000078, 4, 7, 0x00000001},
{"uqsubaddx" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000005},
{"uqsub8" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x0000000f},
{"uqsub16" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000007},
{"uqaddsubx" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000003},
{"uqadd8" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000009},
{"uqadd16" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000001},
{"sxtab" , 2 , 6 , 20, 27, 0x0000006a, 4, 7, 0x00000007},
{"uhsubaddx" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000005},
{"uhsub8" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x0000000f},
{"uhsub16" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000007},
{"uhaddsubx" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000003},
{"uhadd8" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000009},
{"uhadd16" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000001},
{"uaddsubx" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000003},
{"uadd8" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000009},
{"uadd16" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000001},
{"sxtah" , 2 , 6 , 20, 27, 0x0000006b, 4, 7, 0x00000007},
{"sxtab16" , 2 , 6 , 20, 27, 0x00000068, 4, 7, 0x00000007},
{"qadd8" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000009},
{"bxj" , 2 , 5 , 20, 27, 0x00000012, 4, 7, 0x00000002},
{"clz" , 2 , 3 , 20, 27, 0x00000016, 4, 7, 0x00000001},
{"uxtah" , 2 , 6 , 20, 27, 0x0000006f, 4, 7, 0x00000007},
{"bx" , 2 , 2 , 20, 27, 0x00000012, 4, 7, 0x00000001},
{"rev" , 2 , 6 , 20, 27, 0x0000006b, 4, 7, 0x00000003},
{"blx" , 2 , 3 , 20, 27, 0x00000012, 4, 7, 0x00000003},
{"revsh" , 2 , 6 , 20, 27, 0x0000006f, 4, 7, 0x0000000b},
{"qadd" , 2 , 4 , 20, 27, 0x00000010, 4, 7, 0x00000005},
{"qadd16" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000001},
{"qaddsubx" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000003},
{"ldrex" , 2 , 0 , 20, 27, 0x00000019, 4, 7, 0x00000009},
{"qdadd" , 2 , 4 , 20, 27, 0x00000014, 4, 7, 0x00000005},
{"qdsub" , 2 , 4 , 20, 27, 0x00000016, 4, 7, 0x00000005},
{"qsub" , 2 , 4 , 20, 27, 0x00000012, 4, 7, 0x00000005},
{"ldrexb" , 2 , 7 , 20, 27, 0x0000001d, 4, 7, 0x00000009},
{"qsub8" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x0000000f},
{"qsub16" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000007},
{"smuad" , 4 , 6 , 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001},
{"smmul" , 4 , 6 , 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001},
{"smusd" , 4 , 6 , 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001},
{"smlsd" , 3 , 6 , 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001},
{"smlsld" , 3 , 6 , 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001},
{"smmla" , 3 , 6 , 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001},
{"smmls" , 3 , 6 , 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001},
{"smlald" , 3 , 6 , 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001},
{"smlad" , 3 , 6 , 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001},
{"smlaw" , 3 , 4 , 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000},
{"smulw" , 3 , 4 , 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002},
{"pkhtb" , 2 , 6 , 20, 27, 0x00000068, 4, 6, 0x00000005},
{"pkhbt" , 2 , 6 , 20, 27, 0x00000068, 4, 6, 0x00000001},
{"smul" , 3 , 4 , 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000},
{"smlalxy" , 3 , 4 , 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000},
// {"smlal" , 2 , 4 , 21, 27, 0x00000007, 4, 7, 0x00000009},
{"smla" , 3 , 4 , 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000},
{"mcrr" , 1 , 6 , 20, 27, 0x000000c4},
{"mrrc" , 1 , 6 , 20, 27, 0x000000c5},
{"cmp" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000015},
{"tst" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000011},
{"teq" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000013},
{"cmn" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000017},
{"smull" , 2 , 0 , 21, 27, 0x00000006, 4, 7, 0x00000009},
{"umull" , 2 , 0 , 21, 27, 0x00000004, 4, 7, 0x00000009},
{"umlal" , 2 , 0 , 21, 27, 0x00000005, 4, 7, 0x00000009},
{"smlal" , 2 , 0 , 21, 27, 0x00000007, 4, 7, 0x00000009},
{"mul" , 2 , 0 , 21, 27, 0x00000000, 4, 7, 0x00000009},
{"mla" , 2 , 0 , 21, 27, 0x00000001, 4, 7, 0x00000009},
{"ssat" , 2 , 6 , 21, 27, 0x00000035, 4, 5, 0x00000001},
{"usat" , 2 , 6 , 21, 27, 0x00000037, 4, 5, 0x00000001},
{"mrs" , 4 , 0 , 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000},
{"msr" , 3 , 0 , 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000},
{"and" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000000},
{"bic" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000e},
{"ldm" , 3 , 0 , 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000},
{"eor" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000001},
{"add" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000004},
{"rsb" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000003},
{"rsc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000007},
{"sbc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000006},
{"adc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000005},
{"sub" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000002},
{"orr" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000c},
{"mvn" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000f},
{"mov" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000d},
{"stm" , 2 , 0 , 25, 27, 0x00000004, 20, 22, 0x00000004},
{"ldm" , 4 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001},
{"ldrsh" , 3 , 2 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f},
{"stm" , 3 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000},
{"ldm" , 3 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001},
{"ldrsb" , 3 , 2 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d},
{"strd" , 3 , 4 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f},
{"ldrh" , 3 , 0 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b},
{"strh" , 3 , 0 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b},
{"ldrd" , 3 , 4 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d},
{"strt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002},
{"strbt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006},
{"ldrbt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007},
{"ldrt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003},
{"mrc" , 3 , 6 , 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001},
{"mcr" , 3 , 0 , 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001},
{"msr" , 2 , 0 , 23, 27, 0x00000006, 20, 21, 0x00000002},
{"ldrb" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001},
{"strb" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000},
{"ldr" , 4 , 0 , 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001},
{"ldrcond" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001},
{"str" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000},
{"cdp" , 2 , 0 , 24, 27, 0x0000000e, 4, 4, 0x00000000},
{"stc" , 2 , 0 , 25, 27, 0x00000006, 20, 20, 0x00000000},
{"ldc" , 2 , 0 , 25, 27, 0x00000006, 20, 20, 0x00000001},
{"swi" , 1 , 0 , 24, 27, 0x0000000f},
{"bbl" , 1 , 0 , 25, 27, 0x00000005},
};
const ISEITEM arm_exclusion_code[] = {
#define VFP_DECODE_EXCLUSION
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_DECODE_EXCLUSION
{"srs" , 0 , 6 , 0},
{"rfe" , 0 , 6 , 0},
{"bkpt" , 0 , 3 , 0},
{"blx" , 0 , 3 , 0},
{"cps" , 0 , 6 , 0},
{"pld" , 0 , 4 , 0},
{"setend" , 0 , 6 , 0},
{"clrex" , 0 , 6 , 0},
{"rev16" , 0 , 6 , 0},
{"usad8" , 0 , 6 , 0},
{"sxtb" , 0 , 6 , 0},
{"uxtb" , 0 , 6 , 0},
{"sxth" , 0 , 6 , 0},
{"sxtb16" , 0 , 6 , 0},
{"uxth" , 0 , 6 , 0},
{"uxtb16" , 0 , 6 , 0},
{"cpy" , 0 , 6 , 0},
{"uxtab" , 0 , 6 , 0},
{"ssub8" , 0 , 6 , 0},
{"shsub8" , 0 , 6 , 0},
{"ssubaddx" , 0 , 6 , 0},
{"strex" , 0 , 6 , 0},
{"strexb" , 0 , 7 , 0},
{"swp" , 0 , 0 , 0},
{"swpb" , 0 , 0 , 0},
{"ssub16" , 0 , 6 , 0},
{"ssat16" , 0 , 6 , 0},
{"shsubaddx" , 0 , 6 , 0},
{"qsubaddx" , 0 , 6 , 0},
{"shaddsubx" , 0 , 6 , 0},
{"shadd8" , 0 , 6 , 0},
{"shadd16" , 0 , 6 , 0},
{"sel" , 0 , 6 , 0},
{"saddsubx" , 0 , 6 , 0},
{"sadd8" , 0 , 6 , 0},
{"sadd16" , 0 , 6 , 0},
{"shsub16" , 0 , 6 , 0},
{"umaal" , 0 , 6 , 0},
{"uxtab16" , 0 , 6 , 0},
{"usubaddx" , 0 , 6 , 0},
{"usub8" , 0 , 6 , 0},
{"usub16" , 0 , 6 , 0},
{"usat16" , 0 , 6 , 0},
{"usada8" , 0 , 6 , 0},
{"uqsubaddx" , 0 , 6 , 0},
{"uqsub8" , 0 , 6 , 0},
{"uqsub16" , 0 , 6 , 0},
{"uqaddsubx" , 0 , 6 , 0},
{"uqadd8" , 0 , 6 , 0},
{"uqadd16" , 0 , 6 , 0},
{"sxtab" , 0 , 6 , 0},
{"uhsubaddx" , 0 , 6 , 0},
{"uhsub8" , 0 , 6 , 0},
{"uhsub16" , 0 , 6 , 0},
{"uhaddsubx" , 0 , 6 , 0},
{"uhadd8" , 0 , 6 , 0},
{"uhadd16" , 0 , 6 , 0},
{"uaddsubx" , 0 , 6 , 0},
{"uadd8" , 0 , 6 , 0},
{"uadd16" , 0 , 6 , 0},
{"sxtah" , 0 , 6 , 0},
{"sxtab16" , 0 , 6 , 0},
{"qadd8" , 0 , 6 , 0},
{"bxj" , 0 , 5 , 0},
{"clz" , 0 , 3 , 0},
{"uxtah" , 0 , 6 , 0},
{"bx" , 0 , 2 , 0},
{"rev" , 0 , 6 , 0},
{"blx" , 0 , 3 , 0},
{"revsh" , 0 , 6 , 0},
{"qadd" , 0 , 4 , 0},
{"qadd16" , 0 , 6 , 0},
{"qaddsubx" , 0 , 6 , 0},
{"ldrex" , 0 , 0 , 0},
{"qdadd" , 0 , 4 , 0},
{"qdsub" , 0 , 4 , 0},
{"qsub" , 0 , 4 , 0},
{"ldrexb" , 0 , 7 , 0},
{"qsub8" , 0 , 6 , 0},
{"qsub16" , 0 , 6 , 0},
{"smuad" , 0 , 6 , 0},
{"smmul" , 0 , 6 , 0},
{"smusd" , 0 , 6 , 0},
{"smlsd" , 0 , 6 , 0},
{"smlsld" , 0 , 6 , 0},
{"smmla" , 0 , 6 , 0},
{"smmls" , 0 , 6 , 0},
{"smlald" , 0 , 6 , 0},
{"smlad" , 0 , 6 , 0},
{"smlaw" , 0 , 4 , 0},
{"smulw" , 0 , 4 , 0},
{"pkhtb" , 0 , 6 , 0},
{"pkhbt" , 0 , 6 , 0},
{"smul" , 0 , 4 , 0},
{"smlal" , 0 , 4 , 0},
{"smla" , 0 , 4 , 0},
{"mcrr" , 0 , 6 , 0},
{"mrrc" , 0 , 6 , 0},
{"cmp" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"tst" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"teq" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"cmn" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"smull" , 0 , 0 , 0},
{"umull" , 0 , 0 , 0},
{"umlal" , 0 , 0 , 0},
{"smlal" , 0 , 0 , 0},
{"mul" , 0 , 0 , 0},
{"mla" , 0 , 0 , 0},
{"ssat" , 0 , 6 , 0},
{"usat" , 0 , 6 , 0},
{"mrs" , 0 , 0 , 0},
{"msr" , 0 , 0 , 0},
{"and" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"bic" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"ldm" , 0 , 0 , 0},
{"eor" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"add" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"rsb" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"rsc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"sbc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"adc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"sub" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"orr" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"mvn" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"mov" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000},
{"stm" , 0 , 0 , 0},
{"ldm" , 0 , 0 , 0},
{"ldrsh" , 0 , 2 , 0},
{"stm" , 0 , 0 , 0},
{"ldm" , 0 , 0 , 0},
{"ldrsb" , 0 , 2 , 0},
{"strd" , 0 , 4 , 0},
{"ldrh" , 0 , 0 , 0},
{"strh" , 0 , 0 , 0},
{"ldrd" , 0 , 4 , 0},
{"strt" , 0 , 0 , 0},
{"strbt" , 0 , 0 , 0},
{"ldrbt" , 0 , 0 , 0},
{"ldrt" , 0 , 0 , 0},
{"mrc" , 0 , 6 , 0},
{"mcr" , 0 , 0 , 0},
{"msr" , 0 , 0 , 0},
{"ldrb" , 0 , 0 , 0},
{"strb" , 0 , 0 , 0},
{"ldr" , 0 , 0 , 0},
{"ldrcond" , 1 , 0 , 28, 31, 0x0000000e},
{"str" , 0 , 0 , 0},
{"cdp" , 0 , 0 , 0},
{"stc" , 0 , 0 , 0},
{"ldc" , 0 , 0 , 0},
{"swi" , 0 , 0 , 0},
{"bbl" , 0 , 0 , 0},
{"bl_1_thumb", 0, INVALID, 0},/* should be table[-4] */
{"bl_2_thumb", 0, INVALID, 0}, /* should be located at the end of the table[-3] */
{"blx_1_thumb", 0, INVALID, 0}, /* should be located at table[-2] */
{"invalid", 0, INVALID, 0}
};
int decode_arm_instr(uint32_t instr, int32_t *idx)
{
int n = 0;
int base = 0;
int ret = DECODE_FAILURE;
int i = 0;
int instr_slots = sizeof(arm_instruction)/sizeof(ISEITEM);
for (i = 0; i < instr_slots; i++)
{
// ret = DECODE_SUCCESS;
n = arm_instruction[i].attribute_value;
base = 0;
while (n) {
if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
/* clrex */
if (instr != arm_instruction[i].content[base + 2]) {
break;
}
} else if (BITS(arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) {
break;
}
base += 3;
n --;
}
//All conditions is satisfied.
if (n == 0)
ret = DECODE_SUCCESS;
if (ret == DECODE_SUCCESS) {
n = arm_exclusion_code[i].attribute_value;
if (n != 0) {
base = 0;
while (n) {
if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {
break; }
base += 3;
n --;
}
//All conditions is satisfied.
if (n == 0)
ret = DECODE_FAILURE;
}
}
if (ret == DECODE_SUCCESS) {
*idx = i;
return ret;
}
}
return ret;
}

View file

@ -0,0 +1,155 @@
/* Copyright (C)
* 2012 - Michael.Kang blackfin.kang@gmail.com
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/**
* @file arm_dyncom_dec.h
* @brief Some common utility for arm instruction decoder
* @author Michael.Kang blackfin.kang@gmail.com
* @version 7849
* @date 2012-03-15
*/
#ifndef __ARM_DYNCOM_DEC__
#define __ARM_DYNCOM_DEC__
#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
#define BIT(n) ((instr >> (n)) & 1)
#define BAD do{printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); /*exit(0);*/}while(0);
#define ptr_N cpu->ptr_N
#define ptr_Z cpu->ptr_Z
#define ptr_C cpu->ptr_C
#define ptr_V cpu->ptr_V
#define ptr_I cpu->ptr_I
#define ptr_T cpu->ptr_T
#define ptr_CPSR cpu->ptr_gpr[16]
/* for MUL instructions */
/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
#define RDHi ((instr >> 16) & 0xF)
/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
#define RDLo ((instr >> 12) & 0xF)
/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
#define MUL_RD ((instr >> 16) & 0xF)
/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
#define MUL_RN ((instr >> 12) & 0xF)
/*xxxx xxxx xxxx xxxx xxxx 1111 xxxx xxxx */
#define RS ((instr >> 8) & 0xF)
/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
#define RD ((instr >> 12) & 0xF)
/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
#define RN ((instr >> 16) & 0xF)
/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */
#define RM (instr & 0xF)
#define BIT(n) ((instr >> (n)) & 1)
#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
/* CP15 registers */
#define OPCODE_1 BITS(21, 23)
#define CRn BITS(16, 19)
#define CRm BITS(0, 3)
#define OPCODE_2 BITS(5, 7)
/*xxxx xx1x xxxx xxxx xxxx xxxx xxxx xxxx */
#define I BIT(25)
/*xxxx xxxx xxx1 xxxx xxxx xxxx xxxx xxxx */
#define S BIT(20)
#define SHIFT BITS(5,6)
#define SHIFT_IMM BITS(7,11)
#define IMMH BITS(8,11)
#define IMML BITS(0,3)
#define LSPBIT BIT(24)
#define LSUBIT BIT(23)
#define LSBBIT BIT(22)
#define LSWBIT BIT(21)
#define LSLBIT BIT(20)
#define LSSHBITS BITS(5,6)
#define OFFSET12 BITS(0,11)
#define SBIT BIT(20)
#define DESTReg (BITS (12, 15))
/* they are in unused state, give a corrent value when using */
#define IS_V5E 0
#define IS_V5 0
#define IS_V6 0
#define LHSReg 0
/* temp define the using the pc reg need implement a flow */
#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2))
#define OPERAND operand(cpu,instr,bb,NULL)
#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco)
#define BOPERAND boperand(instr)
#define CHECK_RN_PC (RN==15? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)):R(RN))
#define CHECK_RN_PC_WA (RN==15? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)):R(RN))
#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE))))
int decode_arm_instr(uint32_t instr, int32_t *idx);
enum DECODE_STATUS {
DECODE_SUCCESS,
DECODE_FAILURE
};
struct instruction_set_encoding_item {
const char *name;
int attribute_value;
int version;
u32 content[21];
};
typedef struct instruction_set_encoding_item ISEITEM;
#define RECORD_WB(value, flag) {cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag;}
#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag)
#define EXECUTE_WB(base_reg) {if(cpu->dyncom_engine->wb_flag) \
LET(base_reg, cpu->dyncom_engine->wb_value);}
inline int get_reg_count(uint32_t instr){
int i = BITS(0,15);
int count = 0;
while(i){
if(i & 1)
count ++;
i = i >> 1;
}
return count;
}
enum ARMVER {
INVALID = 0,
ARMALL,
ARMV4,
ARMV4T,
ARMV5T,
ARMV5TE,
ARMV5TEJ,
ARMV6,
ARM1176JZF_S,
ARMVFP2,
ARMVFP3
};
//extern const INSTRACT arm_instruction_action[];
extern const ISEITEM arm_instruction[];
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
void InterpreterMainLoop(ARMul_State* state);

View file

@ -0,0 +1,120 @@
/* Copyright (C)
* 2011 - Michael.Kang blackfin.kang@gmail.com
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/**
* @file arm_dyncom_run.cpp
* @brief The dyncom run implementation for arm
* @author Michael.Kang blackfin.kang@gmail.com
* @version 78.77
* @date 2011-11-20
*/
#include <assert.h>
#include "core/arm/skyeye_common/armdefs.h"
void switch_mode(arm_core_t *core, uint32_t mode)
{
uint32_t tmp1, tmp2;
if (core->Mode == mode) {
//Mode not changed.
//printf("mode not changed\n");
return;
}
//printf("%d --->>> %d\n", core->Mode, mode);
//printf("In %s, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
if (mode != USERBANK) {
switch (core->Mode) {
case USER32MODE:
core->Reg_usr[0] = core->Reg[13];
core->Reg_usr[1] = core->Reg[14];
break;
case IRQ32MODE:
core->Reg_irq[0] = core->Reg[13];
core->Reg_irq[1] = core->Reg[14];
core->Spsr[IRQBANK] = core->Spsr_copy;
break;
case SVC32MODE:
core->Reg_svc[0] = core->Reg[13];
core->Reg_svc[1] = core->Reg[14];
core->Spsr[SVCBANK] = core->Spsr_copy;
break;
case ABORT32MODE:
core->Reg_abort[0] = core->Reg[13];
core->Reg_abort[1] = core->Reg[14];
core->Spsr[ABORTBANK] = core->Spsr_copy;
break;
case UNDEF32MODE:
core->Reg_undef[0] = core->Reg[13];
core->Reg_undef[1] = core->Reg[14];
core->Spsr[UNDEFBANK] = core->Spsr_copy;
break;
case FIQ32MODE:
core->Reg_firq[0] = core->Reg[13];
core->Reg_firq[1] = core->Reg[14];
core->Spsr[FIQBANK] = core->Spsr_copy;
break;
}
switch (mode) {
case USER32MODE:
core->Reg[13] = core->Reg_usr[0];
core->Reg[14] = core->Reg_usr[1];
core->Bank = USERBANK;
break;
case IRQ32MODE:
core->Reg[13] = core->Reg_irq[0];
core->Reg[14] = core->Reg_irq[1];
core->Spsr_copy = core->Spsr[IRQBANK];
core->Bank = IRQBANK;
break;
case SVC32MODE:
core->Reg[13] = core->Reg_svc[0];
core->Reg[14] = core->Reg_svc[1];
core->Spsr_copy = core->Spsr[SVCBANK];
core->Bank = SVCBANK;
break;
case ABORT32MODE:
core->Reg[13] = core->Reg_abort[0];
core->Reg[14] = core->Reg_abort[1];
core->Spsr_copy = core->Spsr[ABORTBANK];
core->Bank = ABORTBANK;
break;
case UNDEF32MODE:
core->Reg[13] = core->Reg_undef[0];
core->Reg[14] = core->Reg_undef[1];
core->Spsr_copy = core->Spsr[UNDEFBANK];
core->Bank = UNDEFBANK;
break;
case FIQ32MODE:
core->Reg[13] = core->Reg_firq[0];
core->Reg[14] = core->Reg_firq[1];
core->Spsr_copy = core->Spsr[FIQBANK];
core->Bank = FIQBANK;
break;
}
core->Mode = mode;
//printf("In %si end, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
//printf("\n--------------------------------------\n");
}
else {
printf("user mode\n");
exit(-2);
}
}

View file

@ -0,0 +1,55 @@
/* Copyright (C)
* 2011 - Michael.Kang blackfin.kang@gmail.com
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __ARM_DYNCOM_RUN__
#define __ARM_DYNCOM_RUN__
#include "core/arm/skyeye_common/skyeye_types.h"
void switch_mode(arm_core_t *core, uint32_t mode);
/* FIXME, we temporarily think thumb instruction is always 16 bit */
static inline uint32 GET_INST_SIZE(arm_core_t* core){
return core->TFlag? 2 : 4;
}
/**
* @brief Read R15 and forced R15 to wold align, used address calculation
*
* @param core
* @param Rn
*
* @return
*/
static inline addr_t CHECK_READ_REG15_WA(arm_core_t* core, int Rn){
return (Rn == 15)? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
}
/**
* @brief Read R15, used to data processing with pc
*
* @param core
* @param Rn
*
* @return
*/
static inline uint32 CHECK_READ_REG15(arm_core_t* core, int Rn){
return (Rn == 15)? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn];
}
#endif

View file

@ -0,0 +1,521 @@
/* Copyright (C)
* 2011 - Michael.Kang blackfin.kang@gmail.com
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/**
* @file arm_dyncom_thumb.c
* @brief The thumb dynamic interpreter
* @author Michael.Kang blackfin.kang@gmail.com
* @version 78.77
* @date 2011-11-07
*/
/* We can provide simple Thumb simulation by decoding the Thumb
instruction into its corresponding ARM instruction, and using the
existing ARM simulator. */
#include "core/arm/skyeye_common/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 "core/arm/skyeye_common/armos.h"
#include "core/arm/dyncom/arm_dyncom_thumb.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 thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size)
{
tdstate valid = t_uninitialized;
ARMword next_instr;
ARMword tinstr;
tinstr = instr;
/* The endian should be judge here */
#if 0
if (state->bigendSig) {
next_instr = tinstr & 0xFFFF;
tinstr >>= 16;
}
else {
next_instr = tinstr >> 16;
tinstr &= 0xFFFF;
}
#endif
if((addr & 0x3) != 0)
tinstr = instr >> 16;
else
tinstr &= 0xFFFF;
//printf("In %s, instr=0x%x, tinstr=0x%x, r15=0x%x\n", __FUNCTION__, instr, tinstr, cpu->translate_pc);
#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) {
typedef enum
{ t_norm, t_shift, t_neg, t_mul }otype_t;
/* Format 4 */
struct
{
ARMword opcode;
otype_t otype;
}
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) {
if(1){
//valid = t_branch;
#if 1
*ainstr = 0xE1200030 /* base */
|(Rs << 0); /* Rm */
#endif
} 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 0
if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
state->AbortAddr == pc) {
*ainstr = ARMul_ABORTWORD;
break;
}
#endif
/* 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 */
#if 0
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;
}
#endif
valid = t_branch;
}
else /* UNDEFINED : cc=1110(AL) uses different format */
valid = t_undefined;
break;
case 28: /* B */
/* Format 18 */
#if 0
state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
| ((tinstr & (1 << 10)) ?
0xFFFFF800 : 0)));
#endif
//FLUSHPIPE;
valid = t_branch;
break;
case 29:
if(tinstr & 0x1)
valid = t_undefined;
else{
/* BLX 1 for armv5t and above */
//printf("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;
}
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. */
valid = t_branch;
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. */
{
#if 0
ARMword tmp = (pc + 2);
state->Reg[15] =
(state->Reg[14] + ((tinstr & 0x07FF) << 1));
state->Reg[14] = (tmp | 1);
#endif
valid = t_branch;
}
break;
}
*inst_size = 2;
return valid;
}

View file

@ -0,0 +1,51 @@
/* Copyright (C)
* 2011 - Michael.Kang blackfin.kang@gmail.com
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/**
* @file arm_dyncom_thumb.h
* @brief The thumb dyncom
* @author Michael.Kang blackfin.kang@gmail.com
* @version 78.77
* @date 2011-11-07
*/
#ifndef __ARM_DYNCOM_THUMB_H__
#define __ARM_DYNCOM_THUMB_H__
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/skyeye_types.h"
enum tdstate {
t_undefined, // Undefined Thumb instruction
t_decoded, // Instruction decoded to ARM equivalent
t_branch, // Thumb branch (already processed)
t_uninitialized,
};
tdstate
thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size);
static inline uint32 get_thumb_instr(uint32 instr, addr_t pc){
uint32 tinstr;
if ((pc & 0x3) != 0)
tinstr = instr >> 16;
else
tinstr = instr & 0xFFFF;
return tinstr;
}
#endif

View file

@ -4,7 +4,7 @@
#include "core/arm/interpreter/arm_interpreter.h"
const static cpu_config_t s_arm11_cpu_info = {
const static cpu_config_t arm11_cpu_info = {
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
};
@ -17,12 +17,11 @@ ARM_Interpreter::ARM_Interpreter() {
ARMul_NewState(state);
state->abort_model = 0;
state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
state->cpu = (cpu_config_t*)&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_CoProInit(state);

View file

@ -7,10 +7,10 @@
#include "common/common.h"
#include "core/arm/arm_interface.h"
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/interpreter/armemu.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
class ARM_Interpreter : virtual public ARM_Interface {
class ARM_Interpreter final : virtual public ARM_Interface {
public:
ARM_Interpreter();

View file

@ -15,74 +15,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/interpreter/armos.h"
#include "core/arm/interpreter/armemu.h"
#include "core/arm/interpreter/vfp/vfp.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
//chy 2005-07-08
//#include "ansidecl.h"
//chy -------
//#include "iwmmxt.h"
//chy 2005-09-19 add CP6 MRC support (for get irq number and base)
extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
//chy 2005-09-19---------------
extern unsigned xscale_cp13_init (ARMul_State * state);
extern unsigned xscale_cp13_exit (ARMul_State * state);
extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type,
ARMword instr);
extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg,
ARMword * data);
extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg,
ARMword data);
extern unsigned xscale_cp14_init (ARMul_State * state);
extern unsigned xscale_cp14_exit (ARMul_State * state);
extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type,
ARMword instr);
extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
ARMword * data);
extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
ARMword data);
extern unsigned xscale_cp15_init (ARMul_State * state);
extern unsigned xscale_cp15_exit (ARMul_State * state);
extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type,
ARMword instr, ARMword * data);
extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type,
ARMword instr, ARMword data);
extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type,
ARMword instr);
extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
ARMword * data);
extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
ARMword data);
extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
unsigned cpnum);
/* Dummy Co-processors. */
static unsigned
@ -132,42 +73,6 @@ NoCoPro5W (ARMul_State * state,
static void write_cp14_reg(unsigned, ARMword);
static ARMword read_cp14_reg(unsigned);
/* There are two sets of registers for copro 15.
One set is available when opcode_2 is 0 and
the other set when opcode_2 >= 1. */
static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
/* There are also a set of breakpoint registers
which are accessed via CRm instead of opcode_2. */
static ARMword XScale_cp15_DBR1;
static ARMword XScale_cp15_DBCON;
static ARMword XScale_cp15_IBCR0;
static ARMword XScale_cp15_IBCR1;
static unsigned
XScale_cp15_init (ARMul_State * state)
{
int i;
for (i = 16; i--;) {
XScale_cp15_opcode_2_is_0_Regs[i] = 0;
XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
}
/* Initialise the processor ID. */
//chy 2003-03-24, is same as cpu id in skyeye_options.c
//XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000;
/* Initialise the cache type. */
XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
/* Initialise the ARM Control Register. */
XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
return No_exp;
}
/* Check an access to a register. */
static unsigned
@ -305,347 +210,6 @@ check_cp15_access (ARMul_State * state,
return ARMul_DONE;
}
/* Coprocessor 13: Interrupt Controller and Bus Controller. */
/* There are two sets of registers for copro 13.
One set (of three registers) is available when CRm is 0
and the other set (of six registers) when CRm is 1. */
static ARMword XScale_cp13_CR0_Regs[16];
static ARMword XScale_cp13_CR1_Regs[16];
static unsigned
XScale_cp13_init (ARMul_State * state)
{
int i;
for (i = 16; i--;) {
XScale_cp13_CR0_Regs[i] = 0;
XScale_cp13_CR1_Regs[i] = 0;
}
return No_exp;
}
/* Check an access to a register. */
static unsigned
check_cp13_access (ARMul_State * state,
unsigned reg,
unsigned CRm, unsigned opcode_1, unsigned opcode_2)
{
/* Do not allow access to these registers in USER mode. */
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
if (state->Mode == USER26MODE || state->Mode == USER32MODE )
return ARMul_CANT;
/* The opcodes should be zero. */
if ((opcode_1 != 0) || (opcode_2 != 0))
return ARMul_CANT;
/* Do not allow access to these register if bit
13 of coprocessor 15's register 15 is zero. */
if (!CP_ACCESS_ALLOWED (state, 13))
return ARMul_CANT;
/* Registers 0, 4 and 8 are defined when CRm == 0.
Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
For all other CRm values undefined behaviour results. */
if (CRm == 0) {
if (reg == 0 || reg == 4 || reg == 8)
return ARMul_DONE;
}
else if (CRm == 1) {
if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
return ARMul_DONE;
}
return ARMul_CANT;
}
/* Coprocessor 14: Performance Monitoring, Clock and Power management,
Software Debug. */
static ARMword XScale_cp14_Regs[16];
static unsigned
XScale_cp14_init (ARMul_State * state)
{
int i;
for (i = 16; i--;)
XScale_cp14_Regs[i] = 0;
return No_exp;
}
/* Check an access to a register. */
static unsigned
check_cp14_access (ARMul_State * state,
unsigned reg,
unsigned CRm, unsigned opcode1, unsigned opcode2)
{
/* Not allowed to access these register in USER mode. */
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
if (state->Mode == USER26MODE || state->Mode == USER32MODE )
return ARMul_CANT;
/* CRm should be zero. */
if (CRm != 0)
return ARMul_CANT;
/* OPcodes should be zero. */
if (opcode1 != 0 || opcode2 != 0)
return ARMul_CANT;
/* Accessing registers 4 or 5 has unpredicatable results. */
if (reg >= 4 && reg <= 5)
return ARMul_CANT;
return ARMul_DONE;
}
/* Here's ARMulator's MMU definition. A few things to note:
1) It has eight registers, but only two are defined.
2) You can only access its registers with MCR and MRC.
3) MMU Register 0 (ID) returns 0x41440110
4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4
controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
bit 6 controls late abort timimg and bit 7 controls big/little endian. */
static ARMword MMUReg[8];
static unsigned
MMUInit (ARMul_State * state)
{
/* 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
because the ARMs which skyeye simulates are all belonged to ARMv4,
so I think MMUReg[1]'s bit 6 should always be 1
*/
MMUReg[1] = state->prog32Sig << 4 |
state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7;
//state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present");
return TRUE;
}
static unsigned
MMUMRC (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value)
{
mmu_mrc (state, instr, value);
return (ARMul_DONE);
}
static unsigned
MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
{
mmu_mcr (state, instr, value);
return (ARMul_DONE);
}
/* What follows is the Validation Suite Coprocessor. It uses two
co-processor numbers (4 and 5) and has the follwing functionality.
Sixteen registers. Both co-processor nuimbers can be used in an MCR
and MRC to access these registers. CP 4 can LDC and STC to and from
the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of
cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a
number of cycles (specified in a CP register), CDP 2 issues an IRQW
in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
stores a 32 bit time value in a CP register (actually it's the total
number of N, S, I, C and F cyles). */
static ARMword ValReg[16];
static unsigned
ValLDC (ARMul_State * state,
unsigned type, ARMword instr, ARMword data)
{
static unsigned words;
if (type != ARMul_DATA)
words = 0;
else {
ValReg[BITS (12, 15)] = data;
if (BIT (22))
/* It's a long access, get two words. */
if (words++ != 4)
return ARMul_INC;
}
return ARMul_DONE;
}
static unsigned
ValSTC (ARMul_State * state,
unsigned type, ARMword instr, ARMword * data)
{
static unsigned words;
if (type != ARMul_DATA)
words = 0;
else {
*data = ValReg[BITS (12, 15)];
if (BIT (22))
/* It's a long access, get two words. */
if (words++ != 4)
return ARMul_INC;
}
return ARMul_DONE;
}
static unsigned
ValMRC (ARMul_State * state,
unsigned type, ARMword instr, ARMword * value)
{
*value = ValReg[BITS (16, 19)];
return ARMul_DONE;
}
static unsigned
ValMCR (ARMul_State * state,
unsigned type, ARMword instr, ARMword value)
{
ValReg[BITS (16, 19)] = value;
return ARMul_DONE;
}
static unsigned
ValCDP (ARMul_State * state, unsigned type, ARMword instr)
{
static unsigned int finish = 0;
if (BITS (20, 23) != 0)
return ARMul_CANT;
if (type == ARMul_FIRST) {
ARMword howlong;
howlong = ValReg[BITS (0, 3)];
/* First cycle of a busy wait. */
finish = ARMul_Time (state) + howlong;
return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
}
else if (type == ARMul_BUSY) {
if (ARMul_Time (state) >= finish)
return ARMul_DONE;
else
return ARMul_BUSY;
}
return ARMul_CANT;
}
static unsigned
DoAFIQ (ARMul_State * state)
{
state->NfiqSig = LOW;
return 0;
}
static unsigned
DoAIRQ (ARMul_State * state)
{
state->NirqSig = LOW;
return 0;
}
static unsigned
IntCDP (ARMul_State * state, unsigned type, ARMword instr)
{
static unsigned int finish;
ARMword howlong;
howlong = ValReg[BITS (0, 3)];
switch ((int) BITS (20, 23)) {
case 0:
if (type == ARMul_FIRST) {
/* First cycle of a busy wait. */
finish = ARMul_Time (state) + howlong;
return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
}
else if (type == ARMul_BUSY) {
if (ARMul_Time (state) >= finish)
return ARMul_DONE;
else
return ARMul_BUSY;
}
return ARMul_DONE;
case 1:
if (howlong == 0)
ARMul_Abort (state, ARMul_FIQV);
else
ARMul_ScheduleEvent (state, howlong, DoAFIQ);
return ARMul_DONE;
case 2:
if (howlong == 0)
ARMul_Abort (state, ARMul_IRQV);
else
ARMul_ScheduleEvent (state, howlong, DoAIRQ);
return ARMul_DONE;
case 3:
state->NfiqSig = HIGH;
return ARMul_DONE;
case 4:
state->NirqSig = HIGH;
return ARMul_DONE;
case 5:
ValReg[BITS (0, 3)] = ARMul_Time (state);
return ARMul_DONE;
}
return ARMul_CANT;
}
/* Install co-processor instruction handlers in this routine. */
unsigned
@ -662,64 +226,14 @@ ARMul_CoProInit (ARMul_State * state)
ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
LDC routine, STC routine, MRC routine, MCR routine,
CDP routine, Read Reg routine, Write Reg routine). */
if (state->is_ep9312) {
ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4,
DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL);
ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5,
DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL);
ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL,
DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL);
}
else {
ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC,
ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL);
ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL);
}
if (state->is_XScale) {
//chy 2005-09-19, for PXA27x's CP6
if (state->is_pxa27x) {
ARMul_CoProAttach (state, 6, NULL, NULL,
NULL, NULL, xscale_cp6_mrc,
NULL, NULL, NULL, NULL, NULL, NULL);
}
//chy 2005-09-19 end-------------
ARMul_CoProAttach (state, 13, xscale_cp13_init,
xscale_cp13_exit, xscale_cp13_ldc,
xscale_cp13_stc, xscale_cp13_mrc,
xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp,
xscale_cp13_read_reg,
xscale_cp13_write_reg);
ARMul_CoProAttach (state, 14, xscale_cp14_init,
xscale_cp14_exit, xscale_cp14_ldc,
xscale_cp14_stc, xscale_cp14_mrc,
xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp,
xscale_cp14_read_reg,
xscale_cp14_write_reg);
//chy: 2003-08-24.
ARMul_CoProAttach (state, 15, xscale_cp15_init,
xscale_cp15_exit, xscale_cp15_ldc,
xscale_cp15_stc, xscale_cp15_mrc,
xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp,
xscale_cp15_read_reg,
xscale_cp15_write_reg);
}
else if (state->is_v6) {
if (state->is_v6) {
ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
}
else { //all except xscale
ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
// MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
/*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/
}
//chy 2003-09-03 do it in future!!!!????
#if 0
@ -732,13 +246,6 @@ ARMul_CoProInit (ARMul_State * state)
NULL);
}
#endif
//-----------------------------------------------------------------------------
//chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code.
ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL);
ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
//------------------------------------------------------------------------------
/* No handlers below here. */
/* Call all the initialisation routines. */
@ -816,27 +323,3 @@ ARMul_CoProDetach (ARMul_State * state, unsigned number)
state->CPRead[number] = NULL;
state->CPWrite[number] = NULL;
}
//chy 2003-09-03:below funs just replace the old ones
/* Set the XScale FSR and FAR registers. */
void
XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far)
{
//if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
if (!state->is_XScale)
return;
//assume opcode2=0 crm =0
xscale_cp15_write_reg (state, 5, fsr);
xscale_cp15_write_reg (state, 6, _far);
}
//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????
int
XScale_debug_moe (ARMul_State * state, int moe)
{
//chy 2003-09-03 , W/R CP14 reg, now it's no use ????
printf ("SKYEYE: XScale_debug_moe called !!!!\n");
return 1;
}

View file

@ -18,9 +18,9 @@
//#include <util.h> // DEBUG()
#include "arm_regformat.h"
#include "armdefs.h"
#include "armemu.h"
#include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/hle/hle.h"
//#include "svc.h"
@ -28,9 +28,6 @@
//ichfly
//#define callstacker 1
//#include "armos.h"
//#include "skyeye_callback.h"
//#include "skyeye_bus.h"
//#include "sim_control.h"

View file

@ -17,8 +17,8 @@
//#include <unistd.h>
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/interpreter/armemu.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
/***************************************************************************\
* Definitions for the emulator architecture *

View file

@ -1,238 +0,0 @@
/*
armmmu.c - Memory Management Unit emulation.
ARMulator extensions for the ARM7100 family.
Copyright (C) 1999 Ben Williamson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <string.h>
#include "armdefs.h"
/* two header for arm disassemble */
//#include "skyeye_arch.h"
#include "armcpu.h"
extern mmu_ops_t xscale_mmu_ops;
exception_t arm_mmu_write(short size, u32 addr, uint32_t *value);
exception_t arm_mmu_read(short size, u32 addr, uint32_t *value);
#define MMU_OPS (state->mmu.ops)
ARMword skyeye_cachetype = -1;
int
mmu_init (ARMul_State * state)
{
int ret;
state->mmu.control = 0x70;
state->mmu.translation_table_base = 0xDEADC0DE;
state->mmu.domain_access_control = 0xDEADC0DE;
state->mmu.fault_status = 0;
state->mmu.fault_address = 0;
state->mmu.process_id = 0;
switch (state->cpu->cpu_val & state->cpu->cpu_mask) {
//case SA1100:
//case SA1110:
// NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
// state->mmu.ops = sa_mmu_ops;
// break;
//case PXA250:
//case PXA270: //xscale
// NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
// state->mmu.ops = xscale_mmu_ops;
// break;
//case 0x41807200: //arm720t
//case 0x41007700: //arm7tdmi
//case 0x41007100: //arm7100
// NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n");
// state->mmu.ops = arm7100_mmu_ops;
// break;
//case 0x41009200:
// NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
// state->mmu.ops = arm920t_mmu_ops;
// break;
//case 0x41069260:
// NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
// state->mmu.ops = arm926ejs_mmu_ops;
// break;
/* case 0x560f5810: */
case 0x0007b000:
NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n");
state->mmu.ops = arm1176jzf_s_mmu_ops;
break;
default:
ERROR_LOG (ARM11,
"SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n",
state->cpu->cpu_val & state->cpu->cpu_mask);
break;
};
ret = state->mmu.ops.init (state);
state->mmu_inited = (ret == 0);
/* initialize mmu_read and mmu_write for disassemble */
//skyeye_config_t *config = get_current_config();
//generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
//arch_instance->mmu_read = arm_mmu_read;
//arch_instance->mmu_write = arm_mmu_write;
return ret;
}
int
mmu_reset (ARMul_State * state)
{
if (state->mmu_inited)
mmu_exit (state);
return mmu_init (state);
}
void
mmu_exit (ARMul_State * state)
{
MMU_OPS.exit (state);
state->mmu_inited = 0;
}
fault_t
mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_byte (state, virt_addr, data);
};
fault_t
mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_halfword (state, virt_addr, data);
};
fault_t
mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return MMU_OPS.read_word (state, virt_addr, data);
};
fault_t
mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
//static int count = 0;
//count ++;
fault = MMU_OPS.write_byte (state, virt_addr, data);
return fault;
}
fault_t
mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
//static int count = 0;
//count ++;
fault = MMU_OPS.write_halfword (state, virt_addr, data);
return fault;
}
fault_t
mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
{
fault_t fault;
fault = MMU_OPS.write_word (state, virt_addr, data);
/*used for debug for MMU*
if (!fault){
ARMword tmp;
if (mmu_read_word(state, virt_addr, &tmp)){
err_msg("load back\n");
exit(-1);
}else{
if (tmp != data){
err_msg("load back not equal %d %x\n", count, virt_addr);
}
}
}
*/
return fault;
};
fault_t
mmu_load_instr (ARMul_State * state, ARMword virt_addr, ARMword * instr)
{
return MMU_OPS.load_instr (state, virt_addr, instr);
}
ARMword
mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
return MMU_OPS.mrc (state, instr, value);
}
void
mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
MMU_OPS.mcr (state, instr, value);
}
/*ywc 20050416*/
int
mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
{
return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr));
}
//
//
///* dis_mmu_read for disassemble */
//exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
//{
// ARMul_State *state;
// ARM_CPU_State *cpu = get_current_cpu();
// state = &cpu->core[0];
// switch(size){
// case 8:
// MMU_OPS.read_byte (state, addr, value);
// break;
// case 16:
// case 32:
// break;
// default:
// ERROR_LOG(ARM11, "Error size %d", size);
// break;
// }
// return No_exp;
//}
///* dis_mmu_write for disassemble */
//exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
//{
// ARMul_State *state;
// ARM_CPU_State *cpu = get_current_cpu();
// state = &cpu->core[0];
// switch(size){
// case 8:
// MMU_OPS.write_byte (state, addr, value);
// break;
// case 16:
// case 32:
// break;
// default:
// printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
// break;
// }
// return No_exp;
//}

View file

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

View file

@ -15,18 +15,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
//#include <util.h>
#include <string>
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/interpreter/armemu.h"
#include "core/hle/coprocessor.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/disassembler/arm_disasm.h"
#include "core/mem_map.h"
//#include "ansidecl.h"
//#include "skyeye.h"
//extern int skyeye_instr_debug;
/* Definitions for the support routines. */
static ARMword ModeToBank (ARMword);
static void EnvokeList (ARMul_State *, unsigned int, unsigned int);
@ -751,7 +744,7 @@ ARMword ARMul_MRC (ARMul_State * state, ARMword instr)
int cpopc = BITS(21, 23) & 0x7;
if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer
ARMword result = HLE::CallMRC(instr);
ARMword result = Memory::KERNEL_MEMORY_VADDR;
if (result != -1) {
return result;

View file

@ -23,312 +23,35 @@ 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"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#ifdef VALIDATE /* for running the validate suite */
#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
#define ABORTS 1
#endif
#include "core/mem_map.h"
/* #define ABORTS */
#define dumpstack 1
#define dumpstacksize 0x10
#define maxdmupaddr 0x0033a850
#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);
/*ARMword ARMul_GetCPSR (ARMul_State * state) {
return 0;
}
return fault;
ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) {
return 0;
}
/***************************************************************************\
* 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);
void ARMul_SetCPSR (ARMul_State * state, ARMword value) {
}
#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);
void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) {
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;
void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) {
}
return data;
void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) {
}
/***************************************************************************\
* Load Instruction, Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
{
ARMword ARMul_LoadInstrS(ARMul_State * state, ARMword address, ARMword isize) {
state->NumScycles++;
#ifdef HOURGLASS
@ -336,345 +59,107 @@ ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
HOURGLASS;
}
#endif
return ARMul_ReLoadInstr (state, address, isize);
if (isize == 2)
return (u16)Memory::Read16(address);
else
return (u32)Memory::Read32(address);
}
/***************************************************************************\
* Load Instruction, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
{
ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) {
state->NumNcycles++;
return ARMul_ReLoadInstr (state, address, isize);
if (isize == 2)
return (u16)Memory::Read16(address);
else
return (u32)Memory::Read32(address);
}
/***************************************************************************\
* Read Word (but don't tell anyone!) *
\***************************************************************************/
ARMword
ARMul_ReadWord (ARMul_State * state, ARMword address)
{
ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) {
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
if ((isize == 2) && (address & 0x2)) {
ARMword lo;
lo = (u16)Memory::Read16(address);
return lo;
}
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;
}
data = (u32)Memory::Read32(address);
return data;
}
/***************************************************************************\
* Load Word, Sequential Cycle *
\***************************************************************************/
ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) {
ARMword data;
data = Memory::Read32(address);
return data;
}
ARMword
ARMul_LoadWordS (ARMul_State * state, ARMword address)
{
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)
{
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;
ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) {
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 (u16)Memory::Read16(address);;
}
return data;
ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) {
return (u8)Memory::Read8(address);
}
/***************************************************************************\
* 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)
{
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)
{
void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) {
state->NumNcycles++;
ARMul_WriteWord (state, address, data);
Memory::Write16(address, data);
}
/***************************************************************************\
* Store HalfWord, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) {
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 ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) {
ARMword temp;
state->NumNcycles++;
temp = ARMul_ReadWord(state, address);
state->NumNcycles++;
PutWord (state, address, data);
Memory::Write32(address, data);
return temp;
}
/***************************************************************************\
* Swap Byte, (Two Non Sequential Cycles) *
\***************************************************************************/
ARMword
ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
{
ARMword ARMul_SwapByte(ARMul_State * state, ARMword address, ARMword data) {
ARMword temp;
temp = ARMul_LoadByte(state, address);
ARMul_StoreByte (state, address, data);
Memory::Write8(address, data);
return temp;
}
/***************************************************************************\
* Count I Cycles *
\***************************************************************************/
void
ARMul_Icycles (ARMul_State * state, unsigned number,
ARMword address)
{
state->NumIcycles += number;
ARMul_CLEARABORT;
void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) {
Memory::Write32(address, data);
}
/***************************************************************************\
* Count C Cycles *
\***************************************************************************/
void
ARMul_Ccycles (ARMul_State * state, unsigned number,
ARMword address)
void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data)
{
state->NumCcycles += number;
ARMul_CLEARABORT;
Memory::Write8(address, data);
}
void ARMul_StoreWordS(ARMul_State * state, ARMword address, ARMword data)
{
state->NumScycles++;
ARMul_WriteWord(state, address, data);
}
void ARMul_StoreWordN(ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
ARMul_WriteWord(state, address, data);
}

File diff suppressed because it is too large Load diff

View file

@ -1,37 +0,0 @@
/*
arm1176JZF-S_mmu.h - ARM1176JZF-S Memory Management Unit emulation.
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 _ARM1176JZF_S_MMU_H_
#define _ARM1176JZF_S_MMU_H_
#if 0
typedef struct arm1176jzf-s_mmu_s
{
tlb_t i_tlb;
cache_t i_cache;
tlb_t d_tlb;
cache_t d_cache;
wb_t wb_t;
} arm1176jzf-s_mmu_t;
#endif
extern mmu_ops_t arm1176jzf_s_mmu_ops;
ARMword
arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value);
#endif /*_ARM1176JZF_S_MMU_H_*/

View file

@ -1,370 +0,0 @@
#include "core/arm/interpreter/armdefs.h"
/* mmu cache init
*
* @cache_t :cache_t to init
* @width :cache line width in byte
* @way :way of each cache set
* @set :cache set num
*
* $ -1: error
* 0: sucess
*/
int
mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode)
{
int i, j;
cache_set_t *sets;
cache_line_t *lines;
/*alloc cache set */
sets = NULL;
lines = NULL;
//fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets);
//exit(-1);
sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set);
if (sets == NULL) {
ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set);
goto sets_error;
}
//fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets);
cache_t->sets = sets;
/*init cache set */
for (i = 0; i < set; i++) {
/*alloc cache line */
lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way);
if (lines == NULL) {
ERROR_LOG(ARM11, "line malloc size %d\n",
sizeof (cache_line_t) * way);
goto lines_error;
}
/*init cache line */
for (j = 0; j < way; j++) {
lines[j].tag = 0; //invalid
lines[j].data = (ARMword *) malloc (width);
if (lines[j].data == NULL) {
ERROR_LOG(ARM11, "data alloc size %d\n", width);
goto data_error;
}
}
sets[i].lines = lines;
sets[i].cycle = 0;
}
cache_t->width = width;
cache_t->set = set;
cache_t->way = way;
cache_t->w_mode = w_mode;
return 0;
data_error:
/*free data */
while (j-- > 0)
free (lines[j].data);
/*free data error line */
free (lines);
lines_error:
/*free lines already alloced */
while (i-- > 0) {
for (j = 0; j < way; j++)
free (sets[i].lines[j].data);
free (sets[i].lines);
}
/*free sets */
free (sets);
sets_error:
return -1;
};
/* free a cache_t's inner data, the ptr self is not freed,
* when needed do like below:
* mmu_cache_exit(cache);
* free(cache_t);
*
* @cache_t : the cache_t to free
*/
void
mmu_cache_exit (cache_s * cache_t)
{
int i, j;
cache_set_t *sets, *set;
cache_line_t *lines, *line;
/*free all set */
sets = cache_t->sets;
for (set = sets, i = 0; i < cache_t->set; i++, set++) {
/*free all line */
lines = set->lines;
for (line = lines, j = 0; j < cache_t->way; j++, line++)
free (line->data);
free (lines);
}
free (sets);
}
/* mmu cache search
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @va :virtual address
*
* $ NULL: no cache match
* cache :cache matched
*/
cache_line_t *
mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va)
{
int i;
int set = va_cache_set (va, cache_t);
ARMword tag = va_cache_align (va, cache_t);
cache_line_t *cache;
cache_set_t *cache_set = cache_t->sets + set;
for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) {
if ((cache->tag & TAG_VALID_FLAG)
&& (tag == va_cache_align (cache->tag, cache_t)))
return cache;
}
return NULL;
}
/* mmu cache search by set/index
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @index :set/index value.
*
* $ NULL: no cache match
* cache :cache matched
*/
cache_line_t *
mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index)
{
int way = cache_t->way;
int set_v = index_cache_set (index, cache_t);
int i = 0, index_v = 0;
cache_set_t *set;
while ((way >>= 1) >= 1)
i++;
index_v = index >> (32 - i);
set = cache_t->sets + set_v;
return set->lines + index_v;
}
/* mmu cache alloc
*
* @state :ARMul_State
* @cache_t :cache_t to alloc from
* @va :virtual address that require cache alloc, need not cache aligned
* @pa :physical address of va
*
* $ cache_alloced, always alloc OK
*/
cache_line_t *
mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va,
ARMword pa)
{
cache_line_t *cache;
cache_set_t *set;
int i;
va = va_cache_align (va, cache_t);
pa = va_cache_align (pa, cache_t);
set = &cache_t->sets[va_cache_set (va, cache_t)];
/*robin-round */
cache = &set->lines[set->cycle++];
if (set->cycle == cache_t->way)
set->cycle = 0;
if (cache_t->w_mode == CACHE_WRITE_BACK) {
ARMword t;
/*if cache valid, try to write back */
if (cache->tag & TAG_VALID_FLAG) {
mmu_cache_write_back (state, cache_t, cache);
}
/*read in cache_line */
t = pa;
for (i = 0; i < (cache_t->width >> WORD_SHT);
i++, t += WORD_SIZE) {
//cache->data[i] = mem_read_word (state, t);
bus_read(32, t, &cache->data[i]);
}
}
/*store tag and pa */
cache->tag = va | TAG_VALID_FLAG;
cache->pa = pa;
return cache;
};
/* mmu_cache_write_back write cache data to memory
* @state
* @cache_t :cache_t of the cache line
* @cache : cache line
*/
void
mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
cache_line_t * cache)
{
ARMword pa = cache->pa;
int nw = cache_t->width >> WORD_SHT;
ARMword *data = cache->data;
int i;
int t0, t1, t2;
if ((cache->tag & 1) == 0)
return;
switch (cache->
tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) {
case 0:
return;
case TAG_FIRST_HALF_DIRTY:
nw /= 2;
break;
case TAG_LAST_HALF_DIRTY:
nw /= 2;
pa += nw << WORD_SHT;
data += nw;
break;
case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY:
break;
}
for (i = 0; i < nw; i++, data++, pa += WORD_SIZE)
//mem_write_word (state, pa, *data);
bus_write(32, pa, *data);
cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY);
};
/* mmu_cache_clean: clean a cache of va in cache_t
*
* @state :ARMul_State
* @cache_t :cache_t to clean
* @va :virtaul address
*/
void
mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va)
{
cache_line_t *cache;
cache = mmu_cache_search (state, cache_t, va);
if (cache)
mmu_cache_write_back (state, cache_t, cache);
}
/* mmu_cache_clean_by_index: clean a cache by set/index format value
*
* @state :ARMul_State
* @cache_t :cache_t to clean
* @va :set/index format value
*/
void
mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index)
{
cache_line_t *cache;
cache = mmu_cache_search_by_index (state, cache_t, index);
if (cache)
mmu_cache_write_back (state, cache_t, cache);
}
/* mmu_cache_invalidate : invalidate a cache of va
*
* @state :ARMul_State
* @cache_t :cache_t to invalid
* @va :virt_addr to invalid
*/
void
mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va)
{
cache_line_t *cache;
cache = mmu_cache_search (state, cache_t, va);
if (cache) {
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
}
/* mmu_cache_invalidate_by_index : invalidate a cache by index format
*
* @state :ARMul_State
* @cache_t :cache_t to invalid
* @index :set/index data
*/
void
mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index)
{
cache_line_t *cache;
cache = mmu_cache_search_by_index (state, cache_t, index);
if (cache) {
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
}
/* mmu_cache_invalidate_all
*
* @state:
* @cache_t
* */
void
mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t)
{
int i, j;
cache_set_t *set;
cache_line_t *cache;
set = cache_t->sets;
for (i = 0; i < cache_t->set; i++, set++) {
cache = set->lines;
for (j = 0; j < cache_t->way; j++, cache++) {
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
}
};
void
mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa)
{
ARMword set, way;
cache_line_t *cache;
pa = (pa / cache_t->width);
way = pa & (cache_t->way - 1);
set = (pa / cache_t->way) & (cache_t->set - 1);
cache = &cache_t->sets[set].lines[way];
mmu_cache_write_back (state, cache_t, cache);
cache->tag = 0;
}
cache_line_t* mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){
int i;
int j;
cache_line_t *cache_line = NULL;
cache_set_t *cache_set = cache->sets;
int sets = cache->set;
for (i = 0; i < sets; i++){
for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){
if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY))
return cache_line;
}
}
return NULL;
}

View file

@ -1,168 +0,0 @@
#ifndef _MMU_CACHE_H_
#define _MMU_CACHE_H_
typedef struct cache_line_t
{
ARMword tag; /* cache line align address |
bit2: last half dirty
bit1: first half dirty
bit0: cache valid flag
*/
ARMword pa; /*physical address */
ARMword *data; /*array of cached data */
} cache_line_t;
#define TAG_VALID_FLAG 0x00000001
#define TAG_FIRST_HALF_DIRTY 0x00000002
#define TAG_LAST_HALF_DIRTY 0x00000004
/*cache set association*/
typedef struct cache_set_s
{
cache_line_t *lines;
int cycle;
} cache_set_t;
enum
{
CACHE_WRITE_BACK,
CACHE_WRITE_THROUGH,
};
typedef struct cache_s
{
int width; /*bytes in a line */
int way; /*way of set asscociate */
int set; /*num of set */
int w_mode; /*write back or write through */
//int a_mode; /*alloc mode: random or round-bin*/
cache_set_t *sets;
/**/} cache_s;
typedef struct cache_desc_s
{
int width;
int way;
int set;
int w_mode;
// int a_mode;
} cache_desc_t;
/*virtual address to cache set index*/
#define va_cache_set(va, cache_t) \
(((va) / (cache_t)->width) & ((cache_t)->set - 1))
/*virtual address to cahce line aligned*/
#define va_cache_align(va, cache_t) \
((va) & ~((cache_t)->width - 1))
/*virtaul address to cache line word index*/
#define va_cache_index(va, cache_t) \
(((va) & ((cache_t)->width - 1)) >> WORD_SHT)
/*see Page 558 in arm manual*/
/*set/index format value to cache set value*/
#define index_cache_set(index, cache_t) \
(((index) / (cache_t)->width) & ((cache_t)->set - 1))
/*************************cache********************/
/* mmu cache init
*
* @cache_t :cache_t to init
* @width :cache line width in byte
* @way :way of each cache set
* @set :cache set num
* @w_mode :cache w_mode
*
* $ -1: error
* 0: sucess
*/
int
mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode);
/* free a cache_t's inner data, the ptr self is not freed,
* when needed do like below:
* mmu_cache_exit(cache);
* free(cache_t);
*
* @cache_t : the cache_t to free
*/
void mmu_cache_exit (cache_s * cache_t);
/* mmu cache search
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @va :virtual address
*
* $ NULL: no cache match
* cache :cache matched
* */
cache_line_t *mmu_cache_search (ARMul_State * state, cache_s * cache_t,
ARMword va);
/* mmu cache search by set/index
*
* @state :ARMul_State
* @cache_t :cache_t to search
* @index :set/index value.
*
* $ NULL: no cache match
* cache :cache matched
* */
cache_line_t *mmu_cache_search_by_index (ARMul_State * state,
cache_s * cache_t, ARMword index);
/* mmu cache alloc
*
* @state :ARMul_State
* @cache_t :cache_t to alloc from
* @va :virtual address that require cache alloc, need not cache aligned
* @pa :physical address of va
*
* $ cache_alloced, always alloc OK
*/
cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_s * cache_t,
ARMword va, ARMword pa);
/* mmu_cache_write_back write cache data to memory
*
* @state:
* @cache_t :cache_t of the cache line
* @cache : cache line
*/
void
mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
cache_line_t * cache);
/* mmu_cache_clean: clean a cache of va in cache_t
*
* @state :ARMul_State
* @cache_t :cache_t to clean
* @va :virtaul address
*/
void mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va);
void
mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index);
/* mmu_cache_invalidate : invalidate a cache of va
*
* @state :ARMul_State
* @cache_t :cache_t to invalid
* @va :virt_addr to invalid
*/
void
mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va);
void
mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
ARMword index);
void mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t);
void
mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa);
cache_line_t* mmu_cache_dirty_cache(ARMul_State * state, cache_s * cache_t);
#endif /*_MMU_CACHE_H_*/

File diff suppressed because it is too large Load diff

View file

@ -1,126 +0,0 @@
#include "core/arm/interpreter/armdefs.h"
/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/
ARMword rb_masks[] = {
0x0, //RB_INVALID
4, //RB_1
16, //RB_4
32, //RB_8
};
/*mmu_rb_init
* @rb_t :rb_t to init
* @num :number of entry
* */
int
mmu_rb_init (rb_s * rb_t, int num)
{
int i;
rb_entry_t *entrys;
entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num);
if (entrys == NULL) {
printf ("SKYEYE:mmu_rb_init malloc error\n");
return -1;
}
for (i = 0; i < num; i++) {
entrys[i].type = RB_INVALID;
entrys[i].fault = NO_FAULT;
}
rb_t->entrys = entrys;
rb_t->num = num;
return 0;
}
/*mmu_rb_exit*/
void
mmu_rb_exit (rb_s * rb_t)
{
free (rb_t->entrys);
};
/*mmu_rb_search
* @rb_t :rb_t to serach
* @va :va address to math
*
* $ NULL :not match
* NO-NULL:
* */
rb_entry_t *
mmu_rb_search (rb_s * rb_t, ARMword va)
{
int i;
rb_entry_t *rb = rb_t->entrys;
DEBUG_LOG(ARM11, "va = %x\n", va);
for (i = 0; i < rb_t->num; i++, rb++) {
//2004-06-06 lyh bug from wenye@cs.ucsb.edu
if (rb->type) {
if ((va >= rb->va)
&& (va < (rb->va + rb_masks[rb->type])))
return rb;
}
}
return NULL;
};
void
mmu_rb_invalidate_entry (rb_s * rb_t, int i)
{
rb_t->entrys[i].type = RB_INVALID;
}
void
mmu_rb_invalidate_all (rb_s * rb_t)
{
int i;
for (i = 0; i < rb_t->num; i++)
mmu_rb_invalidate_entry (rb_t, i);
};
void
mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va)
{
rb_entry_t *rb;
int i;
ARMword max_start, min_end;
fault_t fault;
tlb_entry_t *tlb;
/*align va according to type */
va &= ~(rb_masks[type] - 1);
/*invalidate all RB match [va, va + rb_masks[type]] */
for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) {
if (rb->type) {
max_start = max (va, rb->va);
min_end =
min (va + rb_masks[type],
rb->va + rb_masks[rb->type]);
if (max_start < min_end)
rb->type = RB_INVALID;
}
}
/*load word */
rb = &rb_t->entrys[i_rb];
rb->type = type;
fault = translate (state, va, D_TLB (), &tlb);
if (fault) {
rb->fault = fault;
return;
}
fault = check_access (state, va, tlb, 1);
if (fault) {
rb->fault = fault;
return;
}
rb->fault = NO_FAULT;
va = tlb_va_to_pa (tlb, va);
//2004-06-06 lyh bug from wenye@cs.ucsb.edu
for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) {
//rb->data[i] = mem_read_word (state, va);
bus_read(32, va, &rb->data[i]);
};
}

View file

@ -1,55 +0,0 @@
#ifndef _MMU_RB_H
#define _MMU_RB_H
enum rb_type_t
{
RB_INVALID = 0, //invalid
RB_1, //1 word
RB_4, //4 word
RB_8, //8 word
};
/*bytes of each rb_type*/
extern ARMword rb_masks[];
#define RB_WORD_NUM 8
typedef struct rb_entry_s
{
ARMword data[RB_WORD_NUM]; //array to store data
ARMword va; //first word va
int type; //rb type
fault_t fault; //fault set by rb alloc
} rb_entry_t;
typedef struct rb_s
{
int num;
rb_entry_t *entrys;
} rb_s;
/*mmu_rb_init
* @rb_t :rb_t to init
* @num :number of entry
* */
int mmu_rb_init (rb_s * rb_t, int num);
/*mmu_rb_exit*/
void mmu_rb_exit (rb_s * rb_t);
/*mmu_rb_search
* @rb_t :rb_t to serach
* @va :va address to math
*
* $ NULL :not match
* NO-NULL:
* */
rb_entry_t *mmu_rb_search (rb_s * rb_t, ARMword va);
void mmu_rb_invalidate_entry (rb_s * rb_t, int i);
void mmu_rb_invalidate_all (rb_s * rb_t);
void mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb,
int type, ARMword va);
#endif /*_MMU_RB_H_*/

View file

@ -1,864 +0,0 @@
/*
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 "core/arm/interpreter/armdefs.h"
/**
* The interface of read data from bus
*/
int bus_read(short size, int addr, uint32_t * value) {
ERROR_LOG(ARM11, "unimplemented bus_read");
return 0;
}
/**
* The interface of write data from bus
*/
int bus_write(short size, int addr, uint32_t value) {
ERROR_LOG(ARM11, "unimplemented bus_write");
return 0;
}
typedef struct sa_mmu_desc_s
{
int i_tlb;
cache_desc_t i_cache;
int d_tlb;
cache_desc_t main_d_cache;
cache_desc_t mini_d_cache;
int rb;
wb_desc_t wb;
} sa_mmu_desc_t;
static sa_mmu_desc_t sa11xx_mmu_desc = {
32,
{32, 32, 16, CACHE_WRITE_BACK},
32,
{32, 32, 8, CACHE_WRITE_BACK},
{32, 2, 8, CACHE_WRITE_BACK},
4,
//{8, 4}, for word size
{8, 16}, //for byte size, chy 2003-07-11
};
static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data,
ARMword datatype);
static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
ARMword datatype);
static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data,
ARMword datatype, cache_line_t * cache,
cache_s * cache_t, ARMword real_va);
void
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
ARMbyte * data, int n);
int
sa_mmu_init (ARMul_State * state)
{
sa_mmu_desc_t *desc;
cache_desc_t *c_desc;
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;
desc = &sa11xx_mmu_desc;
if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
goto i_tlb_init_error;
}
c_desc = &desc->i_cache;
if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
c_desc->set, c_desc->w_mode)) {
ERROR_LOG(ARM11, "i_cache init %d\n", -1);
goto i_cache_init_error;
}
if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
goto d_tlb_init_error;
}
c_desc = &desc->main_d_cache;
if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
c_desc->set, c_desc->w_mode)) {
ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
goto main_d_cache_init_error;
}
c_desc = &desc->mini_d_cache;
if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
c_desc->set, c_desc->w_mode)) {
ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
goto mini_d_cache_init_error;
}
if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
ERROR_LOG(ARM11, "wb init %d\n", -1);
goto wb_init_error;
}
if (mmu_rb_init (RB (), desc->rb)) {
ERROR_LOG(ARM11, "rb init %d\n", -1);
goto rb_init_error;
}
return 0;
rb_init_error:
mmu_wb_exit (WB ());
wb_init_error:
mmu_cache_exit (MINI_D_CACHE ());
mini_d_cache_init_error:
mmu_cache_exit (MAIN_D_CACHE ());
main_d_cache_init_error:
mmu_tlb_exit (D_TLB ());
d_tlb_init_error:
mmu_cache_exit (I_CACHE ());
i_cache_init_error:
mmu_tlb_exit (I_TLB ());
i_tlb_init_error:
return -1;
}
void
sa_mmu_exit (ARMul_State * state)
{
mmu_rb_exit (RB ());
mmu_wb_exit (WB ());
mmu_cache_exit (MINI_D_CACHE ());
mmu_cache_exit (MAIN_D_CACHE ());
mmu_tlb_exit (D_TLB ());
mmu_cache_exit (I_CACHE ());
mmu_tlb_exit (I_TLB ());
};
static fault_t
sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr)
{
fault_t fault;
tlb_entry_t *tlb;
cache_line_t *cache;
int c; //cache bit
ARMword pa; //physical addr
static int debug_count = 0; //used for debug
DEBUG_LOG(ARM11, "va = %x\n", va);
va = mmu_pid_va_map (va);
if (MMU_Enabled) {
/*align check */
if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
}
else
va &= ~(WORD_SIZE - 1);
/*translate tlb */
fault = translate (state, va, I_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*check access */
fault = check_access (state, va, tlb, 1);
if (fault) {
DEBUG_LOG(ARM11, "check_fault\n");
return fault;
}
}
/*search cache no matter MMU enabled/disabled */
cache = mmu_cache_search (state, I_CACHE (), va);
if (cache) {
*instr = cache->data[va_cache_index (va, I_CACHE ())];
return NO_FAULT;
}
/*if MMU disabled or C flag is set alloc cache */
if (MMU_Disabled) {
c = 1;
pa = va;
}
else {
c = tlb_c_flag (tlb);
pa = tlb_va_to_pa (tlb, va);
}
if (c) {
int index;
debug_count++;
cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
index = va_cache_index (va, I_CACHE ());
*instr = cache->data[va_cache_index (va, I_CACHE ())];
}
else
//*instr = mem_read_word (state, pa);
bus_read(32, pa, instr);
return NO_FAULT;
};
static fault_t
sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
//ARMword temp,offset;
fault_t fault;
fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
return fault;
}
static fault_t
sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
//ARMword temp,offset;
fault_t fault;
fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
return fault;
}
static fault_t
sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
{
return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
}
static fault_t
sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
ARMword datatype)
{
fault_t fault;
rb_entry_t *rb;
tlb_entry_t *tlb;
cache_line_t *cache;
ARMword pa, real_va, temp, offset;
DEBUG_LOG(ARM11, "va = %x\n", va);
va = mmu_pid_va_map (va);
real_va = va;
/*if MMU disabled, memory_read */
if (MMU_Disabled) {
//*data = mem_read_word(state, va);
if (datatype == ARM_BYTE_TYPE)
//*data = mem_read_byte (state, va);
bus_read(8, va, data);
else if (datatype == ARM_HALFWORD_TYPE)
//*data = mem_read_halfword (state, va);
bus_read(16, va, data);
else if (datatype == ARM_WORD_TYPE)
//*data = mem_read_word (state, va);
bus_read(32, va, data);
else {
printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype);
// skyeye_exit (-1);
}
return NO_FAULT;
}
/*align check */
if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
} // else
va &= ~(WORD_SIZE - 1);
/*translate va to tlb */
fault = translate (state, va, D_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*check access permission */
fault = check_access (state, va, tlb, 1);
if (fault)
return fault;
/*search in read buffer */
rb = mmu_rb_search (RB (), va);
if (rb) {
if (rb->fault)
return rb->fault;
*data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
goto datatrans;
//return 0;
};
/*search main cache */
cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
if (cache) {
*data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
goto datatrans;
//return 0;
}
/*search mini cache */
cache = mmu_cache_search (state, MINI_D_CACHE (), va);
if (cache) {
*data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
goto datatrans;
//return 0;
}
/*get phy_addr */
pa = tlb_va_to_pa (tlb, va);
if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
if (tlb_c_flag (tlb)) {
if (tlb_b_flag (tlb)) {
mmu_cache_soft_flush (state, MAIN_D_CACHE (),
pa);
}
else {
mmu_cache_soft_flush (state, MINI_D_CACHE (),
pa);
}
}
return NO_FAULT;
}
/*if Buffer, drain Write Buffer first */
if (tlb_b_flag (tlb))
mmu_wb_drain_all (state, WB ());
/*alloc cache or mem_read */
if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
cache_s *cache_t;
if (tlb_b_flag (tlb))
cache_t = MAIN_D_CACHE ();
else
cache_t = MINI_D_CACHE ();
cache = mmu_cache_alloc (state, cache_t, va, pa);
*data = cache->data[va_cache_index (va, cache_t)];
}
else {
//*data = mem_read_word(state, pa);
if (datatype == ARM_BYTE_TYPE)
//*data = mem_read_byte (state, pa | (real_va & 3));
bus_read(8, pa | (real_va & 3), data);
else if (datatype == ARM_HALFWORD_TYPE)
//*data = mem_read_halfword (state, pa | (real_va & 2));
bus_read(16, pa | (real_va & 2), data);
else if (datatype == ARM_WORD_TYPE)
//*data = mem_read_word (state, pa);
bus_read(32, pa, data);
else {
printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype);
// skyeye_exit (-1);
}
return NO_FAULT;
}
datatrans:
if (datatype == ARM_HALFWORD_TYPE) {
temp = *data;
offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
*data = (temp >> offset) & 0xffff;
}
else if (datatype == ARM_BYTE_TYPE) {
temp = *data;
offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
*data = (temp >> offset & 0xffL);
}
end:
return NO_FAULT;
}
static fault_t
sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
{
return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
}
static fault_t
sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
{
return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
}
static fault_t
sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
{
return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
}
static fault_t
sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype)
{
tlb_entry_t *tlb;
cache_line_t *cache;
int b;
ARMword pa, real_va;
fault_t fault;
DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
va = mmu_pid_va_map (va);
real_va = va;
/*search instruction cache */
cache = mmu_cache_search (state, I_CACHE (), va);
if (cache) {
update_cache (state, va, data, datatype, cache, I_CACHE (),
real_va);
}
if (MMU_Disabled) {
//mem_write_word(state, va, data);
if (datatype == ARM_BYTE_TYPE)
//mem_write_byte (state, va, data);
bus_write(8, va, data);
else if (datatype == ARM_HALFWORD_TYPE)
//mem_write_halfword (state, va, data);
bus_write(16, va, data);
else if (datatype == ARM_WORD_TYPE)
//mem_write_word (state, va, data);
bus_write(32, va, data);
else {
printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype);
// skyeye_exit (-1);
}
return NO_FAULT;
}
/*align check */
//if ((va & (WORD_SIZE - 1)) && MMU_Aligned){
if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
} //else
va &= ~(WORD_SIZE - 1);
/*tlb translate */
fault = translate (state, va, D_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*tlb check access */
fault = check_access (state, va, tlb, 0);
if (fault) {
DEBUG_LOG(ARM11, "check_access\n");
return fault;
}
/*search main cache */
cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
if (cache) {
update_cache (state, va, data, datatype, cache,
MAIN_D_CACHE (), real_va);
}
else {
/*search mini cache */
cache = mmu_cache_search (state, MINI_D_CACHE (), va);
if (cache) {
update_cache (state, va, data, datatype, cache,
MINI_D_CACHE (), real_va);
}
}
if (!cache) {
b = tlb_b_flag (tlb);
pa = tlb_va_to_pa (tlb, va);
if (b) {
if (MMU_WBEnabled) {
if (datatype == ARM_WORD_TYPE)
mmu_wb_write_bytes (state, WB (), pa,
(ARMbyte*)&data, 4);
else if (datatype == ARM_HALFWORD_TYPE)
mmu_wb_write_bytes (state, WB (),
(pa |
(real_va & 2)),
(ARMbyte*)&data, 2);
else if (datatype == ARM_BYTE_TYPE)
mmu_wb_write_bytes (state, WB (),
(pa |
(real_va & 3)),
(ARMbyte*)&data, 1);
}
else {
if (datatype == ARM_WORD_TYPE)
//mem_write_word (state, pa, data);
bus_write(32, pa, data);
else if (datatype == ARM_HALFWORD_TYPE)
/*
mem_write_halfword (state,
(pa |
(real_va & 2)),
data);
*/
bus_write(16, pa | (real_va & 2), data);
else if (datatype == ARM_BYTE_TYPE)
/*
mem_write_byte (state,
(pa | (real_va & 3)),
data);
*/
bus_write(8, pa | (real_va & 3), data);
}
}
else {
mmu_wb_drain_all (state, WB ());
if (datatype == ARM_WORD_TYPE)
//mem_write_word (state, pa, data);
bus_write(32, pa, data);
else if (datatype == ARM_HALFWORD_TYPE)
/*
mem_write_halfword (state,
(pa | (real_va & 2)),
data);
*/
bus_write(16, pa | (real_va & 2), data);
else if (datatype == ARM_BYTE_TYPE)
/*
mem_write_byte (state, (pa | (real_va & 3)),
data);
*/
bus_write(8, pa | (real_va & 3), data);
}
}
return NO_FAULT;
}
static fault_t
update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype,
cache_line_t * cache, cache_s * cache_t, ARMword real_va)
{
ARMword temp, offset;
ARMword index = va_cache_index (va, cache_t);
//cache->data[index] = data;
if (datatype == ARM_WORD_TYPE)
cache->data[index] = data;
else if (datatype == ARM_HALFWORD_TYPE) {
temp = cache->data[index];
offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */
cache->data[index] =
(temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
offset);
}
else if (datatype == ARM_BYTE_TYPE) {
temp = cache->data[index];
offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */
cache->data[index] =
(temp & ~(0xffL << offset)) | ((data & 0xffL) <<
offset);
}
if (index < (cache_t->width >> (WORD_SHT + 1)))
cache->tag |= TAG_FIRST_HALF_DIRTY;
else
cache->tag |= TAG_LAST_HALF_DIRTY;
return NO_FAULT;
}
ARMword
sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
ARMword data;
switch (creg) {
case MMU_ID:
// printf("mmu_mrc read ID ");
data = 0x41007100; /* v3 */
data = state->cpu->cpu_val;
break;
case MMU_CONTROL:
// printf("mmu_mrc read CONTROL");
data = state->mmu.control;
break;
case MMU_TRANSLATION_TABLE_BASE:
// printf("mmu_mrc read TTB ");
data = state->mmu.translation_table_base;
break;
case MMU_DOMAIN_ACCESS_CONTROL:
// printf("mmu_mrc read DACR ");
data = state->mmu.domain_access_control;
break;
case MMU_FAULT_STATUS:
// printf("mmu_mrc read FSR ");
data = state->mmu.fault_status;
break;
case MMU_FAULT_ADDRESS:
// printf("mmu_mrc read FAR ");
data = state->mmu.fault_address;
break;
case MMU_PID:
data = state->mmu.process_id;
default:
printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
data = 0;
break;
}
// printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]);
*value = data;
return data;
}
void
sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
{
int CRm, OPC_2;
CRm = BITS (0, 3);
OPC_2 = BITS (5, 7);
if (OPC_2 == 0 && CRm == 7) {
mmu_cache_invalidate_all (state, I_CACHE ());
mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
mmu_cache_invalidate_all (state, MINI_D_CACHE ());
return;
}
if (OPC_2 == 0 && CRm == 5) {
mmu_cache_invalidate_all (state, I_CACHE ());
return;
}
if (OPC_2 == 0 && CRm == 6) {
mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
mmu_cache_invalidate_all (state, MINI_D_CACHE ());
return;
}
if (OPC_2 == 1 && CRm == 6) {
mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
mmu_cache_invalidate (state, MINI_D_CACHE (), value);
return;
}
if (OPC_2 == 1 && CRm == 0xa) {
mmu_cache_clean (state, MAIN_D_CACHE (), value);
mmu_cache_clean (state, MINI_D_CACHE (), value);
return;
}
if (OPC_2 == 4 && CRm == 0xa) {
mmu_wb_drain_all (state, WB ());
return;
}
ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}
static void
sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value)
{
int CRm, OPC_2;
CRm = BITS (0, 3);
OPC_2 = BITS (5, 7);
if (OPC_2 == 0 && CRm == 0x7) {
mmu_tlb_invalidate_all (state, I_TLB ());
mmu_tlb_invalidate_all (state, D_TLB ());
return;
}
if (OPC_2 == 0 && CRm == 0x5) {
mmu_tlb_invalidate_all (state, I_TLB ());
return;
}
if (OPC_2 == 0 && CRm == 0x6) {
mmu_tlb_invalidate_all (state, D_TLB ());
return;
}
if (OPC_2 == 1 && CRm == 0x6) {
mmu_tlb_invalidate_entry (state, D_TLB (), value);
return;
}
ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}
static void
sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value)
{
int CRm, OPC_2;
CRm = BITS (0, 3);
OPC_2 = BITS (5, 7);
if (OPC_2 == 0x0 && CRm == 0x0) {
mmu_rb_invalidate_all (RB ());
return;
}
if (OPC_2 == 0x2) {
int idx = CRm & 0x3;
int type = ((CRm >> 2) & 0x3) + 1;
if ((idx < 4) && (type < 4))
mmu_rb_load (state, RB (), idx, type, value);
return;
}
if ((OPC_2 == 1) && (CRm < 4)) {
mmu_rb_invalidate_entry (RB (), CRm);
return;
}
ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}
static ARMword
sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) {
switch (creg) {
case MMU_CONTROL:
// printf("mmu_mcr wrote CONTROL ");
state->mmu.control = (value | 0x70) & 0xFFFD;
break;
case MMU_TRANSLATION_TABLE_BASE:
// printf("mmu_mcr wrote TTB ");
state->mmu.translation_table_base =
value & 0xFFFFC000;
break;
case MMU_DOMAIN_ACCESS_CONTROL:
// printf("mmu_mcr wrote DACR ");
state->mmu.domain_access_control = value;
break;
case MMU_FAULT_STATUS:
state->mmu.fault_status = value & 0xFF;
break;
case MMU_FAULT_ADDRESS:
state->mmu.fault_address = value;
break;
case MMU_CACHE_OPS:
sa_mmu_cache_ops (state, instr, value);
break;
case MMU_TLB_OPS:
sa_mmu_tlb_ops (state, instr, value);
break;
case MMU_SA_RB_OPS:
sa_mmu_rb_ops (state, instr, value);
break;
case MMU_SA_DEBUG:
break;
case MMU_SA_CP15_R15:
break;
case MMU_PID:
//2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu
state->mmu.process_id = value & 0x7e000000;
break;
default:
printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
break;
}
}
return 0;
}
//teawater add for arm2x86 2005.06.24-------------------------------------------
static int
sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
{
fault_t fault;
tlb_entry_t *tlb;
virt_addr = mmu_pid_va_map (virt_addr);
if (MMU_Enabled) {
/*align check */
if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
DEBUG_LOG(ARM11, "align\n");
return ALIGNMENT_FAULT;
}
else
virt_addr &= ~(WORD_SIZE - 1);
/*translate tlb */
fault = translate (state, virt_addr, I_TLB (), &tlb);
if (fault) {
DEBUG_LOG(ARM11, "translate\n");
return fault;
}
/*check access */
fault = check_access (state, virt_addr, tlb, 1);
if (fault) {
DEBUG_LOG(ARM11, "check_fault\n");
return fault;
}
}
if (MMU_Disabled) {
*phys_addr = virt_addr;
}
else {
*phys_addr = tlb_va_to_pa (tlb, virt_addr);
}
return (0);
}
//AJ2D--------------------------------------------------------------------------
/*sa mmu_ops_t*/
mmu_ops_t sa_mmu_ops = {
sa_mmu_init,
sa_mmu_exit,
sa_mmu_read_byte,
sa_mmu_write_byte,
sa_mmu_read_halfword,
sa_mmu_write_halfword,
sa_mmu_read_word,
sa_mmu_write_word,
sa_mmu_load_instr,
sa_mmu_mcr,
sa_mmu_mrc,
//teawater add for arm2x86 2005.06.24-------------------------------------------
sa_mmu_v2p_dbct,
//AJ2D--------------------------------------------------------------------------
};

View file

@ -1,58 +0,0 @@
/*
sa_mmu.h - StrongARM Memory Management Unit emulation.
ARMulator extensions for SkyEye.
<lyhost@263.net>
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 _SA_MMU_H_
#define _SA_MMU_H_
/**
* The interface of read data from bus
*/
int bus_read(short size, int addr, uint32_t * value);
/**
* The interface of write data from bus
*/
int bus_write(short size, int addr, uint32_t value);
typedef struct sa_mmu_s
{
tlb_s i_tlb;
cache_s i_cache;
tlb_s d_tlb;
cache_s main_d_cache;
cache_s mini_d_cache;
rb_s rb_t;
wb_s wb_t;
} sa_mmu_t;
#define I_TLB() (&state->mmu.u.sa_mmu.i_tlb)
#define I_CACHE() (&state->mmu.u.sa_mmu.i_cache)
#define D_TLB() (&state->mmu.u.sa_mmu.d_tlb)
#define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache)
#define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache)
#define WB() (&state->mmu.u.sa_mmu.wb_t)
#define RB() (&state->mmu.u.sa_mmu.rb_t)
extern mmu_ops_t sa_mmu_ops;
#endif /*_SA_MMU_H_*/

View file

@ -1,307 +0,0 @@
#include <assert.h>
#include "core/arm/interpreter/armdefs.h"
ARMword tlb_masks[] = {
0x00000000, /* TLB_INVALID */
0xFFFFF000, /* TLB_SMALLPAGE */
0xFFFF0000, /* TLB_LARGEPAGE */
0xFFF00000, /* TLB_SECTION */
0xFFFFF000, /*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */
0xFFFFFC00 /* TLB_TINYPAGE */
};
/* This function encodes table 8-2 Interpreting AP bits,
returning non-zero if access is allowed. */
static int
check_perms (ARMul_State * state, int ap, int read)
{
int s, r, user;
s = state->mmu.control & CONTROL_SYSTEM;
r = state->mmu.control & CONTROL_ROM;
//chy 2006-02-15 , should consider system mode, don't conside 26bit mode
user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
switch (ap) {
case 0:
return read && ((s && !user) || r);
case 1:
return !user;
case 2:
return read || !user;
case 3:
return 1;
}
return 0;
}
fault_t
check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
int read)
{
int access;
state->mmu.last_domain = tlb->domain;
access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
if ((access == 0) || (access == 2)) {
/* It's unclear from the documentation whether this
should always raise a section domain fault, or if
it should be a page domain fault in the case of an
L1 that describes a page table. In the ARM710T
datasheets, "Figure 8-9: Sequence for checking faults"
seems to indicate the former, while "Table 8-4: Priority
encoding of fault status" gives a value for FS[3210] in
the event of a domain fault for a page. Hmm. */
return SECTION_DOMAIN_FAULT;
}
if (access == 1) {
/* client access - check perms */
int subpage, ap;
switch (tlb->mapping) {
/*ks 2004-05-09
* only for XScale
* Extend Small Page(ESP) Format
* 31-12 bits the base addr of ESP
* 11-10 bits SBZ
* 9-6 bits TEX
* 5-4 bits AP
* 3 bit C
* 2 bit B
* 1-0 bits 11
* */
case TLB_ESMALLPAGE: //xj
subpage = 0;
//printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr );
break;
case TLB_TINYPAGE:
subpage = 0;
//printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr );
break;
case TLB_SMALLPAGE:
subpage = (virt_addr >> 10) & 3;
break;
case TLB_LARGEPAGE:
subpage = (virt_addr >> 14) & 3;
break;
case TLB_SECTION:
subpage = 3;
break;
default:
assert (0);
subpage = 0; /* cleans a warning */
}
ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
if (!check_perms (state, ap, read)) {
if (tlb->mapping == TLB_SECTION) {
return SECTION_PERMISSION_FAULT;
}
else {
return SUBPAGE_PERMISSION_FAULT;
}
}
}
else { /* access == 3 */
/* manager access - don't check perms */
}
return NO_FAULT;
}
fault_t
translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
tlb_entry_t ** tlb)
{
*tlb = mmu_tlb_search (state, tlb_t, virt_addr);
if (!*tlb) {
/* walk the translation tables */
ARMword l1addr, l1desc;
tlb_entry_t entry;
l1addr = state->mmu.translation_table_base & 0xFFFFC000;
l1addr = (l1addr | (virt_addr >> 18)) & ~3;
//l1desc = mem_read_word (state, l1addr);
bus_read(32, l1addr, &l1desc);
switch (l1desc & 3) {
case 0:
/*
* according to Figure 3-9 Sequence for checking faults in arm manual,
* section translation fault should be returned here.
*/
{
return SECTION_TRANSLATION_FAULT;
}
case 3:
/* fine page table */
// dcl 2006-01-08
{
ARMword l2addr, l2desc;
l2addr = l1desc & 0xFFFFF000;
l2addr = (l2addr |
((virt_addr & 0x000FFC00) >> 8)) &
~3;
//l2desc = mem_read_word (state, l2addr);
bus_read(32, l2addr, &l2desc);
entry.virt_addr = virt_addr;
entry.phys_addr = l2desc;
entry.perms = l2desc & 0x00000FFC;
entry.domain = (l1desc >> 5) & 0x0000000F;
switch (l2desc & 3) {
case 0:
state->mmu.last_domain = entry.domain;
return PAGE_TRANSLATION_FAULT;
case 3:
entry.mapping = TLB_TINYPAGE;
break;
case 1:
// this is untested
entry.mapping = TLB_LARGEPAGE;
break;
case 2:
// this is untested
entry.mapping = TLB_SMALLPAGE;
break;
}
}
break;
case 1:
/* coarse page table */
{
ARMword l2addr, l2desc;
l2addr = l1desc & 0xFFFFFC00;
l2addr = (l2addr |
((virt_addr & 0x000FF000) >> 10)) &
~3;
//l2desc = mem_read_word (state, l2addr);
bus_read(32, l2addr, &l2desc);
entry.virt_addr = virt_addr;
entry.phys_addr = l2desc;
entry.perms = l2desc & 0x00000FFC;
entry.domain = (l1desc >> 5) & 0x0000000F;
//printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr);
//chy 2003-09-02 for xscale
switch (l2desc & 3) {
case 0:
state->mmu.last_domain = entry.domain;
return PAGE_TRANSLATION_FAULT;
case 3:
if (!state->is_XScale) {
state->mmu.last_domain =
entry.domain;
return PAGE_TRANSLATION_FAULT;
};
//ks 2004-05-09 xscale shold use Extend Small Page
//entry.mapping = TLB_SMALLPAGE;
entry.mapping = TLB_ESMALLPAGE; //xj
break;
case 1:
entry.mapping = TLB_LARGEPAGE;
break;
case 2:
entry.mapping = TLB_SMALLPAGE;
break;
}
}
break;
case 2:
/* section */
//printf("SKYEYE:WARNING: not implement section mapping incompletely\n");
//printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc);
//return SECTION_DOMAIN_FAULT;
//#if 0
entry.virt_addr = virt_addr;
entry.phys_addr = l1desc;
entry.perms = l1desc & 0x00000C0C;
entry.domain = (l1desc >> 5) & 0x0000000F;
entry.mapping = TLB_SECTION;
break;
//#endif
}
entry.virt_addr &= tlb_masks[entry.mapping];
entry.phys_addr &= tlb_masks[entry.mapping];
/* place entry in the tlb */
*tlb = &tlb_t->entrys[tlb_t->cycle];
tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num;
**tlb = entry;
}
state->mmu.last_domain = (*tlb)->domain;
return NO_FAULT;
}
int
mmu_tlb_init (tlb_s * tlb_t, int num)
{
tlb_entry_t *e;
int i;
e = (tlb_entry_t *) malloc (sizeof (*e) * num);
if (e == NULL) {
ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num);
goto tlb_malloc_error;
}
tlb_t->entrys = e;
for (i = 0; i < num; i++, e++)
e->mapping = TLB_INVALID;
tlb_t->cycle = 0;
tlb_t->num = num;
return 0;
tlb_malloc_error:
return -1;
}
void
mmu_tlb_exit (tlb_s * tlb_t)
{
free (tlb_t->entrys);
};
void
mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t)
{
int entry;
for (entry = 0; entry < tlb_t->num; entry++) {
tlb_t->entrys[entry].mapping = TLB_INVALID;
}
tlb_t->cycle = 0;
}
void
mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr)
{
tlb_entry_t *tlb;
tlb = mmu_tlb_search (state, tlb_t, addr);
if (tlb) {
tlb->mapping = TLB_INVALID;
}
}
tlb_entry_t *
mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr)
{
int entry;
for (entry = 0; entry < tlb_t->num; entry++) {
tlb_entry_t *tlb;
ARMword mask;
tlb = &(tlb_t->entrys[entry]);
if (tlb->mapping == TLB_INVALID) {
continue;
}
mask = tlb_masks[tlb->mapping];
if ((virt_addr & mask) == (tlb->virt_addr & mask)) {
return tlb;
}
}
return NULL;
}

View file

@ -1,87 +0,0 @@
#ifndef _MMU_TLB_H_
#define _MMU_TLB_H_
typedef enum tlb_mapping_t
{
TLB_INVALID = 0,
TLB_SMALLPAGE = 1,
TLB_LARGEPAGE = 2,
TLB_SECTION = 3,
TLB_ESMALLPAGE = 4,
TLB_TINYPAGE = 5
} tlb_mapping_t;
extern ARMword tlb_masks[];
/* Permissions bits in a TLB entry:
*
* 31 12 11 10 9 8 7 6 5 4 3 2 1 0
* +-------------+-----+-----+-----+-----+---+---+-------+
* Page:| | ap3 | ap2 | ap1 | ap0 | C | B | |
* +-------------+-----+-----+-----+-----+---+---+-------+
*
* 31 12 11 10 9 4 3 2 1 0
* +-------------+-----+-----------------+---+---+-------+
* Section: | | AP | | C | B | |
* +-------------+-----+-----------------+---+---+-------+
*/
/*
section:
section base address [31:20]
AP - table 8-2, page 8-8
domain
C,B
page:
page base address [31:16] or [31:12]
ap[3:0]
domain (from L1)
C,B
*/
typedef struct tlb_entry_t
{
ARMword virt_addr;
ARMword phys_addr;
ARMword perms;
ARMword domain;
tlb_mapping_t mapping;
} tlb_entry_t;
typedef struct tlb_s
{
int num; /*num of tlb entry */
int cycle; /*current tlb cycle */
tlb_entry_t *entrys;
} tlb_s;
#define tlb_c_flag(tlb) \
((tlb)->perms & 0x8)
#define tlb_b_flag(tlb) \
((tlb)->perms & 0x4)
#define tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping]))
fault_t
check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
int read);
fault_t
translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
tlb_entry_t ** tlb);
int mmu_tlb_init (tlb_s * tlb_t, int num);
void mmu_tlb_exit (tlb_s * tlb_t);
void mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t);
void
mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr);
tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t,
ARMword virt_addr);
#endif /*_MMU_TLB_H_*/

View file

@ -1,149 +0,0 @@
#include "core/arm/interpreter/armdefs.h"
/* wb_init
* @wb_t :wb_t to init
* @num :num of entrys
* @nb :num of byte of each entry
*
* $ -1:error
* 0:ok
* */
int
mmu_wb_init (wb_s * wb_t, int num, int nb)
{
int i;
wb_entry_t *entrys, *wb;
entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num);
if (entrys == NULL) {
ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num);
goto entrys_malloc_error;
}
for (wb = entrys, i = 0; i < num; i++, wb++) {
/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */
//wb->data = (ARMword *)malloc(sizeof(ARMword) * nb);
wb->data = (ARMbyte *) malloc (nb);
if (wb->data == NULL) {
ERROR_LOG(ARM11, "malloc size of %d\n", nb);
goto data_malloc_error;
}
};
wb_t->first = wb_t->last = wb_t->used = 0;
wb_t->num = num;
wb_t->nb = nb;
wb_t->entrys = entrys;
return 0;
data_malloc_error:
while (--i >= 0)
free (entrys[i].data);
free (entrys);
entrys_malloc_error:
return -1;
};
/* wb_exit
* @wb_t :wb_t to exit
* */
void
mmu_wb_exit (wb_s * wb_t)
{
int i;
wb_entry_t *wb;
wb = wb_t->entrys;
for (i = 0; i < wb_t->num; i++, wb++) {
free (wb->data);
}
free (wb_t->entrys);
};
/* wb_write_words :put words in Write Buffer
* @state: ARMul_State
* @wb_t: write buffer
* @pa: physical address
* @data: data ptr
* @n number of word to write
*
* Note: write buffer merge is not implemented, can be done late
* */
void
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
ARMbyte * data, int n)
{
int i;
wb_entry_t *wb;
while (n) {
if (wb_t->num == wb_t->used) {
/*clean the last wb entry */
ARMword t;
wb = &wb_t->entrys[wb_t->last];
t = wb->pa;
for (i = 0; i < wb->nb; i++) {
//mem_write_byte (state, t, wb->data[i]);
bus_write(8, t, wb->data[i]);
//t += WORD_SIZE;
t++;
}
wb_t->last++;
if (wb_t->last == wb_t->num)
wb_t->last = 0;
wb_t->used--;
}
wb = &wb_t->entrys[wb_t->first];
i = (n < wb_t->nb) ? n : wb_t->nb;
wb->pa = pa;
//pa += i << WORD_SHT;
pa += i;
wb->nb = i;
//memcpy(wb->data, data, i << WORD_SHT);
memcpy (wb->data, data, i);
data += i;
n -= i;
wb_t->first++;
if (wb_t->first == wb_t->num)
wb_t->first = 0;
wb_t->used++;
};
//teawater add for set_dirty fflash cache function 2005.07.18-------------------
#ifdef DBCT
if (!skyeye_config.no_dbct) {
tb_setdirty (state, pa, NULL);
}
#endif
//AJ2D--------------------------------------------------------------------------
}
/* wb_drain_all
* @wb_t wb_t to drain
* */
void
mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t)
{
ARMword pa;
wb_entry_t *wb;
int i;
while (wb_t->used) {
wb = &wb_t->entrys[wb_t->last];
pa = wb->pa;
for (i = 0; i < wb->nb; i++) {
//mem_write_byte (state, pa, wb->data[i]);
bus_write(8, pa, wb->data[i]);
//pa += WORD_SIZE;
pa++;
}
wb_t->last++;
if (wb_t->last == wb_t->num)
wb_t->last = 0;
wb_t->used--;
};
}

View file

@ -1,63 +0,0 @@
#ifndef _MMU_WB_H_
#define _MMU_WB_H_
typedef struct wb_entry_s
{
ARMword pa; //phy_addr
ARMbyte *data; //data
int nb; //number byte to write
} wb_entry_t;
typedef struct wb_s
{
int num; //number of wb_entry
int nb; //number of byte of each entry
int first; //
int last; //
int used; //
wb_entry_t *entrys;
} wb_s;
typedef struct wb_desc_s
{
int num;
int nb;
} wb_desc_t;
/* wb_init
* @wb_t :wb_t to init
* @num :num of entrys
* @nw :num of word of each entry
*
* $ -1:error
* 0:ok
* */
int mmu_wb_init (wb_s * wb_t, int num, int nb);
/* wb_exit
* @wb_t :wb_t to exit
* */
void mmu_wb_exit (wb_s * wb);
/* wb_write_bytes :put bytess in Write Buffer
* @state: ARMul_State
* @wb_t: write buffer
* @pa: physical address
* @data: data ptr
* @n number of byte to write
*
* Note: write buffer merge is not implemented, can be done late
* */
void
mmu_wb_write_bytess (ARMul_State * state, wb_s * wb_t, ARMword pa,
ARMbyte * data, int n);
/* wb_drain_all
* @wb_t wb_t to drain
* */
void mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t);
#endif /*_MMU_WB_H_*/

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,7 @@
instruction into its corresponding ARM instruction, and using the
existing ARM simulator. */
#include "skyeye_defs.h"
#include "core/arm/skyeye_common/skyeye_defs.h"
#ifndef MODET /* required for the Thumb instruction support */
#if 1
@ -29,9 +29,9 @@ existing ARM simulator. */
#endif
#endif
#include "armdefs.h"
#include "armemu.h"
#include "armos.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/armos.h"
/* Decode a 16bit Thumb instruction. The instruction is in the low

View file

@ -99,5 +99,7 @@ enum arm_regno{
MAX_REG_NUM,
};
#define CP15(idx) (idx - CP15_BASE)
#define VFP_OFFSET(x) (x - VFP_BASE)
#endif

View file

@ -20,16 +20,13 @@
#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 "common/thread.h"
#include "core/arm/skyeye_common/armdefs.h"
typedef struct ARM_CPU_State_s {
ARMul_State * core;

View file

@ -31,7 +31,7 @@
#include "arm_regformat.h"
#include "common/platform.h"
#include "skyeye_defs.h"
#include "core/arm/skyeye_common/skyeye_defs.h"
//AJ2D--------------------------------------------------------------------------
@ -130,7 +130,7 @@ typedef unsigned long long uint64_t;
#endif
*/
#include "armmmu.h"
#include "core/arm/skyeye_common/armmmu.h"
//#include "lcd/skyeye_lcd.h"
@ -367,7 +367,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
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 */

View file

@ -18,7 +18,7 @@
#define __ARMEMU_H__
#include "armdefs.h"
#include "core/arm/skyeye_common/armdefs.h"
//#include "skyeye.h"
//extern ARMword isize;

View file

@ -134,121 +134,4 @@ typedef enum fault_t
} 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 "core/arm/interpreter/mmu/tlb.h"
#include "core/arm/interpreter/mmu/rb.h"
#include "core/arm/interpreter/mmu/wb.h"
#include "core/arm/interpreter/mmu/cache.h"
/*special process mmu.h*/
#include "core/arm/interpreter/mmu/sa_mmu.h"
//#include "core/arm/interpreter/mmu/arm7100_mmu.h"
//#include "core/arm/interpreter/mmu/arm920t_mmu.h"
//#include "core/arm/interpreter/mmu/arm926ejs_mmu.h"
#include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h"
//#include "core/arm/interpreter/mmu/cortex_a9_mmu.h"
typedef struct mmu_state_t
{
ARMword control;
ARMword translation_table_base;
/* dyf 201-08-11 for arm1176 */
ARMword auxiliary_control;
ARMword coprocessor_access_control;
ARMword translation_table_base0;
ARMword translation_table_base1;
ARMword translation_table_ctrl;
/* arm1176 end */
ARMword domain_access_control;
ARMword fault_status;
ARMword fault_statusi; /* prefetch fault status */
ARMword fault_address;
ARMword last_domain;
ARMword process_id;
ARMword context_id;
ARMword thread_uro_id;
ARMword cache_locked_down;
ARMword tlb_locked_down;
//chy 2003-08-24 for xscale
ARMword cache_type; // 0
ARMword aux_control; // 1
ARMword copro_access; // 15
mmu_ops_t ops;
union
{
sa_mmu_t sa_mmu;
//arm7100_mmu_t arm7100_mmu;
//arm920t_mmu_t arm920t_mmu;
//arm926ejs_mmu_t arm926ejs_mmu;
} u;
} mmu_state_t;
int mmu_init (ARMul_State * state);
int mmu_reset (ARMul_State * state);
void mmu_exit (ARMul_State * state);
fault_t mmu_read_word (ARMul_State * state, ARMword virt_addr,
ARMword * data);
fault_t mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t mmu_load_instr (ARMul_State * state, ARMword virt_addr,
ARMword * instr);
ARMword mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value);
void mmu_mcr (ARMul_State * state, ARMword instr, ARMword value);
/*ywc 20050416*/
int mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
ARMword * phys_addr);
fault_t
mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data);
fault_t
mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t
mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data);
fault_t
mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data);
#endif /* _ARMMMU_H_ */

View file

@ -15,14 +15,7 @@
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;
#include <stdint.h>
#if FAST_MEMORY
/* in user mode, mmap_base will be on initial brk,

View file

@ -108,4 +108,6 @@ typedef struct generic_arch_s
align_t alignment;
} generic_arch_t;
typedef u32 addr_t;
#endif

View file

@ -0,0 +1,55 @@
/*
skyeye_types.h - some data types definition for skyeye debugger
Copyright (C) 2003 Skyeye Develop Group
for help please send mail to <skyeye-developer@lists.sf.linuxforum.net>
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
*/
/*
* 12/16/2006 Michael.Kang <blackfin.kang@gmail.com>
*/
#ifndef __SKYEYE_TYPES_H
#define __SKYEYE_TYPES_H
#include <stdint.h>
/*default machine word length */
#ifndef __BEOS__
/* To avoid the type conflict with the qemu */
#ifndef QEMU
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef int8_t sint8;
typedef int16_t sint16;
typedef int32_t sint32;
typedef int64_t sint64;
#endif
typedef uint32_t address_t;
typedef uint32_t uinteger_t;
typedef int32_t integer_t;
typedef uint32_t physical_address_t;
typedef uint32_t generic_address_t;
#endif
#endif

View file

@ -25,8 +25,8 @@
#include "common/common.h"
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/interpreter/vfp/vfp.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
@ -62,7 +62,7 @@ VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
if (CoProc == 10 || CoProc == 11)
{
#define VFP_MRC_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRC_TRANS
}
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
@ -88,7 +88,7 @@ VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
if (CoProc == 10 || CoProc == 11)
{
#define VFP_MCR_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCR_TRANS
}
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
@ -110,7 +110,7 @@ VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, AR
if (CoProc == 10 || CoProc == 11)
{
#define VFP_MRRC_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRRC_TRANS
}
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
@ -136,7 +136,7 @@ VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMw
if (CoProc == 11 || CoProc == 10)
{
#define VFP_MCRR_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCRR_TRANS
}
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
@ -179,7 +179,7 @@ VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
#endif
#define VFP_STC_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_STC_TRANS
}
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
@ -210,7 +210,7 @@ VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
if (CoProc == 10 || CoProc == 11)
{
#define VFP_LDC_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_LDC_TRANS
}
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
@ -237,7 +237,7 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
if (CoProc == 10 || CoProc == 11)
{
#define VFP_CDP_TRANS
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_CDP_TRANS
int exceptions = 0;
@ -257,21 +257,21 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
/* ----------- MRC ------------ */
#define VFP_MRC_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRC_IMPL
#define VFP_MRRC_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRRC_IMPL
/* ----------- MCR ------------ */
#define VFP_MCR_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCR_IMPL
#define VFP_MCRR_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCRR_IMPL
/* Memory operation are not inlined, as old Interpreter and Fast interpreter
@ -283,19 +283,19 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
/* ----------- STC ------------ */
#define VFP_STC_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_STC_IMPL
/* ----------- LDC ------------ */
#define VFP_LDC_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_LDC_IMPL
/* ----------- CDP ------------ */
#define VFP_CDP_IMPL
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_CDP_IMPL
/* Miscellaneous functions */

View file

@ -25,7 +25,7 @@
#define vfpdebug //printf
#include "core/arm/interpreter/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
unsigned VFPInit (ARMul_State *state);
unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);

View file

@ -38,7 +38,7 @@
#include <stdint.h>
#include <stdio.h>
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/skyeye_common/armdefs.h"
#define u16 uint16_t
#define u32 uint32_t

View file

@ -51,9 +51,9 @@
* ===========================================================================
*/
#include "core/arm/interpreter/vfp/vfp.h"
#include "core/arm/interpreter/vfp/vfp_helper.h"
#include "core/arm/interpreter/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
static struct vfp_double vfp_double_default_qnan = {
//.exponent = 2047,

View file

@ -3709,7 +3709,7 @@ VFPLABEL_INST:
{
fault = check_address_validity(cpu, addr, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d, cpu->ExtReg[inst_cream->d]);
}
@ -3719,13 +3719,13 @@ VFPLABEL_INST:
if (fault) goto MMU_EXCEPTION;
/* Check endianness */
fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d*2], 32);
fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d*2], 32);
if (fault) goto MMU_EXCEPTION;
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[inst_cream->d*2+1], 32);
fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[inst_cream->d*2+1], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, inst_cream->d*2+1, inst_cream->d*2, cpu->ExtReg[inst_cream->d*2+1], cpu->ExtReg[inst_cream->d*2]);
}
@ -3926,7 +3926,7 @@ VFPLABEL_INST:
{
fault = check_address_validity(cpu, addr, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
addr += 4;
@ -3936,12 +3936,12 @@ VFPLABEL_INST:
/* Careful of endianness, little by default */
fault = check_address_validity(cpu, addr, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
if (fault) goto MMU_EXCEPTION;
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
addr += 8;
@ -4048,7 +4048,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
{
if (single)
{
//fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
//fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
#if 0
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
bb = cpu->dyncom_engine->bb;
@ -4166,7 +4166,7 @@ VFPLABEL_INST: /* encoding 1 */
fault = check_address_validity(cpu, addr, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
addr += 4;
@ -4177,13 +4177,13 @@ VFPLABEL_INST: /* encoding 1 */
fault = check_address_validity(cpu, addr, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
if (fault) goto MMU_EXCEPTION;
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
addr += 8;
@ -4304,7 +4304,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
if (single)
{
//fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
//fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
/* if R(i) is R15? */
#if 0
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
@ -4321,7 +4321,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
else
{
//fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
//fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
#if 0
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
bb = cpu->dyncom_engine->bb;
@ -4332,7 +4332,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
bb = cpu->dyncom_engine->bb;
//if (fault) goto MMU_EXCEPTION;
//fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
//fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
#if 0
phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
bb = cpu->dyncom_engine->bb;
@ -4431,7 +4431,7 @@ VFPLABEL_INST:
fault = check_address_validity(cpu, addr, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr, phys_addr, value1, 32);
fault = interpreter_read_memory(addr, phys_addr, value1, 32);
if (fault) goto MMU_EXCEPTION;
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, value1, addr);
cpu->ExtReg[inst_cream->d+i] = value1;
@ -4443,13 +4443,13 @@ VFPLABEL_INST:
fault = check_address_validity(cpu, addr, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr, phys_addr, value1, 32);
fault = interpreter_read_memory(addr, phys_addr, value1, 32);
if (fault) goto MMU_EXCEPTION;
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr + 4, phys_addr, value2, 32);
fault = interpreter_read_memory(addr + 4, phys_addr, value2, 32);
if (fault) goto MMU_EXCEPTION;
DBG("\ts[%d-%d] <= [%x-%x] addr[%x-%x]\n", (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, value2, value1, addr+4, addr);
cpu->ExtReg[(inst_cream->d+i)*2] = value1;
@ -4682,7 +4682,7 @@ VFPLABEL_INST:
{
fault = check_address_validity(cpu, addr, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
fault = interpreter_read_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d, cpu->ExtReg[inst_cream->d], addr);
}
@ -4691,12 +4691,12 @@ VFPLABEL_INST:
unsigned int word1, word2;
fault = check_address_validity(cpu, addr, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr, phys_addr, word1, 32);
fault = interpreter_read_memory(addr, phys_addr, word1, 32);
if (fault) goto MMU_EXCEPTION;
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr + 4, phys_addr, word2, 32);
fault = interpreter_read_memory(addr + 4, phys_addr, word2, 32);
if (fault) goto MMU_EXCEPTION;
/* Check endianness */
cpu->ExtReg[inst_cream->d*2] = word1;
@ -4923,7 +4923,7 @@ VFPLABEL_INST:
{
fault = check_address_validity(cpu, addr, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
fault = interpreter_read_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, cpu->ExtReg[inst_cream->d+i], addr);
addr += 4;
@ -4933,12 +4933,12 @@ VFPLABEL_INST:
/* Careful of endianness, little by default */
fault = check_address_validity(cpu, addr, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
fault = interpreter_read_memory(addr, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2], 32);
if (fault) goto MMU_EXCEPTION;
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
if (fault) goto MMU_EXCEPTION;
fault = interpreter_read_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
fault = interpreter_read_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
if (fault) goto MMU_EXCEPTION;
DBG("\ts[%d-%d] <= [%x-%x] addr[%x-%x]\n", (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2], addr+4, addr);
addr += 8;
@ -5058,7 +5058,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
if (single)
{
//fault = interpreter_write_memory(core, addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
//fault = interpreter_write_memory(addr, phys_addr, cpu->ExtReg[inst_cream->d+i], 32);
/* if R(i) is R15? */
#if 0
phys_addr = get_phys_addr(cpu, bb, Addr, 1);
@ -5095,7 +5095,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
//fault = interpreter_write_memory(core, addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
//fault = interpreter_write_memory(addr + 4, phys_addr, cpu->ExtReg[(inst_cream->d+i)*2 + 1], 32);
//DBG("\taddr[%x-%x] <= s[%d-%d]=[%x-%x]\n", addr+4, addr, (inst_cream->d+i)*2+1, (inst_cream->d+i)*2, cpu->ExtReg[(inst_cream->d+i)*2+1], cpu->ExtReg[(inst_cream->d+i)*2]);
//addr += 8;
Addr = ADD(Addr, CONST(8));

View file

@ -51,9 +51,9 @@
* ===========================================================================
*/
#include "core/arm/interpreter/vfp/vfp_helper.h"
#include "core/arm/interpreter/vfp/asm_vfp.h"
#include "core/arm/interpreter/vfp/vfp.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
static struct vfp_single vfp_single_default_qnan = {
//.exponent = 255,

View file

@ -5,7 +5,7 @@
#pragma once
#include "core/arm/arm_interface.h"
#include "core/arm/interpreter/armdefs.h"
#include "core/arm/skyeye_common/armdefs.h"
////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -1,20 +0,0 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
namespace HLE {
/// Coprocessor operations
enum CoprocessorOperation {
DATA_SYNCHRONIZATION_BARRIER = 0xE0,
CALL_GET_THREAD_COMMAND_BUFFER = 0xE1,
};
/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
s32 CallMRC(u32 instruction);
} // namespace