Fix merge conflicts

This commit is contained in:
darkf 2014-12-29 19:47:41 -08:00
commit 8ba9ac0f74
288 changed files with 17413 additions and 13969 deletions

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -77,6 +77,12 @@ public:
*/
virtual u64 GetTicks() const = 0;
/**
* Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
* @param ticks Number of ticks to advance the CPU core
*/
virtual void AddTicks(u64 ticks) = 0;
/**
* Saves the current CPU context
* @param ctx Thread context to save

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <string>

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/arm/skyeye_common/armcpu.h"
@ -47,68 +47,38 @@ ARM_DynCom::ARM_DynCom() : ticks(0) {
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->Reg[15];
}
/**
* 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::AddTicks(u64 ticks) {
this->ticks += ticks;
}
void ARM_DynCom::ExecuteInstructions(int num_instructions) {
state->NumInstrsToExecute = num_instructions;
@ -118,11 +88,6 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
ticks += 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));
@ -139,11 +104,6 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) {
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));
@ -160,7 +120,6 @@ void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
state->NextInstr = ctx.mode;
}
/// Prepare core for thread reschedule (if needed to correctly handle state)
void ARM_DynCom::PrepareReschedule() {
state->NumInstrsToExecute = 0;
}

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -27,14 +27,14 @@ public:
* Get the current Program Counter
* @return Returns current PC
*/
u32 GetPC() const;
u32 GetPC() const override;
/**
* Get an ARM register
* @param index Register index (0-15)
* @return Returns the value in the register
*/
u32 GetReg(int index) const;
u32 GetReg(int index) const override;
/**
* Set an ARM register
@ -47,7 +47,7 @@ public:
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
u32 GetCPSR() const;
u32 GetCPSR() const override;
/**
* Set the current CPSR register
@ -59,7 +59,13 @@ public:
* Returns the number of clock ticks since the last reset
* @return Returns number of clock ticks
*/
u64 GetTicks() const;
u64 GetTicks() const override;
/**
* Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
* @param ticks Number of ticks to advance the CPU core
*/
void AddTicks(u64 ticks) override;
/**
* Saves the current CPU context

View file

@ -1,402 +1,443 @@
/* 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
*/
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#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},
{ "vmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 },
{ "vmls", 7, ARMVFP2, 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 },
{ "vnmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 },
{ "vnmla", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
{ "vnmls", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
{ "vnmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
{ "vmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
{ "vadd", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
{ "vsub", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
{ "vdiv", 5, ARMVFP2, 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
{ "vmov(i)", 4, ARMVFP3, 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0 },
{ "vmov(r)", 5, ARMVFP3, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 },
{ "vabs", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 },
{ "vneg", 5, ARMVFP2, 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 },
{ "vsqrt", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 },
{ "vcmp", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
{ "vcmp2", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40 },
{ "vcvt(bds)", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 },
{ "vcvt(bff)", 6, ARMVFP3, 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 5, 6, 6, 1 },
{ "vcvt(bfi)", 5, ARMVFP2, 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
{ "vmovbrs", 3, ARMVFP2, 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10 },
{ "vmsr", 2, ARMVFP2, 20, 27, 0xEE, 0, 11, 0xA10 },
{ "vmovbrc", 4, ARMVFP2, 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0, 4, 0x10 },
{ "vmrs", 2, ARMVFP2, 20, 27, 0xEF, 0, 11, 0xA10 },
{ "vmovbcr", 4, ARMVFP2, 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0, 4, 0x10 },
{ "vmovbrrss", 3, ARMVFP2, 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1 },
{ "vmovbrrd", 3, ARMVFP2, 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1 },
{ "vstr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 0, 9, 11, 5 },
{ "vpush", 3, ARMVFP2, 23, 27, 0x1A, 16, 21, 0x2D, 9, 11, 5 },
{ "vstm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 0, 9, 11, 5 },
{ "vpop", 3, ARMVFP2, 23, 27, 0x19, 16, 21, 0x3D, 9, 11, 5 },
{ "vldr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 1, 9, 11, 5 },
{ "vldm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 1, 9, 11, 5 },
{ "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}
{ "vmla", 0, ARMVFP2, 0 },
{ "vmls", 0, ARMVFP2, 0 },
{ "vnmla", 0, ARMVFP2, 0 },
{ "vnmla", 0, ARMVFP2, 0 },
{ "vnmls", 0, ARMVFP2, 0 },
{ "vnmul", 0, ARMVFP2, 0 },
{ "vmul", 0, ARMVFP2, 0 },
{ "vadd", 0, ARMVFP2, 0 },
{ "vsub", 0, ARMVFP2, 0 },
{ "vdiv", 0, ARMVFP2, 0 },
{ "vmov(i)", 0, ARMVFP3, 0 },
{ "vmov(r)", 0, ARMVFP3, 0 },
{ "vabs", 0, ARMVFP2, 0 },
{ "vneg", 0, ARMVFP2, 0 },
{ "vsqrt", 0, ARMVFP2, 0 },
{ "vcmp", 0, ARMVFP2, 0 },
{ "vcmp2", 0, ARMVFP2, 0 },
{ "vcvt(bff)", 0, ARMVFP3, 4, 4, 1 },
{ "vcvt(bds)", 0, ARMVFP2, 0 },
{ "vcvt(bfi)", 0, ARMVFP2, 0 },
{ "vmovbrs", 0, ARMVFP2, 0 },
{ "vmsr", 0, ARMVFP2, 0 },
{ "vmovbrc", 0, ARMVFP2, 0 },
{ "vmrs", 0, ARMVFP2, 0 },
{ "vmovbcr", 0, ARMVFP2, 0 },
{ "vmovbrrss", 0, ARMVFP2, 0 },
{ "vmovbrrd", 0, ARMVFP2, 0 },
{ "vstr", 0, ARMVFP2, 0 },
{ "vpush", 0, ARMVFP2, 0 },
{ "vstm", 0, ARMVFP2, 0 },
{ "vpop", 0, ARMVFP2, 0 },
{ "vldr", 0, ARMVFP2, 0 },
{ "vldm", 0, ARMVFP2, 0 },
{ "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;
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++) {
n = arm_instruction[i].attribute_value;
base = 0;
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;
}
}
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--;
}
if (ret == DECODE_SUCCESS) {
*idx = i;
return ret;
}
}
return ret;
// All conditions is satisfied.
if (n == 0)
ret = DECODE_SUCCESS;
if (ret == DECODE_SUCCESS) {
n = arm_exclusion_code[i].attribute_value;
if (n != 0) {
base = 0;
while (n) {
if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {
break;
}
base += 3;
n--;
}
// All conditions is satisfied.
if (n == 0)
ret = DECODE_FAILURE;
}
}
if (ret == DECODE_SUCCESS) {
*idx = i;
return ret;
}
}
return ret;
}

View file

@ -56,8 +56,6 @@
#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)

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once

View file

@ -1,42 +1,15 @@
/* 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
*/
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#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");
void switch_mode(arm_core_t *core, uint32_t mode) {
if (core->Mode == mode)
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:
@ -110,11 +83,8 @@ void switch_mode(arm_core_t *core, uint32_t mode)
}
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");
} else {
LOG_CRITICAL(Core_ARM11, "user mode");
exit(-2);
}
}

View file

@ -1,35 +1,13 @@
/* 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
*/
// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
/* We can provide simple Thumb simulation by decoding the Thumb
instruction into its corresponding ARM instruction, and using the
existing ARM simulator. */
// 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 */
#ifndef MODET // Required for the Thumb instruction support
#if 1
#error "MODET needs to be defined for the Thumb world to work"
#else
@ -40,482 +18,359 @@ existing ARM simulator. */
#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. */
// 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 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;
ARMword tinstr;
tinstr = instr;
//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
// The endian should be judge here
if((addr & 0x3) != 0)
tinstr = instr >> 16;
else
tinstr &= 0xFFFF;
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;
*ainstr = 0xDEADC0DE; // Debugging to catch non updates
/* 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;
switch ((tinstr & 0xF800) >> 11) {
case 0: // LSL
case 1: // LSR
case 2: // ASR
*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
{
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
{
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) {
enum otype {
t_norm,
t_shift,
t_neg,
t_mul
};
struct {
ARMword opcode;
otype type;
} 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].type) {
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 {
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
*ainstr = 0xE1200030 // base
| (Rs << 0); // Rm
break;
}
}
break;
case 9: // LDR Rd,[PC,#imm8]
*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) {
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 {
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]
{
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]
*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]
*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
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) {
// 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 {
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
*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) {
// 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)
valid = t_branch;
else // UNDEFINED : cc=1110(AL) uses different format
valid = t_undefined;
break;
case 28: // B
valid = t_branch;
break;
case 29:
if(tinstr & 0x1)
valid = t_undefined;
else
valid = t_branch;
break;
case 30: // BL instruction 1
// 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
// 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.
valid = t_branch;
break;
}
*inst_size = 2;
return valid;
}

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/arm/interpreter/arm_interpreter.h"
@ -38,78 +38,43 @@ ARM_Interpreter::~ARM_Interpreter() {
delete state;
}
/**
* Set the Program Counter to an address
* @param addr Address to set PC to
*/
void ARM_Interpreter::SetPC(u32 pc) {
state->pc = state->Reg[15] = pc;
}
/*
* Get the current Program Counter
* @return Returns current PC
*/
u32 ARM_Interpreter::GetPC() const {
return state->pc;
}
/**
* Get an ARM register
* @param index Register index (0-15)
* @return Returns the value in the register
*/
u32 ARM_Interpreter::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_Interpreter::SetReg(int index, u32 value) {
state->Reg[index] = value;
}
/**
* Get the current CPSR register
* @return Returns the value of the CPSR register
*/
u32 ARM_Interpreter::GetCPSR() const {
return state->Cpsr;
}
/**
* Set the current CPSR register
* @param cpsr Value to set CPSR to
*/
void ARM_Interpreter::SetCPSR(u32 cpsr) {
state->Cpsr = cpsr;
}
/**
* Returns the number of clock ticks since the last reset
* @return Returns number of clock ticks
*/
u64 ARM_Interpreter::GetTicks() const {
return ARMul_Time(state);
return state->NumInstrs;
}
void ARM_Interpreter::AddTicks(u64 ticks) {
state->NumInstrs += ticks;
}
/**
* Executes the given number of instructions
* @param num_instructions Number of instructions to executes
*/
void ARM_Interpreter::ExecuteInstructions(int num_instructions) {
state->NumInstrsToExecute = num_instructions - 1;
ARMul_Emulate32(state);
}
/**
* Saves the current CPU context
* @param ctx Thread context to save
* @todo Do we need to save Reg[15] and NextInstr?
*/
void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@ -126,11 +91,6 @@ void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
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_Interpreter::LoadContext(const ThreadContext& ctx) {
memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
@ -147,7 +107,6 @@ void ARM_Interpreter::LoadContext(const ThreadContext& ctx) {
state->NextInstr = ctx.mode;
}
/// Prepare core for thread reschedule (if needed to correctly handle state)
void ARM_Interpreter::PrepareReschedule() {
state->NumInstrsToExecute = 0;
}

View file

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
@ -60,6 +60,12 @@ public:
*/
u64 GetTicks() const override;
/**
* Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
* @param ticks Number of ticks to advance the CPU core
*/
void AddTicks(u64 ticks) override;
/**
* Saves the current CPU context
* @param ctx Thread context to save

File diff suppressed because it is too large Load diff

View file

@ -227,8 +227,9 @@ ARMul_CPSRAltered (ARMul_State * state)
//state->Cpsr &= ~CBIT;
ASSIGNV ((state->Cpsr & VBIT) != 0);
//state->Cpsr &= ~VBIT;
ASSIGNS ((state->Cpsr & SBIT) != 0);
//state->Cpsr &= ~SBIT;
ASSIGNQ ((state->Cpsr & QBIT) != 0);
//state->Cpsr &= ~QBIT;
state->GEFlag = (state->Cpsr & 0x000F0000);
#ifdef MODET
ASSIGNT ((state->Cpsr & TBIT) != 0);
//state->Cpsr &= ~TBIT;
@ -391,6 +392,15 @@ ARMul_NthReg (ARMword instr, unsigned number)
return (bit - 1);
}
/* Unsigned sum of absolute difference */
u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
{
if (left > right)
return left - right;
return right - left;
}
/* Assigns the N and Z flags depending on the value of result. */
void
@ -443,6 +453,14 @@ ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
ASSIGNV (AddOverflow (a, b, result));
}
/* Assigns the Q flag if the given result is considered an overflow from the addition of a and b */
void ARMul_AddOverflowQ(ARMul_State* state, ARMword a, ARMword b)
{
u32 result = a + b;
if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
SETQ;
}
/* Assigns the C flag after an subtraction of a and b to give result. */
void
@ -460,6 +478,142 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
ASSIGNV (SubOverflow (a, b, result));
}
/* 8-bit signed saturated addition */
u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
{
u8 result = left + right;
if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
if (left & 0x80)
result = 0x80;
else
result = 0x7F;
}
return result;
}
/* 8-bit signed saturated subtraction */
u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
{
u8 result = left - right;
if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
if (left & 0x80)
result = 0x80;
else
result = 0x7F;
}
return result;
}
/* 16-bit signed saturated addition */
u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
{
u16 result = left + right;
if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
if (left & 0x8000)
result = 0x8000;
else
result = 0x7FFF;
}
return result;
}
/* 16-bit signed saturated subtraction */
u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
{
u16 result = left - right;
if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
if (left & 0x8000)
result = 0x8000;
else
result = 0x7FFF;
}
return result;
}
/* 8-bit unsigned saturated addition */
u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
{
u8 result = left + right;
if (result < left)
result = 0xFF;
return result;
}
/* 16-bit unsigned saturated addition */
u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
{
u16 result = left + right;
if (result < left)
result = 0xFFFF;
return result;
}
/* 8-bit unsigned saturated subtraction */
u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
{
if (left <= right)
return 0;
return left - right;
}
/* 16-bit unsigned saturated subtraction */
u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
{
if (left <= right)
return 0;
return left - right;
}
// Signed saturation.
u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
{
const u32 max = (1 << shift) - 1;
const s32 top = (value >> shift);
if (top > 0) {
*saturation_occurred = true;
return max;
}
else if (top < -1) {
*saturation_occurred = true;
return ~max;
}
*saturation_occurred = false;
return (u32)value;
}
// Unsigned saturation
u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
{
const u32 max = (1 << shift) - 1;
if (value < 0) {
*saturation_occurred = true;
return 0;
} else if ((u32)value > max) {
*saturation_occurred = true;
return max;
}
*saturation_occurred = false;
return (u32)value;
}
/* This function does the work of generating the addresses used in an
LDC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
@ -665,7 +819,7 @@ ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
//if (!CP_ACCESS_ALLOWED (state, CPNum)) {
if (!state->MCR[CPNum]) {
//chy 2004-07-19 should fix in the future ????!!!!
DEBUG("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source);
LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x",CPNum, source);
ARMul_UndefInstr (state, instr);
return;
}
@ -690,7 +844,7 @@ ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
}
if (cpab == ARMul_CANT) {
DEBUG("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source); //ichfly todo
LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x", instr, CPNum, source); //ichfly todo
//ARMul_Abort (state, ARMul_UndefinedInstrV);
} else {
BUSUSEDINCPCN;
@ -762,7 +916,7 @@ ARMword ARMul_MRC (ARMul_State * state, ARMword instr)
//if (!CP_ACCESS_ALLOWED (state, CPNum)) {
if (!state->MRC[CPNum]) {
//chy 2004-07-19 should fix in the future????!!!!
DEBUG("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x", CPNum, instr);
ARMul_UndefInstr (state, instr);
return -1;
}
@ -865,7 +1019,7 @@ void
ARMul_UndefInstr (ARMul_State * state, ARMword instr)
{
std::string disasm = ARM_Disasm::Disassemble(state->pc, instr);
ERROR_LOG(ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", disasm.c_str(), instr);
LOG_ERROR(Core_ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", disasm.c_str(), instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}

View file

@ -467,7 +467,7 @@ ARMul_ThumbDecode (
(state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC;
state->Reg[14] = (tmp | 1);
CLEART;
DEBUG_LOG(ARM11, "In %s, After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
LOG_DEBUG(Core_ARM11, "After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x", state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
valid = t_branch;
FLUSHPIPE;
}

View file

@ -18,38 +18,26 @@
#ifndef _ARMDEFS_H_
#define _ARMDEFS_H_
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "common/platform.h"
//teawater add for arm2x86 2005.02.14-------------------------------------------
// koodailar remove it for mingw 2005.12.18----------------
//anthonylee modify it for portable 2007.01.30
//#include "portable/mman.h"
#include <cerrno>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "arm_regformat.h"
#include "common/common_types.h"
#include "common/platform.h"
#include "core/arm/skyeye_common/armmmu.h"
#include "core/arm/skyeye_common/skyeye_defs.h"
//AJ2D--------------------------------------------------------------------------
//teawater add for arm2x86 2005.07.03-------------------------------------------
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if EMU_PLATFORM == PLATFORM_LINUX
#include <sys/time.h>
#include <unistd.h>
#endif
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include <memory_space.h>
//AJ2D--------------------------------------------------------------------------
#if 0
#if 0
#define DIFF_STATE 1
@ -70,25 +58,8 @@
#define LOWHIGH 1
#define HIGHLOW 2
//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
#include <signal.h>
#include "common/platform.h"
#if EMU_PLATFORM == PLATFORM_LINUX
#include <sys/time.h>
#endif
//#define DBCT_TEST_SPEED
#define DBCT_TEST_SPEED_SEC 10
//AJ2D--------------------------------------------------------------------------
//teawater add compile switch for DBCT GDB RSP function 2005.10.21--------------
//#define DBCT_GDBRSP
//AJ2D--------------------------------------------------------------------------
//#include <skyeye_defs.h>
//#include <skyeye_types.h>
#define ARM_BYTE_TYPE 0
#define ARM_HALFWORD_TYPE 1
@ -103,71 +74,34 @@
typedef char *VoidStar;
#endif
typedef unsigned long long ARMdword; /* must be 64 bits wide */
typedef unsigned int ARMword; /* must be 32 bits wide */
typedef unsigned char ARMbyte; /* must be 8 bits wide */
typedef unsigned short ARMhword; /* must be 16 bits wide */
typedef u64 ARMdword; // must be 64 bits wide
typedef u32 ARMword; // must be 32 bits wide
typedef u16 ARMhword; // must be 16 bits wide
typedef u8 ARMbyte; // must be 8 bits wide
typedef struct ARMul_State ARMul_State;
typedef struct ARMul_io ARMul_io;
typedef struct ARMul_Energy ARMul_Energy;
//teawater add for arm2x86 2005.06.24-------------------------------------------
#include <stdint.h>
//AJ2D--------------------------------------------------------------------------
/*
//chy 2005-05-11
#ifndef __CYGWIN__
//teawater add for arm2x86 2005.02.14-------------------------------------------
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int u32;
#if defined (__x86_64__)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
////AJ2D--------------------------------------------------------------------------
#endif
*/
#include "core/arm/skyeye_common/armmmu.h"
//#include "lcd/skyeye_lcd.h"
//#include "skyeye.h"
//#include "skyeye_device.h"
//#include "net/skyeye_net.h"
//#include "skyeye_config.h"
typedef unsigned ARMul_CPInits (ARMul_State * state);
typedef unsigned ARMul_CPExits (ARMul_State * state);
typedef unsigned ARMul_LDCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword value);
typedef unsigned ARMul_STCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value);
typedef unsigned ARMul_MRCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value);
typedef unsigned ARMul_MCRs (ARMul_State * state, unsigned type,
ARMword instr, ARMword value);
typedef unsigned ARMul_MRRCs (ARMul_State * state, unsigned type,
ARMword instr, ARMword * value1, ARMword * value2);
typedef unsigned ARMul_MCRRs (ARMul_State * state, unsigned type,
ARMword instr, ARMword value1, ARMword value2);
typedef unsigned ARMul_CDPs (ARMul_State * state, unsigned type,
ARMword instr);
typedef unsigned ARMul_CPReads (ARMul_State * state, unsigned reg,
ARMword * value);
typedef unsigned ARMul_CPWrites (ARMul_State * state, unsigned reg,
ARMword value);
typedef unsigned ARMul_CPInits(ARMul_State* state);
typedef unsigned ARMul_CPExits(ARMul_State* state);
typedef unsigned ARMul_LDCs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
typedef unsigned ARMul_STCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
typedef unsigned ARMul_MRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
typedef unsigned ARMul_MCRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
typedef unsigned ARMul_MRRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
typedef unsigned ARMul_MCRRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
typedef unsigned ARMul_CDPs(ARMul_State* state, unsigned type, ARMword instr);
typedef unsigned ARMul_CPReads(ARMul_State* state, unsigned reg, ARMword* value);
typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value);
//added by ksh,2004-3-5
struct ARMul_io
{
ARMword *instr; //to display the current interrupt state
ARMword *net_flag; //to judge if network is enabled
ARMword *net_int; //netcard interrupt
ARMword *instr; // to display the current interrupt state
ARMword *net_flag; // to judge if network is enabled
ARMword *net_int; // netcard interrupt
//ywc,2004-04-01
ARMword *ts_int;
@ -180,17 +114,17 @@ struct ARMul_io
/* added by ksh,2004-11-26,some energy profiling */
struct ARMul_Energy
{
int energy_prof; /* <tktan> BUG200103282109 : for energy profiling */
int enable_func_energy; /* <tktan> BUG200105181702 */
int energy_prof; /* <tktan> BUG200103282109 : for energy profiling */
int enable_func_energy; /* <tktan> BUG200105181702 */
char *func_energy;
int func_display; /* <tktan> BUG200103311509 : for function call display */
int func_display; /* <tktan> BUG200103311509 : for function call display */
int func_disp_start; /* <tktan> BUG200104191428 : to start func profiling */
char *start_func; /* <tktan> BUG200104191428 */
char *start_func; /* <tktan> BUG200104191428 */
FILE *outfile; /* <tktan> BUG200105201531 : direct console to file */
FILE *outfile; /* <tktan> BUG200105201531 : direct console to file */
long long tcycle, pcycle;
float t_energy;
void *cur_task; /* <tktan> BUG200103291737 */
void *cur_task; /* <tktan> BUG200103291737 */
long long t_mem_cycle, t_idle_cycle, t_uart_cycle;
long long p_mem_cycle, p_idle_cycle, p_uart_cycle;
long long p_io_update_tcycle;
@ -203,13 +137,12 @@ struct ARMul_Energy
typedef struct mem_bank
{
ARMword (*read_byte) (ARMul_State * state, ARMword addr);
void (*write_byte) (ARMul_State * state, ARMword addr, ARMword data);
ARMword (*read_halfword) (ARMul_State * state, ARMword addr);
void (*write_halfword) (ARMul_State * state, ARMword addr,
ARMword data);
ARMword (*read_word) (ARMul_State * state, ARMword addr);
void (*write_word) (ARMul_State * state, ARMword addr, ARMword data);
ARMword (*read_byte) (ARMul_State* state, ARMword addr);
void (*write_byte) (ARMul_State* state, ARMword addr, ARMword data);
ARMword (*read_halfword) (ARMul_State* state, ARMword addr);
void (*write_halfword) (ARMul_State* state, ARMword addr, ARMword data);
ARMword (*read_word) (ARMul_State* state, ARMword addr);
void (*write_word) (ARMul_State* state, ARMword addr, ARMword data);
unsigned int addr, len;
char filename[MAX_STR];
unsigned type; //chy 2003-09-21: maybe io,ram,rom
@ -224,24 +157,24 @@ typedef struct
#define VFP_REG_NUM 64
struct ARMul_State
{
ARMword Emulate; /* to start and stop emulation */
unsigned EndCondition; /* reason for stopping */
ARMword Emulate; /* to start and stop emulation */
unsigned EndCondition; /* reason for stopping */
unsigned ErrorCode; /* type of illegal instruction */
/* Order of the following register should not be modified */
ARMword Reg[16]; /* the current register file */
ARMword Cpsr; /* the current psr */
ARMword Reg[16]; /* the current register file */
ARMword Cpsr; /* the current psr */
ARMword Spsr_copy;
ARMword phys_pc;
ARMword Reg_usr[2];
ARMword Reg_svc[2]; /* R13_SVC R14_SVC */
ARMword Reg_svc[2]; /* R13_SVC R14_SVC */
ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */
ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */
ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */
ARMword Reg_firq[7]; /* R8---R14 FIRQ */
ARMword Spsr[7]; /* the exception psr's */
ARMword Mode; /* the current mode */
ARMword Bank; /* the current register bank */
ARMword Spsr[7]; /* the exception psr's */
ARMword Mode; /* the current mode */
ARMword Bank; /* the current register bank */
ARMword exclusive_tag;
ARMword exclusive_state;
ARMword exclusive_result;
@ -265,7 +198,7 @@ struct ARMul_State
//ARMword translate_pc;
/* add armv6 flags dyf:2010-08-09 */
ARMword GEFlag, EFlag, AFlag, QFlags;
ARMword GEFlag, EFlag, AFlag, QFlag;
//chy:2003-08-19, used in arm v5e|xscale
ARMword SFlag;
#ifdef MODET
@ -281,38 +214,39 @@ struct ARMul_State
ARMword currentexaddr;
ARMword currentexval;
ARMword currentexvald;
ARMword servaddr;
unsigned NextInstr;
unsigned VectorCatch; /* caught exception mask */
unsigned CallDebug; /* set to call the debugger */
unsigned CanWatch; /* set by memory interface if its willing to suffer the
overhead of checking for watchpoints on each memory
access */
unsigned VectorCatch; /* caught exception mask */
unsigned CallDebug; /* set to call the debugger */
unsigned CanWatch; /* set by memory interface if its willing to suffer the
overhead of checking for watchpoints on each memory
access */
unsigned int StopHandle;
char *CommandLine; /* Command Line from ARMsd */
char *CommandLine; /* Command Line from ARMsd */
ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */
ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */
ARMul_LDCs *LDC[16]; /* LDC instruction */
ARMul_STCs *STC[16]; /* STC instruction */
ARMul_MRCs *MRC[16]; /* MRC instruction */
ARMul_MCRs *MCR[16]; /* MCR instruction */
ARMul_MRRCs *MRRC[16]; /* MRRC instruction */
ARMul_MCRRs *MCRR[16]; /* MCRR instruction */
ARMul_CDPs *CDP[16]; /* CDP instruction */
ARMul_CPReads *CPRead[16]; /* Read CP register */
ARMul_CPWrites *CPWrite[16]; /* Write CP register */
unsigned char *CPData[16]; /* Coprocessor data */
ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */
ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */
ARMul_LDCs *LDC[16]; /* LDC instruction */
ARMul_STCs *STC[16]; /* STC instruction */
ARMul_MRCs *MRC[16]; /* MRC instruction */
ARMul_MCRs *MCR[16]; /* MCR instruction */
ARMul_MRRCs *MRRC[16]; /* MRRC instruction */
ARMul_MCRRs *MCRR[16]; /* MCRR instruction */
ARMul_CDPs *CDP[16]; /* CDP instruction */
ARMul_CPReads *CPRead[16]; /* Read CP register */
ARMul_CPWrites *CPWrite[16]; /* Write CP register */
unsigned char *CPData[16]; /* Coprocessor data */
unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */
unsigned EventSet; /* the number of events in the queue */
unsigned int Now; /* time to the nearest cycle */
struct EventNode **EventPtr; /* the event list */
unsigned EventSet; /* the number of events in the queue */
unsigned int Now; /* time to the nearest cycle */
struct EventNode **EventPtr; /* the event list */
unsigned Debug; /* show instructions as they are executed */
unsigned NresetSig; /* reset the processor */
unsigned Debug; /* show instructions as they are executed */
unsigned NresetSig; /* reset the processor */
unsigned NfiqSig;
unsigned NirqSig;
@ -356,12 +290,12 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
*/
unsigned lateabtSig;
ARMword Vector; /* synthesize aborts in cycle modes */
ARMword Aborted; /* sticky flag for aborts */
ARMword Reseted; /* sticky flag for Reset */
ARMword Vector; /* synthesize aborts in cycle modes */
ARMword Aborted; /* sticky flag for aborts */
ARMword Reseted; /* sticky flag for Reset */
ARMword Inted, LastInted; /* sticky flags for interrupts */
ARMword Base; /* extra hand for base writeback */
ARMword AbortAddr; /* to keep track of Prefetch aborts */
ARMword Base; /* extra hand for base writeback */
ARMword AbortAddr; /* to keep track of Prefetch aborts */
const struct Dbg_HostosInterface *hostif;
@ -378,7 +312,7 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
//chy: 2003-08-11, for different arm core type
unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */
unsigned is_v5; /* Are we emulating a v5 architecture ? */
unsigned is_v5e; /* Are we emulating a v5e architecture ? */
unsigned is_v5e; /* Are we emulating a v5e architecture ? */
unsigned is_v6; /* Are we emulating a v6 architecture ? */
unsigned is_v7; /* Are we emulating a v7 architecture ? */
unsigned is_XScale; /* Are we emulating an XScale architecture ? */
@ -387,51 +321,43 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
//chy 2005-09-19
unsigned is_pxa27x; /* Are we emulating a Intel PXA27x co-processor ? */
//chy: seems only used in xscale's CP14
unsigned int LastTime; /* Value of last call to ARMul_Time() */
unsigned int LastTime; /* Value of last call to ARMul_Time() */
ARMword CP14R0_CCD; /* used to count 64 clock cycles with CP14 R0 bit 3 set */
//added by ksh:for handle different machs io 2004-3-5
//added by ksh:for handle different machs io 2004-3-5
ARMul_io mach_io;
/*added by ksh,2004-11-26,some energy profiling*/
/*added by ksh,2004-11-26,some energy profiling*/
ARMul_Energy energy;
//teawater add for next_dis 2004.10.27-----------------------
//teawater add for next_dis 2004.10.27-----------------------
int disassemble;
//AJ2D------------------------------------------
//teawater add for arm2x86 2005.02.15-------------------------------------------
//teawater add for arm2x86 2005.02.15-------------------------------------------
u32 trap;
u32 tea_break_addr;
u32 tea_break_ok;
int tea_pc;
//AJ2D--------------------------------------------------------------------------
//teawater add for arm2x86 2005.07.03-------------------------------------------
/*
* 2007-01-24 removed the term-io functions by Anthony Lee,
* moved to "device/uart/skyeye_uart_stdio.c".
*/
//AJ2D--------------------------------------------------------------------------
//teawater add for arm2x86 2005.07.05-------------------------------------------
//teawater add for arm2x86 2005.07.05-------------------------------------------
//arm_arm A2-18
int abort_model; //0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
//AJ2D--------------------------------------------------------------------------
//teawater change for return if running tb dirty 2005.07.09---------------------
//teawater change for return if running tb dirty 2005.07.09---------------------
void *tb_now;
//AJ2D--------------------------------------------------------------------------
//teawater add for record reg value to ./reg.txt 2005.07.10---------------------
//teawater add for record reg value to ./reg.txt 2005.07.10---------------------
FILE *tea_reg_fd;
//AJ2D--------------------------------------------------------------------------
/*added by ksh in 2005-10-1*/
/*added by ksh in 2005-10-1*/
cpu_config_t *cpu;
//mem_config_t *mem_bank;
/* added LPC remap function */
/* added LPC remap function */
int vector_remap_flag;
u32 vector_remap_addr;
u32 vector_remap_size;
@ -486,17 +412,14 @@ typedef ARMul_State arm_core_t;
#define ARM_Debug_Prop 0x10
#define ARM_Isync_Prop ARM_Debug_Prop
#define ARM_Lock_Prop 0x20
//chy 2003-08-11
#define ARM_v4_Prop 0x40
#define ARM_v5_Prop 0x80
/*jeff.du 2010-08-05 */
#define ARM_v6_Prop 0xc0
#define ARM_v5e_Prop 0x100
#define ARM_XScale_Prop 0x200
#define ARM_ep9312_Prop 0x400
#define ARM_iWMMXt_Prop 0x800
//chy 2005-09-19
#define ARM_PXA27X_Prop 0x1000
#define ARM_v7_Prop 0x2000
@ -591,47 +514,44 @@ typedef ARMul_State arm_core_t;
#ifdef __cplusplus
extern "C" {
#endif
extern void ARMul_EmulateInit (void);
extern void ARMul_Reset (ARMul_State * state);
extern void ARMul_EmulateInit();
extern void ARMul_Reset(ARMul_State* state);
#ifdef __cplusplus
}
#endif
extern ARMul_State *ARMul_NewState (ARMul_State * state);
extern ARMword ARMul_DoProg (ARMul_State * state);
extern ARMword ARMul_DoInstr (ARMul_State * state);
extern ARMul_State *ARMul_NewState(ARMul_State* state);
extern ARMword ARMul_DoProg(ARMul_State* state);
extern ARMword ARMul_DoInstr(ARMul_State* state);
/***************************************************************************\
* Definitons of things for event handling *
\***************************************************************************/
extern void ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
unsigned (*func) ());
extern void ARMul_EnvokeEvent (ARMul_State * state);
extern unsigned int ARMul_Time (ARMul_State * state);
extern void ARMul_ScheduleEvent(ARMul_State* state, unsigned int delay, unsigned(*func) ());
extern void ARMul_EnvokeEvent(ARMul_State* state);
extern unsigned int ARMul_Time(ARMul_State* state);
/***************************************************************************\
* Useful support routines *
\***************************************************************************/
extern ARMword ARMul_GetReg (ARMul_State * state, unsigned mode,
unsigned reg);
extern void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
ARMword value);
extern ARMword ARMul_GetPC (ARMul_State * state);
extern ARMword ARMul_GetNextPC (ARMul_State * state);
extern void ARMul_SetPC (ARMul_State * state, ARMword value);
extern ARMword ARMul_GetR15 (ARMul_State * state);
extern void ARMul_SetR15 (ARMul_State * state, ARMword value);
extern ARMword ARMul_GetReg (ARMul_State* state, unsigned mode, unsigned reg);
extern void ARMul_SetReg (ARMul_State* state, unsigned mode, unsigned reg, ARMword value);
extern ARMword ARMul_GetPC(ARMul_State* state);
extern ARMword ARMul_GetNextPC(ARMul_State* state);
extern void ARMul_SetPC(ARMul_State* state, ARMword value);
extern ARMword ARMul_GetR15(ARMul_State* state);
extern void ARMul_SetR15(ARMul_State* state, ARMword value);
extern ARMword ARMul_GetCPSR (ARMul_State * state);
extern void ARMul_SetCPSR (ARMul_State * state, ARMword value);
extern ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
extern void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
extern ARMword ARMul_GetCPSR(ARMul_State* state);
extern void ARMul_SetCPSR(ARMul_State* state, ARMword value);
extern ARMword ARMul_GetSPSR(ARMul_State* state, ARMword mode);
extern void ARMul_SetSPSR(ARMul_State* state, ARMword mode, ARMword value);
/***************************************************************************\
* Definitons of things to handle aborts *
\***************************************************************************/
extern void ARMul_Abort (ARMul_State * state, ARMword address);
extern void ARMul_Abort(ARMul_State* state, ARMword address);
#ifdef MODET
#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */
#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
@ -649,54 +569,40 @@ extern void ARMul_Abort (ARMul_State * state, ARMword address);
* Definitons of things in the memory interface *
\***************************************************************************/
extern unsigned ARMul_MemoryInit (ARMul_State * state,
unsigned int initmemsize);
extern void ARMul_MemoryExit (ARMul_State * state);
extern unsigned ARMul_MemoryInit(ARMul_State* state, unsigned int initmemsize);
extern void ARMul_MemoryExit(ARMul_State* state);
extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address,
ARMword isize);
extern ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address,
ARMword isize);
extern ARMword ARMul_LoadInstrS(ARMul_State* state, ARMword address, ARMword isize);
extern ARMword ARMul_LoadInstrN(ARMul_State* state, ARMword address, ARMword isize);
#ifdef __cplusplus
extern "C" {
#endif
extern ARMword ARMul_ReLoadInstr (ARMul_State * state, ARMword address,
ARMword isize);
extern ARMword ARMul_ReLoadInstr(ARMul_State* state, ARMword address, ARMword isize);
#ifdef __cplusplus
}
#endif
extern ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadByte (ARMul_State * state, ARMword address);
extern ARMword ARMul_LoadWordS(ARMul_State* state, ARMword address);
extern ARMword ARMul_LoadWordN(ARMul_State* state, ARMword address);
extern ARMword ARMul_LoadHalfWord(ARMul_State* state, ARMword address);
extern ARMword ARMul_LoadByte(ARMul_State* state, ARMword address);
extern void ARMul_StoreWordS (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreWordN (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreHalfWord (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreByte (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_StoreWordS(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_StoreWordN(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_StoreHalfWord(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_StoreByte(ARMul_State* state, ARMword address, ARMword data);
extern ARMword ARMul_SwapWord (ARMul_State * state, ARMword address,
ARMword data);
extern ARMword ARMul_SwapByte (ARMul_State * state, ARMword address,
ARMword data);
extern ARMword ARMul_SwapWord(ARMul_State* state, ARMword address, ARMword data);
extern ARMword ARMul_SwapByte(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_Icycles (ARMul_State * state, unsigned number,
ARMword address);
extern void ARMul_Ccycles (ARMul_State * state, unsigned number,
ARMword address);
extern void ARMul_Icycles(ARMul_State* state, unsigned number, ARMword address);
extern void ARMul_Ccycles(ARMul_State* state, unsigned number, ARMword address);
extern ARMword ARMul_ReadWord (ARMul_State * state, ARMword address);
extern ARMword ARMul_ReadByte (ARMul_State * state, ARMword address);
extern void ARMul_WriteWord (ARMul_State * state, ARMword address,
ARMword data);
extern void ARMul_WriteByte (ARMul_State * state, ARMword address,
ARMword data);
extern ARMword ARMul_ReadWord(ARMul_State* state, ARMword address);
extern ARMword ARMul_ReadByte(ARMul_State* state, ARMword address);
extern void ARMul_WriteWord(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_WriteByte(ARMul_State* state, ARMword address, ARMword data);
extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,
extern ARMword ARMul_MemAccess(ARMul_State* state, ARMword, ARMword,
ARMword, ARMword, ARMword, ARMword, ARMword,
ARMword, ARMword, ARMword);
@ -739,66 +645,40 @@ extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,
#define ARMul_CP15_DBCON_E1 0x000c
#define ARMul_CP15_DBCON_E0 0x0003
extern unsigned ARMul_CoProInit (ARMul_State * state);
extern void ARMul_CoProExit (ARMul_State * state);
extern void ARMul_CoProAttach (ARMul_State * state, unsigned number,
ARMul_CPInits * init, ARMul_CPExits * exit,
ARMul_LDCs * ldc, ARMul_STCs * stc,
ARMul_MRCs * mrc, ARMul_MCRs * mcr,
ARMul_MRRCs * mrrc, ARMul_MCRRs * mcrr,
ARMul_CDPs * cdp,
ARMul_CPReads * read, ARMul_CPWrites * write);
extern void ARMul_CoProDetach (ARMul_State * state, unsigned number);
extern unsigned ARMul_CoProInit(ARMul_State* state);
extern void ARMul_CoProExit(ARMul_State* state);
extern void ARMul_CoProAttach (ARMul_State* state, unsigned number,
ARMul_CPInits* init, ARMul_CPExits* exit,
ARMul_LDCs* ldc, ARMul_STCs* stc,
ARMul_MRCs* mrc, ARMul_MCRs* mcr,
ARMul_MRRCs* mrrc, ARMul_MCRRs* mcrr,
ARMul_CDPs* cdp,
ARMul_CPReads* read, ARMul_CPWrites* write);
extern void ARMul_CoProDetach(ARMul_State* state, unsigned number);
/***************************************************************************\
* Definitons of things in the host environment *
\***************************************************************************/
extern unsigned ARMul_OSInit (ARMul_State * state);
extern void ARMul_OSExit (ARMul_State * state);
extern unsigned ARMul_OSInit(ARMul_State* state);
extern void ARMul_OSExit(ARMul_State* state);
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
extern unsigned ARMul_OSHandleSWI(ARMul_State* state, ARMword number);
#ifdef __cplusplus
}
#endif
extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
extern ARMword ARMul_OSLastErrorP(ARMul_State* state);
extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,
ARMword pc);
extern ARMword ARMul_Debug(ARMul_State* state, ARMword pc, ARMword instr);
extern unsigned ARMul_OSException(ARMul_State* state, ARMword vector, ARMword pc);
extern int rdi_log;
/***************************************************************************\
* Host-dependent stuff *
\***************************************************************************/
#ifdef macintosh
pascal void SpinCursor (short increment); /* copied from CursorCtl.h */
# define HOURGLASS SpinCursor( 1 )
# define HOURGLASS_RATE 1023 /* 2^n - 1 */
#endif
//teawater add for arm2x86 2005.02.14-------------------------------------------
/*ywc 2005-03-31*/
/*
#include "arm2x86.h"
#include "arm2x86_dp.h"
#include "arm2x86_movl.h"
#include "arm2x86_psr.h"
#include "arm2x86_shift.h"
#include "arm2x86_mem.h"
#include "arm2x86_mul.h"
#include "arm2x86_test.h"
#include "arm2x86_other.h"
#include "list.h"
#include "tb.h"
*/
enum ConditionCode {
EQ = 0,
NE = 1,
@ -851,32 +731,16 @@ enum ConditionCode {
#define ZBIT_SHIFT 30
#define CBIT_SHIFT 29
#define VBIT_SHIFT 28
#ifdef DBCT
//teawater change for local tb branch directly jump 2005.10.18------------------
#include "dbct/list.h"
#include "dbct/arm2x86.h"
#include "dbct/arm2x86_dp.h"
#include "dbct/arm2x86_movl.h"
#include "dbct/arm2x86_psr.h"
#include "dbct/arm2x86_shift.h"
#include "dbct/arm2x86_mem.h"
#include "dbct/arm2x86_mul.h"
#include "dbct/arm2x86_test.h"
#include "dbct/arm2x86_other.h"
#include "dbct/arm2x86_coproc.h"
#include "dbct/tb.h"
#endif
//AJ2D--------------------------------------------------------------------------
//AJ2D--------------------------------------------------------------------------
#define SKYEYE_OUTREGS(fd) { fprintf ((fd), "R %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,C %x,S %x,%x,%x,%x,%x,%x,%x,M %x,B %x,E %x,I %x,P %x,T %x,L %x,D %x,",\
state->Reg[0],state->Reg[1],state->Reg[2],state->Reg[3], \
state->Reg[4],state->Reg[5],state->Reg[6],state->Reg[7], \
state->Reg[8],state->Reg[9],state->Reg[10],state->Reg[11], \
state->Reg[12],state->Reg[13],state->Reg[14],state->Reg[15], \
state->Cpsr, state->Spsr[0], state->Spsr[1], state->Spsr[2],\
state->Cpsr, state->Spsr[0], state->Spsr[1], state->Spsr[2],\
state->Spsr[3],state->Spsr[4], state->Spsr[5], state->Spsr[6],\
state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\
state->temp,state->loaded,state->decoded);}
state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\
state->temp,state->loaded,state->decoded);}
#define SKYEYE_OUTMOREREGS(fd) { fprintf ((fd),"\
RUs %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
@ -914,17 +778,30 @@ RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\
#define SA1110 0x6901b110
#define SA1100 0x4401a100
#define PXA250 0x69052100
#define PXA270 0x69054110
//#define PXA250 0x69052903
#define PXA250 0x69052100
#define PXA270 0x69054110
//#define PXA250 0x69052903
// 0x69052903; //PXA250 B1 from intel 278522-001.pdf
extern void ARMul_UndefInstr (ARMul_State *, ARMword);
extern void ARMul_FixCPSR (ARMul_State *, ARMword, ARMword);
extern void ARMul_FixSPSR (ARMul_State *, ARMword, ARMword);
extern void ARMul_ConsolePrint (ARMul_State *, const char *, ...);
extern void ARMul_SelectProcessor (ARMul_State *, unsigned);
extern void ARMul_UndefInstr(ARMul_State*, ARMword);
extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword);
extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
extern u8 ARMul_SignedSaturatedSub8(u8, u8);
extern u16 ARMul_SignedSaturatedAdd16(u16, u16);
extern u16 ARMul_SignedSaturatedSub16(u16, u16);
extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
extern u8 ARMul_UnsignedSaturatedSub8(u8, u8);
extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
extern u32 ARMul_SignedSatQ(s32, u8, bool*);
extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
#define DIFF_LOG 0
#define SAVE_LOG 0

View file

@ -23,8 +23,6 @@
//extern ARMword isize;
#define DEBUG(...) DEBUG_LOG(ARM11, __VA_ARGS__)
/* Shift Opcodes. */
#define LSL 0
#define LSR 1
@ -36,7 +34,7 @@
#define ZBIT (1L << 30)
#define CBIT (1L << 29)
#define VBIT (1L << 28)
#define SBIT (1L << 27)
#define QBIT (1L << 27)
#define IBIT (1L << 7)
#define FBIT (1L << 6)
#define IFBITS (3L << 6)
@ -158,13 +156,14 @@
#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
#define R15MODE (state->Reg[15] & R15MODEBITS)
#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27))
#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (QFLAG << 27))
#define EINT (IFFLAGS << 6)
#define ER15INT (IFFLAGS << 26)
#define EMODE (state->Mode)
#define EGEBITS (state->GEFlag & 0x000F0000)
#ifdef MODET
#define CPSR (ECC | EINT | EMODE | (TFLAG << 5))
#define CPSR (ECC | EGEBITS | (EFLAG << 9) | (AFLAG << 8) | EINT | (TFLAG << 5) | EMODE)
#else
#define CPSR (ECC | EINT | EMODE)
#endif
@ -485,7 +484,7 @@ tdstate;
* out-of-updated with the newer ISA.
* -- Michael.Kang
********************************************************************************/
#define UNDEF_WARNING WARN_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n");
#define UNDEF_WARNING LOG_WARNING(Core_ARM11, "undefined or unpredicted behavior for arm instruction.");
/* Macros to scrutinize instructions. */
#define UNDEF_Test UNDEF_WARNING
@ -603,6 +602,7 @@ extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword);
extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);

View file

@ -32,8 +32,7 @@
//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
unsigned
VFPInit (ARMul_State *state)
unsigned VFPInit(ARMul_State* state)
{
state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
@ -46,8 +45,7 @@ VFPInit (ARMul_State *state)
return 0;
}
unsigned
VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
{
/* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -61,10 +59,21 @@ VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
/* CRn/opc1 CRm/opc2 */
if (CoProc == 10 || CoProc == 11) {
#define VFP_MRC_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRC_TRANS
if (CoProc == 10 || CoProc == 11)
{
if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
{
/* VMOV r to s */
/* Transfering Rt is not mandatory, as the value of interest is pointed by value */
VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, value);
return ARMul_DONE;
}
if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
{
VMRS(state, CRn, Rt, value);
return ARMul_DONE;
}
}
DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
@ -72,8 +81,7 @@ VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
return ARMul_CANT;
}
unsigned
VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
{
/* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -86,10 +94,33 @@ VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
/* TODO check access permission */
/* CRn/opc1 CRm/opc2 */
if (CoProc == 10 || CoProc == 11) {
#define VFP_MCR_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCR_TRANS
if (CoProc == 10 || CoProc == 11)
{
if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
{
/* VMOV s to r */
/* Transfering Rt is not mandatory, as the value of interest is pointed by value */
VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, &value);
return ARMul_DONE;
}
if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
{
VMSR(state, CRn, Rt);
return ARMul_DONE;
}
if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
{
VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
return ARMul_DONE;
}
if (CoProc == 11 && CRm == 0)
{
VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
return ARMul_DONE;
}
}
DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
@ -97,8 +128,7 @@ VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
return ARMul_CANT;
}
unsigned
VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * value2)
unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
{
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -107,10 +137,20 @@ VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * valu
int Rt2 = BITS (16, 19);
int CRm = BITS (0, 3);
if (CoProc == 10 || CoProc == 11) {
#define VFP_MRRC_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRRC_TRANS
if (CoProc == 10 || CoProc == 11)
{
if (CoProc == 10 && (OPC_1 & 0xD) == 1)
{
VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
return ARMul_DONE;
}
if (CoProc == 11 && (OPC_1 & 0xD) == 1)
{
/* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2);
return ARMul_DONE;
}
}
DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
instr, CoProc, OPC_1, Rt, Rt2, CRm);
@ -118,8 +158,7 @@ VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * valu
return ARMul_CANT;
}
unsigned
VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
{
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -132,10 +171,20 @@ VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
/* CRn/opc1 CRm/opc2 */
if (CoProc == 11 || CoProc == 10) {
#define VFP_MCRR_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCRR_TRANS
if (CoProc == 11 || CoProc == 10)
{
if (CoProc == 10 && (OPC_1 & 0xD) == 1)
{
VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
return ARMul_DONE;
}
if (CoProc == 11 && (OPC_1 & 0xD) == 1)
{
/* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2);
return ARMul_DONE;
}
}
DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
instr, CoProc, OPC_1, Rt, Rt2, CRm);
@ -143,8 +192,7 @@ VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
return ARMul_CANT;
}
unsigned
VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
{
/* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -175,9 +223,17 @@ VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
}
#endif
#define VFP_STC_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_STC_TRANS
if (P == 1 && W == 0)
{
return VSTR(state, type, instr, value);
}
if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
{
return VPUSH(state, type, instr, value);
}
return VSTM(state, type, instr, value);
}
DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
instr, CoProc, CRd, Rn, imm8, P, U, D, W);
@ -185,8 +241,7 @@ VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
return ARMul_CANT;
}
unsigned
VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
{
/* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -204,10 +259,19 @@ VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
DEBUG("In %s, UNDEFINED\n", __FUNCTION__);
exit(-1);
}
if (CoProc == 10 || CoProc == 11) {
#define VFP_LDC_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_LDC_TRANS
if (CoProc == 10 || CoProc == 11)
{
if (P == 1 && W == 0)
{
return VLDR(state, type, instr, value);
}
if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
{
return VPOP(state, type, instr, value);
}
return VLDM(state, type, instr, value);
}
DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
instr, CoProc, CRd, Rn, imm8, P, U, D, W);
@ -215,8 +279,7 @@ VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
return ARMul_CANT;
}
unsigned
VFPCDP (ARMul_State * state, unsigned type, u32 instr)
unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
{
/* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
int CoProc = BITS (8, 11); /* 10 or 11 */
@ -275,10 +338,83 @@ VFPCDP (ARMul_State * state, unsigned type, u32 instr)
/* CRn/opc1 CRm/opc2 */
if (CoProc == 10 || CoProc == 11) {
#define VFP_CDP_TRANS
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_CDP_TRANS
if (CoProc == 10 || CoProc == 11)
{
if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 0)
DBG("VMLA :\n");
if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 2)
DBG("VMLS :\n");
if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 2)
DBG("VNMLA :\n");
if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 0)
DBG("VNMLS :\n");
if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 2)
DBG("VNMUL :\n");
if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 0)
DBG("VMUL :\n");
if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 0)
DBG("VADD :\n");
if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 2)
DBG("VSUB :\n");
if ((OPC_1 & 0xB) == 0xA && (OPC_2 & 0x2) == 0)
DBG("VDIV :\n");
if ((OPC_1 & 0xB) == 0xB && BITS(4, 7) == 0)
{
unsigned int single = BIT(8) == 0;
unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
unsigned int imm;
instr = BITS(16, 19) << 4 | BITS(0, 3); /* FIXME dirty workaround to get a correct imm */
if (single)
imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0x1f : 0)<<25 | BITS(0, 5)<<19;
else
imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0xff : 0)<<22 | BITS(0, 5)<<16;
VMOVI(state, single, d, imm);
return ARMul_DONE;
}
if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
{
unsigned int single = BIT(8) == 0;
unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
unsigned int m = (single ? BITS( 0, 3)<<1 | BIT( 5) : BITS( 0, 3) | BIT( 5)<<4);;
VMOVR(state, single, d, m);
return ARMul_DONE;
}
if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x7) == 6)
DBG("VABS :\n");
if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 2)
DBG("VNEG :\n");
if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 6)
DBG("VSQRT :\n");
if ((OPC_1 & 0xB) == 0xB && CRn == 4 && (OPC_2 & 0x2) == 2)
DBG("VCMP(1) :\n");
if ((OPC_1 & 0xB) == 0xB && CRn == 5 && (OPC_2 & 0x2) == 2 && CRm == 0)
DBG("VCMP(2) :\n");
if ((OPC_1 & 0xB) == 0xB && CRn == 7 && (OPC_2 & 0x6) == 6)
DBG("VCVT(BDS) :\n");
if ((OPC_1 & 0xB) == 0xB && CRn >= 0xA && (OPC_2 & 0x2) == 2)
DBG("VCVT(BFF) :\n");
if ((OPC_1 & 0xB) == 0xB && CRn > 7 && (OPC_2 & 0x2) == 2)
DBG("VCVT(BFI) :\n");
int exceptions = 0;
if (CoProc == 10)
@ -296,23 +432,93 @@ VFPCDP (ARMul_State * state, unsigned type, u32 instr)
/* ----------- MRC ------------ */
#define VFP_MRC_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRC_IMPL
#define VFP_MRRC_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MRRC_IMPL
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
{
DBG("VMOV(BRS) :\n");
if (to_arm)
{
DBG("\tr%d <= s%d=[%x]\n", t, n, state->ExtReg[n]);
*value = state->ExtReg[n];
}
else
{
DBG("\ts%d <= r%d=[%x]\n", n, t, *value);
state->ExtReg[n] = *value;
}
}
void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value)
{
DBG("VMRS :");
if (reg == 1)
{
if (Rt != 15)
{
*value = state->VFP[VFP_OFFSET(VFP_FPSCR)];
DBG("\tr%d <= fpscr[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
}
else
{
*value = state->VFP[VFP_OFFSET(VFP_FPSCR)] ;
DBG("\tflags <= fpscr[%1xxxxxxxx]\n", state->VFP[VFP_OFFSET(VFP_FPSCR)]>>28);
}
}
else
{
switch (reg)
{
case 0:
*value = state->VFP[VFP_OFFSET(VFP_FPSID)];
DBG("\tr%d <= fpsid[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSID)]);
break;
case 6:
/* MVFR1, VFPv3 only ? */
DBG("\tr%d <= MVFR1 unimplemented\n", Rt);
break;
case 7:
/* MVFR0, VFPv3 only? */
DBG("\tr%d <= MVFR0 unimplemented\n", Rt);
break;
case 8:
*value = state->VFP[VFP_OFFSET(VFP_FPEXC)];
DBG("\tr%d <= fpexc[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPEXC)]);
break;
default:
DBG("\tSUBARCHITECTURE DEFINED\n");
break;
}
}
}
void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2)
{
DBG("VMOV(BRRD) :\n");
if (to_arm)
{
DBG("\tr[%d-%d] <= s[%d-%d]=[%x-%x]\n", t2, t, n*2+1, n*2, state->ExtReg[n*2+1], state->ExtReg[n*2]);
*value2 = state->ExtReg[n*2+1];
*value1 = state->ExtReg[n*2];
}
else
{
DBG("\ts[%d-%d] <= r[%d-%d]=[%x-%x]\n", n*2+1, n*2, t2, t, *value2, *value1);
state->ExtReg[n*2+1] = *value2;
state->ExtReg[n*2] = *value1;
}
}
/* ----------- MCR ------------ */
#define VFP_MCR_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCR_IMPL
#define VFP_MCRR_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_MCRR_IMPL
void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
{
if (reg == 1)
{
DBG("VMSR :\tfpscr <= r%d=[%x]\n", Rt, state->Reg[Rt]);
state->VFP[VFP_OFFSET(VFP_FPSCR)] = state->Reg[Rt];
}
else if (reg == 8)
{
DBG("VMSR :\tfpexc <= r%d=[%x]\n", Rt, state->Reg[Rt]);
state->VFP[VFP_OFFSET(VFP_FPEXC)] = state->Reg[Rt];
}
}
/* Memory operation are not inlined, as old Interpreter and Fast interpreter
don't have the same memory operation interface.
@ -322,21 +528,342 @@ VFPCDP (ARMul_State * state, unsigned type, u32 instr)
of vfp instructions in old interpreter and fast interpreter are separate. */
/* ----------- STC ------------ */
#define VFP_STC_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_STC_IMPL
int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
{
static int i = 0;
static int single_reg, add, d, n, imm32, regs;
if (type == ARMul_FIRST)
{
single_reg = BIT(8) == 0; /* Double precision */
add = BIT(23); /* */
imm32 = BITS(0,7)<<2; /* may not be used */
d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
n = BITS(16, 19); /* destination register */
DBG("VSTR :\n");
i = 0;
regs = 1;
return ARMul_DONE;
}
else if (type == ARMul_DATA)
{
if (single_reg)
{
*value = state->ExtReg[d+i];
DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d+i]);
i++;
if (i < regs)
return ARMul_INC;
else
return ARMul_DONE;
}
else
{
/* FIXME Careful of endianness, may need to rework this */
*value = state->ExtReg[d*2+i];
DBG("\taddr[?] <= s[%d]=[%x]\n", d*2+i, state->ExtReg[d*2+i]);
i++;
if (i < regs*2)
return ARMul_INC;
else
return ARMul_DONE;
}
}
return -1;
}
int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
{
static int i = 0;
static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST)
{
single_regs = BIT(8) == 0; /* Single precision */
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
imm32 = BITS(0,7)<<2; /* may not be used */
regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FSTMX if regs is odd */
DBG("VPUSH :\n");
DBG("\tsp[%x]", state->Reg[R13]);
state->Reg[R13] = state->Reg[R13] - imm32;
DBG("=>[%x]\n", state->Reg[R13]);
i = 0;
return ARMul_DONE;
}
else if (type == ARMul_DATA)
{
if (single_regs)
{
*value = state->ExtReg[d + i];
DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
i++;
if (i < regs)
return ARMul_INC;
else
return ARMul_DONE;
}
else
{
/* FIXME Careful of endianness, may need to rework this */
*value = state->ExtReg[d*2 + i];
DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
i++;
if (i < regs*2)
return ARMul_INC;
else
return ARMul_DONE;
}
}
return -1;
}
int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
{
static int i = 0;
static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST)
{
single_regs = BIT(8) == 0; /* Single precision */
add = BIT(23); /* */
wback = BIT(21); /* write-back */
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
n = BITS(16, 19); /* destination register */
imm32 = BITS(0,7) * 4; /* may not be used */
regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FSTMX if regs is odd */
DBG("VSTM :\n");
if (wback) {
state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
DBG("\twback r%d[%x]\n", n, state->Reg[n]);
}
i = 0;
return ARMul_DONE;
}
else if (type == ARMul_DATA)
{
if (single_regs)
{
*value = state->ExtReg[d + i];
DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
i++;
if (i < regs)
return ARMul_INC;
else
return ARMul_DONE;
}
else
{
/* FIXME Careful of endianness, may need to rework this */
*value = state->ExtReg[d*2 + i];
DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
i++;
if (i < regs*2)
return ARMul_INC;
else
return ARMul_DONE;
}
}
return -1;
}
/* ----------- LDC ------------ */
#define VFP_LDC_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_LDC_IMPL
int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
{
static int i = 0;
static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST)
{
single_regs = BIT(8) == 0; /* Single precision */
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
imm32 = BITS(0,7)<<2; /* may not be used */
regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FLDMX if regs is odd */
DBG("VPOP :\n");
DBG("\tsp[%x]", state->Reg[R13]);
state->Reg[R13] = state->Reg[R13] + imm32;
DBG("=>[%x]\n", state->Reg[R13]);
i = 0;
return ARMul_DONE;
}
else if (type == ARMul_TRANSFER)
{
return ARMul_DONE;
}
else if (type == ARMul_DATA)
{
if (single_regs)
{
state->ExtReg[d + i] = value;
DBG("\ts%d <= [%x]\n", d + i, value);
i++;
if (i < regs)
return ARMul_INC;
else
return ARMul_DONE;
}
else
{
/* FIXME Careful of endianness, may need to rework this */
state->ExtReg[d*2 + i] = value;
DBG("\ts%d <= [%x]\n", d*2 + i, value);
i++;
if (i < regs*2)
return ARMul_INC;
else
return ARMul_DONE;
}
}
return -1;
}
int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
{
static int i = 0;
static int single_reg, add, d, n, imm32, regs;
if (type == ARMul_FIRST)
{
single_reg = BIT(8) == 0; /* Double precision */
add = BIT(23); /* */
imm32 = BITS(0,7)<<2; /* may not be used */
d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
n = BITS(16, 19); /* destination register */
DBG("VLDR :\n");
i = 0;
regs = 1;
return ARMul_DONE;
}
else if (type == ARMul_TRANSFER)
{
return ARMul_DONE;
}
else if (type == ARMul_DATA)
{
if (single_reg)
{
state->ExtReg[d+i] = value;
DBG("\ts%d <= [%x]\n", d+i, value);
i++;
if (i < regs)
return ARMul_INC;
else
return ARMul_DONE;
}
else
{
/* FIXME Careful of endianness, may need to rework this */
state->ExtReg[d*2+i] = value;
DBG("\ts[%d] <= [%x]\n", d*2+i, value);
i++;
if (i < regs*2)
return ARMul_INC;
else
return ARMul_DONE;
}
}
return -1;
}
int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
{
static int i = 0;
static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST)
{
single_regs = BIT(8) == 0; /* Single precision */
add = BIT(23); /* */
wback = BIT(21); /* write-back */
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
n = BITS(16, 19); /* destination register */
imm32 = BITS(0,7) * 4; /* may not be used */
regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FLDMX if regs is odd */
DBG("VLDM :\n");
if (wback) {
state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
DBG("\twback r%d[%x]\n", n, state->Reg[n]);
}
i = 0;
return ARMul_DONE;
}
else if (type == ARMul_DATA)
{
if (single_regs)
{
state->ExtReg[d + i] = value;
DBG("\ts%d <= [%x] addr[?]\n", d+i, state->ExtReg[d + i]);
i++;
if (i < regs)
return ARMul_INC;
else
return ARMul_DONE;
}
else
{
/* FIXME Careful of endianness, may need to rework this */
state->ExtReg[d*2 + i] = value;
DBG("\ts[%d] <= [%x] addr[?]\n", d*2 + i, state->ExtReg[d*2 + i]);
i++;
if (i < regs*2)
return ARMul_INC;
else
return ARMul_DONE;
}
}
return -1;
}
/* ----------- CDP ------------ */
#define VFP_CDP_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_CDP_IMPL
void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
{
DBG("VMOV(I) :\n");
if (single)
{
DBG("\ts%d <= [%x]\n", d, imm);
state->ExtReg[d] = imm;
}
else
{
/* Check endian please */
DBG("\ts[%d-%d] <= [%x-%x]\n", d*2+1, d*2, imm, 0);
state->ExtReg[d*2+1] = imm;
state->ExtReg[d*2] = 0;
}
}
void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m)
{
DBG("VMOV(R) :\n");
if (single)
{
DBG("\ts%d <= s%d[%x]\n", d, m, state->ExtReg[m]);
state->ExtReg[d] = state->ExtReg[m];
}
else
{
/* Check endian please */
DBG("\ts[%d-%d] <= s[%d-%d][%x-%x]\n", d*2+1, d*2, m*2+1, m*2, state->ExtReg[m*2+1], state->ExtReg[m*2]);
state->ExtReg[d*2+1] = state->ExtReg[m*2+1];
state->ExtReg[d*2] = state->ExtReg[m*2];
}
}
/* Miscellaneous functions */
int32_t vfp_get_float(arm_core_t* state, unsigned int reg)
@ -366,8 +893,6 @@ void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
state->ExtReg[reg*2+1] = (uint32_t) (val>>32);
}
/*
* Process bitmask of exception conditions. (from vfpmodule.c)
*/

