mirror of
				https://github.com/yuzu-emu/yuzu.git
				synced 2025-11-04 08:33:43 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into issue-7-fix
This commit is contained in:
		
						commit
						b8c8d0903e
					
				@ -23,6 +23,7 @@
 | 
			
		||||
#include "core/system.h"
 | 
			
		||||
#include "core/loader.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/arm/disassembler/load_symbol_map.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -74,6 +75,7 @@ GMainWindow::GMainWindow()
 | 
			
		||||
 | 
			
		||||
    // Setup connections
 | 
			
		||||
    connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()));
 | 
			
		||||
    connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap()));
 | 
			
		||||
    connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame()));
 | 
			
		||||
    connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame()));
 | 
			
		||||
    connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame()));
 | 
			
		||||
@ -140,11 +142,17 @@ void GMainWindow::BootGame(const char* filename)
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnMenuLoadFile()
 | 
			
		||||
{
 | 
			
		||||
    QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS homebrew (*.elf *.dat)"));
 | 
			
		||||
    QString filename = QFileDialog::getOpenFileName(this, tr("Load file"), QString(), tr("3DS homebrew (*.elf *.dat *.bin)"));
 | 
			
		||||
    if (filename.size())
 | 
			
		||||
       BootGame(filename.toLatin1().data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnMenuLoadSymbolMap() {
 | 
			
		||||
    QString filename = QFileDialog::getOpenFileName(this, tr("Load symbol map"), QString(), tr("Symbol map (*)"));
 | 
			
		||||
    if (filename.size())
 | 
			
		||||
        LoadSymbolMap(filename.toLatin1().data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnStartGame()
 | 
			
		||||
{
 | 
			
		||||
    render_window->GetEmuThread().SetCpuRunning(true);
 | 
			
		||||
 | 
			
		||||
@ -33,10 +33,11 @@ private:
 | 
			
		||||
    void closeEvent(QCloseEvent* event);
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
	void OnStartGame();
 | 
			
		||||
	void OnPauseGame();
 | 
			
		||||
	void OnStopGame();
 | 
			
		||||
	void OnMenuLoadFile();
 | 
			
		||||
    void OnStartGame();
 | 
			
		||||
    void OnPauseGame();
 | 
			
		||||
    void OnStopGame();
 | 
			
		||||
    void OnMenuLoadFile();
 | 
			
		||||
    void OnMenuLoadSymbolMap();
 | 
			
		||||
    void OnOpenHotkeysDialog();
 | 
			
		||||
    void OnConfigure();
 | 
			
		||||
    void ToggleWindowMode();
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@
 | 
			
		||||
     <string>&File</string>
 | 
			
		||||
    </property>
 | 
			
		||||
    <addaction name="action_Load_File"/>
 | 
			
		||||
    <addaction name="action_Load_Symbol_Map"/>
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="action_Exit"/>
 | 
			
		||||
   </widget>
 | 
			
		||||
@ -72,12 +73,17 @@
 | 
			
		||||
   <addaction name="menu_Help"/>
 | 
			
		||||
  </widget>
 | 
			
		||||
  <widget class="QStatusBar" name="statusbar"/>
 | 
			
		||||
  <action name="action_Load_File">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Load file...</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Exit">
 | 
			
		||||
   <action name="action_Load_File">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Load file...</string>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
   <action name="action_Load_Symbol_Map">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
       <string>Load symbol map...</string>
 | 
			
		||||
     </property>
 | 
			
		||||
   </action>
 | 
			
		||||
   <action name="action_Exit">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>E&xit</string>
 | 
			
		||||
   </property>
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ class Ui_MainWindow
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    QAction *action_Load_File;
 | 
			
		||||
    QAction *action_Load_Symbol_Map;
 | 
			
		||||
    QAction *action_Exit;
 | 
			
		||||
    QAction *action_Start;
 | 
			
		||||
    QAction *action_Pause;
 | 
			
		||||
@ -56,6 +57,8 @@ public:
 | 
			
		||||
        MainWindow->setDockNestingEnabled(true);
 | 
			
		||||
        action_Load_File = new QAction(MainWindow);
 | 
			
		||||
        action_Load_File->setObjectName(QString::fromUtf8("action_Load_File"));
 | 
			
		||||
        action_Load_Symbol_Map = new QAction(MainWindow);
 | 
			
		||||
        action_Load_Symbol_Map->setObjectName(QString::fromUtf8("action_Load_Symbol_Map"));
 | 
			
		||||
        action_Exit = new QAction(MainWindow);
 | 
			
		||||
        action_Exit->setObjectName(QString::fromUtf8("action_Exit"));
 | 
			
		||||
        action_Start = new QAction(MainWindow);
 | 
			
		||||
@ -101,6 +104,7 @@ public:
 | 
			
		||||
        menubar->addAction(menu_View->menuAction());
 | 
			
		||||
        menubar->addAction(menu_Help->menuAction());
 | 
			
		||||
        menu_File->addAction(action_Load_File);
 | 
			
		||||
        menu_File->addAction(action_Load_Symbol_Map);
 | 
			
		||||
        menu_File->addSeparator();
 | 
			
		||||
        menu_File->addAction(action_Exit);
 | 
			
		||||
        menu_Emulation->addAction(action_Start);
 | 
			
		||||
@ -123,6 +127,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
        MainWindow->setWindowTitle(QApplication::translate("MainWindow", "Citra", 0, QApplication::UnicodeUTF8));
 | 
			
		||||
        action_Load_File->setText(QApplication::translate("MainWindow", "Load file...", 0, QApplication::UnicodeUTF8));
 | 
			
		||||
        action_Load_Symbol_Map->setText(QApplication::translate("MainWindow", "Load symbol map...", 0, QApplication::UnicodeUTF8));
 | 
			
		||||
        action_Exit->setText(QApplication::translate("MainWindow", "E&xit", 0, QApplication::UnicodeUTF8));
 | 
			
		||||
        action_Start->setText(QApplication::translate("MainWindow", "&Start", 0, QApplication::UnicodeUTF8));
 | 
			
		||||
        action_Pause->setText(QApplication::translate("MainWindow", "&Pause", 0, QApplication::UnicodeUTF8));
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										172
									
								
								src/common/bit_field.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								src/common/bit_field.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,172 @@
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Copyright 2014 Tony Wasserka
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
//       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
//       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
//       documentation and/or other materials provided with the distribution.
 | 
			
		||||
//     * Neither the name of the owner nor the names of its contributors may
 | 
			
		||||
//       be used to endorse or promote products derived from this software
 | 
			
		||||
//       without specific prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <limits>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Abstract bitfield class
 | 
			
		||||
 *
 | 
			
		||||
 * Allows endianness-independent access to individual bitfields within some raw
 | 
			
		||||
 * integer value. The assembly generated by this class is identical to the
 | 
			
		||||
 * usage of raw bitfields, so it's a perfectly fine replacement.
 | 
			
		||||
 *
 | 
			
		||||
 * For BitField<X,Y,Z>, X is the distance of the bitfield to the LSB of the
 | 
			
		||||
 * raw value, Y is the length in bits of the bitfield. Z is an integer type
 | 
			
		||||
 * which determines the sign of the bitfield. Z must have the same size as the
 | 
			
		||||
 * raw integer.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * General usage:
 | 
			
		||||
 *
 | 
			
		||||
 * Create a new union with the raw integer value as a member.
 | 
			
		||||
 * Then for each bitfield you want to expose, add a BitField member
 | 
			
		||||
 * in the union. The template parameters are the bit offset and the number
 | 
			
		||||
 * of desired bits.
 | 
			
		||||
 *
 | 
			
		||||
 * Changes in the bitfield members will then get reflected in the raw integer
 | 
			
		||||
 * value and vice-versa.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Sample usage:
 | 
			
		||||
 *
 | 
			
		||||
 * union SomeRegister
 | 
			
		||||
 * {
 | 
			
		||||
 *     u32 hex;
 | 
			
		||||
 *
 | 
			
		||||
 *     BitField<0,7,u32> first_seven_bits;     // unsigned
 | 
			
		||||
 *     BitField<7,8,32> next_eight_bits;       // unsigned
 | 
			
		||||
 *     BitField<3,15,s32> some_signed_fields;  // signed
 | 
			
		||||
 * };
 | 
			
		||||
 *
 | 
			
		||||
 * This is equivalent to the little-endian specific code:
 | 
			
		||||
 *
 | 
			
		||||
 * union SomeRegister
 | 
			
		||||
 * {
 | 
			
		||||
 *     u32 hex;
 | 
			
		||||
 *
 | 
			
		||||
 *     struct
 | 
			
		||||
 *     {
 | 
			
		||||
 *         u32 first_seven_bits : 7;
 | 
			
		||||
 *         u32 next_eight_bits : 8;
 | 
			
		||||
 *     };
 | 
			
		||||
 *     struct
 | 
			
		||||
 *     {
 | 
			
		||||
 *         u32 : 3; // padding
 | 
			
		||||
 *         s32 some_signed_fields : 15;
 | 
			
		||||
 *     };
 | 
			
		||||
 * };
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Caveats:
 | 
			
		||||
 *
 | 
			
		||||
 * 1)
 | 
			
		||||
 * BitField provides automatic casting from and to the storage type where
 | 
			
		||||
 * appropriate. However, when using non-typesafe functions like printf, an
 | 
			
		||||
 * explicit cast must be performed on the BitField object to make sure it gets
 | 
			
		||||
 * passed correctly, e.g.:
 | 
			
		||||
 * printf("Value: %d", (s32)some_register.some_signed_fields);
 | 
			
		||||
 *
 | 
			
		||||
 * 2)
 | 
			
		||||
 * Not really a caveat, but potentially irritating: This class is used in some
 | 
			
		||||
 * packed structures that do not guarantee proper alignment. Therefore we have
 | 
			
		||||
 * to use #pragma pack here not to pack the members of the class, but instead
 | 
			
		||||
 * to break GCC's assumption that the members of the class are aligned on
 | 
			
		||||
 * sizeof(StorageType).
 | 
			
		||||
 * TODO(neobrain): Confirm that this is a proper fix and not just masking
 | 
			
		||||
 * symptoms.
 | 
			
		||||
 */
 | 
			
		||||
#pragma pack(1)
 | 
			
		||||
template<std::size_t position, std::size_t bits, typename T>
 | 
			
		||||
struct BitField
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    // This constructor might be considered ambiguous:
 | 
			
		||||
    // Would it initialize the storage or just the bitfield?
 | 
			
		||||
    // Hence, delete it. Use the assignment operator to set bitfield values!
 | 
			
		||||
    BitField(T val) = delete;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    // Force default constructor to be created
 | 
			
		||||
    // so that we can use this within unions
 | 
			
		||||
    BitField() = default;
 | 
			
		||||
 | 
			
		||||
    __forceinline BitField& operator=(T val)
 | 
			
		||||
    {
 | 
			
		||||
        storage = (storage & ~GetMask()) | ((val << position) & GetMask());
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    __forceinline operator T() const
 | 
			
		||||
    {
 | 
			
		||||
        if (std::numeric_limits<T>::is_signed)
 | 
			
		||||
        {
 | 
			
		||||
            std::size_t shift = 8 * sizeof(T)-bits;
 | 
			
		||||
            return (T)(((storage & GetMask()) << (shift - position)) >> shift);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return (T)((storage & GetMask()) >> position);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // StorageType is T for non-enum types and the underlying type of T if
 | 
			
		||||
    // T is an enumeration. Note that T is wrapped within an enable_if in the
 | 
			
		||||
    // former case to workaround compile errors which arise when using
 | 
			
		||||
    // std::underlying_type<T>::type directly.
 | 
			
		||||
    typedef typename std::conditional < std::is_enum<T>::value,
 | 
			
		||||
        std::underlying_type<T>,
 | 
			
		||||
        std::enable_if < true, T >> ::type::type StorageType;
 | 
			
		||||
 | 
			
		||||
    // Unsigned version of StorageType
 | 
			
		||||
    typedef typename std::make_unsigned<StorageType>::type StorageTypeU;
 | 
			
		||||
 | 
			
		||||
    __forceinline StorageType GetMask() const
 | 
			
		||||
    {
 | 
			
		||||
        return ((~(StorageTypeU)0) >> (8 * sizeof(T)-bits)) << position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    StorageType storage;
 | 
			
		||||
 | 
			
		||||
    static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range");
 | 
			
		||||
 | 
			
		||||
    // And, you know, just in case people specify something stupid like bits=position=0x80000000
 | 
			
		||||
    static_assert(position < 8 * sizeof(T), "Invalid position");
 | 
			
		||||
    static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
 | 
			
		||||
    static_assert(bits > 0, "Invalid number of bits");
 | 
			
		||||
};
 | 
			
		||||
#pragma pack()
 | 
			
		||||
@ -157,6 +157,7 @@
 | 
			
		||||
    <ClInclude Include="atomic.h" />
 | 
			
		||||
    <ClInclude Include="atomic_gcc.h" />
 | 
			
		||||
    <ClInclude Include="atomic_win32.h" />
 | 
			
		||||
    <ClInclude Include="bit_field.h" />
 | 
			
		||||
    <ClInclude Include="break_points.h" />
 | 
			
		||||
    <ClInclude Include="chunk_file.h" />
 | 
			
		||||
    <ClInclude Include="common.h" />
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@
 | 
			
		||||
    <ClInclude Include="utf8.h" />
 | 
			
		||||
    <ClInclude Include="symbols.h" />
 | 
			
		||||
    <ClInclude Include="scm_rev.h" />
 | 
			
		||||
    <ClInclude Include="bit_field.h" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClCompile Include="break_points.cpp" />
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ enum LOG_TYPE {
 | 
			
		||||
    EXPANSIONINTERFACE,
 | 
			
		||||
    GDB_STUB,
 | 
			
		||||
    ARM11,
 | 
			
		||||
    GPFIFO,
 | 
			
		||||
    GSP,
 | 
			
		||||
    OSHLE,
 | 
			
		||||
    MASTER_LOG,
 | 
			
		||||
    MEMMAP,
 | 
			
		||||
@ -54,7 +54,7 @@ enum LOG_TYPE {
 | 
			
		||||
    WII_IPC_FILEIO,
 | 
			
		||||
    WII_IPC_HID,
 | 
			
		||||
    WII_IPC_HLE,
 | 
			
		||||
    WII_IPC_NET,
 | 
			
		||||
    SVC,
 | 
			
		||||
    NDMA,
 | 
			
		||||
    HLE,
 | 
			
		||||
    RENDER,
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,7 @@ LogManager::LogManager()
 | 
			
		||||
    m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream",            "StreamingInt");
 | 
			
		||||
    m_Log[LogTypes::DSPINTERFACE]       = new LogContainer("DSP",               "DSPInterface");
 | 
			
		||||
    m_Log[LogTypes::DVDINTERFACE]       = new LogContainer("DVD",               "DVDInterface");
 | 
			
		||||
    m_Log[LogTypes::GPFIFO]             = new LogContainer("GP",                "GPFifo");
 | 
			
		||||
    m_Log[LogTypes::GSP]                = new LogContainer("GSP",               "GSP");
 | 
			
		||||
    m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI",               "ExpansionInt");
 | 
			
		||||
    m_Log[LogTypes::GDB_STUB]           = new LogContainer("GDB_STUB",          "GDB Stub");
 | 
			
		||||
    m_Log[LogTypes::AUDIO_INTERFACE]    = new LogContainer("AI",                "AudioInt");
 | 
			
		||||
@ -66,7 +66,7 @@ LogManager::LogManager()
 | 
			
		||||
    m_Log[LogTypes::WII_IPC_FILEIO]     = new LogContainer("WII_IPC_FILEIO",    "WII IPC FILEIO");
 | 
			
		||||
    m_Log[LogTypes::RENDER]             = new LogContainer("RENDER",            "RENDER");
 | 
			
		||||
    m_Log[LogTypes::LCD]                = new LogContainer("LCD",               "LCD");
 | 
			
		||||
    m_Log[LogTypes::WII_IPC_NET]        = new LogContainer("WII_IPC_NET",       "WII IPC NET");
 | 
			
		||||
    m_Log[LogTypes::SVC]                = new LogContainer("SVC",               "Supervisor Call");
 | 
			
		||||
    m_Log[LogTypes::NDMA]               = new LogContainer("NDMA",              "NDMA");
 | 
			
		||||
    m_Log[LogTypes::HLE]                = new LogContainer("HLE",               "High Level Emulation");
 | 
			
		||||
    m_Log[LogTypes::HW]                 = new LogContainer("HW",                "Hardware");
 | 
			
		||||
@ -147,7 +147,7 @@ LogContainer::LogContainer(const char* shortName, const char* fullName, bool ena
 | 
			
		||||
{
 | 
			
		||||
    strncpy(m_fullName, fullName, 128);
 | 
			
		||||
    strncpy(m_shortName, shortName, 32);
 | 
			
		||||
    m_level = LogTypes::LWARNING;
 | 
			
		||||
    m_level = (LogTypes::LOG_LEVELS)MAX_LOGLEVEL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LogContainer
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,9 @@ set(SRCS    core.cpp
 | 
			
		||||
            mem_map_funcs.cpp
 | 
			
		||||
            system.cpp
 | 
			
		||||
            arm/disassembler/arm_disasm.cpp
 | 
			
		||||
            arm/disassembler/load_symbol_map.cpp
 | 
			
		||||
            arm/interpreter/arm_interpreter.cpp
 | 
			
		||||
            arm/interpreter/armcopro.cpp
 | 
			
		||||
            arm/interpreter/armemu.cpp
 | 
			
		||||
            arm/interpreter/arminit.cpp
 | 
			
		||||
            arm/interpreter/armmmu.cpp
 | 
			
		||||
@ -13,12 +15,24 @@ set(SRCS    core.cpp
 | 
			
		||||
            arm/interpreter/armsupp.cpp
 | 
			
		||||
            arm/interpreter/armvirt.cpp
 | 
			
		||||
            arm/interpreter/thumbemu.cpp
 | 
			
		||||
            arm/mmu/arm1176jzf_s_mmu.cpp
 | 
			
		||||
            arm/interpreter/vfp/vfp.cpp
 | 
			
		||||
            arm/interpreter/vfp/vfpdouble.cpp
 | 
			
		||||
            arm/interpreter/vfp/vfpinstr.cpp
 | 
			
		||||
            arm/interpreter/vfp/vfpsingle.cpp
 | 
			
		||||
            arm/interpreter/mmu/arm1176jzf_s_mmu.cpp
 | 
			
		||||
            arm/interpreter/mmu/cache.cpp
 | 
			
		||||
            arm/interpreter/mmu/maverick.cpp
 | 
			
		||||
            arm/interpreter/mmu/rb.cpp
 | 
			
		||||
            arm/interpreter/mmu/sa_mmu.cpp
 | 
			
		||||
            arm/interpreter/mmu/tlb.cpp
 | 
			
		||||
            arm/interpreter/mmu/wb.cpp
 | 
			
		||||
            arm/interpreter/mmu/xscale_copro.cpp
 | 
			
		||||
            elf/elf_reader.cpp
 | 
			
		||||
            file_sys/directory_file_system.cpp
 | 
			
		||||
            file_sys/meta_file_system.cpp
 | 
			
		||||
            hle/hle.cpp
 | 
			
		||||
            hle/mrc.cpp
 | 
			
		||||
            hle/config_mem.cpp
 | 
			
		||||
            hle/coprocessor.cpp
 | 
			
		||||
            hle/syscall.cpp
 | 
			
		||||
            hle/service/apt.cpp
 | 
			
		||||
            hle/service/gsp.cpp
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								src/core/arm/disassembler/load_symbol_map.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/arm/disassembler/load_symbol_map.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "common/symbols.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/file_util.h"
 | 
			
		||||
 | 
			
		||||
#include "core/arm/disassembler/load_symbol_map.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Loads a symbol map file for use with the disassembler
 | 
			
		||||
 * @param filename String filename path of symbol map file
 | 
			
		||||
 */
 | 
			
		||||
void LoadSymbolMap(std::string filename) {
 | 
			
		||||
    std::ifstream infile(filename);
 | 
			
		||||
 | 
			
		||||
    std::string address_str, function_name, line;
 | 
			
		||||
    u32 size, address;
 | 
			
		||||
 | 
			
		||||
    while (std::getline(infile, line)) {
 | 
			
		||||
        std::istringstream iss(line);
 | 
			
		||||
        if (!(iss >> address_str >> size >> function_name)) { 
 | 
			
		||||
            break; // Error parsing 
 | 
			
		||||
        }
 | 
			
		||||
        u32 address = std::stoul(address_str, nullptr, 16);
 | 
			
		||||
 | 
			
		||||
        Symbols::Add(address, function_name, size, 2);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/core/arm/disassembler/load_symbol_map.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/core/arm/disassembler/load_symbol_map.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Loads a symbol map file for use with the disassembler
 | 
			
		||||
 * @param filename String filename path of symbol map file
 | 
			
		||||
 */
 | 
			
		||||
void LoadSymbolMap(std::string filename);
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.  
 | 
			
		||||
 | 
			
		||||
#include "arm_interpreter.h"
 | 
			
		||||
#include "core/arm/interpreter/arm_interpreter.h"
 | 
			
		||||
 | 
			
		||||
const static cpu_config_t s_arm11_cpu_info = {
 | 
			
		||||
    "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										842
									
								
								src/core/arm/interpreter/armcopro.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										842
									
								
								src/core/arm/interpreter/armcopro.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,842 @@
 | 
			
		||||
/*  armcopro.c -- co-processor interface:  ARM6 Instruction Emulator.
 | 
			
		||||
    Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
 | 
			
		||||
 
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
#include "core/arm/interpreter/armos.h"
 | 
			
		||||
#include "core/arm/interpreter/armemu.h"
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfp.h"
 | 
			
		||||
 | 
			
		||||
//chy 2005-07-08
 | 
			
		||||
//#include "ansidecl.h"
 | 
			
		||||
//chy -------
 | 
			
		||||
//#include "iwmmxt.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//chy 2005-09-19 add CP6 MRC support (for get irq number and base)
 | 
			
		||||
extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type,
 | 
			
		||||
				ARMword instr, ARMword * data);
 | 
			
		||||
//chy 2005-09-19---------------
 | 
			
		||||
 | 
			
		||||
extern unsigned xscale_cp13_init (ARMul_State * state);
 | 
			
		||||
extern unsigned xscale_cp13_exit (ARMul_State * state);
 | 
			
		||||
extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword data);
 | 
			
		||||
extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword data);
 | 
			
		||||
extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr);
 | 
			
		||||
extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg,
 | 
			
		||||
				      ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg,
 | 
			
		||||
				       ARMword data);
 | 
			
		||||
extern unsigned xscale_cp14_init (ARMul_State * state);
 | 
			
		||||
extern unsigned xscale_cp14_exit (ARMul_State * state);
 | 
			
		||||
extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword data);
 | 
			
		||||
extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword data);
 | 
			
		||||
extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr);
 | 
			
		||||
extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
 | 
			
		||||
				      ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
 | 
			
		||||
				       ARMword data);
 | 
			
		||||
extern unsigned xscale_cp15_init (ARMul_State * state);
 | 
			
		||||
extern unsigned xscale_cp15_exit (ARMul_State * state);
 | 
			
		||||
extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword data);
 | 
			
		||||
extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr, ARMword data);
 | 
			
		||||
extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type,
 | 
			
		||||
				 ARMword instr);
 | 
			
		||||
extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
 | 
			
		||||
				      ARMword * data);
 | 
			
		||||
extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
 | 
			
		||||
				       ARMword data);
 | 
			
		||||
extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
 | 
			
		||||
					unsigned cpnum);
 | 
			
		||||
 | 
			
		||||
/* Dummy Co-processors.  */
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
NoCoPro3R (ARMul_State * state,
 | 
			
		||||
	   unsigned a, ARMword b)
 | 
			
		||||
{
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
NoCoPro4R (ARMul_State * state,
 | 
			
		||||
	   unsigned a,
 | 
			
		||||
	   ARMword b, ARMword c)
 | 
			
		||||
{
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
NoCoPro4W (ARMul_State * state,
 | 
			
		||||
	   unsigned a,
 | 
			
		||||
	   ARMword b, ARMword * c)
 | 
			
		||||
{
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
NoCoPro5R (ARMul_State * state,
 | 
			
		||||
	   unsigned a,
 | 
			
		||||
	   ARMword b, 
 | 
			
		||||
	   ARMword c, ARMword d)
 | 
			
		||||
{
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
NoCoPro5W (ARMul_State * state,
 | 
			
		||||
	   unsigned a,
 | 
			
		||||
	   ARMword b,
 | 
			
		||||
	   ARMword * c, ARMword * d )
 | 
			
		||||
{
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The XScale Co-processors.  */
 | 
			
		||||
 | 
			
		||||
/* Coprocessor 15:  System Control.  */
 | 
			
		||||
static void write_cp14_reg (unsigned, ARMword);
 | 
			
		||||
static ARMword read_cp14_reg (unsigned);
 | 
			
		||||
 | 
			
		||||
/* There are two sets of registers for copro 15.
 | 
			
		||||
   One set is available when opcode_2 is 0 and
 | 
			
		||||
   the other set when opcode_2 >= 1.  */
 | 
			
		||||
static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
 | 
			
		||||
static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
 | 
			
		||||
/* There are also a set of breakpoint registers
 | 
			
		||||
   which are accessed via CRm instead of opcode_2.  */
 | 
			
		||||
static ARMword XScale_cp15_DBR1;
 | 
			
		||||
static ARMword XScale_cp15_DBCON;
 | 
			
		||||
static ARMword XScale_cp15_IBCR0;
 | 
			
		||||
static ARMword XScale_cp15_IBCR1;
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
XScale_cp15_init (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 16; i--;) {
 | 
			
		||||
		XScale_cp15_opcode_2_is_0_Regs[i] = 0;
 | 
			
		||||
		XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Initialise the processor ID.  */
 | 
			
		||||
	//chy 2003-03-24, is same as cpu id in skyeye_options.c
 | 
			
		||||
	//XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
 | 
			
		||||
	XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000;
 | 
			
		||||
 | 
			
		||||
	/* Initialise the cache type.  */
 | 
			
		||||
	XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
 | 
			
		||||
 | 
			
		||||
	/* Initialise the ARM Control Register.  */
 | 
			
		||||
	XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
 | 
			
		||||
 | 
			
		||||
	return No_exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check an access to a register.  */
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
check_cp15_access (ARMul_State * state,
 | 
			
		||||
		   unsigned reg,
 | 
			
		||||
		   unsigned CRm, unsigned opcode_1, unsigned opcode_2)
 | 
			
		||||
{
 | 
			
		||||
	/* Do not allow access to these register in USER mode.  */
 | 
			
		||||
	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
 | 
			
		||||
	if (state->Mode == USER26MODE || state->Mode == USER32MODE )
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* Opcode_1should be zero.  */
 | 
			
		||||
	if (opcode_1 != 0)
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* Different register have different access requirements.  */
 | 
			
		||||
	switch (reg) {
 | 
			
		||||
	case 0:
 | 
			
		||||
	case 1:
 | 
			
		||||
		/* CRm must be 0.  Opcode_2 can be anything.  */
 | 
			
		||||
		if (CRm != 0)
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
	case 3:
 | 
			
		||||
		/* CRm must be 0.  Opcode_2 must be zero.  */
 | 
			
		||||
		if ((CRm != 0) || (opcode_2 != 0))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 4:
 | 
			
		||||
		/* Access not allowed.  */
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
	case 5:
 | 
			
		||||
	case 6:
 | 
			
		||||
		/* Opcode_2 must be zero.  CRm must be 0.  */
 | 
			
		||||
		if ((CRm != 0) || (opcode_2 != 0))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 7:
 | 
			
		||||
		/* Permissable combinations:
 | 
			
		||||
		   Opcode_2  CRm
 | 
			
		||||
		   0       5
 | 
			
		||||
		   0       6
 | 
			
		||||
		   0       7
 | 
			
		||||
		   1       5
 | 
			
		||||
		   1       6
 | 
			
		||||
		   1      10
 | 
			
		||||
		   4      10
 | 
			
		||||
		   5       2
 | 
			
		||||
		   6       5  */
 | 
			
		||||
		switch (opcode_2) {
 | 
			
		||||
		default:
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		case 6:
 | 
			
		||||
			if (CRm != 5)
 | 
			
		||||
				return ARMul_CANT;
 | 
			
		||||
			break;
 | 
			
		||||
		case 5:
 | 
			
		||||
			if (CRm != 2)
 | 
			
		||||
				return ARMul_CANT;
 | 
			
		||||
			break;
 | 
			
		||||
		case 4:
 | 
			
		||||
			if (CRm != 10)
 | 
			
		||||
				return ARMul_CANT;
 | 
			
		||||
			break;
 | 
			
		||||
		case 1:
 | 
			
		||||
			if ((CRm != 5) && (CRm != 6) && (CRm != 10))
 | 
			
		||||
				return ARMul_CANT;
 | 
			
		||||
			break;
 | 
			
		||||
		case 0:
 | 
			
		||||
			if ((CRm < 5) || (CRm > 7))
 | 
			
		||||
				return ARMul_CANT;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case 8:
 | 
			
		||||
		/* Permissable combinations:
 | 
			
		||||
		   Opcode_2  CRm
 | 
			
		||||
		   0       5
 | 
			
		||||
		   0       6
 | 
			
		||||
		   0       7
 | 
			
		||||
		   1       5
 | 
			
		||||
		   1       6  */
 | 
			
		||||
		if (opcode_2 > 1)
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		if ((CRm < 5) || (CRm > 7))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		if (opcode_2 == 1 && CRm == 7)
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 9:
 | 
			
		||||
		/* Opcode_2 must be zero or one.  CRm must be 1 or 2.  */
 | 
			
		||||
		if (((CRm != 0) && (CRm != 1))
 | 
			
		||||
		    || ((opcode_2 != 1) && (opcode_2 != 2)))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 10:
 | 
			
		||||
		/* Opcode_2 must be zero or one.  CRm must be 4 or 8.  */
 | 
			
		||||
		if (((CRm != 0) && (CRm != 1))
 | 
			
		||||
		    || ((opcode_2 != 4) && (opcode_2 != 8)))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 11:
 | 
			
		||||
		/* Access not allowed.  */
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
	case 12:
 | 
			
		||||
		/* Access not allowed.  */
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
	case 13:
 | 
			
		||||
		/* Opcode_2 must be zero.  CRm must be 0.  */
 | 
			
		||||
		if ((CRm != 0) || (opcode_2 != 0))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 14:
 | 
			
		||||
		/* Opcode_2 must be 0.  CRm must be 0, 3, 4, 8 or 9.  */
 | 
			
		||||
		if (opcode_2 != 0)
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
		if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8)
 | 
			
		||||
		    && (CRm != 9))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 15:
 | 
			
		||||
		/* Opcode_2 must be zero.  CRm must be 1.  */
 | 
			
		||||
		if ((CRm != 1) || (opcode_2 != 0))
 | 
			
		||||
			return ARMul_CANT;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		/* Should never happen.  */
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ARMul_DONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Coprocessor 13:  Interrupt Controller and Bus Controller.  */
 | 
			
		||||
 | 
			
		||||
/* There are two sets of registers for copro 13.
 | 
			
		||||
   One set (of three registers) is available when CRm is 0
 | 
			
		||||
   and the other set (of six registers) when CRm is 1.  */
 | 
			
		||||
 | 
			
		||||
static ARMword XScale_cp13_CR0_Regs[16];
 | 
			
		||||
static ARMword XScale_cp13_CR1_Regs[16];
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
XScale_cp13_init (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 16; i--;) {
 | 
			
		||||
		XScale_cp13_CR0_Regs[i] = 0;
 | 
			
		||||
		XScale_cp13_CR1_Regs[i] = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return No_exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check an access to a register.  */
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
check_cp13_access (ARMul_State * state,
 | 
			
		||||
		   unsigned reg,
 | 
			
		||||
		   unsigned CRm, unsigned opcode_1, unsigned opcode_2)
 | 
			
		||||
{
 | 
			
		||||
	/* Do not allow access to these registers in USER mode.  */
 | 
			
		||||
	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
 | 
			
		||||
	if (state->Mode == USER26MODE || state->Mode == USER32MODE )
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* The opcodes should be zero.  */
 | 
			
		||||
	if ((opcode_1 != 0) || (opcode_2 != 0))
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* Do not allow access to these register if bit
 | 
			
		||||
	   13 of coprocessor 15's register 15 is zero.  */
 | 
			
		||||
	if (!CP_ACCESS_ALLOWED (state, 13))
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* Registers 0, 4 and 8 are defined when CRm == 0.
 | 
			
		||||
	   Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
 | 
			
		||||
	   For all other CRm values undefined behaviour results.  */
 | 
			
		||||
	if (CRm == 0) {
 | 
			
		||||
		if (reg == 0 || reg == 4 || reg == 8)
 | 
			
		||||
			return ARMul_DONE;
 | 
			
		||||
	}
 | 
			
		||||
	else if (CRm == 1) {
 | 
			
		||||
		if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
 | 
			
		||||
			return ARMul_DONE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Coprocessor 14:  Performance Monitoring,  Clock and Power management,
 | 
			
		||||
   Software Debug.  */
 | 
			
		||||
 | 
			
		||||
static ARMword XScale_cp14_Regs[16];
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
XScale_cp14_init (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 16; i--;)
 | 
			
		||||
		XScale_cp14_Regs[i] = 0;
 | 
			
		||||
 | 
			
		||||
	return No_exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check an access to a register.  */
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
check_cp14_access (ARMul_State * state,
 | 
			
		||||
		   unsigned reg,
 | 
			
		||||
		   unsigned CRm, unsigned opcode1, unsigned opcode2)
 | 
			
		||||
{
 | 
			
		||||
	/* Not allowed to access these register in USER mode.  */
 | 
			
		||||
	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
 | 
			
		||||
	if (state->Mode == USER26MODE || state->Mode == USER32MODE )
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* CRm should be zero.  */
 | 
			
		||||
	if (CRm != 0)
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* OPcodes should be zero.  */
 | 
			
		||||
	if (opcode1 != 0 || opcode2 != 0)
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	/* Accessing registers 4 or 5 has unpredicatable results.  */
 | 
			
		||||
	if (reg >= 4 && reg <= 5)
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	return ARMul_DONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Here's ARMulator's MMU definition.  A few things to note:
 | 
			
		||||
   1) It has eight registers, but only two are defined.
 | 
			
		||||
   2) You can only access its registers with MCR and MRC.
 | 
			
		||||
   3) MMU Register 0 (ID) returns 0x41440110
 | 
			
		||||
   4) Register 1 only has 4 bits defined.  Bits 0 to 3 are unused, bit 4
 | 
			
		||||
      controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
 | 
			
		||||
      bit 6 controls late abort timimg and bit 7 controls big/little endian.  */
 | 
			
		||||
 | 
			
		||||
static ARMword MMUReg[8];
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
MMUInit (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
/* 2004-05-09 chy
 | 
			
		||||
-------------------------------------------------------------
 | 
			
		||||
read ARM Architecture Reference Manual
 | 
			
		||||
2.6.5 Data Abort
 | 
			
		||||
There are three Abort Model in ARM arch.
 | 
			
		||||
 | 
			
		||||
Early Abort Model: used in some ARMv3 and earlier implementations. In this
 | 
			
		||||
model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
 | 
			
		||||
the base register was unchanged for all other instructions. (oldest)
 | 
			
		||||
 | 
			
		||||
Base Restored Abort Model: If a Data Abort occurs in an instruction which
 | 
			
		||||
specifies base register writeback, the value in the base register is
 | 
			
		||||
unchanged. (strongarm, xscale)
 | 
			
		||||
 | 
			
		||||
Base Updated Abort Model: If a Data Abort occurs in an instruction which
 | 
			
		||||
specifies base register writeback, the base register writeback still occurs.
 | 
			
		||||
(arm720T)
 | 
			
		||||
 | 
			
		||||
read PART B
 | 
			
		||||
chap2 The System Control Coprocessor  CP15
 | 
			
		||||
2.4 Register1:control register
 | 
			
		||||
L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
 | 
			
		||||
processor could be configured:
 | 
			
		||||
0=early Abort Model Selected(now obsolete)
 | 
			
		||||
1=Late Abort Model selceted(same as Base Updated Abort Model)
 | 
			
		||||
 | 
			
		||||
on later processors, this bit reads as 1 and ignores writes.
 | 
			
		||||
-------------------------------------------------------------
 | 
			
		||||
So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
 | 
			
		||||
    if lateabtSig=0, then it means Base Restored Abort Model
 | 
			
		||||
because the ARMs which skyeye simulates are all belonged to  ARMv4,
 | 
			
		||||
so I think MMUReg[1]'s bit 6 should always be 1
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
	MMUReg[1] = state->prog32Sig << 4 |
 | 
			
		||||
		state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7;
 | 
			
		||||
	//state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present");
 | 
			
		||||
 | 
			
		||||
	return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
MMUMRC (ARMul_State * state, unsigned type,
 | 
			
		||||
	ARMword instr, ARMword * value)
 | 
			
		||||
{
 | 
			
		||||
	mmu_mrc (state, instr, value);
 | 
			
		||||
	return (ARMul_DONE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	mmu_mcr (state, instr, value);
 | 
			
		||||
	return (ARMul_DONE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* What follows is the Validation Suite Coprocessor.  It uses two
 | 
			
		||||
   co-processor numbers (4 and 5) and has the follwing functionality.
 | 
			
		||||
   Sixteen registers.  Both co-processor nuimbers can be used in an MCR
 | 
			
		||||
   and MRC to access these registers.  CP 4 can LDC and STC to and from
 | 
			
		||||
   the registers.  CP 4 and CP 5 CDP 0 will busy wait for the number of
 | 
			
		||||
   cycles specified by a CP register.  CP 5 CDP 1 issues a FIQ after a
 | 
			
		||||
   number of cycles (specified in a CP register), CDP 2 issues an IRQW
 | 
			
		||||
   in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
 | 
			
		||||
   stores a 32 bit time value in a CP register (actually it's the total
 | 
			
		||||
   number of N, S, I, C and F cyles).  */
 | 
			
		||||
 | 
			
		||||
static ARMword ValReg[16];
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
ValLDC (ARMul_State * state,
 | 
			
		||||
	unsigned type, ARMword instr, ARMword data)
 | 
			
		||||
{
 | 
			
		||||
	static unsigned words;
 | 
			
		||||
 | 
			
		||||
	if (type != ARMul_DATA)
 | 
			
		||||
		words = 0;
 | 
			
		||||
	else {
 | 
			
		||||
		ValReg[BITS (12, 15)] = data;
 | 
			
		||||
 | 
			
		||||
		if (BIT (22))
 | 
			
		||||
			/* It's a long access, get two words.  */
 | 
			
		||||
			if (words++ != 4)
 | 
			
		||||
				return ARMul_INC;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ARMul_DONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
ValSTC (ARMul_State * state,
 | 
			
		||||
	unsigned type, ARMword instr, ARMword * data)
 | 
			
		||||
{
 | 
			
		||||
	static unsigned words;
 | 
			
		||||
 | 
			
		||||
	if (type != ARMul_DATA)
 | 
			
		||||
		words = 0;
 | 
			
		||||
	else {
 | 
			
		||||
		*data = ValReg[BITS (12, 15)];
 | 
			
		||||
 | 
			
		||||
		if (BIT (22))
 | 
			
		||||
			/* It's a long access, get two words.  */
 | 
			
		||||
			if (words++ != 4)
 | 
			
		||||
				return ARMul_INC;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ARMul_DONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
ValMRC (ARMul_State * state,
 | 
			
		||||
	unsigned type, ARMword instr, ARMword * value)
 | 
			
		||||
{
 | 
			
		||||
	*value = ValReg[BITS (16, 19)];
 | 
			
		||||
 | 
			
		||||
	return ARMul_DONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
ValMCR (ARMul_State * state,
 | 
			
		||||
	unsigned type, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	ValReg[BITS (16, 19)] = value;
 | 
			
		||||
 | 
			
		||||
	return ARMul_DONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
ValCDP (ARMul_State * state, unsigned type, ARMword instr)
 | 
			
		||||
{
 | 
			
		||||
	static unsigned int finish = 0;
 | 
			
		||||
 | 
			
		||||
	if (BITS (20, 23) != 0)
 | 
			
		||||
		return ARMul_CANT;
 | 
			
		||||
 | 
			
		||||
	if (type == ARMul_FIRST) {
 | 
			
		||||
		ARMword howlong;
 | 
			
		||||
 | 
			
		||||
		howlong = ValReg[BITS (0, 3)];
 | 
			
		||||
 | 
			
		||||
		/* First cycle of a busy wait.  */
 | 
			
		||||
		finish = ARMul_Time (state) + howlong;
 | 
			
		||||
 | 
			
		||||
		return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
 | 
			
		||||
	}
 | 
			
		||||
	else if (type == ARMul_BUSY) {
 | 
			
		||||
		if (ARMul_Time (state) >= finish)
 | 
			
		||||
			return ARMul_DONE;
 | 
			
		||||
		else
 | 
			
		||||
			return ARMul_BUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
DoAFIQ (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	state->NfiqSig = LOW;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
DoAIRQ (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	state->NirqSig = LOW;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned
 | 
			
		||||
IntCDP (ARMul_State * state, unsigned type, ARMword instr)
 | 
			
		||||
{
 | 
			
		||||
	static unsigned int finish;
 | 
			
		||||
	ARMword howlong;
 | 
			
		||||
 | 
			
		||||
	howlong = ValReg[BITS (0, 3)];
 | 
			
		||||
 | 
			
		||||
	switch ((int) BITS (20, 23)) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		if (type == ARMul_FIRST) {
 | 
			
		||||
			/* First cycle of a busy wait.  */
 | 
			
		||||
			finish = ARMul_Time (state) + howlong;
 | 
			
		||||
 | 
			
		||||
			return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
 | 
			
		||||
		}
 | 
			
		||||
		else if (type == ARMul_BUSY) {
 | 
			
		||||
			if (ARMul_Time (state) >= finish)
 | 
			
		||||
				return ARMul_DONE;
 | 
			
		||||
			else
 | 
			
		||||
				return ARMul_BUSY;
 | 
			
		||||
		}
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
 | 
			
		||||
	case 1:
 | 
			
		||||
		if (howlong == 0)
 | 
			
		||||
			ARMul_Abort (state, ARMul_FIQV);
 | 
			
		||||
		else
 | 
			
		||||
			ARMul_ScheduleEvent (state, howlong, DoAFIQ);
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
 | 
			
		||||
	case 2:
 | 
			
		||||
		if (howlong == 0)
 | 
			
		||||
			ARMul_Abort (state, ARMul_IRQV);
 | 
			
		||||
		else
 | 
			
		||||
			ARMul_ScheduleEvent (state, howlong, DoAIRQ);
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
 | 
			
		||||
	case 3:
 | 
			
		||||
		state->NfiqSig = HIGH;
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
 | 
			
		||||
	case 4:
 | 
			
		||||
		state->NirqSig = HIGH;
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
 | 
			
		||||
	case 5:
 | 
			
		||||
		ValReg[BITS (0, 3)] = ARMul_Time (state);
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Install co-processor instruction handlers in this routine.  */
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
ARMul_CoProInit (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	/* Initialise tham all first.  */
 | 
			
		||||
	for (i = 0; i < 16; i++)
 | 
			
		||||
		ARMul_CoProDetach (state, i);
 | 
			
		||||
 | 
			
		||||
	/* Install CoPro Instruction handlers here.
 | 
			
		||||
	   The format is:
 | 
			
		||||
	   ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
 | 
			
		||||
	   LDC routine, STC routine, MRC routine, MCR routine,
 | 
			
		||||
	   CDP routine, Read Reg routine, Write Reg routine).  */
 | 
			
		||||
	if (state->is_ep9312) {
 | 
			
		||||
		ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4,
 | 
			
		||||
				   DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL);
 | 
			
		||||
		ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5,
 | 
			
		||||
				   DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL);
 | 
			
		||||
		ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL,
 | 
			
		||||
				   DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC,
 | 
			
		||||
				   ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
		ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
 | 
			
		||||
				   ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (state->is_XScale) {
 | 
			
		||||
		//chy 2005-09-19, for PXA27x's CP6
 | 
			
		||||
		if (state->is_pxa27x) {
 | 
			
		||||
			ARMul_CoProAttach (state, 6, NULL, NULL,
 | 
			
		||||
					   NULL, NULL, xscale_cp6_mrc,
 | 
			
		||||
					   NULL, NULL, NULL, NULL, NULL, NULL);
 | 
			
		||||
		}
 | 
			
		||||
		//chy 2005-09-19 end------------- 
 | 
			
		||||
		ARMul_CoProAttach (state, 13, xscale_cp13_init,
 | 
			
		||||
				   xscale_cp13_exit, xscale_cp13_ldc,
 | 
			
		||||
				   xscale_cp13_stc, xscale_cp13_mrc,
 | 
			
		||||
				   xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp,
 | 
			
		||||
				   xscale_cp13_read_reg,
 | 
			
		||||
				   xscale_cp13_write_reg);
 | 
			
		||||
 | 
			
		||||
		ARMul_CoProAttach (state, 14, xscale_cp14_init,
 | 
			
		||||
				   xscale_cp14_exit, xscale_cp14_ldc,
 | 
			
		||||
				   xscale_cp14_stc, xscale_cp14_mrc,
 | 
			
		||||
				   xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp,
 | 
			
		||||
				   xscale_cp14_read_reg,
 | 
			
		||||
				   xscale_cp14_write_reg);
 | 
			
		||||
		//chy: 2003-08-24.
 | 
			
		||||
		ARMul_CoProAttach (state, 15, xscale_cp15_init,
 | 
			
		||||
				   xscale_cp15_exit, xscale_cp15_ldc,
 | 
			
		||||
				   xscale_cp15_stc, xscale_cp15_mrc,
 | 
			
		||||
				   xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp,
 | 
			
		||||
				   xscale_cp15_read_reg,
 | 
			
		||||
				   xscale_cp15_write_reg);
 | 
			
		||||
	}
 | 
			
		||||
	else if (state->is_v6) {
 | 
			
		||||
		ARMul_CoProAttach (state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
 | 
			
		||||
				   VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
 | 
			
		||||
		ARMul_CoProAttach (state, 11, VFPInit, NULL, VFPLDC, VFPSTC,
 | 
			
		||||
				   VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
 | 
			
		||||
		
 | 
			
		||||
		ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
 | 
			
		||||
				   MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
 | 
			
		||||
	}
 | 
			
		||||
	else {			//all except xscale
 | 
			
		||||
		ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
 | 
			
		||||
				   //                  MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
 | 
			
		||||
				   MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);
 | 
			
		||||
	}
 | 
			
		||||
//chy 2003-09-03 do it in future!!!!????
 | 
			
		||||
#if 0
 | 
			
		||||
	if (state->is_iWMMXt) {
 | 
			
		||||
		ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
 | 
			
		||||
				   NULL, NULL, IwmmxtCDP, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
		ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
 | 
			
		||||
				   IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
 | 
			
		||||
				   NULL);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	//-----------------------------------------------------------------------------
 | 
			
		||||
	//chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code.
 | 
			
		||||
	ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
 | 
			
		||||
			   ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL);
 | 
			
		||||
	ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC,
 | 
			
		||||
			   NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 | 
			
		||||
	//------------------------------------------------------------------------------
 | 
			
		||||
	/* No handlers below here.  */
 | 
			
		||||
 | 
			
		||||
	/* Call all the initialisation routines.  */
 | 
			
		||||
	for (i = 0; i < 16; i++)
 | 
			
		||||
		if (state->CPInit[i])
 | 
			
		||||
			(state->CPInit[i]) (state);
 | 
			
		||||
 | 
			
		||||
	return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Install co-processor finalisation routines in this routine.  */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ARMul_CoProExit (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	register unsigned i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 16; i++)
 | 
			
		||||
		if (state->CPExit[i])
 | 
			
		||||
			(state->CPExit[i]) (state);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 16; i++)	/* Detach all handlers.  */
 | 
			
		||||
		ARMul_CoProDetach (state, i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Routines to hook Co-processors into ARMulator.  */
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	if (init != NULL)
 | 
			
		||||
		state->CPInit[number] = init;
 | 
			
		||||
	if (exit != NULL)
 | 
			
		||||
		state->CPExit[number] = exit;
 | 
			
		||||
	if (ldc != NULL)
 | 
			
		||||
		state->LDC[number] = ldc;
 | 
			
		||||
	if (stc != NULL)
 | 
			
		||||
		state->STC[number] = stc;
 | 
			
		||||
	if (mrc != NULL)
 | 
			
		||||
		state->MRC[number] = mrc;
 | 
			
		||||
	if (mcr != NULL)
 | 
			
		||||
		state->MCR[number] = mcr;
 | 
			
		||||
	if (mrrc != NULL)
 | 
			
		||||
		state->MRRC[number] = mrrc;
 | 
			
		||||
	if (mcrr != NULL)
 | 
			
		||||
		state->MCRR[number] = mcrr;
 | 
			
		||||
	if (cdp != NULL)
 | 
			
		||||
		state->CDP[number] = cdp;
 | 
			
		||||
	if (read != NULL)
 | 
			
		||||
		state->CPRead[number] = read;
 | 
			
		||||
	if (write != NULL)
 | 
			
		||||
		state->CPWrite[number] = write;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ARMul_CoProDetach (ARMul_State * state, unsigned number)
 | 
			
		||||
{
 | 
			
		||||
	ARMul_CoProAttach (state, number, NULL, NULL,
 | 
			
		||||
			   NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
 | 
			
		||||
			   NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	state->CPInit[number] = NULL;
 | 
			
		||||
	state->CPExit[number] = NULL;
 | 
			
		||||
	state->CPRead[number] = NULL;
 | 
			
		||||
	state->CPWrite[number] = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//chy 2003-09-03:below funs just replace the old ones
 | 
			
		||||
 | 
			
		||||
/* Set the XScale FSR and FAR registers.  */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far)
 | 
			
		||||
{
 | 
			
		||||
	//if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
 | 
			
		||||
	if (!state->is_XScale)
 | 
			
		||||
		return;
 | 
			
		||||
	//assume opcode2=0 crm =0
 | 
			
		||||
	xscale_cp15_write_reg (state, 5, fsr);
 | 
			
		||||
	xscale_cp15_write_reg (state, 6, _far);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????
 | 
			
		||||
int
 | 
			
		||||
XScale_debug_moe (ARMul_State * state, int moe)
 | 
			
		||||
{
 | 
			
		||||
	//chy 2003-09-03 , W/R CP14 reg, now it's no use ????
 | 
			
		||||
	printf ("SKYEYE: XScale_debug_moe called !!!!\n");
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
@ -23,17 +23,6 @@
 | 
			
		||||
#include "armemu.h"
 | 
			
		||||
#include "armos.h"
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword _far)
 | 
			
		||||
{
 | 
			
		||||
    _dbg_assert_msg_(ARM11, false, "ImplementMe: XScale_set_fsr_far!");
 | 
			
		||||
    //if (!state->is_XScale || (read_cp14_reg(10) & (1UL << 31)) == 0)
 | 
			
		||||
    //    return;
 | 
			
		||||
    //
 | 
			
		||||
    //write_cp15_reg(state, 5, 0, 0, fsr);
 | 
			
		||||
    //write_cp15_reg(state, 6, 0, 0, _far);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ARMul_Debug(x,y,z) 0 // Disabling this /bunnei
 | 
			
		||||
 | 
			
		||||
//#include "skyeye_callback.h"
 | 
			
		||||
@ -5536,14 +5525,15 @@ Handle_Load_Double (ARMul_State * state, ARMword instr)
 | 
			
		||||
        addr = base;
 | 
			
		||||
 | 
			
		||||
    /* The address must be aligned on a 8 byte boundary.  */
 | 
			
		||||
    if (addr & 0x7) {
 | 
			
		||||
#ifdef ABORTS
 | 
			
		||||
        ARMul_DATAABORT (addr);
 | 
			
		||||
#else
 | 
			
		||||
        ARMul_UndefInstr (state, instr);
 | 
			
		||||
#endif
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // FIX(Normatt): Disable strict alignment on LDRD/STRD
 | 
			
		||||
//    if (addr & 0x7) {
 | 
			
		||||
//#ifdef ABORTS
 | 
			
		||||
//        ARMul_DATAABORT (addr);
 | 
			
		||||
//#else
 | 
			
		||||
//        ARMul_UndefInstr (state, instr);
 | 
			
		||||
//#endif
 | 
			
		||||
//        return;
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    /* For pre indexed or post indexed addressing modes,
 | 
			
		||||
       check that the destination registers do not overlap
 | 
			
		||||
@ -5640,14 +5630,15 @@ Handle_Store_Double (ARMul_State * state, ARMword instr)
 | 
			
		||||
        addr = base;
 | 
			
		||||
 | 
			
		||||
    /* The address must be aligned on a 8 byte boundary.  */
 | 
			
		||||
    if (addr & 0x7) {
 | 
			
		||||
#ifdef ABORTS
 | 
			
		||||
        ARMul_DATAABORT (addr);
 | 
			
		||||
#else
 | 
			
		||||
        ARMul_UndefInstr (state, instr);
 | 
			
		||||
#endif
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // FIX(Normatt): Disable strict alignment on LDRD/STRD
 | 
			
		||||
//    if (addr & 0x7) {
 | 
			
		||||
//#ifdef ABORTS
 | 
			
		||||
//        ARMul_DATAABORT (addr);
 | 
			
		||||
//#else
 | 
			
		||||
//        ARMul_UndefInstr (state, instr);
 | 
			
		||||
//#endif
 | 
			
		||||
//        return;
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    /* For pre indexed or post indexed addressing modes,
 | 
			
		||||
       check that the destination registers do not overlap
 | 
			
		||||
@ -6405,6 +6396,8 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
 | 
			
		||||
        if (state->Aborted) {
 | 
			
		||||
            TAKEABORT;
 | 
			
		||||
        }
 | 
			
		||||
        // FIX(Normmatt): Handle RD in STREX/STREXB
 | 
			
		||||
        state->Reg[DESTReg] = 0; //Always succeed
 | 
			
		||||
 | 
			
		||||
        return 1;
 | 
			
		||||
     }
 | 
			
		||||
@ -6432,7 +6425,8 @@ handle_v6_insn (ARMul_State * state, ARMword instr)
 | 
			
		||||
        if (state->Aborted) {
 | 
			
		||||
            TAKEABORT;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // FIX(Normmatt): Handle RD in STREX/STREXB
 | 
			
		||||
        state->Reg[DESTReg] = 0; //Always succeed
 | 
			
		||||
        //printf("In %s, strexb not implemented\n", __FUNCTION__);
 | 
			
		||||
        UNDEF_LSRBPC;
 | 
			
		||||
        /* WRITESDEST (dest); */
 | 
			
		||||
 | 
			
		||||
@ -17,9 +17,9 @@
 | 
			
		||||
#ifndef __ARMEMU_H__
 | 
			
		||||
#define __ARMEMU_H__
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
#include "armdefs.h"
 | 
			
		||||
//#include "skyeye.h"
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/skyeye_defs.h"
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
extern ARMword isize;
 | 
			
		||||
 | 
			
		||||
@ -73,9 +73,7 @@ extern ARMword isize;
 | 
			
		||||
#define ASSIGNT(res) state->TFlag = res
 | 
			
		||||
#define INSN_SIZE (TFLAG ? 2 : 4)
 | 
			
		||||
#else
 | 
			
		||||
#define TBIT (1L << 5)
 | 
			
		||||
#define INSN_SIZE 4
 | 
			
		||||
#define TFLAG 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*add armv6 CPSR  feature*/
 | 
			
		||||
@ -166,6 +164,7 @@ extern ARMword isize;
 | 
			
		||||
#define PCWRAP(pc) ((pc) & R15PCBITS)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PC (state->Reg[15] & PCMASK)
 | 
			
		||||
#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS))
 | 
			
		||||
#define R15INT (state->Reg[15] & R15INTBITS)
 | 
			
		||||
#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS))
 | 
			
		||||
@ -180,11 +179,11 @@ extern ARMword isize;
 | 
			
		||||
#define ER15INT (IFFLAGS << 26)
 | 
			
		||||
#define EMODE (state->Mode)
 | 
			
		||||
 | 
			
		||||
//#ifdef MODET
 | 
			
		||||
//#define CPSR (ECC | EINT | EMODE | (TFLAG << 5))
 | 
			
		||||
//#else
 | 
			
		||||
//#define CPSR (ECC | EINT | EMODE)
 | 
			
		||||
//#endif
 | 
			
		||||
#ifdef MODET
 | 
			
		||||
#define CPSR (ECC | EINT | EMODE | (TFLAG << 5))
 | 
			
		||||
#else
 | 
			
		||||
#define CPSR (ECC | EINT | EMODE)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MODE32
 | 
			
		||||
#define PATCHR15
 | 
			
		||||
@ -240,12 +239,12 @@ extern ARMword isize;
 | 
			
		||||
    }									\
 | 
			
		||||
  while (0)
 | 
			
		||||
 | 
			
		||||
//#ifndef MODE32
 | 
			
		||||
#ifndef MODE32
 | 
			
		||||
#define VECTORS 0x20
 | 
			
		||||
#define LEGALADDR 0x03ffffff
 | 
			
		||||
#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
 | 
			
		||||
#define ADDREXCEPT(address)   (address > LEGALADDR && !state->data32Sig)
 | 
			
		||||
//#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define INTERNALABORT(address)			\
 | 
			
		||||
  do						\
 | 
			
		||||
@ -420,12 +419,10 @@ extern ARMword isize;
 | 
			
		||||
     || (! (STATE)->is_XScale)				\
 | 
			
		||||
     || (read_cp15_reg (15, 0, 1) & (1 << (CP))))
 | 
			
		||||
*/
 | 
			
		||||
//#define CP_ACCESS_ALLOWED(STATE, CP)			\
 | 
			
		||||
//	(((CP) >= 14)					\
 | 
			
		||||
//	|| (!(STATE)->is_XScale)				\
 | 
			
		||||
//	|| (xscale_cp15_cp_access_allowed(STATE, 15, CP)))
 | 
			
		||||
 | 
			
		||||
#define CP_ACCESS_ALLOWED(STATE, CP) false // Disabled coprocessor shit /bunnei
 | 
			
		||||
#define CP_ACCESS_ALLOWED(STATE, CP)			\
 | 
			
		||||
    (   ((CP) >= 14)					\
 | 
			
		||||
     || (! (STATE)->is_XScale)				\
 | 
			
		||||
     || (xscale_cp15_cp_access_allowed(STATE,15,CP)))
 | 
			
		||||
 | 
			
		||||
/* Macro to rotate n right by b bits.  */
 | 
			
		||||
#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
 | 
			
		||||
@ -517,7 +514,7 @@ tdstate;
 | 
			
		||||
 * out-of-updated with the newer ISA.
 | 
			
		||||
 * -- Michael.Kang
 | 
			
		||||
 ********************************************************************************/
 | 
			
		||||
#define UNDEF_WARNING ERROR_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n");
 | 
			
		||||
#define UNDEF_WARNING WARN_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n");
 | 
			
		||||
 | 
			
		||||
/* Macros to scrutinize instructions.  */
 | 
			
		||||
#define UNDEF_Test UNDEF_WARNING
 | 
			
		||||
 | 
			
		||||
@ -23,8 +23,8 @@
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#include "armdefs.h"
 | 
			
		||||
#include "armemu.h"
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
#include "core/arm/interpreter/armemu.h"
 | 
			
		||||
 | 
			
		||||
/***************************************************************************\
 | 
			
		||||
*                 Definitions for the emulator architecture                 *
 | 
			
		||||
@ -271,7 +271,7 @@ below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function
 | 
			
		||||
 | 
			
		||||
	/* Only initialse the coprocessor support once we
 | 
			
		||||
	   know what kind of chip we are dealing with.  */
 | 
			
		||||
	//ARMul_CoProInit (state); Commented out /bunnei
 | 
			
		||||
	ARMul_CoProInit (state);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -318,7 +318,7 @@ ARMul_Reset (ARMul_State * state)
 | 
			
		||||
	state->NumFcycles = 0;
 | 
			
		||||
 | 
			
		||||
	//fprintf(stderr,"armul_reset 3: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);  
 | 
			
		||||
	//mmu_reset (state); Commented out /bunnei
 | 
			
		||||
	mmu_reset (state);
 | 
			
		||||
	//fprintf(stderr,"armul_reset 4: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);  
 | 
			
		||||
 | 
			
		||||
	//mem_reset (state); /* move to memory/ram.c */
 | 
			
		||||
 | 
			
		||||
@ -172,18 +172,18 @@ typedef struct mmu_ops_s
 | 
			
		||||
} mmu_ops_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "core/arm/mmu/tlb.h"
 | 
			
		||||
#include "core/arm/mmu/rb.h"
 | 
			
		||||
#include "core/arm/mmu/wb.h"
 | 
			
		||||
#include "core/arm/mmu/cache.h"
 | 
			
		||||
#include "core/arm/interpreter/mmu/tlb.h"
 | 
			
		||||
#include "core/arm/interpreter/mmu/rb.h"
 | 
			
		||||
#include "core/arm/interpreter/mmu/wb.h"
 | 
			
		||||
#include "core/arm/interpreter/mmu/cache.h"
 | 
			
		||||
 | 
			
		||||
/*special process mmu.h*/
 | 
			
		||||
//#include "core/arm/mmu/sa_mmu.h"
 | 
			
		||||
//#include "core/arm/mmu/arm7100_mmu.h"
 | 
			
		||||
//#include "core/arm/mmu/arm920t_mmu.h"
 | 
			
		||||
//#include "core/arm/mmu/arm926ejs_mmu.h"
 | 
			
		||||
#include "core/arm/mmu/arm1176jzf_s_mmu.h"
 | 
			
		||||
//#include "core/arm/mmu/cortex_a9_mmu.h"
 | 
			
		||||
#include "core/arm/interpreter/mmu/sa_mmu.h"
 | 
			
		||||
//#include "core/arm/interpreter/mmu/arm7100_mmu.h"
 | 
			
		||||
//#include "core/arm/interpreter/mmu/arm920t_mmu.h"
 | 
			
		||||
//#include "core/arm/interpreter/mmu/arm926ejs_mmu.h"
 | 
			
		||||
#include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h"
 | 
			
		||||
//#include "core/arm/interpreter/mmu/cortex_a9_mmu.h"
 | 
			
		||||
 | 
			
		||||
typedef struct mmu_state_t
 | 
			
		||||
{
 | 
			
		||||
@ -213,13 +213,13 @@ typedef struct mmu_state_t
 | 
			
		||||
	ARMword copro_access;	// 15
 | 
			
		||||
 | 
			
		||||
	mmu_ops_t ops;
 | 
			
		||||
	//union
 | 
			
		||||
	//{
 | 
			
		||||
		//sa_mmu_t sa_mmu;
 | 
			
		||||
	union
 | 
			
		||||
	{
 | 
			
		||||
		sa_mmu_t sa_mmu;
 | 
			
		||||
		//arm7100_mmu_t arm7100_mmu;
 | 
			
		||||
		//arm920t_mmu_t arm920t_mmu;
 | 
			
		||||
		//arm926ejs_mmu_t arm926ejs_mmu;
 | 
			
		||||
	//} u;
 | 
			
		||||
	} u;
 | 
			
		||||
} mmu_state_t;
 | 
			
		||||
 | 
			
		||||
int mmu_init (ARMul_State * state);
 | 
			
		||||
 | 
			
		||||
@ -15,12 +15,10 @@
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 | 
			
		||||
 | 
			
		||||
#include "armdefs.h"
 | 
			
		||||
#include "armemu.h"
 | 
			
		||||
 | 
			
		||||
//#include "ansidecl.h"
 | 
			
		||||
#include "skyeye_defs.h"
 | 
			
		||||
#include "core/hle/mrc.h"
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
#include "core/arm/interpreter/armemu.h"
 | 
			
		||||
#include "core/arm/interpreter/skyeye_defs.h"
 | 
			
		||||
#include "core/hle/coprocessor.h"
 | 
			
		||||
#include "core/arm/disassembler/arm_disasm.h"
 | 
			
		||||
 | 
			
		||||
unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
 | 
			
		||||
@ -127,8 +125,7 @@ ARMul_GetCPSR (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	//chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator
 | 
			
		||||
	//return (CPSR | state->Cpsr); for gdb20030716
 | 
			
		||||
    // NOTE(bunnei): Changed this from [now] commented out macro "CPSR"
 | 
			
		||||
    return ((ECC | EINT | EMODE | (TFLAG << 5)));	//had be tested in old skyeye with gdb5.0-5.3
 | 
			
		||||
	return (CPSR);		//had be tested in old skyeye with gdb5.0-5.3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This routine sets the value of the CPSR.  */
 | 
			
		||||
@ -145,7 +142,7 @@ ARMul_SetCPSR (ARMul_State * state, ARMword value)
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
 | 
			
		||||
{  
 | 
			
		||||
{
 | 
			
		||||
	state->Cpsr = ARMul_GetCPSR (state);
 | 
			
		||||
	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
 | 
			
		||||
	if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
 | 
			
		||||
@ -500,8 +497,8 @@ ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ADDREXCEPT (address))
 | 
			
		||||
		INTERNALABORT (address);
 | 
			
		||||
	//if (ADDREXCEPT (address))
 | 
			
		||||
	//	INTERNALABORT (address);
 | 
			
		||||
 | 
			
		||||
	cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
 | 
			
		||||
	while (cpab == ARMul_BUSY) {
 | 
			
		||||
@ -594,8 +591,8 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ADDREXCEPT (address) || VECTORACCESS (address))
 | 
			
		||||
		INTERNALABORT (address);
 | 
			
		||||
	//if (ADDREXCEPT (address) || VECTORACCESS (address))
 | 
			
		||||
	//	INTERNALABORT (address);
 | 
			
		||||
 | 
			
		||||
	cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
 | 
			
		||||
	while (cpab == ARMul_BUSY) {
 | 
			
		||||
@ -739,39 +736,43 @@ ARMul_MRC (ARMul_State * state, ARMword instr)
 | 
			
		||||
{
 | 
			
		||||
	unsigned cpab;
 | 
			
		||||
 | 
			
		||||
	ARMword result = HLE::CallMRC((HLE::ARM11_MRC_OPERATION)BITS(20, 27));
 | 
			
		||||
	ARMword result = HLE::CallMRC(instr);
 | 
			
		||||
 | 
			
		||||
	////printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
 | 
			
		||||
	//if (!CP_ACCESS_ALLOWED (state, CPNum)) {
 | 
			
		||||
	//	//chy 2004-07-19 should fix in the future????!!!!
 | 
			
		||||
	//	//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr  CPnum is %x, instr %x\n",CPNum, instr);
 | 
			
		||||
	//	ARMul_UndefInstr (state, instr);
 | 
			
		||||
	//	return -1;
 | 
			
		||||
	//}
 | 
			
		||||
	if (result != -1) {
 | 
			
		||||
		return result;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
 | 
			
		||||
	//while (cpab == ARMul_BUSY) {
 | 
			
		||||
	//	ARMul_Icycles (state, 1, 0);
 | 
			
		||||
	//	if (IntPending (state)) {
 | 
			
		||||
	//		cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
 | 
			
		||||
	//					    instr, 0);
 | 
			
		||||
	//		return (0);
 | 
			
		||||
	//	}
 | 
			
		||||
	//	else
 | 
			
		||||
	//		cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
 | 
			
		||||
	//					    &result);
 | 
			
		||||
	//}
 | 
			
		||||
	//if (cpab == ARMul_CANT) {
 | 
			
		||||
	//	printf ("SKYEYE ARMul_MRC,CANT UndefInstr  CPnum is %x, instr %x\n", CPNum, instr);
 | 
			
		||||
	//	ARMul_Abort (state, ARMul_UndefinedInstrV);
 | 
			
		||||
	//	/* Parent will destroy the flags otherwise.  */
 | 
			
		||||
	//	result = ECC;
 | 
			
		||||
	//}
 | 
			
		||||
	//else {
 | 
			
		||||
	//	BUSUSEDINCPCN;
 | 
			
		||||
	//	ARMul_Ccycles (state, 1, 0);
 | 
			
		||||
	//	ARMul_Icycles (state, 1, 0);
 | 
			
		||||
	//}
 | 
			
		||||
	//printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
 | 
			
		||||
	if (!CP_ACCESS_ALLOWED (state, CPNum)) {
 | 
			
		||||
		//chy 2004-07-19 should fix in the future????!!!!
 | 
			
		||||
		//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr  CPnum is %x, instr %x\n",CPNum, instr);
 | 
			
		||||
		ARMul_UndefInstr (state, instr);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
 | 
			
		||||
	while (cpab == ARMul_BUSY) {
 | 
			
		||||
		ARMul_Icycles (state, 1, 0);
 | 
			
		||||
		if (IntPending (state)) {
 | 
			
		||||
			cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
 | 
			
		||||
						    instr, 0);
 | 
			
		||||
			return (0);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
 | 
			
		||||
						    &result);
 | 
			
		||||
	}
 | 
			
		||||
	if (cpab == ARMul_CANT) {
 | 
			
		||||
		printf ("SKYEYE ARMul_MRC,CANT UndefInstr  CPnum is %x, instr %x\n", CPNum, instr);
 | 
			
		||||
		ARMul_Abort (state, ARMul_UndefinedInstrV);
 | 
			
		||||
		/* Parent will destroy the flags otherwise.  */
 | 
			
		||||
		result = ECC;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		BUSUSEDINCPCN;
 | 
			
		||||
		ARMul_Ccycles (state, 1, 0);
 | 
			
		||||
		ARMul_Icycles (state, 1, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
@ -906,9 +907,7 @@ ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
 | 
			
		||||
		state->Now = ARMul_Time (state);
 | 
			
		||||
	when = (state->Now + delay) % EVENTLISTSIZE;
 | 
			
		||||
	event = (struct EventNode *) malloc (sizeof (struct EventNode));
 | 
			
		||||
 | 
			
		||||
	_dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n");
 | 
			
		||||
 | 
			
		||||
	event->func = what;
 | 
			
		||||
	event->next = *(state->EventPtr + when);
 | 
			
		||||
	*(state->EventPtr + when) = event;
 | 
			
		||||
 | 
			
		||||
@ -355,7 +355,7 @@ arm1176jzf_s_mmu_load_instr (ARMul_State *state, ARMword va, ARMword *instr)
 | 
			
		||||
 | 
			
		||||
    static int debug_count = 0;    /* used for debug */
 | 
			
		||||
 | 
			
		||||
    DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
    //DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
 | 
			
		||||
    va = mmu_pid_va_map (va);
 | 
			
		||||
    if (MMU_Enabled) {
 | 
			
		||||
@ -444,7 +444,7 @@ arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, ARMword *data,
 | 
			
		||||
    ARMword perm;        /* physical addr access permissions */
 | 
			
		||||
    int ap, sop;
 | 
			
		||||
 | 
			
		||||
    DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
    //DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
 | 
			
		||||
    va = mmu_pid_va_map (va);
 | 
			
		||||
    real_va = va;
 | 
			
		||||
@ -629,7 +629,7 @@ arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, ARMword data,
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
 | 
			
		||||
    //DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
 | 
			
		||||
    va = mmu_pid_va_map (va);
 | 
			
		||||
    real_va = va;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										370
									
								
								src/core/arm/interpreter/mmu/cache.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								src/core/arm/interpreter/mmu/cache.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,370 @@
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
/* mmu cache init
 | 
			
		||||
 *
 | 
			
		||||
 * @cache_t :cache_t to init
 | 
			
		||||
 * @width	:cache line width in byte
 | 
			
		||||
 * @way		:way of each cache set
 | 
			
		||||
 * @set		:cache set num
 | 
			
		||||
 *
 | 
			
		||||
 * $ -1: error
 | 
			
		||||
 * 	 0: sucess
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
	cache_set_t *sets;
 | 
			
		||||
	cache_line_t *lines;
 | 
			
		||||
 | 
			
		||||
	/*alloc cache set */
 | 
			
		||||
	sets = NULL;
 | 
			
		||||
	lines = NULL;
 | 
			
		||||
	//fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets);
 | 
			
		||||
	//exit(-1);
 | 
			
		||||
	sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set);
 | 
			
		||||
	if (sets == NULL) {
 | 
			
		||||
		ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set);
 | 
			
		||||
		goto sets_error;
 | 
			
		||||
	}
 | 
			
		||||
	//fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets);
 | 
			
		||||
	cache_t->sets = sets;
 | 
			
		||||
 | 
			
		||||
	/*init cache set */
 | 
			
		||||
	for (i = 0; i < set; i++) {
 | 
			
		||||
		/*alloc cache line */
 | 
			
		||||
		lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way);
 | 
			
		||||
		if (lines == NULL) {
 | 
			
		||||
			ERROR_LOG(ARM11, "line malloc size %d\n",
 | 
			
		||||
				 sizeof (cache_line_t) * way);
 | 
			
		||||
			goto lines_error;
 | 
			
		||||
		}
 | 
			
		||||
		/*init cache line */
 | 
			
		||||
		for (j = 0; j < way; j++) {
 | 
			
		||||
			lines[j].tag = 0;	//invalid
 | 
			
		||||
			lines[j].data = (ARMword *) malloc (width);
 | 
			
		||||
			if (lines[j].data == NULL) {
 | 
			
		||||
				ERROR_LOG(ARM11, "data alloc size %d\n", width);
 | 
			
		||||
				goto data_error;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sets[i].lines = lines;
 | 
			
		||||
		sets[i].cycle = 0;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	cache_t->width = width;
 | 
			
		||||
	cache_t->set = set;
 | 
			
		||||
	cache_t->way = way;
 | 
			
		||||
	cache_t->w_mode = w_mode;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
      data_error:
 | 
			
		||||
	/*free data */
 | 
			
		||||
	while (j-- > 0)
 | 
			
		||||
		free (lines[j].data);
 | 
			
		||||
	/*free data error line */
 | 
			
		||||
	free (lines);
 | 
			
		||||
      lines_error:
 | 
			
		||||
	/*free lines already alloced */
 | 
			
		||||
	while (i-- > 0) {
 | 
			
		||||
		for (j = 0; j < way; j++)
 | 
			
		||||
			free (sets[i].lines[j].data);
 | 
			
		||||
		free (sets[i].lines);
 | 
			
		||||
	}
 | 
			
		||||
	/*free sets */
 | 
			
		||||
	free (sets);
 | 
			
		||||
      sets_error:
 | 
			
		||||
	return -1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* free a cache_t's inner data, the ptr self is not freed,
 | 
			
		||||
 * when needed do like below:
 | 
			
		||||
 * 		mmu_cache_exit(cache);
 | 
			
		||||
 * 		free(cache_t);
 | 
			
		||||
 *
 | 
			
		||||
 * @cache_t : the cache_t to free
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_exit (cache_s * cache_t)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
	cache_set_t *sets, *set;
 | 
			
		||||
	cache_line_t *lines, *line;
 | 
			
		||||
 | 
			
		||||
	/*free all set */
 | 
			
		||||
	sets = cache_t->sets;
 | 
			
		||||
	for (set = sets, i = 0; i < cache_t->set; i++, set++) {
 | 
			
		||||
		/*free all line */
 | 
			
		||||
		lines = set->lines;
 | 
			
		||||
		for (line = lines, j = 0; j < cache_t->way; j++, line++)
 | 
			
		||||
			free (line->data);
 | 
			
		||||
		free (lines);
 | 
			
		||||
	}
 | 
			
		||||
	free (sets);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* mmu cache search
 | 
			
		||||
 *
 | 
			
		||||
 * @state	:ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to search
 | 
			
		||||
 * @va		:virtual address
 | 
			
		||||
 *
 | 
			
		||||
 * $	NULL:	no cache match
 | 
			
		||||
 * 		cache	:cache matched
 | 
			
		||||
 */
 | 
			
		||||
cache_line_t *
 | 
			
		||||
mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int set = va_cache_set (va, cache_t);
 | 
			
		||||
	ARMword tag = va_cache_align (va, cache_t);
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
 | 
			
		||||
	cache_set_t *cache_set = cache_t->sets + set;
 | 
			
		||||
	for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) {
 | 
			
		||||
		if ((cache->tag & TAG_VALID_FLAG)
 | 
			
		||||
		    && (tag == va_cache_align (cache->tag, cache_t)))
 | 
			
		||||
			return cache;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* mmu cache search by set/index
 | 
			
		||||
 *
 | 
			
		||||
 * @state	:ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to search
 | 
			
		||||
 * @index	:set/index value. 
 | 
			
		||||
 *
 | 
			
		||||
 * $	NULL:	no cache match
 | 
			
		||||
 * 		cache	:cache matched
 | 
			
		||||
 */
 | 
			
		||||
cache_line_t *
 | 
			
		||||
mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t,
 | 
			
		||||
			   ARMword index)
 | 
			
		||||
{
 | 
			
		||||
	int way = cache_t->way;
 | 
			
		||||
	int set_v = index_cache_set (index, cache_t);
 | 
			
		||||
	int i = 0, index_v = 0;
 | 
			
		||||
	cache_set_t *set;
 | 
			
		||||
 | 
			
		||||
	while ((way >>= 1) >= 1)
 | 
			
		||||
		i++;
 | 
			
		||||
	index_v = index >> (32 - i);
 | 
			
		||||
	set = cache_t->sets + set_v;
 | 
			
		||||
 | 
			
		||||
	return set->lines + index_v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* mmu cache alloc
 | 
			
		||||
 *
 | 
			
		||||
 * @state :ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to alloc from
 | 
			
		||||
 * @va		:virtual address that require cache alloc, need not cache aligned
 | 
			
		||||
 * @pa		:physical address of va
 | 
			
		||||
 *
 | 
			
		||||
 * $	cache_alloced, always alloc OK
 | 
			
		||||
 */
 | 
			
		||||
cache_line_t *
 | 
			
		||||
mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va,
 | 
			
		||||
		 ARMword pa)
 | 
			
		||||
{
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
	cache_set_t *set;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	va = va_cache_align (va, cache_t);
 | 
			
		||||
	pa = va_cache_align (pa, cache_t);
 | 
			
		||||
 | 
			
		||||
	set = &cache_t->sets[va_cache_set (va, cache_t)];
 | 
			
		||||
 | 
			
		||||
	/*robin-round */
 | 
			
		||||
	cache = &set->lines[set->cycle++];
 | 
			
		||||
	if (set->cycle == cache_t->way)
 | 
			
		||||
		set->cycle = 0;
 | 
			
		||||
 | 
			
		||||
	if (cache_t->w_mode == CACHE_WRITE_BACK) {
 | 
			
		||||
		ARMword t;
 | 
			
		||||
 | 
			
		||||
		/*if cache valid, try to write back */
 | 
			
		||||
		if (cache->tag & TAG_VALID_FLAG) {
 | 
			
		||||
			mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
		}
 | 
			
		||||
		/*read in cache_line */
 | 
			
		||||
		t = pa;
 | 
			
		||||
		for (i = 0; i < (cache_t->width >> WORD_SHT);
 | 
			
		||||
		     i++, t += WORD_SIZE) {
 | 
			
		||||
			//cache->data[i] = mem_read_word (state, t);
 | 
			
		||||
			bus_read(32, t, &cache->data[i]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/*store tag and pa */
 | 
			
		||||
	cache->tag = va | TAG_VALID_FLAG;
 | 
			
		||||
	cache->pa = pa;
 | 
			
		||||
 | 
			
		||||
	return cache;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* mmu_cache_write_back write cache data to memory
 | 
			
		||||
 * @state
 | 
			
		||||
 * @cache_t :cache_t of the cache line
 | 
			
		||||
 * @cache : cache line
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_write_back (ARMul_State * state, cache_s * cache_t,
 | 
			
		||||
		      cache_line_t * cache)
 | 
			
		||||
{
 | 
			
		||||
	ARMword pa = cache->pa;
 | 
			
		||||
	int nw = cache_t->width >> WORD_SHT;
 | 
			
		||||
	ARMword *data = cache->data;
 | 
			
		||||
	int i;
 | 
			
		||||
	int t0, t1, t2;
 | 
			
		||||
 | 
			
		||||
	if ((cache->tag & 1) == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	switch (cache->
 | 
			
		||||
		tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return;
 | 
			
		||||
	case TAG_FIRST_HALF_DIRTY:
 | 
			
		||||
		nw /= 2;
 | 
			
		||||
		break;
 | 
			
		||||
	case TAG_LAST_HALF_DIRTY:
 | 
			
		||||
		nw /= 2;
 | 
			
		||||
		pa += nw << WORD_SHT;
 | 
			
		||||
		data += nw;
 | 
			
		||||
		break;
 | 
			
		||||
	case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	for (i = 0; i < nw; i++, data++, pa += WORD_SIZE)
 | 
			
		||||
		//mem_write_word (state, pa, *data);
 | 
			
		||||
		bus_write(32, pa, *data);
 | 
			
		||||
 | 
			
		||||
	cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* mmu_cache_clean: clean a cache of va in cache_t
 | 
			
		||||
 *
 | 
			
		||||
 * @state	:ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to clean
 | 
			
		||||
 * @va		:virtaul address
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va)
 | 
			
		||||
{
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
 | 
			
		||||
	cache = mmu_cache_search (state, cache_t, va);
 | 
			
		||||
	if (cache)
 | 
			
		||||
		mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* mmu_cache_clean_by_index: clean a cache by set/index format value
 | 
			
		||||
 *
 | 
			
		||||
 * @state	:ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to clean
 | 
			
		||||
 * @va		:set/index format value
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t,
 | 
			
		||||
			  ARMword index)
 | 
			
		||||
{
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
 | 
			
		||||
	cache = mmu_cache_search_by_index (state, cache_t, index);
 | 
			
		||||
	if (cache)
 | 
			
		||||
		mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* mmu_cache_invalidate : invalidate a cache of va
 | 
			
		||||
 *
 | 
			
		||||
 * @state	:ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to invalid
 | 
			
		||||
 * @va		:virt_addr to invalid
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va)
 | 
			
		||||
{
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
 | 
			
		||||
	cache = mmu_cache_search (state, cache_t, va);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
		cache->tag = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* mmu_cache_invalidate_by_index : invalidate a cache by index format
 | 
			
		||||
 *
 | 
			
		||||
 * @state	:ARMul_State
 | 
			
		||||
 * @cache_t	:cache_t to invalid
 | 
			
		||||
 * @index	:set/index data
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t,
 | 
			
		||||
			       ARMword index)
 | 
			
		||||
{
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
 | 
			
		||||
	cache = mmu_cache_search_by_index (state, cache_t, index);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
		cache->tag = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* mmu_cache_invalidate_all
 | 
			
		||||
 *
 | 
			
		||||
 * @state:
 | 
			
		||||
 * @cache_t
 | 
			
		||||
 * */
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
	cache_set_t *set;
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
 | 
			
		||||
	set = cache_t->sets;
 | 
			
		||||
	for (i = 0; i < cache_t->set; i++, set++) {
 | 
			
		||||
		cache = set->lines;
 | 
			
		||||
		for (j = 0; j < cache_t->way; j++, cache++) {
 | 
			
		||||
			mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
			cache->tag = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa)
 | 
			
		||||
{
 | 
			
		||||
	ARMword set, way;
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
	pa = (pa / cache_t->width);
 | 
			
		||||
	way = pa & (cache_t->way - 1);
 | 
			
		||||
	set = (pa / cache_t->way) & (cache_t->set - 1);
 | 
			
		||||
	cache = &cache_t->sets[set].lines[way];
 | 
			
		||||
 | 
			
		||||
	mmu_cache_write_back (state, cache_t, cache);
 | 
			
		||||
	cache->tag = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cache_line_t*  mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){
 | 
			
		||||
	int i;
 | 
			
		||||
	int j;
 | 
			
		||||
	cache_line_t *cache_line = NULL;
 | 
			
		||||
	cache_set_t *cache_set = cache->sets;
 | 
			
		||||
	int sets = cache->set;
 | 
			
		||||
	for (i = 0; i < sets; i++){
 | 
			
		||||
		for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){
 | 
			
		||||
			if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY))
 | 
			
		||||
				return cache_line;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1206
									
								
								src/core/arm/interpreter/mmu/maverick.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1206
									
								
								src/core/arm/interpreter/mmu/maverick.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										126
									
								
								src/core/arm/interpreter/mmu/rb.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/core/arm/interpreter/mmu/rb.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,126 @@
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/
 | 
			
		||||
ARMword rb_masks[] = {
 | 
			
		||||
	0x0,			//RB_INVALID
 | 
			
		||||
	4,			//RB_1
 | 
			
		||||
	16,			//RB_4
 | 
			
		||||
	32,			//RB_8
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*mmu_rb_init
 | 
			
		||||
 * @rb_t	:rb_t to init
 | 
			
		||||
 * @num		:number of entry
 | 
			
		||||
 * */
 | 
			
		||||
int
 | 
			
		||||
mmu_rb_init (rb_s * rb_t, int num)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	rb_entry_t *entrys;
 | 
			
		||||
 | 
			
		||||
	entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num);
 | 
			
		||||
	if (entrys == NULL) {
 | 
			
		||||
		printf ("SKYEYE:mmu_rb_init malloc error\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	for (i = 0; i < num; i++) {
 | 
			
		||||
		entrys[i].type = RB_INVALID;
 | 
			
		||||
		entrys[i].fault = NO_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rb_t->entrys = entrys;
 | 
			
		||||
	rb_t->num = num;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*mmu_rb_exit*/
 | 
			
		||||
void
 | 
			
		||||
mmu_rb_exit (rb_s * rb_t)
 | 
			
		||||
{
 | 
			
		||||
	free (rb_t->entrys);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*mmu_rb_search
 | 
			
		||||
 * @rb_t	:rb_t to serach
 | 
			
		||||
 * @va		:va address to math
 | 
			
		||||
 *
 | 
			
		||||
 * $	NULL :not match
 | 
			
		||||
 * 		NO-NULL:
 | 
			
		||||
 * */
 | 
			
		||||
rb_entry_t *
 | 
			
		||||
mmu_rb_search (rb_s * rb_t, ARMword va)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	rb_entry_t *rb = rb_t->entrys;
 | 
			
		||||
 | 
			
		||||
	DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
	for (i = 0; i < rb_t->num; i++, rb++) {
 | 
			
		||||
		//2004-06-06 lyh  bug from wenye@cs.ucsb.edu
 | 
			
		||||
		if (rb->type) {
 | 
			
		||||
			if ((va >= rb->va)
 | 
			
		||||
			    && (va < (rb->va + rb_masks[rb->type])))
 | 
			
		||||
				return rb;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_rb_invalidate_entry (rb_s * rb_t, int i)
 | 
			
		||||
{
 | 
			
		||||
	rb_t->entrys[i].type = RB_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_rb_invalidate_all (rb_s * rb_t)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < rb_t->num; i++)
 | 
			
		||||
		mmu_rb_invalidate_entry (rb_t, i);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va)
 | 
			
		||||
{
 | 
			
		||||
	rb_entry_t *rb;
 | 
			
		||||
	int i;
 | 
			
		||||
	ARMword max_start, min_end;
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
	tlb_entry_t *tlb;
 | 
			
		||||
 | 
			
		||||
	/*align va according to type */
 | 
			
		||||
	va &= ~(rb_masks[type] - 1);
 | 
			
		||||
	/*invalidate all RB match [va, va + rb_masks[type]] */
 | 
			
		||||
	for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) {
 | 
			
		||||
		if (rb->type) {
 | 
			
		||||
			max_start = max (va, rb->va);
 | 
			
		||||
			min_end =
 | 
			
		||||
				min (va + rb_masks[type],
 | 
			
		||||
				     rb->va + rb_masks[rb->type]);
 | 
			
		||||
			if (max_start < min_end)
 | 
			
		||||
				rb->type = RB_INVALID;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/*load word */
 | 
			
		||||
	rb = &rb_t->entrys[i_rb];
 | 
			
		||||
	rb->type = type;
 | 
			
		||||
	fault = translate (state, va, D_TLB (), &tlb);
 | 
			
		||||
	if (fault) {
 | 
			
		||||
		rb->fault = fault;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	fault = check_access (state, va, tlb, 1);
 | 
			
		||||
	if (fault) {
 | 
			
		||||
		rb->fault = fault;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rb->fault = NO_FAULT;
 | 
			
		||||
	va = tlb_va_to_pa (tlb, va);
 | 
			
		||||
	//2004-06-06 lyh  bug from wenye@cs.ucsb.edu
 | 
			
		||||
	for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) {
 | 
			
		||||
		//rb->data[i] = mem_read_word (state, va);
 | 
			
		||||
		bus_read(32, va, &rb->data[i]);
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										864
									
								
								src/core/arm/interpreter/mmu/sa_mmu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										864
									
								
								src/core/arm/interpreter/mmu/sa_mmu.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,864 @@
 | 
			
		||||
/*
 | 
			
		||||
    armmmu.c - Memory Management Unit emulation.
 | 
			
		||||
    ARMulator extensions for the ARM7100 family.
 | 
			
		||||
    Copyright (C) 1999  Ben Williamson
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  The interface of read data from bus
 | 
			
		||||
 */
 | 
			
		||||
int bus_read(short size, int addr, uint32_t * value) {
 | 
			
		||||
    ERROR_LOG(ARM11, "unimplemented bus_read");
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The interface of write data from bus
 | 
			
		||||
 */
 | 
			
		||||
int bus_write(short size, int addr, uint32_t value) {
 | 
			
		||||
    ERROR_LOG(ARM11, "unimplemented bus_write");
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct sa_mmu_desc_s
 | 
			
		||||
{
 | 
			
		||||
	int i_tlb;
 | 
			
		||||
	cache_desc_t i_cache;
 | 
			
		||||
 | 
			
		||||
	int d_tlb;
 | 
			
		||||
	cache_desc_t main_d_cache;
 | 
			
		||||
	cache_desc_t mini_d_cache;
 | 
			
		||||
	int rb;
 | 
			
		||||
	wb_desc_t wb;
 | 
			
		||||
} sa_mmu_desc_t;
 | 
			
		||||
 | 
			
		||||
static sa_mmu_desc_t sa11xx_mmu_desc = {
 | 
			
		||||
	32,
 | 
			
		||||
	{32, 32, 16, CACHE_WRITE_BACK},
 | 
			
		||||
 | 
			
		||||
	32,
 | 
			
		||||
	{32, 32, 8, CACHE_WRITE_BACK},
 | 
			
		||||
	{32, 2, 8, CACHE_WRITE_BACK},
 | 
			
		||||
	4,
 | 
			
		||||
	//{8, 4},  for word size 
 | 
			
		||||
	{8, 16},		//for byte size,   chy 2003-07-11
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data,
 | 
			
		||||
			     ARMword datatype);
 | 
			
		||||
static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
 | 
			
		||||
			    ARMword datatype);
 | 
			
		||||
static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data,
 | 
			
		||||
			     ARMword datatype, cache_line_t * cache,
 | 
			
		||||
			     cache_s * cache_t, ARMword real_va);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
 | 
			
		||||
		    ARMbyte * data, int n);
 | 
			
		||||
int
 | 
			
		||||
sa_mmu_init (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	sa_mmu_desc_t *desc;
 | 
			
		||||
	cache_desc_t *c_desc;
 | 
			
		||||
 | 
			
		||||
	state->mmu.control = 0x70;
 | 
			
		||||
	state->mmu.translation_table_base = 0xDEADC0DE;
 | 
			
		||||
	state->mmu.domain_access_control = 0xDEADC0DE;
 | 
			
		||||
	state->mmu.fault_status = 0;
 | 
			
		||||
	state->mmu.fault_address = 0;
 | 
			
		||||
	state->mmu.process_id = 0;
 | 
			
		||||
 | 
			
		||||
	desc = &sa11xx_mmu_desc;
 | 
			
		||||
	if (mmu_tlb_init (I_TLB (), desc->i_tlb)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "i_tlb init %d\n", -1);
 | 
			
		||||
		goto i_tlb_init_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c_desc = &desc->i_cache;
 | 
			
		||||
	if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way,
 | 
			
		||||
			    c_desc->set, c_desc->w_mode)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "i_cache init %d\n", -1);
 | 
			
		||||
		goto i_cache_init_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mmu_tlb_init (D_TLB (), desc->d_tlb)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "d_tlb init %d\n", -1);
 | 
			
		||||
		goto d_tlb_init_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c_desc = &desc->main_d_cache;
 | 
			
		||||
	if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way,
 | 
			
		||||
			    c_desc->set, c_desc->w_mode)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "main_d_cache init %d\n", -1);
 | 
			
		||||
		goto main_d_cache_init_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c_desc = &desc->mini_d_cache;
 | 
			
		||||
	if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way,
 | 
			
		||||
			    c_desc->set, c_desc->w_mode)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1);
 | 
			
		||||
		goto mini_d_cache_init_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "wb init %d\n", -1);
 | 
			
		||||
		goto wb_init_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mmu_rb_init (RB (), desc->rb)) {
 | 
			
		||||
		ERROR_LOG(ARM11, "rb init %d\n", -1);
 | 
			
		||||
		goto rb_init_error;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
      rb_init_error:
 | 
			
		||||
	mmu_wb_exit (WB ());
 | 
			
		||||
      wb_init_error:
 | 
			
		||||
	mmu_cache_exit (MINI_D_CACHE ());
 | 
			
		||||
      mini_d_cache_init_error:
 | 
			
		||||
	mmu_cache_exit (MAIN_D_CACHE ());
 | 
			
		||||
      main_d_cache_init_error:
 | 
			
		||||
	mmu_tlb_exit (D_TLB ());
 | 
			
		||||
      d_tlb_init_error:
 | 
			
		||||
	mmu_cache_exit (I_CACHE ());
 | 
			
		||||
      i_cache_init_error:
 | 
			
		||||
	mmu_tlb_exit (I_TLB ());
 | 
			
		||||
      i_tlb_init_error:
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
sa_mmu_exit (ARMul_State * state)
 | 
			
		||||
{
 | 
			
		||||
	mmu_rb_exit (RB ());
 | 
			
		||||
	mmu_wb_exit (WB ());
 | 
			
		||||
	mmu_cache_exit (MINI_D_CACHE ());
 | 
			
		||||
	mmu_cache_exit (MAIN_D_CACHE ());
 | 
			
		||||
	mmu_tlb_exit (D_TLB ());
 | 
			
		||||
	mmu_cache_exit (I_CACHE ());
 | 
			
		||||
	mmu_tlb_exit (I_TLB ());
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr)
 | 
			
		||||
{
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
	tlb_entry_t *tlb;
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
	int c;			//cache bit
 | 
			
		||||
	ARMword pa;		//physical addr
 | 
			
		||||
 | 
			
		||||
	static int debug_count = 0;	//used for debug
 | 
			
		||||
 | 
			
		||||
	DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
 | 
			
		||||
	va = mmu_pid_va_map (va);
 | 
			
		||||
	if (MMU_Enabled) {
 | 
			
		||||
		/*align check */
 | 
			
		||||
		if ((va & (WORD_SIZE - 1)) && MMU_Aligned) {
 | 
			
		||||
			DEBUG_LOG(ARM11, "align\n");
 | 
			
		||||
			return ALIGNMENT_FAULT;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			va &= ~(WORD_SIZE - 1);
 | 
			
		||||
 | 
			
		||||
		/*translate tlb */
 | 
			
		||||
		fault = translate (state, va, I_TLB (), &tlb);
 | 
			
		||||
		if (fault) {
 | 
			
		||||
			DEBUG_LOG(ARM11, "translate\n");
 | 
			
		||||
			return fault;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*check access */
 | 
			
		||||
		fault = check_access (state, va, tlb, 1);
 | 
			
		||||
		if (fault) {
 | 
			
		||||
			DEBUG_LOG(ARM11, "check_fault\n");
 | 
			
		||||
			return fault;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*search cache no matter MMU enabled/disabled */
 | 
			
		||||
	cache = mmu_cache_search (state, I_CACHE (), va);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		*instr = cache->data[va_cache_index (va, I_CACHE ())];
 | 
			
		||||
		return NO_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*if MMU disabled or C flag is set alloc cache */
 | 
			
		||||
	if (MMU_Disabled) {
 | 
			
		||||
		c = 1;
 | 
			
		||||
		pa = va;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		c = tlb_c_flag (tlb);
 | 
			
		||||
		pa = tlb_va_to_pa (tlb, va);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (c) {
 | 
			
		||||
		int index;
 | 
			
		||||
 | 
			
		||||
		debug_count++;
 | 
			
		||||
		cache = mmu_cache_alloc (state, I_CACHE (), va, pa);
 | 
			
		||||
		index = va_cache_index (va, I_CACHE ());
 | 
			
		||||
		*instr = cache->data[va_cache_index (va, I_CACHE ())];
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		//*instr = mem_read_word (state, pa);
 | 
			
		||||
		bus_read(32, pa, instr);
 | 
			
		||||
 | 
			
		||||
	return NO_FAULT;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data)
 | 
			
		||||
{
 | 
			
		||||
	//ARMword temp,offset;
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
	fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);
 | 
			
		||||
	return fault;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data)
 | 
			
		||||
{
 | 
			
		||||
	//ARMword temp,offset;
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
	fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);
 | 
			
		||||
	return fault;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data)
 | 
			
		||||
{
 | 
			
		||||
	return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data,
 | 
			
		||||
	     ARMword datatype)
 | 
			
		||||
{
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
	rb_entry_t *rb;
 | 
			
		||||
	tlb_entry_t *tlb;
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
	ARMword pa, real_va, temp, offset;
 | 
			
		||||
 | 
			
		||||
	DEBUG_LOG(ARM11, "va = %x\n", va);
 | 
			
		||||
 | 
			
		||||
	va = mmu_pid_va_map (va);
 | 
			
		||||
	real_va = va;
 | 
			
		||||
	/*if MMU disabled, memory_read */
 | 
			
		||||
	if (MMU_Disabled) {
 | 
			
		||||
		//*data = mem_read_word(state, va);
 | 
			
		||||
		if (datatype == ARM_BYTE_TYPE)
 | 
			
		||||
			//*data = mem_read_byte (state, va);
 | 
			
		||||
			bus_read(8, va, data);
 | 
			
		||||
		else if (datatype == ARM_HALFWORD_TYPE)
 | 
			
		||||
			//*data = mem_read_halfword (state, va);
 | 
			
		||||
			bus_read(16, va, data);
 | 
			
		||||
		else if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
			//*data = mem_read_word (state, va);
 | 
			
		||||
			bus_read(32, va, data);
 | 
			
		||||
		else {
 | 
			
		||||
			printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype);
 | 
			
		||||
			// skyeye_exit (-1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return NO_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*align check */
 | 
			
		||||
	if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
 | 
			
		||||
	    ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
 | 
			
		||||
		DEBUG_LOG(ARM11, "align\n");
 | 
			
		||||
		return ALIGNMENT_FAULT;
 | 
			
		||||
	}			// else
 | 
			
		||||
 | 
			
		||||
	va &= ~(WORD_SIZE - 1);
 | 
			
		||||
 | 
			
		||||
	/*translate va to tlb */
 | 
			
		||||
	fault = translate (state, va, D_TLB (), &tlb);
 | 
			
		||||
	if (fault) {
 | 
			
		||||
		DEBUG_LOG(ARM11, "translate\n");
 | 
			
		||||
		return fault;
 | 
			
		||||
	}
 | 
			
		||||
	/*check access permission */
 | 
			
		||||
	fault = check_access (state, va, tlb, 1);
 | 
			
		||||
	if (fault)
 | 
			
		||||
		return fault;
 | 
			
		||||
	/*search in read buffer */
 | 
			
		||||
	rb = mmu_rb_search (RB (), va);
 | 
			
		||||
	if (rb) {
 | 
			
		||||
		if (rb->fault)
 | 
			
		||||
			return rb->fault;
 | 
			
		||||
		*data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT];
 | 
			
		||||
		goto datatrans;
 | 
			
		||||
		//return 0;
 | 
			
		||||
	};
 | 
			
		||||
	/*search main cache */
 | 
			
		||||
	cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		*data = cache->data[va_cache_index (va, MAIN_D_CACHE ())];
 | 
			
		||||
		goto datatrans;
 | 
			
		||||
		//return 0;
 | 
			
		||||
	}
 | 
			
		||||
	/*search mini cache */
 | 
			
		||||
	cache = mmu_cache_search (state, MINI_D_CACHE (), va);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		*data = cache->data[va_cache_index (va, MINI_D_CACHE ())];
 | 
			
		||||
		goto datatrans;
 | 
			
		||||
		//return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*get phy_addr */
 | 
			
		||||
	pa = tlb_va_to_pa (tlb, va);
 | 
			
		||||
	if ((pa >= 0xe0000000) && (pa < 0xe8000000)) {
 | 
			
		||||
		if (tlb_c_flag (tlb)) {
 | 
			
		||||
			if (tlb_b_flag (tlb)) {
 | 
			
		||||
				mmu_cache_soft_flush (state, MAIN_D_CACHE (),
 | 
			
		||||
						      pa);
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				mmu_cache_soft_flush (state, MINI_D_CACHE (),
 | 
			
		||||
						      pa);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return NO_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*if Buffer, drain Write Buffer first */
 | 
			
		||||
	if (tlb_b_flag (tlb))
 | 
			
		||||
		mmu_wb_drain_all (state, WB ());
 | 
			
		||||
 | 
			
		||||
	/*alloc cache or mem_read */
 | 
			
		||||
	if (tlb_c_flag (tlb) && MMU_DCacheEnabled) {
 | 
			
		||||
		cache_s *cache_t;
 | 
			
		||||
 | 
			
		||||
		if (tlb_b_flag (tlb))
 | 
			
		||||
			cache_t = MAIN_D_CACHE ();
 | 
			
		||||
		else
 | 
			
		||||
			cache_t = MINI_D_CACHE ();
 | 
			
		||||
		cache = mmu_cache_alloc (state, cache_t, va, pa);
 | 
			
		||||
		*data = cache->data[va_cache_index (va, cache_t)];
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		//*data = mem_read_word(state, pa);
 | 
			
		||||
		if (datatype == ARM_BYTE_TYPE)
 | 
			
		||||
			//*data = mem_read_byte (state, pa | (real_va & 3));
 | 
			
		||||
			bus_read(8, pa | (real_va & 3), data);
 | 
			
		||||
		else if (datatype == ARM_HALFWORD_TYPE)
 | 
			
		||||
			//*data = mem_read_halfword (state, pa | (real_va & 2));
 | 
			
		||||
			bus_read(16, pa | (real_va & 2), data);
 | 
			
		||||
		else if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
			//*data = mem_read_word (state, pa);
 | 
			
		||||
			bus_read(32, pa, data);
 | 
			
		||||
		else {
 | 
			
		||||
			printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype);
 | 
			
		||||
			// skyeye_exit (-1);
 | 
			
		||||
		}
 | 
			
		||||
		return NO_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      datatrans:
 | 
			
		||||
	if (datatype == ARM_HALFWORD_TYPE) {
 | 
			
		||||
		temp = *data;
 | 
			
		||||
		offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3;	/* bit offset into the word */
 | 
			
		||||
		*data = (temp >> offset) & 0xffff;
 | 
			
		||||
	}
 | 
			
		||||
	else if (datatype == ARM_BYTE_TYPE) {
 | 
			
		||||
		temp = *data;
 | 
			
		||||
		offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3;	/* bit offset into the word */
 | 
			
		||||
		*data = (temp >> offset & 0xffL);
 | 
			
		||||
	}
 | 
			
		||||
      end:
 | 
			
		||||
	return NO_FAULT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data)
 | 
			
		||||
{
 | 
			
		||||
	return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data)
 | 
			
		||||
{
 | 
			
		||||
	return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data)
 | 
			
		||||
{
 | 
			
		||||
	return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype)
 | 
			
		||||
{
 | 
			
		||||
	tlb_entry_t *tlb;
 | 
			
		||||
	cache_line_t *cache;
 | 
			
		||||
	int b;
 | 
			
		||||
	ARMword pa, real_va;
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
 | 
			
		||||
	DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data);
 | 
			
		||||
	va = mmu_pid_va_map (va);
 | 
			
		||||
	real_va = va;
 | 
			
		||||
 | 
			
		||||
	/*search instruction cache */
 | 
			
		||||
	cache = mmu_cache_search (state, I_CACHE (), va);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		update_cache (state, va, data, datatype, cache, I_CACHE (),
 | 
			
		||||
			      real_va);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (MMU_Disabled) {
 | 
			
		||||
		//mem_write_word(state, va, data);
 | 
			
		||||
		if (datatype == ARM_BYTE_TYPE)
 | 
			
		||||
			//mem_write_byte (state, va, data);
 | 
			
		||||
			bus_write(8, va, data);
 | 
			
		||||
		else if (datatype == ARM_HALFWORD_TYPE)
 | 
			
		||||
			//mem_write_halfword (state, va, data);
 | 
			
		||||
			bus_write(16, va, data);
 | 
			
		||||
		else if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
			//mem_write_word (state, va, data);
 | 
			
		||||
			bus_write(32, va, data);
 | 
			
		||||
		else {
 | 
			
		||||
			printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype);
 | 
			
		||||
			// skyeye_exit (-1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return NO_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
	/*align check */
 | 
			
		||||
	//if ((va & (WORD_SIZE - 1)) && MMU_Aligned){
 | 
			
		||||
	if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
 | 
			
		||||
	    ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) {
 | 
			
		||||
		DEBUG_LOG(ARM11, "align\n");
 | 
			
		||||
		return ALIGNMENT_FAULT;
 | 
			
		||||
	}			//else
 | 
			
		||||
	va &= ~(WORD_SIZE - 1);
 | 
			
		||||
	/*tlb translate */
 | 
			
		||||
	fault = translate (state, va, D_TLB (), &tlb);
 | 
			
		||||
	if (fault) {
 | 
			
		||||
		DEBUG_LOG(ARM11, "translate\n");
 | 
			
		||||
		return fault;
 | 
			
		||||
	}
 | 
			
		||||
	/*tlb check access */
 | 
			
		||||
	fault = check_access (state, va, tlb, 0);
 | 
			
		||||
	if (fault) {
 | 
			
		||||
		DEBUG_LOG(ARM11, "check_access\n");
 | 
			
		||||
		return fault;
 | 
			
		||||
	}
 | 
			
		||||
	/*search main cache */
 | 
			
		||||
	cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		update_cache (state, va, data, datatype, cache,
 | 
			
		||||
			      MAIN_D_CACHE (), real_va);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		/*search mini cache */
 | 
			
		||||
		cache = mmu_cache_search (state, MINI_D_CACHE (), va);
 | 
			
		||||
		if (cache) {
 | 
			
		||||
			update_cache (state, va, data, datatype, cache,
 | 
			
		||||
				      MINI_D_CACHE (), real_va);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!cache) {
 | 
			
		||||
		b = tlb_b_flag (tlb);
 | 
			
		||||
		pa = tlb_va_to_pa (tlb, va);
 | 
			
		||||
		if (b) {
 | 
			
		||||
			if (MMU_WBEnabled) {
 | 
			
		||||
				if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
					mmu_wb_write_bytes (state, WB (), pa,
 | 
			
		||||
							    (ARMbyte*)&data, 4);
 | 
			
		||||
				else if (datatype == ARM_HALFWORD_TYPE)
 | 
			
		||||
					mmu_wb_write_bytes (state, WB (),
 | 
			
		||||
							    (pa |
 | 
			
		||||
							     (real_va & 2)),
 | 
			
		||||
							    (ARMbyte*)&data, 2);
 | 
			
		||||
				else if (datatype == ARM_BYTE_TYPE)
 | 
			
		||||
					mmu_wb_write_bytes (state, WB (),
 | 
			
		||||
							    (pa |
 | 
			
		||||
							     (real_va & 3)),
 | 
			
		||||
							    (ARMbyte*)&data, 1);
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
					//mem_write_word (state, pa, data);
 | 
			
		||||
					bus_write(32, pa, data);
 | 
			
		||||
				else if (datatype == ARM_HALFWORD_TYPE)
 | 
			
		||||
					/*
 | 
			
		||||
					mem_write_halfword (state,
 | 
			
		||||
							    (pa |
 | 
			
		||||
							     (real_va & 2)),
 | 
			
		||||
							    data);
 | 
			
		||||
					*/
 | 
			
		||||
					bus_write(16, pa | (real_va & 2), data);
 | 
			
		||||
				else if (datatype == ARM_BYTE_TYPE)
 | 
			
		||||
					/*
 | 
			
		||||
					mem_write_byte (state,
 | 
			
		||||
							(pa | (real_va & 3)),
 | 
			
		||||
							data);
 | 
			
		||||
					*/
 | 
			
		||||
					bus_write(8, pa | (real_va & 3), data);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			mmu_wb_drain_all (state, WB ());
 | 
			
		||||
 | 
			
		||||
			if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
				//mem_write_word (state, pa, data);
 | 
			
		||||
				bus_write(32, pa, data);
 | 
			
		||||
			else if (datatype == ARM_HALFWORD_TYPE)
 | 
			
		||||
				/*
 | 
			
		||||
					mem_write_halfword (state,
 | 
			
		||||
						    (pa | (real_va & 2)),
 | 
			
		||||
						    data);
 | 
			
		||||
				*/
 | 
			
		||||
				bus_write(16, pa | (real_va & 2), data);
 | 
			
		||||
			else if (datatype == ARM_BYTE_TYPE)
 | 
			
		||||
				/*
 | 
			
		||||
				mem_write_byte (state, (pa | (real_va & 3)),
 | 
			
		||||
						data);
 | 
			
		||||
				*/
 | 
			
		||||
				bus_write(8, pa | (real_va & 3), data);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NO_FAULT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static fault_t
 | 
			
		||||
update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype,
 | 
			
		||||
	      cache_line_t * cache, cache_s * cache_t, ARMword real_va)
 | 
			
		||||
{
 | 
			
		||||
	ARMword temp, offset;
 | 
			
		||||
 | 
			
		||||
	ARMword index = va_cache_index (va, cache_t);
 | 
			
		||||
 | 
			
		||||
	//cache->data[index] = data;
 | 
			
		||||
 | 
			
		||||
	if (datatype == ARM_WORD_TYPE)
 | 
			
		||||
		cache->data[index] = data;
 | 
			
		||||
	else if (datatype == ARM_HALFWORD_TYPE) {
 | 
			
		||||
		temp = cache->data[index];
 | 
			
		||||
		offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3;	/* bit offset into the word */
 | 
			
		||||
		cache->data[index] =
 | 
			
		||||
			(temp & ~(0xffffL << offset)) | ((data & 0xffffL) <<
 | 
			
		||||
							 offset);
 | 
			
		||||
	}
 | 
			
		||||
	else if (datatype == ARM_BYTE_TYPE) {
 | 
			
		||||
		temp = cache->data[index];
 | 
			
		||||
		offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3;	/* bit offset into the word */
 | 
			
		||||
		cache->data[index] =
 | 
			
		||||
			(temp & ~(0xffL << offset)) | ((data & 0xffL) <<
 | 
			
		||||
						       offset);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (index < (cache_t->width >> (WORD_SHT + 1)))
 | 
			
		||||
		cache->tag |= TAG_FIRST_HALF_DIRTY;
 | 
			
		||||
	else
 | 
			
		||||
		cache->tag |= TAG_LAST_HALF_DIRTY;
 | 
			
		||||
 | 
			
		||||
	return NO_FAULT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ARMword
 | 
			
		||||
sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
 | 
			
		||||
{
 | 
			
		||||
	mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
 | 
			
		||||
	ARMword data;
 | 
			
		||||
 | 
			
		||||
	switch (creg) {
 | 
			
		||||
	case MMU_ID:
 | 
			
		||||
//              printf("mmu_mrc read ID     ");
 | 
			
		||||
		data = 0x41007100;	/* v3 */
 | 
			
		||||
		data = state->cpu->cpu_val;
 | 
			
		||||
		break;
 | 
			
		||||
	case MMU_CONTROL:
 | 
			
		||||
//              printf("mmu_mrc read CONTROL");
 | 
			
		||||
		data = state->mmu.control;
 | 
			
		||||
		break;
 | 
			
		||||
	case MMU_TRANSLATION_TABLE_BASE:
 | 
			
		||||
//              printf("mmu_mrc read TTB    ");
 | 
			
		||||
		data = state->mmu.translation_table_base;
 | 
			
		||||
		break;
 | 
			
		||||
	case MMU_DOMAIN_ACCESS_CONTROL:
 | 
			
		||||
//              printf("mmu_mrc read DACR   ");
 | 
			
		||||
		data = state->mmu.domain_access_control;
 | 
			
		||||
		break;
 | 
			
		||||
	case MMU_FAULT_STATUS:
 | 
			
		||||
//              printf("mmu_mrc read FSR    ");
 | 
			
		||||
		data = state->mmu.fault_status;
 | 
			
		||||
		break;
 | 
			
		||||
	case MMU_FAULT_ADDRESS:
 | 
			
		||||
//              printf("mmu_mrc read FAR    ");
 | 
			
		||||
		data = state->mmu.fault_address;
 | 
			
		||||
		break;
 | 
			
		||||
	case MMU_PID:
 | 
			
		||||
		data = state->mmu.process_id;
 | 
			
		||||
	default:
 | 
			
		||||
		printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);
 | 
			
		||||
		data = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
//      printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]);
 | 
			
		||||
	*value = data;
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	int CRm, OPC_2;
 | 
			
		||||
 | 
			
		||||
	CRm = BITS (0, 3);
 | 
			
		||||
	OPC_2 = BITS (5, 7);
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0 && CRm == 7) {
 | 
			
		||||
		mmu_cache_invalidate_all (state, I_CACHE ());
 | 
			
		||||
		mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
 | 
			
		||||
		mmu_cache_invalidate_all (state, MINI_D_CACHE ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0 && CRm == 5) {
 | 
			
		||||
		mmu_cache_invalidate_all (state, I_CACHE ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0 && CRm == 6) {
 | 
			
		||||
		mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
 | 
			
		||||
		mmu_cache_invalidate_all (state, MINI_D_CACHE ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 1 && CRm == 6) {
 | 
			
		||||
		mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
 | 
			
		||||
		mmu_cache_invalidate (state, MINI_D_CACHE (), value);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 1 && CRm == 0xa) {
 | 
			
		||||
		mmu_cache_clean (state, MAIN_D_CACHE (), value);
 | 
			
		||||
		mmu_cache_clean (state, MINI_D_CACHE (), value);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 4 && CRm == 0xa) {
 | 
			
		||||
		mmu_wb_drain_all (state, WB ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	int CRm, OPC_2;
 | 
			
		||||
 | 
			
		||||
	CRm = BITS (0, 3);
 | 
			
		||||
	OPC_2 = BITS (5, 7);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0 && CRm == 0x7) {
 | 
			
		||||
		mmu_tlb_invalidate_all (state, I_TLB ());
 | 
			
		||||
		mmu_tlb_invalidate_all (state, D_TLB ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0 && CRm == 0x5) {
 | 
			
		||||
		mmu_tlb_invalidate_all (state, I_TLB ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0 && CRm == 0x6) {
 | 
			
		||||
		mmu_tlb_invalidate_all (state, D_TLB ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 1 && CRm == 0x6) {
 | 
			
		||||
		mmu_tlb_invalidate_entry (state, D_TLB (), value);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	int CRm, OPC_2;
 | 
			
		||||
 | 
			
		||||
	CRm = BITS (0, 3);
 | 
			
		||||
	OPC_2 = BITS (5, 7);
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0x0 && CRm == 0x0) {
 | 
			
		||||
		mmu_rb_invalidate_all (RB ());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (OPC_2 == 0x2) {
 | 
			
		||||
		int idx = CRm & 0x3;
 | 
			
		||||
		int type = ((CRm >> 2) & 0x3) + 1;
 | 
			
		||||
 | 
			
		||||
		if ((idx < 4) && (type < 4))
 | 
			
		||||
			mmu_rb_load (state, RB (), idx, type, value);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((OPC_2 == 1) && (CRm < 4)) {
 | 
			
		||||
		mmu_rb_invalidate_entry (RB (), CRm);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ARMword
 | 
			
		||||
sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15);
 | 
			
		||||
	if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) {
 | 
			
		||||
		switch (creg) {
 | 
			
		||||
		case MMU_CONTROL:
 | 
			
		||||
//              printf("mmu_mcr wrote CONTROL      ");
 | 
			
		||||
			state->mmu.control = (value | 0x70) & 0xFFFD;
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_TRANSLATION_TABLE_BASE:
 | 
			
		||||
//              printf("mmu_mcr wrote TTB          ");
 | 
			
		||||
			state->mmu.translation_table_base =
 | 
			
		||||
				value & 0xFFFFC000;
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_DOMAIN_ACCESS_CONTROL:
 | 
			
		||||
//              printf("mmu_mcr wrote DACR         ");
 | 
			
		||||
			state->mmu.domain_access_control = value;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case MMU_FAULT_STATUS:
 | 
			
		||||
			state->mmu.fault_status = value & 0xFF;
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_FAULT_ADDRESS:
 | 
			
		||||
			state->mmu.fault_address = value;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case MMU_CACHE_OPS:
 | 
			
		||||
			sa_mmu_cache_ops (state, instr, value);
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_TLB_OPS:
 | 
			
		||||
			sa_mmu_tlb_ops (state, instr, value);
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_SA_RB_OPS:
 | 
			
		||||
			sa_mmu_rb_ops (state, instr, value);
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_SA_DEBUG:
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_SA_CP15_R15:
 | 
			
		||||
			break;
 | 
			
		||||
		case MMU_PID:
 | 
			
		||||
			//2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu
 | 
			
		||||
			state->mmu.process_id = value & 0x7e000000;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//teawater add for arm2x86 2005.06.24-------------------------------------------
 | 
			
		||||
static int
 | 
			
		||||
sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
 | 
			
		||||
{
 | 
			
		||||
	fault_t fault;
 | 
			
		||||
	tlb_entry_t *tlb;
 | 
			
		||||
 | 
			
		||||
	virt_addr = mmu_pid_va_map (virt_addr);
 | 
			
		||||
	if (MMU_Enabled) {
 | 
			
		||||
 | 
			
		||||
		/*align check */
 | 
			
		||||
		if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) {
 | 
			
		||||
			DEBUG_LOG(ARM11, "align\n");
 | 
			
		||||
			return ALIGNMENT_FAULT;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			virt_addr &= ~(WORD_SIZE - 1);
 | 
			
		||||
 | 
			
		||||
		/*translate tlb */
 | 
			
		||||
		fault = translate (state, virt_addr, I_TLB (), &tlb);
 | 
			
		||||
		if (fault) {
 | 
			
		||||
			DEBUG_LOG(ARM11, "translate\n");
 | 
			
		||||
			return fault;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*check access */
 | 
			
		||||
		fault = check_access (state, virt_addr, tlb, 1);
 | 
			
		||||
		if (fault) {
 | 
			
		||||
			DEBUG_LOG(ARM11, "check_fault\n");
 | 
			
		||||
			return fault;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (MMU_Disabled) {
 | 
			
		||||
		*phys_addr = virt_addr;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		*phys_addr = tlb_va_to_pa (tlb, virt_addr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//AJ2D--------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
/*sa mmu_ops_t*/
 | 
			
		||||
mmu_ops_t sa_mmu_ops = {
 | 
			
		||||
	sa_mmu_init,
 | 
			
		||||
	sa_mmu_exit,
 | 
			
		||||
	sa_mmu_read_byte,
 | 
			
		||||
	sa_mmu_write_byte,
 | 
			
		||||
	sa_mmu_read_halfword,
 | 
			
		||||
	sa_mmu_write_halfword,
 | 
			
		||||
	sa_mmu_read_word,
 | 
			
		||||
	sa_mmu_write_word,
 | 
			
		||||
	sa_mmu_load_instr,
 | 
			
		||||
	sa_mmu_mcr,
 | 
			
		||||
	sa_mmu_mrc,
 | 
			
		||||
//teawater add for arm2x86 2005.06.24-------------------------------------------
 | 
			
		||||
	sa_mmu_v2p_dbct,
 | 
			
		||||
//AJ2D--------------------------------------------------------------------------
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										58
									
								
								src/core/arm/interpreter/mmu/sa_mmu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/core/arm/interpreter/mmu/sa_mmu.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
/*
 | 
			
		||||
    sa_mmu.h - StrongARM Memory Management Unit emulation.
 | 
			
		||||
    ARMulator extensions for SkyEye.
 | 
			
		||||
	<lyhost@263.net>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef _SA_MMU_H_
 | 
			
		||||
#define _SA_MMU_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  The interface of read data from bus
 | 
			
		||||
 */
 | 
			
		||||
int bus_read(short size, int addr, uint32_t * value);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The interface of write data from bus
 | 
			
		||||
 */
 | 
			
		||||
int bus_write(short size, int addr, uint32_t value);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct sa_mmu_s
 | 
			
		||||
{
 | 
			
		||||
	tlb_s i_tlb;
 | 
			
		||||
	cache_s i_cache;
 | 
			
		||||
 | 
			
		||||
	tlb_s d_tlb;
 | 
			
		||||
	cache_s main_d_cache;
 | 
			
		||||
	cache_s mini_d_cache;
 | 
			
		||||
	rb_s rb_t;
 | 
			
		||||
	wb_s wb_t;
 | 
			
		||||
} sa_mmu_t;
 | 
			
		||||
 | 
			
		||||
#define I_TLB() (&state->mmu.u.sa_mmu.i_tlb)
 | 
			
		||||
#define I_CACHE() (&state->mmu.u.sa_mmu.i_cache)
 | 
			
		||||
 | 
			
		||||
#define D_TLB() (&state->mmu.u.sa_mmu.d_tlb)
 | 
			
		||||
#define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache)
 | 
			
		||||
#define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache)
 | 
			
		||||
#define WB() (&state->mmu.u.sa_mmu.wb_t)
 | 
			
		||||
#define RB() (&state->mmu.u.sa_mmu.rb_t)
 | 
			
		||||
 | 
			
		||||
extern mmu_ops_t sa_mmu_ops;
 | 
			
		||||
#endif /*_SA_MMU_H_*/
 | 
			
		||||
							
								
								
									
										307
									
								
								src/core/arm/interpreter/mmu/tlb.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								src/core/arm/interpreter/mmu/tlb.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,307 @@
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
ARMword tlb_masks[] = {
 | 
			
		||||
	0x00000000,		/* TLB_INVALID */
 | 
			
		||||
	0xFFFFF000,		/* TLB_SMALLPAGE */
 | 
			
		||||
	0xFFFF0000,		/* TLB_LARGEPAGE */
 | 
			
		||||
	0xFFF00000,		/* TLB_SECTION */
 | 
			
		||||
	0xFFFFF000,		/*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */
 | 
			
		||||
	0xFFFFFC00		/* TLB_TINYPAGE */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* This function encodes table 8-2 Interpreting AP bits,
 | 
			
		||||
   returning non-zero if access is allowed. */
 | 
			
		||||
static int
 | 
			
		||||
check_perms (ARMul_State * state, int ap, int read)
 | 
			
		||||
{
 | 
			
		||||
	int s, r, user;
 | 
			
		||||
 | 
			
		||||
	s = state->mmu.control & CONTROL_SYSTEM;
 | 
			
		||||
	r = state->mmu.control & CONTROL_ROM;
 | 
			
		||||
	//chy 2006-02-15 , should consider system mode, don't conside 26bit mode
 | 
			
		||||
	user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE);
 | 
			
		||||
 | 
			
		||||
	switch (ap) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		return read && ((s && !user) || r);
 | 
			
		||||
	case 1:
 | 
			
		||||
		return !user;
 | 
			
		||||
	case 2:
 | 
			
		||||
		return read || !user;
 | 
			
		||||
	case 3:
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fault_t
 | 
			
		||||
check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
 | 
			
		||||
	      int read)
 | 
			
		||||
{
 | 
			
		||||
	int access;
 | 
			
		||||
 | 
			
		||||
	state->mmu.last_domain = tlb->domain;
 | 
			
		||||
	access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3;
 | 
			
		||||
	if ((access == 0) || (access == 2)) {
 | 
			
		||||
		/* It's unclear from the documentation whether this
 | 
			
		||||
		   should always raise a section domain fault, or if
 | 
			
		||||
		   it should be a page domain fault in the case of an
 | 
			
		||||
		   L1 that describes a page table.  In the ARM710T
 | 
			
		||||
		   datasheets, "Figure 8-9: Sequence for checking faults"
 | 
			
		||||
		   seems to indicate the former, while "Table 8-4: Priority
 | 
			
		||||
		   encoding of fault status" gives a value for FS[3210] in
 | 
			
		||||
		   the event of a domain fault for a page.  Hmm. */
 | 
			
		||||
		return SECTION_DOMAIN_FAULT;
 | 
			
		||||
	}
 | 
			
		||||
	if (access == 1) {
 | 
			
		||||
		/* client access - check perms */
 | 
			
		||||
		int subpage, ap;
 | 
			
		||||
 | 
			
		||||
		switch (tlb->mapping) {
 | 
			
		||||
			/*ks 2004-05-09   
 | 
			
		||||
			 *   only for XScale
 | 
			
		||||
			 *   Extend Small Page(ESP) Format
 | 
			
		||||
			 *   31-12 bits    the base addr of ESP
 | 
			
		||||
			 *   11-10 bits    SBZ
 | 
			
		||||
			 *   9-6   bits    TEX
 | 
			
		||||
			 *   5-4   bits    AP
 | 
			
		||||
			 *   3     bit     C
 | 
			
		||||
			 *   2     bit     B
 | 
			
		||||
			 *   1-0   bits    11
 | 
			
		||||
			 * */
 | 
			
		||||
		case TLB_ESMALLPAGE:	//xj
 | 
			
		||||
			subpage = 0;
 | 
			
		||||
			//printf("TLB_ESMALLPAGE virt_addr=0x%x  \n",virt_addr );
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case TLB_TINYPAGE:
 | 
			
		||||
			subpage = 0;
 | 
			
		||||
			//printf("TLB_TINYPAGE virt_addr=0x%x  \n",virt_addr );
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case TLB_SMALLPAGE:
 | 
			
		||||
			subpage = (virt_addr >> 10) & 3;
 | 
			
		||||
			break;
 | 
			
		||||
		case TLB_LARGEPAGE:
 | 
			
		||||
			subpage = (virt_addr >> 14) & 3;
 | 
			
		||||
			break;
 | 
			
		||||
		case TLB_SECTION:
 | 
			
		||||
			subpage = 3;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			assert (0);
 | 
			
		||||
			subpage = 0;	/* cleans a warning */
 | 
			
		||||
		}
 | 
			
		||||
		ap = (tlb->perms >> (subpage * 2 + 4)) & 3;
 | 
			
		||||
		if (!check_perms (state, ap, read)) {
 | 
			
		||||
			if (tlb->mapping == TLB_SECTION) {
 | 
			
		||||
				return SECTION_PERMISSION_FAULT;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				return SUBPAGE_PERMISSION_FAULT;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else {			/* access == 3 */
 | 
			
		||||
		/* manager access - don't check perms */
 | 
			
		||||
	}
 | 
			
		||||
	return NO_FAULT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fault_t
 | 
			
		||||
translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t,
 | 
			
		||||
	   tlb_entry_t ** tlb)
 | 
			
		||||
{
 | 
			
		||||
	*tlb = mmu_tlb_search (state, tlb_t, virt_addr);
 | 
			
		||||
	if (!*tlb) {
 | 
			
		||||
		/* walk the translation tables */
 | 
			
		||||
		ARMword l1addr, l1desc;
 | 
			
		||||
		tlb_entry_t entry;
 | 
			
		||||
 | 
			
		||||
		l1addr = state->mmu.translation_table_base & 0xFFFFC000;
 | 
			
		||||
		l1addr = (l1addr | (virt_addr >> 18)) & ~3;
 | 
			
		||||
		//l1desc = mem_read_word (state, l1addr);
 | 
			
		||||
		bus_read(32, l1addr, &l1desc);
 | 
			
		||||
		switch (l1desc & 3) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			/* 
 | 
			
		||||
			 * according to Figure 3-9 Sequence for checking faults in arm manual,
 | 
			
		||||
			 * section translation fault should be returned here. 
 | 
			
		||||
			 */
 | 
			
		||||
			{
 | 
			
		||||
				return SECTION_TRANSLATION_FAULT;
 | 
			
		||||
			}
 | 
			
		||||
		case 3:
 | 
			
		||||
			/* fine page table */
 | 
			
		||||
			// dcl 2006-01-08
 | 
			
		||||
			{
 | 
			
		||||
				ARMword l2addr, l2desc;
 | 
			
		||||
 | 
			
		||||
				l2addr = l1desc & 0xFFFFF000;
 | 
			
		||||
				l2addr = (l2addr |
 | 
			
		||||
					  ((virt_addr & 0x000FFC00) >> 8)) &
 | 
			
		||||
					~3;
 | 
			
		||||
				//l2desc = mem_read_word (state, l2addr);				 
 | 
			
		||||
				bus_read(32, l2addr, &l2desc);
 | 
			
		||||
 | 
			
		||||
				entry.virt_addr = virt_addr;
 | 
			
		||||
				entry.phys_addr = l2desc;
 | 
			
		||||
				entry.perms = l2desc & 0x00000FFC;
 | 
			
		||||
				entry.domain = (l1desc >> 5) & 0x0000000F;
 | 
			
		||||
				switch (l2desc & 3) {
 | 
			
		||||
				case 0:
 | 
			
		||||
					state->mmu.last_domain = entry.domain;
 | 
			
		||||
					return PAGE_TRANSLATION_FAULT;
 | 
			
		||||
				case 3:
 | 
			
		||||
					entry.mapping = TLB_TINYPAGE;
 | 
			
		||||
					break;
 | 
			
		||||
				case 1:
 | 
			
		||||
					// this is untested
 | 
			
		||||
					entry.mapping = TLB_LARGEPAGE;
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					// this is untested
 | 
			
		||||
					entry.mapping = TLB_SMALLPAGE;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 1:
 | 
			
		||||
			/* coarse page table */
 | 
			
		||||
			{
 | 
			
		||||
				ARMword l2addr, l2desc;
 | 
			
		||||
 | 
			
		||||
				l2addr = l1desc & 0xFFFFFC00;
 | 
			
		||||
				l2addr = (l2addr |
 | 
			
		||||
					  ((virt_addr & 0x000FF000) >> 10)) &
 | 
			
		||||
					~3;
 | 
			
		||||
				//l2desc = mem_read_word (state, l2addr);
 | 
			
		||||
				bus_read(32, l2addr, &l2desc);
 | 
			
		||||
 | 
			
		||||
				entry.virt_addr = virt_addr;
 | 
			
		||||
				entry.phys_addr = l2desc;
 | 
			
		||||
				entry.perms = l2desc & 0x00000FFC;
 | 
			
		||||
				entry.domain = (l1desc >> 5) & 0x0000000F;
 | 
			
		||||
				//printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr);
 | 
			
		||||
				//chy 2003-09-02 for xscale
 | 
			
		||||
				switch (l2desc & 3) {
 | 
			
		||||
				case 0:
 | 
			
		||||
					state->mmu.last_domain = entry.domain;
 | 
			
		||||
					return PAGE_TRANSLATION_FAULT;
 | 
			
		||||
				case 3:
 | 
			
		||||
					if (!state->is_XScale) {
 | 
			
		||||
						state->mmu.last_domain =
 | 
			
		||||
							entry.domain;
 | 
			
		||||
						return PAGE_TRANSLATION_FAULT;
 | 
			
		||||
					};
 | 
			
		||||
					//ks 2004-05-09 xscale shold use Extend Small Page
 | 
			
		||||
					//entry.mapping = TLB_SMALLPAGE;
 | 
			
		||||
					entry.mapping = TLB_ESMALLPAGE;	//xj
 | 
			
		||||
					break;
 | 
			
		||||
				case 1:
 | 
			
		||||
					entry.mapping = TLB_LARGEPAGE;
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					entry.mapping = TLB_SMALLPAGE;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case 2:
 | 
			
		||||
			/* section */
 | 
			
		||||
			//printf("SKYEYE:WARNING: not implement section mapping incompletely\n");
 | 
			
		||||
			//printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc);
 | 
			
		||||
			//return SECTION_DOMAIN_FAULT;
 | 
			
		||||
			//#if 0
 | 
			
		||||
			entry.virt_addr = virt_addr;
 | 
			
		||||
			entry.phys_addr = l1desc;
 | 
			
		||||
			entry.perms = l1desc & 0x00000C0C;
 | 
			
		||||
			entry.domain = (l1desc >> 5) & 0x0000000F;
 | 
			
		||||
			entry.mapping = TLB_SECTION;
 | 
			
		||||
			break;
 | 
			
		||||
			//#endif
 | 
			
		||||
		}
 | 
			
		||||
		entry.virt_addr &= tlb_masks[entry.mapping];
 | 
			
		||||
		entry.phys_addr &= tlb_masks[entry.mapping];
 | 
			
		||||
 | 
			
		||||
		/* place entry in the tlb */
 | 
			
		||||
		*tlb = &tlb_t->entrys[tlb_t->cycle];
 | 
			
		||||
		tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num;
 | 
			
		||||
		**tlb = entry;
 | 
			
		||||
	}
 | 
			
		||||
	state->mmu.last_domain = (*tlb)->domain;
 | 
			
		||||
	return NO_FAULT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
mmu_tlb_init (tlb_s * tlb_t, int num)
 | 
			
		||||
{
 | 
			
		||||
	tlb_entry_t *e;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	e = (tlb_entry_t *) malloc (sizeof (*e) * num);
 | 
			
		||||
	if (e == NULL) {
 | 
			
		||||
		ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num);
 | 
			
		||||
		goto tlb_malloc_error;
 | 
			
		||||
	}
 | 
			
		||||
	tlb_t->entrys = e;
 | 
			
		||||
	for (i = 0; i < num; i++, e++)
 | 
			
		||||
		e->mapping = TLB_INVALID;
 | 
			
		||||
	tlb_t->cycle = 0;
 | 
			
		||||
	tlb_t->num = num;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
      tlb_malloc_error:
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_tlb_exit (tlb_s * tlb_t)
 | 
			
		||||
{
 | 
			
		||||
	free (tlb_t->entrys);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t)
 | 
			
		||||
{
 | 
			
		||||
	int entry;
 | 
			
		||||
 | 
			
		||||
	for (entry = 0; entry < tlb_t->num; entry++) {
 | 
			
		||||
		tlb_t->entrys[entry].mapping = TLB_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
	tlb_t->cycle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr)
 | 
			
		||||
{
 | 
			
		||||
	tlb_entry_t *tlb;
 | 
			
		||||
 | 
			
		||||
	tlb = mmu_tlb_search (state, tlb_t, addr);
 | 
			
		||||
	if (tlb) {
 | 
			
		||||
		tlb->mapping = TLB_INVALID;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tlb_entry_t *
 | 
			
		||||
mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr)
 | 
			
		||||
{
 | 
			
		||||
	int entry;
 | 
			
		||||
 | 
			
		||||
	for (entry = 0; entry < tlb_t->num; entry++) {
 | 
			
		||||
		tlb_entry_t *tlb;
 | 
			
		||||
		ARMword mask;
 | 
			
		||||
 | 
			
		||||
		tlb = &(tlb_t->entrys[entry]);
 | 
			
		||||
		if (tlb->mapping == TLB_INVALID) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		mask = tlb_masks[tlb->mapping];
 | 
			
		||||
		if ((virt_addr & mask) == (tlb->virt_addr & mask)) {
 | 
			
		||||
			return tlb;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
@ -63,14 +63,7 @@ typedef struct tlb_s
 | 
			
		||||
#define tlb_b_flag(tlb) \
 | 
			
		||||
    ((tlb)->perms & 0x4)
 | 
			
		||||
 | 
			
		||||
#define  tlb_va_to_pa(tlb, va) \
 | 
			
		||||
(\
 | 
			
		||||
 {\
 | 
			
		||||
    ARMword mask = tlb_masks[tlb->mapping];      \
 | 
			
		||||
    (tlb->phys_addr & mask) | (va & ~mask);\
 | 
			
		||||
 }\
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
#define  tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping]))
 | 
			
		||||
fault_t
 | 
			
		||||
check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb,
 | 
			
		||||
          int read);
 | 
			
		||||
							
								
								
									
										149
									
								
								src/core/arm/interpreter/mmu/wb.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/core/arm/interpreter/mmu/wb.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
/* wb_init
 | 
			
		||||
 * @wb_t	:wb_t to init
 | 
			
		||||
 * @num		:num of entrys
 | 
			
		||||
 * @nb		:num of byte of each entry
 | 
			
		||||
 *
 | 
			
		||||
 * $	-1:error
 | 
			
		||||
 * 		 0:ok
 | 
			
		||||
 * */
 | 
			
		||||
int
 | 
			
		||||
mmu_wb_init (wb_s * wb_t, int num, int nb)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	wb_entry_t *entrys, *wb;
 | 
			
		||||
 | 
			
		||||
	entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num);
 | 
			
		||||
	if (entrys == NULL) {
 | 
			
		||||
		ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num);
 | 
			
		||||
		goto entrys_malloc_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (wb = entrys, i = 0; i < num; i++, wb++) {
 | 
			
		||||
		/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */
 | 
			
		||||
		//wb->data = (ARMword *)malloc(sizeof(ARMword) * nb);
 | 
			
		||||
		wb->data = (ARMbyte *) malloc (nb);
 | 
			
		||||
		if (wb->data == NULL) {
 | 
			
		||||
			ERROR_LOG(ARM11, "malloc size of %d\n", nb);
 | 
			
		||||
			goto data_malloc_error;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	wb_t->first = wb_t->last = wb_t->used = 0;
 | 
			
		||||
	wb_t->num = num;
 | 
			
		||||
	wb_t->nb = nb;
 | 
			
		||||
	wb_t->entrys = entrys;
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
      data_malloc_error:
 | 
			
		||||
	while (--i >= 0)
 | 
			
		||||
		free (entrys[i].data);
 | 
			
		||||
	free (entrys);
 | 
			
		||||
      entrys_malloc_error:
 | 
			
		||||
	return -1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* wb_exit
 | 
			
		||||
 * @wb_t :wb_t to exit
 | 
			
		||||
 * */
 | 
			
		||||
void
 | 
			
		||||
mmu_wb_exit (wb_s * wb_t)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	wb_entry_t *wb;
 | 
			
		||||
 | 
			
		||||
	wb = wb_t->entrys;
 | 
			
		||||
	for (i = 0; i < wb_t->num; i++, wb++) {
 | 
			
		||||
		free (wb->data);
 | 
			
		||||
	}
 | 
			
		||||
	free (wb_t->entrys);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* wb_write_words :put words in Write Buffer
 | 
			
		||||
 * @state:	ARMul_State
 | 
			
		||||
 * @wb_t:	write buffer
 | 
			
		||||
 * @pa:		physical address
 | 
			
		||||
 * @data:	data ptr
 | 
			
		||||
 * @n		number of word to write
 | 
			
		||||
 *
 | 
			
		||||
 * Note: write buffer merge is not implemented, can be done late
 | 
			
		||||
 * */
 | 
			
		||||
void
 | 
			
		||||
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
 | 
			
		||||
		    ARMbyte * data, int n)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	wb_entry_t *wb;
 | 
			
		||||
 | 
			
		||||
	while (n) {
 | 
			
		||||
		if (wb_t->num == wb_t->used) {
 | 
			
		||||
			/*clean the last wb entry */
 | 
			
		||||
			ARMword t;
 | 
			
		||||
 | 
			
		||||
			wb = &wb_t->entrys[wb_t->last];
 | 
			
		||||
			t = wb->pa;
 | 
			
		||||
			for (i = 0; i < wb->nb; i++) {
 | 
			
		||||
				//mem_write_byte (state, t, wb->data[i]);
 | 
			
		||||
				bus_write(8, t, wb->data[i]);
 | 
			
		||||
				//t += WORD_SIZE;
 | 
			
		||||
				t++;
 | 
			
		||||
			}
 | 
			
		||||
			wb_t->last++;
 | 
			
		||||
			if (wb_t->last == wb_t->num)
 | 
			
		||||
				wb_t->last = 0;
 | 
			
		||||
			wb_t->used--;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		wb = &wb_t->entrys[wb_t->first];
 | 
			
		||||
		i = (n < wb_t->nb) ? n : wb_t->nb;
 | 
			
		||||
 | 
			
		||||
		wb->pa = pa;
 | 
			
		||||
		//pa += i << WORD_SHT;
 | 
			
		||||
		pa += i;
 | 
			
		||||
 | 
			
		||||
		wb->nb = i;
 | 
			
		||||
		//memcpy(wb->data, data, i << WORD_SHT);
 | 
			
		||||
		memcpy (wb->data, data, i);
 | 
			
		||||
		data += i;
 | 
			
		||||
		n -= i;
 | 
			
		||||
		wb_t->first++;
 | 
			
		||||
		if (wb_t->first == wb_t->num)
 | 
			
		||||
			wb_t->first = 0;
 | 
			
		||||
		wb_t->used++;
 | 
			
		||||
	};
 | 
			
		||||
//teawater add for set_dirty fflash cache function 2005.07.18-------------------
 | 
			
		||||
#ifdef DBCT
 | 
			
		||||
	if (!skyeye_config.no_dbct) {
 | 
			
		||||
		tb_setdirty (state, pa, NULL);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
//AJ2D--------------------------------------------------------------------------
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* wb_drain_all
 | 
			
		||||
 * @wb_t wb_t to drain
 | 
			
		||||
 * */
 | 
			
		||||
void
 | 
			
		||||
mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t)
 | 
			
		||||
{
 | 
			
		||||
	ARMword pa;
 | 
			
		||||
	wb_entry_t *wb;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	while (wb_t->used) {
 | 
			
		||||
		wb = &wb_t->entrys[wb_t->last];
 | 
			
		||||
		pa = wb->pa;
 | 
			
		||||
		for (i = 0; i < wb->nb; i++) {
 | 
			
		||||
			//mem_write_byte (state, pa, wb->data[i]);
 | 
			
		||||
			bus_write(8, pa, wb->data[i]);
 | 
			
		||||
			//pa += WORD_SIZE;
 | 
			
		||||
			pa++;
 | 
			
		||||
		}
 | 
			
		||||
		wb_t->last++;
 | 
			
		||||
		if (wb_t->last == wb_t->num)
 | 
			
		||||
			wb_t->last = 0;
 | 
			
		||||
		wb_t->used--;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1391
									
								
								src/core/arm/interpreter/mmu/xscale_copro.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1391
									
								
								src/core/arm/interpreter/mmu/xscale_copro.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										84
									
								
								src/core/arm/interpreter/vfp/asm_vfp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/core/arm/interpreter/vfp/asm_vfp.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
			
		||||
/*
 | 
			
		||||
 * arch/arm/include/asm/vfp.h
 | 
			
		||||
 *
 | 
			
		||||
 * VFP register definitions.
 | 
			
		||||
 * First, the standard VFP set.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define FPSID			cr0
 | 
			
		||||
#define FPSCR			cr1
 | 
			
		||||
#define MVFR1			cr6
 | 
			
		||||
#define MVFR0			cr7
 | 
			
		||||
#define FPEXC			cr8
 | 
			
		||||
#define FPINST			cr9
 | 
			
		||||
#define FPINST2			cr10
 | 
			
		||||
 | 
			
		||||
/* FPSID bits */
 | 
			
		||||
#define FPSID_IMPLEMENTER_BIT	(24)
 | 
			
		||||
#define FPSID_IMPLEMENTER_MASK	(0xff << FPSID_IMPLEMENTER_BIT)
 | 
			
		||||
#define FPSID_SOFTWARE		(1<<23)
 | 
			
		||||
#define FPSID_FORMAT_BIT	(21)
 | 
			
		||||
#define FPSID_FORMAT_MASK	(0x3  << FPSID_FORMAT_BIT)
 | 
			
		||||
#define FPSID_NODOUBLE		(1<<20)
 | 
			
		||||
#define FPSID_ARCH_BIT		(16)
 | 
			
		||||
#define FPSID_ARCH_MASK		(0xF  << FPSID_ARCH_BIT)
 | 
			
		||||
#define FPSID_PART_BIT		(8)
 | 
			
		||||
#define FPSID_PART_MASK		(0xFF << FPSID_PART_BIT)
 | 
			
		||||
#define FPSID_VARIANT_BIT	(4)
 | 
			
		||||
#define FPSID_VARIANT_MASK	(0xF  << FPSID_VARIANT_BIT)
 | 
			
		||||
#define FPSID_REV_BIT		(0)
 | 
			
		||||
#define FPSID_REV_MASK		(0xF  << FPSID_REV_BIT)
 | 
			
		||||
 | 
			
		||||
/* FPEXC bits */
 | 
			
		||||
#define FPEXC_EX		(1 << 31)
 | 
			
		||||
#define FPEXC_EN		(1 << 30)
 | 
			
		||||
#define FPEXC_DEX		(1 << 29)
 | 
			
		||||
#define FPEXC_FP2V		(1 << 28)
 | 
			
		||||
#define FPEXC_VV		(1 << 27)
 | 
			
		||||
#define FPEXC_TFV		(1 << 26)
 | 
			
		||||
#define FPEXC_LENGTH_BIT	(8)
 | 
			
		||||
#define FPEXC_LENGTH_MASK	(7 << FPEXC_LENGTH_BIT)
 | 
			
		||||
#define FPEXC_IDF		(1 << 7)
 | 
			
		||||
#define FPEXC_IXF		(1 << 4)
 | 
			
		||||
#define FPEXC_UFF		(1 << 3)
 | 
			
		||||
#define FPEXC_OFF		(1 << 2)
 | 
			
		||||
#define FPEXC_DZF		(1 << 1)
 | 
			
		||||
#define FPEXC_IOF		(1 << 0)
 | 
			
		||||
#define FPEXC_TRAP_MASK		(FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF)
 | 
			
		||||
 | 
			
		||||
/* FPSCR bits */
 | 
			
		||||
#define FPSCR_DEFAULT_NAN	(1<<25)
 | 
			
		||||
#define FPSCR_FLUSHTOZERO	(1<<24)
 | 
			
		||||
#define FPSCR_ROUND_NEAREST	(0<<22)
 | 
			
		||||
#define FPSCR_ROUND_PLUSINF	(1<<22)
 | 
			
		||||
#define FPSCR_ROUND_MINUSINF	(2<<22)
 | 
			
		||||
#define FPSCR_ROUND_TOZERO	(3<<22)
 | 
			
		||||
#define FPSCR_RMODE_BIT		(22)
 | 
			
		||||
#define FPSCR_RMODE_MASK	(3 << FPSCR_RMODE_BIT)
 | 
			
		||||
#define FPSCR_STRIDE_BIT	(20)
 | 
			
		||||
#define FPSCR_STRIDE_MASK	(3 << FPSCR_STRIDE_BIT)
 | 
			
		||||
#define FPSCR_LENGTH_BIT	(16)
 | 
			
		||||
#define FPSCR_LENGTH_MASK	(7 << FPSCR_LENGTH_BIT)
 | 
			
		||||
#define FPSCR_IOE		(1<<8)
 | 
			
		||||
#define FPSCR_DZE		(1<<9)
 | 
			
		||||
#define FPSCR_OFE		(1<<10)
 | 
			
		||||
#define FPSCR_UFE		(1<<11)
 | 
			
		||||
#define FPSCR_IXE		(1<<12)
 | 
			
		||||
#define FPSCR_IDE		(1<<15)
 | 
			
		||||
#define FPSCR_IOC		(1<<0)
 | 
			
		||||
#define FPSCR_DZC		(1<<1)
 | 
			
		||||
#define FPSCR_OFC		(1<<2)
 | 
			
		||||
#define FPSCR_UFC		(1<<3)
 | 
			
		||||
#define FPSCR_IXC		(1<<4)
 | 
			
		||||
#define FPSCR_IDC		(1<<7)
 | 
			
		||||
 | 
			
		||||
/* MVFR0 bits */
 | 
			
		||||
#define MVFR0_A_SIMD_BIT	(0)
 | 
			
		||||
#define MVFR0_A_SIMD_MASK	(0xf << MVFR0_A_SIMD_BIT)
 | 
			
		||||
 | 
			
		||||
/* Bit patterns for decoding the packaged operation descriptors */
 | 
			
		||||
#define VFPOPDESC_LENGTH_BIT	(9)
 | 
			
		||||
#define VFPOPDESC_LENGTH_MASK	(0x07 << VFPOPDESC_LENGTH_BIT)
 | 
			
		||||
#define VFPOPDESC_UNUSED_BIT	(24)
 | 
			
		||||
#define VFPOPDESC_UNUSED_MASK	(0xFF << VFPOPDESC_UNUSED_BIT)
 | 
			
		||||
#define VFPOPDESC_OPDESC_MASK	(~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
 | 
			
		||||
							
								
								
									
										357
									
								
								src/core/arm/interpreter/vfp/vfp.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								src/core/arm/interpreter/vfp/vfp.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,357 @@
 | 
			
		||||
/*
 | 
			
		||||
    armvfp.c - ARM VFPv3 emulation unit
 | 
			
		||||
    Copyright (C) 2003 Skyeye Develop Group
 | 
			
		||||
    for help please send mail to <skyeye-developer@lists.gro.clinux.org>
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/* Note: this file handles interface with arm core and vfp registers */
 | 
			
		||||
 | 
			
		||||
/* Opens debug for classic interpreter only */
 | 
			
		||||
//#define DEBUG
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfp.h"
 | 
			
		||||
 | 
			
		||||
//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_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;
 | 
			
		||||
	state->VFP[VFP_OFFSET(VFP_FPEXC)] = 0;
 | 
			
		||||
	state->VFP[VFP_OFFSET(VFP_FPSCR)] = 0;
 | 
			
		||||
	
 | 
			
		||||
	//persistent_state = state;
 | 
			
		||||
	/* Reset only specify VFP_FPEXC_EN = '0' */
 | 
			
		||||
 | 
			
		||||
	return No_exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
 | 
			
		||||
{
 | 
			
		||||
	/* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int OPC_1 = BITS (21, 23);
 | 
			
		||||
	int Rt = BITS (12, 15);
 | 
			
		||||
	int CRn = BITS (16, 19);
 | 
			
		||||
	int CRm = BITS (0, 3);
 | 
			
		||||
	int OPC_2 = BITS (5, 7);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO check access permission */
 | 
			
		||||
	
 | 
			
		||||
	/* CRn/opc1 CRm/opc2 */
 | 
			
		||||
	
 | 
			
		||||
	if (CoProc == 10 || CoProc == 11)
 | 
			
		||||
	{
 | 
			
		||||
		#define VFP_MRC_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_MRC_TRANS
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 
 | 
			
		||||
	       instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	/* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int OPC_1 = BITS (21, 23);
 | 
			
		||||
	int Rt = BITS (12, 15);
 | 
			
		||||
	int CRn = BITS (16, 19);
 | 
			
		||||
	int CRm = BITS (0, 3);
 | 
			
		||||
	int OPC_2 = BITS (5, 7);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO check access permission */
 | 
			
		||||
	
 | 
			
		||||
	/* CRn/opc1 CRm/opc2 */
 | 
			
		||||
	if (CoProc == 10 || CoProc == 11)
 | 
			
		||||
	{
 | 
			
		||||
		#define VFP_MCR_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_MCR_TRANS
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 
 | 
			
		||||
	       instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2)
 | 
			
		||||
{
 | 
			
		||||
	/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int OPC_1 = BITS (4, 7);
 | 
			
		||||
	int Rt = BITS (12, 15);
 | 
			
		||||
	int Rt2 = BITS (16, 19);
 | 
			
		||||
	int CRm = BITS (0, 3);
 | 
			
		||||
	
 | 
			
		||||
	if (CoProc == 10 || CoProc == 11)
 | 
			
		||||
	{
 | 
			
		||||
		#define VFP_MRRC_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_MRRC_TRANS
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 
 | 
			
		||||
	       instr, CoProc, OPC_1, Rt, Rt2, CRm);
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2)
 | 
			
		||||
{
 | 
			
		||||
	/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int OPC_1 = BITS (4, 7);
 | 
			
		||||
	int Rt = BITS (12, 15);
 | 
			
		||||
	int Rt2 = BITS (16, 19);
 | 
			
		||||
	int CRm = BITS (0, 3);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO check access permission */
 | 
			
		||||
	
 | 
			
		||||
	/* CRn/opc1 CRm/opc2 */
 | 
			
		||||
	
 | 
			
		||||
	if (CoProc == 11 || CoProc == 10)
 | 
			
		||||
	{
 | 
			
		||||
		#define VFP_MCRR_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_MCRR_TRANS
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 
 | 
			
		||||
	       instr, CoProc, OPC_1, Rt, Rt2, CRm);
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value)
 | 
			
		||||
{
 | 
			
		||||
	/* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int CRd = BITS (12, 15);
 | 
			
		||||
	int Rn = BITS (16, 19);
 | 
			
		||||
	int imm8 = BITS (0, 7);
 | 
			
		||||
	int P = BIT(24);
 | 
			
		||||
	int U = BIT(23);
 | 
			
		||||
	int D = BIT(22);
 | 
			
		||||
	int W = BIT(21);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO check access permission */
 | 
			
		||||
	
 | 
			
		||||
	/* VSTM */
 | 
			
		||||
	if ( (P|U|D|W) == 0 )
 | 
			
		||||
	{
 | 
			
		||||
		DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1);
 | 
			
		||||
	}
 | 
			
		||||
	if (CoProc == 10 || CoProc == 11)
 | 
			
		||||
	{
 | 
			
		||||
		#if 1
 | 
			
		||||
		if (P == 0 && U == 0 && W == 0)
 | 
			
		||||
		{
 | 
			
		||||
			DEBUG_LOG(ARM11, "VSTM Related encodings\n"); exit(-1);
 | 
			
		||||
		}
 | 
			
		||||
		if (P == U && W == 1)
 | 
			
		||||
		{
 | 
			
		||||
			DEBUG_LOG(ARM11, "UNDEFINED\n"); exit(-1);
 | 
			
		||||
		}
 | 
			
		||||
		#endif
 | 
			
		||||
 | 
			
		||||
		#define VFP_STC_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_STC_TRANS
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 
 | 
			
		||||
	       instr, CoProc, CRd, Rn, imm8, P, U, D, W);
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
 | 
			
		||||
{
 | 
			
		||||
	/* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int CRd = BITS (12, 15);
 | 
			
		||||
	int Rn = BITS (16, 19);
 | 
			
		||||
	int imm8 = BITS (0, 7);
 | 
			
		||||
	int P = BIT(24);
 | 
			
		||||
	int U = BIT(23);
 | 
			
		||||
	int D = BIT(22);
 | 
			
		||||
	int W = BIT(21);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO check access permission */
 | 
			
		||||
	
 | 
			
		||||
	if ( (P|U|D|W) == 0 )
 | 
			
		||||
	{
 | 
			
		||||
		DEBUG_LOG(ARM11, "In %s, UNDEFINED\n", __FUNCTION__); exit(-1);
 | 
			
		||||
	}
 | 
			
		||||
	if (CoProc == 10 || CoProc == 11)
 | 
			
		||||
	{
 | 
			
		||||
		#define VFP_LDC_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_LDC_TRANS
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 
 | 
			
		||||
	       instr, CoProc, CRd, Rn, imm8, P, U, D, W);
 | 
			
		||||
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned
 | 
			
		||||
VFPCDP (ARMul_State * state, unsigned type, ARMword instr)
 | 
			
		||||
{
 | 
			
		||||
	/* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
 | 
			
		||||
	int CoProc = BITS (8, 11); /* 10 or 11 */
 | 
			
		||||
	int OPC_1 = BITS (20, 23);
 | 
			
		||||
	int CRd = BITS (12, 15);
 | 
			
		||||
	int CRn = BITS (16, 19);
 | 
			
		||||
	int CRm = BITS (0, 3);
 | 
			
		||||
	int OPC_2 = BITS (5, 7);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO check access permission */
 | 
			
		||||
	
 | 
			
		||||
	/* CRn/opc1 CRm/opc2 */
 | 
			
		||||
 | 
			
		||||
	if (CoProc == 10 || CoProc == 11)
 | 
			
		||||
	{
 | 
			
		||||
		#define VFP_CDP_TRANS
 | 
			
		||||
		#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
		#undef VFP_CDP_TRANS
 | 
			
		||||
		
 | 
			
		||||
		int exceptions = 0;
 | 
			
		||||
		if (CoProc == 10)
 | 
			
		||||
			exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
 | 
			
		||||
		else 
 | 
			
		||||
			exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
 | 
			
		||||
 | 
			
		||||
		vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
 | 
			
		||||
 | 
			
		||||
		return ARMul_DONE;
 | 
			
		||||
	}
 | 
			
		||||
	DEBUG_LOG(ARM11, "Can't identify %x\n", instr);
 | 
			
		||||
	return ARMul_CANT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ----------- MRC ------------ */
 | 
			
		||||
#define VFP_MRC_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_MRC_IMPL
 | 
			
		||||
 | 
			
		||||
#define VFP_MRRC_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_MRRC_IMPL
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ----------- MCR ------------ */
 | 
			
		||||
#define VFP_MCR_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_MCR_IMPL
 | 
			
		||||
 | 
			
		||||
#define VFP_MCRR_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_MCRR_IMPL
 | 
			
		||||
 | 
			
		||||
/* Memory operation are not inlined, as old Interpreter and Fast interpreter
 | 
			
		||||
   don't have the same memory operation interface.
 | 
			
		||||
   Old interpreter framework does one access to coprocessor per data, and
 | 
			
		||||
   handles already data write, as well as address computation,
 | 
			
		||||
   which is not the case for Fast interpreter. Therefore, implementation
 | 
			
		||||
   of vfp instructions in old interpreter and fast interpreter are separate. */
 | 
			
		||||
 | 
			
		||||
/* ----------- STC ------------ */
 | 
			
		||||
#define VFP_STC_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_STC_IMPL
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ----------- LDC ------------ */
 | 
			
		||||
#define VFP_LDC_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_LDC_IMPL
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ----------- CDP ------------ */
 | 
			
		||||
#define VFP_CDP_IMPL
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfpinstr.cpp"
 | 
			
		||||
#undef VFP_CDP_IMPL
 | 
			
		||||
 | 
			
		||||
/* Miscellaneous functions */
 | 
			
		||||
int32_t vfp_get_float(arm_core_t* state, unsigned int reg)
 | 
			
		||||
{
 | 
			
		||||
	DBG("VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]);
 | 
			
		||||
	return state->ExtReg[reg];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg)
 | 
			
		||||
{
 | 
			
		||||
	DBG("VFP put float: s%d <= [%08x]\n", reg, val);
 | 
			
		||||
	state->ExtReg[reg] = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t vfp_get_double(arm_core_t* state, unsigned int reg)
 | 
			
		||||
{
 | 
			
		||||
	uint64_t result;
 | 
			
		||||
	result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
 | 
			
		||||
	DBG("VFP get double: s[%d-%d]=[%016llx]\n", reg*2+1, reg*2, result);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
 | 
			
		||||
{
 | 
			
		||||
	DBG("VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg*2+1, reg*2, (uint32_t) (val>>32), (uint32_t) (val & 0xffffffff));
 | 
			
		||||
	state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff);
 | 
			
		||||
	state->ExtReg[reg*2+1] = (uint32_t) (val>>32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Process bitmask of exception conditions. (from vfpmodule.c)
 | 
			
		||||
 */
 | 
			
		||||
void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr)
 | 
			
		||||
{
 | 
			
		||||
	int si_code = 0;
 | 
			
		||||
 | 
			
		||||
	vfpdebug("VFP: raising exceptions %08x\n", exceptions);
 | 
			
		||||
 | 
			
		||||
	if (exceptions == VFP_EXCEPTION_ERROR) {
 | 
			
		||||
		DEBUG_LOG(ARM11, "unhandled bounce %x\n", inst);
 | 
			
		||||
		exit(-1);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If any of the status flags are set, update the FPSCR.
 | 
			
		||||
	 * Comparison instructions always return at least one of
 | 
			
		||||
	 * these flags set.
 | 
			
		||||
	 */
 | 
			
		||||
	if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V))
 | 
			
		||||
		fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V);
 | 
			
		||||
 | 
			
		||||
	fpscr |= exceptions;
 | 
			
		||||
 | 
			
		||||
	state->VFP[VFP_OFFSET(VFP_FPSCR)] = fpscr;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										111
									
								
								src/core/arm/interpreter/vfp/vfp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/core/arm/interpreter/vfp/vfp.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,111 @@
 | 
			
		||||
/* 
 | 
			
		||||
    vfp/vfp.h - ARM VFPv3 emulation unit - vfp interface
 | 
			
		||||
    Copyright (C) 2003 Skyeye Develop Group
 | 
			
		||||
    for help please send mail to <skyeye-developer@lists.gro.clinux.org>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with this program; if not, write to the Free Software
 | 
			
		||||
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef __VFP_H__
 | 
			
		||||
#define __VFP_H__
 | 
			
		||||
 | 
			
		||||
#define DBG(...) DEBUG_LOG(ARM11, __VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#define vfpdebug //printf
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
 | 
			
		||||
 | 
			
		||||
unsigned VFPInit (ARMul_State *state);
 | 
			
		||||
unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
 | 
			
		||||
unsigned VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value);
 | 
			
		||||
unsigned VFPMRRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value1, ARMword * value2);
 | 
			
		||||
unsigned VFPMCRR (ARMul_State * state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
 | 
			
		||||
unsigned VFPSTC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
 | 
			
		||||
unsigned VFPLDC (ARMul_State * state, unsigned type, ARMword instr, ARMword value);
 | 
			
		||||
unsigned VFPCDP (ARMul_State * state, unsigned type, ARMword instr);
 | 
			
		||||
 | 
			
		||||
/* FPSID Information */
 | 
			
		||||
#define VFP_FPSID_IMPLMEN 0 	/* should be the same as cp15 0 c0 0*/
 | 
			
		||||
#define VFP_FPSID_SW 0
 | 
			
		||||
#define VFP_FPSID_SUBARCH 0x2 	/* VFP version. Current is v3 (not strict) */
 | 
			
		||||
#define VFP_FPSID_PARTNUM 0x1
 | 
			
		||||
#define VFP_FPSID_VARIANT 0x1
 | 
			
		||||
#define VFP_FPSID_REVISION 0x1
 | 
			
		||||
 | 
			
		||||
/* FPEXC Flags */
 | 
			
		||||
#define VFP_FPEXC_EX 1<<31
 | 
			
		||||
#define VFP_FPEXC_EN 1<<30
 | 
			
		||||
 | 
			
		||||
/* FPSCR Flags */
 | 
			
		||||
#define VFP_FPSCR_NFLAG 1<<31
 | 
			
		||||
#define VFP_FPSCR_ZFLAG 1<<30
 | 
			
		||||
#define VFP_FPSCR_CFLAG 1<<29
 | 
			
		||||
#define VFP_FPSCR_VFLAG 1<<28
 | 
			
		||||
 | 
			
		||||
#define VFP_FPSCR_AHP 1<<26 	/* Alternative Half Precision */
 | 
			
		||||
#define VFP_FPSCR_DN 1<<25 	/* Default NaN */
 | 
			
		||||
#define VFP_FPSCR_FZ 1<<24 	/* Flush-to-zero */
 | 
			
		||||
#define VFP_FPSCR_RMODE 3<<22 	/* Rounding Mode */
 | 
			
		||||
#define VFP_FPSCR_STRIDE 3<<20 	/* Stride (vector) */
 | 
			
		||||
#define VFP_FPSCR_LEN 7<<16 	/* Stride (vector) */
 | 
			
		||||
 | 
			
		||||
#define VFP_FPSCR_IDE 1<<15	/* Input Denormal exc */
 | 
			
		||||
#define VFP_FPSCR_IXE 1<<12	/* Inexact exc */
 | 
			
		||||
#define VFP_FPSCR_UFE 1<<11	/* Undeflow exc */
 | 
			
		||||
#define VFP_FPSCR_OFE 1<<10	/* Overflow exc */
 | 
			
		||||
#define VFP_FPSCR_DZE 1<<9	/* Division by Zero exc */
 | 
			
		||||
#define VFP_FPSCR_IOE 1<<8	/* Invalid Operation exc */
 | 
			
		||||
 | 
			
		||||
#define VFP_FPSCR_IDC 1<<7	/* Input Denormal cum exc */
 | 
			
		||||
#define VFP_FPSCR_IXC 1<<4	/* Inexact cum exc */
 | 
			
		||||
#define VFP_FPSCR_UFC 1<<3	/* Undeflow cum exc */
 | 
			
		||||
#define VFP_FPSCR_OFC 1<<2	/* Overflow cum exc */
 | 
			
		||||
#define VFP_FPSCR_DZC 1<<1	/* Division by Zero cum exc */
 | 
			
		||||
#define VFP_FPSCR_IOC 1<<0	/* Invalid Operation cum exc */
 | 
			
		||||
 | 
			
		||||
/* Inline instructions. Note: Used in a cpp file as well */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
int32_t vfp_get_float(ARMul_State * state, unsigned int reg);
 | 
			
		||||
void vfp_put_float(ARMul_State * state, int32_t val, unsigned int reg);
 | 
			
		||||
uint64_t vfp_get_double(ARMul_State * state, unsigned int reg);
 | 
			
		||||
void vfp_put_double(ARMul_State * state, uint64_t val, unsigned int reg);
 | 
			
		||||
void vfp_raise_exceptions(ARMul_State * state, uint32_t exceptions, uint32_t inst, uint32_t fpscr);
 | 
			
		||||
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
 | 
			
		||||
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
 | 
			
		||||
 | 
			
		||||
/* MRC */
 | 
			
		||||
inline void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword *value);
 | 
			
		||||
inline void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value);
 | 
			
		||||
inline void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2);
 | 
			
		||||
inline void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm);
 | 
			
		||||
inline void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword imm);
 | 
			
		||||
/* MCR */
 | 
			
		||||
inline void VMSR(ARMul_State * state, ARMword reg, ARMword Rt);
 | 
			
		||||
/* STC */
 | 
			
		||||
inline int VSTM(ARMul_State * state, int type, ARMword instr, ARMword* value);
 | 
			
		||||
inline int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword* value);
 | 
			
		||||
inline int VSTR(ARMul_State * state, int type, ARMword instr, ARMword* value);
 | 
			
		||||
/* LDC */
 | 
			
		||||
inline int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value);
 | 
			
		||||
inline int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value);
 | 
			
		||||
inline int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										541
									
								
								src/core/arm/interpreter/vfp/vfp_helper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										541
									
								
								src/core/arm/interpreter/vfp/vfp_helper.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,541 @@
 | 
			
		||||
/*
 | 
			
		||||
    vfp/vfp.h - ARM VFPv3 emulation unit - SoftFloat lib helper
 | 
			
		||||
    Copyright (C) 2003 Skyeye Develop Group
 | 
			
		||||
    for help please send mail to <skyeye-developer@lists.gro.clinux.org>
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 *  The following code is derivative from Linux Android kernel vfp
 | 
			
		||||
 *  floating point support.
 | 
			
		||||
 * 
 | 
			
		||||
 *  Copyright (C) 2004 ARM Limited.
 | 
			
		||||
 *  Written by Deep Blue Solutions Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __VFP_HELPER_H__
 | 
			
		||||
#define __VFP_HELPER_H__
 | 
			
		||||
 | 
			
		||||
/* Custom edit */
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "core/arm/interpreter/armdefs.h"
 | 
			
		||||
 | 
			
		||||
#define u16 uint16_t
 | 
			
		||||
#define u32 uint32_t
 | 
			
		||||
#define u64 uint64_t
 | 
			
		||||
#define s16 int16_t
 | 
			
		||||
#define s32 int32_t
 | 
			
		||||
#define s64 int64_t
 | 
			
		||||
 | 
			
		||||
#define pr_info //printf
 | 
			
		||||
#define pr_debug //printf
 | 
			
		||||
 | 
			
		||||
static u32 fls(int x);
 | 
			
		||||
#define do_div(n, base) {n/=base;}
 | 
			
		||||
 | 
			
		||||
/* From vfpinstr.h */
 | 
			
		||||
 | 
			
		||||
#define INST_CPRTDO(inst)	(((inst) & 0x0f000000) == 0x0e000000)
 | 
			
		||||
#define INST_CPRT(inst)		((inst) & (1 << 4))
 | 
			
		||||
#define INST_CPRT_L(inst)	((inst) & (1 << 20))
 | 
			
		||||
#define INST_CPRT_Rd(inst)	(((inst) & (15 << 12)) >> 12)
 | 
			
		||||
#define INST_CPRT_OP(inst)	(((inst) >> 21) & 7)
 | 
			
		||||
#define INST_CPNUM(inst)	((inst) & 0xf00)
 | 
			
		||||
#define CPNUM(cp)		((cp) << 8)
 | 
			
		||||
 | 
			
		||||
#define FOP_MASK	(0x00b00040)
 | 
			
		||||
#define FOP_FMAC	(0x00000000)
 | 
			
		||||
#define FOP_FNMAC	(0x00000040)
 | 
			
		||||
#define FOP_FMSC	(0x00100000)
 | 
			
		||||
#define FOP_FNMSC	(0x00100040)
 | 
			
		||||
#define FOP_FMUL	(0x00200000)
 | 
			
		||||
#define FOP_FNMUL	(0x00200040)
 | 
			
		||||
#define FOP_FADD	(0x00300000)
 | 
			
		||||
#define FOP_FSUB	(0x00300040)
 | 
			
		||||
#define FOP_FDIV	(0x00800000)
 | 
			
		||||
#define FOP_EXT		(0x00b00040)
 | 
			
		||||
 | 
			
		||||
#define FOP_TO_IDX(inst)	((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
 | 
			
		||||
 | 
			
		||||
#define FEXT_MASK	(0x000f0080)
 | 
			
		||||
#define FEXT_FCPY	(0x00000000)
 | 
			
		||||
#define FEXT_FABS	(0x00000080)
 | 
			
		||||
#define FEXT_FNEG	(0x00010000)
 | 
			
		||||
#define FEXT_FSQRT	(0x00010080)
 | 
			
		||||
#define FEXT_FCMP	(0x00040000)
 | 
			
		||||
#define FEXT_FCMPE	(0x00040080)
 | 
			
		||||
#define FEXT_FCMPZ	(0x00050000)
 | 
			
		||||
#define FEXT_FCMPEZ	(0x00050080)
 | 
			
		||||
#define FEXT_FCVT	(0x00070080)
 | 
			
		||||
#define FEXT_FUITO	(0x00080000)
 | 
			
		||||
#define FEXT_FSITO	(0x00080080)
 | 
			
		||||
#define FEXT_FTOUI	(0x000c0000)
 | 
			
		||||
#define FEXT_FTOUIZ	(0x000c0080)
 | 
			
		||||
#define FEXT_FTOSI	(0x000d0000)
 | 
			
		||||
#define FEXT_FTOSIZ	(0x000d0080)
 | 
			
		||||
 | 
			
		||||
#define FEXT_TO_IDX(inst)	((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
 | 
			
		||||
 | 
			
		||||
#define vfp_get_sd(inst)	((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
 | 
			
		||||
#define vfp_get_dd(inst)	((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
 | 
			
		||||
#define vfp_get_sm(inst)	((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
 | 
			
		||||
#define vfp_get_dm(inst)	((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
 | 
			
		||||
#define vfp_get_sn(inst)	((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
 | 
			
		||||
#define vfp_get_dn(inst)	((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
 | 
			
		||||
 | 
			
		||||
#define vfp_single(inst)	(((inst) & 0x0000f00) == 0xa00)
 | 
			
		||||
 | 
			
		||||
#define FPSCR_N	(1 << 31)
 | 
			
		||||
#define FPSCR_Z	(1 << 30)
 | 
			
		||||
#define FPSCR_C (1 << 29)
 | 
			
		||||
#define FPSCR_V	(1 << 28)
 | 
			
		||||
 | 
			
		||||
/* -------------- */
 | 
			
		||||
 | 
			
		||||
/* From asm/include/vfp.h */
 | 
			
		||||
 | 
			
		||||
/* FPSCR bits */
 | 
			
		||||
#define FPSCR_DEFAULT_NAN	(1<<25)
 | 
			
		||||
#define FPSCR_FLUSHTOZERO	(1<<24)
 | 
			
		||||
#define FPSCR_ROUND_NEAREST	(0<<22)
 | 
			
		||||
#define FPSCR_ROUND_PLUSINF	(1<<22)
 | 
			
		||||
#define FPSCR_ROUND_MINUSINF	(2<<22)
 | 
			
		||||
#define FPSCR_ROUND_TOZERO	(3<<22)
 | 
			
		||||
#define FPSCR_RMODE_BIT		(22)
 | 
			
		||||
#define FPSCR_RMODE_MASK	(3 << FPSCR_RMODE_BIT)
 | 
			
		||||
#define FPSCR_STRIDE_BIT	(20)
 | 
			
		||||
#define FPSCR_STRIDE_MASK	(3 << FPSCR_STRIDE_BIT)
 | 
			
		||||
#define FPSCR_LENGTH_BIT	(16)
 | 
			
		||||
#define FPSCR_LENGTH_MASK	(7 << FPSCR_LENGTH_BIT)
 | 
			
		||||
#define FPSCR_IOE		(1<<8)
 | 
			
		||||
#define FPSCR_DZE		(1<<9)
 | 
			
		||||
#define FPSCR_OFE		(1<<10)
 | 
			
		||||
#define FPSCR_UFE		(1<<11)
 | 
			
		||||
#define FPSCR_IXE		(1<<12)
 | 
			
		||||
#define FPSCR_IDE		(1<<15)
 | 
			
		||||
#define FPSCR_IOC		(1<<0)
 | 
			
		||||
#define FPSCR_DZC		(1<<1)
 | 
			
		||||
#define FPSCR_OFC		(1<<2)
 | 
			
		||||
#define FPSCR_UFC		(1<<3)
 | 
			
		||||
#define FPSCR_IXC		(1<<4)
 | 
			
		||||
#define FPSCR_IDC		(1<<7)
 | 
			
		||||
 | 
			
		||||
/* ---------------- */
 | 
			
		||||
 | 
			
		||||
static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
 | 
			
		||||
{
 | 
			
		||||
	if (shift) {
 | 
			
		||||
		if (shift < 32)
 | 
			
		||||
			val = val >> shift | ((val << (32 - shift)) != 0);
 | 
			
		||||
		else
 | 
			
		||||
			val = val != 0;
 | 
			
		||||
	}
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
 | 
			
		||||
{
 | 
			
		||||
	if (shift) {
 | 
			
		||||
		if (shift < 64)
 | 
			
		||||
			val = val >> shift | ((val << (64 - shift)) != 0);
 | 
			
		||||
		else
 | 
			
		||||
			val = val != 0;
 | 
			
		||||
	}
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline u32 vfp_hi64to32jamming(u64 val)
 | 
			
		||||
{
 | 
			
		||||
	u32 v;
 | 
			
		||||
	u32 highval = val >> 32;
 | 
			
		||||
	u32 lowval = val & 0xffffffff;
 | 
			
		||||
 | 
			
		||||
	if (lowval >= 1)
 | 
			
		||||
		v = highval | 1;
 | 
			
		||||
	else
 | 
			
		||||
		v = highval;
 | 
			
		||||
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void add128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml)
 | 
			
		||||
{
 | 
			
		||||
	*resl = nl + ml;
 | 
			
		||||
	*resh = nh + mh;
 | 
			
		||||
	if (*resl < nl)
 | 
			
		||||
		*resh += 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void sub128(u64 *resh, u64 *resl, u64 nh, u64 nl, u64 mh, u64 ml)
 | 
			
		||||
{
 | 
			
		||||
	*resl = nl - ml;
 | 
			
		||||
	*resh = nh - mh;
 | 
			
		||||
	if (*resl > nl)
 | 
			
		||||
		*resh -= 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void mul64to128(u64 *resh, u64 *resl, u64 n, u64 m)
 | 
			
		||||
{
 | 
			
		||||
	u32 nh, nl, mh, ml;
 | 
			
		||||
	u64 rh, rma, rmb, rl;
 | 
			
		||||
 | 
			
		||||
	nl = n;
 | 
			
		||||
	ml = m;
 | 
			
		||||
	rl = (u64)nl * ml;
 | 
			
		||||
 | 
			
		||||
	nh = n >> 32;
 | 
			
		||||
	rma = (u64)nh * ml;
 | 
			
		||||
 | 
			
		||||
	mh = m >> 32;
 | 
			
		||||
	rmb = (u64)nl * mh;
 | 
			
		||||
	rma += rmb;
 | 
			
		||||
 | 
			
		||||
	rh = (u64)nh * mh;
 | 
			
		||||
	rh += ((u64)(rma < rmb) << 32) + (rma >> 32);
 | 
			
		||||
 | 
			
		||||
	rma <<= 32;
 | 
			
		||||
	rl += rma;
 | 
			
		||||
	rh += (rl < rma);
 | 
			
		||||
 | 
			
		||||
	*resl = rl;
 | 
			
		||||
	*resh = rh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void shift64left(u64 *resh, u64 *resl, u64 n)
 | 
			
		||||
{
 | 
			
		||||
	*resh = n >> 63;
 | 
			
		||||
	*resl = n << 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline u64 vfp_hi64multiply64(u64 n, u64 m)
 | 
			
		||||
{
 | 
			
		||||
	u64 rh, rl;
 | 
			
		||||
	mul64to128(&rh, &rl, n, m);
 | 
			
		||||
	return rh | (rl != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
 | 
			
		||||
{
 | 
			
		||||
	u64 mh, ml, remh, reml, termh, terml, z;
 | 
			
		||||
 | 
			
		||||
	if (nh >= m)
 | 
			
		||||
		return ~0ULL;
 | 
			
		||||
	mh = m >> 32;
 | 
			
		||||
	if (mh << 32 <= nh) {
 | 
			
		||||
		z = 0xffffffff00000000ULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		z = nh;
 | 
			
		||||
		do_div(z, mh);
 | 
			
		||||
		z <<= 32;
 | 
			
		||||
	}
 | 
			
		||||
	mul64to128(&termh, &terml, m, z);
 | 
			
		||||
	sub128(&remh, &reml, nh, nl, termh, terml);
 | 
			
		||||
	ml = m << 32;
 | 
			
		||||
	while ((s64)remh < 0) {
 | 
			
		||||
		z -= 0x100000000ULL;
 | 
			
		||||
		add128(&remh, &reml, remh, reml, mh, ml);
 | 
			
		||||
	}
 | 
			
		||||
	remh = (remh << 32) | (reml >> 32);
 | 
			
		||||
	if (mh << 32 <= remh) {
 | 
			
		||||
		z |= 0xffffffff;
 | 
			
		||||
	} else {
 | 
			
		||||
		do_div(remh, mh);
 | 
			
		||||
		z |= remh;
 | 
			
		||||
	}
 | 
			
		||||
	return z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Operations on unpacked elements
 | 
			
		||||
 */
 | 
			
		||||
#define vfp_sign_negate(sign)	(sign ^ 0x8000)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Single-precision
 | 
			
		||||
 */
 | 
			
		||||
struct vfp_single {
 | 
			
		||||
	s16	exponent;
 | 
			
		||||
	u16	sign;
 | 
			
		||||
	u32	significand;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
extern s32 vfp_get_float(ARMul_State * state, unsigned int reg);
 | 
			
		||||
extern void vfp_put_float(ARMul_State * state, s32 val, unsigned int reg);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
 | 
			
		||||
 * VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent
 | 
			
		||||
 * VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand
 | 
			
		||||
 *  which are not propagated to the float upon packing.
 | 
			
		||||
 */
 | 
			
		||||
#define VFP_SINGLE_MANTISSA_BITS	(23)
 | 
			
		||||
#define VFP_SINGLE_EXPONENT_BITS	(8)
 | 
			
		||||
#define VFP_SINGLE_LOW_BITS		(32 - VFP_SINGLE_MANTISSA_BITS - 2)
 | 
			
		||||
#define VFP_SINGLE_LOW_BITS_MASK	((1 << VFP_SINGLE_LOW_BITS) - 1)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The bit in an unpacked float which indicates that it is a quiet NaN
 | 
			
		||||
 */
 | 
			
		||||
#define VFP_SINGLE_SIGNIFICAND_QNAN	(1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Operations on packed single-precision numbers
 | 
			
		||||
 */
 | 
			
		||||
#define vfp_single_packed_sign(v)	((v) & 0x80000000)
 | 
			
		||||
#define vfp_single_packed_negate(v)	((v) ^ 0x80000000)
 | 
			
		||||
#define vfp_single_packed_abs(v)	((v) & ~0x80000000)
 | 
			
		||||
#define vfp_single_packed_exponent(v)	(((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
 | 
			
		||||
#define vfp_single_packed_mantissa(v)	((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Unpack a single-precision float.  Note that this returns the magnitude
 | 
			
		||||
 * of the single-precision float mantissa with the 1. if necessary,
 | 
			
		||||
 * aligned to bit 30.
 | 
			
		||||
 */
 | 
			
		||||
static inline void vfp_single_unpack(struct vfp_single *s, s32 val)
 | 
			
		||||
{
 | 
			
		||||
	u32 significand;
 | 
			
		||||
 | 
			
		||||
	s->sign = vfp_single_packed_sign(val) >> 16,
 | 
			
		||||
	s->exponent = vfp_single_packed_exponent(val);
 | 
			
		||||
 | 
			
		||||
	significand = (u32) val;
 | 
			
		||||
	significand = (significand << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
 | 
			
		||||
	if (s->exponent && s->exponent != 255)
 | 
			
		||||
		significand |= 0x40000000;
 | 
			
		||||
	s->significand = significand;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Re-pack a single-precision float.  This assumes that the float is
 | 
			
		||||
 * already normalised such that the MSB is bit 30, _not_ bit 31.
 | 
			
		||||
 */
 | 
			
		||||
static inline s32 vfp_single_pack(struct vfp_single *s)
 | 
			
		||||
{
 | 
			
		||||
	u32 val;
 | 
			
		||||
	val = (s->sign << 16) +
 | 
			
		||||
	      (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
 | 
			
		||||
	      (s->significand >> VFP_SINGLE_LOW_BITS);
 | 
			
		||||
	return (s32)val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define VFP_NUMBER		(1<<0)
 | 
			
		||||
#define VFP_ZERO		(1<<1)
 | 
			
		||||
#define VFP_DENORMAL		(1<<2)
 | 
			
		||||
#define VFP_INFINITY		(1<<3)
 | 
			
		||||
#define VFP_NAN			(1<<4)
 | 
			
		||||
#define VFP_NAN_SIGNAL		(1<<5)
 | 
			
		||||
 | 
			
		||||
#define VFP_QNAN		(VFP_NAN)
 | 
			
		||||
#define VFP_SNAN		(VFP_NAN|VFP_NAN_SIGNAL)
 | 
			
		||||
 | 
			
		||||
static inline int vfp_single_type(struct vfp_single *s)
 | 
			
		||||
{
 | 
			
		||||
	int type = VFP_NUMBER;
 | 
			
		||||
	if (s->exponent == 255) {
 | 
			
		||||
		if (s->significand == 0)
 | 
			
		||||
			type = VFP_INFINITY;
 | 
			
		||||
		else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN)
 | 
			
		||||
			type = VFP_QNAN;
 | 
			
		||||
		else
 | 
			
		||||
			type = VFP_SNAN;
 | 
			
		||||
	} else if (s->exponent == 0) {
 | 
			
		||||
		if (s->significand == 0)
 | 
			
		||||
			type |= VFP_ZERO;
 | 
			
		||||
		else
 | 
			
		||||
			type |= VFP_DENORMAL;
 | 
			
		||||
	}
 | 
			
		||||
	return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Double-precision
 | 
			
		||||
 */
 | 
			
		||||
struct vfp_double {
 | 
			
		||||
	s16	exponent;
 | 
			
		||||
	u16	sign;
 | 
			
		||||
	u64	significand;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * VFP_REG_ZERO is a special register number for vfp_get_double
 | 
			
		||||
 * which returns (double)0.0.  This is useful for the compare with
 | 
			
		||||
 * zero instructions.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef CONFIG_VFPv3
 | 
			
		||||
#define VFP_REG_ZERO	32
 | 
			
		||||
#else
 | 
			
		||||
#define VFP_REG_ZERO	16
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
extern u64 vfp_get_double(ARMul_State * state, unsigned int reg);
 | 
			
		||||
extern void vfp_put_double(ARMul_State * state, u64 val, unsigned int reg);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
#define VFP_DOUBLE_MANTISSA_BITS	(52)
 | 
			
		||||
#define VFP_DOUBLE_EXPONENT_BITS	(11)
 | 
			
		||||
#define VFP_DOUBLE_LOW_BITS		(64 - VFP_DOUBLE_MANTISSA_BITS - 2)
 | 
			
		||||
#define VFP_DOUBLE_LOW_BITS_MASK	((1 << VFP_DOUBLE_LOW_BITS) - 1)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The bit in an unpacked double which indicates that it is a quiet NaN
 | 
			
		||||
 */
 | 
			
		||||
#define VFP_DOUBLE_SIGNIFICAND_QNAN	(1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Operations on packed single-precision numbers
 | 
			
		||||
 */
 | 
			
		||||
#define vfp_double_packed_sign(v)	((v) & (1ULL << 63))
 | 
			
		||||
#define vfp_double_packed_negate(v)	((v) ^ (1ULL << 63))
 | 
			
		||||
#define vfp_double_packed_abs(v)	((v) & ~(1ULL << 63))
 | 
			
		||||
#define vfp_double_packed_exponent(v)	(((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
 | 
			
		||||
#define vfp_double_packed_mantissa(v)	((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Unpack a double-precision float.  Note that this returns the magnitude
 | 
			
		||||
 * of the double-precision float mantissa with the 1. if necessary,
 | 
			
		||||
 * aligned to bit 62.
 | 
			
		||||
 */
 | 
			
		||||
static inline void vfp_double_unpack(struct vfp_double *s, s64 val)
 | 
			
		||||
{
 | 
			
		||||
	u64 significand;
 | 
			
		||||
 | 
			
		||||
	s->sign = vfp_double_packed_sign(val) >> 48;
 | 
			
		||||
	s->exponent = vfp_double_packed_exponent(val);
 | 
			
		||||
 | 
			
		||||
	significand = (u64) val;
 | 
			
		||||
	significand = (significand << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2;
 | 
			
		||||
	if (s->exponent && s->exponent != 2047)
 | 
			
		||||
		significand |= (1ULL << 62);
 | 
			
		||||
	s->significand = significand;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Re-pack a double-precision float.  This assumes that the float is
 | 
			
		||||
 * already normalised such that the MSB is bit 30, _not_ bit 31.
 | 
			
		||||
 */
 | 
			
		||||
static inline s64 vfp_double_pack(struct vfp_double *s)
 | 
			
		||||
{
 | 
			
		||||
	u64 val;
 | 
			
		||||
	val = ((u64)s->sign << 48) +
 | 
			
		||||
	      ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
 | 
			
		||||
	      (s->significand >> VFP_DOUBLE_LOW_BITS);
 | 
			
		||||
	return (s64)val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int vfp_double_type(struct vfp_double *s)
 | 
			
		||||
{
 | 
			
		||||
	int type = VFP_NUMBER;
 | 
			
		||||
	if (s->exponent == 2047) {
 | 
			
		||||
		if (s->significand == 0)
 | 
			
		||||
			type = VFP_INFINITY;
 | 
			
		||||
		else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN)
 | 
			
		||||
			type = VFP_QNAN;
 | 
			
		||||
		else
 | 
			
		||||
			type = VFP_SNAN;
 | 
			
		||||
	} else if (s->exponent == 0) {
 | 
			
		||||
		if (s->significand == 0)
 | 
			
		||||
			type |= VFP_ZERO;
 | 
			
		||||
		else
 | 
			
		||||
			type |= VFP_DENORMAL;
 | 
			
		||||
	}
 | 
			
		||||
	return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
 | 
			
		||||
 | 
			
		||||
u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A special flag to tell the normalisation code not to normalise.
 | 
			
		||||
 */
 | 
			
		||||
#define VFP_NAN_FLAG	0x100
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A bit pattern used to indicate the initial (unset) value of the
 | 
			
		||||
 * exception mask, in case nothing handles an instruction.  This
 | 
			
		||||
 * doesn't include the NAN flag, which get masked out before
 | 
			
		||||
 * we check for an error.
 | 
			
		||||
 */
 | 
			
		||||
#define VFP_EXCEPTION_ERROR	((u32)-1 & ~VFP_NAN_FLAG)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A flag to tell vfp instruction type.
 | 
			
		||||
 *  OP_SCALAR - this operation always operates in scalar mode
 | 
			
		||||
 *  OP_SD - the instruction exceptionally writes to a single precision result.
 | 
			
		||||
 *  OP_DD - the instruction exceptionally writes to a double precision result.
 | 
			
		||||
 *  OP_SM - the instruction exceptionally reads from a single precision operand.
 | 
			
		||||
 */
 | 
			
		||||
#define OP_SCALAR	(1 << 0)
 | 
			
		||||
#define OP_SD		(1 << 1)
 | 
			
		||||
#define OP_DD		(1 << 1)
 | 
			
		||||
#define OP_SM		(1 << 2)
 | 
			
		||||
 | 
			
		||||
struct op {
 | 
			
		||||
	u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
 | 
			
		||||
	u32 flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline u32 fls(int x)
 | 
			
		||||
{
 | 
			
		||||
	int r = 32;
 | 
			
		||||
 | 
			
		||||
	if (!x)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (!(x & 0xffff0000u)) {
 | 
			
		||||
		x <<= 16;
 | 
			
		||||
		r -= 16;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(x & 0xff000000u)) {
 | 
			
		||||
		x <<= 8;
 | 
			
		||||
		r -= 8;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(x & 0xf0000000u)) {
 | 
			
		||||
		x <<= 4;
 | 
			
		||||
		r -= 4;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(x & 0xc0000000u)) {
 | 
			
		||||
		x <<= 2;
 | 
			
		||||
		r -= 2;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(x & 0x80000000u)) {
 | 
			
		||||
		x <<= 1;
 | 
			
		||||
		r -= 1;
 | 
			
		||||
	}
 | 
			
		||||
	return r;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1263
									
								
								src/core/arm/interpreter/vfp/vfpdouble.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1263
									
								
								src/core/arm/interpreter/vfp/vfpdouble.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5123
									
								
								src/core/arm/interpreter/vfp/vfpinstr.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5123
									
								
								src/core/arm/interpreter/vfp/vfpinstr.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1278
									
								
								src/core/arm/interpreter/vfp/vfpsingle.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1278
									
								
								src/core/arm/interpreter/vfp/vfpsingle.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -138,6 +138,8 @@
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClCompile Include="arm\disassembler\arm_disasm.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\disassembler\load_symbol_map.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\armcopro.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\armemu.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\arminit.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\armmmu.cpp" />
 | 
			
		||||
@ -145,15 +147,27 @@
 | 
			
		||||
    <ClCompile Include="arm\interpreter\armsupp.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\armvirt.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\arm_interpreter.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\arm1176jzf_s_mmu.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\cache.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\maverick.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\rb.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\sa_mmu.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\tlb.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\wb.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\xscale_copro.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\thumbemu.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfp.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp" />
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp" />
 | 
			
		||||
    <ClCompile Include="core.cpp" />
 | 
			
		||||
    <ClCompile Include="core_timing.cpp" />
 | 
			
		||||
    <ClCompile Include="elf\elf_reader.cpp" />
 | 
			
		||||
    <ClCompile Include="file_sys\directory_file_system.cpp" />
 | 
			
		||||
    <ClCompile Include="file_sys\meta_file_system.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\config_mem.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\coprocessor.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\hle.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\mrc.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\service\apt.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\service\gsp.cpp" />
 | 
			
		||||
    <ClCompile Include="hle\service\hid.cpp" />
 | 
			
		||||
@ -171,6 +185,7 @@
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClInclude Include="arm\arm_interface.h" />
 | 
			
		||||
    <ClInclude Include="arm\disassembler\arm_disasm.h" />
 | 
			
		||||
    <ClInclude Include="arm\disassembler\load_symbol_map.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\armcpu.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\armdefs.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\armemu.h" />
 | 
			
		||||
@ -178,12 +193,16 @@
 | 
			
		||||
    <ClInclude Include="arm\interpreter\armos.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\arm_interpreter.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\arm_regformat.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\arm1176jzf_s_mmu.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\cache.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\rb.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\sa_mmu.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\tlb.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\wb.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\skyeye_defs.h" />
 | 
			
		||||
    <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h" />
 | 
			
		||||
    <ClInclude Include="arm\mmu\cache.h" />
 | 
			
		||||
    <ClInclude Include="arm\mmu\rb.h" />
 | 
			
		||||
    <ClInclude Include="arm\mmu\tlb.h" />
 | 
			
		||||
    <ClInclude Include="arm\mmu\wb.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\vfp\asm_vfp.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\vfp\vfp.h" />
 | 
			
		||||
    <ClInclude Include="arm\interpreter\vfp\vfp_helper.h" />
 | 
			
		||||
    <ClInclude Include="core.h" />
 | 
			
		||||
    <ClInclude Include="core_timing.h" />
 | 
			
		||||
    <ClInclude Include="elf\elf_reader.h" />
 | 
			
		||||
@ -191,9 +210,10 @@
 | 
			
		||||
    <ClInclude Include="file_sys\directory_file_system.h" />
 | 
			
		||||
    <ClInclude Include="file_sys\file_sys.h" />
 | 
			
		||||
    <ClInclude Include="file_sys\meta_file_system.h" />
 | 
			
		||||
    <ClInclude Include="hle\config_mem.h" />
 | 
			
		||||
    <ClInclude Include="hle\coprocessor.h" />
 | 
			
		||||
    <ClInclude Include="hle\function_wrappers.h" />
 | 
			
		||||
    <ClInclude Include="hle\hle.h" />
 | 
			
		||||
    <ClInclude Include="hle\mrc.h" />
 | 
			
		||||
    <ClInclude Include="hle\service\apt.h" />
 | 
			
		||||
    <ClInclude Include="hle\service\gsp.h" />
 | 
			
		||||
    <ClInclude Include="hle\service\hid.h" />
 | 
			
		||||
 | 
			
		||||
@ -7,9 +7,6 @@
 | 
			
		||||
    <Filter Include="arm\disassembler">
 | 
			
		||||
      <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
    <Filter Include="arm\mmu">
 | 
			
		||||
      <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
    <Filter Include="file_sys">
 | 
			
		||||
      <UniqueIdentifier>{7f618562-73d1-4f55-9628-887497c27654}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
@ -28,6 +25,12 @@
 | 
			
		||||
    <Filter Include="hle\service">
 | 
			
		||||
      <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
    <Filter Include="arm\interpreter\vfp">
 | 
			
		||||
      <UniqueIdentifier>{de62238f-a28e-4a33-8495-23fed6784588}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
    <Filter Include="arm\interpreter\mmu">
 | 
			
		||||
      <UniqueIdentifier>{13ef9860-2ba0-47e9-a93d-b4052adab269}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClCompile Include="arm\disassembler\arm_disasm.cpp">
 | 
			
		||||
@ -57,9 +60,6 @@
 | 
			
		||||
    <ClCompile Include="arm\interpreter\thumbemu.cpp">
 | 
			
		||||
      <Filter>arm\interpreter</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp">
 | 
			
		||||
      <Filter>arm\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="file_sys\directory_file_system.cpp">
 | 
			
		||||
      <Filter>file_sys</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
@ -105,9 +105,54 @@
 | 
			
		||||
    <ClCompile Include="hw\lcd.cpp">
 | 
			
		||||
      <Filter>hw</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="hle\mrc.cpp">
 | 
			
		||||
    <ClCompile Include="arm\disassembler\load_symbol_map.cpp">
 | 
			
		||||
      <Filter>arm\disassembler</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="hle\coprocessor.cpp">
 | 
			
		||||
      <Filter>hle</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="hle\config_mem.cpp">
 | 
			
		||||
      <Filter>hle</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfp.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\arm1176jzf_s_mmu.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\xscale_copro.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\sa_mmu.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\cache.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\rb.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\tlb.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\wb.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\armcopro.cpp">
 | 
			
		||||
      <Filter>arm</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="arm\interpreter\mmu\maverick.cpp">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClInclude Include="arm\disassembler\arm_disasm.h">
 | 
			
		||||
@ -137,21 +182,6 @@
 | 
			
		||||
    <ClInclude Include="arm\interpreter\skyeye_defs.h">
 | 
			
		||||
      <Filter>arm\interpreter</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h">
 | 
			
		||||
      <Filter>arm\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\mmu\cache.h">
 | 
			
		||||
      <Filter>arm\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\mmu\rb.h">
 | 
			
		||||
      <Filter>arm\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\mmu\tlb.h">
 | 
			
		||||
      <Filter>arm\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\mmu\wb.h">
 | 
			
		||||
      <Filter>arm\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="file_sys\directory_file_system.h">
 | 
			
		||||
      <Filter>file_sys</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
@ -208,9 +238,42 @@
 | 
			
		||||
    <ClInclude Include="hw\lcd.h">
 | 
			
		||||
      <Filter>hw</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="hle\mrc.h">
 | 
			
		||||
    <ClInclude Include="arm\disassembler\load_symbol_map.h">
 | 
			
		||||
      <Filter>arm\disassembler</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="hle\coprocessor.h">
 | 
			
		||||
      <Filter>hle</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="hle\config_mem.h">
 | 
			
		||||
      <Filter>hle</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\vfp\asm_vfp.h">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\vfp\vfp.h">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\vfp\vfp_helper.h">
 | 
			
		||||
      <Filter>arm\interpreter\vfp</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\arm1176jzf_s_mmu.h">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\cache.h">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\rb.h">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\tlb.h">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\wb.h">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="arm\interpreter\mmu\sa_mmu.h">
 | 
			
		||||
      <Filter>arm\interpreter\mmu</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Text Include="CMakeLists.txt" />
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										70
									
								
								src/core/hle/config_mem.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/core/hle/config_mem.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.  
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/log.h"
 | 
			
		||||
 | 
			
		||||
#include "core/hle/config_mem.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
namespace ConfigMem {
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    KERNEL_VERSIONREVISION  = 0x1FF80001,
 | 
			
		||||
    KERNEL_VERSIONMINOR     = 0x1FF80002,
 | 
			
		||||
    KERNEL_VERSIONMAJOR     = 0x1FF80003,
 | 
			
		||||
    UPDATEFLAG              = 0x1FF80004,
 | 
			
		||||
    NSTID                   = 0x1FF80008,
 | 
			
		||||
    SYSCOREVER              = 0x1FF80010,
 | 
			
		||||
    UNITINFO                = 0x1FF80014,
 | 
			
		||||
    KERNEL_CTRSDKVERSION    = 0x1FF80018,
 | 
			
		||||
    APPMEMTYPE              = 0x1FF80030,
 | 
			
		||||
    APPMEMALLOC             = 0x1FF80040,
 | 
			
		||||
    FIRM_VERSIONREVISION    = 0x1FF80061,
 | 
			
		||||
    FIRM_VERSIONMINOR       = 0x1FF80062,
 | 
			
		||||
    FIRM_VERSIONMAJOR       = 0x1FF80063,
 | 
			
		||||
    FIRM_SYSCOREVER         = 0x1FF80064,
 | 
			
		||||
    FIRM_CTRSDKVERSION      = 0x1FF80068,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Read(T &var, const u32 addr) {
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
 | 
			
		||||
    // Bit 0 set for Retail
 | 
			
		||||
    case UNITINFO:
 | 
			
		||||
        var = 0x00000001;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    // Set app memory size to 64MB?
 | 
			
		||||
    case APPMEMALLOC:
 | 
			
		||||
        var = 0x04000000;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    // Unknown - normally set to: 0x08000000 - (APPMEMALLOC + *0x1FF80048)
 | 
			
		||||
    // (Total FCRAM size - APPMEMALLOC - *0x1FF80048)
 | 
			
		||||
    case 0x1FF80044:
 | 
			
		||||
        var = 0x08000000 - (0x04000000 + 0x1400000);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    // Unknown - normally set to: 0x1400000 (20MB)
 | 
			
		||||
    case 0x1FF80048:
 | 
			
		||||
        var = 0x1400000;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(HLE, "unknown ConfigMem::Read%d @ 0x%08X", sizeof(var) * 8, addr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Explicitly instantiate template functions because we aren't defining this in the header:
 | 
			
		||||
 | 
			
		||||
template void Read<u64>(u64 &var, const u32 addr);
 | 
			
		||||
template void Read<u32>(u32 &var, const u32 addr);
 | 
			
		||||
template void Read<u16>(u16 &var, const u32 addr);
 | 
			
		||||
template void Read<u8>(u8 &var, const u32 addr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
							
								
								
									
										21
									
								
								src/core/hle/config_mem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/core/hle/config_mem.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.  
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Configuration memory stores various hardware/kernel configuration settings. This memory page is 
 | 
			
		||||
// read-only for ARM11 processes. I'm guessing this would normally be written to by the firmware/
 | 
			
		||||
// bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm
 | 
			
		||||
// putting this as a subset of HLE for now.
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
namespace ConfigMem {
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Read(T &var, const u32 addr);
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
							
								
								
									
										34
									
								
								src/core/hle/coprocessor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/core/hle/coprocessor.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.  
 | 
			
		||||
 | 
			
		||||
#include "core/hle/coprocessor.h"
 | 
			
		||||
#include "core/hle/hle.h"
 | 
			
		||||
#include "core/mem_map.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
 | 
			
		||||
namespace HLE {
 | 
			
		||||
 | 
			
		||||
/// Returns the coprocessor (in this case, syscore) command buffer pointer
 | 
			
		||||
Addr GetThreadCommandBuffer() {
 | 
			
		||||
    // Called on insruction: mrc p15, 0, r0, c13, c0, 3
 | 
			
		||||
    return Memory::KERNEL_MEMORY_VADDR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
 | 
			
		||||
s32 CallMRC(u32 instruction) {
 | 
			
		||||
    CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF);
 | 
			
		||||
 | 
			
		||||
    switch (operation) {
 | 
			
		||||
 | 
			
		||||
    case CALL_GET_THREAD_COMMAND_BUFFER:
 | 
			
		||||
        return GetThreadCommandBuffer();
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        //DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
@ -8,13 +8,13 @@
 | 
			
		||||
 | 
			
		||||
namespace HLE {
 | 
			
		||||
 | 
			
		||||
/// MRC operations (ARM register from coprocessor), decoded as instr[20:27]
 | 
			
		||||
enum ARM11_MRC_OPERATION {
 | 
			
		||||
/// Coprocessor operations
 | 
			
		||||
enum CoprocessorOperation {
 | 
			
		||||
    DATA_SYNCHRONIZATION_BARRIER    = 0xE0,
 | 
			
		||||
    CALL_GET_THREAD_COMMAND_BUFFER  = 0xE1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Call an MRC operation in HLE
 | 
			
		||||
u32 CallMRC(ARM11_MRC_OPERATION operation);
 | 
			
		||||
/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
 | 
			
		||||
s32 CallMRC(u32 instruction);
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
@ -143,8 +143,8 @@ template<int func(u32, u32, u32, u32, u32)> void WrapI_UUUUU() {
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func()> void WrapI_V() {
 | 
			
		||||
    int retval = func();
 | 
			
		||||
template<int func(void*)> void WrapI_V() {
 | 
			
		||||
    u32 retval = func(Memory::GetPointer(PARAM(0)));
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -623,6 +623,10 @@ template<u32 func(const char *, const char *)> void WrapU_CC() {
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<void func(const char*)> void WrapV_C() {
 | 
			
		||||
    func(Memory::GetCharPointer(PARAM(0)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<void func(const char *, int)> void WrapV_CI() {
 | 
			
		||||
    func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
 | 
			
		||||
}
 | 
			
		||||
@ -701,18 +705,28 @@ template <int func(int, const char *, int)> void WrapI_ICI() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){
 | 
			
		||||
  u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
 | 
			
		||||
  RETURN(retval);
 | 
			
		||||
    u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){
 | 
			
		||||
  u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
 | 
			
		||||
  RETURN(retval);
 | 
			
		||||
    u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func(void *, u32, u32, u32, u32, u32)> void WrapI_VUUUUU(){
 | 
			
		||||
  u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5));
 | 
			
		||||
  RETURN(retval);
 | 
			
		||||
template<int func(void*, u32)> void WrapI_VU(){
 | 
			
		||||
    u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1));
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func(void*, u32, void*, int)> void WrapI_VUVI(){
 | 
			
		||||
    u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), PARAM(3));
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func(void*, u32, u32, u32, u32, u32)> void WrapI_VUUUUU(){
 | 
			
		||||
    u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5));
 | 
			
		||||
    RETURN(retval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int func(u32, s64)> void WrapI_US64() {
 | 
			
		||||
 | 
			
		||||
@ -15,49 +15,6 @@ namespace HLE {
 | 
			
		||||
 | 
			
		||||
static std::vector<ModuleDef> g_module_db;
 | 
			
		||||
 | 
			
		||||
u8* g_command_buffer = NULL;    ///< Command buffer used for sharing between appcore and syscore
 | 
			
		||||
 | 
			
		||||
// Read from memory used by CTROS HLE functions
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Read(T &var, const u32 addr) {
 | 
			
		||||
    if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) {
 | 
			
		||||
        var = *((const T*)&g_command_buffer[addr & CMD_BUFFER_MASK]);
 | 
			
		||||
    } else {
 | 
			
		||||
        ERROR_LOG(HLE, "unknown read from address %08X", addr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write to memory used by CTROS HLE functions
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Write(u32 addr, const T data) {
 | 
			
		||||
    if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) {
 | 
			
		||||
        *(T*)&g_command_buffer[addr & CMD_BUFFER_MASK] = data;
 | 
			
		||||
    } else {
 | 
			
		||||
        ERROR_LOG(HLE, "unknown write to address %08X", addr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u8 *GetPointer(const u32 addr) {
 | 
			
		||||
    if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) {
 | 
			
		||||
        return g_command_buffer + (addr & CMD_BUFFER_MASK);
 | 
			
		||||
    } else {
 | 
			
		||||
        ERROR_LOG(HLE, "unknown pointer from address %08X", addr);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Explicitly instantiate template functions because we aren't defining this in the header:
 | 
			
		||||
 | 
			
		||||
template void Read<u64>(u64 &var, const u32 addr);
 | 
			
		||||
template void Read<u32>(u32 &var, const u32 addr);
 | 
			
		||||
template void Read<u16>(u16 &var, const u32 addr);
 | 
			
		||||
template void Read<u8>(u8 &var, const u32 addr);
 | 
			
		||||
 | 
			
		||||
template void Write<u64>(u32 addr, const u64 data);
 | 
			
		||||
template void Write<u32>(u32 addr, const u32 data);
 | 
			
		||||
template void Write<u16>(u32 addr, const u16 data);
 | 
			
		||||
template void Write<u8>(u32 addr, const u8 data);
 | 
			
		||||
 | 
			
		||||
const FunctionDef* GetSyscallInfo(u32 opcode) {
 | 
			
		||||
    u32 func_num = opcode & 0xFFFFFF; // 8 bits
 | 
			
		||||
    if (func_num > 0xFF) {
 | 
			
		||||
@ -91,8 +48,6 @@ void RegisterAllModules() {
 | 
			
		||||
 | 
			
		||||
void Init() {
 | 
			
		||||
    Service::Init();
 | 
			
		||||
 | 
			
		||||
    g_command_buffer = new u8[CMD_BUFFER_SIZE];
 | 
			
		||||
    
 | 
			
		||||
    RegisterAllModules();
 | 
			
		||||
 | 
			
		||||
@ -102,8 +57,6 @@ void Init() {
 | 
			
		||||
void Shutdown() {
 | 
			
		||||
    Service::Shutdown();
 | 
			
		||||
 | 
			
		||||
    delete g_command_buffer;
 | 
			
		||||
 | 
			
		||||
    g_module_db.clear();
 | 
			
		||||
 | 
			
		||||
    NOTICE_LOG(HLE, "shutdown OK");
 | 
			
		||||
 | 
			
		||||
@ -17,13 +17,6 @@
 | 
			
		||||
 | 
			
		||||
namespace HLE {
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    CMD_BUFFER_ADDR     = 0xA0010000,    ///< Totally arbitrary unused address space
 | 
			
		||||
    CMD_BUFFER_SIZE     = 0x10000,
 | 
			
		||||
    CMD_BUFFER_MASK     = (CMD_BUFFER_SIZE - 1),
 | 
			
		||||
    CMD_BUFFER_ADDR_END = (CMD_BUFFER_ADDR + CMD_BUFFER_SIZE),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef u32 Addr;
 | 
			
		||||
typedef void (*Func)();
 | 
			
		||||
 | 
			
		||||
@ -39,20 +32,6 @@ struct ModuleDef {
 | 
			
		||||
    const FunctionDef*  func_table;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Read from memory used by CTROS HLE functions
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Read(T &var, const u32 addr);
 | 
			
		||||
 | 
			
		||||
// Write to memory used by CTROS HLE functions
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Write(u32 addr, const T data);
 | 
			
		||||
 | 
			
		||||
u8* GetPointer(const u32 Address);
 | 
			
		||||
 | 
			
		||||
inline const char* GetCharPointer(const u32 address) {
 | 
			
		||||
    return (const char *)GetPointer(address);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table);
 | 
			
		||||
 | 
			
		||||
void CallSyscall(u32 opcode);
 | 
			
		||||
 | 
			
		||||
@ -1,64 +0,0 @@
 | 
			
		||||
// Copyright 2014 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2
 | 
			
		||||
// Refer to the license.txt file included.  
 | 
			
		||||
 | 
			
		||||
#include "core/hle/mrc.h"
 | 
			
		||||
#include "core/hle/hle.h"
 | 
			
		||||
#include "core/mem_map.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
 | 
			
		||||
namespace HLE {
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    CMD_GX_REQUEST_DMA  = 0x00000000,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Data synchronization barrier
 | 
			
		||||
u32 DataSynchronizationBarrier(u32* command_buffer) {
 | 
			
		||||
    u32 command = command_buffer[0];
 | 
			
		||||
 | 
			
		||||
    switch (command) {
 | 
			
		||||
 | 
			
		||||
    case CMD_GX_REQUEST_DMA:
 | 
			
		||||
        {
 | 
			
		||||
            u32* src = (u32*)Memory::GetPointer(command_buffer[1]);
 | 
			
		||||
            u32* dst = (u32*)Memory::GetPointer(command_buffer[2]);
 | 
			
		||||
            u32 size = command_buffer[3];
 | 
			
		||||
            memcpy(dst, src, size);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(OSHLE, "MRC::DataSynchronizationBarrier unknown command 0x%08X", command);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the coprocessor (in this case, syscore) command buffer pointer
 | 
			
		||||
Addr GetThreadCommandBuffer() {
 | 
			
		||||
    // Called on insruction: mrc p15, 0, r0, c13, c0, 3
 | 
			
		||||
    // Returns an address in OSHLE memory for the CPU to read/write to
 | 
			
		||||
    RETURN(CMD_BUFFER_ADDR);
 | 
			
		||||
    return CMD_BUFFER_ADDR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Call an MRC operation in HLE
 | 
			
		||||
u32 CallMRC(ARM11_MRC_OPERATION operation) {
 | 
			
		||||
    switch (operation) {
 | 
			
		||||
 | 
			
		||||
    case DATA_SYNCHRONIZATION_BARRIER:
 | 
			
		||||
        return DataSynchronizationBarrier((u32*)Memory::GetPointer(PARAM(0)));
 | 
			
		||||
 | 
			
		||||
    case CALL_GET_THREAD_COMMAND_BUFFER:
 | 
			
		||||
        return GetThreadCommandBuffer();
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(OSHLE, "unimplemented MRC operation 0x%02X", operation);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
@ -18,7 +18,7 @@ void Initialize(Service::Interface* self) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GetLockHandle(Service::Interface* self) {
 | 
			
		||||
    u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
 | 
			
		||||
    u32* cmd_buff = Service::GetCommandBuffer();
 | 
			
		||||
    cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "common/log.h"
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
 | 
			
		||||
#include "core/mem_map.h"
 | 
			
		||||
#include "core/hle/hle.h"
 | 
			
		||||
@ -11,11 +12,52 @@
 | 
			
		||||
 | 
			
		||||
#include "core/hw/lcd.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/// GSP shared memory GX command buffer header
 | 
			
		||||
union GX_CmdBufferHeader {
 | 
			
		||||
    u32 hex;
 | 
			
		||||
 | 
			
		||||
    // Current command index. This index is updated by GSP module after loading the command data, 
 | 
			
		||||
    // right before the command is processed. When this index is updated by GSP module, the total 
 | 
			
		||||
    // commands field is decreased by one as well.
 | 
			
		||||
    BitField<0,8,u32>   index;
 | 
			
		||||
    
 | 
			
		||||
    // Total commands to process, must not be value 0 when GSP module handles commands. This must be
 | 
			
		||||
    // <=15 when writing a command to shared memory. This is incremented by the application when 
 | 
			
		||||
    // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only 
 | 
			
		||||
    // used if this field is value 1.
 | 
			
		||||
    BitField<8,8,u32>  number_commands;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Gets the address of the start (header) of a command buffer in GSP shared memory
 | 
			
		||||
static inline u32 GX_GetCmdBufferAddress(u32 thread_id) {
 | 
			
		||||
    return (0x10002000 + 0x800 + (thread_id * 0x200));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Gets a pointer to the start (header) of a command buffer in GSP shared memory
 | 
			
		||||
static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) {
 | 
			
		||||
    return Memory::GetPointer(GX_GetCmdBufferAddress(thread_id) + offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Finishes execution of a GSP command
 | 
			
		||||
void GX_FinishCommand(u32 thread_id) {
 | 
			
		||||
    GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(thread_id);
 | 
			
		||||
    header->number_commands = header->number_commands - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Namespace GSP_GPU
 | 
			
		||||
 | 
			
		||||
namespace GSP_GPU {
 | 
			
		||||
 | 
			
		||||
u32 g_thread_id = 0;
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    CMD_GX_REQUEST_DMA  = 0x00000000,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    REG_FRAMEBUFFER_1   = 0x00400468,
 | 
			
		||||
    REG_FRAMEBUFFER_2   = 0x00400494,
 | 
			
		||||
@ -26,7 +68,7 @@ void ReadHWRegs(Service::Interface* self) {
 | 
			
		||||
    static const u32 framebuffer_1[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME1, LCD::PADDR_VRAM_TOP_RIGHT_FRAME1};
 | 
			
		||||
    static const u32 framebuffer_2[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME2, LCD::PADDR_VRAM_TOP_RIGHT_FRAME2};
 | 
			
		||||
 | 
			
		||||
    u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
 | 
			
		||||
    u32* cmd_buff = Service::GetCommandBuffer();
 | 
			
		||||
    u32 reg_addr = cmd_buff[1];
 | 
			
		||||
    u32 size = cmd_buff[2];
 | 
			
		||||
    u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]);
 | 
			
		||||
@ -50,18 +92,37 @@ void ReadHWRegs(Service::Interface* self) {
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(OSHLE, "GSP_GPU::ReadHWRegs unknown register read at address %08X", reg_addr);
 | 
			
		||||
        ERROR_LOG(GSP, "ReadHWRegs unknown register read at address %08X", reg_addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RegisterInterruptRelayQueue(Service::Interface* self) {
 | 
			
		||||
    u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
 | 
			
		||||
    u32* cmd_buff = Service::GetCommandBuffer();
 | 
			
		||||
    u32 flags = cmd_buff[1];
 | 
			
		||||
    u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling
 | 
			
		||||
    
 | 
			
		||||
    cmd_buff[2] = g_thread_id;          // ThreadID
 | 
			
		||||
    cmd_buff[4] = self->NewHandle();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
/// This triggers handling of the GX command written to the command buffer in shared memory.
 | 
			
		||||
void TriggerCmdReqQueue(Service::Interface* self) {
 | 
			
		||||
    GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(g_thread_id);
 | 
			
		||||
    u32* cmd_buff = (u32*)GX_GetCmdBufferPointer(g_thread_id, 0x20 + (header->index * 0x20));
 | 
			
		||||
 | 
			
		||||
    switch (cmd_buff[0]) {
 | 
			
		||||
 | 
			
		||||
    // GX request DMA - typically used for copying memory from GSP heap to VRAM
 | 
			
		||||
    case CMD_GX_REQUEST_DMA:
 | 
			
		||||
        memcpy(Memory::GetPointer(cmd_buff[2]), Memory::GetPointer(cmd_buff[1]), cmd_buff[3]);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(GSP, "TriggerCmdReqQueue unknown command 0x%08X", cmd_buff[0]);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    GX_FinishCommand(g_thread_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Interface::FunctionInfo FunctionTable[] = {
 | 
			
		||||
@ -76,7 +137,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 | 
			
		||||
    {0x00090082, NULL,                          "InvalidateDataCache"},
 | 
			
		||||
    {0x000A0044, NULL,                          "RegisterInterruptEvents"},
 | 
			
		||||
    {0x000B0040, NULL,                          "SetLcdForceBlack"},
 | 
			
		||||
    {0x000C0000, NULL,                          "TriggerCmdReqQueue"},
 | 
			
		||||
    {0x000C0000, TriggerCmdReqQueue,            "TriggerCmdReqQueue"},
 | 
			
		||||
    {0x000D0140, NULL,                          "SetDisplayTransfer"},
 | 
			
		||||
    {0x000E0180, NULL,                          "SetTextureCopy"},
 | 
			
		||||
    {0x000F0200, NULL,                          "SetMemoryFill"},
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include "common/common.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/mem_map.h"
 | 
			
		||||
#include "core/hle/syscall.h"
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
@ -22,6 +23,15 @@ typedef s32 NativeUID;                          ///< Native handle for a service
 | 
			
		||||
static const int kMaxPortSize           = 0x08; ///< Maximum size of a port name (8 characters)
 | 
			
		||||
static const int kCommandHeaderOffset   = 0x80; ///< Offset into command buffer of header
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a pointer to the command buffer in kernel memory
 | 
			
		||||
 * @param offset Optional offset into command buffer
 | 
			
		||||
 * @return Pointer to command buffer
 | 
			
		||||
 */
 | 
			
		||||
inline static u32* GetCommandBuffer(const int offset=0) {
 | 
			
		||||
    return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Manager;
 | 
			
		||||
 | 
			
		||||
/// Interface to a CTROS service
 | 
			
		||||
@ -81,7 +91,7 @@ public:
 | 
			
		||||
     * @return Return result of svcSendSyncRequest passed back to user app
 | 
			
		||||
     */
 | 
			
		||||
    Syscall::Result Sync() {
 | 
			
		||||
        u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + kCommandHeaderOffset);
 | 
			
		||||
        u32* cmd_buff = GetCommandBuffer();
 | 
			
		||||
        auto itr = m_functions.find(cmd_buff[0]);
 | 
			
		||||
 | 
			
		||||
        if (itr == m_functions.end()) {
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@ void Initialize(Service::Interface* self) {
 | 
			
		||||
 | 
			
		||||
void GetServiceHandle(Service::Interface* self) {
 | 
			
		||||
    Syscall::Result res = 0;
 | 
			
		||||
    u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset);
 | 
			
		||||
    u32* cmd_buff = Service::GetCommandBuffer();
 | 
			
		||||
 | 
			
		||||
    std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
 | 
			
		||||
    Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,9 @@ enum MapMemoryPermission {
 | 
			
		||||
Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
 | 
			
		||||
    u32 virtual_address = 0x00000000;
 | 
			
		||||
 | 
			
		||||
    DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 
 | 
			
		||||
        operation, addr0, addr1, size, permissions);
 | 
			
		||||
 | 
			
		||||
    switch (operation) {
 | 
			
		||||
 | 
			
		||||
    // Map normal heap memory
 | 
			
		||||
@ -43,16 +46,18 @@ Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissi
 | 
			
		||||
 | 
			
		||||
    // Unknown ControlMemory operation
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(OSHLE, "Unknown ControlMemory operation %08X", operation);
 | 
			
		||||
        ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Core::g_app_core->SetReg(1, virtual_address);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Maps a memory block to specified address
 | 
			
		||||
Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) {
 | 
			
		||||
    int x = 0;
 | 
			
		||||
    DEBUG_LOG(SVC, "MapMemoryBlock called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 
 | 
			
		||||
        memblock, addr, mypermissions, otherpermission);
 | 
			
		||||
    switch (mypermissions) {
 | 
			
		||||
    case MEMORY_PERMISSION_NORMAL:
 | 
			
		||||
    case MEMORY_PERMISSION_NORMAL + 1:
 | 
			
		||||
@ -60,20 +65,23 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper
 | 
			
		||||
        Memory::MapBlock_Shared(memblock, addr, mypermissions);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(OSHLE, "Unknown MapMemoryBlock permissions %08X", mypermissions);
 | 
			
		||||
        ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Connect to an OS service given the port name, returns the handle to the port to out
 | 
			
		||||
Result ConnectToPort(void* out, const char* port_name) {
 | 
			
		||||
    
 | 
			
		||||
    Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
 | 
			
		||||
    Core::g_app_core->SetReg(1, service->GetUID());
 | 
			
		||||
    DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Synchronize to an OS service
 | 
			
		||||
Result SendSyncRequest(Handle session) {
 | 
			
		||||
    DEBUG_LOG(SVC, "SendSyncRequest called session=0x%08X");
 | 
			
		||||
    Service::Interface* service = Service::g_manager->FetchFromUID(session);
 | 
			
		||||
    service->Sync();
 | 
			
		||||
    return 0;
 | 
			
		||||
@ -82,142 +90,177 @@ Result SendSyncRequest(Handle session) {
 | 
			
		||||
/// Close a handle
 | 
			
		||||
Result CloseHandle(Handle handle) {
 | 
			
		||||
    // ImplementMe
 | 
			
		||||
    DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Wait for a handle to synchronize, timeout after the specified nanoseconds
 | 
			
		||||
Result WaitSynchronization1(Handle handle, s64 nanoseconds) {
 | 
			
		||||
    // ImplementMe
 | 
			
		||||
    DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", 
 | 
			
		||||
        handle, nanoseconds);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Create an address arbiter (to allocate access to shared resources)
 | 
			
		||||
Result CreateAddressArbiter(void* arbiter) {
 | 
			
		||||
    // ImplementMe
 | 
			
		||||
    DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called");
 | 
			
		||||
    Core::g_app_core->SetReg(1, 0xDEADBEEF);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
 | 
			
		||||
void OutputDebugString(const char* string) {
 | 
			
		||||
    NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Get resource limit
 | 
			
		||||
Result GetResourceLimit(void* resource_limit, Handle process) {
 | 
			
		||||
    // With regards to proceess values:
 | 
			
		||||
    // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for 
 | 
			
		||||
    // the current KThread.
 | 
			
		||||
    DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process);
 | 
			
		||||
    Core::g_app_core->SetReg(1, 0xDEADBEEF);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Get resource limit current values
 | 
			
		||||
Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) {
 | 
			
		||||
    //s64* values = (s64*)_values;
 | 
			
		||||
    DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d",
 | 
			
		||||
        resource_limit, names, name_count);
 | 
			
		||||
    Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const HLE::FunctionDef Syscall_Table[] = {
 | 
			
		||||
    {0x00,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x01,  WrapI_UUUUU<ControlMemory>,         "ControlMemory"},
 | 
			
		||||
    {0x02,  NULL,                               "QueryMemory"},
 | 
			
		||||
    {0x03,  NULL,                               "ExitProcess"},
 | 
			
		||||
    {0x04,  NULL,                               "GetProcessAffinityMask"},
 | 
			
		||||
    {0x05,  NULL,                               "SetProcessAffinityMask"},
 | 
			
		||||
    {0x06,  NULL,                               "GetProcessIdealProcessor"},
 | 
			
		||||
    {0x07,  NULL,                               "SetProcessIdealProcessor"},
 | 
			
		||||
    {0x08,  NULL,                               "CreateThread"},
 | 
			
		||||
    {0x09,  NULL,                               "ExitThread"},
 | 
			
		||||
    {0x0A,  NULL,                               "SleepThread"},
 | 
			
		||||
    {0x0B,  NULL,                               "GetThreadPriority"},
 | 
			
		||||
    {0x0C,  NULL,                               "SetThreadPriority"},
 | 
			
		||||
    {0x0D,  NULL,                               "GetThreadAffinityMask"},
 | 
			
		||||
    {0x0E,  NULL,                               "SetThreadAffinityMask"},
 | 
			
		||||
    {0x0F,  NULL,                               "GetThreadIdealProcessor"},
 | 
			
		||||
    {0x10,  NULL,                               "SetThreadIdealProcessor"},
 | 
			
		||||
    {0x11,  NULL,                               "GetCurrentProcessorNumber"},
 | 
			
		||||
    {0x12,  NULL,                               "Run"},
 | 
			
		||||
    {0x13,  NULL,                               "CreateMutex"},
 | 
			
		||||
    {0x14,  NULL,                               "ReleaseMutex"},
 | 
			
		||||
    {0x15,  NULL,                               "CreateSemaphore"},
 | 
			
		||||
    {0x16,  NULL,                               "ReleaseSemaphore"},
 | 
			
		||||
    {0x17,  NULL,                               "CreateEvent"},
 | 
			
		||||
    {0x18,  NULL,                               "SignalEvent"},
 | 
			
		||||
    {0x19,  NULL,                               "ClearEvent"},
 | 
			
		||||
    {0x1A,  NULL,                               "CreateTimer"},
 | 
			
		||||
    {0x1B,  NULL,                               "SetTimer"},
 | 
			
		||||
    {0x1C,  NULL,                               "CancelTimer"},
 | 
			
		||||
    {0x1D,  NULL,                               "ClearTimer"},
 | 
			
		||||
    {0x1E,  NULL,                               "CreateMemoryBlock"},
 | 
			
		||||
    {0x1F,  WrapI_UUUU<MapMemoryBlock>,         "MapMemoryBlock"},
 | 
			
		||||
    {0x20,  NULL,                               "UnmapMemoryBlock"},
 | 
			
		||||
    {0x21,  NULL,                               "CreateAddressArbiter"},
 | 
			
		||||
    {0x22,  NULL,                               "ArbitrateAddress"},
 | 
			
		||||
    {0x23,  WrapI_U<CloseHandle>,               "CloseHandle"},
 | 
			
		||||
    {0x24,  WrapI_US64<WaitSynchronization1>,   "WaitSynchronization1"},
 | 
			
		||||
    {0x25,  NULL,                               "WaitSynchronizationN"},
 | 
			
		||||
    {0x26,  NULL,                               "SignalAndWait"},
 | 
			
		||||
    {0x27,  NULL,                               "DuplicateHandle"},
 | 
			
		||||
    {0x28,  NULL,                               "GetSystemTick"},
 | 
			
		||||
    {0x29,  NULL,                               "GetHandleInfo"},
 | 
			
		||||
    {0x2A,  NULL,                               "GetSystemInfo"},
 | 
			
		||||
    {0x2B,  NULL,                               "GetProcessInfo"},
 | 
			
		||||
    {0x2C,  NULL,                               "GetThreadInfo"},
 | 
			
		||||
    {0x2D,  WrapI_VC<ConnectToPort>,            "ConnectToPort"},
 | 
			
		||||
    {0x2E,  NULL,                               "SendSyncRequest1"},
 | 
			
		||||
    {0x2F,  NULL,                               "SendSyncRequest2"},
 | 
			
		||||
    {0x30,  NULL,                               "SendSyncRequest3"},
 | 
			
		||||
    {0x31,  NULL,                               "SendSyncRequest4"},
 | 
			
		||||
    {0x32,  WrapI_U<SendSyncRequest>,           "SendSyncRequest"},
 | 
			
		||||
    {0x33,  NULL,                               "OpenProcess"},
 | 
			
		||||
    {0x34,  NULL,                               "OpenThread"},
 | 
			
		||||
    {0x35,  NULL,                               "GetProcessId"},
 | 
			
		||||
    {0x36,  NULL,                               "GetProcessIdOfThread"},
 | 
			
		||||
    {0x37,  NULL,                               "GetThreadId"},
 | 
			
		||||
    {0x38,  NULL,                               "GetResourceLimit"},
 | 
			
		||||
    {0x39,  NULL,                               "GetResourceLimitLimitValues"},
 | 
			
		||||
    {0x3A,  NULL,                               "GetResourceLimitCurrentValues"},
 | 
			
		||||
    {0x3B,  NULL,                               "GetThreadContext"},
 | 
			
		||||
    {0x3C,  NULL,                               "Break"},
 | 
			
		||||
    {0x3D,  NULL,                               "OutputDebugString"},
 | 
			
		||||
    {0x3E,  NULL,                               "ControlPerformanceCounter"},
 | 
			
		||||
    {0x3F,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x40,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x41,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x42,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x43,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x44,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x45,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x46,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x47,  NULL,                               "CreatePort"},
 | 
			
		||||
    {0x48,  NULL,                               "CreateSessionToPort"},
 | 
			
		||||
    {0x49,  NULL,                               "CreateSession"},
 | 
			
		||||
    {0x4A,  NULL,                               "AcceptSession"},
 | 
			
		||||
    {0x4B,  NULL,                               "ReplyAndReceive1"},
 | 
			
		||||
    {0x4C,  NULL,                               "ReplyAndReceive2"},
 | 
			
		||||
    {0x4D,  NULL,                               "ReplyAndReceive3"},
 | 
			
		||||
    {0x4E,  NULL,                               "ReplyAndReceive4"},
 | 
			
		||||
    {0x4F,  NULL,                               "ReplyAndReceive"},
 | 
			
		||||
    {0x50,  NULL,                               "BindInterrupt"},
 | 
			
		||||
    {0x51,  NULL,                               "UnbindInterrupt"},
 | 
			
		||||
    {0x52,  NULL,                               "InvalidateProcessDataCache"},
 | 
			
		||||
    {0x53,  NULL,                               "StoreProcessDataCache"},
 | 
			
		||||
    {0x54,  NULL,                               "FlushProcessDataCache"},
 | 
			
		||||
    {0x55,  NULL,                               "StartInterProcessDma"},
 | 
			
		||||
    {0x56,  NULL,                               "StopDma"},
 | 
			
		||||
    {0x57,  NULL,                               "GetDmaState"},
 | 
			
		||||
    {0x58,  NULL,                               "RestartDma"},
 | 
			
		||||
    {0x59,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x5A,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x5B,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x5C,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x5D,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x5E,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x5F,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x60,  NULL,                               "DebugActiveProcess"},
 | 
			
		||||
    {0x61,  NULL,                               "BreakDebugProcess"},
 | 
			
		||||
    {0x62,  NULL,                               "TerminateDebugProcess"},
 | 
			
		||||
    {0x63,  NULL,                               "GetProcessDebugEvent"},
 | 
			
		||||
    {0x64,  NULL,                               "ContinueDebugEvent"},
 | 
			
		||||
    {0x65,  NULL,                               "GetProcessList"},
 | 
			
		||||
    {0x66,  NULL,                               "GetThreadList"},
 | 
			
		||||
    {0x67,  NULL,                               "GetDebugThreadContext"},
 | 
			
		||||
    {0x68,  NULL,                               "SetDebugThreadContext"},
 | 
			
		||||
    {0x69,  NULL,                               "QueryDebugProcessMemory"},
 | 
			
		||||
    {0x6A,  NULL,                               "ReadProcessMemory"},
 | 
			
		||||
    {0x6B,  NULL,                               "WriteProcessMemory"},
 | 
			
		||||
    {0x6C,  NULL,                               "SetHardwareBreakPoint"},
 | 
			
		||||
    {0x6D,  NULL,                               "GetDebugThreadParam"},
 | 
			
		||||
    {0x6E,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x6F,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x70,  NULL,                               "ControlProcessMemory"},
 | 
			
		||||
    {0x71,  NULL,                               "MapProcessMemory"},
 | 
			
		||||
    {0x72,  NULL,                               "UnmapProcessMemory"},
 | 
			
		||||
    {0x73,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x74,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x75,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x76,  NULL,                               "TerminateProcess"},
 | 
			
		||||
    {0x77,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x78,  NULL,                               "CreateResourceLimit"},
 | 
			
		||||
    {0x79,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x7A,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x7B,  NULL,                               "Unknown"},
 | 
			
		||||
    {0x7C,  NULL,                               "KernelSetState"},
 | 
			
		||||
    {0x7D,  NULL,                               "QueryProcessMemory"},
 | 
			
		||||
    {0x00,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x01,  WrapI_UUUUU<ControlMemory>,                 "ControlMemory"},
 | 
			
		||||
    {0x02,  NULL,                                       "QueryMemory"},
 | 
			
		||||
    {0x03,  NULL,                                       "ExitProcess"},
 | 
			
		||||
    {0x04,  NULL,                                       "GetProcessAffinityMask"},
 | 
			
		||||
    {0x05,  NULL,                                       "SetProcessAffinityMask"},
 | 
			
		||||
    {0x06,  NULL,                                       "GetProcessIdealProcessor"},
 | 
			
		||||
    {0x07,  NULL,                                       "SetProcessIdealProcessor"},
 | 
			
		||||
    {0x08,  NULL,                                       "CreateThread"},
 | 
			
		||||
    {0x09,  NULL,                                       "ExitThread"},
 | 
			
		||||
    {0x0A,  NULL,                                       "SleepThread"},
 | 
			
		||||
    {0x0B,  NULL,                                       "GetThreadPriority"},
 | 
			
		||||
    {0x0C,  NULL,                                       "SetThreadPriority"},
 | 
			
		||||
    {0x0D,  NULL,                                       "GetThreadAffinityMask"},
 | 
			
		||||
    {0x0E,  NULL,                                       "SetThreadAffinityMask"},
 | 
			
		||||
    {0x0F,  NULL,                                       "GetThreadIdealProcessor"},
 | 
			
		||||
    {0x10,  NULL,                                       "SetThreadIdealProcessor"},
 | 
			
		||||
    {0x11,  NULL,                                       "GetCurrentProcessorNumber"},
 | 
			
		||||
    {0x12,  NULL,                                       "Run"},
 | 
			
		||||
    {0x13,  NULL,                                       "CreateMutex"},
 | 
			
		||||
    {0x14,  NULL,                                       "ReleaseMutex"},
 | 
			
		||||
    {0x15,  NULL,                                       "CreateSemaphore"},
 | 
			
		||||
    {0x16,  NULL,                                       "ReleaseSemaphore"},
 | 
			
		||||
    {0x17,  NULL,                                       "CreateEvent"},
 | 
			
		||||
    {0x18,  NULL,                                       "SignalEvent"},
 | 
			
		||||
    {0x19,  NULL,                                       "ClearEvent"},
 | 
			
		||||
    {0x1A,  NULL,                                       "CreateTimer"},
 | 
			
		||||
    {0x1B,  NULL,                                       "SetTimer"},
 | 
			
		||||
    {0x1C,  NULL,                                       "CancelTimer"},
 | 
			
		||||
    {0x1D,  NULL,                                       "ClearTimer"},
 | 
			
		||||
    {0x1E,  NULL,                                       "CreateMemoryBlock"},
 | 
			
		||||
    {0x1F,  WrapI_UUUU<MapMemoryBlock>,                 "MapMemoryBlock"},
 | 
			
		||||
    {0x20,  NULL,                                       "UnmapMemoryBlock"},
 | 
			
		||||
    {0x21,  WrapI_V<CreateAddressArbiter>,              "CreateAddressArbiter"},
 | 
			
		||||
    {0x22,  NULL,                                       "ArbitrateAddress"},
 | 
			
		||||
    {0x23,  WrapI_U<CloseHandle>,                       "CloseHandle"},
 | 
			
		||||
    {0x24,  WrapI_US64<WaitSynchronization1>,           "WaitSynchronization1"},
 | 
			
		||||
    {0x25,  NULL,                                       "WaitSynchronizationN"},
 | 
			
		||||
    {0x26,  NULL,                                       "SignalAndWait"},
 | 
			
		||||
    {0x27,  NULL,                                       "DuplicateHandle"},
 | 
			
		||||
    {0x28,  NULL,                                       "GetSystemTick"},
 | 
			
		||||
    {0x29,  NULL,                                       "GetHandleInfo"},
 | 
			
		||||
    {0x2A,  NULL,                                       "GetSystemInfo"},
 | 
			
		||||
    {0x2B,  NULL,                                       "GetProcessInfo"},
 | 
			
		||||
    {0x2C,  NULL,                                       "GetThreadInfo"},
 | 
			
		||||
    {0x2D,  WrapI_VC<ConnectToPort>,                    "ConnectToPort"},
 | 
			
		||||
    {0x2E,  NULL,                                       "SendSyncRequest1"},
 | 
			
		||||
    {0x2F,  NULL,                                       "SendSyncRequest2"},
 | 
			
		||||
    {0x30,  NULL,                                       "SendSyncRequest3"},
 | 
			
		||||
    {0x31,  NULL,                                       "SendSyncRequest4"},
 | 
			
		||||
    {0x32,  WrapI_U<SendSyncRequest>,                   "SendSyncRequest"},
 | 
			
		||||
    {0x33,  NULL,                                       "OpenProcess"},
 | 
			
		||||
    {0x34,  NULL,                                       "OpenThread"},
 | 
			
		||||
    {0x35,  NULL,                                       "GetProcessId"},
 | 
			
		||||
    {0x36,  NULL,                                       "GetProcessIdOfThread"},
 | 
			
		||||
    {0x37,  NULL,                                       "GetThreadId"},
 | 
			
		||||
    {0x38,  WrapI_VU<GetResourceLimit>,                 "GetResourceLimit"},
 | 
			
		||||
    {0x39,  NULL,                                       "GetResourceLimitLimitValues"},
 | 
			
		||||
    {0x3A,  WrapI_VUVI<GetResourceLimitCurrentValues>,  "GetResourceLimitCurrentValues"},
 | 
			
		||||
    {0x3B,  NULL,                                       "GetThreadContext"},
 | 
			
		||||
    {0x3C,  NULL,                                       "Break"},
 | 
			
		||||
    {0x3D,  WrapV_C<OutputDebugString>,                 "OutputDebugString"},
 | 
			
		||||
    {0x3E,  NULL,                                       "ControlPerformanceCounter"},
 | 
			
		||||
    {0x3F,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x40,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x41,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x42,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x43,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x44,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x45,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x46,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x47,  NULL,                                       "CreatePort"},
 | 
			
		||||
    {0x48,  NULL,                                       "CreateSessionToPort"},
 | 
			
		||||
    {0x49,  NULL,                                       "CreateSession"},
 | 
			
		||||
    {0x4A,  NULL,                                       "AcceptSession"},
 | 
			
		||||
    {0x4B,  NULL,                                       "ReplyAndReceive1"},
 | 
			
		||||
    {0x4C,  NULL,                                       "ReplyAndReceive2"},
 | 
			
		||||
    {0x4D,  NULL,                                       "ReplyAndReceive3"},
 | 
			
		||||
    {0x4E,  NULL,                                       "ReplyAndReceive4"},
 | 
			
		||||
    {0x4F,  NULL,                                       "ReplyAndReceive"},
 | 
			
		||||
    {0x50,  NULL,                                       "BindInterrupt"},
 | 
			
		||||
    {0x51,  NULL,                                       "UnbindInterrupt"},
 | 
			
		||||
    {0x52,  NULL,                                       "InvalidateProcessDataCache"},
 | 
			
		||||
    {0x53,  NULL,                                       "StoreProcessDataCache"},
 | 
			
		||||
    {0x54,  NULL,                                       "FlushProcessDataCache"},
 | 
			
		||||
    {0x55,  NULL,                                       "StartInterProcessDma"},
 | 
			
		||||
    {0x56,  NULL,                                       "StopDma"},
 | 
			
		||||
    {0x57,  NULL,                                       "GetDmaState"},
 | 
			
		||||
    {0x58,  NULL,                                       "RestartDma"},
 | 
			
		||||
    {0x59,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x5A,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x5B,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x5C,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x5D,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x5E,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x5F,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x60,  NULL,                                       "DebugActiveProcess"},
 | 
			
		||||
    {0x61,  NULL,                                       "BreakDebugProcess"},
 | 
			
		||||
    {0x62,  NULL,                                       "TerminateDebugProcess"},
 | 
			
		||||
    {0x63,  NULL,                                       "GetProcessDebugEvent"},
 | 
			
		||||
    {0x64,  NULL,                                       "ContinueDebugEvent"},
 | 
			
		||||
    {0x65,  NULL,                                       "GetProcessList"},
 | 
			
		||||
    {0x66,  NULL,                                       "GetThreadList"},
 | 
			
		||||
    {0x67,  NULL,                                       "GetDebugThreadContext"},
 | 
			
		||||
    {0x68,  NULL,                                       "SetDebugThreadContext"},
 | 
			
		||||
    {0x69,  NULL,                                       "QueryDebugProcessMemory"},
 | 
			
		||||
    {0x6A,  NULL,                                       "ReadProcessMemory"},
 | 
			
		||||
    {0x6B,  NULL,                                       "WriteProcessMemory"},
 | 
			
		||||
    {0x6C,  NULL,                                       "SetHardwareBreakPoint"},
 | 
			
		||||
    {0x6D,  NULL,                                       "GetDebugThreadParam"},
 | 
			
		||||
    {0x6E,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x6F,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x70,  NULL,                                       "ControlProcessMemory"},
 | 
			
		||||
    {0x71,  NULL,                                       "MapProcessMemory"},
 | 
			
		||||
    {0x72,  NULL,                                       "UnmapProcessMemory"},
 | 
			
		||||
    {0x73,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x74,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x75,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x76,  NULL,                                       "TerminateProcess"},
 | 
			
		||||
    {0x77,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x78,  NULL,                                       "CreateResourceLimit"},
 | 
			
		||||
    {0x79,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x7A,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x7B,  NULL,                                       "Unknown"},
 | 
			
		||||
    {0x7C,  NULL,                                       "KernelSetState"},
 | 
			
		||||
    {0x7D,  NULL,                                       "QueryProcessMemory"},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Register() {
 | 
			
		||||
 | 
			
		||||
@ -89,8 +89,8 @@ bool Load_DAT(std::string &filename) {
 | 
			
		||||
        * but for the sake of making it easier... we'll temporarily/hackishly
 | 
			
		||||
        * allow it. No sense in making a proper reader for this.
 | 
			
		||||
        */
 | 
			
		||||
        u32 entrypoint = 0x080c3ee0; // write to same entrypoint as elf
 | 
			
		||||
        u32 payload_offset = 0x6F4;
 | 
			
		||||
        u32 entrypoint = 0x00100000; // write to same entrypoint as elf
 | 
			
		||||
        u32 payload_offset = 0xA150;
 | 
			
		||||
        
 | 
			
		||||
        const u8 *src = &buffer[payload_offset];
 | 
			
		||||
        u8 *dst = Memory::GetPointer(entrypoint);
 | 
			
		||||
@ -114,6 +114,47 @@ bool Load_DAT(std::string &filename) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Loads a CTR BIN file extracted from an ExeFS
 | 
			
		||||
bool Load_BIN(std::string &filename) {
 | 
			
		||||
    std::string full_path = filename;
 | 
			
		||||
    std::string path, file, extension;
 | 
			
		||||
    SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension);
 | 
			
		||||
#if EMU_PLATFORM == PLATFORM_WINDOWS
 | 
			
		||||
    path = ReplaceAll(path, "/", "\\");
 | 
			
		||||
#endif
 | 
			
		||||
    File::IOFile f(filename, "rb");
 | 
			
		||||
 | 
			
		||||
    if (f.IsOpen()) {
 | 
			
		||||
        u64 size = f.GetSize();
 | 
			
		||||
        u8* buffer = new u8[size];
 | 
			
		||||
 | 
			
		||||
        f.ReadBytes(buffer, size);
 | 
			
		||||
 | 
			
		||||
        u32 entrypoint = 0x00100000; // Hardcoded, read from exheader
 | 
			
		||||
        
 | 
			
		||||
        const u8 *src = buffer;
 | 
			
		||||
        u8 *dst = Memory::GetPointer(entrypoint);
 | 
			
		||||
        u32 srcSize = size;
 | 
			
		||||
        u32 *s = (u32*)src;
 | 
			
		||||
        u32 *d = (u32*)dst;
 | 
			
		||||
        for (int j = 0; j < (int)(srcSize + 3) / 4; j++)
 | 
			
		||||
        {
 | 
			
		||||
            *d++ = (*s++);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        Core::g_app_core->SetPC(entrypoint);
 | 
			
		||||
 | 
			
		||||
        delete[] buffer;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    f.Close();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Loader {
 | 
			
		||||
 | 
			
		||||
bool IsBootableDirectory() {
 | 
			
		||||
@ -145,6 +186,9 @@ FileType IdentifyFile(std::string &filename) {
 | 
			
		||||
    else if (!strcasecmp(extension.c_str(), ".elf")) {
 | 
			
		||||
        return FILETYPE_CTR_ELF; // TODO(bunnei): Do some filetype checking :p
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcasecmp(extension.c_str(), ".bin")) {
 | 
			
		||||
        return FILETYPE_CTR_BIN;
 | 
			
		||||
    }
 | 
			
		||||
    else if (!strcasecmp(extension.c_str(), ".dat")) {
 | 
			
		||||
        return FILETYPE_LAUNCHER_DAT;
 | 
			
		||||
    }
 | 
			
		||||
@ -178,6 +222,9 @@ bool LoadFile(std::string &filename, std::string *error_string) {
 | 
			
		||||
    case FILETYPE_CTR_ELF:
 | 
			
		||||
        return Load_ELF(filename);
 | 
			
		||||
 | 
			
		||||
    case FILETYPE_CTR_BIN:
 | 
			
		||||
        return Load_BIN(filename);
 | 
			
		||||
 | 
			
		||||
    case FILETYPE_LAUNCHER_DAT:
 | 
			
		||||
        return Load_DAT(filename);
 | 
			
		||||
 | 
			
		||||
@ -215,7 +262,7 @@ bool LoadFile(std::string &filename, std::string *error_string) {
 | 
			
		||||
    case FILETYPE_UNKNOWN:
 | 
			
		||||
    default:
 | 
			
		||||
        ERROR_LOG(LOADER, "Failed to identify file");
 | 
			
		||||
        *error_string = "Failed to identify file";
 | 
			
		||||
        *error_string = " Failed to identify file";
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
@ -17,19 +17,21 @@ enum FileType {
 | 
			
		||||
    FILETYPE_CTR_CIA,
 | 
			
		||||
    FILETYPE_CTR_CXI,
 | 
			
		||||
    FILETYPE_CTR_ELF,
 | 
			
		||||
    FILETYPE_CTR_BIN,
 | 
			
		||||
 | 
			
		||||
    FILETYPE_LAUNCHER_DAT,
 | 
			
		||||
 | 
			
		||||
	FILETYPE_DIRECTORY_CXI,
 | 
			
		||||
 | 
			
		||||
	FILETYPE_UNKNOWN_BIN,
 | 
			
		||||
	FILETYPE_UNKNOWN_ELF,
 | 
			
		||||
 | 
			
		||||
	FILETYPE_ARCHIVE_RAR,
 | 
			
		||||
	FILETYPE_ARCHIVE_ZIP,
 | 
			
		||||
 | 
			
		||||
	FILETYPE_NORMAL_DIRECTORY,
 | 
			
		||||
 | 
			
		||||
	FILETYPE_UNKNOWN
 | 
			
		||||
    FILETYPE_DIRECTORY_CXI,
 | 
			
		||||
    
 | 
			
		||||
    FILETYPE_UNKNOWN_BIN,
 | 
			
		||||
    FILETYPE_UNKNOWN_ELF,
 | 
			
		||||
    
 | 
			
		||||
    FILETYPE_ARCHIVE_RAR,
 | 
			
		||||
    FILETYPE_ARCHIVE_ZIP,
 | 
			
		||||
    
 | 
			
		||||
    FILETYPE_NORMAL_DIRECTORY,
 | 
			
		||||
    
 | 
			
		||||
    FILETYPE_UNKNOWN
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ u8* g_heap                      = NULL;         ///< Application heap (main memo
 | 
			
		||||
u8* g_heap_gsp                  = NULL;         ///< GSP heap (main memory)
 | 
			
		||||
u8* g_vram                      = NULL;         ///< Video memory (VRAM) pointer
 | 
			
		||||
u8* g_shared_mem                = NULL;         ///< Shared memory
 | 
			
		||||
u8* g_kernel_mem;                               ///< Kernel memory
 | 
			
		||||
 | 
			
		||||
u8* g_physical_bootrom          = NULL;         ///< Bootrom physical memory
 | 
			
		||||
u8* g_uncached_bootrom          = NULL;
 | 
			
		||||
@ -30,6 +31,7 @@ u8* g_physical_fcram            = NULL;         ///< Main physical memory (FCRAM
 | 
			
		||||
u8* g_physical_heap_gsp         = NULL;         ///< GSP heap physical memory
 | 
			
		||||
u8* g_physical_vram             = NULL;         ///< Video physical memory (VRAM)
 | 
			
		||||
u8* g_physical_shared_mem       = NULL;         ///< Physical shared memory
 | 
			
		||||
u8* g_physical_kernel_mem;                      ///< Kernel memory
 | 
			
		||||
 | 
			
		||||
// We don't declare the IO region in here since its handled by other means.
 | 
			
		||||
static MemoryView g_views[] = {
 | 
			
		||||
@ -37,6 +39,7 @@ static MemoryView g_views[] = {
 | 
			
		||||
    {&g_vram,       &g_physical_vram,       VRAM_VADDR,             VRAM_SIZE,          0},
 | 
			
		||||
    {&g_heap,       &g_physical_fcram,      HEAP_VADDR,             HEAP_SIZE,          MV_IS_PRIMARY_RAM},
 | 
			
		||||
    {&g_shared_mem, &g_physical_shared_mem, SHARED_MEMORY_VADDR,    SHARED_MEMORY_SIZE, 0},
 | 
			
		||||
    {&g_kernel_mem, &g_physical_kernel_mem, KERNEL_MEMORY_VADDR,    KERNEL_MEMORY_SIZE, 0},
 | 
			
		||||
    {&g_heap_gsp,   &g_physical_heap_gsp,   HEAP_GSP_VADDR,         HEAP_GSP_SIZE,      0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -32,10 +32,20 @@ enum {
 | 
			
		||||
    SHARED_MEMORY_VADDR_END = (SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE),
 | 
			
		||||
    SHARED_MEMORY_MASK      = (SHARED_MEMORY_SIZE - 1),
 | 
			
		||||
 | 
			
		||||
    CONFIG_MEMORY_SIZE      = 0x00001000,   ///< Configuration memory size
 | 
			
		||||
    CONFIG_MEMORY_VADDR     = 0x1FF80000,   ///< Configuration memory virtual address
 | 
			
		||||
    CONFIG_MEMORY_VADDR_END = (CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE),
 | 
			
		||||
    CONFIG_MEMORY_MASK      = (CONFIG_MEMORY_SIZE - 1),
 | 
			
		||||
 | 
			
		||||
    KERNEL_MEMORY_SIZE      = 0x00001000,   ///< Kernel memory size
 | 
			
		||||
    KERNEL_MEMORY_VADDR     = 0xFFFF0000,   ///< Kernel memory where the kthread objects etc are
 | 
			
		||||
    KERNEL_MEMORY_VADDR_END = (KERNEL_MEMORY_VADDR + KERNEL_MEMORY_SIZE),
 | 
			
		||||
    KERNEL_MEMORY_MASK      = (KERNEL_MEMORY_SIZE - 1),
 | 
			
		||||
 | 
			
		||||
    EXEFS_CODE_SIZE         = 0x03F00000,
 | 
			
		||||
    EXEFS_CODE_VADDR        = 0x00100000,   ///< ExeFS:/.code is loaded here
 | 
			
		||||
    EXEFS_CODE_VADDR_END    = (EXEFS_CODE_VADDR + EXEFS_CODE_SIZE),
 | 
			
		||||
    EXEFS_CODE_MASK         = (EXEFS_CODE_VADDR - 1),
 | 
			
		||||
    EXEFS_CODE_MASK         = 0x03FFFFFF,
 | 
			
		||||
 | 
			
		||||
    HEAP_SIZE               = FCRAM_SIZE,   ///< Application heap size
 | 
			
		||||
    //HEAP_PADDR              = HEAP_GSP_SIZE,
 | 
			
		||||
@ -105,6 +115,7 @@ extern u8* g_heap_gsp;      ///< GSP heap (main memory)
 | 
			
		||||
extern u8* g_heap;          ///< Application heap (main memory)
 | 
			
		||||
extern u8* g_vram;          ///< Video memory (VRAM)
 | 
			
		||||
extern u8* g_shared_mem;    ///< Shared memory
 | 
			
		||||
extern u8* g_kernel_mem;    ///< Kernel memory
 | 
			
		||||
extern u8* g_exefs_code;    ///< ExeFS:/.code is loaded here
 | 
			
		||||
 | 
			
		||||
void Init();
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
#include "core/mem_map.h"
 | 
			
		||||
#include "core/hw/hw.h"
 | 
			
		||||
#include "hle/hle.h"
 | 
			
		||||
#include "hle/config_mem.h"
 | 
			
		||||
 | 
			
		||||
namespace Memory {
 | 
			
		||||
 | 
			
		||||
@ -46,12 +47,10 @@ inline void _Read(T &var, const u32 addr) {
 | 
			
		||||
    // Could just do a base-relative read, too.... TODO
 | 
			
		||||
 | 
			
		||||
    const u32 vaddr = _VirtualAddress(addr);
 | 
			
		||||
    
 | 
			
		||||
    // Memory allocated for HLE use that can be addressed from the emulated application
 | 
			
		||||
    // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
 | 
			
		||||
    // core running the user application (appcore)
 | 
			
		||||
    if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) {
 | 
			
		||||
        HLE::Read<T>(var, vaddr);
 | 
			
		||||
 | 
			
		||||
    // Kernel memory command buffer
 | 
			
		||||
    if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
 | 
			
		||||
        var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]);
 | 
			
		||||
 | 
			
		||||
    // Hardware I/O register reads
 | 
			
		||||
    // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
 | 
			
		||||
@ -74,6 +73,10 @@ inline void _Read(T &var, const u32 addr) {
 | 
			
		||||
    } else if ((vaddr >= SHARED_MEMORY_VADDR)  && (vaddr < SHARED_MEMORY_VADDR_END)) {
 | 
			
		||||
        var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
 | 
			
		||||
 | 
			
		||||
    // Config memory
 | 
			
		||||
    } else if ((vaddr >= CONFIG_MEMORY_VADDR)  && (vaddr < CONFIG_MEMORY_VADDR_END)) {
 | 
			
		||||
        ConfigMem::Read<T>(var, vaddr);
 | 
			
		||||
 | 
			
		||||
    // VRAM
 | 
			
		||||
    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
 | 
			
		||||
        var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
 | 
			
		||||
@ -87,11 +90,9 @@ template <typename T>
 | 
			
		||||
inline void _Write(u32 addr, const T data) {
 | 
			
		||||
    u32 vaddr = _VirtualAddress(addr);
 | 
			
		||||
    
 | 
			
		||||
    // Memory allocated for HLE use that can be addressed from the emulated application
 | 
			
		||||
    // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
 | 
			
		||||
    // core running the user application (appcore)
 | 
			
		||||
    if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) {
 | 
			
		||||
        HLE::Write<T>(vaddr, data);
 | 
			
		||||
    // Kernel memory command buffer
 | 
			
		||||
    if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
 | 
			
		||||
        *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data;
 | 
			
		||||
 | 
			
		||||
    // Hardware I/O register writes
 | 
			
		||||
    // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
 | 
			
		||||
@ -118,12 +119,12 @@ inline void _Write(u32 addr, const T data) {
 | 
			
		||||
    } else if ((vaddr >= VRAM_VADDR)  && (vaddr < VRAM_VADDR_END)) {
 | 
			
		||||
        *(T*)&g_vram[vaddr & VRAM_MASK] = data;
 | 
			
		||||
 | 
			
		||||
    } else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
 | 
			
		||||
        _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
 | 
			
		||||
    } else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
 | 
			
		||||
        _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory");
 | 
			
		||||
    } else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
 | 
			
		||||
        _assert_msg_(MEMMAP, false, "umimplemented write to shared page");
 | 
			
		||||
    //} else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
 | 
			
		||||
    //    _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
 | 
			
		||||
    //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
 | 
			
		||||
    //    _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory");
 | 
			
		||||
    //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
 | 
			
		||||
    //    _assert_msg_(MEMMAP, false, "umimplemented write to shared page");
 | 
			
		||||
    
 | 
			
		||||
    // Error out...
 | 
			
		||||
    } else {
 | 
			
		||||
@ -135,8 +136,12 @@ inline void _Write(u32 addr, const T data) {
 | 
			
		||||
u8 *GetPointer(const u32 addr) {
 | 
			
		||||
    const u32 vaddr = _VirtualAddress(addr);
 | 
			
		||||
 | 
			
		||||
    // Kernel memory command buffer
 | 
			
		||||
    if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
 | 
			
		||||
        return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK);
 | 
			
		||||
 | 
			
		||||
    // ExeFS:/.code is loaded here
 | 
			
		||||
    if ((vaddr >= EXEFS_CODE_VADDR)  && (vaddr < EXEFS_CODE_VADDR_END)) {
 | 
			
		||||
    } else if ((vaddr >= EXEFS_CODE_VADDR)  && (vaddr < EXEFS_CODE_VADDR_END)) {
 | 
			
		||||
        return g_exefs_code + (vaddr & EXEFS_CODE_MASK);
 | 
			
		||||
 | 
			
		||||
    // FCRAM - GSP heap
 | 
			
		||||
 | 
			
		||||
@ -58,15 +58,14 @@ void RendererOpenGL::SwapBuffers() {
 | 
			
		||||
 * @todo Early on hack... I'd like to find a more efficient way of doing this /bunnei
 | 
			
		||||
 */
 | 
			
		||||
void RendererOpenGL::FlipFramebuffer(const u8* in, u8* out) {
 | 
			
		||||
    for (int y = 0; y < VideoCore::kScreenTopHeight; y++) {
 | 
			
		||||
        for (int x = 0; x < VideoCore::kScreenTopWidth; x++) {
 | 
			
		||||
            int in_coord = (VideoCore::kScreenTopHeight * 3 * x) + (VideoCore::kScreenTopHeight * 3)
 | 
			
		||||
                - (3 * y + 3);
 | 
			
		||||
            int out_coord = (VideoCore::kScreenTopWidth * y * 3) + (x * 3);
 | 
			
		||||
 | 
			
		||||
            out[out_coord + 0] = in[in_coord + 0];
 | 
			
		||||
    int in_coord = 0;
 | 
			
		||||
    for (int x = 0; x < VideoCore::kScreenTopWidth; x++) {
 | 
			
		||||
        for (int y = VideoCore::kScreenTopHeight-1; y >= 0; y--) {
 | 
			
		||||
            int out_coord = (x + y * VideoCore::kScreenTopWidth) * 3;
 | 
			
		||||
            out[out_coord] = in[in_coord];
 | 
			
		||||
            out[out_coord + 1] = in[in_coord + 1];
 | 
			
		||||
            out[out_coord + 2] = in[in_coord + 2];
 | 
			
		||||
            in_coord+=3;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user