mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2024-11-30 21:34:15 +01:00
Merge pull request #112 from bunnei/skyeye-dyncom-interpreter
SkyEye dyncom interpreter
This commit is contained in:
commit
4615c73d15
@ -9,7 +9,7 @@
|
|||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "common/break_points.h"
|
#include "common/break_points.h"
|
||||||
#include "common/symbols.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"
|
#include "core/arm/disassembler/arm_disasm.h"
|
||||||
|
|
||||||
DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {
|
DisassemblerModel::DisassemblerModel(QObject* parent) : QAbstractItemModel(parent), base_address(0), code_size(0), program_counter(0), selection(QModelIndex()) {
|
||||||
|
@ -1,27 +1,22 @@
|
|||||||
set(SRCS
|
set(SRCS
|
||||||
arm/disassembler/arm_disasm.cpp
|
arm/disassembler/arm_disasm.cpp
|
||||||
arm/disassembler/load_symbol_map.cpp
|
arm/disassembler/load_symbol_map.cpp
|
||||||
arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
|
arm/dyncom/arm_dyncom.cpp
|
||||||
arm/interpreter/mmu/cache.cpp
|
arm/dyncom/arm_dyncom_dec.cpp
|
||||||
arm/interpreter/mmu/maverick.cpp
|
arm/dyncom/arm_dyncom_interpreter.cpp
|
||||||
arm/interpreter/mmu/rb.cpp
|
arm/dyncom/arm_dyncom_run.cpp
|
||||||
arm/interpreter/mmu/sa_mmu.cpp
|
arm/dyncom/arm_dyncom_thumb.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/interpreter/arm_interpreter.cpp
|
arm/interpreter/arm_interpreter.cpp
|
||||||
arm/interpreter/armcopro.cpp
|
arm/interpreter/armcopro.cpp
|
||||||
arm/interpreter/armemu.cpp
|
arm/interpreter/armemu.cpp
|
||||||
arm/interpreter/arminit.cpp
|
arm/interpreter/arminit.cpp
|
||||||
arm/interpreter/armmmu.cpp
|
|
||||||
arm/interpreter/armos.cpp
|
|
||||||
arm/interpreter/armsupp.cpp
|
arm/interpreter/armsupp.cpp
|
||||||
arm/interpreter/armvirt.cpp
|
arm/interpreter/armvirt.cpp
|
||||||
arm/interpreter/thumbemu.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_romfs.cpp
|
||||||
file_sys/archive_sdmc.cpp
|
file_sys/archive_sdmc.cpp
|
||||||
file_sys/file_romfs.cpp
|
file_sys/file_romfs.cpp
|
||||||
@ -43,7 +38,6 @@ set(SRCS
|
|||||||
hle/service/service.cpp
|
hle/service/service.cpp
|
||||||
hle/service/srv.cpp
|
hle/service/srv.cpp
|
||||||
hle/config_mem.cpp
|
hle/config_mem.cpp
|
||||||
hle/coprocessor.cpp
|
|
||||||
hle/hle.cpp
|
hle/hle.cpp
|
||||||
hle/svc.cpp
|
hle/svc.cpp
|
||||||
hw/gpu.cpp
|
hw/gpu.cpp
|
||||||
@ -63,23 +57,23 @@ set(SRCS
|
|||||||
set(HEADERS
|
set(HEADERS
|
||||||
arm/disassembler/arm_disasm.h
|
arm/disassembler/arm_disasm.h
|
||||||
arm/disassembler/load_symbol_map.h
|
arm/disassembler/load_symbol_map.h
|
||||||
arm/interpreter/mmu/arm1176jzf_s_mmu.h
|
arm/dyncom/arm_dyncom.h
|
||||||
arm/interpreter/mmu/cache.h
|
arm/dyncom/arm_dyncom_dec.h
|
||||||
arm/interpreter/mmu/rb.h
|
arm/dyncom/arm_dyncom_interpreter.h
|
||||||
arm/interpreter/mmu/sa_mmu.h
|
arm/dyncom/arm_dyncom_run.h
|
||||||
arm/interpreter/mmu/tlb.h
|
arm/dyncom/arm_dyncom_thumb.h
|
||||||
arm/interpreter/mmu/wb.h
|
|
||||||
arm/interpreter/vfp/asm_vfp.h
|
|
||||||
arm/interpreter/vfp/vfp.h
|
|
||||||
arm/interpreter/vfp/vfp_helper.h
|
|
||||||
arm/interpreter/arm_interpreter.h
|
arm/interpreter/arm_interpreter.h
|
||||||
arm/interpreter/arm_regformat.h
|
arm/skyeye_common/arm_regformat.h
|
||||||
arm/interpreter/armcpu.h
|
arm/skyeye_common/armcpu.h
|
||||||
arm/interpreter/armdefs.h
|
arm/skyeye_common/armdefs.h
|
||||||
arm/interpreter/armemu.h
|
arm/skyeye_common/armemu.h
|
||||||
arm/interpreter/armmmu.h
|
arm/skyeye_common/armmmu.h
|
||||||
arm/interpreter/armos.h
|
arm/skyeye_common/armos.h
|
||||||
arm/interpreter/skyeye_defs.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
|
arm/arm_interface.h
|
||||||
file_sys/archive.h
|
file_sys/archive.h
|
||||||
file_sys/archive_romfs.h
|
file_sys/archive_romfs.h
|
||||||
@ -105,7 +99,6 @@ set(HEADERS
|
|||||||
hle/service/service.h
|
hle/service/service.h
|
||||||
hle/service/srv.h
|
hle/service/srv.h
|
||||||
hle/config_mem.h
|
hle/config_mem.h
|
||||||
hle/coprocessor.h
|
|
||||||
hle/function_wrappers.h
|
hle/function_wrappers.h
|
||||||
hle/hle.h
|
hle/hle.h
|
||||||
hle/svc.h
|
hle/svc.h
|
||||||
|
163
src/core/arm/dyncom/arm_dyncom.cpp
Normal file
163
src/core/arm/dyncom/arm_dyncom.cpp
Normal 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;
|
||||||
|
}
|
90
src/core/arm/dyncom/arm_dyncom.h
Normal file
90
src/core/arm/dyncom/arm_dyncom.h
Normal 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;
|
||||||
|
|
||||||
|
};
|
402
src/core/arm/dyncom/arm_dyncom_dec.cpp
Normal file
402
src/core/arm/dyncom/arm_dyncom_dec.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
155
src/core/arm/dyncom/arm_dyncom_dec.h
Normal file
155
src/core/arm/dyncom/arm_dyncom_dec.h
Normal 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
|
6563
src/core/arm/dyncom/arm_dyncom_interpreter.cpp
Normal file
6563
src/core/arm/dyncom/arm_dyncom_interpreter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
7
src/core/arm/dyncom/arm_dyncom_interpreter.h
Normal file
7
src/core/arm/dyncom/arm_dyncom_interpreter.h
Normal 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);
|
120
src/core/arm/dyncom/arm_dyncom_run.cpp
Normal file
120
src/core/arm/dyncom/arm_dyncom_run.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
55
src/core/arm/dyncom/arm_dyncom_run.h
Normal file
55
src/core/arm/dyncom/arm_dyncom_run.h
Normal 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
|
521
src/core/arm/dyncom/arm_dyncom_thumb.cpp
Normal file
521
src/core/arm/dyncom/arm_dyncom_thumb.cpp
Normal 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;
|
||||||
|
}
|
51
src/core/arm/dyncom/arm_dyncom_thumb.h
Normal file
51
src/core/arm/dyncom/arm_dyncom_thumb.h
Normal 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
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "core/arm/interpreter/arm_interpreter.h"
|
#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
|
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,12 +17,11 @@ ARM_Interpreter::ARM_Interpreter() {
|
|||||||
ARMul_NewState(state);
|
ARMul_NewState(state);
|
||||||
|
|
||||||
state->abort_model = 0;
|
state->abort_model = 0;
|
||||||
state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
|
state->cpu = (cpu_config_t*)&arm11_cpu_info;
|
||||||
state->bigendSig = LOW;
|
state->bigendSig = LOW;
|
||||||
|
|
||||||
ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
|
ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
|
||||||
state->lateabtSig = LOW;
|
state->lateabtSig = LOW;
|
||||||
mmu_init(state);
|
|
||||||
|
|
||||||
// Reset the core to initial state
|
// Reset the core to initial state
|
||||||
ARMul_CoProInit(state);
|
ARMul_CoProInit(state);
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "core/arm/interpreter/armemu.h"
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
|
|
||||||
class ARM_Interpreter : virtual public ARM_Interface {
|
class ARM_Interpreter final : virtual public ARM_Interface {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ARM_Interpreter();
|
ARM_Interpreter();
|
||||||
|
@ -15,74 +15,15 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
#include "core/arm/interpreter/armos.h"
|
#include "core/arm/skyeye_common/vfp/vfp.h"
|
||||||
#include "core/arm/interpreter/armemu.h"
|
|
||||||
#include "core/arm/interpreter/vfp/vfp.h"
|
|
||||||
|
|
||||||
//chy 2005-07-08
|
//chy 2005-07-08
|
||||||
//#include "ansidecl.h"
|
//#include "ansidecl.h"
|
||||||
//chy -------
|
//chy -------
|
||||||
//#include "iwmmxt.h"
|
//#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. */
|
/* Dummy Co-processors. */
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
@ -132,42 +73,6 @@ NoCoPro5W (ARMul_State * state,
|
|||||||
static void write_cp14_reg(unsigned, ARMword);
|
static void write_cp14_reg(unsigned, ARMword);
|
||||||
static ARMword read_cp14_reg(unsigned);
|
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. */
|
/* Check an access to a register. */
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
@ -305,347 +210,6 @@ check_cp15_access (ARMul_State * state,
|
|||||||
return ARMul_DONE;
|
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. */
|
/* Install co-processor instruction handlers in this routine. */
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
@ -662,64 +226,14 @@ ARMul_CoProInit (ARMul_State * state)
|
|||||||
ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
|
ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
|
||||||
LDC routine, STC routine, MRC routine, MCR routine,
|
LDC routine, STC routine, MRC routine, MCR routine,
|
||||||
CDP routine, Read Reg routine, Write Reg routine). */
|
CDP routine, Read Reg routine, Write Reg routine). */
|
||||||
if (state->is_ep9312) {
|
if (state->is_v6) {
|
||||||
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) {
|
|
||||||
ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
|
ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
|
||||||
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
|
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
|
||||||
ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
|
ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
|
||||||
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
|
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
|
||||||
|
|
||||||
ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
|
/*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
|
||||||
MMUMRC, MMUMCR, NULL, NULL, 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);
|
|
||||||
}
|
}
|
||||||
//chy 2003-09-03 do it in future!!!!????
|
//chy 2003-09-03 do it in future!!!!????
|
||||||
#if 0
|
#if 0
|
||||||
@ -732,13 +246,6 @@ ARMul_CoProInit (ARMul_State * state)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#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. */
|
/* No handlers below here. */
|
||||||
|
|
||||||
/* Call all the initialisation routines. */
|
/* Call all the initialisation routines. */
|
||||||
@ -816,27 +323,3 @@ ARMul_CoProDetach (ARMul_State * state, unsigned number)
|
|||||||
state->CPRead[number] = NULL;
|
state->CPRead[number] = NULL;
|
||||||
state->CPWrite[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;
|
|
||||||
}
|
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
//#include <util.h> // DEBUG()
|
//#include <util.h> // DEBUG()
|
||||||
|
|
||||||
#include "arm_regformat.h"
|
#include "core/arm/skyeye_common/arm_regformat.h"
|
||||||
#include "armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "armemu.h"
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
#include "core/hle/hle.h"
|
#include "core/hle/hle.h"
|
||||||
|
|
||||||
//#include "svc.h"
|
//#include "svc.h"
|
||||||
@ -28,9 +28,6 @@
|
|||||||
//ichfly
|
//ichfly
|
||||||
//#define callstacker 1
|
//#define callstacker 1
|
||||||
|
|
||||||
|
|
||||||
//#include "armos.h"
|
|
||||||
|
|
||||||
//#include "skyeye_callback.h"
|
//#include "skyeye_callback.h"
|
||||||
//#include "skyeye_bus.h"
|
//#include "skyeye_bus.h"
|
||||||
//#include "sim_control.h"
|
//#include "sim_control.h"
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
//#include <unistd.h>
|
//#include <unistd.h>
|
||||||
|
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "core/arm/interpreter/armemu.h"
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
|
|
||||||
/***************************************************************************\
|
/***************************************************************************\
|
||||||
* Definitions for the emulator architecture *
|
* Definitions for the emulator architecture *
|
||||||
|
@ -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;
|
|
||||||
//}
|
|
@ -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;
|
|
||||||
//}
|
|
@ -15,18 +15,11 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
//#include <util.h>
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
#include <string>
|
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
|
||||||
#include "core/arm/interpreter/armemu.h"
|
|
||||||
#include "core/hle/coprocessor.h"
|
|
||||||
#include "core/arm/disassembler/arm_disasm.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 ARMword ModeToBank (ARMword);
|
||||||
static void EnvokeList (ARMul_State *, unsigned int, unsigned int);
|
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;
|
int cpopc = BITS(21, 23) & 0x7;
|
||||||
|
|
||||||
if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer
|
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) {
|
if (result != -1) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -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
|
freed as they might be needed again. A single area of memory may be
|
||||||
defined to generate aborts. */
|
defined to generate aborts. */
|
||||||
|
|
||||||
#include "armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "skyeye_defs.h"
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
//#include "code_cov.h"
|
|
||||||
|
|
||||||
#ifdef VALIDATE /* for running the validate suite */
|
#include "core/mem_map.h"
|
||||||
#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
|
|
||||||
#define ABORTS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define ABORTS */
|
#define dumpstack 1
|
||||||
|
#define dumpstacksize 0x10
|
||||||
|
#define maxdmupaddr 0x0033a850
|
||||||
|
|
||||||
#ifdef ABORTS /* the memory system will abort */
|
/*ARMword ARMul_GetCPSR (ARMul_State * state) {
|
||||||
/* For the old test suite Abort between 32 Kbytes and 32 Mbytes
|
return 0;
|
||||||
For the new test suite Abort between 8 Mbytes and 26 Mbytes */
|
|
||||||
/* #define LOWABORT 32 * 1024
|
|
||||||
#define HIGHABORT 32 * 1024 * 1024 */
|
|
||||||
#define LOWABORT 8 * 1024 * 1024
|
|
||||||
#define HIGHABORT 26 * 1024 * 1024
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NUMPAGES 64 * 1024
|
|
||||||
#define PAGESIZE 64 * 1024
|
|
||||||
#define PAGEBITS 16
|
|
||||||
#define OFFSETBITS 0xffff
|
|
||||||
//chy 2003-08-19: seems no use ????
|
|
||||||
int SWI_vector_installed = FALSE;
|
|
||||||
extern ARMword skyeye_cachetype;
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Get a byte into Virtual Memory, maybe allocating the page *
|
|
||||||
\***************************************************************************/
|
|
||||||
static fault_t
|
|
||||||
GetByte (ARMul_State * state, ARMword address, ARMword * data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
fault = mmu_read_byte (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
|
|
||||||
// printf("SKYEYE: GetByte fault %d \n", fault);
|
|
||||||
}
|
}
|
||||||
return fault;
|
ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
void ARMul_SetCPSR (ARMul_State * state, ARMword value) {
|
||||||
/***************************************************************************\
|
|
||||||
* Get a halfword into Virtual Memory, maybe allocating the page *
|
|
||||||
\***************************************************************************/
|
|
||||||
static fault_t
|
|
||||||
GetHalfWord (ARMul_State * state, ARMword address, ARMword * data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
fault = mmu_read_halfword (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
|
|
||||||
// printf("SKYEYE: GetHalfWord fault %d \n", fault);
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Get a Word from Virtual Memory, maybe allocating the page *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
static fault_t
|
|
||||||
GetWord (ARMul_State * state, ARMword address, ARMword * data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
fault = mmu_read_word (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
|
|
||||||
#if 0
|
|
||||||
/* XXX */ extern int hack;
|
|
||||||
hack = 1;
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
printf ("mmu_read_word at 0x%08x: ", address);
|
|
||||||
switch (fault) {
|
|
||||||
case ALIGNMENT_FAULT:
|
|
||||||
printf ("ALIGNMENT_FAULT");
|
|
||||||
break;
|
|
||||||
case SECTION_TRANSLATION_FAULT:
|
|
||||||
printf ("SECTION_TRANSLATION_FAULT");
|
|
||||||
break;
|
|
||||||
case PAGE_TRANSLATION_FAULT:
|
|
||||||
printf ("PAGE_TRANSLATION_FAULT");
|
|
||||||
break;
|
|
||||||
case SECTION_DOMAIN_FAULT:
|
|
||||||
printf ("SECTION_DOMAIN_FAULT");
|
|
||||||
break;
|
|
||||||
case SECTION_PERMISSION_FAULT:
|
|
||||||
printf ("SECTION_PERMISSION_FAULT");
|
|
||||||
break;
|
|
||||||
case SUBPAGE_PERMISSION_FAULT:
|
|
||||||
printf ("SUBPAGE_PERMISSION_FAULT");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf ("Unrecognized fault number!");
|
|
||||||
}
|
|
||||||
printf ("\tpc = 0x%08x\n", state->Reg[15]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
//2003-07-10 chy: lyh change
|
|
||||||
/****************************************************************************\
|
|
||||||
* Load a Instrion Word into Virtual Memory *
|
|
||||||
\****************************************************************************/
|
|
||||||
static fault_t
|
|
||||||
LoadInstr (ARMul_State * state, ARMword address, ARMword * instr)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
fault = mmu_load_instr (state, address, instr);
|
|
||||||
return fault;
|
|
||||||
//if (fault)
|
|
||||||
// log_msg("load_instr fault = %d, address = %x\n", fault, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Put a byte into Virtual Memory, maybe allocating the page *
|
|
||||||
\***************************************************************************/
|
|
||||||
static fault_t
|
|
||||||
PutByte (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
fault = mmu_write_byte (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
|
|
||||||
// printf("SKYEYE: PutByte fault %d \n", fault);
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Put a halfword into Virtual Memory, maybe allocating the page *
|
|
||||||
\***************************************************************************/
|
|
||||||
static fault_t
|
|
||||||
PutHalfWord (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
fault = mmu_write_halfword (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
|
|
||||||
// printf("SKYEYE: PutHalfWord fault %d \n", fault);
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Put a Word into Virtual Memory, maybe allocating the page *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
static fault_t
|
|
||||||
PutWord (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
fault = mmu_write_word (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
|
|
||||||
#if 0
|
|
||||||
/* XXX */ extern int hack;
|
|
||||||
hack = 1;
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
printf ("mmu_write_word at 0x%08x: ", address);
|
|
||||||
switch (fault) {
|
|
||||||
case ALIGNMENT_FAULT:
|
|
||||||
printf ("ALIGNMENT_FAULT");
|
|
||||||
break;
|
|
||||||
case SECTION_TRANSLATION_FAULT:
|
|
||||||
printf ("SECTION_TRANSLATION_FAULT");
|
|
||||||
break;
|
|
||||||
case PAGE_TRANSLATION_FAULT:
|
|
||||||
printf ("PAGE_TRANSLATION_FAULT");
|
|
||||||
break;
|
|
||||||
case SECTION_DOMAIN_FAULT:
|
|
||||||
printf ("SECTION_DOMAIN_FAULT");
|
|
||||||
break;
|
|
||||||
case SECTION_PERMISSION_FAULT:
|
|
||||||
printf ("SECTION_PERMISSION_FAULT");
|
|
||||||
break;
|
|
||||||
case SUBPAGE_PERMISSION_FAULT:
|
|
||||||
printf ("SUBPAGE_PERMISSION_FAULT");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf ("Unrecognized fault number!");
|
|
||||||
}
|
|
||||||
printf ("\tpc = 0x%08x\n", state->Reg[15]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Initialise the memory interface *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Remove the memory interface *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_MemoryExit (ARMul_State * state)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* ReLoad Instruction *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
|
|
||||||
{
|
|
||||||
ARMword data;
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
#ifdef ABORTS
|
|
||||||
if (address >= LOWABORT && address < HIGHABORT) {
|
|
||||||
ARMul_PREFETCHABORT (address);
|
|
||||||
return ARMul_ABORTWORD;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
/* do profiling for code coverage */
|
|
||||||
if (skyeye_config.code_cov.prof_on)
|
|
||||||
cov_prof(EXEC_FLAG, address);
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
if ((isize == 2) && (address & 0x2)) {
|
|
||||||
ARMword lo, hi;
|
|
||||||
if (!(skyeye_cachetype == INSTCACHE))
|
|
||||||
fault = GetHalfWord (state, address, &lo);
|
|
||||||
else
|
|
||||||
fault = LoadInstr (state, address, &lo);
|
|
||||||
#if 0
|
|
||||||
if (!fault) {
|
|
||||||
if (!(skyeye_cachetype == INSTCACHE))
|
|
||||||
fault = GetHalfWord (state, address + isize, &hi);
|
|
||||||
else
|
|
||||||
fault = LoadInstr (state, address + isize, &hi);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) {
|
||||||
if (fault) {
|
|
||||||
ARMul_PREFETCHABORT (address);
|
|
||||||
return ARMul_ABORTWORD;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
|
||||||
return lo;
|
|
||||||
#if 0
|
|
||||||
if (state->bigendSig == HIGH)
|
|
||||||
return (lo << 16) | (hi >> 16);
|
|
||||||
else
|
|
||||||
return ((hi & 0xFFFF) << 16) | (lo >> 16);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!(skyeye_cachetype == INSTCACHE))
|
|
||||||
fault = GetWord (state, address, &data);
|
|
||||||
else
|
|
||||||
fault = LoadInstr (state, address, &data);
|
|
||||||
|
|
||||||
if (fault) {
|
}*/
|
||||||
|
|
||||||
/* dyf add for s3c6410 no instcache temporary 2010.9.17 */
|
void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) {
|
||||||
if (!(skyeye_cachetype == INSTCACHE)) {
|
|
||||||
/* set translation fault on prefetch abort */
|
|
||||||
state->mmu.fault_statusi = fault & 0xFF;
|
|
||||||
state->mmu.fault_address = address;
|
|
||||||
}
|
|
||||||
/* add end */
|
|
||||||
|
|
||||||
ARMul_PREFETCHABORT (address);
|
|
||||||
return ARMul_ABORTWORD;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_LoadInstrS(ARMul_State * state, ARMword address, ARMword isize) {
|
||||||
* Load Instruction, Sequential Cycle *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
|
|
||||||
{
|
|
||||||
state->NumScycles++;
|
state->NumScycles++;
|
||||||
|
|
||||||
#ifdef HOURGLASS
|
#ifdef HOURGLASS
|
||||||
@ -336,345 +59,107 @@ ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
|
|||||||
HOURGLASS;
|
HOURGLASS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (isize == 2)
|
||||||
return ARMul_ReLoadInstr (state, address, isize);
|
return (u16)Memory::Read16(address);
|
||||||
|
else
|
||||||
|
return (u32)Memory::Read32(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) {
|
||||||
* Load Instruction, Non Sequential Cycle *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
|
|
||||||
{
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
|
|
||||||
return ARMul_ReLoadInstr (state, address, isize);
|
if (isize == 2)
|
||||||
|
return (u16)Memory::Read16(address);
|
||||||
|
else
|
||||||
|
return (u32)Memory::Read32(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) {
|
||||||
* Read Word (but don't tell anyone!) *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_ReadWord (ARMul_State * state, ARMword address)
|
|
||||||
{
|
|
||||||
ARMword data;
|
ARMword data;
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
#ifdef ABORTS
|
if ((isize == 2) && (address & 0x2)) {
|
||||||
if (address >= LOWABORT && address < HIGHABORT) {
|
ARMword lo;
|
||||||
ARMul_DATAABORT (address);
|
lo = (u16)Memory::Read16(address);
|
||||||
return ARMul_ABORTWORD;
|
return lo;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fault = GetWord (state, address, &data);
|
data = (u32)Memory::Read32(address);
|
||||||
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;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) {
|
||||||
* Load Word, Sequential Cycle *
|
ARMword data;
|
||||||
\***************************************************************************/
|
data = Memory::Read32(address);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
ARMword
|
ARMword ARMul_LoadWordS(ARMul_State * state, ARMword address) {
|
||||||
ARMul_LoadWordS (ARMul_State * state, ARMword address)
|
|
||||||
{
|
|
||||||
state->NumScycles++;
|
state->NumScycles++;
|
||||||
|
|
||||||
return ARMul_ReadWord(state, address);
|
return ARMul_ReadWord(state, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_LoadWordN(ARMul_State * state, ARMword address) {
|
||||||
* Load Word, Non Sequential Cycle *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_LoadWordN (ARMul_State * state, ARMword address)
|
|
||||||
{
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
|
|
||||||
return ARMul_ReadWord(state, address);
|
return ARMul_ReadWord(state, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) {
|
||||||
* Load Halfword, (Non Sequential Cycle) *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
|
|
||||||
{
|
|
||||||
ARMword data;
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
fault = GetHalfWord (state, address, &data);
|
return (u16)Memory::Read16(address);;
|
||||||
|
|
||||||
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;
|
ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) {
|
||||||
|
return (u8)Memory::Read8(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_LoadByte(ARMul_State * state, ARMword 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)
|
|
||||||
{
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
|
|
||||||
return ARMul_ReadByte(state, address);
|
return ARMul_ReadByte(state, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) {
|
||||||
* Write Word (but don't tell anyone!) *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
|
|
||||||
#ifdef ABORTS
|
|
||||||
if (address >= LOWABORT && address < HIGHABORT) {
|
|
||||||
ARMul_DATAABORT (address);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fault = PutWord (state, address, data);
|
|
||||||
if (fault) {
|
|
||||||
state->mmu.fault_status =
|
|
||||||
(fault | (state->mmu.last_domain << 4)) & 0xFF;
|
|
||||||
state->mmu.fault_address = address;
|
|
||||||
ARMul_DATAABORT (address);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Store Word, Sequential Cycle *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
state->NumScycles++;
|
|
||||||
|
|
||||||
ARMul_WriteWord (state, address, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************\
|
|
||||||
* Store Word, Non Sequential Cycle *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
|
Memory::Write16(address, data);
|
||||||
ARMul_WriteWord (state, address, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) {
|
||||||
* Store HalfWord, (Non Sequential Cycle) *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
fault_t fault;
|
|
||||||
state->NumNcycles++;
|
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);
|
ARMul_WriteByte(state, address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) {
|
||||||
* Swap Word, (Two Non Sequential Cycles) *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
ARMword temp;
|
ARMword temp;
|
||||||
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
|
|
||||||
temp = ARMul_ReadWord(state, address);
|
temp = ARMul_ReadWord(state, address);
|
||||||
|
|
||||||
state->NumNcycles++;
|
state->NumNcycles++;
|
||||||
|
Memory::Write32(address, data);
|
||||||
PutWord (state, address, data);
|
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
ARMword ARMul_SwapByte(ARMul_State * state, ARMword address, ARMword data) {
|
||||||
* Swap Byte, (Two Non Sequential Cycles) *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
ARMword
|
|
||||||
ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
|
|
||||||
{
|
|
||||||
ARMword temp;
|
ARMword temp;
|
||||||
|
|
||||||
temp = ARMul_LoadByte(state, address);
|
temp = ARMul_LoadByte(state, address);
|
||||||
ARMul_StoreByte (state, address, data);
|
Memory::Write8(address, data);
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) {
|
||||||
* Count I Cycles *
|
Memory::Write32(address, data);
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_Icycles (ARMul_State * state, unsigned number,
|
|
||||||
ARMword address)
|
|
||||||
{
|
|
||||||
state->NumIcycles += number;
|
|
||||||
ARMul_CLEARABORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************\
|
void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data)
|
||||||
* Count C Cycles *
|
|
||||||
\***************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
ARMul_Ccycles (ARMul_State * state, unsigned number,
|
|
||||||
ARMword address)
|
|
||||||
{
|
{
|
||||||
state->NumCcycles += number;
|
Memory::Write8(address, data);
|
||||||
ARMul_CLEARABORT;
|
}
|
||||||
|
|
||||||
|
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
@ -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_*/
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
@ -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]);
|
|
||||||
};
|
|
||||||
}
|
|
@ -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_*/
|
|
@ -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--------------------------------------------------------------------------
|
|
||||||
};
|
|
@ -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_*/
|
|
@ -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;
|
|
||||||
}
|
|
@ -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_*/
|
|
@ -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--;
|
|
||||||
};
|
|
||||||
}
|
|
@ -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
@ -19,7 +19,7 @@
|
|||||||
instruction into its corresponding ARM instruction, and using the
|
instruction into its corresponding ARM instruction, and using the
|
||||||
existing ARM simulator. */
|
existing ARM simulator. */
|
||||||
|
|
||||||
#include "skyeye_defs.h"
|
#include "core/arm/skyeye_common/skyeye_defs.h"
|
||||||
|
|
||||||
#ifndef MODET /* required for the Thumb instruction support */
|
#ifndef MODET /* required for the Thumb instruction support */
|
||||||
#if 1
|
#if 1
|
||||||
@ -29,9 +29,9 @@ existing ARM simulator. */
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "armemu.h"
|
#include "core/arm/skyeye_common/armemu.h"
|
||||||
#include "armos.h"
|
#include "core/arm/skyeye_common/armos.h"
|
||||||
|
|
||||||
|
|
||||||
/* Decode a 16bit Thumb instruction. The instruction is in the low
|
/* Decode a 16bit Thumb instruction. The instruction is in the low
|
||||||
|
@ -99,5 +99,7 @@ enum arm_regno{
|
|||||||
MAX_REG_NUM,
|
MAX_REG_NUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CP15(idx) (idx - CP15_BASE)
|
||||||
#define VFP_OFFSET(x) (x - VFP_BASE)
|
#define VFP_OFFSET(x) (x - VFP_BASE)
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -20,16 +20,13 @@
|
|||||||
|
|
||||||
#ifndef __ARM_CPU_H__
|
#ifndef __ARM_CPU_H__
|
||||||
#define __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 <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
|
|
||||||
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
|
|
||||||
typedef struct ARM_CPU_State_s {
|
typedef struct ARM_CPU_State_s {
|
||||||
ARMul_State * core;
|
ARMul_State * core;
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#include "arm_regformat.h"
|
#include "arm_regformat.h"
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "skyeye_defs.h"
|
#include "core/arm/skyeye_common/skyeye_defs.h"
|
||||||
|
|
||||||
//AJ2D--------------------------------------------------------------------------
|
//AJ2D--------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ typedef unsigned long long uint64_t;
|
|||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "armmmu.h"
|
#include "core/arm/skyeye_common/armmmu.h"
|
||||||
//#include "lcd/skyeye_lcd.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 */
|
int verbose; /* non-zero means print various messages like the banner */
|
||||||
|
|
||||||
mmu_state_t mmu;
|
|
||||||
int mmu_inited;
|
int mmu_inited;
|
||||||
//mem_state_t mem;
|
//mem_state_t mem;
|
||||||
/*remove io_state to skyeye_mach_*.c files */
|
/*remove io_state to skyeye_mach_*.c files */
|
@ -18,7 +18,7 @@
|
|||||||
#define __ARMEMU_H__
|
#define __ARMEMU_H__
|
||||||
|
|
||||||
|
|
||||||
#include "armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
//#include "skyeye.h"
|
//#include "skyeye.h"
|
||||||
|
|
||||||
//extern ARMword isize;
|
//extern ARMword isize;
|
@ -134,121 +134,4 @@ typedef enum fault_t
|
|||||||
|
|
||||||
} 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_ */
|
#endif /* _ARMMMU_H_ */
|
@ -15,14 +15,7 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
//#include "bank_defs.h"
|
#include <stdint.h>
|
||||||
//#include "dyncom/defines.h"
|
|
||||||
|
|
||||||
//typedef struct mmap_area{
|
|
||||||
// mem_bank_t bank;
|
|
||||||
// void *mmap_addr;
|
|
||||||
// struct mmap_area *next;
|
|
||||||
//}mmap_area_t;
|
|
||||||
|
|
||||||
#if FAST_MEMORY
|
#if FAST_MEMORY
|
||||||
/* in user mode, mmap_base will be on initial brk,
|
/* in user mode, mmap_base will be on initial brk,
|
@ -108,4 +108,6 @@ typedef struct generic_arch_s
|
|||||||
align_t alignment;
|
align_t alignment;
|
||||||
} generic_arch_t;
|
} generic_arch_t;
|
||||||
|
|
||||||
|
typedef u32 addr_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
55
src/core/arm/skyeye_common/skyeye_types.h
Normal file
55
src/core/arm/skyeye_common/skyeye_types.h
Normal 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
|
@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
#include "core/arm/interpreter/vfp/vfp.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. */
|
//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)
|
if (CoProc == 10 || CoProc == 11)
|
||||||
{
|
{
|
||||||
#define VFP_MRC_TRANS
|
#define VFP_MRC_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MRC_TRANS
|
#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",
|
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)
|
if (CoProc == 10 || CoProc == 11)
|
||||||
{
|
{
|
||||||
#define VFP_MCR_TRANS
|
#define VFP_MCR_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MCR_TRANS
|
#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",
|
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)
|
if (CoProc == 10 || CoProc == 11)
|
||||||
{
|
{
|
||||||
#define VFP_MRRC_TRANS
|
#define VFP_MRRC_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MRRC_TRANS
|
#undef VFP_MRRC_TRANS
|
||||||
}
|
}
|
||||||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
|
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)
|
if (CoProc == 11 || CoProc == 10)
|
||||||
{
|
{
|
||||||
#define VFP_MCRR_TRANS
|
#define VFP_MCRR_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MCRR_TRANS
|
#undef VFP_MCRR_TRANS
|
||||||
}
|
}
|
||||||
DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
|
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
|
#endif
|
||||||
|
|
||||||
#define VFP_STC_TRANS
|
#define VFP_STC_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_STC_TRANS
|
#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",
|
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)
|
if (CoProc == 10 || CoProc == 11)
|
||||||
{
|
{
|
||||||
#define VFP_LDC_TRANS
|
#define VFP_LDC_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_LDC_TRANS
|
#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",
|
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)
|
if (CoProc == 10 || CoProc == 11)
|
||||||
{
|
{
|
||||||
#define VFP_CDP_TRANS
|
#define VFP_CDP_TRANS
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_CDP_TRANS
|
#undef VFP_CDP_TRANS
|
||||||
|
|
||||||
int exceptions = 0;
|
int exceptions = 0;
|
||||||
@ -257,21 +257,21 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
|
|||||||
|
|
||||||
/* ----------- MRC ------------ */
|
/* ----------- MRC ------------ */
|
||||||
#define VFP_MRC_IMPL
|
#define VFP_MRC_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MRC_IMPL
|
#undef VFP_MRC_IMPL
|
||||||
|
|
||||||
#define VFP_MRRC_IMPL
|
#define VFP_MRRC_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MRRC_IMPL
|
#undef VFP_MRRC_IMPL
|
||||||
|
|
||||||
|
|
||||||
/* ----------- MCR ------------ */
|
/* ----------- MCR ------------ */
|
||||||
#define VFP_MCR_IMPL
|
#define VFP_MCR_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MCR_IMPL
|
#undef VFP_MCR_IMPL
|
||||||
|
|
||||||
#define VFP_MCRR_IMPL
|
#define VFP_MCRR_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_MCRR_IMPL
|
#undef VFP_MCRR_IMPL
|
||||||
|
|
||||||
/* Memory operation are not inlined, as old Interpreter and Fast interpreter
|
/* Memory operation are not inlined, as old Interpreter and Fast interpreter
|
||||||
@ -283,19 +283,19 @@ VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
|
|||||||
|
|
||||||
/* ----------- STC ------------ */
|
/* ----------- STC ------------ */
|
||||||
#define VFP_STC_IMPL
|
#define VFP_STC_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_STC_IMPL
|
#undef VFP_STC_IMPL
|
||||||
|
|
||||||
|
|
||||||
/* ----------- LDC ------------ */
|
/* ----------- LDC ------------ */
|
||||||
#define VFP_LDC_IMPL
|
#define VFP_LDC_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_LDC_IMPL
|
#undef VFP_LDC_IMPL
|
||||||
|
|
||||||
|
|
||||||
/* ----------- CDP ------------ */
|
/* ----------- CDP ------------ */
|
||||||
#define VFP_CDP_IMPL
|
#define VFP_CDP_IMPL
|
||||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
|
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
|
||||||
#undef VFP_CDP_IMPL
|
#undef VFP_CDP_IMPL
|
||||||
|
|
||||||
/* Miscellaneous functions */
|
/* Miscellaneous functions */
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#define vfpdebug //printf
|
#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 VFPInit (ARMul_State *state);
|
||||||
unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
|
unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
|
@ -38,7 +38,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
|
|
||||||
#define u16 uint16_t
|
#define u16 uint16_t
|
||||||
#define u32 uint32_t
|
#define u32 uint32_t
|
@ -51,9 +51,9 @@
|
|||||||
* ===========================================================================
|
* ===========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "core/arm/interpreter/vfp/vfp.h"
|
#include "core/arm/skyeye_common/vfp/vfp.h"
|
||||||
#include "core/arm/interpreter/vfp/vfp_helper.h"
|
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
|
||||||
#include "core/arm/interpreter/vfp/asm_vfp.h"
|
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
|
||||||
|
|
||||||
static struct vfp_double vfp_double_default_qnan = {
|
static struct vfp_double vfp_double_default_qnan = {
|
||||||
//.exponent = 2047,
|
//.exponent = 2047,
|
@ -3709,7 +3709,7 @@ VFPLABEL_INST:
|
|||||||
{
|
{
|
||||||
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d, cpu->ExtReg[inst_cream->d]);
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
/* Check endianness */
|
/* 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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
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]);
|
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);
|
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
|
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
@ -3936,12 +3936,12 @@ VFPLABEL_INST:
|
|||||||
/* Careful of endianness, little by default */
|
/* Careful of endianness, little by default */
|
||||||
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
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]);
|
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 += 8;
|
||||||
@ -4048,7 +4048,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
|
|||||||
{
|
{
|
||||||
if (single)
|
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
|
#if 0
|
||||||
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
|
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
|
||||||
bb = cpu->dyncom_engine->bb;
|
bb = cpu->dyncom_engine->bb;
|
||||||
@ -4166,7 +4166,7 @@ VFPLABEL_INST: /* encoding 1 */
|
|||||||
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
|
DBG("\taddr[%x] <= s%d=[%x]\n", addr, inst_cream->d+i, cpu->ExtReg[inst_cream->d+i]);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
@ -4177,13 +4177,13 @@ VFPLABEL_INST: /* encoding 1 */
|
|||||||
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
|
fault = check_address_validity(cpu, addr + 4, &phys_addr, 0);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
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]);
|
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 += 8;
|
||||||
@ -4304,7 +4304,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
|
|||||||
if (single)
|
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 R(i) is R15? */
|
||||||
#if 0
|
#if 0
|
||||||
phys_addr = get_phys_addr(cpu, bb, Addr, 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
|
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
|
#if 0
|
||||||
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
|
phys_addr = get_phys_addr(cpu, bb, Addr, 0);
|
||||||
bb = cpu->dyncom_engine->bb;
|
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;
|
bb = cpu->dyncom_engine->bb;
|
||||||
//if (fault) goto MMU_EXCEPTION;
|
//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
|
#if 0
|
||||||
phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
|
phys_addr = get_phys_addr(cpu, bb, ADD(Addr, CONST(4)), 0);
|
||||||
bb = cpu->dyncom_engine->bb;
|
bb = cpu->dyncom_engine->bb;
|
||||||
@ -4431,7 +4431,7 @@ VFPLABEL_INST:
|
|||||||
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, value1, addr);
|
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, value1, addr);
|
||||||
cpu->ExtReg[inst_cream->d+i] = value1;
|
cpu->ExtReg[inst_cream->d+i] = value1;
|
||||||
@ -4443,13 +4443,13 @@ VFPLABEL_INST:
|
|||||||
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
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);
|
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;
|
cpu->ExtReg[(inst_cream->d+i)*2] = value1;
|
||||||
@ -4682,7 +4682,7 @@ VFPLABEL_INST:
|
|||||||
{
|
{
|
||||||
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d, cpu->ExtReg[inst_cream->d], addr);
|
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;
|
unsigned int word1, word2;
|
||||||
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
/* Check endianness */
|
/* Check endianness */
|
||||||
cpu->ExtReg[inst_cream->d*2] = word1;
|
cpu->ExtReg[inst_cream->d*2] = word1;
|
||||||
@ -4923,7 +4923,7 @@ VFPLABEL_INST:
|
|||||||
{
|
{
|
||||||
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, cpu->ExtReg[inst_cream->d+i], addr);
|
DBG("\ts%d <= [%x] addr[%x]\n", inst_cream->d+i, cpu->ExtReg[inst_cream->d+i], addr);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
@ -4933,12 +4933,12 @@ VFPLABEL_INST:
|
|||||||
/* Careful of endianness, little by default */
|
/* Careful of endianness, little by default */
|
||||||
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
if (fault) goto MMU_EXCEPTION;
|
||||||
|
|
||||||
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
|
fault = check_address_validity(cpu, addr + 4, &phys_addr, 1);
|
||||||
if (fault) goto MMU_EXCEPTION;
|
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;
|
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);
|
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;
|
addr += 8;
|
||||||
@ -5058,7 +5058,7 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
|
|||||||
if (single)
|
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 R(i) is R15? */
|
||||||
#if 0
|
#if 0
|
||||||
phys_addr = get_phys_addr(cpu, bb, Addr, 1);
|
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);
|
val = new LoadInst(cpu->dyncom_engine->read_value, "", false, bb);
|
||||||
LETFPS((d + i) * 2 + 1, FPBITCAST32(val));
|
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]);
|
//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 += 8;
|
||||||
Addr = ADD(Addr, CONST(8));
|
Addr = ADD(Addr, CONST(8));
|
@ -51,9 +51,9 @@
|
|||||||
* ===========================================================================
|
* ===========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "core/arm/interpreter/vfp/vfp_helper.h"
|
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
|
||||||
#include "core/arm/interpreter/vfp/asm_vfp.h"
|
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
|
||||||
#include "core/arm/interpreter/vfp/vfp.h"
|
#include "core/arm/skyeye_common/vfp/vfp.h"
|
||||||
|
|
||||||
static struct vfp_single vfp_single_default_qnan = {
|
static struct vfp_single vfp_single_default_qnan = {
|
||||||
//.exponent = 255,
|
//.exponent = 255,
|
@ -5,7 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/arm/interpreter/armdefs.h"
|
#include "core/arm/skyeye_common/armdefs.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user