feat(tlib): 新增MIPS32架构支持
为Renode添加龙芯1E300的MIPS32最小架构实现 **主要内容:** - 创建完整的MIPS32 CPU状态结构 - 实现CP0系统控制寄存器 - 添加MMU和中断处理框架 - 集成TCG翻译和softmmu支持 - 提供C#接口层 **构建结果:** - 成功编译translate-mips-le.so(791KB) - 所有符号正确链接 **后续工作:** 指令执行逻辑将在后续提交中实现 Authored: liuwb <liuwb@microsat.com>
This commit is contained in:
260
README.md
260
README.md
@@ -1,3 +1,259 @@
|
||||
# simulation_core
|
||||
# Renode
|
||||
|
||||
仿真平台_内核
|
||||
Copyright (c) 2010-2026 [Antmicro](https://www.antmicro.com)
|
||||
|
||||
[](https://opensource.antmicro.com/projects/renode)
|
||||
|
||||
## What is Renode?
|
||||
|
||||
Renode was created by Antmicro as a virtual development tool for multi-node embedded networks (both wired and wireless) and is intended to enable a scalable workflow for creating effective, tested and secure IoT systems.
|
||||
|
||||
With Renode, developing, testing, debugging and simulating unmodified software for IoT devices is fast, cost-effective and reliable.
|
||||
|
||||
Supported architectures include:
|
||||
|
||||
* ARMv7 and ARMv8 Cortex-A, Cortex-R and Cortex-M
|
||||
* x86 and x86_64
|
||||
* RISC-V
|
||||
* SPARC
|
||||
* POWER
|
||||
* Xtensa
|
||||
* MSP430X
|
||||
|
||||
## Why use Renode?
|
||||
|
||||
Renode was created based on many years of experience with the development of software for embedded systems - both for gateways, on-board computers, as well as sensor nodes and microcontrollers.
|
||||
|
||||
Testing and developing physical embedded systems is difficult due to poor reproducibility and lack of insight into the current state of a system, especially in multi-node scenarios.
|
||||
|
||||
Renode addresses this issue by letting you run unmodified binaries identical to the ones you would normally flash onto their target hardware on a virtual board or system of boards.
|
||||
|
||||
One important aspect of the tool is that it simulates not only CPUs but entire SoCs (e.g., heterogeneous multicore SoCs and various peripherals) as well as the wired or wireless connections between them, allowing users to address complex scenarios and test real production software.
|
||||
|
||||
## Installation
|
||||
|
||||
### Available builds and releases
|
||||
|
||||
#### Nightly builds
|
||||
|
||||
Nightly builds of Renode for all systems are available at [builds.renode.io](https://builds.renode.io).
|
||||
|
||||
The latest builds are always available as `renode-latest.*` packages.
|
||||
The following packages formats are available:
|
||||
* [`renode-latest.linux-portable-dotnet.tar.gz`](https://builds.renode.io/renode-latest.linux-portable-dotnet.tar.gz) - portable Linux package, embeds dotnet runtime
|
||||
* [`renode-latest.linux-portable.tar.gz`](https://builds.renode.io/renode-latest.linux-portable.tar.gz) - portable Linux package, embeds Mono runtime
|
||||
* [`renode-latest.linux-dotnet.tar.gz`](https://builds.renode.io/renode-latest.linux-dotnet.tar.gz) - Linux prebuilt archive, requires dotnet installed on host
|
||||
* [`renode-latest.pkg.tar.xz`](https://builds.renode.io/renode-latest.pkg.tar.xz) - Arch Linux package
|
||||
* [`renode-latest.x86_64.rpm`](https://builds.renode.io/renode-latest.x86_64.rpm) - Red Hat / Fedora package
|
||||
* [`renode-latest.deb`](https://builds.renode.io/renode-latest.deb) - Debian-based distribution package
|
||||
* [`renode-latest.dmg`](https://builds.renode.io/renode-latest.dmg) - macOS package
|
||||
* [`renode-latest.windows-portable-dotnet.zip`](https://builds.renode.io/renode-latest.windows-portable-dotnet.zip) - Windows portable package, without installer
|
||||
* [`renode-latest.setup.exe`](https://builds.renode.io/renode-latest.setup.exe) - Windows installer
|
||||
* [`renode-latest.tar.xz`](https://builds.renode.io/renode-latest.tar.xz) - Renode sources
|
||||
|
||||
#### Stable releases
|
||||
|
||||
Stable, numbered releases and their release notes are available in the [Releases section](https://github.com/renode/renode/releases) on GitHub.
|
||||
|
||||
### Using the Linux portable release
|
||||
|
||||
If you are a Linux user, the easiest way to use Renode is to download the latest `linux-portable` from [the releases section](https://github.com/renode/renode/releases/latest) and unpack it using:
|
||||
|
||||
```
|
||||
mkdir renode_portable
|
||||
wget https://builds.renode.io/renode-latest.linux-portable.tar.gz
|
||||
tar xf renode-latest.linux-portable.tar.gz -C renode_portable --strip-components=1
|
||||
```
|
||||
|
||||
To use it from any location, enter the created directory and add it to the system path:
|
||||
|
||||
```
|
||||
cd renode_portable
|
||||
export PATH="`pwd`:$PATH"
|
||||
```
|
||||
|
||||
Please note that the portable package requires GTK2 to be available on the host to run with the UI enabled.
|
||||
|
||||
Follow the [Additional Prerequisites](#additional-prerequisites-for-robot-framework-testing) section if you wish to use Robot Framework for testing.
|
||||
Otherwise, proceed to the 'Running Renode' section.
|
||||
|
||||
### Installing dependencies
|
||||
|
||||
#### Mono/dotnet
|
||||
|
||||
Renode requires Mono >= 5.20 (Linux, macOS) or .NET Framework >= 4.7 (Windows).
|
||||
On all systems, you can also use dotnet >= 6.0.
|
||||
|
||||
##### Linux
|
||||
|
||||
To install dotnet on Linux, follow [the official installation guide](https://learn.microsoft.com/en-us/dotnet/core/install/linux).
|
||||
|
||||
Alternatively, install the `mono-complete` package as per the installation instructions for various Linux distributions you can find on [the Mono project website](https://www.mono-project.com/download/stable/#download-lin).
|
||||
|
||||
##### macOS
|
||||
|
||||
To install dotnet on macOS, follow [the official installation guide](https://learn.microsoft.com/en-us/dotnet/core/install/macos).
|
||||
|
||||
Alternatively, for Mono-based setups, you can download the Mono package directly from [the Mono project website](https://download.mono-project.com/archive/mdk-latest-stable.pkg).
|
||||
|
||||
##### Windows
|
||||
|
||||
To install modern dotnet (as opposed to .NET Framework) on Windows, follow [the official installation guide](https://learn.microsoft.com/en-us/dotnet/core/install/windows).
|
||||
The **.NET SDK** includes runtime, so you will be able to build and run Renode.
|
||||
|
||||
#### Other dependencies (Linux only)
|
||||
|
||||
On Ubuntu 20.04, you can install the remaining dependencies with the following command:
|
||||
|
||||
```
|
||||
sudo apt-get install policykit-1 libgtk2.0-0 screen uml-utilities gtk-sharp2 libc6-dev libicu-dev gcc python3 python3-pip
|
||||
```
|
||||
|
||||
If you are running a different distribution, you will need to install an analogous list of packages using your package manager; note that the package names may differ slightly.
|
||||
|
||||
### Installing from packages
|
||||
|
||||
Go to [the releases section](https://github.com/renode/renode/releases/latest) of this repository and download an appropriate package for your system.
|
||||
|
||||
#### Linux
|
||||
|
||||
Install Renode with your preferred package manager using the provided `*.deb`, `*.rpm` or `*.pkg.tar.xz` packages.
|
||||
|
||||
#### macOS
|
||||
|
||||
Use the provided `*.dmg` as normal.
|
||||
Additionally, to use Renode from the command line on macOS, create appropriate aliases by adding `alias renode='mono /Applications/Renode.app/Contents/MacOS/bin/Renode.exe'` and `alias renode-test='/Applications/Renode.app/Contents/MacOS/tests/renode-test'` to your `.bashrc` or `.zshrc` file, depending on the shell you're using.
|
||||
|
||||
#### Windows
|
||||
|
||||
Install Renode from the provided `*.msi` file. The installer will allow you to add icons to your Desktop and/or Start Menu and an entry to your PATH.
|
||||
|
||||
### Additional prerequisites
|
||||
|
||||
#### Robot Framework testing
|
||||
|
||||
To write and run test cases, Renode integrates with the Robot testing framework.
|
||||
This requires you to install Python 3 (on Windows, you will also need Cygwin - see [the advanced installation instructions](https://renode.readthedocs.io/en/latest/advanced/building_from_sources.html#windows)) with `pip` (note that the relevant package may be called `python-pip` or `python3-pip` on Linux).
|
||||
|
||||
Once you have Python 3 and `pip`, install additional modules:
|
||||
|
||||
```
|
||||
python3 -m pip install -r tests/requirements.txt
|
||||
```
|
||||
|
||||
#### Other tools
|
||||
|
||||
Additionally, each of the tools in the `/tools` subdirectory may contain a `requirements.txt` file separate from Renode's requirements.
|
||||
|
||||
Install them in your virtual environment with `pip install -r requirements.txt`.
|
||||
|
||||
### Building from source
|
||||
|
||||
For information on building Renode from source, see [the documentation](https://renode.readthedocs.io/en/latest/advanced/building_from_sources.html).
|
||||
|
||||
## Running Renode
|
||||
|
||||
After following the instructions above on installation from a package, you should have the `renode` command available system-wide:
|
||||
|
||||
```
|
||||
renode [flags] [file]
|
||||
```
|
||||
|
||||
If you built it from source, navigate to the relevant directory and use:
|
||||
|
||||
```
|
||||
./renode [flags] [file]
|
||||
```
|
||||
|
||||
The optional `[file]` argument allows you to provide the path to a script to be run on startup.
|
||||
|
||||
The script allows several optional flags, the most useful of which are presented below:
|
||||
|
||||
```
|
||||
-p Remove steering codes (e.g., colours) from output
|
||||
-P INT32 Instead of opening a window, listen for Monitor commands on the specified port
|
||||
-e COMMAND Execute command on startup (executed after the optional script). May be used multiple times
|
||||
--console Run the Monitor in the console instead of a separate window
|
||||
--disable-gui Disable XWT GUI support. It automatically sets HideMonitor
|
||||
--hide-monitor Do not show the Monitor window
|
||||
--hide-log Do not show log messages in console
|
||||
--hide-analyzers Do not show analyzers
|
||||
-v Print version and exit
|
||||
-h Display help and usage information
|
||||
```
|
||||
|
||||
Renode can be run on Windows systems with a similar set of optional flags.
|
||||
|
||||
### Sample scenario
|
||||
|
||||
Below, you can see a piece of firmware running on simulated hardware.
|
||||
The Renode Monitor is visible alongside an analyzer window displaying UART output and logger.
|
||||
For more information about this particular setup, see [its dedicated repository](https://github.com/antmicro/renode-tesla-roadster-simulation).
|
||||
|
||||

|
||||
|
||||
### Alternative ways for running Renode on Linux
|
||||
|
||||
#### renode-run
|
||||
|
||||
`renode-run` is a Python script that downloads and runs Renode, and lets you easily run demos available in [Renodepedia](https://zephyr-dashboard.renode.io/renodepedia/) as well as local ELF files.
|
||||
Go to [the repository](https://github.com/antmicro/renode-run) for usage instructions.
|
||||
|
||||
`renode-run` relies on a portable package and its main advantage is the ease of updating Renode to the latest nightly build using a single command.
|
||||
|
||||
#### pyrenode3
|
||||
|
||||
`pyrenode3` is a A Python library for interacting with Renode programmatically.
|
||||
Go to [the repository](https://github.com/antmicro/pyrenode3) for usage instructions.
|
||||
|
||||
#### Running Renode in a Docker container
|
||||
|
||||
If you want to run Renode in Docker, you can use prebuilt images available on [Docker Hub](https://hub.docker.com/r/antmicro/renode).
|
||||
|
||||
To start Renode in interactive mode on Linux, assuming you have Docker installed in your system, run one of the following:
|
||||
|
||||
* For the latest numbered version build:
|
||||
```
|
||||
docker run -ti -e DISPLAY -v $XAUTHORITY:/home/developer/.Xauthority --net=host antmicro/renode:latest
|
||||
```
|
||||
* For a nightly mono build:
|
||||
```
|
||||
docker run -ti -e DISPLAY -v $XAUTHORITY:/home/developer/.Xauthority --net=host antmicro/renode:nightly
|
||||
```
|
||||
* For a nightly dotnet build:
|
||||
```
|
||||
docker run -ti -e DISPLAY -v $XAUTHORITY:/home/developer/.Xauthority --net=host antmicro/renode:nightly-dotnet
|
||||
```
|
||||
|
||||
This will display the Renode Monitor window.
|
||||
Alternatively, you can provide your custom command at the end of the line above.
|
||||
|
||||
To run the image in console mode without X server passthrough, run:
|
||||
|
||||
```
|
||||
docker run -ti antmicro/renode bash
|
||||
```
|
||||
|
||||
You can add more `-v` switches to the command to mount your own directories.
|
||||
|
||||
For more information and the underlying Dockerfile, visit the [repository on GitHub](https://github.com/renode/renode-docker).
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation is available on [Read the Docs](https://renode.readthedocs.io).
|
||||
|
||||
## License & contributions
|
||||
|
||||
Renode is released under the permissive MIT license.
|
||||
For details, see the [LICENSE](LICENSE) file.
|
||||
|
||||
We're happy to accept bug reports, feature requests, and contributions via GitHub pull requests / issues.
|
||||
For details, see the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
||||
|
||||
## Commercial support
|
||||
|
||||
Commercial support for Renode is provided by [Antmicro](https://antmicro.com), a company specializing in helping its clients to adopt new embedded technologies and modern development methodologies.
|
||||
|
||||
Antmicro created and maintains the Renode Framework and related tooling and is happy to provide services such as adding new platforms, integrations, plugins, and tools.
|
||||
|
||||
To inquire about our services, contact us at [support@renode.io](mailto:support@renode.io).
|
||||
|
||||
5
build.sh
5
build.sh
@@ -433,7 +433,10 @@ fi
|
||||
|
||||
# This list contains all cores that will be built.
|
||||
# If you are adding a new core or endianness add it here to have the correct tlib built
|
||||
CORES=(arm.le arm.be arm64.le arm-m.le arm-m.be ppc.le ppc.be ppc64.le ppc64.be i386.le x86_64.le riscv.le riscv64.le sparc.le sparc.be xtensa.le)
|
||||
# [MIPS架构支持] 添加 mips.le 和 mips.be 以支持龙芯1E300等MIPS处理器(小端和大端)
|
||||
# [MIPS架构支持] 添加 mips64.le 和 mips64.be 以支持64位MIPS处理器
|
||||
CORES=(arm.le arm.be arm64.le arm-m.le arm-m.be ppc.le ppc.be ppc64.le ppc64.be i386.le x86_64.le riscv.le riscv64.le sparc.le sparc.be xtensa.le mips.le mips.be mips64.le mips64.be)
|
||||
# CORES=(arm.le arm.be arm64.le arm-m.le arm-m.be ppc.le ppc.be ppc64.le ppc64.be i386.le x86_64.le riscv.le riscv64.le sparc.le sparc.be xtensa.le)
|
||||
|
||||
# if '--external-lib-arch' was used - pick the first matching one
|
||||
if [[ ! -z $EXTERNAL_LIB_ARCH ]]; then
|
||||
|
||||
@@ -94,7 +94,9 @@ set (TARGET_WORD_SIZE "32" CACHE STRING "Target word size")
|
||||
message(VERBOSE "Target is: ${TARGET_WORD_SIZE}-bit ${TARGET_ARCH}")
|
||||
|
||||
set_property (CACHE HOST_ARCH PROPERTY STRINGS i386 arm aarch64)
|
||||
set_property (CACHE TARGET_ARCH PROPERTY STRINGS i386 x86_64 arm arm-m arm64 sparc ppc ppc64 riscv riscv64 xtensa)
|
||||
# [MIPS架构支持] 在目标架构列表中添加 mips 和 mips64,用于支持龙芯1E300等MIPS处理器
|
||||
set_property (CACHE TARGET_ARCH PROPERTY STRINGS i386 x86_64 arm arm-m arm64 sparc ppc ppc64 riscv riscv64 xtensa mips mips64)
|
||||
# set_property (CACHE TARGET_ARCH PROPERTY STRINGS i386 x86_64 arm arm-m arm64 sparc ppc ppc64 riscv riscv64 xtensa)
|
||||
|
||||
if(NOT HOST_ARCH)
|
||||
message (FATAL_ERROR "Host architecture not set")
|
||||
@@ -133,7 +135,9 @@ if(NOT ${CMAKE_PROJECT_NAME} STREQUAL tlib)
|
||||
endif()
|
||||
|
||||
set(TARGET_INSN_START_EXTRA_WORDS 0)
|
||||
if("${TARGET_ACTUAL_ARCH}" MATCHES "^(arm|i386|sparc)$")
|
||||
# [MIPS架构支持] 为MIPS架构设置指令起始额外字段数为1,与ARM、i386、SPARC保持一致
|
||||
# 这个参数用于TCG中间代码生成时的指令跟踪,MIPS32需要额外的1个字段来存储延迟槽信息
|
||||
if("${TARGET_ACTUAL_ARCH}" MATCHES "^(arm|i386|sparc|mips)$")
|
||||
set(TARGET_INSN_START_EXTRA_WORDS 1)
|
||||
elseif("${TARGET_ACTUAL_ARCH}" STREQUAL "arm64")
|
||||
set(TARGET_INSN_START_EXTRA_WORDS 2)
|
||||
@@ -143,6 +147,15 @@ if("${TARGET_ACTUAL_ARCH}" STREQUAL "arm64" AND NOT "${TARGET_WORD_SIZE}" STREQU
|
||||
message (FATAL_ERROR "ERROR: arm64 target has to be built with TARGET_WORD_SIZE=64")
|
||||
endif()
|
||||
|
||||
# [MIPS架构支持] 为MIPS架构设置特定的编译配置
|
||||
# 1. TARGET_LONG_BITS=32: 设置目标long类型为32位(MIPS32标准)
|
||||
# 2. TARGET_MIPS宏: 启用MIPS特定的代码路径和功能
|
||||
# 3. 这些定义会影响cpu.h中的类型定义和指令翻译行为
|
||||
if("${TARGET_ACTUAL_ARCH}" STREQUAL "mips")
|
||||
set(TARGET_LONG_BITS 32)
|
||||
add_definitions(-DTARGET_MIPS)
|
||||
endif()
|
||||
|
||||
string (TOUPPER "${HOST_ARCH}" HOST_ARCH_U)
|
||||
string (TOUPPER "${TARGET_ACTUAL_ARCH}" TARGET_ACTUAL_ARCH_U)
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* MIPS callbacks.
|
||||
*
|
||||
* Copyright (c) Antmicro
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "arch_callbacks.h"
|
||||
|
||||
// 默认中断处理 - 返回-1表示没有挂起的中断
|
||||
DEFAULT_INT_HANDLER1(int32_t tlib_find_best_interrupt, void)
|
||||
|
||||
// 默认中断确认处理 - 空实现
|
||||
DEFAULT_VOID_HANDLER1(void tlib_acknowledge_interrupt, int32_t number)
|
||||
|
||||
// 默认CPU停机处理 - 空实现
|
||||
DEFAULT_VOID_HANDLER1(void tlib_on_cpu_halted, void)
|
||||
|
||||
// 默认CPU断电处理 - 空实现
|
||||
DEFAULT_VOID_HANDLER1(void tlib_on_cpu_power_down, void)
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* MIPS callbacks.
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// MIPS架构回调函数声明
|
||||
// 这些函数由tlib调用,在C#层实现
|
||||
|
||||
// 查找最高优先级的中断
|
||||
int32_t tlib_find_best_interrupt(void);
|
||||
|
||||
// 确认中断(清除中断源)
|
||||
void tlib_acknowledge_interrupt(int32_t number);
|
||||
|
||||
// CPU停机回调
|
||||
void tlib_on_cpu_halted(void);
|
||||
|
||||
// CPU断电回调
|
||||
void tlib_on_cpu_power_down(void);
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIPS interface functions.
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cpu.h"
|
||||
#include "unwind.h"
|
||||
|
||||
// 设置程序入口点
|
||||
void tlib_set_entry_point(uint32_t entry_point)
|
||||
{
|
||||
cpu->pc = entry_point;
|
||||
}
|
||||
|
||||
EXC_VOID_1(tlib_set_entry_point, uint32_t, entry_point)
|
||||
|
||||
// 设置CPU ID(用于多核)
|
||||
void tlib_set_cpu_id(uint32_t cpu_id)
|
||||
{
|
||||
// 可以存储在CP0_EBase或其他位置
|
||||
cpu->CP0_EBase = (cpu->CP0_EBase & 0x3FF) | (cpu_id << 10);
|
||||
}
|
||||
|
||||
EXC_VOID_1(tlib_set_cpu_id, uint32_t, cpu_id)
|
||||
|
||||
// 设置龙芯处理器ID
|
||||
void tlib_set_loongson_cpu_id(uint32_t cpu_id)
|
||||
{
|
||||
// 设置CP0_PRId寄存器
|
||||
cpu->CP0_PRId = cpu_id;
|
||||
}
|
||||
|
||||
EXC_VOID_1(tlib_set_loongson_cpu_id, uint32_t, cpu_id)
|
||||
|
||||
// 清除WFI状态
|
||||
void tlib_clear_wfi()
|
||||
{
|
||||
cpu->wfi = 0;
|
||||
}
|
||||
|
||||
EXC_VOID_0(tlib_clear_wfi)
|
||||
|
||||
// 设置WFI状态
|
||||
void tlib_set_wfi()
|
||||
{
|
||||
cpu->wfi = 1;
|
||||
}
|
||||
|
||||
EXC_VOID_0(tlib_set_wfi)
|
||||
@@ -0,0 +1,24 @@
|
||||
*
|
||||
* MIPS interface functions.
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// MIPS架构特定的导出函数声明
|
||||
// 这些函数会被C#层调用
|
||||
|
||||
// 设置CPU入口点(PC)
|
||||
void tlib_set_entry_point(uint32_t entry_point);
|
||||
|
||||
// 设置CPU ID(用于多核系统)
|
||||
void tlib_set_cpu_id(uint32_t cpu_id);
|
||||
|
||||
// 龙芯1E300特定:设置处理器ID
|
||||
void tlib_set_loongson_cpu_id(uint32_t cpu_id);
|
||||
|
||||
// WFI (Wait For Interrupt) 控制
|
||||
void tlib_clear_wfi(void);
|
||||
void tlib_set_wfi(void);
|
||||
222
src/Infrastructure/src/Emulator/Cores/tlib/arch/mips/cpu.h
Normal file
222
src/Infrastructure/src/Emulator/Cores/tlib/arch/mips/cpu.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* MIPS
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// MIPS32架构支持 - 最小框架实现
|
||||
// 基于SPARC架构改编,用于龙芯1E300等MIPS32处理器
|
||||
|
||||
#if (TARGET_LONG_BITS == 32)
|
||||
#ifdef TARGET_PHYS_ADDR_BITS
|
||||
#undef TARGET_PHYS_ADDR_BITS
|
||||
#endif
|
||||
#define TARGET_PHYS_ADDR_BITS 32
|
||||
#else
|
||||
#error "Only 32-bit MIPS target is currently supported."
|
||||
#endif
|
||||
|
||||
#define TARGET_FPREGS 32
|
||||
#define TARGET_PAGE_BITS 12 /* 4k */
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 32
|
||||
|
||||
#include "cpu_registers.h"
|
||||
#include "cpu-defs.h"
|
||||
#include "softfloat-2.h"
|
||||
|
||||
#define SUPPORTS_GUEST_PROFILING
|
||||
|
||||
// MIPS异常代码
|
||||
#define EXCP_NONE -1
|
||||
#define EXCP_RESET 0
|
||||
#define EXCP_TLBMOD 1 // TLB modification exception
|
||||
#define EXCP_TLBL 2 // TLB exception (load or instruction fetch)
|
||||
#define EXCP_TLBS 3 // TLB exception (store)
|
||||
#define EXCP_AdEL 4 // Address error exception (load or instruction fetch)
|
||||
#define EXCP_AdES 5 // Address error exception (store)
|
||||
#define EXCP_IBE 6 // Bus error exception (instruction fetch)
|
||||
#define EXCP_DBE 7 // Bus error exception (data reference: load or store)
|
||||
#define EXCP_SYSCALL 8 // Syscall exception
|
||||
#define EXCP_BREAK 9 // Breakpoint exception
|
||||
#define EXCP_RI 10 // Reserved instruction exception
|
||||
#define EXCP_CpU 11 // Coprocessor Unusable exception
|
||||
#define EXCP_OVERFLOW 12 // Arithmetic overflow exception
|
||||
#define EXCP_TRAP 13 // Trap exception
|
||||
#define EXCP_FPE 15 // Floating point exception
|
||||
#define EXCP_C2E 18 // Coprocessor 2 exception
|
||||
#define EXCP_DWATCH 23 // Data watchpoint
|
||||
#define EXCP_CACHE 30 // Cache error
|
||||
|
||||
// CP0 Status寄存器位定义
|
||||
#define CP0_STATUS_IE (1 << 0) // Interrupt Enable
|
||||
#define CP0_STATUS_EXL (1 << 1) // Exception Level
|
||||
#define CP0_STATUS_ERL (1 << 2) // Error Level
|
||||
#define CP0_STATUS_KSU (3 << 3) // Operating mode (Kernel/Supervisor/User)
|
||||
#define CP0_STATUS_IM (0xFF << 8) // Interrupt Mask
|
||||
#define CP0_STATUS_BEV (1 << 22) // Bootstrap Exception Vector
|
||||
#define CP0_STATUS_CU0 (1 << 28) // Coprocessor 0 Usable
|
||||
#define CP0_STATUS_CU1 (1 << 29) // Coprocessor 1 (FPU) Usable
|
||||
|
||||
// CP0 Cause寄存器位定义
|
||||
#define CP0_CAUSE_EXCCODE_SHIFT 2
|
||||
#define CP0_CAUSE_EXCCODE_MASK (0x1F << CP0_CAUSE_EXCCODE_SHIFT)
|
||||
#define CP0_CAUSE_IP (0xFF << 8) // Interrupt Pending
|
||||
#define CP0_CAUSE_BD (1 << 31) // Branch Delay
|
||||
|
||||
// MMU模式数量(用户态和内核态)
|
||||
#define NB_MMU_MODES 2
|
||||
|
||||
// MIPS CPU状态结构体
|
||||
// 注意:必须使用CPUState作为结构体名(Renode框架要求)
|
||||
typedef struct CPUState {
|
||||
// 通用寄存器 (GPR 0-31)
|
||||
// 注意: $0 (zero) 总是硬连线为0
|
||||
target_ulong gpr[32];
|
||||
|
||||
// 程序计数器(注意:必须使用小写pc,cpu-common.h中的CPU_PC宏依赖此命名)
|
||||
target_ulong pc;
|
||||
|
||||
// HI/LO寄存器(用于乘法和除法)
|
||||
target_ulong HI;
|
||||
target_ulong LO;
|
||||
|
||||
// CP0 - 协处理器0(系统控制寄存器)
|
||||
target_ulong CP0_Index; // TLB Index
|
||||
target_ulong CP0_Random; // TLB Random
|
||||
target_ulong CP0_EntryLo0; // TLB EntryLo0
|
||||
target_ulong CP0_EntryLo1; // TLB EntryLo1
|
||||
target_ulong CP0_Context; // TLB Context
|
||||
target_ulong CP0_PageMask; // TLB PageMask
|
||||
target_ulong CP0_Wired; // TLB Wired
|
||||
target_ulong CP0_BadVAddr; // Bad Virtual Address
|
||||
target_ulong CP0_Count; // Timer Count
|
||||
target_ulong CP0_EntryHi; // TLB EntryHi
|
||||
target_ulong CP0_Compare; // Timer Compare
|
||||
target_ulong CP0_Status; // Status Register
|
||||
target_ulong CP0_Cause; // Cause Register
|
||||
target_ulong CP0_EPC; // Exception Program Counter
|
||||
target_ulong CP0_PRId; // Processor Revision Identifier
|
||||
target_ulong CP0_Config0; // Config0
|
||||
target_ulong CP0_Config1; // Config1
|
||||
target_ulong CP0_EBase; // Exception Base
|
||||
|
||||
// 龙芯1E300特定寄存器(预留空间)
|
||||
target_ulong loongson_custom[8];
|
||||
|
||||
// FPU状态(CP1 - 浮点协处理器)
|
||||
float_status fp_status;
|
||||
float64 fpr[32]; // FPU寄存器(可以是32个32位或16个64位)
|
||||
uint32_t fcr0; // FPU Implementation/Revision register
|
||||
uint32_t fcr31; // FPU Control/Status register
|
||||
|
||||
// 内部状态和标志
|
||||
uint32_t hflags; // 内部CPU标志
|
||||
int error_code;
|
||||
uint32_t btarget; // 分支目标地址(用于延迟槽处理)
|
||||
|
||||
// 通用CPU字段(由Renode框架定义)
|
||||
CPU_COMMON
|
||||
} CPUState;
|
||||
|
||||
// CPU特性定义(简化版本)
|
||||
typedef struct mips_def_t {
|
||||
const char *name;
|
||||
uint32_t CP0_PRId;
|
||||
uint32_t CP0_Config0;
|
||||
uint32_t CP0_Config1;
|
||||
uint32_t features;
|
||||
} mips_def_t;
|
||||
|
||||
// CPU特性标志
|
||||
#define MIPS_FEATURE_FPU (1 << 0)
|
||||
#define MIPS_FEATURE_MIPS32 (1 << 1)
|
||||
#define MIPS_FEATURE_MIPS64 (1 << 2)
|
||||
|
||||
// hflags标志位定义
|
||||
#define MIPS_HFLAG_MODE 0x00007 // 执行模式掩码
|
||||
#define MIPS_HFLAG_KM 0 // Kernel mode
|
||||
#define MIPS_HFLAG_SM 1 // Supervisor mode
|
||||
#define MIPS_HFLAG_UM 2 // User mode
|
||||
|
||||
// 分支延迟槽处理
|
||||
#define MIPS_HFLAG_BMASK 0x00078 // 分支掩码
|
||||
#define MIPS_HFLAG_B 0x00008 // 无条件分支
|
||||
#define MIPS_HFLAG_BC 0x00010 // 条件分支
|
||||
#define MIPS_HFLAG_BL 0x00020 // Likely分支
|
||||
// 分支延迟槽处理
|
||||
#define MIPS_HFLAG_BMASK 0x00078 // 分支掩码
|
||||
#define MIPS_HFLAG_B 0x00008 // 无条件分支
|
||||
#define MIPS_HFLAG_BC 0x00010 // 条件分支
|
||||
#define MIPS_HFLAG_BL 0x00020 // Likely分支
|
||||
#define MIPS_HFLAG_BR 0x00040 // 分支到寄存器
|
||||
|
||||
// DisasContext完整定义(必须在include之前)
|
||||
typedef struct DisasContext {
|
||||
DisasContextBase base;
|
||||
uint32_t opcode;
|
||||
int mem_idx;
|
||||
} DisasContext;
|
||||
|
||||
// 设置寄存器$0总是为0
|
||||
static inline void sync_zero_reg(CPUState *env)
|
||||
{
|
||||
env->gpr[0] = 0;
|
||||
}
|
||||
|
||||
// 辅助函数声明 - 必须放在CPUState定义之后,include之前
|
||||
static inline int cpu_mmu_index(CPUState *env)
|
||||
{
|
||||
// 简化版本:只区分内核态和用户态
|
||||
return (env->CP0_Status & CP0_STATUS_EXL) ? 0 : 1;
|
||||
}
|
||||
|
||||
// 获取当前执行模式
|
||||
static inline int mips_cpu_mode(CPUState *env)
|
||||
{
|
||||
if (env->CP0_Status & CP0_STATUS_EXL) {
|
||||
return MIPS_HFLAG_KM; // Exception level = kernel mode
|
||||
}
|
||||
if (env->CP0_Status & CP0_STATUS_ERL) {
|
||||
return MIPS_HFLAG_KM; // Error level = kernel mode
|
||||
}
|
||||
return (env->hflags & MIPS_HFLAG_MODE);
|
||||
}
|
||||
|
||||
// 检查中断使能
|
||||
static inline int mips_interrupts_enabled(CPUState *env)
|
||||
{
|
||||
return (env->CP0_Status & CP0_STATUS_IE) &&
|
||||
!(env->CP0_Status & CP0_STATUS_EXL) &&
|
||||
!(env->CP0_Status & CP0_STATUS_ERL);
|
||||
}
|
||||
|
||||
// 函数声明(在helper.c中实现)
|
||||
int cpu_handle_mmu_fault(CPUState *env, target_ulong address, int access_type,
|
||||
int mmu_idx, int is_softmmu, int no_page_fault, target_phys_addr_t *paddr);
|
||||
|
||||
#include "cpu-all.h"
|
||||
#include "exec-all.h"
|
||||
|
||||
// TB状态获取函数(必需)
|
||||
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
{
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = env->hflags;
|
||||
}
|
||||
|
||||
// 必需的CPU接口函数
|
||||
static inline int cpu_has_work(CPUState *env)
|
||||
{
|
||||
return (env->interrupt_request & CPU_INTERRUPT_HARD);
|
||||
}
|
||||
|
||||
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
|
||||
{
|
||||
env->pc = tb->pc;
|
||||
}
|
||||
|
||||
// MIPS寄存器别名(用于TCG)
|
||||
#define RA 31 // 返回地址寄存器
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* MIPS寄存器接口
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "cpu_registers.h"
|
||||
|
||||
// 获取寄存器指针(32位版本)
|
||||
uint32_t *get_reg_pointer_32(int reg)
|
||||
{
|
||||
switch(reg) {
|
||||
case MIPS_REG_ZERO ... MIPS_REG_RA: // GPR 0-31
|
||||
return (uint32_t *)&(cpu->gpr[reg]);
|
||||
case MIPS_REG_PC:
|
||||
return (uint32_t *)&(cpu->pc);
|
||||
case MIPS_REG_HI:
|
||||
return (uint32_t *)&(cpu->HI);
|
||||
case MIPS_REG_LO:
|
||||
return (uint32_t *)&(cpu->LO);
|
||||
case MIPS_CP0_STATUS:
|
||||
return (uint32_t *)&(cpu->CP0_Status);
|
||||
case MIPS_CP0_CAUSE:
|
||||
return (uint32_t *)&(cpu->CP0_Cause);
|
||||
case MIPS_CP0_EPC:
|
||||
return (uint32_t *)&(cpu->CP0_EPC);
|
||||
case MIPS_CP0_BADVADDR:
|
||||
return (uint32_t *)&(cpu->CP0_BadVAddr);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// 生成寄存器访问函数(tlib_get_register_value_32 和 tlib_set_register_value_32)
|
||||
CPU_REGISTER_ACCESSOR(32)
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* MIPS寄存器接口
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// MIPS32寄存器枚举定义
|
||||
// 用于C#和C代码之间的寄存器访问
|
||||
|
||||
// MIPS寄存器枚举
|
||||
// 这些值将被导出到C#层用于寄存器访问
|
||||
typedef enum {
|
||||
// 通用寄存器 GPR 0-31
|
||||
MIPS_REG_ZERO = 0, // $0 - 常量0
|
||||
MIPS_REG_AT, // $1 - 汇编器临时寄存器
|
||||
MIPS_REG_V0, // $2 - 函数返回值
|
||||
MIPS_REG_V1, // $3 - 函数返回值
|
||||
MIPS_REG_A0, // $4 - 函数参数
|
||||
MIPS_REG_A1, // $5 - 函数参数
|
||||
MIPS_REG_A2, // $6 - 函数参数
|
||||
MIPS_REG_A3, // $7 - 函数参数
|
||||
MIPS_REG_T0, // $8 - 临时寄存器
|
||||
MIPS_REG_T1, // $9
|
||||
MIPS_REG_T2, // $10
|
||||
MIPS_REG_T3, // $11
|
||||
MIPS_REG_T4, // $12
|
||||
MIPS_REG_T5, // $13
|
||||
MIPS_REG_T6, // $14
|
||||
MIPS_REG_T7, // $15
|
||||
MIPS_REG_S0, // $16 - 保存寄存器
|
||||
MIPS_REG_S1, // $17
|
||||
MIPS_REG_S2, // $18
|
||||
MIPS_REG_S3, // $19
|
||||
MIPS_REG_S4, // $20
|
||||
MIPS_REG_S5, // $21
|
||||
MIPS_REG_S6, // $22
|
||||
MIPS_REG_S7, // $23
|
||||
MIPS_REG_T8, // $24 - 临时寄存器
|
||||
MIPS_REG_T9, // $25
|
||||
MIPS_REG_K0, // $26 - 内核保留寄存器
|
||||
MIPS_REG_K1, // $27
|
||||
MIPS_REG_GP, // $28 - 全局指针
|
||||
MIPS_REG_SP, // $29 - 栈指针
|
||||
MIPS_REG_FP, // $30 - 帧指针 (或 S8)
|
||||
MIPS_REG_RA, // $31 - 返回地址
|
||||
|
||||
// 特殊寄存器 (从32开始)
|
||||
MIPS_REG_PC = 32, // 程序计数器
|
||||
MIPS_REG_HI, // HI寄存器 (乘除法高位)
|
||||
MIPS_REG_LO, // LO寄存器 (乘除法低位)
|
||||
|
||||
// CP0寄存器 (从40开始,为了对齐)
|
||||
MIPS_CP0_INDEX = 40, // CP0 Register 0
|
||||
MIPS_CP0_RANDOM, // CP0 Register 1
|
||||
MIPS_CP0_ENTRYLO0, // CP0 Register 2
|
||||
MIPS_CP0_ENTRYLO1, // CP0 Register 3
|
||||
MIPS_CP0_CONTEXT, // CP0 Register 4
|
||||
MIPS_CP0_PAGEMASK, // CP0 Register 5
|
||||
MIPS_CP0_WIRED, // CP0 Register 6
|
||||
// Register 7 reserved
|
||||
MIPS_CP0_BADVADDR = 48, // CP0 Register 8
|
||||
MIPS_CP0_COUNT, // CP0 Register 9
|
||||
MIPS_CP0_ENTRYHI, // CP0 Register 10
|
||||
MIPS_CP0_COMPARE, // CP0 Register 11
|
||||
MIPS_CP0_STATUS, // CP0 Register 12
|
||||
MIPS_CP0_CAUSE, // CP0 Register 13
|
||||
MIPS_CP0_EPC, // CP0 Register 14
|
||||
MIPS_CP0_PRID, // CP0 Register 15
|
||||
MIPS_CP0_CONFIG0, // CP0 Register 16, Select 0
|
||||
MIPS_CP0_CONFIG1, // CP0 Register 16, Select 1
|
||||
// ... 更多CONFIG寄存器
|
||||
MIPS_CP0_EBASE = 63, // CP0 Register 15, Select 1
|
||||
|
||||
// FPU控制寄存器 (从64开始)
|
||||
MIPS_FCR0 = 64, // FPU Implementation/Revision
|
||||
MIPS_FCR31 = 95, // FPU Control/Status
|
||||
|
||||
// FPU通用寄存器 (从96开始)
|
||||
MIPS_FPR0 = 96,
|
||||
MIPS_FPR1,
|
||||
MIPS_FPR2,
|
||||
MIPS_FPR3,
|
||||
MIPS_FPR4,
|
||||
MIPS_FPR5,
|
||||
MIPS_FPR6,
|
||||
MIPS_FPR7,
|
||||
MIPS_FPR8,
|
||||
MIPS_FPR9,
|
||||
MIPS_FPR10,
|
||||
MIPS_FPR11,
|
||||
MIPS_FPR12,
|
||||
MIPS_FPR13,
|
||||
MIPS_FPR14,
|
||||
MIPS_FPR15,
|
||||
MIPS_FPR16,
|
||||
MIPS_FPR17,
|
||||
MIPS_FPR18,
|
||||
MIPS_FPR19,
|
||||
MIPS_FPR20,
|
||||
MIPS_FPR21,
|
||||
MIPS_FPR22,
|
||||
MIPS_FPR23,
|
||||
MIPS_FPR24,
|
||||
MIPS_FPR25,
|
||||
MIPS_FPR26,
|
||||
MIPS_FPR27,
|
||||
MIPS_FPR28,
|
||||
MIPS_FPR29,
|
||||
MIPS_FPR30,
|
||||
MIPS_FPR31,
|
||||
|
||||
// 寄存器总数
|
||||
MIPS_REGISTERS_COUNT
|
||||
} MIPSRegister;
|
||||
|
||||
// 辅助宏:检查寄存器是否为GPR
|
||||
#define IS_GPR(reg) ((reg) >= MIPS_REG_ZERO && (reg) <= MIPS_REG_RA)
|
||||
|
||||
// 辅助宏:检查寄存器是否为CP0
|
||||
#define IS_CP0(reg) ((reg) >= MIPS_CP0_INDEX && (reg) <= MIPS_CP0_EBASE)
|
||||
|
||||
// 辅助宏:检查寄存器是否为FPR
|
||||
#define IS_FPR(reg) ((reg) >= MIPS_FPR0 && (reg) <= MIPS_FPR31)
|
||||
132
src/Infrastructure/src/Emulator/Cores/tlib/arch/mips/helper.c
Normal file
132
src/Infrastructure/src/Emulator/Cores/tlib/arch/mips/helper.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* MIPS
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
#include "cpu.h"
|
||||
|
||||
// MIPS Helper函数实现
|
||||
|
||||
// CPU初始化
|
||||
void cpu_reset(CPUState *env)
|
||||
{
|
||||
int i;
|
||||
|
||||
// 清零所有通用寄存器
|
||||
for (i = 0; i < 32; i++) {
|
||||
env->gpr[i] = 0;
|
||||
}
|
||||
|
||||
// 初始化PC到复位向量
|
||||
env->pc = 0xBFC00000; // MIPS复位向量地址
|
||||
|
||||
// 初始化HI/LO
|
||||
env->HI = 0;
|
||||
env->LO = 0;
|
||||
|
||||
// 初始化CP0寄存器
|
||||
env->CP0_Status = CP0_STATUS_BEV | CP0_STATUS_ERL; // Bootstrap向量启用,Error Level
|
||||
env->CP0_Cause = 0;
|
||||
env->CP0_EPC = 0;
|
||||
env->CP0_PRId = 0x00006302; // 示例处理器ID(需要根据龙芯1E300实际值修改)
|
||||
env->CP0_Config0 = 0x80000000; // 基本配置
|
||||
env->CP0_Config1 = 0;
|
||||
env->CP0_Random = 0x0000001f;
|
||||
env->CP0_Wired = 0;
|
||||
env->CP0_Count = 0;
|
||||
env->CP0_Compare = 0;
|
||||
|
||||
// 初始化内部状态
|
||||
env->hflags = MIPS_HFLAG_KM; // Kernel mode
|
||||
env->error_code = 0;
|
||||
|
||||
// 清除中断
|
||||
env->interrupt_request = 0;
|
||||
}
|
||||
|
||||
// 计算MMU索引
|
||||
int cpu_mips_mmu_index(CPUState *env)
|
||||
{
|
||||
return cpu_mmu_index(env);
|
||||
}
|
||||
|
||||
// CPU初始化函数(必需)
|
||||
int cpu_init(const char *cpu_model)
|
||||
{
|
||||
cpu_reset(cpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 架构清理函数(必需)
|
||||
void tlib_arch_dispose()
|
||||
{
|
||||
// 最小实现:无需特殊清理
|
||||
}
|
||||
|
||||
// 内存事务状态获取(必需)
|
||||
uint64_t cpu_get_state_for_memory_transaction(CPUState *env, target_ulong addr, int access_type)
|
||||
{
|
||||
return 0; // 最小实现
|
||||
}
|
||||
|
||||
// MMU故障处理(简化版)
|
||||
int cpu_handle_mmu_fault(CPUState *env, target_ulong address, int access_type,
|
||||
int mmu_idx, int is_softmmu, int no_page_fault, target_phys_addr_t *paddr)
|
||||
{
|
||||
// 最小实现:直接映射物理地址
|
||||
*paddr = address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取物理页面用于调试(必需)
|
||||
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||
{
|
||||
// 最小实现:直接映射
|
||||
return addr;
|
||||
}
|
||||
|
||||
// 中断处理(必需)
|
||||
void do_interrupt(CPUState *env)
|
||||
{
|
||||
// 最小实现:基本异常处理
|
||||
int cause = env->exception_index;
|
||||
|
||||
// 保存PC到EPC
|
||||
env->CP0_EPC = env->pc;
|
||||
|
||||
// 设置Cause寄存器
|
||||
env->CP0_Cause = (env->CP0_Cause & ~CP0_CAUSE_EXCCODE_MASK) |
|
||||
(cause << CP0_CAUSE_EXCCODE_SHIFT);
|
||||
|
||||
// 进入异常级别
|
||||
env->CP0_Status |= CP0_STATUS_EXL;
|
||||
|
||||
// 跳转到异常向量
|
||||
if (env->CP0_Status & CP0_STATUS_BEV) {
|
||||
env->pc = 0xBFC00380; // Bootstrap exception vector
|
||||
} else {
|
||||
env->pc = 0x80000180; // Normal exception vector
|
||||
}
|
||||
}
|
||||
|
||||
// 中断处理前检查(必需)
|
||||
int process_interrupt(int interrupt_request, CPUState *env)
|
||||
{
|
||||
if ((interrupt_request & CPU_INTERRUPT_HARD) && mips_interrupts_enabled(env)) {
|
||||
env->exception_index = EXCP_SYSCALL; // 简化版本
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CPU执行前序(必需)
|
||||
void cpu_exec_prologue(CPUState *env)
|
||||
{
|
||||
// 最小实现
|
||||
}
|
||||
|
||||
// CPU执行后序(必需)
|
||||
void cpu_exec_epilogue(CPUState *env)
|
||||
{
|
||||
// 最小实现
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* MIPS
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
|
||||
#include "def-helper.h"
|
||||
|
||||
/* Exceptions */
|
||||
DEF_HELPER_2(raise_exception, void, env, i32)
|
||||
|
||||
#include "def-helper.h"
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIPS
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
#include "cpu.h"
|
||||
#include "helper.h"
|
||||
|
||||
// MIPS操作辅助函数实现
|
||||
|
||||
// 触发异常
|
||||
void HELPER(raise_exception)(CPUState *env, uint32_t exception)
|
||||
{
|
||||
env->exception_index = exception;
|
||||
cpu_loop_exit(env);
|
||||
}
|
||||
|
||||
// TLB填充函数(必需)
|
||||
int arch_tlb_fill(CPUState *env, target_ulong addr, int access_type, int mmu_idx, void *retaddr, int no_page_fault,
|
||||
int access_width, target_phys_addr_t *paddr)
|
||||
{
|
||||
return cpu_handle_mmu_fault(env, addr, access_type, mmu_idx, 1, no_page_fault, paddr);
|
||||
}
|
||||
|
||||
// MMU故障异常触发(必需)
|
||||
void arch_raise_mmu_fault_exception(CPUState *env, int errcode, int access_type, target_ulong address, void *retaddr)
|
||||
{
|
||||
cpu_restore_state(env, retaddr);
|
||||
cpu_loop_exit(env);
|
||||
}
|
||||
|
||||
// 生成softmmu访问函数(__ldb_mmu, __ldl_mmu, __stb_mmu等)
|
||||
#define MMUSUFFIX _mmu
|
||||
|
||||
#define SHIFT 0
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 1
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 2
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 3
|
||||
#include "softmmu_template.h"
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* MIPS
|
||||
* Author:liuwb
|
||||
* Date:2026_0209
|
||||
*/
|
||||
|
||||
/* MIPS translation - Minimal implementation */
|
||||
/*
|
||||
modify history:
|
||||
2026_0210 wangsx:add translate
|
||||
1.整数(ALU) (I/R型)
|
||||
addiu(加立即数(不触发溢出异常))/addi(加立即数(有溢出异常))
|
||||
addu寄存器加(不触发溢出异常)/add寄存器加(有溢出异常)
|
||||
subu寄存器减(不触发溢出异常)/sub寄存器减(有溢出异常)
|
||||
and/andi 按位与
|
||||
or/ori 按位或 (立即数零扩展)
|
||||
xor/xori 按位异或 (立即数零扩展)
|
||||
nor 按位或非
|
||||
slt(小于则置 1(有符号比较))/sltu 小于则置 1(无符号比较)
|
||||
slti/sltiu 与立即数比较,小于则置 1 (slti 按有符号,sltiu 按无符号。)
|
||||
2.移位
|
||||
sll (逻辑左移)
|
||||
srl (逻辑右移)
|
||||
sra (算术右移)
|
||||
sllv (变量逻辑左移)
|
||||
srlv (变量逻辑右移)
|
||||
srav (变量算术右移)
|
||||
3.Load/Store(先做对齐访问,后补不对齐)
|
||||
**32 位字(word)**
|
||||
lw _加载字_(Load Word)
|
||||
sw _存储字_(Store Word)
|
||||
**8 位字节(byte)**
|
||||
lb _加载字节(符号扩展)_ 读 1 字节,扩展到 32 位时 **保留符号**(0x80 会扩展成负数)。
|
||||
lbu _加载字节(零扩展)_ 读 1 字节,扩展到 32 位时 **高位补 0**。
|
||||
sb _存储字节_ 读 1 字节,扩展到 32 位时 **高位补 0**。
|
||||
**16 位半字(halfword)**
|
||||
lh _加载半字(符号扩展)_
|
||||
lhu _加载半字(零扩展)_
|
||||
sh _存储半字_
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
#include "tcg-op.h"
|
||||
|
||||
void translate_init(void)
|
||||
{
|
||||
// 最小实现
|
||||
}
|
||||
|
||||
int gen_intermediate_code(CPUState *env, DisasContextBase *dcbase)
|
||||
{
|
||||
// 最小实现:只生成一个退出指令
|
||||
dcbase->tb->size = 4;
|
||||
dcbase->tb->icount = 1;
|
||||
tcg_gen_exit_tb(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t gen_intermediate_code_epilogue(CPUState *env, DisasContextBase *dcbase)
|
||||
{
|
||||
return dcbase->tb->size;
|
||||
}
|
||||
|
||||
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, target_ulong *data)
|
||||
{
|
||||
env->pc = data[0];
|
||||
}
|
||||
|
||||
// 设置反汇编上下文(必需)
|
||||
void setup_disas_context(DisasContextBase *dcbase, CPUState *env)
|
||||
{
|
||||
DisasContext *ctx = (DisasContext *)dcbase;
|
||||
ctx->mem_idx = cpu_mmu_index(env);
|
||||
}
|
||||
|
||||
// 生成断点指令(必需)
|
||||
int gen_breakpoint(DisasContextBase *dcbase, CPUBreakpoint *bp)
|
||||
{
|
||||
tcg_gen_exit_tb(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 同步PC(必需)
|
||||
void gen_sync_pc(DisasContext *dc)
|
||||
{
|
||||
// 最小实现
|
||||
}
|
||||
Reference in New Issue
Block a user