diff --git a/.github/workflows/check_format.yml b/.github/workflows/check_format.yml new file mode 100644 index 0000000..82d7126 --- /dev/null +++ b/.github/workflows/check_format.yml @@ -0,0 +1,59 @@ +name: Check for format changes + +# Build on every branch push, tag push, and pull request change: +on: [push, pull_request] + +jobs: + check_format: + name: Check format + runs-on: ubuntu-latest + + steps: + - name: Checkout reposistory + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + + - name: Install dependencies + run: sudo apt install clang-format-11 + + - name: make format + run: make -j $(nproc) format + + - name: Check if there are format changes + id: format_changes + uses: tj-actions/verify-changed-files@v14 + + - name: format changes + if: steps.format_changes.outputs.files_changed == 'true' + run: | + echo "Changed files: ${{ steps.format_changes.outputs.changed_files }}" + echo "Please run \`make format\` and commit the result" + exit 1 + + check_tidy: + name: Check tidy + runs-on: ubuntu-latest + + steps: + - name: Checkout reposistory + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + + - name: Install dependencies + run: sudo apt install clang-tidy-11 + + - name: make tidy + run: make -j $(nproc) tidy + + - name: Check if there are tidy changes + id: tidy_changes + uses: tj-actions/verify-changed-files@v14 + + - name: tidy changes + if: steps.tidy_changes.outputs.files_changed == 'true' + run: | + echo "Changed files: ${{ steps.tidy_changes.outputs.changed_files }}" + echo "Please run \`make tidy\` and commit the result" + exit 1 diff --git a/.github/workflows/check_tables.yml b/.github/workflows/check_tables.yml new file mode 100644 index 0000000..2958660 --- /dev/null +++ b/.github/workflows/check_tables.yml @@ -0,0 +1,59 @@ +name: Check for ungenerated tables + +# Build on every branch push, tag push, and pull request change: +on: [push, pull_request] + +jobs: + check_tables: + name: Check tables + runs-on: ubuntu-latest + + steps: + - name: Checkout reposistory + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + + - name: clean everything + run: make -j $(nproc) distclean + + - name: make tables + run: make -j $(nproc) tables + + - name: Check if there are tables changes + id: tables_changes + uses: tj-actions/verify-changed-files@v14 + + - name: tables changes + if: steps.tables_changes.outputs.files_changed == 'true' + run: | + echo "Changed files: ${{ steps.tables_changes.outputs.changed_files }}" + echo "Please run \`make distclean && make tables\` and commit the result" + exit 1 + + check_rust_tables: + name: Check Rust tables + runs-on: ubuntu-latest + + steps: + - name: Checkout reposistory + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + + - name: clean everything + run: make -j $(nproc) -C rust distclean + + - name: make Rust tables + run: make -j $(nproc) -C rust tables + + - name: Check if there are Rust tables changes + id: rust_tables_changes + uses: tj-actions/verify-changed-files@v14 + + - name: Rust tables changes + if: steps.rust_tables_changes.outputs.files_changed == 'true' + run: | + echo "Changed files: ${{ steps.rust_tables_changes.outputs.changed_files }}" + echo "Please run \`make -C rust distclean && make -C rust tables\` and commit the result" + exit 1 diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml index 4903846..3f70c96 100644 --- a/.github/workflows/make.yml +++ b/.github/workflows/make.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: build_repo: - name: Build repo + name: Build repo and run tests runs-on: ubuntu-latest steps: diff --git a/.github/workflows/publish_crate.yml b/.github/workflows/publish_crate.yml index 06c5de8..d57ff40 100644 --- a/.github/workflows/publish_crate.yml +++ b/.github/workflows/publish_crate.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: build_rust: - name: Build rust stuff + name: Build Rust stuff and run Rust tests runs-on: ubuntu-latest steps: diff --git a/.github/workflows/ci.yml b/.github/workflows/pypi_upload.yml similarity index 79% rename from .github/workflows/ci.yml rename to .github/workflows/pypi_upload.yml index d58816d..7a7ac31 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/pypi_upload.yml @@ -1,7 +1,11 @@ name: Build and upload to PyPI -# Build on every branch push, tag push, and pull request change: -on: [push, pull_request] +# Only run on releases +on: + push: + # Pattern matched against refs/tags + tags: + - '**' # Push events to every tag including hierarchical tags like v1.0/beta jobs: build_wheels: @@ -12,10 +16,10 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build wheels - uses: pypa/cibuildwheel@v2.12.1 + uses: pypa/cibuildwheel@v2.12.3 env: CIBW_ARCHS_WINDOWS: "auto" CIBW_ARCHS_LINUX: "auto" @@ -29,7 +33,7 @@ jobs: name: Build source distribution runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build sdist run: pipx run build --sdist diff --git a/Cargo.toml b/Cargo.toml index bb1e71f..ee3556e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "rabbitizer" # Version should be synced with include/common/RabbitizerVersion.h -version = "1.6.2" +version = "1.7.0" edition = "2021" authors = ["Anghelo Carvajal "] description = "MIPS instruction decoder" diff --git a/Makefile b/Makefile index f2eeed7..7b053ab 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,8 @@ all: static tests static: $(STATIC_LIB) $(STATIC_LIB_XX) dynamic: $(DYNAMIC_LIB) $(DYNAMIC_LIB_XX) +tables: $(TABLE_GENERATED) + clean: $(RM) -rf build @@ -123,7 +125,7 @@ tidy: tests: $(TESTS_ELFS) -.PHONY: all clean distclean format tidy tests +.PHONY: all static dynamic tables clean distclean format tidy tests .DEFAULT_GOAL := all .SECONDARY: diff --git a/cplusplus/include/instructions/InstructionR3000GTE.hpp b/cplusplus/include/instructions/InstructionR3000GTE.hpp new file mode 100644 index 0000000..7637e3d --- /dev/null +++ b/cplusplus/include/instructions/InstructionR3000GTE.hpp @@ -0,0 +1,28 @@ +/* SPDX-FileCopyrightText: © 2023 Decompollaborate */ +/* SPDX-License-Identifier: MIT */ + +#ifndef RABBITIZER_INSTRUCTION_R3000GTE_HPP +#define RABBITIZER_INSTRUCTION_R3000GTE_HPP +#pragma once + +#include "InstructionBase.hpp" + + +namespace rabbitizer { + class InstructionR3000GTE : public InstructionBase { + public: + InstructionR3000GTE(uint32_t word, uint32_t vram); + virtual ~InstructionR3000GTE(); + + uint8_t GetR3000GTE_fakeOpcode() const; + + uint8_t GetR3000GTE_sf() const; + uint8_t GetR3000GTE_mx() const; + uint8_t GetR3000GTE_v() const; + uint8_t GetR3000GTE_cv() const; + uint8_t GetR3000GTE_lm() const; + }; +}; + + +#endif diff --git a/cplusplus/include/rabbitizer.hpp b/cplusplus/include/rabbitizer.hpp index 332101e..ccb34d7 100644 --- a/cplusplus/include/rabbitizer.hpp +++ b/cplusplus/include/rabbitizer.hpp @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: © 2022 Decompollaborate */ +/* SPDX-FileCopyrightText: © 2022-2023 Decompollaborate */ /* SPDX-License-Identifier: MIT */ #ifndef RABBITIZER_HPP @@ -17,6 +17,7 @@ #include "instructions/InstructionBase.hpp" #include "instructions/InstructionCpu.hpp" #include "instructions/InstructionRsp.hpp" +#include "instructions/InstructionR3000GTE.hpp" #include "instructions/InstructionR5900.hpp" #include "analysis/LoPairingInfo.hpp" diff --git a/cplusplus/src/instructions/InstructionR3000GTE.cpp b/cplusplus/src/instructions/InstructionR3000GTE.cpp new file mode 100644 index 0000000..25f6985 --- /dev/null +++ b/cplusplus/src/instructions/InstructionR3000GTE.cpp @@ -0,0 +1,38 @@ +/* SPDX-FileCopyrightText: © 2023 Decompollaborate */ +/* SPDX-License-Identifier: MIT */ + +#include "instructions/InstructionR3000GTE.hpp" + +#include "instructions/RabbitizerInstructionR3000GTE.h" + +using namespace rabbitizer; + +InstructionR3000GTE::InstructionR3000GTE(uint32_t word, uint32_t vram) : InstructionBase() { + RabbitizerInstructionR3000GTE_init(&this->instr, word, vram); + RabbitizerInstructionR3000GTE_processUniqueId(&this->instr); +} + +InstructionR3000GTE::~InstructionR3000GTE() { + RabbitizerInstructionR3000GTE_destroy(&this->instr); +} + +uint8_t InstructionR3000GTE::GetR3000GTE_fakeOpcode() const { + return RAB_INSTR_R3000GTE_GET_FAKE_OPCODE(&this->instr); +} + +uint8_t InstructionR3000GTE::GetR3000GTE_sf() const { + return RAB_INSTR_R3000GTE_GET_sf(&this->instr); +} + +uint8_t InstructionR3000GTE::GetR3000GTE_mx() const { + return RAB_INSTR_R3000GTE_GET_mx(&this->instr); +} +uint8_t InstructionR3000GTE::GetR3000GTE_v() const { + return RAB_INSTR_R3000GTE_GET_v(&this->instr); +} +uint8_t InstructionR3000GTE::GetR3000GTE_cv() const { + return RAB_INSTR_R3000GTE_GET_cv(&this->instr); +} +uint8_t InstructionR3000GTE::GetR3000GTE_lm() const { + return RAB_INSTR_R3000GTE_GET_lm(&this->instr); +} diff --git a/include/common/RabbitizerVersion.h b/include/common/RabbitizerVersion.h index 0cd57eb..e5b7249 100644 --- a/include/common/RabbitizerVersion.h +++ b/include/common/RabbitizerVersion.h @@ -13,8 +13,8 @@ extern "C" { // Header version #define RAB_VERSION_MAJOR 1 -#define RAB_VERSION_MINOR 6 -#define RAB_VERSION_PATCH 2 +#define RAB_VERSION_MINOR 7 +#define RAB_VERSION_PATCH 0 #define RAB_VERSION_STR RAB_STRINGIFY(RAB_VERSION_MAJOR) "." RAB_STRINGIFY(RAB_VERSION_MINOR) "." RAB_STRINGIFY(RAB_VERSION_PATCH) diff --git a/pyproject.toml b/pyproject.toml index 57ebcf6..2338e41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ [project] name = "rabbitizer" # Version should be synced with include/common/RabbitizerVersion.h -version = "1.6.2" +version = "1.7.0" description = "MIPS instruction decoder" # license = "MIT" readme = "README.md" diff --git a/rabbitizer/enums/rabbitizer_enum_Abi.c b/rabbitizer/enums/rabbitizer_enum_Abi.c index a0d5fb0..62a61b5 100644 --- a/rabbitizer/enums/rabbitizer_enum_Abi.c +++ b/rabbitizer/enums/rabbitizer_enum_Abi.c @@ -36,8 +36,8 @@ static PyObject *rabbitizer_enum_Abi_fromStr(UNUSED PyObject *self, PyObject *ar } -#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) rabbitizer_enum_Abi_##name, METH_NOARGS, PyDoc_STR(docs) } -#define METHOD_ARGS(name, docs) { #name, (PyCFunction) rabbitizer_enum_Abi_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } +#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_Abi_##name, METH_NOARGS, PyDoc_STR(docs) } +#define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_Abi_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } static PyMethodDef rabbitizer_enum_Abi_methods[] = { METHOD_ARGS(fromStr, ""), diff --git a/rabbitizer/enums/rabbitizer_enum_InstrCategory.c b/rabbitizer/enums/rabbitizer_enum_InstrCategory.c index 4c533b0..6d555d6 100644 --- a/rabbitizer/enums/rabbitizer_enum_InstrCategory.c +++ b/rabbitizer/enums/rabbitizer_enum_InstrCategory.c @@ -38,8 +38,8 @@ static PyObject *rabbitizer_enum_InstrCategory_fromStr(UNUSED PyObject *self, Py } -#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) rabbitizer_enum_InstrCategory_##name, METH_NOARGS, PyDoc_STR(docs) } -#define METHOD_ARGS(name, docs) { #name, (PyCFunction) rabbitizer_enum_InstrCategory_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } +#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_InstrCategory_##name, METH_NOARGS, PyDoc_STR(docs) } +#define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_InstrCategory_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } static PyMethodDef rabbitizer_enum_InstrCategory_methods[] = { METHOD_ARGS(fromStr, ""), diff --git a/rabbitizer/enums/rabbitizer_type_Enum.c b/rabbitizer/enums/rabbitizer_type_Enum.c index 299fb38..fef200e 100644 --- a/rabbitizer/enums/rabbitizer_type_Enum.c +++ b/rabbitizer/enums/rabbitizer_type_Enum.c @@ -171,8 +171,8 @@ static PyObject *rabbitizer_type_Enum___reduce__(PyRabbitizerEnum *self, UNUSED } -#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction)rabbitizer_type_Enum_##name, METH_NOARGS, PyDoc_STR(docs) } -#define METHOD_ARGS(name, docs) { #name, (PyCFunction)rabbitizer_type_Enum_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } +#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_type_Enum_##name, METH_NOARGS, PyDoc_STR(docs) } +#define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_type_Enum_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } static PyMethodDef rabbitizer_type_Enum_methods[] = { diff --git a/rabbitizer/rabbitizer_submodule_Utils.c b/rabbitizer/rabbitizer_submodule_Utils.c index 31b844a..31b897f 100644 --- a/rabbitizer/rabbitizer_submodule_Utils.c +++ b/rabbitizer/rabbitizer_submodule_Utils.c @@ -50,8 +50,8 @@ static PyObject *rabbitizer_submodule_Utils_escapeString(UNUSED PyObject *self, } -#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) rabbitizer_submodule_Utils_##name, METH_NOARGS, PyDoc_STR(docs) } -#define METHOD_ARGS(name, docs) { #name, (PyCFunction) rabbitizer_submodule_Utils_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } +#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_submodule_Utils_##name, METH_NOARGS, PyDoc_STR(docs) } +#define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_submodule_Utils_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } static PyMethodDef rabbitizer_submodule_Utils_methods[] = { METHOD_ARGS(from2Complement, ""), diff --git a/rabbitizer/rabbitizer_type_Instruction.c b/rabbitizer/rabbitizer_type_Instruction.c index c7aa24e..16a5d6f 100644 --- a/rabbitizer/rabbitizer_type_Instruction.c +++ b/rabbitizer/rabbitizer_type_Instruction.c @@ -494,8 +494,8 @@ static PyObject *rabbitizer_type_Instruction___reduce__(PyRabbitizerInstruction } -#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction)rabbitizer_type_Instruction_##name, METH_NOARGS, PyDoc_STR(docs) } -#define METHOD_ARGS(name, docs) { #name, (PyCFunction)rabbitizer_type_Instruction_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } +#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_type_Instruction_##name, METH_NOARGS, PyDoc_STR(docs) } +#define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_type_Instruction_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } static PyMethodDef rabbitizer_type_Instruction_methods[] = { diff --git a/rabbitizer/rabbitizer_type_RegistersTracker.c b/rabbitizer/rabbitizer_type_RegistersTracker.c index f3aac93..7a2b6a7 100644 --- a/rabbitizer/rabbitizer_type_RegistersTracker.c +++ b/rabbitizer/rabbitizer_type_RegistersTracker.c @@ -245,8 +245,8 @@ static PyObject *rabbitizer_type_RegistersTracker_hasLoButNoHi(PyRabbitizerRegis } -#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction)rabbitizer_type_RegistersTracker_##name, METH_NOARGS, PyDoc_STR(docs) } -#define METHOD_ARGS(name, docs) { #name, (PyCFunction)rabbitizer_type_RegistersTracker_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } +#define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_type_RegistersTracker_##name, METH_NOARGS, PyDoc_STR(docs) } +#define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_type_RegistersTracker_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } static PyMethodDef rabbitizer_type_RegistersTracker_methods[] = { METHOD_ARGS(moveRegisters, ""), diff --git a/rust/Makefile b/rust/Makefile index 382033f..e72c42c 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -9,7 +9,9 @@ TABLE_GENERATED := $(TABLE_TEMPLATES:%.tablers.template=%.rs) TABLE_DEP_FILES := $(TABLE_GENERATED:%.rs=%.tablers.d) -all: $(TABLE_GENERATED) +all: tables + +tables: $(TABLE_GENERATED) clean: $(RM) -rf $(TABLE_GENERATED) @@ -17,7 +19,7 @@ clean: distclean: clean -.PHONY: all clean distclean +.PHONY: all tables clean distclean .DEFAULT_GOAL := all .SECONDARY: diff --git a/rust/src/instr_category_enum.rs b/rust/src/instr_category_enum.rs index cdaabca..2ddec0e 100644 --- a/rust/src/instr_category_enum.rs +++ b/rust/src/instr_category_enum.rs @@ -9,6 +9,7 @@ pub enum InstrCategory { CPU, RSP, +R3000GTE, R5900, MAX, } diff --git a/rust/src/instr_id_enum.rs b/rust/src/instr_id_enum.rs index f2e01eb..d858a1d 100644 --- a/rust/src/instr_id_enum.rs +++ b/rust/src/instr_id_enum.rs @@ -414,6 +414,50 @@ rsp_USERDEF_17, rsp_USERDEF_18, rsp_USERDEF_19, rsp_MAX, +r3000gte_INVALID, +r3000gte_RTPS, +r3000gte_RTPT, +r3000gte_DPCL, +r3000gte_DPCS, +r3000gte_DPCT, +r3000gte_INTPL, +r3000gte_NCS, +r3000gte_NCT, +r3000gte_NCDS, +r3000gte_NCDT, +r3000gte_NCCS, +r3000gte_NCCT, +r3000gte_CDP, +r3000gte_CC, +r3000gte_NCLIP, +r3000gte_AVSZ3, +r3000gte_AVSZ4, +r3000gte_MVMVA, +r3000gte_SQR, +r3000gte_OP, +r3000gte_GPF, +r3000gte_GPL, +r3000gte_USERDEF_00, +r3000gte_USERDEF_01, +r3000gte_USERDEF_02, +r3000gte_USERDEF_03, +r3000gte_USERDEF_04, +r3000gte_USERDEF_05, +r3000gte_USERDEF_06, +r3000gte_USERDEF_07, +r3000gte_USERDEF_08, +r3000gte_USERDEF_09, +r3000gte_USERDEF_10, +r3000gte_USERDEF_11, +r3000gte_USERDEF_12, +r3000gte_USERDEF_13, +r3000gte_USERDEF_14, +r3000gte_USERDEF_15, +r3000gte_USERDEF_16, +r3000gte_USERDEF_17, +r3000gte_USERDEF_18, +r3000gte_USERDEF_19, +r3000gte_MAX, r5900_INVALID, r5900_lq, r5900_sq, diff --git a/rust/src/instruction.rs b/rust/src/instruction.rs index 05b3225..4360322 100644 --- a/rust/src/instruction.rs +++ b/rust/src/instruction.rs @@ -36,6 +36,13 @@ extern "C" { fn RabbitizerInstructionRsp_processUniqueId(self_: *mut Instruction); } +extern "C" { + fn RabbitizerInstructionR3000GTE_init(self_: *mut Instruction, word: u32, vram: u32); + fn RabbitizerInstructionR3000GTE_destroy(self_: *mut Instruction); + + fn RabbitizerInstructionR3000GTE_processUniqueId(self_: *mut Instruction); +} + extern "C" { fn RabbitizerInstructionR5900_init(self_: *mut Instruction, word: u32, vram: u32); fn RabbitizerInstructionR5900_destroy(self_: *mut Instruction); @@ -165,6 +172,9 @@ impl Drop for Instruction { instr_category_enum::InstrCategory::RSP => { RabbitizerInstructionRsp_destroy(self); } + instr_category_enum::InstrCategory::R3000GTE => { + RabbitizerInstructionR3000GTE_destroy(self); + } instr_category_enum::InstrCategory::R5900 => { RabbitizerInstructionR5900_destroy(self); } @@ -189,6 +199,10 @@ impl Instruction { RabbitizerInstructionRsp_init(instr.as_mut_ptr(), word, vram); RabbitizerInstructionRsp_processUniqueId(instr.as_mut_ptr()); } + instr_category_enum::InstrCategory::R3000GTE => { + RabbitizerInstructionR3000GTE_init(instr.as_mut_ptr(), word, vram); + RabbitizerInstructionR3000GTE_processUniqueId(instr.as_mut_ptr()); + } instr_category_enum::InstrCategory::R5900 => { RabbitizerInstructionR5900_init(instr.as_mut_ptr(), word, vram); RabbitizerInstructionR5900_processUniqueId(instr.as_mut_ptr()); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 0897a5a..aef8a6e 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -31,6 +31,13 @@ pub use register_descriptor::RegisterDescriptor; mod tests { use super::*; + #[derive(Default, Debug, Clone)] + struct TestEntry { + word: u32, + imm_override: Option, + expected_str: String, + } + #[test] fn it_works() { assert_eq!( @@ -75,4 +82,88 @@ mod tests { fn test_register_descriptor() { assert!(registers::GprO32::a0.descriptor().is_clobbered_by_func_call()); } + + #[test] + fn test_r3000gte_instructions() { + let entries = [ + TestEntry { word: 0x4A180001, imm_override: None, expected_str: "RTPS".to_string() }, + TestEntry { word: 0x4A280030, imm_override: None, expected_str: "RTPT".to_string() }, + TestEntry { word: 0x4A680029, imm_override: None, expected_str: "DPCL".to_string() }, + TestEntry { word: 0x4A780010, imm_override: None, expected_str: "DPCS".to_string() }, + TestEntry { word: 0x4AF8002A, imm_override: None, expected_str: "DPCT".to_string() }, + TestEntry { word: 0x4A980011, imm_override: None, expected_str: "INTPL".to_string() }, + TestEntry { word: 0x4AC8041E, imm_override: None, expected_str: "NCS".to_string() }, + TestEntry { word: 0x4AD80420, imm_override: None, expected_str: "NCT".to_string() }, + TestEntry { word: 0x4AE80413, imm_override: None, expected_str: "NCDS".to_string() }, + TestEntry { word: 0x4AF80416, imm_override: None, expected_str: "NCDT".to_string() }, + TestEntry { word: 0x4B08041B, imm_override: None, expected_str: "NCCS".to_string() }, + TestEntry { word: 0x4B18043F, imm_override: None, expected_str: "NCCT".to_string() }, + TestEntry { word: 0x4B280414, imm_override: None, expected_str: "CDP".to_string() }, + TestEntry { word: 0x4B38041C, imm_override: None, expected_str: "CC".to_string() }, + TestEntry { word: 0x4B400006, imm_override: None, expected_str: "NCLIP".to_string() }, + TestEntry { word: 0x4B58002D, imm_override: None, expected_str: "AVSZ3".to_string() }, + TestEntry { word: 0x4B68002E, imm_override: None, expected_str: "AVSZ4".to_string() }, + TestEntry { word: 0x4A400012, imm_override: None, expected_str: "MVMVA 0, 0, 0, 0, 0".to_string() }, + TestEntry { word: 0x4AA00428, imm_override: None, expected_str: "SQR 0".to_string() }, + TestEntry { word: 0x4B70000C, imm_override: None, expected_str: "OP 0".to_string() }, + TestEntry { word: 0x4B90003D, imm_override: None, expected_str: "GPF 0".to_string() }, + TestEntry { word: 0x4BA0003E, imm_override: None, expected_str: "GPL 0".to_string() }, + TestEntry { word: 0x4A486012, imm_override: None, expected_str: "MVMVA 1, 0, 0, 3, 0".to_string() }, + TestEntry { word: 0x4A48E012, imm_override: None, expected_str: "MVMVA 1, 0, 1, 3, 0".to_string() }, + TestEntry { word: 0x4A496012, imm_override: None, expected_str: "MVMVA 1, 0, 2, 3, 0".to_string() }, + TestEntry { word: 0x4A49E012, imm_override: None, expected_str: "MVMVA 1, 0, 3, 3, 0".to_string() }, + TestEntry { word: 0x4A41E012, imm_override: None, expected_str: "MVMVA 0, 0, 3, 3, 0".to_string() }, + TestEntry { word: 0x4A480012, imm_override: None, expected_str: "MVMVA 1, 0, 0, 0, 0".to_string() }, + TestEntry { word: 0x4A488012, imm_override: None, expected_str: "MVMVA 1, 0, 1, 0, 0".to_string() }, + TestEntry { word: 0x4A490012, imm_override: None, expected_str: "MVMVA 1, 0, 2, 0, 0".to_string() }, + TestEntry { word: 0x4A498012, imm_override: None, expected_str: "MVMVA 1, 0, 3, 0, 0".to_string() }, + TestEntry { word: 0x4A482012, imm_override: None, expected_str: "MVMVA 1, 0, 0, 1, 0".to_string() }, + TestEntry { word: 0x4A48A012, imm_override: None, expected_str: "MVMVA 1, 0, 1, 1, 0".to_string() }, + TestEntry { word: 0x4A492012, imm_override: None, expected_str: "MVMVA 1, 0, 2, 1, 0".to_string() }, + TestEntry { word: 0x4A49A012, imm_override: None, expected_str: "MVMVA 1, 0, 3, 1, 0".to_string() }, + TestEntry { word: 0x4A4A6412, imm_override: None, expected_str: "MVMVA 1, 1, 0, 3, 1".to_string() }, + TestEntry { word: 0x4A4A6012, imm_override: None, expected_str: "MVMVA 1, 1, 0, 3, 0".to_string() }, + TestEntry { word: 0x4A4AE012, imm_override: None, expected_str: "MVMVA 1, 1, 1, 3, 0".to_string() }, + TestEntry { word: 0x4A4B6012, imm_override: None, expected_str: "MVMVA 1, 1, 2, 3, 0".to_string() }, + TestEntry { word: 0x4A4BE012, imm_override: None, expected_str: "MVMVA 1, 1, 3, 3, 0".to_string() }, + TestEntry { word: 0x4A4A0012, imm_override: None, expected_str: "MVMVA 1, 1, 0, 0, 0".to_string() }, + TestEntry { word: 0x4A4A8012, imm_override: None, expected_str: "MVMVA 1, 1, 1, 0, 0".to_string() }, + TestEntry { word: 0x4A4B0012, imm_override: None, expected_str: "MVMVA 1, 1, 2, 0, 0".to_string() }, + TestEntry { word: 0x4A4B8012, imm_override: None, expected_str: "MVMVA 1, 1, 3, 0, 0".to_string() }, + TestEntry { word: 0x4A4A2012, imm_override: None, expected_str: "MVMVA 1, 1, 0, 1, 0".to_string() }, + TestEntry { word: 0x4A4AA012, imm_override: None, expected_str: "MVMVA 1, 1, 1, 1, 0".to_string() }, + TestEntry { word: 0x4A4B2012, imm_override: None, expected_str: "MVMVA 1, 1, 2, 1, 0".to_string() }, + TestEntry { word: 0x4A4BA012, imm_override: None, expected_str: "MVMVA 1, 1, 3, 1, 0".to_string() }, + TestEntry { word: 0x4A4DA412, imm_override: None, expected_str: "MVMVA 1, 2, 3, 1, 1".to_string() }, + TestEntry { word: 0x4A4C6012, imm_override: None, expected_str: "MVMVA 1, 2, 0, 3, 0".to_string() }, + TestEntry { word: 0x4A4CE012, imm_override: None, expected_str: "MVMVA 1, 2, 1, 3, 0".to_string() }, + TestEntry { word: 0x4A4D6012, imm_override: None, expected_str: "MVMVA 1, 2, 2, 3, 0".to_string() }, + TestEntry { word: 0x4A4DE012, imm_override: None, expected_str: "MVMVA 1, 2, 3, 3, 0".to_string() }, + TestEntry { word: 0x4A4C0012, imm_override: None, expected_str: "MVMVA 1, 2, 0, 0, 0".to_string() }, + TestEntry { word: 0x4A4C8012, imm_override: None, expected_str: "MVMVA 1, 2, 1, 0, 0".to_string() }, + TestEntry { word: 0x4A4D0012, imm_override: None, expected_str: "MVMVA 1, 2, 2, 0, 0".to_string() }, + TestEntry { word: 0x4A4D8012, imm_override: None, expected_str: "MVMVA 1, 2, 3, 0, 0".to_string() }, + TestEntry { word: 0x4A4C2012, imm_override: None, expected_str: "MVMVA 1, 2, 0, 1, 0".to_string() }, + TestEntry { word: 0x4A4CA012, imm_override: None, expected_str: "MVMVA 1, 2, 1, 1, 0".to_string() }, + TestEntry { word: 0x4A4D2012, imm_override: None, expected_str: "MVMVA 1, 2, 2, 1, 0".to_string() }, + TestEntry { word: 0x4A4DA012, imm_override: None, expected_str: "MVMVA 1, 2, 3, 1, 0".to_string() }, + TestEntry { word: 0x4AA80428, imm_override: None, expected_str: "SQR 1".to_string() }, + TestEntry { word: 0x4AA80428, imm_override: None, expected_str: "SQR 1".to_string() }, + TestEntry { word: 0x4B78000C, imm_override: None, expected_str: "OP 1".to_string() }, + TestEntry { word: 0x4B70000C, imm_override: None, expected_str: "OP 0".to_string() }, + TestEntry { word: 0x4B98003D, imm_override: None, expected_str: "GPF 1".to_string() }, + TestEntry { word: 0x4B90003D, imm_override: None, expected_str: "GPF 0".to_string() }, + TestEntry { word: 0x4BA8003E, imm_override: None, expected_str: "GPL 1".to_string() }, + TestEntry { word: 0x4BA0003E, imm_override: None, expected_str: "GPL 0".to_string() }, + ]; + + for entry in entries.iter() { + let instr = instruction::Instruction::new(entry.word, 0x80000000, instr_category_enum::InstrCategory::R3000GTE); + + assert_eq!( + instr.disassemble(entry.imm_override.as_ref().map(|x| x.as_str()), 0), + entry.expected_str + ); + } + } } diff --git a/rust/src/operand_type_enum.rs b/rust/src/operand_type_enum.rs index dbc0f4e..c9740cc 100644 --- a/rust/src/operand_type_enum.rs +++ b/rust/src/operand_type_enum.rs @@ -45,6 +45,11 @@ rsp_vs_index, rsp_offset_rs, rsp_immediate_base, rsp_maybe_rd_rs, + r3000gte_sf, + r3000gte_mx, + r3000gte_v, + r3000gte_cv, + r3000gte_lm, r5900_I, r5900_Q, r5900_R, diff --git a/rust/src/utils.rs b/rust/src/utils.rs index d8bafdb..aa82cff 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -23,3 +23,10 @@ pub fn shiftl(v: u32, s: u32, w: u32) -> u32 { pub fn shiftr(v: u32, s: u32, w: u32) -> u32 { mask(v >> s, w) } + +pub fn convert_option_string_to_option_str(input: &Option) -> Option<&str> { + match input { + None => None, + Some(x) => Some(x.as_str()) + } +} diff --git a/setup.py b/setup.py index e8f53bb..7550844 100644 --- a/setup.py +++ b/setup.py @@ -1,25 +1,29 @@ -# SPDX-FileCopyrightText: © 2022 Decompollaborate +# SPDX-FileCopyrightText: © 2022-2023 Decompollaborate # SPDX-License-Identifier: MIT from setuptools import setup, Extension from pathlib import Path +import platform bindingsPath = Path("rabbitizer") srcPath = Path("src") sourcesList = [str(x) for x in bindingsPath.glob("**/*.c")] + [str(x) for x in srcPath.glob("**/*.c")] +extraCompileArgs = ["-std=c11", "-Wall", "-g",] +if platform.system() == "Linux": + extraCompileArgs += ["-Os", "-Wextra",] + extraCompileArgs += ["-Werror=vla", "-Werror=switch", "-Werror=implicit-fallthrough", "-Werror=unused-function", "-Werror=unused-parameter", "-Werror=shadow", "-Werror=switch"] + extraCompileArgs += ["-Werror=implicit-function-declaration", "-Werror=incompatible-pointer-types"] + extraCompileArgs += ["-Werror"] + setup( ext_modules=[ Extension( name="rabbitizer", sources=sourcesList, include_dirs=["include", "rabbitizer"], - extra_compile_args = [ - "-std=c11", - "-Wall", - "-g", - ], + extra_compile_args = extraCompileArgs, ), ], )