View file

@ -27,6 +27,12 @@
#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
#define VFP_DEBUG_TRANSLATE DBG("in func %s, %x\n", __FUNCTION__, inst);
#define VFP_DEBUG_UNIMPLEMENTED(x) printf("in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
#define VFP_DEBUG_UNTESTED(x) printf("in func %s, " #x " untested\n", __FUNCTION__);
#define CHECK_VFP_ENABLED
#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);}
unsigned VFPInit (ARMul_State *state);
unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
unsigned VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value);

File diff suppressed because it is too large Load diff

View file

@ -522,8 +522,7 @@ static s64 vfp_single_to_doubleintern(ARMul_State* state, s32 m, u32 fpscr) //ic
if (tm == VFP_QNAN)
vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
goto pack_nan;
}
else if (tm & VFP_ZERO)
} else if (tm & VFP_ZERO)
vdd.exponent = 0;
else
vdd.exponent = vsm.exponent + (1023 - 127);
@ -615,12 +614,12 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
exceptions |= FPSCR_IDC;
if (tm & VFP_NAN)
vsm.sign = 0;
vsm.sign = 1;
if (vsm.exponent >= 127 + 32) {
d = vsm.sign ? 0 : 0xffffffff;
exceptions = FPSCR_IOC;
} else if (vsm.exponent >= 127 - 1) {
} else if (vsm.exponent >= 127) {
int shift = 127 + 31 - vsm.exponent;
u32 rem, incr = 0;
@ -705,7 +704,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
if (vsm.sign)
d = ~d;
exceptions |= FPSCR_IOC;
} else if (vsm.exponent >= 127 - 1) {
} else if (vsm.exponent >= 127) {
int shift = 127 + 31 - vsm.exponent;
u32 rem, incr = 0;
@ -1149,7 +1148,10 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
/*
* Subtraction is addition with one sign inverted.
*/
return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr);
if (m != 0x7FC00000) // Only negate if m isn't NaN.
m = vfp_single_packed_negate(m);
return vfp_single_fadd(state, sd, sn, m, fpscr);
}
/*