├── rabbitizer ├── py.typed ├── TrinaryValue.pyi ├── LoPairingInfo.pyi ├── Abi.pyi ├── JrRegData.pyi ├── InstrCategory.pyi ├── AccessType.pyi ├── TrackedRegisterState.pyi ├── Utils.pyi ├── enums │ ├── rabbitizer_enum_AccessType.c │ ├── rabbitizer_enum_InstrIdType.c │ ├── rabbitizer_enum_TrinaryValue.c │ ├── rabbitizer_enum_OperandType.c │ ├── registers │ │ ├── rabbitizer_enum_GprN32.c │ │ ├── rabbitizer_enum_GprO32.c │ │ ├── rabbitizer_enum_Cop1N32.c │ │ ├── rabbitizer_enum_Cop1N64.c │ │ └── rabbitizer_enum_Cop1O32.c │ ├── rabbitizer_enum_InstrId.c │ ├── enums_utils.c │ ├── rabbitizer_enum_Abi.c │ └── rabbitizer_enum_InstrCategory.c ├── Enum.pyi ├── RegGprN32.pyi ├── RegGprO32.pyi ├── __init__.pyi ├── RegCop1N64.pyi ├── RegCop1N32.pyi ├── RegCop1O32.pyi ├── Config.pyi ├── rabbitizer_module.h └── RegistersTracker.pyi ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── feature_suggestion.yml └── workflows │ ├── md_lint.yml │ ├── isolated_python_build.yml │ ├── check_tables.yml │ └── check_format.yml ├── tests ├── asm │ ├── r5900 │ │ ├── Makefile │ │ ├── trunc_w_c.s │ │ └── vcallms.s │ ├── r4000allegrex │ │ ├── README.txt │ │ ├── Makefile │ │ └── sceVfpuMatrix3Transform.c │ └── r3000gte │ │ ├── gte_instrs.s │ │ └── inline_gte_commands.inc.s ├── run_build_info_checks.sh ├── run_logic_checks.sh ├── cplusplus │ └── test.cpp ├── run_instruction_checks.sh └── c │ ├── instruction_checks │ ├── r5900_trunc_cvt.c │ └── r5900_disasm.c │ ├── test.c │ ├── r5900test.c │ ├── r3000gte.c │ ├── rsptest.c │ ├── r4000allegrex.c │ └── registersTrackerTest.c ├── tables ├── tables │ ├── InstrSuffix.inc │ ├── Abi.inc │ ├── operands │ │ ├── RabbitizerOperandType_r3000gte.inc │ │ ├── RabbitizerOperandType_rsp.inc │ │ ├── RabbitizerOperandType_cpu.inc │ │ └── RabbitizerOperandType_r5900.inc │ ├── InstrIds.inc │ ├── OperandTypes.inc │ ├── InstrCategory.inc │ ├── InstrIdType.inc │ ├── AccessType.inc │ ├── instr_id_types │ │ ├── InstrIdType_r3000gte.inc │ │ ├── InstrIdType_rsp.inc │ │ ├── InstrIdType_cpu.inc │ │ └── InstrIdType_r5900.inc │ ├── instr_id │ │ ├── rsp │ │ │ ├── rsp_cop0.inc │ │ │ ├── rsp_cop2.inc │ │ │ ├── rsp_regimm.inc │ │ │ └── rsp_normal_lwc2.inc │ │ ├── r4000allegrex │ │ │ ├── r4000allegrex_regimm.inc │ │ │ ├── r4000allegrex_cop0_bc0.inc │ │ │ ├── r4000allegrex_cop1_bc1.inc │ │ │ ├── r4000allegrex_cop0.inc │ │ │ ├── r4000allegrex_cop2.inc │ │ │ ├── r4000allegrex_cop1.inc │ │ │ ├── r4000allegrex_cop2_mfhc2_p_s.inc │ │ │ ├── r4000allegrex_cop2_mfhc2.inc │ │ │ ├── r4000allegrex_cop2_mfhc2_p.inc │ │ │ ├── r4000allegrex_vfpu4_fmt0.inc │ │ │ ├── r4000allegrex_cop0_tlb.inc │ │ │ ├── r4000allegrex_quadlr.inc │ │ │ ├── r4000allegrex_cop1_fpu_s.inc │ │ │ ├── r4000allegrex_cop1_fpu_w.inc │ │ │ ├── r4000allegrex_special_rs.inc │ │ │ ├── r4000allegrex_vfpu4.inc │ │ │ ├── r4000allegrex_vfpu7.inc │ │ │ ├── r4000allegrex_special_sa.inc │ │ │ ├── r4000allegrex_cop2_mthc2.inc │ │ │ ├── r4000allegrex_special2.inc │ │ │ ├── r4000allegrex_special3.inc │ │ │ ├── r4000allegrex_vfpu4_fmt0_control.inc │ │ │ ├── r4000allegrex_cop2_bc2.inc │ │ │ └── r4000allegrex_special3_bshfl.inc │ │ ├── r5900 │ │ │ ├── r5900_mmi_pmthl.inc │ │ │ ├── r5900_regimm.inc │ │ │ ├── r5900_cop0_tlb.inc │ │ │ ├── r5900_cop2_bc2.inc │ │ │ ├── r5900_cop2_i.inc │ │ │ ├── r5900_cop2_ni.inc │ │ │ ├── r5900_special.inc │ │ │ └── r5900_mmi_pmfhl.inc │ │ └── cpu │ │ │ ├── cpu_cop2.inc │ │ │ ├── cpu_cop1_bc1.inc │ │ │ ├── cpu_cop0_bc0.inc │ │ │ ├── cpu_cop1_fpu_l.inc │ │ │ └── cpu_cop1_fpu_w.inc │ └── registers │ │ └── RabbitizerRegister_RspCop0.inc ├── templates │ ├── cplusplus │ │ ├── AccessType_enum_class.table.template │ │ ├── InstrIdType_enum_class.table.template │ │ ├── OperandType_enum_class.table.template │ │ └── UniqueId_enum_class.table.template │ ├── c │ │ ├── Abi_enum.table.template │ │ ├── AccessType_enum.table.template │ │ ├── InstrCategory_Names_array.table.template │ │ ├── InstrIdType_enum.table.template │ │ ├── InstrIdType_Names_array.table.template │ │ ├── instrOpercandCallbacks_array.table.template │ │ ├── OperandType_function_declarations.table.template │ │ ├── InstrCategory_enum.table.template │ │ ├── InstrSuffix_enum.table.template │ │ ├── OperandType_enum.table.template │ │ ├── InstrId_Names_array.table.template │ │ ├── InstrDescriptor_Descriptors_array.table.template │ │ └── InstrId_enum.table.template │ ├── python │ │ ├── AccessType.tablepyi.template │ │ ├── InstrIdType.tablepyi.template │ │ ├── Abi.tablepyi.template │ │ ├── OperandType.tablepyi.template │ │ ├── InstrCategory.tablepyi.template │ │ ├── RegCop1N32.tablepyi.template │ │ ├── RegCop1N64.tablepyi.template │ │ ├── RegCop1O32.tablepyi.template │ │ ├── RegGprN32.tablepyi.template │ │ ├── RegGprO32.tablepyi.template │ │ └── InstrId.tablepyi.template │ └── rust │ │ ├── abi_enum.tablers.template │ │ ├── access_type_enum.tablers.template │ │ ├── instr_id_type_enum.tablers.template │ │ ├── instr_category_enum.tablers.template │ │ ├── instr_suffix_enum.tablers.template │ │ ├── operand_type_enum.tablers.template │ │ └── instr_id_enum.tablers.template └── tools │ ├── rs_table_gen.sh │ ├── pyi_table_gen.sh │ └── c_table_gen.sh ├── MANIFEST.in ├── .vscode └── extensions.json ├── cplusplus ├── include │ ├── common │ │ └── Utils.hpp │ ├── instructions │ │ ├── AccessType.hpp │ │ ├── OperandType.hpp │ │ ├── Registers.hpp │ │ ├── InstrId.hpp │ │ ├── InstrIdType.hpp │ │ ├── InstructionCpu.hpp │ │ ├── InstructionR3000GTE.hpp │ │ ├── InstructionRsp.hpp │ │ └── InstructionR5900.hpp │ ├── generated │ │ └── AccessType_enum_class.hpp │ ├── rabbitizer.hpp │ └── analysis │ │ ├── JrRegData.hpp │ │ └── LoPairingInfo.hpp └── src │ ├── instructions │ ├── InstrIdType.cpp │ ├── InstrId.cpp │ ├── InstructionCpu.cpp │ └── InstructionR3000GTE.cpp │ └── analysis │ ├── JrRegData.cpp │ └── LoPairingInfo.cpp ├── rust ├── src │ ├── abi_enum.rs │ ├── instr_suffix_enum.rs │ ├── instr_category_enum.rs │ ├── access_type_enum.rs │ ├── utils.rs │ ├── register_descriptor.rs │ ├── opereand_type.rs │ ├── config.rs │ └── instr_descriptor.rs └── build.rs ├── include ├── instructions │ ├── RabbitizerAccessType.h │ ├── RabbitizerInstrCategory.h │ ├── RabbitizerInstrIdType.h │ ├── RabbitizerInstrId.h │ ├── RabbitizerOperandType.h │ └── RabbitizerInstrSuffix.h ├── generated │ ├── InstrSuffix_enum.h │ ├── Abi_enum.h │ ├── InstrCategory_enum.h │ ├── InstrCategory_Names_array.h │ └── AccessType_enum.h ├── analysis │ ├── RabbitizerLoPairingInfo.h │ └── RabbitizerJrRegData.h ├── common │ └── RabbitizerVersion.h └── rabbitizer.h ├── .markdownlint.jsonc ├── src ├── common │ ├── RabbitizerVersion.c │ └── RabbitizerConfig.c ├── analysis │ ├── RabbitizerLoPairingInfo.c │ └── RabbitizerJrRegData.c └── instructions │ ├── RabbitizerInstrIdType.c │ ├── RabbitizerInstrCategory.c │ ├── RabbitizerInstructionR5900 │ └── RabbitizerInstructionR5900.c │ ├── RabbitizerInstructionR3000GTE │ └── RabbitizerInstructionR3000GTE.c │ ├── RabbitizerInstructionR4000Allegrex │ └── RabbitizerInstructionR4000Allegrex.c │ ├── RabbitizerInstrId.c │ ├── RabbitizerRegisterDescriptor.c │ └── RabbitizerInstructionRsp │ └── RabbitizerInstructionRsp.c ├── .clang-format ├── .clang-tidy ├── Cargo.toml ├── pyproject.toml ├── LICENSE ├── .gitattributes └── setup.py /rabbitizer/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /tests/asm/r5900/Makefile: -------------------------------------------------------------------------------- 1 | CROSS := mips-linux-gnu- 2 | AS := $(CROSS)as 3 | 4 | %.o: %.s 5 | $(AS) -march=r5900 -mabi=eabi -o $@ $^ 6 | -------------------------------------------------------------------------------- /tables/tables/InstrSuffix.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RAB_DEF_INSTRSUFFIX(R5900, xyzw) 5 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 2 | # SPDX-License-Identifier: MIT 3 | 4 | include **/*.h 5 | include **/**/*.h 6 | graft include 7 | graft tables 8 | graft src 9 | -------------------------------------------------------------------------------- /tests/run_build_info_checks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-FileCopyrightText: © 2023-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -e 7 | 8 | ./build/tests/c/build_info_checks/version_number.elf 9 | -------------------------------------------------------------------------------- /tests/run_logic_checks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -e 7 | 8 | ./build/tests/c/logic_checks/descriptor_logic_check.elf 9 | -------------------------------------------------------------------------------- /tests/asm/r5900/trunc_w_c.s: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | .section .text 4 | 5 | .global test 6 | trunc.w.s $f0, $f12 7 | jr $31 8 | nop 9 | 10 | .global test2 11 | cvt.w.s $f0, $f12 12 | jr $31 13 | nop 14 | 15 | 16 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "davidanson.vscode-markdownlint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tables/tables/Abi.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_ABI(NUMERIC) 5 | RABBITIZER_DEF_ABI(O32) 6 | RABBITIZER_DEF_ABI(N32) 7 | RABBITIZER_DEF_ABI(N64) 8 | -------------------------------------------------------------------------------- /rabbitizer/TrinaryValue.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2023-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class TrinaryValue: 11 | NONE: Enum 12 | FALSE: Enum 13 | TRUE: Enum 14 | -------------------------------------------------------------------------------- /tables/templates/cplusplus/AccessType_enum_class.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_ACCESSTYPE(name) name, 5 | 6 | enum class AccessType { 7 | #include "AccessType.inc" 8 | 9 | RAB_DEF_ACCESSTYPE(MAX) 10 | }; 11 | 12 | #undef RAB_DEF_ACCESSTYPE 13 | -------------------------------------------------------------------------------- /cplusplus/include/common/Utils.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_UTILS_HPP 5 | #define RABBITIZER_UTILS_HPP 6 | 7 | namespace rabbitizer { 8 | enum class TrinaryValue { 9 | NONE, 10 | FALSE, 11 | TRUE, 12 | }; 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/AccessType.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_ACCESS_TYPE_HPP 5 | #define RABBITIZER_ACCESS_TYPE_HPP 6 | #pragma once 7 | 8 | 9 | namespace rabbitizer { 10 | #include "generated/AccessType_enum_class.hpp" 11 | }; 12 | 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/OperandType.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_OPERAND_TYPE_HPP 5 | #define RABBITIZER_OPERAND_TYPE_HPP 6 | #pragma once 7 | 8 | 9 | namespace rabbitizer { 10 | #include "generated/OperandType_enum_class.hpp" 11 | }; 12 | 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /tables/templates/c/Abi_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_ABI(name) RABBITIZER_ABI_##name, 5 | 6 | typedef enum RabbitizerAbi { 7 | #include "Abi.inc" 8 | 9 | RABBITIZER_DEF_ABI(MAX) 10 | } RabbitizerAbi; 11 | 12 | #undef RABBITIZER_DEF_ABI 13 | -------------------------------------------------------------------------------- /tables/templates/cplusplus/InstrIdType_enum_class.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID_TYPE(prefix, name) \ 5 | prefix##_##name, 6 | 7 | enum class IdType { 8 | #include "InstrIdType.inc" 9 | }; 10 | 11 | #undef RABBITIZER_DEF_INSTR_ID_TYPE 12 | -------------------------------------------------------------------------------- /rust/src/abi_enum.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #[repr(u32)] 7 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] 8 | #[allow(non_camel_case_types)] 9 | pub enum Abi { 10 | NUMERIC, 11 | O32, 12 | N32, 13 | N64, 14 | MAX, 15 | } 16 | -------------------------------------------------------------------------------- /rabbitizer/LoPairingInfo.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | 9 | class LoPairingInfo: 10 | instrOffset: int 11 | value: int 12 | shouldProcess: bool 13 | isGpRel: bool 14 | isGpGot: bool 15 | 16 | def __init__(self): ... 17 | -------------------------------------------------------------------------------- /rust/src/instr_suffix_enum.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #[repr(u32)] 7 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] 8 | #[allow(non_camel_case_types)] 9 | pub enum InstrSuffix { 10 | ALL_NONE, 11 | R5900_xyzw, 12 | ALL_MAX, 13 | } 14 | -------------------------------------------------------------------------------- /tables/tables/operands/RabbitizerOperandType_r3000gte.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RAB_DEF_OPERAND(r3000gte, gbg) 5 | RAB_DEF_OPERAND(r3000gte, sf) 6 | RAB_DEF_OPERAND(r3000gte, mx) 7 | RAB_DEF_OPERAND(r3000gte, v) 8 | RAB_DEF_OPERAND(r3000gte, cv) 9 | RAB_DEF_OPERAND(r3000gte, lm) 10 | -------------------------------------------------------------------------------- /tables/templates/c/AccessType_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_ACCESSTYPE(name) RAB_ACCESSTYPE_##name, 5 | 6 | typedef enum RabbitizerAccessType { 7 | #include "AccessType.inc" 8 | 9 | RAB_DEF_ACCESSTYPE(MAX) 10 | } RabbitizerAccessType; 11 | 12 | #undef RAB_DEF_ACCESSTYPE 13 | -------------------------------------------------------------------------------- /tables/templates/c/InstrCategory_Names_array.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_CATEGORY(name) [RABBITIZER_INSTRCAT_##name] = #name, 5 | 6 | const char *const RabbitizerInstrCategory_Names[] = { 7 | #include "InstrCategory.inc" 8 | }; 9 | 10 | #undef RABBITIZER_DEF_INSTR_CATEGORY 11 | -------------------------------------------------------------------------------- /tables/templates/c/InstrIdType_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID_TYPE(prefix, name) \ 5 | RAB_INSTR_ID_TYPE_##prefix##_##name, 6 | 7 | typedef enum RabInstrIdType { 8 | #include "InstrIdType.inc" 9 | } RabInstrIdType; 10 | 11 | #undef RABBITIZER_DEF_INSTR_ID_TYPE 12 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/Registers.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_REGISTER_HPP 5 | #define RABBITIZER_REGISTER_HPP 6 | #pragma once 7 | 8 | 9 | namespace rabbitizer { 10 | namespace Registers { 11 | #include "generated/Registers_enum_classes.hpp" 12 | }; 13 | }; 14 | 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /tables/templates/python/AccessType.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RAB_DEF_ACCESSTYPE(name) name: Enum 9 | 10 | class AccessType: 11 | #include "AccessType.inc" 12 | 13 | MAX: Enum 14 | 15 | #undef RAB_DEF_ACCESSTYPE 16 | -------------------------------------------------------------------------------- /tables/tables/InstrIds.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instr_id/RabbitizerInstrId_cpu.inc" 5 | #include "instr_id/RabbitizerInstrId_rsp.inc" 6 | #include "instr_id/RabbitizerInstrId_r3000gte.inc" 7 | #include "instr_id/RabbitizerInstrId_r4000allegrex.inc" 8 | #include "instr_id/RabbitizerInstrId_r5900.inc" 9 | -------------------------------------------------------------------------------- /include/instructions/RabbitizerAccessType.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_ACCESS_TYPE_H 5 | #define RABBITIZER_ACCESS_TYPE_H 6 | #pragma once 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #include "generated/AccessType_enum.h" 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /tables/templates/c/InstrIdType_Names_array.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID_TYPE(prefix, name) \ 5 | [RAB_INSTR_ID_TYPE_##prefix##_##name] = #prefix "_" #name, 6 | 7 | const char *RabInstrIdType_Names[] = { 8 | #include "InstrIdType.inc" 9 | }; 10 | 11 | #undef RABBITIZER_DEF_INSTR_ID_TYPE 12 | -------------------------------------------------------------------------------- /rabbitizer/Abi.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class Abi: 11 | NUMERIC: Enum 12 | O32: Enum 13 | N32: Enum 14 | N64: Enum 15 | @staticmethod 16 | def fromStr(name: str | None) -> Enum: ... 17 | -------------------------------------------------------------------------------- /rust/src/instr_category_enum.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #[repr(u32)] 7 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] 8 | #[allow(non_camel_case_types)] 9 | pub enum InstrCategory { 10 | CPU, 11 | RSP, 12 | R3000GTE, 13 | R4000ALLEGREX, 14 | R5900, 15 | MAX, 16 | } 17 | -------------------------------------------------------------------------------- /tables/tables/OperandTypes.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "operands/RabbitizerOperandType_cpu.inc" 5 | #include "operands/RabbitizerOperandType_rsp.inc" 6 | #include "operands/RabbitizerOperandType_r3000gte.inc" 7 | #include "operands/RabbitizerOperandType_r4000allegrex.inc" 8 | #include "operands/RabbitizerOperandType_r5900.inc" 9 | -------------------------------------------------------------------------------- /tables/templates/c/instrOpercandCallbacks_array.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_OPERAND(prefix, operand) [RAB_OPERAND_##prefix##_##operand] = RabbitizerOperandType_process_##prefix##_##operand, 5 | 6 | const OperandCallback instrOpercandCallbacks[] = { 7 | #include "OperandTypes.inc" 8 | }; 9 | 10 | #undef RAB_DEF_OPERAND 11 | -------------------------------------------------------------------------------- /tables/templates/python/InstrIdType.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_INSTR_ID_TYPE(prefix, name) \ 9 | prefix##_##name: Enum 10 | 11 | class InstrIdType: 12 | #include "InstrIdType.inc" 13 | 14 | #undef RABBITIZER_DEF_INSTR_ID_TYPE 15 | -------------------------------------------------------------------------------- /rabbitizer/JrRegData.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | 9 | class JrRegData: 10 | def hasInfo(self) -> bool: ... 11 | def offset(self) -> int: ... 12 | def address(self) -> int: ... 13 | def checkedForBranching(self) -> bool: ... 14 | def lastBranchOffset(self) -> bool: ... 15 | -------------------------------------------------------------------------------- /tables/templates/c/OperandType_function_declarations.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_OPERAND(prefix, operand) size_t RabbitizerOperandType_process_##prefix##_##operand (const struct RabbitizerInstruction *self, char *dst, const char *immOverride, size_t immOverrideLength); 5 | 6 | #include "OperandTypes.inc" 7 | 8 | #undef RAB_DEF_OPERAND 9 | -------------------------------------------------------------------------------- /tables/templates/cplusplus/OperandType_enum_class.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_OPERAND(prefix, operand) \ 5 | prefix##_##operand, 6 | 7 | enum class OperandType { 8 | RAB_DEF_OPERAND(ALL, INVALID) 9 | 10 | #include "OperandTypes.inc" 11 | 12 | RAB_DEF_OPERAND(ALL, MAX) 13 | }; 14 | 15 | #undef RAB_DEF_OPERAND 16 | -------------------------------------------------------------------------------- /tables/templates/python/Abi.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_ABI(name) name: Enum 9 | 10 | class Abi: 11 | #include "Abi.inc" 12 | 13 | @staticmethod 14 | def fromStr(name: str | None) -> Enum: ... 15 | 16 | #undef RAB_DEF_ACCESSTYPE 17 | -------------------------------------------------------------------------------- /tables/templates/c/InstrCategory_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_CATEGORY(name) RABBITIZER_INSTRCAT_##name, 5 | 6 | typedef enum RabbitizerInstrCategory { 7 | #include "InstrCategory.inc" 8 | 9 | RABBITIZER_DEF_INSTR_CATEGORY(MAX) 10 | } RabbitizerInstrCategory; 11 | 12 | #undef RABBITIZER_DEF_INSTR_CATEGORY 13 | -------------------------------------------------------------------------------- /.markdownlint.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | // https://github.com/DavidAnson/markdownlint/blob/main/doc/md024.md 3 | // MD024 - Multiple headings with the same content 4 | "MD024": { 5 | "siblings_only": true 6 | }, 7 | 8 | // https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md 9 | // MD013 - Line length 10 | "MD013": { 11 | "code_block_line_length": 120, 12 | "headings": false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/common/RabbitizerVersion.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "common/RabbitizerVersion.h" 5 | 6 | const int RabVersion_Major = RAB_VERSION_MAJOR; 7 | const int RabVersion_Minor = RAB_VERSION_MINOR; 8 | const int RabVersion_Patch = RAB_VERSION_PATCH; 9 | 10 | const char RabVersion_Str[] = RAB_VERSION_STR; 11 | 12 | const char RabVersion_Author[] = RAB_VERSION_AUTHOR; 13 | -------------------------------------------------------------------------------- /tests/asm/r5900/vcallms.s: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | .section .text 4 | 5 | .global vcallms_test 6 | vcallms_test: 7 | .ent vcallms_test 8 | vcallms 0x0000 9 | vcallms 0x0800 10 | vcallms 0x1000 11 | vcallms 0x1100 12 | vcallms 0x1200 13 | vcallms 0x1300 14 | vcallms 0x1400 15 | vcallms 0xFFF8 16 | vcallms 0x10000 17 | vcallms 0x3F000 18 | vcallms 0x3FFF0 19 | jr $ra 20 | nop 21 | 22 | .end vcallms_test 23 | -------------------------------------------------------------------------------- /tables/tables/InstrCategory.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_INSTR_CATEGORY(CPU) 5 | RABBITIZER_DEF_INSTR_CATEGORY(RSP) // N64 6 | RABBITIZER_DEF_INSTR_CATEGORY(R3000GTE) // R3000 CPU with PS1's Geometry Transformation Engine extension 7 | RABBITIZER_DEF_INSTR_CATEGORY(R4000ALLEGREX) // PSP's CPU 8 | RABBITIZER_DEF_INSTR_CATEGORY(R5900) // PS2's Emotion Engine 9 | -------------------------------------------------------------------------------- /include/generated/InstrSuffix_enum.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #ifndef InstrSuffix_enum_h_automatic 7 | #define InstrSuffix_enum_h_automatic 8 | 9 | typedef enum RabbitizerInstrSuffix { 10 | RABINSTRSUFFIX_ALL_NONE, 11 | RABINSTRSUFFIX_R5900_xyzw, 12 | RABINSTRSUFFIX_ALL_MAX, 13 | } RabbitizerInstrSuffix; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /tables/templates/c/InstrSuffix_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_INSTRSUFFIX(prefix, name) RABINSTRSUFFIX_##prefix##_##name, 5 | 6 | typedef enum RabbitizerInstrSuffix { 7 | RAB_DEF_INSTRSUFFIX(ALL, NONE) 8 | 9 | #include "InstrSuffix.inc" 10 | 11 | RAB_DEF_INSTRSUFFIX(ALL, MAX) 12 | } RabbitizerInstrSuffix; 13 | 14 | #undef RAB_DEF_INSTRSUFFIX 15 | -------------------------------------------------------------------------------- /tables/templates/c/OperandType_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RAB_DEF_OPERAND(prefix, operand) \ 5 | RAB_OPERAND_##prefix##_##operand, 6 | 7 | typedef enum RabbitizerOperandType { 8 | RAB_DEF_OPERAND(ALL, INVALID) 9 | 10 | #include "OperandTypes.inc" 11 | 12 | RAB_DEF_OPERAND(ALL, MAX) 13 | } RabbitizerOperandType; 14 | 15 | #undef RAB_DEF_OPERAND 16 | -------------------------------------------------------------------------------- /cplusplus/src/instructions/InstrIdType.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/InstrIdType.hpp" 5 | 6 | #include "instructions/RabbitizerInstrIdType.h" 7 | 8 | using namespace rabbitizer; 9 | 10 | std::string InstrIdType::getName(IdType idType) { 11 | RabInstrIdType id = static_cast(idType); 12 | 13 | return std::string(RabInstrIdType_getName(id)); 14 | } 15 | -------------------------------------------------------------------------------- /include/generated/Abi_enum.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #ifndef Abi_enum_h_automatic 7 | #define Abi_enum_h_automatic 8 | 9 | typedef enum RabbitizerAbi { 10 | RABBITIZER_ABI_NUMERIC, 11 | RABBITIZER_ABI_O32, 12 | RABBITIZER_ABI_N32, 13 | RABBITIZER_ABI_N64, 14 | RABBITIZER_ABI_MAX, 15 | } RabbitizerAbi; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /tests/cplusplus/test.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/InstructionCpu.hpp" 5 | 6 | 7 | int main() { 8 | uint32_t word = 0x8D4A7E18; // lw 9 | uint32_t vram = 0x80000000; 10 | int extraLJust = 5; 11 | rabbitizer::InstructionCpu instr(word, vram); 12 | 13 | printf("%08X: %s\n", word, instr.disassemble(extraLJust).c_str()); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/analysis/RabbitizerLoPairingInfo.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "analysis/RabbitizerLoPairingInfo.h" 5 | 6 | void RabbitizerLoPairingInfo_Init(RabbitizerLoPairingInfo *self) { 7 | *self = (RabbitizerLoPairingInfo){ 8 | .instrOffset = 0, 9 | .value = 0, 10 | .shouldProcess = false, 11 | .isGpRel = false, 12 | .isGpGot = false, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/InstrId.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRID_HPP 5 | #define RABBITIZER_INSTRID_HPP 6 | #pragma once 7 | 8 | #include 9 | 10 | 11 | namespace rabbitizer { 12 | namespace InstrId { 13 | #include "generated/UniqueId_enum_class.hpp" 14 | 15 | std::string getOpcodeName(UniqueId uniqueId); 16 | }; 17 | }; 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /.github/workflows/md_lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint markdown files 2 | 3 | # Build on every branch push, tag push, and pull request change: 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | checks: 8 | runs-on: ubuntu-22.04 9 | name: Lint md files 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@main 13 | 14 | - name: Lint markdown files 15 | uses: articulate/actions-markdownlint@v1.1.0 16 | with: 17 | config: .markdownlint.jsonc 18 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/InstrIdType.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTR_ID_TYPE_HPP 5 | #define RABBITIZER_INSTR_ID_TYPE_HPP 6 | #pragma once 7 | 8 | #include 9 | 10 | 11 | namespace rabbitizer { 12 | namespace InstrIdType { 13 | #include "generated/InstrIdType_enum_class.hpp" 14 | 15 | std::string getName(IdType idType); 16 | }; 17 | }; 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /cplusplus/src/instructions/InstrId.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/InstrId.hpp" 5 | 6 | #include "instructions/RabbitizerInstrId.h" 7 | 8 | using namespace rabbitizer; 9 | 10 | std::string InstrId::getOpcodeName(InstrId::UniqueId uniqueId) { 11 | RabbitizerInstrId id = static_cast(uniqueId); 12 | 13 | return std::string(RabbitizerInstrId_getOpcodeName(id)); 14 | } 15 | -------------------------------------------------------------------------------- /tables/templates/python/OperandType.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RAB_DEF_OPERAND(prefix, operand) \ 9 | prefix##_##operand: Enum 10 | 11 | class OperandType: 12 | RAB_DEF_OPERAND(ALL, INVALID) 13 | 14 | #include "OperandTypes.inc" 15 | 16 | RAB_DEF_OPERAND(ALL, MAX) 17 | 18 | #undef RAB_DEF_OPERAND 19 | -------------------------------------------------------------------------------- /rabbitizer/InstrCategory.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class InstrCategory: 11 | CPU: Enum 12 | RSP: Enum 13 | R3000GTE: Enum 14 | R4000ALLEGREX: Enum 15 | R5900: Enum 16 | MAX: Enum 17 | @staticmethod 18 | def fromStr(name: str | None) -> Enum|None: ... 19 | -------------------------------------------------------------------------------- /tables/templates/python/InstrCategory.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_INSTR_CATEGORY(name) name: Enum 9 | 10 | class InstrCategory: 11 | #include "InstrCategory.inc" 12 | MAX: Enum 13 | 14 | @staticmethod 15 | def fromStr(name: str | None) -> Enum|None: ... 16 | 17 | #undef RABBITIZER_DEF_INSTR_CATEGORY 18 | -------------------------------------------------------------------------------- /tables/tables/InstrIdType.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_INSTR_ID_TYPE(ALL, INVALID) 5 | 6 | #include "instr_id_types/InstrIdType_cpu.inc" 7 | #include "instr_id_types/InstrIdType_rsp.inc" 8 | #include "instr_id_types/InstrIdType_r3000gte.inc" 9 | #include "instr_id_types/InstrIdType_r4000allegrex.inc" 10 | #include "instr_id_types/InstrIdType_r5900.inc" 11 | 12 | RABBITIZER_DEF_INSTR_ID_TYPE(ALL, MAX) 13 | -------------------------------------------------------------------------------- /tests/asm/r4000allegrex/README.txt: -------------------------------------------------------------------------------- 1 | This folder is a small test suite to check how the official SN toolchain 2 | encodes and decodes instructions, so we can properly mimic it. 3 | 4 | The `.dump.s` files are the decoded files by the `snbin.exe` tool. 5 | 6 | To add more cases to the existing files then add them to the `.s` files and run 7 | `make COMPILER_PATH=path/to/psp/sn/toolchain`. This will use `wine` by default. 8 | The `wine` path can be changing by using the setting the `WINE=` variable when 9 | invoking the makefile. 10 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/InstructionCpu.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRUCTION_CPU_HPP 5 | #define RABBITIZER_INSTRUCTION_CPU_HPP 6 | #pragma once 7 | 8 | #include "InstructionBase.hpp" 9 | 10 | 11 | namespace rabbitizer { 12 | class InstructionCpu : public InstructionBase { 13 | public: 14 | InstructionCpu(uint32_t word, uint32_t vram); 15 | virtual ~InstructionCpu(); 16 | }; 17 | }; 18 | 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /cplusplus/src/instructions/InstructionCpu.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/InstructionCpu.hpp" 5 | 6 | using namespace rabbitizer; 7 | 8 | InstructionCpu::InstructionCpu(uint32_t word, uint32_t vram) : InstructionBase() { 9 | RabbitizerInstruction_init(&this->instr, word, vram); 10 | RabbitizerInstruction_processUniqueId(&this->instr); 11 | } 12 | 13 | InstructionCpu::~InstructionCpu() { 14 | RabbitizerInstruction_destroy(&this->instr); 15 | } 16 | -------------------------------------------------------------------------------- /tables/tools/rs_table_gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -e 7 | 8 | INPUT_FILE=$1 9 | OUTPUT_FILE=$2 10 | 11 | echo "/* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */" > ${OUTPUT_FILE} 12 | echo "/* SPDX-License-Identifier: MIT */" >> ${OUTPUT_FILE} 13 | echo >> ${OUTPUT_FILE} 14 | echo "/* Automatically generated. DO NOT MODIFY */" >> ${OUTPUT_FILE} 15 | 16 | echo >> ${OUTPUT_FILE} 17 | 18 | cpp -P -I include -I tables ${INPUT_FILE} >> ${OUTPUT_FILE} 19 | -------------------------------------------------------------------------------- /rust/src/access_type_enum.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #[repr(u32)] 7 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] 8 | #[allow(non_camel_case_types)] 9 | pub enum AccessType { 10 | INVALID, 11 | BYTE, 12 | SHORT, 13 | WORD, 14 | DOUBLEWORD, 15 | QUADWORD, 16 | FLOAT, 17 | DOUBLEFLOAT, 18 | WORD_LEFT, 19 | WORD_RIGHT, 20 | DOUBLEWORD_LEFT, 21 | DOUBLEWORD_RIGHT, 22 | MAX, 23 | } 24 | -------------------------------------------------------------------------------- /tests/run_instruction_checks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -e 7 | 8 | ./build/tests/c/instruction_checks/jalr.elf 9 | ./build/tests/c/instruction_checks/plain_disassembly.elf 10 | ./build/tests/c/instruction_checks/r3000gte_disasm.elf 11 | ./build/tests/c/instruction_checks/r4000allegrex_disasm.elf 12 | ./build/tests/c/instruction_checks/r4000allegrex_vfpu_disasm.elf 13 | ./build/tests/c/instruction_checks/r5900_disasm.elf 14 | ./build/tests/c/instruction_checks/r5900_trunc_cvt.elf 15 | -------------------------------------------------------------------------------- /include/instructions/RabbitizerInstrCategory.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRCATEGORY_H 5 | #define RABBITIZER_INSTRCATEGORY_H 6 | #pragma once 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | 13 | #include "generated/InstrCategory_enum.h" 14 | 15 | extern const char *const RabbitizerInstrCategory_Names[]; 16 | 17 | RabbitizerInstrCategory RabbitizerInstrCategory_fromStr(const char *name); 18 | 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /tables/templates/c/InstrId_Names_array.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) [RABBITIZER_INSTR_ID_##prefix##_##name] = #name, 5 | 6 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) [RABBITIZER_INSTR_ID_##prefix##_##name] = #altname, 7 | 8 | const char *RabbitizerInstrId_Names[] = { 9 | #include "InstrIds.inc" 10 | }; 11 | 12 | #undef RABBITIZER_DEF_INSTR_ID 13 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 14 | -------------------------------------------------------------------------------- /tables/tables/AccessType.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RAB_DEF_ACCESSTYPE(INVALID) 5 | 6 | RAB_DEF_ACCESSTYPE(BYTE) 7 | RAB_DEF_ACCESSTYPE(SHORT) 8 | RAB_DEF_ACCESSTYPE(WORD) 9 | RAB_DEF_ACCESSTYPE(DOUBLEWORD) 10 | RAB_DEF_ACCESSTYPE(QUADWORD) 11 | RAB_DEF_ACCESSTYPE(FLOAT) 12 | RAB_DEF_ACCESSTYPE(DOUBLEFLOAT) 13 | RAB_DEF_ACCESSTYPE(WORD_LEFT) 14 | RAB_DEF_ACCESSTYPE(WORD_RIGHT) 15 | RAB_DEF_ACCESSTYPE(DOUBLEWORD_LEFT) 16 | RAB_DEF_ACCESSTYPE(DOUBLEWORD_RIGHT) 17 | -------------------------------------------------------------------------------- /include/generated/InstrCategory_enum.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #ifndef InstrCategory_enum_h_automatic 7 | #define InstrCategory_enum_h_automatic 8 | 9 | typedef enum RabbitizerInstrCategory { 10 | RABBITIZER_INSTRCAT_CPU, 11 | RABBITIZER_INSTRCAT_RSP, 12 | RABBITIZER_INSTRCAT_R3000GTE, 13 | RABBITIZER_INSTRCAT_R4000ALLEGREX, 14 | RABBITIZER_INSTRCAT_R5900, 15 | RABBITIZER_INSTRCAT_MAX, 16 | } RabbitizerInstrCategory; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /tables/templates/rust/abi_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RABBITIZER_DEF_ABI(name) name, 9 | 10 | SPECIAL_RS_TAG(repr(u32)) 11 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 12 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 13 | pub enum Abi { 14 | #include "Abi.inc" 15 | 16 | RABBITIZER_DEF_ABI(MAX) 17 | } 18 | 19 | #undef RABBITIZER_DEF_ABI 20 | -------------------------------------------------------------------------------- /rabbitizer/AccessType.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class AccessType: 11 | INVALID: Enum 12 | BYTE: Enum 13 | SHORT: Enum 14 | WORD: Enum 15 | DOUBLEWORD: Enum 16 | QUADWORD: Enum 17 | FLOAT: Enum 18 | DOUBLEFLOAT: Enum 19 | WORD_LEFT: Enum 20 | WORD_RIGHT: Enum 21 | DOUBLEWORD_LEFT: Enum 22 | DOUBLEWORD_RIGHT: Enum 23 | MAX: Enum 24 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstrIdType.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstrIdType.h" 5 | 6 | #include 7 | 8 | #include "generated/InstrIdType_Names_array.h" 9 | 10 | const char *RabInstrIdType_getName(RabInstrIdType idType) { 11 | const char *name; 12 | 13 | assert(idType >= RAB_INSTR_ID_TYPE_ALL_INVALID); 14 | assert(idType < RAB_INSTR_ID_TYPE_ALL_MAX); 15 | 16 | name = RabInstrIdType_Names[idType]; 17 | assert(name != NULL); 18 | 19 | return name; 20 | } 21 | -------------------------------------------------------------------------------- /cplusplus/include/generated/AccessType_enum_class.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #ifndef AccessType_enum_class_hpp_automatic 7 | #define AccessType_enum_class_hpp_automatic 8 | 9 | enum class AccessType { 10 | INVALID, 11 | BYTE, 12 | SHORT, 13 | WORD, 14 | DOUBLEWORD, 15 | QUADWORD, 16 | FLOAT, 17 | DOUBLEFLOAT, 18 | WORD_LEFT, 19 | WORD_RIGHT, 20 | DOUBLEWORD_LEFT, 21 | DOUBLEWORD_RIGHT, 22 | MAX, 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /rabbitizer/TrackedRegisterState.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | 9 | class RegistersTracker: 10 | registerNum: int 11 | 12 | hasLuiValue: bool 13 | luiOffset: int # The offset of last lui which set a value to this register 14 | luiSetOnBranchLikely: bool 15 | 16 | hasGpGot: bool 17 | gpGotOffset: int 18 | 19 | hasLoValue: bool 20 | loOffset: int 21 | dereferenced: bool 22 | dereferenceOffset: int 23 | 24 | value: int 25 | -------------------------------------------------------------------------------- /tables/templates/python/RegCop1N32.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | name: Enum 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VA_ARGS__) 13 | 14 | class RegCop1N32: 15 | #include "registers/RabbitizerRegister_Cop1N32.inc" 16 | 17 | #undef RABBITIZER_DEF_REG_NODOLLAR 18 | #undef RABBITIZER_DEF_REG 19 | -------------------------------------------------------------------------------- /tables/templates/python/RegCop1N64.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | name: Enum 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VA_ARGS__) 13 | 14 | class RegCop1N64: 15 | #include "registers/RabbitizerRegister_Cop1N64.inc" 16 | 17 | #undef RABBITIZER_DEF_REG_NODOLLAR 18 | #undef RABBITIZER_DEF_REG 19 | -------------------------------------------------------------------------------- /tables/templates/python/RegCop1O32.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | name: Enum 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VA_ARGS__) 13 | 14 | class RegCop1O32: 15 | #include "registers/RabbitizerRegister_Cop1O32.inc" 16 | 17 | #undef RABBITIZER_DEF_REG_NODOLLAR 18 | #undef RABBITIZER_DEF_REG 19 | -------------------------------------------------------------------------------- /tables/templates/python/RegGprN32.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | name: Enum 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VA_ARGS__) 13 | 14 | class RegGprN32: 15 | #include "registers/RabbitizerRegister_GprN32.inc" 16 | 17 | #undef RABBITIZER_DEF_REG_NODOLLAR 18 | #undef RABBITIZER_DEF_REG 19 | -------------------------------------------------------------------------------- /tables/templates/python/RegGprO32.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | name: Enum 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VA_ARGS__) 13 | 14 | class RegGprO32: 15 | #include "registers/RabbitizerRegister_GprO32.inc" 16 | 17 | #undef RABBITIZER_DEF_REG_NODOLLAR 18 | #undef RABBITIZER_DEF_REG 19 | -------------------------------------------------------------------------------- /tables/templates/rust/access_type_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RAB_DEF_ACCESSTYPE(name) name, 9 | 10 | SPECIAL_RS_TAG(repr(u32)) 11 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 12 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 13 | pub enum AccessType { 14 | #include "AccessType.inc" 15 | 16 | RAB_DEF_ACCESSTYPE(MAX) 17 | } 18 | 19 | #undef RAB_DEF_ACCESSTYPE 20 | -------------------------------------------------------------------------------- /include/instructions/RabbitizerInstrIdType.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTR_ID_TYPE_H 5 | #define RABBITIZER_INSTR_ID_TYPE_H 6 | #pragma once 7 | 8 | #include "common/Utils.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "generated/InstrIdType_enum.h" 15 | 16 | extern const char *RabInstrIdType_Names[]; 17 | 18 | 19 | CONST NODISCARD RETURNS_NON_NULL 20 | const char *RabInstrIdType_getName(RabInstrIdType idType); 21 | 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tables/tables/instr_id_types/InstrIdType_r3000gte.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, INVALID) 5 | 6 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, NORMAL) 7 | 8 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, SPECIAL) 9 | 10 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, REGIMM) 11 | 12 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, COP0) 13 | 14 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, COP1) 15 | 16 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, COP2) 17 | RABBITIZER_DEF_INSTR_ID_TYPE(R3000GTE, COP2_GTE) 18 | -------------------------------------------------------------------------------- /tables/tools/pyi_table_gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-FileCopyrightText: © 2023-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -e 7 | 8 | INPUT_FILE=$1 9 | OUTPUT_FILE=$2 10 | 11 | echo "#!/usr/bin/env python3" > ${OUTPUT_FILE} 12 | echo >> ${OUTPUT_FILE} 13 | echo "# SPDX-FileCopyrightText: © 2022-2024 Decompollaborate" >> ${OUTPUT_FILE} 14 | echo "# SPDX-License-Identifier: MIT" >> ${OUTPUT_FILE} 15 | echo >> ${OUTPUT_FILE} 16 | echo "# Automatically generated. DO NOT MODIFY" >> ${OUTPUT_FILE} 17 | 18 | echo >> ${OUTPUT_FILE} 19 | 20 | cpp -P -I include -I tables ${INPUT_FILE} >> ${OUTPUT_FILE} 21 | -------------------------------------------------------------------------------- /tables/templates/cplusplus/UniqueId_enum_class.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) \ 5 | prefix##_##name, 6 | 7 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) \ 8 | RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__) 9 | 10 | enum class UniqueId { 11 | #include "InstrIds.inc" 12 | 13 | ALL_MAX = RABBITIZER_DEF_INSTR_ID(r5900, , MAX, ) 14 | }; 15 | 16 | #undef RABBITIZER_DEF_INSTR_ID 17 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 18 | -------------------------------------------------------------------------------- /tables/templates/rust/instr_id_type_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RABBITIZER_DEF_INSTR_ID_TYPE(prefix, name) \ 9 | prefix##_##name, 10 | 11 | SPECIAL_RS_TAG(repr(u32)) 12 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 13 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 14 | pub enum InstrIdType { 15 | #include "InstrIdType.inc" 16 | } 17 | 18 | #undef RABBITIZER_DEF_INSTR_ID_TYPE 19 | -------------------------------------------------------------------------------- /include/generated/InstrCategory_Names_array.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #ifndef InstrCategory_Names_array_h_automatic 7 | #define InstrCategory_Names_array_h_automatic 8 | 9 | const char *const RabbitizerInstrCategory_Names[] = { 10 | [RABBITIZER_INSTRCAT_CPU] = "CPU", 11 | [RABBITIZER_INSTRCAT_RSP] = "RSP", 12 | [RABBITIZER_INSTRCAT_R3000GTE] = "R3000GTE", 13 | [RABBITIZER_INSTRCAT_R4000ALLEGREX] = "R4000ALLEGREX", 14 | [RABBITIZER_INSTRCAT_R5900] = "R5900", 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /tables/templates/c/InstrDescriptor_Descriptors_array.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) [RABBITIZER_INSTR_ID_##prefix##_##name] = { __VA_ARGS__ }, 5 | 6 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__) 7 | 8 | const RabbitizerInstrDescriptor RabbitizerInstrDescriptor_Descriptors[] = { 9 | #include "InstrIds.inc" 10 | }; 11 | 12 | #undef RABBITIZER_DEF_INSTR_ID 13 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 14 | -------------------------------------------------------------------------------- /tables/templates/rust/instr_category_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RABBITIZER_DEF_INSTR_CATEGORY(name) name, 9 | 10 | SPECIAL_RS_TAG(repr(u32)) 11 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 12 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 13 | pub enum InstrCategory { 14 | #include "InstrCategory.inc" 15 | 16 | RABBITIZER_DEF_INSTR_CATEGORY(MAX) 17 | } 18 | 19 | #undef RABBITIZER_DEF_INSTR_CATEGORY 20 | -------------------------------------------------------------------------------- /rabbitizer/Utils.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | 9 | class Utils: 10 | @staticmethod 11 | def from2Complement(number: int, bits: int) -> int: ... 12 | 13 | @staticmethod 14 | def escapeString(src: str) -> str: ... 15 | 16 | @staticmethod 17 | def floatRepr_32From16(hex_repr: int) -> int: 18 | """ 19 | Converts an unsigned 16 bits value representing a half precision 20 | float to a unsigned 32 bits value representing a single precision 21 | float. 22 | """ 23 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_AccessType.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "instructions/RabbitizerAccessType.h" 6 | 7 | 8 | #define RAB_DEF_ACCESSTYPE(name) { "AccessType", #name , RAB_ACCESSTYPE_##name, false, NULL }, 9 | 10 | RabbitizerEnumMetadata rabbitizer_enum_AccessType_enumvalues[] = { 11 | #include "tables/AccessType.inc" 12 | 13 | RAB_DEF_ACCESSTYPE(MAX) 14 | 15 | { 0 }, 16 | }; 17 | 18 | #undef RAB_DEF_ACCESSTYPE 19 | 20 | 21 | static PyMethodDef rabbitizer_enum_AccessType_methods[] = { 22 | { 0 }, 23 | }; 24 | 25 | DEF_ENUM(AccessType, "") 26 | -------------------------------------------------------------------------------- /tables/tables/instr_id_types/InstrIdType_rsp.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, INVALID) 5 | 6 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, NORMAL) 7 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, NORMAL_LWC2) 8 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, NORMAL_SWC2) 9 | 10 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, SPECIAL) 11 | 12 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, REGIMM) 13 | 14 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, COP0) 15 | 16 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, COP1) 17 | 18 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, COP2) 19 | RABBITIZER_DEF_INSTR_ID_TYPE(RSP, COP2_VU) 20 | -------------------------------------------------------------------------------- /tables/templates/rust/instr_suffix_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RAB_DEF_INSTRSUFFIX(prefix, name) prefix##_##name, 9 | 10 | SPECIAL_RS_TAG(repr(u32)) 11 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 12 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 13 | pub enum InstrSuffix { 14 | RAB_DEF_INSTRSUFFIX(ALL, NONE) 15 | 16 | #include "InstrSuffix.inc" 17 | 18 | RAB_DEF_INSTRSUFFIX(ALL, MAX) 19 | } 20 | 21 | #undef RAB_DEF_INSTRSUFFIX 22 | -------------------------------------------------------------------------------- /tables/templates/rust/operand_type_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RAB_DEF_OPERAND(prefix, operand) \ 9 | prefix##_##operand, 10 | 11 | SPECIAL_RS_TAG(repr(u32)) 12 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 13 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 14 | pub enum OperandType { 15 | RAB_DEF_OPERAND(ALL, INVALID) 16 | 17 | #include "OperandTypes.inc" 18 | 19 | RAB_DEF_OPERAND(ALL, MAX) 20 | } 21 | 22 | #undef RAB_DEF_OPERAND 23 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_InstrIdType.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "instructions/RabbitizerInstrIdType.h" 6 | 7 | 8 | #define RABBITIZER_DEF_INSTR_ID_TYPE(prefix, name) \ 9 | { "InstrIdType", #prefix "_" #name, RAB_INSTR_ID_TYPE_##prefix##_##name, false, NULL }, 10 | 11 | RabbitizerEnumMetadata rabbitizer_enum_InstrIdType_enumvalues[] = { 12 | #include "tables/InstrIdType.inc" 13 | { 0 }, 14 | }; 15 | 16 | #undef RABBITIZER_DEF_INSTR_ID_TYPE 17 | 18 | static PyMethodDef rabbitizer_enum_InstrIdType_methods[] = { 19 | { 0 }, 20 | }; 21 | 22 | DEF_ENUM(InstrIdType, "") 23 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_TrinaryValue.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "common/Utils.h" 6 | 7 | #define RAB_DEF_TRINARYVALUE(name) { "TrinaryValue", #name , RAB_TRINARY_VAL_##name, false, NULL }, 8 | 9 | RabbitizerEnumMetadata rabbitizer_enum_TrinaryValue_enumvalues[] = { 10 | RAB_DEF_TRINARYVALUE(NONE) 11 | RAB_DEF_TRINARYVALUE(FALSE) 12 | RAB_DEF_TRINARYVALUE(TRUE) 13 | 14 | { 0 }, 15 | }; 16 | 17 | #undef RAB_DEF_TRINARYVALUE 18 | 19 | 20 | static PyMethodDef rabbitizer_enum_TrinaryValue_methods[] = { 21 | { 0 }, 22 | }; 23 | 24 | DEF_ENUM(TrinaryValue, "") 25 | -------------------------------------------------------------------------------- /tables/templates/c/InstrId_enum.table.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) \ 5 | RABBITIZER_INSTR_ID_##prefix##_##name, 6 | 7 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) \ 8 | RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__) 9 | 10 | typedef enum RabbitizerInstrId { 11 | #include "InstrIds.inc" 12 | 13 | RABBITIZER_INSTR_ID_ALL_LAST, 14 | RABBITIZER_INSTR_ID_ALL_MAX = RABBITIZER_INSTR_ID_ALL_LAST - 1 15 | } RabbitizerInstrId; 16 | 17 | #undef RABBITIZER_DEF_INSTR_ID 18 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 19 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstrCategory.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstrCategory.h" 5 | 6 | #include 7 | 8 | #include "generated/InstrCategory_Names_array.h" 9 | 10 | RabbitizerInstrCategory RabbitizerInstrCategory_fromStr(const char *name) { 11 | if (name == NULL) { 12 | return (RabbitizerInstrCategory)-2; 13 | } 14 | 15 | for (RabbitizerInstrCategory i = 0; i < RABBITIZER_INSTRCAT_MAX; i++) { 16 | if (strcmp(RabbitizerInstrCategory_Names[i], name) == 0) { 17 | return i; 18 | } 19 | } 20 | 21 | return (RabbitizerInstrCategory)-1; 22 | } 23 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | IndentWidth: 4 2 | Language: Cpp 3 | UseTab: Never 4 | ColumnLimit: 120 5 | PointerAlignment: Right 6 | BreakBeforeBraces: Attach 7 | SpaceAfterCStyleCast: false 8 | Cpp11BracedListStyle: false 9 | IndentCaseLabels: true 10 | BinPackArguments: true 11 | BinPackParameters: true 12 | AlignAfterOpenBracket: Align 13 | AlignOperands: true 14 | BreakBeforeTernaryOperators: true 15 | BreakBeforeBinaryOperators: None 16 | AllowShortBlocksOnASingleLine: true 17 | AllowShortIfStatementsOnASingleLine: false 18 | AllowShortLoopsOnASingleLine: false 19 | AllowShortCaseLabelsOnASingleLine: false 20 | AllowShortFunctionsOnASingleLine: false 21 | AlignEscapedNewlines: Left 22 | AlignTrailingComments: true 23 | SortIncludes: false 24 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionR5900.h" 5 | 6 | void RabbitizerInstructionR5900_init(RabbitizerInstruction *self, uint32_t word, uint32_t vram) { 7 | RabbitizerInstruction_init(self, word, vram); 8 | 9 | self->uniqueId = RABBITIZER_INSTR_ID_r5900_INVALID; 10 | self->descriptor = &RabbitizerInstrDescriptor_Descriptors[self->uniqueId]; 11 | 12 | self->category = RABBITIZER_INSTRCAT_R5900; 13 | } 14 | 15 | void RabbitizerInstructionR5900_destroy(RabbitizerInstruction *self) { 16 | RabbitizerInstruction_destroy(self); 17 | } 18 | -------------------------------------------------------------------------------- /tables/tables/instr_id/rsp/rsp_cop0.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | // OP rt, cop0d 5 | RABBITIZER_DEF_INSTR_ID( 6 | rsp, 0x00, mfc0, 7 | .operands={RAB_OPERAND_rsp_rt, RAB_OPERAND_rsp_cop0d}, 8 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 9 | .modifiesRt=true, 10 | .notEmittedByCompilers=true 11 | ) // Move word From CP0 12 | RABBITIZER_DEF_INSTR_ID( 13 | rsp, 0x04, mtc0, 14 | .operands={RAB_OPERAND_rsp_rt, RAB_OPERAND_rsp_cop0d}, 15 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 16 | .readsRt=true, 17 | .notEmittedByCompilers=true 18 | ) // Move word to CP0 19 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: 'readability-*,-readability-magic-numbers,clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-optin.performance.Padding,bugprone*,-bugprone-branch-clone,modernize*,performance*,portability*,diagnostic-*,analyzer-*,misc*,-misc-no-recursion' 2 | WarningsAsErrors: '' 3 | HeaderFilterRegex: '(src|include)\/.*\.h$' 4 | FormatStyle: 'file' 5 | CheckOptions: 6 | # Require argument names to match exactly (instead of allowing a name to be a prefix/suffix of another) 7 | # Note: 'true' is expected by clang-tidy 12+ but '1' is used for compatibility with older versions 8 | - key: readability-inconsistent-declaration-parameter-name.Strict 9 | value: 1 10 | -------------------------------------------------------------------------------- /include/instructions/RabbitizerInstrId.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRID_H 5 | #define RABBITIZER_INSTRID_H 6 | #pragma once 7 | 8 | #include 9 | 10 | #include "common/Utils.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #include "generated/InstrId_enum.h" 17 | 18 | extern const char *RabbitizerInstrId_Names[]; 19 | 20 | 21 | CONST NODISCARD 22 | bool RabbitizerInstrId_isValid(RabbitizerInstrId uniqueId); 23 | 24 | CONST NODISCARD RETURNS_NON_NULL 25 | const char *RabbitizerInstrId_getOpcodeName(RabbitizerInstrId uniqueId); 26 | 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstructionR3000GTE/RabbitizerInstructionR3000GTE.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionR3000GTE.h" 5 | 6 | void RabbitizerInstructionR3000GTE_init(RabbitizerInstruction *self, uint32_t word, uint32_t vram) { 7 | RabbitizerInstruction_init(self, word, vram); 8 | 9 | self->uniqueId = RABBITIZER_INSTR_ID_r3000gte_INVALID; 10 | self->descriptor = &RabbitizerInstrDescriptor_Descriptors[self->uniqueId]; 11 | 12 | self->category = RABBITIZER_INSTRCAT_R3000GTE; 13 | } 14 | 15 | void RabbitizerInstructionR3000GTE_destroy(RabbitizerInstruction *self) { 16 | RabbitizerInstruction_destroy(self); 17 | } 18 | -------------------------------------------------------------------------------- /tables/templates/python/InstrId.tablepyi.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | from __future__ import annotations 5 | 6 | from .Enum import Enum 7 | 8 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) \ 9 | prefix##_##name: Enum 10 | 11 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) \ 12 | RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__) 13 | 14 | #define INSTRID_AVOID_USERDEF 15 | 16 | class InstrId: 17 | #include "InstrIds.inc" 18 | 19 | RABBITIZER_DEF_INSTR_ID(ALL, , MAX) 20 | 21 | #undef INSTRID_AVOID_USERDEF 22 | 23 | #undef RABBITIZER_DEF_INSTR_ID 24 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 25 | -------------------------------------------------------------------------------- /include/instructions/RabbitizerOperandType.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_OPERAND_TYPE_H 5 | #define RABBITIZER_OPERAND_TYPE_H 6 | #pragma once 7 | 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "generated/OperandType_enum.h" 15 | 16 | struct RabbitizerInstruction; 17 | 18 | typedef size_t (*OperandCallback)(const struct RabbitizerInstruction *self, char *dst, const char *immOverride, size_t immOverrideLength); 19 | 20 | extern const OperandCallback instrOpercandCallbacks[]; 21 | 22 | #include "generated/OperandType_function_declarations.h" 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_OperandType.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "instructions/RabbitizerOperandType.h" 6 | 7 | 8 | #define RAB_DEF_OPERAND(prefix, operand) { "OperandType", #prefix "_" #operand, RAB_OPERAND_##prefix##_##operand, false, NULL }, 9 | 10 | RabbitizerEnumMetadata rabbitizer_enum_OperandType_enumvalues[] = { 11 | RAB_DEF_OPERAND(ALL, INVALID) 12 | 13 | #include "tables/OperandTypes.inc" 14 | 15 | RAB_DEF_OPERAND(ALL, MAX) 16 | 17 | { 0 }, 18 | }; 19 | 20 | #undef RAB_DEF_OPERAND 21 | 22 | static PyMethodDef rabbitizer_enum_OperandType_methods[] = { 23 | { 0 }, 24 | }; 25 | 26 | DEF_ENUM(OperandType, "") 27 | -------------------------------------------------------------------------------- /tests/asm/r4000allegrex/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: © 2024 Decompollaborate 2 | # SPDX-License-Identifier: MIT 3 | 4 | TARGETS := allegrex_instrs_pspsnc.dump.s allegrex_vfpu_pspsnc.dump.s allegrex_vfpu_expecteds_pspsnc.dump.s 5 | 6 | 7 | COMPILER_PATH ?= 8 | WINE ?= wine 9 | 10 | ifeq ($(COMPILER_PATH),) 11 | $(error Please set 'COMPILER_PATH' to the path where the SN toolchain is located) 12 | endif 13 | 14 | CC := $(WINE) "$(COMPILER_PATH)/pspsnc.exe" 15 | OBJDUMP := $(WINE) "${COMPILER_PATH}/snbin.exe" 16 | 17 | COMP_FLAGS := -O2 -g 18 | 19 | 20 | all: $(TARGETS) 21 | 22 | 23 | %_pspsnc.dump.s: %.s 24 | $(CC) -c $(COMP_FLAGS) -o $(<:.s=_pspsnc.o) $< 25 | $(OBJDUMP) -d $(<:.s=_pspsnc.o) > $@ 26 | dos2unix $@ 27 | 28 | -------------------------------------------------------------------------------- /rabbitizer/Enum.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | 9 | class Enum: 10 | name: str 11 | value: int 12 | 13 | def __init__(self, enumType: str, name: str, value: int) -> None: ... 14 | 15 | def __reduce__(self) -> tuple: ... 16 | 17 | def __lt__(self, __o: object) -> bool: ... 18 | def __le__(self, __o: object) -> bool: ... 19 | def __eq__(self, __o: object) -> bool: ... 20 | def __gt__(self, __o: object) -> bool: ... 21 | def __ge__(self, __o: object) -> bool: ... 22 | 23 | def __hash__(self) -> int: ... 24 | 25 | def __repr__(self) -> str: ... 26 | def __str__(self) -> str: ... 27 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstructionR4000Allegrex/RabbitizerInstructionR4000Allegrex.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionR4000Allegrex.h" 5 | 6 | void RabbitizerInstructionR4000Allegrex_init(RabbitizerInstruction *self, uint32_t word, uint32_t vram) { 7 | RabbitizerInstruction_init(self, word, vram); 8 | 9 | self->uniqueId = RABBITIZER_INSTR_ID_r4000allegrex_INVALID; 10 | self->descriptor = &RabbitizerInstrDescriptor_Descriptors[self->uniqueId]; 11 | 12 | self->category = RABBITIZER_INSTRCAT_R4000ALLEGREX; 13 | } 14 | 15 | void RabbitizerInstructionR4000Allegrex_destroy(RabbitizerInstruction *self) { 16 | RabbitizerInstruction_destroy(self); 17 | } 18 | -------------------------------------------------------------------------------- /include/generated/AccessType_enum.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* Automatically generated. DO NOT MODIFY */ 5 | 6 | #ifndef AccessType_enum_h_automatic 7 | #define AccessType_enum_h_automatic 8 | 9 | typedef enum RabbitizerAccessType { 10 | RAB_ACCESSTYPE_INVALID, 11 | RAB_ACCESSTYPE_BYTE, 12 | RAB_ACCESSTYPE_SHORT, 13 | RAB_ACCESSTYPE_WORD, 14 | RAB_ACCESSTYPE_DOUBLEWORD, 15 | RAB_ACCESSTYPE_QUADWORD, 16 | RAB_ACCESSTYPE_FLOAT, 17 | RAB_ACCESSTYPE_DOUBLEFLOAT, 18 | RAB_ACCESSTYPE_WORD_LEFT, 19 | RAB_ACCESSTYPE_WORD_RIGHT, 20 | RAB_ACCESSTYPE_DOUBLEWORD_LEFT, 21 | RAB_ACCESSTYPE_DOUBLEWORD_RIGHT, 22 | RAB_ACCESSTYPE_MAX, 23 | } RabbitizerAccessType; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /.github/workflows/isolated_python_build.yml: -------------------------------------------------------------------------------- 1 | name: Build Python package in isolated environment 2 | 3 | # Build on every branch push, tag push, and pull request change: 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | buildstuff: 8 | name: Build 9 | runs-on: ubuntu-22.04 10 | 11 | steps: 12 | - name: Checkout reposistory 13 | uses: actions/checkout@main 14 | 15 | - name: Install dependencies 16 | run: sudo apt update && sudo apt install -y python3-venv 17 | 18 | - name: Setup venv 19 | run: python3 -m venv .venv 20 | 21 | - name: Install build module 22 | run: | 23 | . .venv/bin/activate 24 | python3 -m pip install build -U 25 | 26 | - name: Build 27 | run: | 28 | . .venv/bin/activate 29 | python3 -m build 30 | -------------------------------------------------------------------------------- /tables/tables/instr_id/rsp/rsp_cop2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | // OP cop2t, vd[index] 5 | RABBITIZER_DEF_INSTR_ID( 6 | rsp, 0x00, mfc2, 7 | .operands={RAB_OPERAND_rsp_cop2t, RAB_OPERAND_rsp_vs_index} 8 | ) 9 | RABBITIZER_DEF_INSTR_ID( 10 | rsp, 0x04, mtc2, 11 | .operands={RAB_OPERAND_rsp_cop2t, RAB_OPERAND_rsp_vs_index} 12 | ) 13 | 14 | // OP rt, cop2cd 15 | RABBITIZER_DEF_INSTR_ID( 16 | rsp, 0x02, cfc2, 17 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_rsp_cop2cd}, 18 | .modifiesRt=true 19 | ) 20 | RABBITIZER_DEF_INSTR_ID( 21 | rsp, 0x06, ctc2, 22 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_rsp_cop2cd}, 23 | .readsRt=true 24 | ) 25 | -------------------------------------------------------------------------------- /include/analysis/RabbitizerLoPairingInfo.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_LO_PAIRING_INFO_H 5 | #define RABBITIZER_LO_PAIRING_INFO_H 6 | #pragma once 7 | 8 | #include 9 | 10 | #include "common/Utils.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | typedef struct RabbitizerLoPairingInfo { 18 | int instrOffset; 19 | int64_t value; // could be either an unsigned 32 bits number or a signed one, so use 64 bits to ensure it fits 20 | bool shouldProcess; 21 | bool isGpRel; 22 | bool isGpGot; 23 | } RabbitizerLoPairingInfo; 24 | 25 | 26 | NON_NULL(1) 27 | void RabbitizerLoPairingInfo_Init(RabbitizerLoPairingInfo *self); 28 | 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/instructions/RabbitizerInstrSuffix.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRSUFFIX_H 5 | #define RABBITIZER_INSTRSUFFIX_H 6 | #pragma once 7 | 8 | #include "common/Utils.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | struct RabbitizerInstruction; 16 | 17 | #include "generated/InstrSuffix_enum.h" 18 | 19 | CONST NODISCARD NON_NULL(1) 20 | size_t RabbitizerInstrSuffix_getSizeForBuffer(const struct RabbitizerInstruction *self, RabbitizerInstrSuffix instrSuffix); 21 | 22 | CONST NODISCARD NON_NULL(1, 2) 23 | size_t RabbitizerInstrSuffix_processSuffix(const struct RabbitizerInstruction *self, char *dst, RabbitizerInstrSuffix instrSuffix); 24 | 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/InstructionR3000GTE.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRUCTION_R3000GTE_HPP 5 | #define RABBITIZER_INSTRUCTION_R3000GTE_HPP 6 | #pragma once 7 | 8 | #include "InstructionBase.hpp" 9 | 10 | 11 | namespace rabbitizer { 12 | class InstructionR3000GTE : public InstructionBase { 13 | public: 14 | InstructionR3000GTE(uint32_t word, uint32_t vram); 15 | virtual ~InstructionR3000GTE(); 16 | 17 | uint8_t GetR3000GTE_gbg() const; 18 | 19 | uint8_t GetR3000GTE_sf() const; 20 | uint8_t GetR3000GTE_mx() const; 21 | uint8_t GetR3000GTE_v() const; 22 | uint8_t GetR3000GTE_cv() const; 23 | uint8_t GetR3000GTE_lm() const; 24 | }; 25 | }; 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /rabbitizer/RegGprN32.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class RegGprN32: 11 | zero: Enum 12 | at: Enum 13 | v0: Enum 14 | v1: Enum 15 | a0: Enum 16 | a1: Enum 17 | a2: Enum 18 | a3: Enum 19 | a4: Enum 20 | a5: Enum 21 | a6: Enum 22 | a7: Enum 23 | t0: Enum 24 | t1: Enum 25 | t2: Enum 26 | t3: Enum 27 | s0: Enum 28 | s1: Enum 29 | s2: Enum 30 | s3: Enum 31 | s4: Enum 32 | s5: Enum 33 | s6: Enum 34 | s7: Enum 35 | t8: Enum 36 | t9: Enum 37 | k0: Enum 38 | k1: Enum 39 | gp: Enum 40 | sp: Enum 41 | fp: Enum 42 | ra: Enum 43 | -------------------------------------------------------------------------------- /rabbitizer/RegGprO32.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class RegGprO32: 11 | zero: Enum 12 | at: Enum 13 | v0: Enum 14 | v1: Enum 15 | a0: Enum 16 | a1: Enum 17 | a2: Enum 18 | a3: Enum 19 | t0: Enum 20 | t1: Enum 21 | t2: Enum 22 | t3: Enum 23 | t4: Enum 24 | t5: Enum 25 | t6: Enum 26 | t7: Enum 27 | s0: Enum 28 | s1: Enum 29 | s2: Enum 30 | s3: Enum 31 | s4: Enum 32 | s5: Enum 33 | s6: Enum 34 | s7: Enum 35 | t8: Enum 36 | t9: Enum 37 | k0: Enum 38 | k1: Enum 39 | gp: Enum 40 | sp: Enum 41 | fp: Enum 42 | ra: Enum 43 | -------------------------------------------------------------------------------- /rabbitizer/__init__.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | __version_info__: tuple[int, int, int] 9 | __version__: str 10 | __author__: str 11 | 12 | from .Utils import * 13 | 14 | from .Enum import * 15 | from .InstrCategory import * 16 | from .InstrId import * 17 | from .InstrIdType import * 18 | from .OperandType import * 19 | from .AccessType import * 20 | 21 | from .RegGprO32 import * 22 | from .RegGprN32 import * 23 | 24 | from .RegCop1O32 import * 25 | from .RegCop1N32 import * 26 | from .RegCop1N64 import * 27 | 28 | from .Abi import * 29 | 30 | from .TrinaryValue import * 31 | 32 | from .Config import * 33 | 34 | from .rabbitizer import * 35 | 36 | from .JrRegData import * 37 | from .RegistersTracker import * 38 | -------------------------------------------------------------------------------- /rabbitizer/RegCop1N64.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class RegCop1N64: 11 | fv0: Enum 12 | ft12: Enum 13 | fv1: Enum 14 | ft13: Enum 15 | ft0: Enum 16 | ft1: Enum 17 | ft2: Enum 18 | ft3: Enum 19 | ft4: Enum 20 | ft5: Enum 21 | ft6: Enum 22 | ft7: Enum 23 | fa0: Enum 24 | fa1: Enum 25 | fa2: Enum 26 | fa3: Enum 27 | fa4: Enum 28 | fa5: Enum 29 | fa6: Enum 30 | fa7: Enum 31 | ft8: Enum 32 | ft9: Enum 33 | ft10: Enum 34 | ft11: Enum 35 | fs0: Enum 36 | fs1: Enum 37 | fs2: Enum 38 | fs3: Enum 39 | fs4: Enum 40 | fs5: Enum 41 | fs6: Enum 42 | fs7: Enum 43 | -------------------------------------------------------------------------------- /rabbitizer/RegCop1N32.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class RegCop1N32: 11 | fv0: Enum 12 | ft14: Enum 13 | fv1: Enum 14 | ft15: Enum 15 | ft0: Enum 16 | ft1: Enum 17 | ft2: Enum 18 | ft3: Enum 19 | ft4: Enum 20 | ft5: Enum 21 | ft6: Enum 22 | ft7: Enum 23 | fa0: Enum 24 | fa1: Enum 25 | fa2: Enum 26 | fa3: Enum 27 | fa4: Enum 28 | fa5: Enum 29 | fa6: Enum 30 | fa7: Enum 31 | fs0: Enum 32 | ft8: Enum 33 | fs1: Enum 34 | ft9: Enum 35 | fs2: Enum 36 | ft10: Enum 37 | fs3: Enum 38 | ft11: Enum 39 | fs4: Enum 40 | ft12: Enum 41 | fs5: Enum 42 | ft13: Enum 43 | -------------------------------------------------------------------------------- /tables/tables/instr_id_types/InstrIdType_cpu.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, INVALID) 5 | 6 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, NORMAL) 7 | 8 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, SPECIAL) 9 | 10 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, REGIMM) 11 | 12 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP0) 13 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP0_BC0) 14 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP0_TLB) 15 | 16 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP1) 17 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP1_BC1) 18 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP1_FPUS) 19 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP1_FPUD) 20 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP1_FPUW) 21 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP1_FPUL) 22 | 23 | RABBITIZER_DEF_INSTR_ID_TYPE(CPU, COP2) 24 | -------------------------------------------------------------------------------- /rabbitizer/enums/registers/rabbitizer_enum_GprN32.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums/enums_utils.h" 5 | #include "instructions/RabbitizerRegister.h" 6 | 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | { "RegGprN32", #name, RABBITIZER_REG_##prefix##_##name, false, NULL }, 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VARGS__) 13 | 14 | RabbitizerEnumMetadata rabbitizer_enum_RegGprN32_enumvalues[] = { 15 | #include "tables/registers/RabbitizerRegister_GprN32.inc" 16 | 17 | { 0 }, 18 | }; 19 | 20 | #undef RABBITIZER_DEF_REG 21 | #undef RABBITIZER_DEF_REG_NODOLLAR 22 | 23 | 24 | static PyMethodDef rabbitizer_enum_RegGprN32_methods[] = { 25 | { 0 }, 26 | }; 27 | 28 | DEF_ENUM(RegGprN32, "") 29 | -------------------------------------------------------------------------------- /rabbitizer/enums/registers/rabbitizer_enum_GprO32.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums/enums_utils.h" 5 | #include "instructions/RabbitizerRegister.h" 6 | 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | { "RegGprO32", #name, RABBITIZER_REG_##prefix##_##name, false, NULL }, 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VARGS__) 13 | 14 | RabbitizerEnumMetadata rabbitizer_enum_RegGprO32_enumvalues[] = { 15 | #include "tables/registers/RabbitizerRegister_GprO32.inc" 16 | 17 | { 0 }, 18 | }; 19 | 20 | #undef RABBITIZER_DEF_REG 21 | #undef RABBITIZER_DEF_REG_NODOLLAR 22 | 23 | 24 | static PyMethodDef rabbitizer_enum_RegGprO32_methods[] = { 25 | { 0 }, 26 | }; 27 | 28 | DEF_ENUM(RegGprO32, "") 29 | -------------------------------------------------------------------------------- /rabbitizer/RegCop1O32.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Automatically generated. DO NOT MODIFY 7 | 8 | from __future__ import annotations 9 | from .Enum import Enum 10 | class RegCop1O32: 11 | fv0: Enum 12 | fv0f: Enum 13 | fv1: Enum 14 | fv1f: Enum 15 | ft0: Enum 16 | ft0f: Enum 17 | ft1: Enum 18 | ft1f: Enum 19 | ft2: Enum 20 | ft2f: Enum 21 | ft3: Enum 22 | ft3f: Enum 23 | fa0: Enum 24 | fa0f: Enum 25 | fa1: Enum 26 | fa1f: Enum 27 | ft4: Enum 28 | ft4f: Enum 29 | ft5: Enum 30 | ft5f: Enum 31 | fs0: Enum 32 | fs0f: Enum 33 | fs1: Enum 34 | fs1f: Enum 35 | fs2: Enum 36 | fs2f: Enum 37 | fs3: Enum 38 | fs3f: Enum 39 | fs4: Enum 40 | fs4f: Enum 41 | fs5: Enum 42 | fs5f: Enum 43 | -------------------------------------------------------------------------------- /rabbitizer/enums/registers/rabbitizer_enum_Cop1N32.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums/enums_utils.h" 5 | #include "instructions/RabbitizerRegister.h" 6 | 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | { "RegCop1N32", #name, RABBITIZER_REG_##prefix##_##name, false, NULL }, 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VARGS__) 13 | 14 | RabbitizerEnumMetadata rabbitizer_enum_RegCop1N32_enumvalues[] = { 15 | #include "tables/registers/RabbitizerRegister_Cop1N32.inc" 16 | 17 | { 0 }, 18 | }; 19 | 20 | #undef RABBITIZER_DEF_REG 21 | #undef RABBITIZER_DEF_REG_NODOLLAR 22 | 23 | 24 | static PyMethodDef rabbitizer_enum_RegCop1N32_methods[] = { 25 | { 0 }, 26 | }; 27 | 28 | DEF_ENUM(RegCop1N32, "") 29 | -------------------------------------------------------------------------------- /rabbitizer/enums/registers/rabbitizer_enum_Cop1N64.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums/enums_utils.h" 5 | #include "instructions/RabbitizerRegister.h" 6 | 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | { "RegCop1N64", #name, RABBITIZER_REG_##prefix##_##name, false, NULL }, 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VARGS__) 13 | 14 | RabbitizerEnumMetadata rabbitizer_enum_RegCop1N64_enumvalues[] = { 15 | #include "tables/registers/RabbitizerRegister_Cop1N64.inc" 16 | 17 | { 0 }, 18 | }; 19 | 20 | #undef RABBITIZER_DEF_REG 21 | #undef RABBITIZER_DEF_REG_NODOLLAR 22 | 23 | 24 | static PyMethodDef rabbitizer_enum_RegCop1N64_methods[] = { 25 | { 0 }, 26 | }; 27 | 28 | DEF_ENUM(RegCop1N64, "") 29 | -------------------------------------------------------------------------------- /rabbitizer/enums/registers/rabbitizer_enum_Cop1O32.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums/enums_utils.h" 5 | #include "instructions/RabbitizerRegister.h" 6 | 7 | 8 | #define RABBITIZER_DEF_REG(prefix, name, numeric, ...) \ 9 | { "RegCop1O32", #name, RABBITIZER_REG_##prefix##_##name, false, NULL }, 10 | 11 | #define RABBITIZER_DEF_REG_NODOLLAR(prefix, name, numeric, ...) \ 12 | RABBITIZER_DEF_REG(prefix, name, numeric, __VARGS__) 13 | 14 | RabbitizerEnumMetadata rabbitizer_enum_RegCop1O32_enumvalues[] = { 15 | #include "tables/registers/RabbitizerRegister_Cop1O32.inc" 16 | 17 | { 0 }, 18 | }; 19 | 20 | #undef RABBITIZER_DEF_REG 21 | #undef RABBITIZER_DEF_REG_NODOLLAR 22 | 23 | 24 | static PyMethodDef rabbitizer_enum_RegCop1O32_methods[] = { 25 | { 0 }, 26 | }; 27 | 28 | DEF_ENUM(RegCop1O32, "") 29 | -------------------------------------------------------------------------------- /tables/tools/c_table_gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -e 7 | 8 | INPUT_FILE=$1 9 | OUTPUT_FILE=$2 10 | HEADER_GUARD_BAD=$3 11 | 12 | # Change dots to underscores 13 | HEADER_GUARD=$(echo ${HEADER_GUARD_BAD} | sed 's/\./_/g') 14 | 15 | echo "/* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */" > ${OUTPUT_FILE} 16 | echo "/* SPDX-License-Identifier: MIT */" >> ${OUTPUT_FILE} 17 | echo >> ${OUTPUT_FILE} 18 | echo "/* Automatically generated. DO NOT MODIFY */" >> ${OUTPUT_FILE} 19 | echo >> ${OUTPUT_FILE} 20 | 21 | echo "#ifndef ${HEADER_GUARD}_automatic" >> ${OUTPUT_FILE} 22 | echo "#define ${HEADER_GUARD}_automatic" >> ${OUTPUT_FILE} 23 | 24 | echo >> ${OUTPUT_FILE} 25 | 26 | cpp -P -I tables ${INPUT_FILE} >> ${OUTPUT_FILE} 27 | 28 | echo >> ${OUTPUT_FILE} 29 | 30 | echo "#endif" >> ${OUTPUT_FILE} 31 | -------------------------------------------------------------------------------- /rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let c_paths: Vec = glob::glob("src/**/*.c") 3 | .unwrap() 4 | .filter_map(|g| g.ok()) 5 | .collect(); 6 | let h_paths: Vec = glob::glob("include/**/*.h") 7 | .unwrap() 8 | .filter_map(|g| g.ok()) 9 | .collect(); 10 | let tables_paths: Vec = glob::glob("tables/tables/**/*.inc") 11 | .unwrap() 12 | .filter_map(|g| g.ok()) 13 | .collect(); 14 | 15 | for path in c_paths.iter().chain(&h_paths).chain(&tables_paths) { 16 | println!("cargo:rerun-if-changed={}", path.to_string_lossy()); 17 | } 18 | 19 | assert!(!c_paths.is_empty()); 20 | 21 | cc::Build::new() 22 | .files(c_paths) 23 | .include("include") 24 | .include("tables") 25 | .warnings(false) 26 | .compile("rabbitizer"); 27 | } 28 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_regimm.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26----------20-------16------------------------------0 6 | | = REGIMM | | rt | | 7 | ------6---------------------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // The other instructions are implemented using the main CPU table 17 | -------------------------------------------------------------------------------- /tables/templates/rust/instr_id_enum.tablers.template: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #define HASH # 5 | #define HASH_EXPANSION(x) x 6 | #define SPECIAL_RS_TAG(...) HASH_EXPANSION(HASH)[__VA_ARGS__] 7 | 8 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) \ 9 | prefix##_##name, 10 | 11 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) \ 12 | RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__) 13 | 14 | SPECIAL_RS_TAG(repr(u32)) 15 | SPECIAL_RS_TAG(derive(Debug, Copy, Clone, Hash, PartialEq, Eq)) 16 | SPECIAL_RS_TAG(allow(non_camel_case_types)) 17 | pub enum InstrId { 18 | #include "InstrIds.inc" 19 | } 20 | 21 | impl InstrId { 22 | pub const ALL_MAX: InstrId = InstrId::r5900_MAX; 23 | } 24 | 25 | #undef RABBITIZER_DEF_INSTR_ID 26 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 27 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop0_bc0.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21-20------16------------------------------0 6 | | = COP0 | BC0 | fmt | | 7 | ------6----------5----------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // The other instructions are implemented using the main CPU table 17 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop1_bc1.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21-20------16------------------------------0 6 | | = COP1 | BC1 | fmt | | 7 | ------6----------5----------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // The other instructions are implemented using the main CPU table 17 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 2 | # SPDX-License-Identifier: MIT 3 | 4 | [package] 5 | name = "rabbitizer" 6 | # Version should be synced with include/common/RabbitizerVersion.h 7 | version = "1.14.3" 8 | edition = "2021" 9 | authors = ["Anghelo Carvajal "] 10 | description = "MIPS instruction decoder" 11 | readme = "README.md" 12 | repository = "https://github.com/Decompollaborate/rabbitizer" 13 | license-file = "LICENSE" 14 | rust-version = "1.66.1" 15 | keywords = ["MIPS", "decoder"] 16 | build = "rust/build.rs" 17 | include = ["/rust/src", "/rust/build.rs", "/src", "/include", "/tables"] 18 | 19 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 20 | 21 | [lib] 22 | path = "rust/src/lib.rs" 23 | 24 | [dependencies] 25 | num_enum = "0.5.7" 26 | 27 | [build-dependencies] 28 | cc = "1.0.78" 29 | glob = "0.3.0" 30 | -------------------------------------------------------------------------------- /tests/asm/r3000gte/gte_instrs.s: -------------------------------------------------------------------------------- 1 | .set noreorder 2 | 3 | .section .text 4 | 5 | .global gte_rtps_b 6 | gte_rtps_b: 7 | RTPS 8 | jr $ra 9 | nop 10 | 11 | .global gte_macros 12 | gte_macros: 13 | rtv0 14 | rtv1 15 | rtv2 16 | rtir12 17 | rtir0 18 | rtv0tr 19 | rtv1tr 20 | rtv2tr 21 | rtirtr 22 | rtv0bk 23 | rtv1bk 24 | rtv2bk 25 | rtirbk 26 | ll 27 | llv0 28 | llv1 29 | llv2 30 | llvir 31 | llv0tr 32 | llv1tr 33 | llv2tr 34 | llirtr 35 | llv0bk 36 | llv1bk 37 | llv2bk 38 | llirbk 39 | lc 40 | lcv0 41 | lcv1 42 | lcv2 43 | lcvir 44 | lcv0tr 45 | lcv1tr 46 | lcv2tr 47 | lcirtr 48 | lev0bk 49 | lev1bk 50 | lev2bk 51 | leirbk 52 | # sqr12 53 | sqr0 54 | op12 55 | op0 56 | gpf12 57 | gpf0 58 | gpl12 59 | gpl0 60 | jr $ra 61 | nop 62 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_InstrId.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "instructions/RabbitizerInstrId.h" 6 | 7 | 8 | #define RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, ...) { "InstrId", #prefix "_" #name, RABBITIZER_INSTR_ID_##prefix##_##name, false, NULL }, 9 | #define RABBITIZER_DEF_INSTR_ID_ALTNAME(prefix, caseBits, name, altname, ...) RABBITIZER_DEF_INSTR_ID(prefix, caseBits, name, __VA_ARGS__) 10 | 11 | RabbitizerEnumMetadata rabbitizer_enum_InstrId_enumvalues[] = { 12 | #include "tables/InstrIds.inc" 13 | 14 | RABBITIZER_DEF_INSTR_ID(ALL, , MAX, ) 15 | { 0 }, 16 | }; 17 | 18 | #undef RABBITIZER_DEF_INSTR_ID 19 | #undef RABBITIZER_DEF_INSTR_ID_ALTNAME 20 | 21 | static PyMethodDef rabbitizer_enum_InstrId_methods[] = { 22 | { 0 }, 23 | }; 24 | 25 | DEF_ENUM(InstrId, "") 26 | -------------------------------------------------------------------------------- /src/analysis/RabbitizerJrRegData.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "analysis/RabbitizerJrRegData.h" 5 | 6 | void RabbitizerJrRegData_init(RabbitizerJrRegData *self) { 7 | *self = (RabbitizerJrRegData){ 0 }; 8 | } 9 | 10 | void RabbitizerJrRegData_copy(RabbitizerJrRegData *self, const RabbitizerJrRegData *other) { 11 | *self = *other; 12 | } 13 | 14 | void RabbitizerJrRegData_initFromRegisterState(RabbitizerJrRegData *self, const RabbitizerTrackedRegisterState *state) { 15 | RabbitizerJrRegData_init(self); 16 | 17 | if (!state->hasLoValue || !state->dereferenced) { 18 | return; 19 | } 20 | 21 | self->hasInfo = true; 22 | self->offset = state->loOffset; 23 | self->address = state->value; 24 | self->checkedForBranching = state->checkedForBranching; 25 | self->lastBranchOffset = state->lastBranchOffset; 26 | } 27 | -------------------------------------------------------------------------------- /include/common/RabbitizerVersion.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_VERSION_H 5 | #define RABBITIZER_VERSION_H 6 | 7 | #include "Utils.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | 14 | // Header version 15 | #define RAB_VERSION_MAJOR 1 16 | #define RAB_VERSION_MINOR 14 17 | #define RAB_VERSION_PATCH 3 18 | 19 | #define RAB_VERSION_STR RAB_STRINGIFY(RAB_VERSION_MAJOR) "." RAB_STRINGIFY(RAB_VERSION_MINOR) "." RAB_STRINGIFY(RAB_VERSION_PATCH) 20 | 21 | #define RAB_VERSION_AUTHOR "Decompollaborate" 22 | 23 | 24 | // Compiled library version 25 | extern const int RabVersion_Major; 26 | extern const int RabVersion_Minor; 27 | extern const int RabVersion_Patch; 28 | 29 | extern const char RabVersion_Str[]; 30 | 31 | extern const char RabVersion_Author[]; 32 | 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop0.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 ----------------------------------------0 6 | | = COP0 | fmt | | 7 | ------6----------5----------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | MFC0 | --- | --- | --- | MTC0 | --- | --- | --- | 10 | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | *1=BC See BC0 list 15 | */ 16 | 17 | // The other instructions are implemented using the main CPU table 18 | -------------------------------------------------------------------------------- /cplusplus/include/rabbitizer.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_HPP 5 | #define RABBITIZER_HPP 6 | #pragma once 7 | 8 | 9 | #include "common/RabbitizerVersion.h" 10 | #include "common/RabbitizerConfig.h" 11 | 12 | #include "common/Utils.hpp" 13 | 14 | #include "instructions/OperandType.hpp" 15 | #include "instructions/InstrId.hpp" 16 | //#include "instructions/InstrSuffix.hpp" 17 | //#include "instructions/InstrDescriptor.hpp" 18 | #include "instructions/Registers.hpp" 19 | #include "instructions/InstructionBase.hpp" 20 | #include "instructions/InstructionCpu.hpp" 21 | #include "instructions/InstructionRsp.hpp" 22 | #include "instructions/InstructionR3000GTE.hpp" 23 | #include "instructions/InstructionR4000Allegrex.hpp" 24 | #include "instructions/InstructionR5900.hpp" 25 | 26 | #include "analysis/LoPairingInfo.hpp" 27 | #include "analysis/RegistersTracker.hpp" 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /.github/workflows/check_tables.yml: -------------------------------------------------------------------------------- 1 | name: Check for ungenerated tables 2 | 3 | # Build on every branch push, tag push, and pull request change: 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | check_tables: 8 | name: Check tables 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout reposistory 13 | uses: actions/checkout@main 14 | 15 | - name: clean tables 16 | run: make -C tables -j $(nproc) distclean 17 | 18 | - name: make tables 19 | run: make -C tables -j $(nproc) 20 | 21 | - name: Check if there are tables changes 22 | id: tables_changes 23 | uses: tj-actions/verify-changed-files@v14 24 | 25 | - name: tables changes 26 | if: steps.tables_changes.outputs.files_changed == 'true' 27 | run: | 28 | echo "Changed files: ${{ steps.tables_changes.outputs.changed_files }}" 29 | echo "Please run \`make -C tables distclean && make -C tables tables\` and commit the result" 30 | exit 1 31 | -------------------------------------------------------------------------------- /tests/c/instruction_checks/r5900_trunc_cvt.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "rabbitizer.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "expected_disasm_utils.h" 11 | 12 | #define TEST_ENTRY_C(word, gnu, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R5900, word, imm, expected, .gnuMode=gnu,) 13 | 14 | const TestEntry test_entries[] = { 15 | TEST_ENTRY_C(0x4600600D, true, NULL, ".word 0x4600600D # trunc.w.s $f0, $f12 # 00000000 "), 16 | TEST_ENTRY_C(0x46006024, true, NULL, ".word 0x46006024 # cvt.w.s $f0, $f12 # 00000000 "), 17 | TEST_ENTRY_C(0x4600600D, false, NULL, "trunc.w.s $f0, $f12"), 18 | TEST_ENTRY_C(0x46006024, false, NULL, "cvt.w.s $f0, $f12"), 19 | }; 20 | 21 | size_t test_entries_len = ARRAY_COUNT(test_entries); 22 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 ----------------------------------------0 6 | | = COP2 | fmt | | 7 | ------6----------5----------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | MFC2 | --- | CFC2 | *2 | MTC2 | --- | CTC2 | *3 | 10 | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | *1 = See BC2 table 15 | *2 = See MFHC2 table 16 | *3 = See MTHC2 table 17 | */ 18 | 19 | // The other instructions are implemented using the main CPU table 20 | -------------------------------------------------------------------------------- /tables/tables/operands/RabbitizerOperandType_rsp.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RAB_DEF_OPERAND(rsp, rs) 5 | RAB_DEF_OPERAND(rsp, rt) 6 | RAB_DEF_OPERAND(rsp, rd) 7 | RAB_DEF_OPERAND(rsp, cop0d) 8 | RAB_DEF_OPERAND(rsp, cop2t) 9 | RAB_DEF_OPERAND(rsp, cop2cd) // Coprocessor 2 control rd 10 | RAB_DEF_OPERAND(rsp, vs) 11 | RAB_DEF_OPERAND(rsp, vt) 12 | RAB_DEF_OPERAND(rsp, vd) 13 | RAB_DEF_OPERAND(rsp, hint) 14 | // RAB_DEF_OPERAND(rsp, elementhigh) 15 | // RAB_DEF_OPERAND(rsp, elementlow) 16 | // RAB_DEF_OPERAND(rsp, index) 17 | // RAB_DEF_OPERAND(rsp, offset) 18 | 19 | // composed/aliased operands 20 | RAB_DEF_OPERAND(rsp, vt_elementhigh) 21 | RAB_DEF_OPERAND(rsp, vt_elementlow) 22 | RAB_DEF_OPERAND(rsp, vd_de) 23 | RAB_DEF_OPERAND(rsp, vs_index) 24 | RAB_DEF_OPERAND(rsp, offset_rs) 25 | RAB_DEF_OPERAND(rsp, immediate_base) 26 | RAB_DEF_OPERAND(rsp, maybe_rd_rs) 27 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 2 | # SPDX-License-Identifier: MIT 3 | 4 | [project] 5 | name = "rabbitizer" 6 | # Version should be synced with include/common/RabbitizerVersion.h 7 | version = "1.14.3" 8 | description = "MIPS instruction decoder" 9 | # license = "MIT" 10 | readme = "README.md" 11 | requires-python = ">=3.9" 12 | authors = [ 13 | { name="Anghelo Carvajal", email="angheloalf95@gmail.com" }, 14 | ] 15 | 16 | [project.urls] 17 | "Homepage" = "https://github.com/Decompollaborate/rabbitizer" 18 | "Bug Tracker" = "https://github.com/Decompollaborate/rabbitizer/issues" 19 | 20 | [build-system] 21 | requires = ["setuptools>=65.0", "wheel"] 22 | build-backend = "setuptools.build_meta" 23 | 24 | [tool.setuptools] 25 | include-package-data = true 26 | packages = ["rabbitizer"] 27 | 28 | [tool.setuptools.package-data] 29 | rabbitizer = ["py.typed", "*.pyi", "**/*.pyi"] 30 | 31 | [tool.cibuildwheel] 32 | enable = [ 33 | # Include all PyPy versions 34 | "pypy", "pypy-eol", 35 | ] 36 | -------------------------------------------------------------------------------- /cplusplus/include/analysis/JrRegData.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_JR_REG_DATA_HPP 5 | #define RABBITIZER_JR_REG_DATA_HPP 6 | #pragma once 7 | 8 | #include "analysis/RabbitizerJrRegData.h" 9 | 10 | namespace rabbitizer { 11 | class JrRegData { 12 | protected: 13 | RabbitizerJrRegData regData; 14 | 15 | public: 16 | JrRegData(); 17 | JrRegData(const RabbitizerJrRegData &other); 18 | 19 | /** 20 | * Returns a pointer to the inner RabbitizerJrRegData. 21 | * It is recommended to not mess with it unless you know what you are doing. 22 | */ 23 | RabbitizerJrRegData *getCPtr(); 24 | const RabbitizerJrRegData *getCPtr() const; 25 | 26 | bool hasInfo() const; 27 | 28 | int offset() const; 29 | uint32_t address() const; 30 | bool checkedForBranching() const; 31 | int lastBranchOffset() const; 32 | }; 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/analysis/RabbitizerJrRegData.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_JR_REG_DATA_H 5 | #define RABBITIZER_JR_REG_DATA_H 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #include "common/Utils.h" 12 | 13 | #include "RabbitizerTrackedRegisterState.h" 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | 20 | typedef struct RabbitizerJrRegData { 21 | bool hasInfo; 22 | 23 | int offset; 24 | uint32_t address; 25 | bool checkedForBranching; 26 | int lastBranchOffset; 27 | } RabbitizerJrRegData; 28 | 29 | 30 | NON_NULL(1) 31 | void RabbitizerJrRegData_init(RabbitizerJrRegData *self); 32 | NON_NULL(1, 2) 33 | void RabbitizerJrRegData_copy(RabbitizerJrRegData *self, const RabbitizerJrRegData *other); 34 | 35 | NON_NULL(1, 2) 36 | void RabbitizerJrRegData_initFromRegisterState(RabbitizerJrRegData *self, const RabbitizerTrackedRegisterState *state); 37 | 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop1.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 ----------------------------------------0 6 | | = COP1 | fmt | | 7 | ------6----------5----------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | MFC1 | --- | CFC1 | MFHC1 | MTC1 | --- | CTC1 | MTHC1 | 10 | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | *2 | --- | --- | --- | *3 | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | *1 = BC See BC1 list 15 | *2 = S instr, see FPU S list 16 | *3 = W instr, see FPU W list 17 | */ 18 | 19 | /* 20 | TODO: 21 | - MFHC1 22 | - MTHC1 23 | */ 24 | 25 | // The other instructions are implemented using the main CPU table 26 | -------------------------------------------------------------------------------- /cplusplus/src/analysis/JrRegData.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "analysis/JrRegData.hpp" 5 | 6 | using namespace rabbitizer; 7 | 8 | JrRegData::JrRegData() { 9 | RabbitizerJrRegData_init(&this->regData); 10 | } 11 | JrRegData::JrRegData(const RabbitizerJrRegData &other) { 12 | RabbitizerJrRegData_copy(&this->regData, &other); 13 | } 14 | 15 | RabbitizerJrRegData *JrRegData::getCPtr() { 16 | return &this->regData; 17 | } 18 | const RabbitizerJrRegData *JrRegData::getCPtr() const { 19 | return &this->regData; 20 | } 21 | 22 | bool JrRegData::hasInfo() const { 23 | return this->regData.hasInfo; 24 | } 25 | 26 | int JrRegData::offset() const { 27 | return this->regData.offset; 28 | } 29 | uint32_t JrRegData::address() const { 30 | return this->regData.address; 31 | } 32 | bool JrRegData::checkedForBranching() const { 33 | return this->regData.checkedForBranching; 34 | } 35 | int JrRegData::lastBranchOffset() const { 36 | return this->regData.lastBranchOffset; 37 | } 38 | -------------------------------------------------------------------------------- /include/rabbitizer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_H 5 | #define RABBITIZER_H 6 | #pragma once 7 | 8 | #include "common/Utils.h" 9 | #include "common/RabbitizerVersion.h" 10 | #include "common/RabbitizerConfig.h" 11 | 12 | #include "instructions/RabbitizerOperandType.h" 13 | #include "instructions/RabbitizerInstrId.h" 14 | #include "instructions/RabbitizerInstrSuffix.h" 15 | #include "instructions/RabbitizerInstrDescriptor.h" 16 | #include "instructions/RabbitizerRegister.h" 17 | #include "instructions/RabbitizerRegisterDescriptor.h" 18 | #include "instructions/RabbitizerInstruction.h" 19 | #include "instructions/RabbitizerInstructionRsp.h" 20 | #include "instructions/RabbitizerInstructionR3000GTE.h" 21 | #include "instructions/RabbitizerInstructionR4000Allegrex.h" 22 | #include "instructions/RabbitizerInstructionR5900.h" 23 | 24 | #include "analysis/RabbitizerTrackedRegisterState.h" 25 | #include "analysis/RabbitizerLoPairingInfo.h" 26 | #include "analysis/RabbitizerRegistersTracker.h" 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /cplusplus/include/analysis/LoPairingInfo.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_LO_PAIRING_INFO_HPP 5 | #define RABBITIZER_LO_PAIRING_INFO_HPP 6 | #pragma once 7 | 8 | #include "analysis/RabbitizerLoPairingInfo.h" 9 | 10 | 11 | namespace rabbitizer { 12 | class LoPairingInfo { 13 | protected: 14 | RabbitizerLoPairingInfo pairingInfo; 15 | 16 | public: 17 | LoPairingInfo(); 18 | LoPairingInfo(const RabbitizerLoPairingInfo &pairingInfo); 19 | 20 | /** 21 | * Returns a pointer to the inner RabbitizerLoPairingInfo. 22 | * It is recommended to not mess with it unless you know what you are doing. 23 | */ 24 | RabbitizerLoPairingInfo *getCPtr(); 25 | const RabbitizerLoPairingInfo *getCPtr() const; 26 | 27 | int getInstrOffset() const; 28 | int64_t getValue() const; 29 | bool shouldProcess() const; 30 | bool isGpRel() const; 31 | bool isGpGot() const; 32 | }; 33 | }; 34 | 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /cplusplus/src/analysis/LoPairingInfo.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "analysis/LoPairingInfo.hpp" 5 | 6 | using namespace rabbitizer; 7 | 8 | LoPairingInfo::LoPairingInfo() : pairingInfo{} { 9 | } 10 | LoPairingInfo::LoPairingInfo(const RabbitizerLoPairingInfo &newPairingInfo) : pairingInfo{ newPairingInfo } { 11 | } 12 | 13 | RabbitizerLoPairingInfo *LoPairingInfo::getCPtr() { 14 | return &this->pairingInfo; 15 | } 16 | const RabbitizerLoPairingInfo *LoPairingInfo::getCPtr() const { 17 | return &this->pairingInfo; 18 | } 19 | 20 | int LoPairingInfo::getInstrOffset() const { 21 | return this->pairingInfo.instrOffset; 22 | } 23 | int64_t LoPairingInfo::getValue() const { 24 | return this->pairingInfo.value; 25 | } 26 | bool LoPairingInfo::shouldProcess() const { 27 | return this->pairingInfo.shouldProcess; 28 | } 29 | bool LoPairingInfo::isGpRel() const { 30 | return this->pairingInfo.isGpRel; 31 | } 32 | bool LoPairingInfo::isGpGot() const { 33 | return this->pairingInfo.isGpGot; 34 | } 35 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop2_mfhc2_p_s.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 -------------------------7-6---4--------0 6 | | = COP2 | MFHC2 | |1|1 1 1| fmt | 7 | ------6----------5-------------------------------1---3------4---- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 0 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | 1 | --- | --- | --- | --- | --- | --- | --- | vsync2| 11 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 12 | */ 13 | 14 | /* 15 | vsync2 16 | 31--------26-25-----21---------------------------7-6---4-3------0 17 | | COP2 |0 0 0 1 1| |1|1 1 1|1 1 1 1| 18 | ------6----------5---------5---------------------1---3------4---- 19 | */ 20 | 21 | RABBITIZER_DEF_INSTR_ID( 22 | r4000allegrex, 0xF, vsync2, 23 | .operands={0}, 24 | .instrType=RABBITIZER_INSTR_TYPE_R 25 | ) // SYNChronize2 26 | -------------------------------------------------------------------------------- /tables/tables/operands/RabbitizerOperandType_cpu.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RAB_DEF_OPERAND(cpu, rs) 5 | RAB_DEF_OPERAND(cpu, rt) 6 | RAB_DEF_OPERAND(cpu, rd) 7 | RAB_DEF_OPERAND(cpu, sa) 8 | RAB_DEF_OPERAND(cpu, zero) // $zero 9 | // RAB_DEF_OPERAND(cpu, function) 10 | RAB_DEF_OPERAND(cpu, cop0d) 11 | RAB_DEF_OPERAND(cpu, fs) 12 | RAB_DEF_OPERAND(cpu, ft) 13 | RAB_DEF_OPERAND(cpu, fd) 14 | RAB_DEF_OPERAND(cpu, cop1cs) // Coprocessor 1 control fs 15 | RAB_DEF_OPERAND(cpu, cop2t) 16 | RAB_DEF_OPERAND(cpu, cop2cd) // Coprocessor 2 control rd 17 | RAB_DEF_OPERAND(cpu, op) 18 | RAB_DEF_OPERAND(cpu, hint) 19 | RAB_DEF_OPERAND(cpu, code) 20 | RAB_DEF_OPERAND(cpu, code_lower) 21 | RAB_DEF_OPERAND(cpu, copraw) 22 | RAB_DEF_OPERAND(cpu, label) 23 | RAB_DEF_OPERAND(cpu, immediate) 24 | RAB_DEF_OPERAND(cpu, branch_target_label) 25 | 26 | // composed/aliased operands 27 | RAB_DEF_OPERAND(cpu, immediate_base) 28 | RAB_DEF_OPERAND(cpu, maybe_rd_rs) // $rd is omitted if it is $ra 29 | -------------------------------------------------------------------------------- /tests/c/test.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstruction.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | int main() { 13 | uint32_t word; 14 | RabbitizerInstruction instr; 15 | char *buffer; 16 | int extraLJust = 5; 17 | size_t bufferSize; 18 | size_t disassembledSize; 19 | 20 | word = 0x8D4A7E18; // lw 21 | //word = 0x00004010; // mfhi 22 | 23 | RabbitizerInstruction_init(&instr, word, 0x80000000); 24 | 25 | RabbitizerInstruction_processUniqueId(&instr); 26 | 27 | bufferSize = RabbitizerInstruction_getSizeForBuffer(&instr, 0, extraLJust); 28 | buffer = malloc(bufferSize + 1); 29 | assert(buffer != NULL); 30 | 31 | disassembledSize = RabbitizerInstruction_disassemble(&instr, buffer, NULL, 0, extraLJust); 32 | assert(disassembledSize <= bufferSize); 33 | 34 | printf("%08X: %s\n", word, buffer); 35 | 36 | free(buffer); 37 | RabbitizerInstruction_destroy(&instr); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Decompollaborate 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop2_mfhc2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 -------------------------7--------------0 6 | | = COP2 | MFHC2 | |p| | 7 | ------6----------5-------------------------------1--------------- 8 | |---------------0---------------|---------------1---------------| p 9 | | mfv | *1 | 10 | |-------------------------------|-------------------------------| 11 | *1 = See P table 12 | */ 13 | 14 | /* 15 | mfv 16 | 31--------26-25-----21-20-----16-----------------7-6------------0 17 | | COP2 |0 0 0 1 1| rt |0 0 0 0 0 0 0 0|0| vd | 18 | ------6----------5---------5---------------------1-------7------- 19 | */ 20 | 21 | RABBITIZER_DEF_INSTR_ID( 22 | r4000allegrex, 0, mfv, 23 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r4000allegrex_s_vd}, 24 | .instrType=RABBITIZER_INSTR_TYPE_R, 25 | .modifiesRt=true 26 | ) // Move word From Vfpu 27 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop2_mfhc2_p.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 -------------------------7-6---4--------0 6 | | = COP2 | MFHC2 | |1| fmt | | 7 | ------6----------5-------------------------------1---3----------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| fmt 9 | | mfvc | --- | --- | --- | --- | --- | --- | *1 | 10 | |-------|-------|-------|-------|-------|-------|-------|-------| 11 | *1 See S list 12 | */ 13 | 14 | /* 15 | mfvc 16 | 31--------26-25-----21-20-----16-----------------7-6------------0 17 | | COP2 |0 0 0 1 1| rt |0 0 0 0 0 0 0 0|1| cop2cd | 18 | ------6----------5---------5---------------------1-------7------- 19 | */ 20 | 21 | RABBITIZER_DEF_INSTR_ID( 22 | r4000allegrex, 0x0, mfvc, 23 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r4000allegrex_cop2cd}, 24 | .instrType=RABBITIZER_INSTR_TYPE_R, 25 | .modifiesRt=true 26 | ) // Move word From Vfpu Control 27 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_vfpu4_fmt0.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25--23-----19--------------------------------------0 6 | | VFPU4 |0 0| fmt | | 7 | ------6-------2------5------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | *1 | --- | *2 | *3 | *4 | --- | *5 | *6 | 10 | 01 | *7 | *8 | *9 | *10 | *11 | *11 | *11 | *11 | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | *1 = See FMT0 table 15 | *2 = See FMT2 table 16 | *3 = See FMT3 table 17 | *4 = See RND table 18 | *5 = See CVTFLT table 19 | *6 = See CVTINT table 20 | *7 = See FMT8 table 21 | *8 = See FMT9 table 22 | *9 = See CONTROL table 23 | *10 = See COLOR table 24 | *11 = See CST table 25 | */ 26 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop0_tlb.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21--------------------------------5--------0 6 | | = COP0 | TLB | | fmt | 7 | ------6----------5----------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 000 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | ERET | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | --- | --- | --- | --- | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | --- | --- | --- | --- | 17 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 18 | */ 19 | 20 | // The other instructions are implemented using the main CPU table 21 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_quadlr.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26-----------------------------------------------2-1-0 6 | | = QUADLR | |Z| | 7 | ------6------------------------------------------------------1--- 8 | |---------------0---------------|---------------1---------------| lo 9 | | SVL.Q | SVR.Q | 10 | |-------------------------------|-------------------------------| 11 | */ 12 | 13 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 14 | r4000allegrex, 0, svl_q, svl.q, 15 | .operands={RAB_OPERAND_r4000allegrex_q_vt_imm, RAB_OPERAND_r4000allegrex_offset14_base}, 16 | .instrType=RABBITIZER_INSTR_TYPE_I, 17 | .readsRs=true 18 | ) // Store Quad word Left from Vfpu 19 | 20 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 21 | r4000allegrex, 1, svr_q, svr.q, 22 | .operands={RAB_OPERAND_r4000allegrex_q_vt_imm, RAB_OPERAND_r4000allegrex_offset14_base}, 23 | .instrType=RABBITIZER_INSTR_TYPE_I, 24 | .readsRs=true 25 | ) // Store Quad word Right from Vfpu 26 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/InstructionRsp.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRUCTION_RSP_HPP 5 | #define RABBITIZER_INSTRUCTION_RSP_HPP 6 | #pragma once 7 | 8 | #include "InstructionBase.hpp" 9 | 10 | 11 | namespace rabbitizer { 12 | class InstructionRsp : public InstructionBase { 13 | public: 14 | InstructionRsp(uint32_t word, uint32_t vram); 15 | virtual ~InstructionRsp(); 16 | 17 | Registers::Rsp::Gpr GetRsp_rs() const; 18 | Registers::Rsp::Gpr GetRsp_rt() const; 19 | Registers::Rsp::Gpr GetRsp_rd() const; 20 | 21 | Registers::Rsp::Cop0 GetRsp_cop0d() const; 22 | 23 | Registers::Rsp::Cop2 GetRsp_cop2t() const; 24 | 25 | Registers::Rsp::Cop2Control GetRsp_cop2cd() const; 26 | 27 | Registers::Rsp::Vector GetRsp_vs() const; 28 | Registers::Rsp::Vector GetRsp_vt() const; 29 | Registers::Rsp::Vector GetRsp_vd() const; 30 | 31 | uint8_t GetRsp_elementhigh() const; 32 | uint8_t GetRsp_elementlow() const; 33 | 34 | uint8_t GetRsp_index() const; 35 | uint8_t GetRsp_de() const; 36 | }; 37 | }; 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /rabbitizer/enums/enums_utils.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | 6 | 7 | int rabbitizer_EnumMetadata_Initialize(PyObject *submodule, RabbitizerEnumMetadata *enumValues) { 8 | for (size_t i = 0; enumValues[i].enumType != 0; i++) { 9 | PyObject *args; 10 | 11 | args = Py_BuildValue("ssi", enumValues[i].enumType, enumValues[i].name, enumValues[i].value); 12 | if (args == NULL) { 13 | goto error; 14 | } 15 | 16 | enumValues[i].instance = PyObject_CallObject((PyObject*)&rabbitizer_type_Enum_TypeObject, args); 17 | Py_DECREF(args); 18 | if (enumValues[i].instance == NULL) { 19 | goto error; 20 | } 21 | 22 | enumValues[i].isInstanced = true; 23 | if (PyModule_AddObject(submodule, enumValues[i].name, enumValues[i].instance) < 0) { 24 | goto error; 25 | } 26 | } 27 | return 0; 28 | 29 | error: 30 | for (size_t i = 0; enumValues[i].enumType != 0; i++) { 31 | if (enumValues[i].isInstanced) { 32 | Py_DECREF(enumValues[i].instance); 33 | } 34 | enumValues[i].isInstanced = false; 35 | } 36 | 37 | return -1; 38 | } 39 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | include/generated/* linguist-generated=true 5 | cplusplus/include/generated/* linguist-generated=true 6 | 7 | rust/src/abi_enum.rs linguist-generated=true 8 | rust/src/access_type_enum.rs linguist-generated=true 9 | rust/src/instr_category_enum.rs linguist-generated=true 10 | rust/src/instr_id_enum.rs linguist-generated=true 11 | rust/src/instr_id_type_enum.rs linguist-generated=true 12 | rust/src/instr_suffix_enum.rs linguist-generated=true 13 | rust/src/operand_type_enum.rs linguist-generated=true 14 | rust/src/registers_enum.rs linguist-generated=true 15 | 16 | rabbitizer/Abi.pyi linguist-generated=true 17 | rabbitizer/AccessType.pyi linguist-generated=true 18 | rabbitizer/InstrCategory.pyi linguist-generated=true 19 | rabbitizer/InstrId.pyi linguist-generated=true 20 | rabbitizer/InstrIdType.pyi linguist-generated=true 21 | rabbitizer/OperandType.pyi linguist-generated=true 22 | rabbitizer/RegGprO32.pyi linguist-generated=true 23 | rabbitizer/RegGprN32.pyi linguist-generated=true 24 | rabbitizer/RegCop1O32.pyi linguist-generated=true 25 | rabbitizer/RegCop1N32.pyi linguist-generated=true 26 | rabbitizer/RegCop1N64.pyi linguist-generated=true 27 | rabbitizer/TrinaryValue.pyi linguist-generated=true 28 | -------------------------------------------------------------------------------- /rust/src/utils.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | pub type SizeT = usize; 5 | 6 | pub fn c_string_from_str(str: Option<&str>) -> (*const core::ffi::c_char, SizeT) { 7 | if let Some(str) = str { 8 | (str.as_ptr() as *const core::ffi::c_char, str.len()) 9 | } else { 10 | (std::ptr::null(), 0) 11 | } 12 | } 13 | 14 | pub fn mask(v: u32, w: u32) -> u32 { 15 | v & ((1 << w) - 1) 16 | } 17 | 18 | pub fn shiftl(v: u32, s: u32, w: u32) -> u32 { 19 | mask(v, w) << s 20 | } 21 | 22 | pub fn shiftr(v: u32, s: u32, w: u32) -> u32 { 23 | mask(v >> s, w) 24 | } 25 | 26 | pub fn bitrepack(fullword: u32, v: u32, s: u32, w: u32) -> u32 { 27 | (shiftr(fullword, s + w, 32 - (s + w)) << (s + w)) | shiftl(v, s, w) | mask(fullword, s) 28 | } 29 | 30 | pub fn convert_option_string_to_option_str(input: &Option) -> Option<&str> { 31 | match input { 32 | None => None, 33 | Some(x) => Some(x.as_str()), 34 | } 35 | } 36 | 37 | #[repr(u32)] 38 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] 39 | #[allow(non_camel_case_types)] 40 | #[derive(num_enum::TryFromPrimitive, num_enum::IntoPrimitive)] 41 | pub enum TrinaryValue { 42 | NONE, 43 | FALSE, 44 | TRUE, 45 | } 46 | -------------------------------------------------------------------------------- /tables/tables/instr_id_types/InstrIdType_r5900.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, INVALID) 5 | 6 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, NORMAL) 7 | 8 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, SPECIAL) 9 | 10 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, REGIMM) 11 | 12 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP0) 13 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP0_TLB) 14 | 15 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP1) 16 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP1_FPUS) 17 | 18 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP2) 19 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP2_NOHIGHBIT) 20 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP2_BC2) 21 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP2_SPECIAL1) 22 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP2_SPECIAL2) 23 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, COP2_VIWR) 24 | 25 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI) 26 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI_0) 27 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI_1) 28 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI_2) 29 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI_3) 30 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI_PMFHL) 31 | RABBITIZER_DEF_INSTR_ID_TYPE(R5900, MMI_PMTHL) 32 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_mmi_pmthl.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26------------------------------10------6-5----------0 6 | |0 1 1 1 0 0| | fmt |1 1 0 0 0 1| 7 | ------6----------------------------------------5----------6------ 8 | |-------00------|-------01------|-------10------|-------11------| 9 | 000 | PMTHL.LW | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | 13 | 100 | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | 17 | hi |---------------|---------------|---------------|---------------| 18 | */ 19 | 20 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 21 | r5900, 0x00, pmthl_lw, pmthl.lw, 22 | .operands={RAB_OPERAND_cpu_rs}, 23 | .readsRs=true 24 | ) // Parallel Move To Hi/Lo register 25 | -------------------------------------------------------------------------------- /tests/asm/r3000gte/inline_gte_commands.inc.s: -------------------------------------------------------------------------------- 1 | ; 2 | ; GTE commands without nops 3 | ; 4 | 5 | RTPS macro 6 | dw $0000007f 7 | endm 8 | 9 | RTPT macro 10 | dw $000000bf 11 | endm 12 | 13 | DCPL macro 14 | dw $00000dff 15 | endm 16 | 17 | DPCS macro 18 | dw $00000e3f 19 | endm 20 | 21 | DPCT macro 22 | dw $00000e7f 23 | endm 24 | 25 | INTPL macro 26 | dw $00000ebf 27 | endm 28 | 29 | NCS macro 30 | dw $00000f7f 31 | endm 32 | 33 | NCT macro 34 | dw $00000fbf 35 | endm 36 | 37 | NCDS macro 38 | dw $00000fff 39 | endm 40 | 41 | NCDT macro 42 | dw $0000103f 43 | endm 44 | 45 | NCCS macro 46 | dw $0000107f 47 | endm 48 | 49 | NCCT macro 50 | dw $000010bf 51 | endm 52 | 53 | CDP macro 54 | dw $000010ff 55 | endm 56 | 57 | CC macro 58 | dw $0000113f 59 | endm 60 | 61 | NCLIP macro 62 | dw $0000117f 63 | endm 64 | 65 | AVSZ3 macro 66 | dw $000011bf 67 | endm 68 | 69 | AVSZ4 macro 70 | dw $000011ff 71 | endm 72 | 73 | MVMVA macro sf,mx,v,cv,lm 74 | dw $000013bf|sf<<25|mx<<23|v<<21|cv<<19|lm<<18 75 | endm 76 | 77 | SQR macro sf 78 | dw $000013ff|sf<<25 79 | endm 80 | 81 | OP macro sf 82 | dw $0000143f|sf<<25 83 | endm 84 | 85 | GPF macro sf 86 | dw $0000147f|sf<<25 87 | endm 88 | 89 | GPL macro sf 90 | dw $000014bf|sf<<25 91 | endm 92 | -------------------------------------------------------------------------------- /cplusplus/include/instructions/InstructionR5900.hpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef RABBITIZER_INSTRUCTION_R5900_HPP 5 | #define RABBITIZER_INSTRUCTION_R5900_HPP 6 | #pragma once 7 | 8 | #include "InstructionBase.hpp" 9 | 10 | 11 | namespace rabbitizer { 12 | class InstructionR5900 : public InstructionBase { 13 | public: 14 | InstructionR5900(uint32_t word, uint32_t vram); 15 | virtual ~InstructionR5900(); 16 | 17 | Registers::R5900::VF GetR5900_vfs() const; 18 | Registers::R5900::VF GetR5900_vft() const; 19 | Registers::R5900::VF GetR5900_vfd() const; 20 | 21 | Registers::R5900::VI GetR5900_vis() const; 22 | Registers::R5900::VI GetR5900_vit() const; 23 | Registers::R5900::VI GetR5900_vid() const; 24 | 25 | uint8_t GetR5900_mmi_function() const; 26 | uint8_t GetR5900_fhi_flo() const; 27 | 28 | uint8_t GetR5900_xyzw_x() const; 29 | uint8_t GetR5900_xyzw_y() const; 30 | uint8_t GetR5900_xyzw_z() const; 31 | uint8_t GetR5900_xyzw_w() const; 32 | uint8_t GetR5900_n() const; 33 | uint8_t GetR5900_l() const; 34 | uint8_t GetR5900_m() const; 35 | 36 | int8_t GetR5900_imm5() const; 37 | }; 38 | }; 39 | 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /tests/c/r5900test.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionR5900.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | int main() { 13 | uint32_t word; 14 | RabbitizerInstruction instr; 15 | char *buffer; 16 | int extraLJust = 5; 17 | #if 1 18 | uint32_t validbits; 19 | #endif 20 | 21 | word = 0x4BE1634B; 22 | 23 | RabbitizerInstructionR5900_init(&instr, word, 0x00100000); 24 | 25 | RabbitizerInstructionR5900_processUniqueId(&instr); 26 | 27 | buffer = malloc(RabbitizerInstruction_getSizeForBuffer(&instr, 0, extraLJust) + 1); 28 | assert(buffer != NULL); 29 | 30 | RabbitizerInstruction_disassemble(&instr, buffer, NULL, 0, extraLJust); 31 | 32 | printf("%08X: %s\n", word, buffer); 33 | 34 | #if 1 35 | validbits = RabbitizerInstruction_getValidBits(&instr); 36 | 37 | printf("word: %08X\n", instr.word); 38 | printf("mandatory bits: %08X\n", instr._mandatorybits); 39 | printf("valid bits: %08X\n", validbits); 40 | printf("invalid bits: %08X\n", (~validbits) & instr.word); 41 | #endif 42 | 43 | free(buffer); 44 | RabbitizerInstructionR5900_destroy(&instr); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/c/r3000gte.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionR3000GTE.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | int main() { 13 | uint32_t word; 14 | RabbitizerInstruction instr; 15 | char *buffer; 16 | int extraLJust = 5; 17 | #if 1 18 | uint32_t validbits; 19 | #endif 20 | 21 | word = 0x4A180001; // RTPS 22 | 23 | RabbitizerInstructionR3000GTE_init(&instr, word, 0x00100000); 24 | 25 | RabbitizerInstructionR3000GTE_processUniqueId(&instr); 26 | 27 | buffer = malloc(RabbitizerInstruction_getSizeForBuffer(&instr, 0, extraLJust) + 1); 28 | assert(buffer != NULL); 29 | 30 | RabbitizerInstruction_disassemble(&instr, buffer, NULL, 0, extraLJust); 31 | 32 | printf("%08X: %s\n", word, buffer); 33 | 34 | #if 1 35 | validbits = RabbitizerInstruction_getValidBits(&instr); 36 | 37 | printf("word: %08X\n", instr.word); 38 | printf("mandatory bits: %08X\n", instr._mandatorybits); 39 | printf("valid bits: %08X\n", validbits); 40 | printf("invalid bits: %08X\n", (~validbits) & instr.word); 41 | #endif 42 | 43 | free(buffer); 44 | RabbitizerInstructionR3000GTE_destroy(&instr); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/c/rsptest.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionRsp.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | int main() { 13 | uint32_t word; 14 | RabbitizerInstruction instr; 15 | char *buffer; 16 | int extraLJust = 5; 17 | uint32_t validbits; 18 | 19 | //word = 0x4B01C8E8; // vand $v3, $v25, $v1[0] 20 | word = 0x48952000; // mtc2 $21, $v4[0] 21 | 22 | RabbitizerInstructionRsp_init(&instr, word, 0x80000000); 23 | 24 | RabbitizerInstructionRsp_processUniqueId(&instr); 25 | 26 | buffer = malloc(RabbitizerInstruction_getSizeForBuffer(&instr, 0, extraLJust) + 1); 27 | assert(buffer != NULL); 28 | 29 | RabbitizerInstruction_disassemble(&instr, buffer, NULL, 0, extraLJust); 30 | 31 | printf("%08X: %s\n", word, buffer); 32 | 33 | validbits = RabbitizerInstruction_getValidBits(&instr); 34 | 35 | printf("word: %08X\n", instr.word); 36 | printf("mandatory bits: %08X\n", instr._mandatorybits); 37 | printf("valid bits: %08X\n", validbits); 38 | printf("invalid bits: %08X\n", (~validbits) & instr.word); 39 | 40 | free(buffer); 41 | RabbitizerInstructionRsp_destroy(&instr); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_regimm.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26----------20-------16------------------------------0 6 | | = REGIMM | | rt | | 7 | ------6---------------------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | 10 | 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | --- | TNEI | --- | 11 | 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | 12 | 11 | MTSAB | MTSAH | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // The other instructions are implemented using the main CPU table 17 | 18 | // OP rs, IMM 19 | RABBITIZER_DEF_INSTR_ID( 20 | r5900, 0x18, mtsab, 21 | .operands={RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_immediate}, 22 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 23 | .readsRs=true 24 | ) 25 | RABBITIZER_DEF_INSTR_ID( 26 | r5900, 0x19, mtsah, 27 | .operands={RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_immediate}, 28 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 29 | .readsRs=true 30 | ) 31 | -------------------------------------------------------------------------------- /tests/c/r4000allegrex.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionR4000Allegrex.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | int main() { 13 | uint32_t word; 14 | RabbitizerInstruction instr; 15 | char *buffer; 16 | int extraLJust = 5; 17 | #if 1 18 | uint32_t validbits; 19 | #endif 20 | 21 | word = 0x0040080B; // clo 22 | 23 | RabbitizerInstructionR4000Allegrex_init(&instr, word, 0x00100000); 24 | 25 | RabbitizerInstructionR4000Allegrex_processUniqueId(&instr); 26 | 27 | buffer = malloc(RabbitizerInstruction_getSizeForBuffer(&instr, 0, extraLJust) + 1); 28 | assert(buffer != NULL); 29 | 30 | RabbitizerInstruction_disassemble(&instr, buffer, NULL, 0, extraLJust); 31 | 32 | printf("%08X: %s\n", word, buffer); 33 | 34 | #if 1 35 | validbits = RabbitizerInstruction_getValidBits(&instr); 36 | 37 | printf("word: %08X\n", instr.word); 38 | printf("mandatory bits: %08X\n", instr._mandatorybits); 39 | printf("valid bits: %08X\n", validbits); 40 | printf("invalid bits: %08X\n", (~validbits) & instr.word); 41 | #endif 42 | 43 | free(buffer); 44 | RabbitizerInstructionR4000Allegrex_destroy(&instr); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/c/registersTrackerTest.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstruction.h" 5 | #include "analysis/RabbitizerRegistersTracker.h" 6 | 7 | 8 | int main() { 9 | RabbitizerRegistersTracker regsTracker; 10 | RabbitizerInstruction instr; 11 | uint32_t word = 0x002D0821; // addu $at, $at, $t5 12 | uint32_t vram = 0x0042F170; 13 | int instrOffset = 220; 14 | 15 | RabbitizerRegistersTracker_init(®sTracker, NULL); 16 | 17 | RabbitizerInstruction_init(&instr, word, vram); 18 | RabbitizerInstruction_processUniqueId(&instr); 19 | 20 | regsTracker.registers[1] = (RabbitizerTrackedRegisterState){ 21 | .dereferenceOffset = 212, 22 | .dereferenced = true, 23 | .gpGotOffset = 212, 24 | .hasGpGot = true, 25 | .hasLoValue = true, 26 | .hasLuiValue = false, 27 | .loOffset = 212, 28 | .luiOffset = 0, 29 | .luiSetOnBranchLikely = false, 30 | .value = 0x10010000, 31 | .registerNum = regsTracker.registers[1].registerNum, 32 | }; 33 | 34 | RabbitizerRegistersTracker_overwriteRegisters(®sTracker, &instr, instrOffset); 35 | 36 | RabbitizerInstruction_destroy(&instr); 37 | 38 | RabbitizerRegistersTracker_destroy(®sTracker); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 2 | # SPDX-License-Identifier: MIT 3 | 4 | from setuptools import setup, Extension 5 | from pathlib import Path 6 | import platform 7 | 8 | bindingsPath = Path("rabbitizer") 9 | srcPath = Path("src") 10 | 11 | sourcesList = [str(x) for x in bindingsPath.glob("**/*.c")] + [str(x) for x in srcPath.glob("**/*.c")] 12 | headersList = [str(x) for x in bindingsPath.glob("**/*.h")] + [str(x) for x in srcPath.glob("**/*.h")] 13 | 14 | extraCompileArgs = ["-std=c11", "-Wall", "-g",] 15 | if platform.system() == "Linux": 16 | extraCompileArgs += ["-Wno-unknown-warning-option",] 17 | extraCompileArgs += ["-Os", "-Wextra",] 18 | extraCompileArgs += ["-Werror=vla", "-Werror=switch", "-Werror=implicit-fallthrough", "-Werror=unused-function", "-Werror=unused-parameter", "-Werror=shadow", "-Werror=switch"] 19 | extraCompileArgs += ["-Werror=implicit-function-declaration", "-Werror=incompatible-pointer-types"] 20 | extraCompileArgs += ["-Werror"] 21 | extraCompileArgs += ["-Wno-nonnull-compare"] 22 | 23 | setup( 24 | ext_modules=[ 25 | Extension( 26 | name="rabbitizer", 27 | sources=sourcesList, 28 | include_dirs=["include", "rabbitizer", "tables"], 29 | extra_compile_args = extraCompileArgs, 30 | depends=headersList, 31 | ), 32 | ], 33 | ) 34 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_cop0_tlb.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21--------------------------------5--------0 6 | | = COP0 | TLB | | fmt | 7 | ------6----------5----------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- | 10 | 001 | TLBP | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | ERET | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | --- | --- | --- | --- | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | EI | DI | --- | --- | --- | --- | --- | --- | 17 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 18 | */ 19 | 20 | // The other instructions are implemented using the main CPU table 21 | 22 | RABBITIZER_DEF_INSTR_ID( 23 | r5900, 0x38, ei, 24 | .operands={0} 25 | ) 26 | RABBITIZER_DEF_INSTR_ID( 27 | r5900, 0x39, di, 28 | .operands={0} 29 | ) 30 | -------------------------------------------------------------------------------- /tables/tables/operands/RabbitizerOperandType_r5900.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RAB_DEF_OPERAND(r5900, I) 5 | RAB_DEF_OPERAND(r5900, Q) 6 | RAB_DEF_OPERAND(r5900, R) 7 | RAB_DEF_OPERAND(r5900, ACC) 8 | RAB_DEF_OPERAND(r5900, ACCxyzw) 9 | RAB_DEF_OPERAND(r5900, vfs) 10 | RAB_DEF_OPERAND(r5900, vft) 11 | RAB_DEF_OPERAND(r5900, vfd) 12 | RAB_DEF_OPERAND(r5900, vfsxyzw) 13 | RAB_DEF_OPERAND(r5900, vftxyzw) 14 | RAB_DEF_OPERAND(r5900, vfdxyzw) 15 | RAB_DEF_OPERAND(r5900, vfsn) 16 | RAB_DEF_OPERAND(r5900, vftn) 17 | RAB_DEF_OPERAND(r5900, vfdn) 18 | RAB_DEF_OPERAND(r5900, vfsl) 19 | RAB_DEF_OPERAND(r5900, vftl) 20 | RAB_DEF_OPERAND(r5900, vfdl) 21 | RAB_DEF_OPERAND(r5900, vfsm) 22 | RAB_DEF_OPERAND(r5900, vftm) 23 | RAB_DEF_OPERAND(r5900, vfdm) 24 | RAB_DEF_OPERAND(r5900, vis) 25 | RAB_DEF_OPERAND(r5900, vit) 26 | RAB_DEF_OPERAND(r5900, vid) 27 | RAB_DEF_OPERAND(r5900, vis_predecr) 28 | RAB_DEF_OPERAND(r5900, vit_predecr) 29 | RAB_DEF_OPERAND(r5900, vid_predecr) 30 | RAB_DEF_OPERAND(r5900, vis_postincr) 31 | RAB_DEF_OPERAND(r5900, vit_postincr) 32 | RAB_DEF_OPERAND(r5900, vid_postincr) 33 | RAB_DEF_OPERAND(r5900, vis_parenthesis) 34 | RAB_DEF_OPERAND(r5900, immediate5) 35 | RAB_DEF_OPERAND(r5900, immediate15) 36 | -------------------------------------------------------------------------------- /cplusplus/src/instructions/InstructionR3000GTE.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/InstructionR3000GTE.hpp" 5 | 6 | #include "instructions/RabbitizerInstructionR3000GTE.h" 7 | 8 | using namespace rabbitizer; 9 | 10 | InstructionR3000GTE::InstructionR3000GTE(uint32_t word, uint32_t vram) : InstructionBase() { 11 | RabbitizerInstructionR3000GTE_init(&this->instr, word, vram); 12 | RabbitizerInstructionR3000GTE_processUniqueId(&this->instr); 13 | } 14 | 15 | InstructionR3000GTE::~InstructionR3000GTE() { 16 | RabbitizerInstructionR3000GTE_destroy(&this->instr); 17 | } 18 | 19 | uint8_t InstructionR3000GTE::GetR3000GTE_gbg() const { 20 | return RAB_INSTR_R3000GTE_GET_gbg(&this->instr); 21 | } 22 | 23 | uint8_t InstructionR3000GTE::GetR3000GTE_sf() const { 24 | return RAB_INSTR_R3000GTE_GET_sf(&this->instr); 25 | } 26 | 27 | uint8_t InstructionR3000GTE::GetR3000GTE_mx() const { 28 | return RAB_INSTR_R3000GTE_GET_mx(&this->instr); 29 | } 30 | uint8_t InstructionR3000GTE::GetR3000GTE_v() const { 31 | return RAB_INSTR_R3000GTE_GET_v(&this->instr); 32 | } 33 | uint8_t InstructionR3000GTE::GetR3000GTE_cv() const { 34 | return RAB_INSTR_R3000GTE_GET_cv(&this->instr); 35 | } 36 | uint8_t InstructionR3000GTE::GetR3000GTE_lm() const { 37 | return RAB_INSTR_R3000GTE_GET_lm(&this->instr); 38 | } 39 | -------------------------------------------------------------------------------- /rabbitizer/Config.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | from .Enum import Enum 9 | from .Abi import Abi 10 | 11 | class _RabbitizerConfig: 12 | regNames_namedRegisters: bool = True 13 | regNames_gprAbiNames: Enum = Abi.O32 14 | regNames_fprAbiNames: Enum = Abi.NUMERIC 15 | regNames_userFpcCsr: bool = True 16 | regNames_vr4300Cop0NamedRegisters: bool = True 17 | regNames_vr4300RspCop0NamedRegisters: bool = True 18 | regNames_r4000AllegrexVfpuControlNamedRegisters: bool = False 19 | 20 | pseudos_enablePseudos: bool = True 21 | pseudos_pseudoBeqz: bool = True 22 | pseudos_pseudoBnez: bool = True 23 | pseudos_pseudoB: bool = True 24 | pseudos_pseudoMove: bool = True 25 | pseudos_pseudoNot: bool = True 26 | pseudos_pseudoNeg: bool = True 27 | pseudos_pseudoNegu: bool = True 28 | pseudos_pseudoBal: bool = True 29 | 30 | toolchainTweaks_treatJAsUnconditionalBranch: bool = True 31 | toolchainTweaks_sn64DivFix: bool = False 32 | toolchainTweaks_gnuMode: bool = True 33 | 34 | misc_opcodeLJust: int = 11 35 | misc_unknownInstrComment: bool = True 36 | misc_omit0XOnSmallImm: bool = False 37 | misc_upperCaseImm: bool = True 38 | misc_expandJalr: bool = False 39 | 40 | config: _RabbitizerConfig 41 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop1_fpu_s.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31----------26-25--------21 -----------------------------------------5----------0 6 | | = COP1 | = S | | function | 7 | -------6------------5-----------------------------------------------------6------ 8 | |---000---|---001---|---010---|---011---|---100---|---101---|---110---|---111---| lo 9 | 000 | ADD.S | SUB.S | MUL.S | DIV.S | SQRT.S | ABS.S | MOV.S | NEG.S | 10 | 001 | --- | --- | --- | --- |ROUND.W.S|TRUNC.W.S| CEIL.W.S|FLOOR.W.S| 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | --- | --- | --- | --- | CVT.W.S | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | C.F.S | C.UN.S | C.EQ.S | C.UEQ.S | C.OLT.S | C.ULT.S | C.OLE.S | C.ULE.S | 16 | 111 | C.SF.S | C.NGLE.S| C.SEQ.S | C.NGL.S | C.LT.S | C.NGE.S | C.LE.S | C.NGT.S | 17 | hi |---------|---------|---------|---------|---------|---------|---------|---------| 18 | */ 19 | 20 | // The other instructions are implemented using the main CPU table 21 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop1_fpu_w.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31----------26-25--------21 -----------------------------------------5----------0 6 | | = COP1 | = W | | function | 7 | -------6------------5-----------------------------------------------------6------ 8 | |---000---|---001---|---010---|---011---|---100---|---101---|---110---|---111---| lo 9 | 000 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | CVT.S.W | --- | --- | --- | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | --- | --- | --- | --- | 17 | hi |---------|---------|---------|---------|---------|---------|---------|---------| 18 | */ 19 | 20 | // The other instructions are implemented using the main CPU table 21 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_special_rs.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25-----21---------------------------------5--------0 6 | | = SPECIAL | rs | | 0x02 | 7 | ------6----------5-----------------------------------------6----- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | srl | rotr | --- | --- | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | RABBITIZER_DEF_INSTR_ID( 17 | r4000allegrex, 0x00, srl, 18 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_sa}, 19 | .instrType=RABBITIZER_INSTR_TYPE_R, 20 | .modifiesRd=true, 21 | .readsRt=true 22 | ) // Shift word Right Logical 23 | 24 | RABBITIZER_DEF_INSTR_ID( 25 | r4000allegrex, 0x01, rotr, 26 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_sa}, 27 | .instrType=RABBITIZER_INSTR_TYPE_R, 28 | .modifiesRd=true, 29 | .readsRt=true 30 | ) // ROTate word Right 31 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_vfpu4.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25-24---------------15--------------7--------------0 6 | | VFPU4 |fmt| |t| |p| | 7 | ------6-------2------------------1---------------1--------------- 8 | |-------00------|-------01------|-------10------|-------11------| fmt 9 | 00 | *1 | --- | *2 | vwbn.s | 10 | 01 | *1 | --- | *2 | --- | 11 | 10 | *1 | --- | *2 | --- | 12 | 11 | *1 | --- | *2 | --- | 13 | tp |---------------|---------------|---------------|---------------| 14 | *1 See fmt0 table 15 | *2 See fmt2 table 16 | */ 17 | 18 | /* 19 | vwbn.s 20 | 31--------26-25-24------------16---14----------8---6------------0 21 | | VFPU4 |1 1| imm8 |0| vs |0| vd | 22 | ------6-------2---------8--------1-------7-------1-------7------- 23 | */ 24 | 25 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 26 | r4000allegrex, 0x3 << 2 | 0x0, vwbn_s, vwbn.s, 27 | .operands={RAB_OPERAND_r4000allegrex_s_vd, RAB_OPERAND_r4000allegrex_s_vs, RAB_OPERAND_r4000allegrex_bn}, 28 | .instrType=RABBITIZER_INSTR_TYPE_R 29 | ) // WrapBN Single word 30 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstrId.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstrId.h" 5 | 6 | #include 7 | 8 | #include "generated/InstrId_Names_array.h" 9 | 10 | /** 11 | * Check the word corresponds to a valid instruction. 12 | */ 13 | bool RabbitizerInstrId_isValid(RabbitizerInstrId uniqueId) { 14 | switch (uniqueId) { 15 | case RABBITIZER_INSTR_ID_cpu_INVALID: 16 | case RABBITIZER_INSTR_ID_rsp_INVALID: 17 | case RABBITIZER_INSTR_ID_r3000gte_INVALID: 18 | case RABBITIZER_INSTR_ID_r5900_INVALID: 19 | case RABBITIZER_INSTR_ID_r4000allegrex_INVALID: 20 | case RABBITIZER_INSTR_ID_cpu_MAX: 21 | case RABBITIZER_INSTR_ID_rsp_MAX: 22 | case RABBITIZER_INSTR_ID_r3000gte_MAX: 23 | case RABBITIZER_INSTR_ID_r5900_MAX: 24 | case RABBITIZER_INSTR_ID_r4000allegrex_MAX: 25 | // case RABBITIZER_INSTR_ID_ALL_MAX: Same as last MAX 26 | return false; 27 | 28 | default: 29 | return true; 30 | } 31 | } 32 | 33 | const char *RabbitizerInstrId_getOpcodeName(RabbitizerInstrId uniqueId) { 34 | const char *name; 35 | 36 | assert(uniqueId >= RABBITIZER_INSTR_ID_cpu_INVALID && uniqueId < RABBITIZER_INSTR_ID_ALL_MAX); 37 | 38 | name = RabbitizerInstrId_Names[uniqueId]; 39 | assert(name != NULL); 40 | 41 | return name; 42 | } 43 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_vfpu7.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | vnop 6 | 31--------26-25-------------------------------------------------0 7 | | VFPU7 |1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| 8 | ------6-------------------------------26------------------------- 9 | */ 10 | 11 | RABBITIZER_DEF_INSTR_ID( 12 | r4000allegrex, 0x3FF0000, vnop, 13 | .operands={0}, 14 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN 15 | ) // Nop 16 | 17 | /* 18 | vsync 19 | 31--------26-25-------------------------------------------------0 20 | | VFPU7 |1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0| 21 | ------6-------------------------------26------------------------- 22 | */ 23 | 24 | RABBITIZER_DEF_INSTR_ID( 25 | r4000allegrex, 0x3FF0320, vsync, 26 | .operands={0}, 27 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN 28 | ) // Synchronize 29 | 30 | /* 31 | vflush 32 | 31--------26-25-------------------------------------------------0 33 | | VFPU7 |1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1| 34 | ------6-------------------------------26------------------------- 35 | */ 36 | 37 | RABBITIZER_DEF_INSTR_ID( 38 | r4000allegrex, 0x3FF040D, vflush, 39 | .operands={0}, 40 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN 41 | ) // Flush Write Buffer 42 | -------------------------------------------------------------------------------- /rabbitizer/rabbitizer_module.h: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #ifndef PYRABBITIZER_MODULE_H 5 | #define PYRABBITIZER_MODULE_H 6 | #pragma once 7 | 8 | #define PY_SSIZE_T_CLEAN 9 | #include 10 | #include "structmember.h" 11 | 12 | #include "rabbitizer_macro_utilities.h" 13 | #include "enums/enums_utils.h" 14 | 15 | #include "instructions/RabbitizerInstruction.h" 16 | #include "analysis/RabbitizerLoPairingInfo.h" 17 | #include "analysis/RabbitizerTrackedRegisterState.h" 18 | #include "analysis/RabbitizerRegistersTracker.h" 19 | 20 | 21 | // TODO: clean up this... 22 | 23 | 24 | extern PyModuleDef rabbitizer_module; 25 | 26 | PyObject *rabbitizer_submodule_Utils_Init(void); 27 | 28 | extern PyTypeObject rabbitizer_global_config_TypeObject; 29 | 30 | extern PyTypeObject rabbitizer_type_Enum_TypeObject; 31 | 32 | DECL_RAB_TYPE(Instruction, instr) 33 | DECL_RAB_TYPE(LoPairingInfo, pairingInfo) 34 | DECL_RAB_TYPE(TrackedRegisterState, registerState) 35 | DECL_RAB_TYPE(RegistersTracker, tracker) 36 | DECL_RAB_TYPE(JrRegData, jrRegData) 37 | 38 | 39 | DECL_ENUM(Abi) 40 | DECL_ENUM(InstrCategory) 41 | DECL_ENUM(InstrId) 42 | DECL_ENUM(InstrIdType) 43 | DECL_ENUM(OperandType) 44 | DECL_ENUM(AccessType) 45 | 46 | DECL_ENUM(RegGprO32) 47 | DECL_ENUM(RegGprN32) 48 | 49 | DECL_ENUM(RegCop1O32) 50 | DECL_ENUM(RegCop1N32) 51 | DECL_ENUM(RegCop1N64) 52 | 53 | DECL_ENUM(TrinaryValue) 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_special_sa.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26--------------------------------10------6-5--------0 6 | | = SPECIAL | | sa | 0x06 | 7 | ------6------------------------------------------5---------6----- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | srlv | rotrv | --- | --- | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | RABBITIZER_DEF_INSTR_ID( 17 | r4000allegrex, 0x00, srlv, 18 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_rs}, 19 | .instrType=RABBITIZER_INSTR_TYPE_R, 20 | .modifiesRd=true, 21 | .readsRs=true, 22 | .readsRt=true 23 | ) // Shift word Right Logical Variable 24 | 25 | RABBITIZER_DEF_INSTR_ID( 26 | r4000allegrex, 0x01, rotrv, 27 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_rs}, 28 | .instrType=RABBITIZER_INSTR_TYPE_R, 29 | .modifiesRd=true, 30 | .readsRs=true, 31 | .readsRt=true 32 | ) // ROTate word Right Variable 33 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_Abi.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "common/RabbitizerConfig.h" 6 | #include "common/Utils.h" 7 | 8 | 9 | #define RABBITIZER_DEF_ABI(name) { "Abi", #name, RABBITIZER_ABI_##name, false, NULL }, 10 | 11 | RabbitizerEnumMetadata rabbitizer_enum_Abi_enumvalues[] = { 12 | #include "tables/Abi.inc" 13 | RABBITIZER_DEF_ABI(MAX) 14 | 15 | { 0 }, 16 | }; 17 | 18 | #undef RABBITIZER_DEF_ABI 19 | 20 | 21 | static PyObject *rabbitizer_enum_Abi_fromStr(UNUSED PyObject *self, PyObject *args, PyObject *kwds) { 22 | static char *kwlist[] = { "name", NULL }; 23 | const char *name = NULL; 24 | RabbitizerAbi abi; 25 | PyObject *ret; 26 | 27 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "z", kwlist, &name)) { 28 | return NULL; 29 | } 30 | 31 | abi = RabbitizerAbi_fromStr(name); 32 | 33 | ret = rabbitizer_enum_Abi_enumvalues[abi].instance; 34 | Py_INCREF(ret); 35 | return ret; 36 | } 37 | 38 | 39 | #define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_Abi_##name, METH_NOARGS, PyDoc_STR(docs) } 40 | #define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_Abi_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } 41 | 42 | static PyMethodDef rabbitizer_enum_Abi_methods[] = { 43 | METHOD_ARGS(fromStr, ""), 44 | 45 | { 0 }, 46 | }; 47 | 48 | DEF_ENUM(Abi, "") 49 | -------------------------------------------------------------------------------- /tables/tables/instr_id/cpu/cpu_cop2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 ----------------------------------------0 6 | | = COP0 | fmt | | 7 | ------6----------5----------------------------------------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | MFC2 | --- | CFC2 | --- | MTC2 | --- | CTC2 | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // OP rt, cop2cd 17 | RABBITIZER_DEF_INSTR_ID( 18 | cpu, 0x00, mfc2, 19 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_cop2cd}, 20 | .modifiesRt=true 21 | ) 22 | RABBITIZER_DEF_INSTR_ID( 23 | cpu, 0x04, mtc2, 24 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_cop2cd}, 25 | .readsRt=true 26 | ) 27 | 28 | // OP rt, cop2cd 29 | RABBITIZER_DEF_INSTR_ID( 30 | cpu, 0x02, cfc2, 31 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_cop2cd}, 32 | .modifiesRt=true 33 | ) 34 | RABBITIZER_DEF_INSTR_ID( 35 | cpu, 0x06, ctc2, 36 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_cop2cd}, 37 | .readsRt=true 38 | ) 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_suggestion.yml: -------------------------------------------------------------------------------- 1 | name: Feature suggestion 2 | description: Suggest a new feature (cool new ideas are interesting to hear about) 3 | title: "[Suggestion]: " 4 | labels: ["enhancement"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for suggesting a new feature! 10 | - type: textarea 11 | id: the-feature 12 | attributes: 13 | label: Explain the feature 14 | description: What does this new feature do? How it would be done? 15 | placeholder: | 16 | - Print capybara ascii art on each run 17 | - Introduce achievements 18 | - Play the Oof sound on errors 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: advantage 23 | attributes: 24 | label: Advantage 25 | description: What are the pros of this new feature? 26 | placeholder: | 27 | - XYZ is a common case. 28 | - The produced assembly would be more correct because... 29 | - Would fix Windows builds. 30 | - type: textarea 31 | id: disadvantage 32 | attributes: 33 | label: Disadvantage 34 | description: What could be any drawback of the new feature? 35 | placeholder: | 36 | - Slower runtime. 37 | - Harder to debug. 38 | - Would fix Windows builds. 39 | - type: textarea 40 | id: example 41 | attributes: 42 | label: Example(s) 43 | description: Include examples on how this feature would look like or related info. 44 | validations: 45 | required: true 46 | -------------------------------------------------------------------------------- /rust/src/register_descriptor.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #[repr(C)] 5 | #[derive(Debug, Copy, Clone)] 6 | #[allow(non_camel_case_types)] 7 | pub struct RegisterDescriptor { 8 | is_clobbered_by_func_call: bool, 9 | is_reserved: bool, 10 | is_kernel: bool, 11 | is_zero: bool, 12 | is_at: bool, 13 | is_return_reg: bool, 14 | is_ra: bool, 15 | is_stack_pointer: bool, 16 | is_gp: bool, 17 | is_temp: bool, 18 | is_arg: bool, 19 | is_saved: bool, 20 | } 21 | 22 | impl RegisterDescriptor { 23 | pub fn is_clobbered_by_func_call(&self) -> bool { 24 | self.is_clobbered_by_func_call 25 | } 26 | pub fn is_reserved(&self) -> bool { 27 | self.is_reserved 28 | } 29 | pub fn is_kernel(&self) -> bool { 30 | self.is_kernel 31 | } 32 | pub fn is_zero(&self) -> bool { 33 | self.is_zero 34 | } 35 | pub fn is_at(&self) -> bool { 36 | self.is_at 37 | } 38 | pub fn is_return_reg(&self) -> bool { 39 | self.is_return_reg 40 | } 41 | pub fn is_ra(&self) -> bool { 42 | self.is_ra 43 | } 44 | pub fn is_stack_pointer(&self) -> bool { 45 | self.is_stack_pointer 46 | } 47 | pub fn is_gp(&self) -> bool { 48 | self.is_gp 49 | } 50 | pub fn is_temp(&self) -> bool { 51 | self.is_temp 52 | } 53 | pub fn is_arg(&self) -> bool { 54 | self.is_arg 55 | } 56 | pub fn is_saved(&self) -> bool { 57 | self.is_saved 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_cop2_bc2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21-20------16------------------------------0 6 | | = COP0 | BC2 | fmt | | 7 | ------6----------5----------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BC2F | BC2T | BC2FL | BC2TL | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // TODO: operands and properties 17 | 18 | RABBITIZER_DEF_INSTR_ID( 19 | r5900, 0x00, bc2f, 20 | .operands={RAB_OPERAND_cpu_branch_target_label}, 21 | .isBranch=true 22 | ) 23 | RABBITIZER_DEF_INSTR_ID( 24 | r5900, 0x01, bc2t, 25 | .operands={RAB_OPERAND_cpu_branch_target_label}, 26 | .isBranch=true 27 | ) 28 | RABBITIZER_DEF_INSTR_ID( 29 | r5900, 0x02, bc2fl, 30 | .operands={RAB_OPERAND_cpu_branch_target_label}, 31 | .isBranch=true, 32 | .isBranchLikely=true 33 | ) 34 | RABBITIZER_DEF_INSTR_ID( 35 | r5900, 0x03, bc2tl, 36 | .operands={RAB_OPERAND_cpu_branch_target_label}, 37 | .isBranch=true, 38 | .isBranchLikely=true 39 | ) 40 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop2_mthc2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 -------------------------7--------------0 6 | | = COP2 | MFHC2 | |p| | 7 | ------6----------5-------------------------------1--------------- 8 | |---------------0---------------|---------------1---------------| p 9 | | mtv | mtvc | 10 | |-------------------------------|-------------------------------| 11 | */ 12 | 13 | /* 14 | mtv 15 | 31--------26-25-----21-20-----16-----------------7-6------------0 16 | | COP2 |0 0 1 1 1| rt |0 0 0 0 0 0 0 0|0| vd | 17 | ------6----------5---------5---------------------1-------7------- 18 | */ 19 | 20 | RABBITIZER_DEF_INSTR_ID( 21 | r4000allegrex, 0x0, mtv, 22 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r4000allegrex_s_vd}, 23 | .instrType=RABBITIZER_INSTR_TYPE_R, 24 | .readsRt=true 25 | ) // Move word To Vfpu 26 | 27 | /* 28 | mtvc 29 | 31--------26-25-----21-20-----16-----------------7-6------------0 30 | | COP2 |0 0 1 1 1| rt |0 0 0 0 0 0 0 0|1| cop2cd | 31 | ------6----------5---------5---------------------1-------7------- 32 | */ 33 | 34 | RABBITIZER_DEF_INSTR_ID( 35 | r4000allegrex, 0x1, mtvc, 36 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r4000allegrex_cop2cd}, 37 | .instrType=RABBITIZER_INSTR_TYPE_R, 38 | .readsRt=true 39 | ) // Move word To Vfpu Control 40 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_cop2_i.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2025 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 --------------------------------------1-0 6 | | = COP2 | fmt | |1| 7 | ------6----------5---------------------------------------------1- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | --- |QMFC2.I| CFC2.I| --- | --- |QMTC2.I| CTC2.I| --- | 10 | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | 12 | 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | *1 = BC instructions, see BC2 list *2 =see special1 table 15 | */ 16 | 17 | // TODO: properties 18 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 19 | r5900, 0x01, qmfc2_i, qmfc2.i, 20 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vfs}, 21 | .modifiesRt=true 22 | ) 23 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 24 | r5900, 0x02, cfc2_i, cfc2.i, 25 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vis}, 26 | .modifiesRt=true 27 | ) 28 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 29 | r5900, 0x05, qmtc2_i, qmtc2.i, 30 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vfs}, 31 | .readsRt=true 32 | ) 33 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 34 | r5900, 0x06, ctc2_i, ctc2.i, 35 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vis}, 36 | .readsRt=true 37 | ) 38 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_cop2_ni.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2025 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21 --------------------------------------1-0 6 | | = COP2 | fmt | |0| 7 | ------6----------5---------------------------------------------1- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | --- |QMFC2.NI|CFC2.NI| --- | --- |QMTC2.NI|CTC2.NI| --- | 10 | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | 12 | 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | *1 = BC instructions, see BC2 list *2 =see special1 table 15 | */ 16 | 17 | // TODO: properties 18 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 19 | r5900, 0x01, qmfc2_ni, qmfc2.ni, 20 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vfs}, 21 | .modifiesRt=true 22 | ) 23 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 24 | r5900, 0x02, cfc2_ni, cfc2.ni, 25 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vis}, 26 | .modifiesRt=true 27 | ) 28 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 29 | r5900, 0x05, qmtc2_ni, qmtc2.ni, 30 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vfs}, 31 | .readsRt=true 32 | ) 33 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 34 | r5900, 0x06, ctc2_ni, ctc2.ni, 35 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_r5900_vis}, 36 | .readsRt=true 37 | ) 38 | -------------------------------------------------------------------------------- /rust/src/opereand_type.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | use crate::{instruction, operand_type_enum, utils}; 5 | 6 | extern "C" { 7 | fn RabbitizerOperandType_getBufferSize( 8 | operand: operand_type_enum::OperandType, 9 | instr: *const instruction::Instruction, 10 | immOverrideLength: utils::SizeT, 11 | ) -> utils::SizeT; 12 | 13 | fn RabbitizerOperandType_disassemble( 14 | operand: operand_type_enum::OperandType, 15 | instr: *const instruction::Instruction, 16 | dst: *mut core::ffi::c_char, 17 | immOverride: *const core::ffi::c_char, 18 | immOverrideLength: utils::SizeT, 19 | ) -> utils::SizeT; 20 | } 21 | 22 | impl operand_type_enum::OperandType { 23 | pub fn disassemble( 24 | &self, 25 | instr: &instruction::Instruction, 26 | imm_override: Option<&str>, 27 | ) -> String { 28 | let (imm_override_ptr, imm_override_len) = utils::c_string_from_str(imm_override); 29 | 30 | unsafe { 31 | let buffer_size = RabbitizerOperandType_getBufferSize(*self, instr, imm_override_len); 32 | 33 | let mut buffer: Vec = vec![0; buffer_size + 1]; 34 | let disassembled_size = RabbitizerOperandType_disassemble( 35 | *self, 36 | instr, 37 | buffer.as_mut_ptr() as *mut core::ffi::c_char, 38 | imm_override_ptr, 39 | imm_override_len, 40 | ); 41 | buffer.truncate(disassembled_size); 42 | 43 | String::from_utf8(buffer).unwrap() 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/check_format.yml: -------------------------------------------------------------------------------- 1 | name: Check for format changes 2 | 3 | # Build on every branch push, tag push, and pull request change: 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | check_format: 8 | name: Check format 9 | runs-on: ubuntu-22.04 10 | 11 | steps: 12 | - name: Checkout reposistory 13 | uses: actions/checkout@main 14 | 15 | - name: Install dependencies 16 | run: sudo apt install clang-format-11 17 | 18 | - name: make format 19 | run: make -j $(nproc) format 20 | 21 | - name: Check if there are format changes 22 | id: format_changes 23 | uses: tj-actions/verify-changed-files@v14 24 | 25 | - name: format changes 26 | if: steps.format_changes.outputs.files_changed == 'true' 27 | run: | 28 | echo "Changed files: ${{ steps.format_changes.outputs.changed_files }}" 29 | echo "Please run \`make format\` and commit the result" 30 | exit 1 31 | 32 | check_tidy: 33 | name: Check tidy 34 | runs-on: ubuntu-22.04 35 | 36 | steps: 37 | - name: Checkout reposistory 38 | uses: actions/checkout@main 39 | 40 | - name: Install dependencies 41 | run: sudo apt install clang-tidy-11 42 | 43 | - name: make tidy 44 | run: make -j $(nproc) tidy 45 | 46 | - name: Check if there are tidy changes 47 | id: tidy_changes 48 | uses: tj-actions/verify-changed-files@v14 49 | 50 | - name: tidy changes 51 | if: steps.tidy_changes.outputs.files_changed == 'true' 52 | run: | 53 | echo "Changed files: ${{ steps.tidy_changes.outputs.changed_files }}" 54 | echo "Please run \`make tidy\` and commit the result" 55 | exit 1 56 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_special2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26------------------------------------------5--------0 6 | | =SPECIAL2 | | function| 7 | ------6----------------------------------------------------6----- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 000 | SLEEP | --- | --- | --- | --- | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | --- | --- | --- | --- | MFIE | --- | MTIE | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | --- | --- | --- | --- | 17 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 18 | */ 19 | 20 | // OP 21 | 22 | RABBITIZER_DEF_INSTR_ID( 23 | r4000allegrex, 0x00, sleep, 24 | .operands={0}, 25 | .instrType=RABBITIZER_INSTR_TYPE_R 26 | ) 27 | 28 | RABBITIZER_DEF_INSTR_ID( 29 | r4000allegrex, 0x24, mfie, 30 | .operands={RAB_OPERAND_cpu_rt}, 31 | .instrType=RABBITIZER_INSTR_TYPE_R, 32 | .modifiesRt=true 33 | ) 34 | 35 | RABBITIZER_DEF_INSTR_ID( 36 | r4000allegrex, 0x26, mtie, 37 | .operands={RAB_OPERAND_cpu_rt}, 38 | .instrType=RABBITIZER_INSTR_TYPE_R, 39 | .readsRt=true 40 | ) 41 | -------------------------------------------------------------------------------- /rabbitizer/enums/rabbitizer_enum_InstrCategory.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "enums_utils.h" 5 | #include "instructions/RabbitizerInstruction.h" 6 | 7 | 8 | #define RABBITIZER_DEF_INSTR_CATEGORY(name) { "InstrCategory", #name, RABBITIZER_INSTRCAT_##name, false, NULL }, 9 | 10 | RabbitizerEnumMetadata rabbitizer_enum_InstrCategory_enumvalues[] = { 11 | #include "tables/InstrCategory.inc" 12 | RABBITIZER_DEF_INSTR_CATEGORY(MAX) 13 | 14 | { 0 }, 15 | }; 16 | 17 | #undef RABBITIZER_DEF_INSTR_CATEGORY 18 | 19 | 20 | static PyObject *rabbitizer_enum_InstrCategory_fromStr(UNUSED PyObject *self, PyObject *args, PyObject *kwds) { 21 | static char *kwlist[] = { "name", NULL }; 22 | const char *name = NULL; 23 | RabbitizerInstrCategory instrCategory; 24 | PyObject *ret; 25 | 26 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "z", kwlist, &name)) { 27 | return NULL; 28 | } 29 | 30 | instrCategory = RabbitizerInstrCategory_fromStr(name); 31 | if ((int)instrCategory < 0) { 32 | Py_RETURN_NONE; 33 | } 34 | 35 | ret = rabbitizer_enum_InstrCategory_enumvalues[instrCategory].instance; 36 | Py_INCREF(ret); 37 | return ret; 38 | } 39 | 40 | 41 | #define METHOD_NO_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_InstrCategory_##name, METH_NOARGS, PyDoc_STR(docs) } 42 | #define METHOD_ARGS(name, docs) { #name, (PyCFunction) (void *) rabbitizer_enum_InstrCategory_##name, METH_VARARGS | METH_KEYWORDS, PyDoc_STR(docs) } 43 | 44 | static PyMethodDef rabbitizer_enum_InstrCategory_methods[] = { 45 | METHOD_ARGS(fromStr, ""), 46 | 47 | { 0 }, 48 | }; 49 | 50 | DEF_ENUM(InstrCategory, "") 51 | -------------------------------------------------------------------------------- /tables/tables/instr_id/cpu/cpu_cop1_bc1.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21-20------16------------------------------0 6 | | = COP1 | BC1 | fmt | | 7 | ------6----------5----------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // OP IMM 17 | RABBITIZER_DEF_INSTR_ID( 18 | cpu, 0x00, bc1f, 19 | .operands={RAB_OPERAND_cpu_branch_target_label}, 20 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 21 | .isBranch=true 22 | ) 23 | RABBITIZER_DEF_INSTR_ID( 24 | cpu, 0x01, bc1t, 25 | .operands={RAB_OPERAND_cpu_branch_target_label}, 26 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 27 | .isBranch=true 28 | ) 29 | RABBITIZER_DEF_INSTR_ID( 30 | cpu, 0x02, bc1fl, 31 | .operands={RAB_OPERAND_cpu_branch_target_label}, 32 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 33 | .isBranch=true, 34 | .isBranchLikely=true 35 | ) 36 | RABBITIZER_DEF_INSTR_ID( 37 | cpu, 0x03, bc1tl, 38 | .operands={RAB_OPERAND_cpu_branch_target_label}, 39 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 40 | .isBranch=true, 41 | .isBranchLikely=true 42 | ) 43 | -------------------------------------------------------------------------------- /rust/src/config.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | use crate::abi_enum; 5 | 6 | #[repr(C)] 7 | #[derive(Debug, Copy, Clone)] 8 | #[allow(non_camel_case_types)] 9 | pub struct RegisterNames { 10 | pub named_registers: bool, 11 | pub gpr_abi_names: abi_enum::Abi, 12 | pub fpr_abi_names: abi_enum::Abi, 13 | pub user_fpc_csr: bool, 14 | pub vr4300_cop0_named_registers: bool, 15 | pub vr4300_rsp_cop0_named_registers: bool, 16 | } 17 | 18 | #[repr(C)] 19 | #[derive(Debug, Copy, Clone)] 20 | #[allow(non_camel_case_types)] 21 | pub struct PseudoInstr { 22 | pub enable_pseudos: bool, 23 | pub pseudo_beqz: bool, 24 | pub pseudo_bnez: bool, 25 | pub pseudo_b: bool, 26 | pub pseudo_move: bool, 27 | pub pseudo_not: bool, 28 | pub pseudo_neg: bool, 29 | pub pseudo_negu: bool, 30 | pub pseudo_bal: bool, 31 | } 32 | 33 | #[repr(C)] 34 | #[derive(Debug, Copy, Clone)] 35 | #[allow(non_camel_case_types)] 36 | pub struct ToolchainTweaks { 37 | pub treat_j_as_unconditional_branch: bool, 38 | pub sn64_div_fix: bool, 39 | pub gnu_mode: bool, 40 | } 41 | 42 | #[repr(C)] 43 | #[derive(Debug, Copy, Clone)] 44 | #[allow(non_camel_case_types)] 45 | pub struct Misc { 46 | pub opcode_l_just: i32, 47 | pub unknown_instr_comment: bool, 48 | pub omit_0x_on_small_imm: bool, 49 | pub upper_case_imm: bool, 50 | } 51 | 52 | #[repr(C)] 53 | #[derive(Debug, Copy, Clone)] 54 | #[allow(non_camel_case_types)] 55 | pub struct Config { 56 | pub reg_names: RegisterNames, 57 | pub pseudos: PseudoInstr, 58 | pub toolchain_tweaks: ToolchainTweaks, 59 | pub misc: Misc, 60 | } 61 | 62 | extern "C" { 63 | pub static mut RabbitizerConfig_Cfg: Config; 64 | } 65 | -------------------------------------------------------------------------------- /tables/tables/registers/RabbitizerRegister_RspCop0.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | RABBITIZER_DEF_REG_NODOLLAR( 5 | RSP_COP0, SP_MEM_ADDR, 0, 6 | 0 7 | ) 8 | RABBITIZER_DEF_REG_NODOLLAR( 9 | RSP_COP0, SP_DRAM_ADDR, 1, 10 | 0 11 | ) 12 | RABBITIZER_DEF_REG_NODOLLAR( 13 | RSP_COP0, SP_RD_LEN, 2, 14 | 0 15 | ) 16 | RABBITIZER_DEF_REG_NODOLLAR( 17 | RSP_COP0, SP_WR_LEN, 3, 18 | 0 19 | ) 20 | RABBITIZER_DEF_REG_NODOLLAR( 21 | RSP_COP0, SP_STATUS, 4, 22 | 0 23 | ) 24 | RABBITIZER_DEF_REG_NODOLLAR( 25 | RSP_COP0, SP_DMA_FULL, 5, 26 | 0 27 | ) 28 | RABBITIZER_DEF_REG_NODOLLAR( 29 | RSP_COP0, SP_DMA_BUSY, 6, 30 | 0 31 | ) 32 | RABBITIZER_DEF_REG_NODOLLAR( 33 | RSP_COP0, SP_SEMAPHORE, 7, 34 | 0 35 | ) 36 | RABBITIZER_DEF_REG_NODOLLAR( 37 | RSP_COP0, DPC_START, 8, 38 | 0 39 | ) 40 | RABBITIZER_DEF_REG_NODOLLAR( 41 | RSP_COP0, DPC_END, 9, 42 | 0 43 | ) 44 | RABBITIZER_DEF_REG_NODOLLAR( 45 | RSP_COP0, DPC_CURRENT, 10, 46 | 0 47 | ) 48 | RABBITIZER_DEF_REG_NODOLLAR( 49 | RSP_COP0, DPC_STATUS, 11, 50 | 0 51 | ) 52 | RABBITIZER_DEF_REG_NODOLLAR( 53 | RSP_COP0, DPC_CLOCK, 12, 54 | 0 55 | ) 56 | RABBITIZER_DEF_REG_NODOLLAR( 57 | RSP_COP0, DPC_BUFBUSY, 13, 58 | 0 59 | ) 60 | RABBITIZER_DEF_REG_NODOLLAR( 61 | RSP_COP0, DPC_PIPEBUSY, 14, 62 | 0 63 | ) 64 | RABBITIZER_DEF_REG_NODOLLAR( 65 | RSP_COP0, DPC_TMEM, 15, 66 | 0 67 | ) 68 | -------------------------------------------------------------------------------- /src/common/RabbitizerConfig.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "common/RabbitizerConfig.h" 5 | 6 | #include 7 | 8 | RabbitizerAbi RabbitizerAbi_fromStr(const char *name) { 9 | if (name == NULL || strcmp(name, "32") == 0 || strcmp(name, "o32") == 0 || strcmp(name, "O32") == 0) { 10 | return RABBITIZER_ABI_O32; 11 | } 12 | if (strcmp(name, "n32") == 0 || strcmp(name, "N32") == 0) { 13 | return RABBITIZER_ABI_N32; 14 | } 15 | if (strcmp(name, "64") == 0 || strcmp(name, "n64") == 0 || strcmp(name, "N64") == 0) { 16 | return RABBITIZER_ABI_N64; 17 | } 18 | return RABBITIZER_ABI_NUMERIC; 19 | } 20 | 21 | RabbitizerConfig RabbitizerConfig_Cfg = { 22 | .regNames = { 23 | .namedRegisters = true, 24 | .gprAbiNames = RABBITIZER_ABI_O32, 25 | .fprAbiNames = RABBITIZER_ABI_NUMERIC, 26 | .userFpcCsr = true, 27 | .vr4300Cop0NamedRegisters = true, 28 | .vr4300RspCop0NamedRegisters = true, 29 | .r4000AllegrexVfpuControlNamedRegisters = false, 30 | }, 31 | .pseudos = { 32 | .enablePseudos = true, 33 | .pseudoBeqz = true, 34 | .pseudoBnez = true, 35 | .pseudoB = true, 36 | .pseudoMove = true, 37 | .pseudoNot = true, 38 | .pseudoNeg = true, 39 | .pseudoNegu = true, 40 | .pseudoBal = true, 41 | }, 42 | .toolchainTweaks = { 43 | .treatJAsUnconditionalBranch = true, 44 | .sn64DivFix = false, 45 | .gnuMode = true, 46 | }, 47 | .misc = { 48 | .opcodeLJust = 7+4, 49 | .unknownInstrComment = true, 50 | .omit0XOnSmallImm = false, 51 | .upperCaseImm = true, 52 | .expandJalr = false, 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_special3.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26------------------------------------------5--------0 6 | | =SPECIAL3 | | function| 7 | ------6----------------------------------------------------6----- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 000 | EXT | --- | --- | --- | INS | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | *1 | --- | --- | --- | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | --- | --- | --- | --- | 17 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 18 | *1 = SPECIAL3 BSHFL 19 | */ 20 | 21 | RABBITIZER_DEF_INSTR_ID( 22 | r4000allegrex, 0x00, ext, 23 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_rs, RAB_OPERAND_r4000allegrex_pos, RAB_OPERAND_r4000allegrex_size}, 24 | .instrType=RABBITIZER_INSTR_TYPE_R, 25 | .modifiesRt=true, 26 | .readsRs=true 27 | ) // EXTract bit field 28 | 29 | RABBITIZER_DEF_INSTR_ID( 30 | r4000allegrex, 0x04, ins, 31 | .operands={RAB_OPERAND_cpu_rt, RAB_OPERAND_cpu_rs, RAB_OPERAND_r4000allegrex_pos, RAB_OPERAND_r4000allegrex_size_plus_pos}, 32 | .instrType=RABBITIZER_INSTR_TYPE_R, 33 | .modifiesRt=true, 34 | .readsRs=true 35 | ) // INSert bit field 36 | -------------------------------------------------------------------------------- /rabbitizer/RegistersTracker.pyi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # SPDX-FileCopyrightText: © 2022-2024 Decompollaborate 4 | # SPDX-License-Identifier: MIT 5 | 6 | from __future__ import annotations 7 | 8 | from .rabbitizer import Instruction 9 | from .LoPairingInfo import LoPairingInfo 10 | from .JrRegData import JrRegData 11 | 12 | 13 | class RegistersTracker: 14 | def __init__(self, other: RegistersTracker|None=None): ... 15 | 16 | def moveRegisters(self, instr: Instruction) -> bool: ... 17 | def overwriteRegisters(self, instr: Instruction, instructionOffset: int) -> None: ... 18 | def unsetRegistersAfterFuncCall(self, instr: Instruction, prevInstr: Instruction) -> None: ... 19 | def getAddressIfCanSetType(self, instr: Instruction, instrOffset: int) -> int|None: ... 20 | #! deprecated: use `getJrRegData` instead 21 | def getJrInfo(self, instr: Instruction) -> tuple[int, int]|None: ... 22 | def getJrRegData(self, instr: Instruction) -> JrRegData: ... 23 | 24 | def processLui(self, instr: Instruction, instrOffset: int, prevInstr: Instruction|None=None) -> None: ... 25 | def processGpLoad(self, instr: Instruction, instrOffset: int) -> None: ... 26 | def getLuiOffsetForConstant(self, instr: Instruction) -> int|None: ... 27 | def processConstant(self, instr: Instruction, value: int, offset: int) -> None: ... 28 | def getLuiOffsetForLo(self, instr: Instruction, instrOffset: int) -> tuple[int, bool, bool]: #! deprecated 29 | """Use `.preprocessLoAndGetInfo()` instead""" 30 | def preprocessLoAndGetInfo(self, instr: Instruction, instrOffset: int) -> LoPairingInfo: ... 31 | def processLo(self, instr: Instruction, value: int, offset: int) -> None: ... 32 | def processBranch(self, instr: Instruction, instrOffset: int) -> None: ... 33 | def hasLoButNoHi(self, instr: Instruction) -> bool: ... 34 | -------------------------------------------------------------------------------- /tables/tables/instr_id/rsp/rsp_regimm.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | // OP rs, IMM 5 | RABBITIZER_DEF_INSTR_ID( 6 | rsp, 0x00, bltz, 7 | .operands={RAB_OPERAND_rsp_rs, RAB_OPERAND_cpu_branch_target_label}, 8 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 9 | .readsRs=true, 10 | .isBranch=true 11 | ) // Branch on Less Than Zero 12 | RABBITIZER_DEF_INSTR_ID( 13 | rsp, 0x01, bgez, 14 | .operands={RAB_OPERAND_rsp_rs, RAB_OPERAND_cpu_branch_target_label}, 15 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 16 | .readsRs=true, 17 | .isBranch=true 18 | ) // Branch on Greater than or Equal to Zero 19 | 20 | RABBITIZER_DEF_INSTR_ID( 21 | rsp, 0x10, bltzal, 22 | .operands={RAB_OPERAND_rsp_rs, RAB_OPERAND_cpu_branch_target_label}, 23 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 24 | .readsRs=true, 25 | .isBranch=true, 26 | .doesLink=true 27 | ) // Branch on Less Than Zero and Link 28 | RABBITIZER_DEF_INSTR_ID( 29 | rsp, 0x11, bgezal, 30 | .operands={RAB_OPERAND_rsp_rs, RAB_OPERAND_cpu_branch_target_label}, 31 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 32 | .readsRs=true, 33 | .isBranch=true, 34 | .notEmittedByCompilers=true, 35 | .doesLink=true 36 | ) // Branch on Greater Than or Equal to Zero and Link 37 | 38 | 39 | // Pseudo-Instruction Unique IDs 40 | 41 | RABBITIZER_DEF_INSTR_ID( 42 | rsp, -0x11, bal, 43 | .operands={RAB_OPERAND_cpu_branch_target_label}, 44 | .instrType=RABBITIZER_INSTR_TYPE_REGIMM, 45 | .isBranch=true, 46 | .notEmittedByCompilers=true, 47 | .doesLink=true, 48 | .isPseudo=true 49 | ) // Branch and Link 50 | -------------------------------------------------------------------------------- /tables/tables/instr_id/cpu/cpu_cop0_bc0.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25------21-20------16------------------------------0 6 | | = COP0 | BC0 | fmt | | 7 | ------6----------5----------5------------------------------------ 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // OP IMM 17 | RABBITIZER_DEF_INSTR_ID( 18 | cpu, 0x00, bc0f, 19 | .operands={RAB_OPERAND_cpu_branch_target_label}, 20 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 21 | .isBranch=true 22 | ) // Branch on FP False 23 | RABBITIZER_DEF_INSTR_ID( 24 | cpu, 0x01, bc0t, 25 | .operands={RAB_OPERAND_cpu_branch_target_label}, 26 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 27 | .isBranch=true 28 | ) // Branch on FP True 29 | RABBITIZER_DEF_INSTR_ID( 30 | cpu, 0x02, bc0fl, 31 | .operands={RAB_OPERAND_cpu_branch_target_label}, 32 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 33 | .isBranch=true, 34 | .isBranchLikely=true 35 | ) // Branch on FP False Likely 36 | RABBITIZER_DEF_INSTR_ID( 37 | cpu, 0x03, bc0tl, 38 | .operands={RAB_OPERAND_cpu_branch_target_label}, 39 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 40 | .isBranch=true, 41 | .isBranchLikely=true 42 | ) // Branch on FP True Likely 43 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerRegisterDescriptor.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerRegisterDescriptor.h" 5 | 6 | #include "instructions/RabbitizerRegister.h" 7 | 8 | #include "generated/RegisterDescriptor_Descriptors_arrays.h" 9 | 10 | bool RabbitizerRegisterDescriptor_isClobberedByFuncCall(const RabbitizerRegisterDescriptor *self) { 11 | return self->isClobberedByFuncCall; 12 | } 13 | bool RabbitizerRegisterDescriptor_isReserved(const RabbitizerRegisterDescriptor *self) { 14 | return self->isReserved; 15 | } 16 | bool RabbitizerRegisterDescriptor_isKernel(const RabbitizerRegisterDescriptor *self) { 17 | return self->isKernel; 18 | } 19 | bool RabbitizerRegisterDescriptor_isZero(const RabbitizerRegisterDescriptor *self) { 20 | return self->isZero; 21 | } 22 | bool RabbitizerRegisterDescriptor_isAt(const RabbitizerRegisterDescriptor *self) { 23 | return self->isAt; 24 | } 25 | bool RabbitizerRegisterDescriptor_isReturnReg(const RabbitizerRegisterDescriptor *self) { 26 | return self->isReturnReg; 27 | } 28 | bool RabbitizerRegisterDescriptor_isRa(const RabbitizerRegisterDescriptor *self) { 29 | return self->isRa; 30 | } 31 | bool RabbitizerRegisterDescriptor_isStackPointer(const RabbitizerRegisterDescriptor *self) { 32 | return self->isStackPointer; 33 | } 34 | bool RabbitizerRegisterDescriptor_isGp(const RabbitizerRegisterDescriptor *self) { 35 | return self->isGp; 36 | } 37 | bool RabbitizerRegisterDescriptor_isTemp(const RabbitizerRegisterDescriptor *self) { 38 | return self->isTemp; 39 | } 40 | bool RabbitizerRegisterDescriptor_isArg(const RabbitizerRegisterDescriptor *self) { 41 | return self->isArg; 42 | } 43 | bool RabbitizerRegisterDescriptor_isSaved(const RabbitizerRegisterDescriptor *self) { 44 | return self->isSaved; 45 | } 46 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_vfpu4_fmt0_control.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25--23-----19----16-----------------7--------------0 6 | | VFPU4 |0 0|0 1 0 0 1| fmt |t| |p| | 7 | ------6-------2------5-------3---1---------------1--------------- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| fmt 9 | 00 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | 01 | --- | vmtvc | --- | --- | --- | --- | --- | --- | 11 | 10 | vmfvc | --- | --- | --- | --- | --- | --- | --- | 12 | 11 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | tp |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | /* 17 | vmfvc 18 | 31--------26-25-24--21--19----16---14----------8---6------------0 19 | | VFPU4 |0 0|0 1 0|1 0|0 0 0|1| cop2cs |0| vd | 20 | ------6-------2----3----2----3---1-------7---------------7------- 21 | */ 22 | 23 | RABBITIZER_DEF_INSTR_ID( 24 | r4000allegrex, 0x00 << 2 | 0x2, vmfvc, 25 | .operands={RAB_OPERAND_r4000allegrex_s_vd, RAB_OPERAND_r4000allegrex_cop2cs}, 26 | .instrType=RABBITIZER_INSTR_TYPE_R 27 | ) // VFPU Move Word from VFPU Control 28 | 29 | /* 30 | vmtvc 31 | 31--------26-25-24--21--19----16---14----------8---6------------0 32 | | VFPU4 |0 0|0 1 0|1 0|0 0 1|0| vs |1| cop2cd | 33 | ------6-------2----3----2----3-----------7-------1-------7------- 34 | */ 35 | 36 | RABBITIZER_DEF_INSTR_ID( 37 | r4000allegrex, 0x01 << 2 | 0x1, vmtvc, 38 | .operands={RAB_OPERAND_r4000allegrex_cop2cd, RAB_OPERAND_r4000allegrex_s_vs}, 39 | .instrType=RABBITIZER_INSTR_TYPE_R 40 | ) // VFPU Move Word to VFPU Control 41 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_cop2_bc2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31--------26-25-----21------17-16-------------------------------0 6 | | = COP2 | BC2 | |fmt| | 7 | ------6----------5------------2---------------------------------- 8 | |---------------0---------------|---------------1---------------| lo 9 | 0 | BVF | BVT | 10 | 1 | BVFL | BVTL | 11 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 12 | */ 13 | 14 | // OP IMM 15 | RABBITIZER_DEF_INSTR_ID( 16 | r4000allegrex, 0x00, bvf, 17 | .operands={RAB_OPERAND_r4000allegrex_imm3, RAB_OPERAND_cpu_branch_target_label}, 18 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 19 | .isBranch=true 20 | ) // Branch on Vfpu False 21 | RABBITIZER_DEF_INSTR_ID( 22 | r4000allegrex, 0x01, bvt, 23 | .operands={RAB_OPERAND_r4000allegrex_imm3, RAB_OPERAND_cpu_branch_target_label}, 24 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 25 | .isBranch=true 26 | ) // Branch on Vfpu True 27 | RABBITIZER_DEF_INSTR_ID( 28 | r4000allegrex, 0x02, bvfl, 29 | .operands={RAB_OPERAND_r4000allegrex_imm3, RAB_OPERAND_cpu_branch_target_label}, 30 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 31 | .isBranch=true, 32 | .isBranchLikely=true 33 | ) // Branch on Vfpu False Likely 34 | RABBITIZER_DEF_INSTR_ID( 35 | r4000allegrex, 0x03, bvtl, 36 | .operands={RAB_OPERAND_r4000allegrex_imm3, RAB_OPERAND_cpu_branch_target_label}, 37 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 38 | .isBranch=true, 39 | .isBranchLikely=true 40 | ) // Branch on Vfpu True Likely 41 | -------------------------------------------------------------------------------- /tables/tables/instr_id/cpu/cpu_cop1_fpu_l.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31----------26-25--------21 -----------------------------------------5----------0 6 | | = COP1 | = L | | function | 7 | -------6------------5-----------------------------------------------------6------ 8 | |---000---|---001---|---010---|---011---|---100---|---101---|---110---|---111---| lo 9 | 000 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | CVT.S.L | CVT.D.L | --- | --- | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | --- | --- | --- | --- | 17 | hi |---------|---------|---------|---------|---------|---------|---------|---------| 18 | */ 19 | 20 | // OP fd, fs 21 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 22 | cpu, 0x20, cvt_s_l, cvt.s.l, 23 | .operands={RAB_OPERAND_cpu_fd, RAB_OPERAND_cpu_fs}, 24 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 25 | .isFloat=true, 26 | .modifiesFd=true, 27 | .readsFs=true 28 | ) 29 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 30 | cpu, 0x21, cvt_d_l, cvt.d.l, 31 | .operands={RAB_OPERAND_cpu_fd, RAB_OPERAND_cpu_fs}, 32 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 33 | .isFloat=true, 34 | .isDouble=true, 35 | .modifiesFd=true, 36 | .readsFs=true 37 | ) 38 | -------------------------------------------------------------------------------- /tables/tables/instr_id/cpu/cpu_cop1_fpu_w.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31----------26-25--------21 -----------------------------------------5----------0 6 | | = COP1 | = W | | function | 7 | -------6------------5-----------------------------------------------------6------ 8 | |---000---|---001---|---010---|---011---|---100---|---101---|---110---|---111---| lo 9 | 000 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 13 | 100 | CVT.S.W | CVT.D.W | --- | --- | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | --- | --- | --- | --- | 17 | hi |---------|---------|---------|---------|---------|---------|---------|---------| 18 | */ 19 | 20 | // OP fd, fs 21 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 22 | cpu, 0x20, cvt_s_w, cvt.s.w, 23 | .operands={RAB_OPERAND_cpu_fd, RAB_OPERAND_cpu_fs}, 24 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 25 | .isFloat=true, 26 | .modifiesFd=true, 27 | .readsFs=true 28 | ) 29 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 30 | cpu, 0x21, cvt_d_w, cvt.d.w, 31 | .operands={RAB_OPERAND_cpu_fd, RAB_OPERAND_cpu_fs}, 32 | .instrType=RABBITIZER_INSTR_TYPE_UNKNOWN, 33 | .isFloat=true, 34 | .isDouble=true, 35 | .modifiesFd=true, 36 | .readsFs=true 37 | ) 38 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_special.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26------------------------------------------5--------0 6 | | = SPECIAL | | function| 7 | ------6----------------------------------------------------6----- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 000 | SLL | --- | SRL | SRA | SLLV | --- | SRLV | SRAV | 10 | 001 | JR | JALR | MOVZ | MOVN |SYSCALL| BREAK | --- | SYNC | 11 | 010 | MFHI | MTHI | MFLO | MTLO | DSLLV | --- | DSRLV | DSRAV | 12 | 011 | MULT | MULTU | DIV | DIVU | ---- | --- | ---- | ----- | 13 | 100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR | 14 | 101 | MFSA | MTSA | SLT | SLTU | DADD | DADDU | DSUB | DSUBU | 15 | 110 | TGE | TGEU | TLT | TLTU | TEQ | --- | TNE | --- | 16 | 111 | DSLL | --- | DSRL | DSRA |DSLL32 | --- |DSRL32 |DSRA32 | 17 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 18 | */ 19 | 20 | // The other instructions are implemented using the main CPU table 21 | 22 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 23 | r5900, -0x0F, sync_p, sync.p, 24 | .operands={0}, 25 | .instrType=RABBITIZER_INSTR_TYPE_R 26 | ) // Sync 27 | 28 | RABBITIZER_DEF_INSTR_ID( 29 | r5900, 0x18, mult, 30 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_rt}, 31 | .instrType=RABBITIZER_INSTR_TYPE_R, 32 | .modifiesRd=true, 33 | .readsRs=true, 34 | .readsRt=true 35 | ) // MULTtiply word 36 | 37 | RABBITIZER_DEF_INSTR_ID( 38 | r5900, 0x28, mfsa, 39 | .operands={RAB_OPERAND_cpu_rd}, 40 | .modifiesRd=true 41 | ) // Move From Shift Amount register 42 | RABBITIZER_DEF_INSTR_ID( 43 | r5900, 0x29, mtsa, 44 | .operands={RAB_OPERAND_cpu_rs}, 45 | .readsRs=true 46 | ) // Move To Shift Amount register 47 | -------------------------------------------------------------------------------- /tests/asm/r4000allegrex/sceVfpuMatrix3Transform.c: -------------------------------------------------------------------------------- 1 | typedef struct ScePspFVector3 { 2 | float x, y, z; 3 | } ScePspFVector3; 4 | 5 | typedef struct ScePspFMatrix3 { 6 | ScePspFVector3 x, y, z; 7 | } ScePspFMatrix3; 8 | 9 | ScePspFVector3 *sceVfpuMatrix3Transform(ScePspFVector3 *pv0, const ScePspFMatrix3 *pm1, const ScePspFVector3 *pv2) 10 | { 11 | #if 0 12 | pv0->x = (pm1->x.x * pv2->x) + (pm1->y.x * pv2->y) + (pm1->z.x * pv2->z); 13 | pv0->y = (pm1->x.y * pv2->x) + (pm1->y.y * pv2->y) + (pm1->z.y * pv2->z); 14 | pv0->z = (pm1->x.z * pv2->x) + (pm1->y.z * pv2->y) + (pm1->z.z * pv2->z); 15 | #else 16 | __asm__ ( 17 | ".set push\n" // save assembler option 18 | ".set noreorder\n" // suppress reordering 19 | "lv.s s100, 0 + %1\n" // s100 = pm1->x.x 20 | "lv.s s101, 4 + %1\n" // s101 = pm1->x.y 21 | "lv.s s102, 8 + %1\n" // s102 = pm1->x.z 22 | "lv.s s110, 12 + %1\n" // s110 = pm1->y.x 23 | "lv.s s111, 16 + %1\n" // s111 = pm1->y.y 24 | "lv.s s112, 20 + %1\n" // s112 = pm1->y.z 25 | "lv.s s120, 24 + %1\n" // s120 = pm1->z.x 26 | "lv.s s121, 28 + %1\n" // s121 = pm1->z.y 27 | "lv.s s122, 32 + %1\n" // s122 = pm1->z.z 28 | "lv.s s200, 0 + %2\n" // s200 = pv2->x 29 | "lv.s s201, 4 + %2\n" // s201 = pv2->y 30 | "lv.s s202, 8 + %2\n" // s202 = pv2->z 31 | "vctfm3.t c000, e100, c200\n" // c000 = e100 * c200 32 | "sv.s s000, 0 + %0\n" // pv0->x = s000 33 | "sv.s s001, 4 + %0\n" // pv0->y = s001 34 | "sv.s s002, 8 + %0\n" // pv0->z = s002 35 | ".set pop\n" // restore assembler option 36 | : "=o"(*pv0) 37 | : "o"(*pm1), "o"(*pv2) 38 | ); 39 | #endif 40 | return (pv0); 41 | } 42 | -------------------------------------------------------------------------------- /tables/tables/instr_id/rsp/rsp_normal_lwc2.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | // OP vt[elementlow], offset(vs) 5 | RABBITIZER_DEF_INSTR_ID( 6 | rsp, 0x00, lbv, 7 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 8 | .readsRs=true 9 | ) 10 | RABBITIZER_DEF_INSTR_ID( 11 | rsp, 0x01, lsv, 12 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 13 | .readsRs=true 14 | ) 15 | RABBITIZER_DEF_INSTR_ID( 16 | rsp, 0x02, llv, 17 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 18 | .readsRs=true 19 | ) 20 | RABBITIZER_DEF_INSTR_ID( 21 | rsp, 0x03, ldv, 22 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 23 | .readsRs=true 24 | ) 25 | RABBITIZER_DEF_INSTR_ID( 26 | rsp, 0x04, lqv, 27 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 28 | .readsRs=true 29 | ) 30 | RABBITIZER_DEF_INSTR_ID( 31 | rsp, 0x05, lrv, 32 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 33 | .readsRs=true 34 | ) 35 | RABBITIZER_DEF_INSTR_ID( 36 | rsp, 0x06, lpv, 37 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 38 | .readsRs=true 39 | ) 40 | RABBITIZER_DEF_INSTR_ID( 41 | rsp, 0x07, luv, 42 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 43 | .readsRs=true 44 | ) 45 | RABBITIZER_DEF_INSTR_ID( 46 | rsp, 0x08, lhv, 47 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 48 | .readsRs=true 49 | ) 50 | RABBITIZER_DEF_INSTR_ID( 51 | rsp, 0x09, lfv, 52 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 53 | .readsRs=true 54 | ) 55 | RABBITIZER_DEF_INSTR_ID( 56 | rsp, 0x0B, ltv, 57 | .operands={RAB_OPERAND_rsp_vt_elementlow, RAB_OPERAND_rsp_offset_rs}, 58 | .readsRs=true 59 | ) 60 | -------------------------------------------------------------------------------- /src/instructions/RabbitizerInstructionRsp/RabbitizerInstructionRsp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "instructions/RabbitizerInstructionRsp.h" 5 | 6 | void RabbitizerInstructionRsp_init(RabbitizerInstruction *self, uint32_t word, uint32_t vram) { 7 | RabbitizerInstruction_init(self, word, vram); 8 | 9 | self->uniqueId = RABBITIZER_INSTR_ID_rsp_INVALID; 10 | self->descriptor = &RabbitizerInstrDescriptor_Descriptors[self->uniqueId]; 11 | 12 | self->_handwrittenCategory = true; 13 | self->category = RABBITIZER_INSTRCAT_RSP; 14 | } 15 | 16 | void RabbitizerInstructionRsp_destroy(RabbitizerInstruction *self) { 17 | RabbitizerInstruction_destroy(self); 18 | } 19 | 20 | uint16_t RabbitizerInstructionRsp_GetOffsetVector(const RabbitizerInstruction *self) { 21 | uint16_t offset = RAB_INSTR_RSP_GET_OFFSET_VECTOR_RAW(self); 22 | 23 | switch (self->uniqueId) { 24 | case RABBITIZER_INSTR_ID_rsp_lsv: 25 | case RABBITIZER_INSTR_ID_rsp_ssv: 26 | return offset << 1; 27 | 28 | case RABBITIZER_INSTR_ID_rsp_llv: 29 | case RABBITIZER_INSTR_ID_rsp_slv: 30 | return offset << 2; 31 | 32 | case RABBITIZER_INSTR_ID_rsp_ldv: 33 | case RABBITIZER_INSTR_ID_rsp_sdv: 34 | case RABBITIZER_INSTR_ID_rsp_lpv: 35 | case RABBITIZER_INSTR_ID_rsp_spv: 36 | case RABBITIZER_INSTR_ID_rsp_luv: 37 | case RABBITIZER_INSTR_ID_rsp_suv: 38 | return offset << 3; 39 | 40 | case RABBITIZER_INSTR_ID_rsp_lqv: 41 | case RABBITIZER_INSTR_ID_rsp_sqv: 42 | case RABBITIZER_INSTR_ID_rsp_lrv: 43 | case RABBITIZER_INSTR_ID_rsp_srv: 44 | case RABBITIZER_INSTR_ID_rsp_lhv: 45 | case RABBITIZER_INSTR_ID_rsp_shv: 46 | case RABBITIZER_INSTR_ID_rsp_lfv: 47 | case RABBITIZER_INSTR_ID_rsp_sfv: 48 | case RABBITIZER_INSTR_ID_rsp_ltv: 49 | case RABBITIZER_INSTR_ID_rsp_stv: 50 | case RABBITIZER_INSTR_ID_rsp_swv: 51 | return offset << 4; 52 | 53 | default: 54 | return offset; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r5900/r5900_mmi_pmfhl.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26------------------------------10------6-5----------0 6 | |0 1 1 1 0 0| | fmt |1 1 0 0 0 0| 7 | ------6----------------------------------------5----------6------ 8 | |-------00------|-------01------|-------10------|-------11------| 9 | 000 | PMFHL.LW | PMFHL.UW | PMFHL.SLW | PMFHL.LH | 10 | 001 | PMFHL.SH | --- | --- | --- | 11 | 010 | --- | --- | --- | --- | 12 | 011 | --- | --- | --- | --- | 13 | 100 | --- | --- | --- | --- | 14 | 101 | --- | --- | --- | --- | 15 | 110 | --- | --- | --- | --- | 16 | 111 | --- | --- | --- | --- | 17 | hi |---------------|---------------|---------------|---------------| 18 | */ 19 | 20 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 21 | r5900, 0x00, pmfhl_lw, pmfhl.lw, 22 | .operands={RAB_OPERAND_cpu_rd}, 23 | .modifiesRd=true 24 | ) // Parallel Move From Hi/Lo register 25 | 26 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 27 | r5900, 0x01, pmfhl_uw, pmfhl.uw, 28 | .operands={RAB_OPERAND_cpu_rd}, 29 | .modifiesRd=true 30 | ) // Parallel Move From Hi/Lo register 31 | 32 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 33 | r5900, 0x02, pmfhl_slw, pmfhl.slw, 34 | .operands={RAB_OPERAND_cpu_rd}, 35 | .modifiesRd=true 36 | ) // Parallel Move From Hi/Lo register 37 | 38 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 39 | r5900, 0x03, pmfhl_lh, pmfhl.lh, 40 | .operands={RAB_OPERAND_cpu_rd}, 41 | .modifiesRd=true 42 | ) // Parallel Move From Hi/Lo register 43 | 44 | RABBITIZER_DEF_INSTR_ID_ALTNAME( 45 | r5900, 0x04, pmfhl_sh, pmfhl.sh, 46 | .operands={RAB_OPERAND_cpu_rd}, 47 | .modifiesRd=true 48 | ) // Parallel Move From Hi/Lo register 49 | -------------------------------------------------------------------------------- /rust/src/instr_descriptor.rs: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2022-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | use crate::{access_type_enum, instr_suffix_enum, operand_type_enum}; 5 | 6 | #[repr(C)] 7 | #[derive(Debug, Copy, Clone)] 8 | #[allow(non_camel_case_types)] 9 | pub struct InstrDescriptor { 10 | operands: [operand_type_enum::OperandType; 6usize], 11 | instr_type: u32, // RabbitizerInstrType, // This type is deprecated and I don't care enough to make a binding for it 12 | 13 | instr_suffix: instr_suffix_enum::InstrSuffix, 14 | 15 | is_branch: bool, 16 | is_branch_likely: bool, 17 | is_jump: bool, 18 | is_jump_with_address: bool, 19 | is_trap: bool, 20 | 21 | is_float: bool, 22 | is_double: bool, 23 | 24 | is_unsigned: bool, 25 | 26 | modifies_rs: bool, 27 | modifies_rt: bool, 28 | modifies_rd: bool, 29 | 30 | reads_rs: bool, 31 | reads_rt: bool, 32 | reads_rd: bool, 33 | 34 | reads_hi: bool, 35 | reads_lo: bool, 36 | modifies_hi: bool, 37 | modifies_lo: bool, 38 | 39 | modifies_fs: bool, 40 | modifies_ft: bool, 41 | modifies_fd: bool, 42 | 43 | reads_fs: bool, 44 | reads_ft: bool, 45 | reads_fd: bool, 46 | 47 | not_emited_by_compilers: bool, 48 | 49 | can_be_hi: bool, 50 | can_be_lo: bool, 51 | does_link: bool, 52 | 53 | does_dereference: bool, 54 | does_load: bool, 55 | does_store: bool, 56 | 57 | maybe_is_move: bool, 58 | 59 | is_pseudo: bool, 60 | 61 | access_type: access_type_enum::AccessType, 62 | does_unsigned_memory_access: bool, 63 | } 64 | 65 | impl InstrDescriptor { 66 | pub fn get_operand_type(&self, index: usize) -> operand_type_enum::OperandType { 67 | assert!(index < self.operands.len()); 68 | 69 | self.operands[index] 70 | } 71 | 72 | pub fn operands_slice(&self) -> &[operand_type_enum::OperandType] { 73 | let end = self 74 | .operands 75 | .iter() 76 | .position(|&r| r == operand_type_enum::OperandType::ALL_INVALID) 77 | .unwrap_or(self.operands.len()); 78 | 79 | &self.operands[0..end] 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tables/tables/instr_id/r4000allegrex/r4000allegrex_special3_bshfl.inc: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | /* 5 | 31---------26--------------------------------10------6-5--------0 6 | | =SPECIAL3 | | sa | = BSHFL | 7 | ------6------------------------------------------5---------6----- 8 | |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 9 | 00 | --- | --- | WSBH | WSBW | --- | --- | --- | --- | 10 | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | 10 | SEB | --- | --- | --- | BITREV| --- | --- | --- | 12 | 11 | SEH | --- | --- | --- | --- | --- | --- | --- | 13 | hi |-------|-------|-------|-------|-------|-------|-------|-------| 14 | */ 15 | 16 | // OP rd, rt 17 | 18 | RABBITIZER_DEF_INSTR_ID( 19 | r4000allegrex, 0x02, wsbh, 20 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt}, 21 | .instrType=RABBITIZER_INSTR_TYPE_R, 22 | .modifiesRd=true, 23 | .readsRt=true 24 | ) // Word Swap Bytes within Halfword 25 | 26 | RABBITIZER_DEF_INSTR_ID( 27 | r4000allegrex, 0x03, wsbw, 28 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt}, 29 | .instrType=RABBITIZER_INSTR_TYPE_R, 30 | .modifiesRd=true, 31 | .readsRt=true 32 | ) // Word Swap Bytes within Word 33 | 34 | RABBITIZER_DEF_INSTR_ID( 35 | r4000allegrex, 0x10, seb, 36 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt}, 37 | .instrType=RABBITIZER_INSTR_TYPE_R, 38 | .modifiesRd=true, 39 | .readsRt=true 40 | ) // Sign-Extend Byte 41 | 42 | RABBITIZER_DEF_INSTR_ID( 43 | r4000allegrex, 0x18, seh, 44 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt}, 45 | .instrType=RABBITIZER_INSTR_TYPE_R, 46 | .modifiesRd=true, 47 | .readsRt=true 48 | ) // Sign-Extend Halfword 49 | 50 | RABBITIZER_DEF_INSTR_ID( 51 | r4000allegrex, 0x14, bitrev, 52 | .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rt}, 53 | .instrType=RABBITIZER_INSTR_TYPE_R, 54 | .modifiesRd=true, 55 | .readsRt=true 56 | ) // BIT REVerse 57 | -------------------------------------------------------------------------------- /tests/c/instruction_checks/r5900_disasm.c: -------------------------------------------------------------------------------- 1 | /* SPDX-FileCopyrightText: © 2023-2024 Decompollaborate */ 2 | /* SPDX-License-Identifier: MIT */ 3 | 4 | #include "rabbitizer.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "expected_disasm_utils.h" 11 | 12 | #define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R5900, word, imm, expected,) 13 | 14 | // TODO: fill 15 | const TestEntry test_entries[] = { 16 | TEST_ENTRY_C(0x4A000038, NULL, "vcallms 0x0"), 17 | TEST_ENTRY_C(0x4A004038, NULL, "vcallms 0x800"), 18 | TEST_ENTRY_C(0x4A008038, NULL, "vcallms 0x1000"), 19 | TEST_ENTRY_C(0x4A008838, NULL, "vcallms 0x1100"), 20 | TEST_ENTRY_C(0x4A009038, NULL, "vcallms 0x1200"), 21 | TEST_ENTRY_C(0x4A009838, NULL, "vcallms 0x1300"), 22 | TEST_ENTRY_C(0x4A00a038, NULL, "vcallms 0x1400"), 23 | TEST_ENTRY_C(0x4A07FFF8, NULL, "vcallms 0xFFF8"), 24 | TEST_ENTRY_C(0x4A080038, NULL, "vcallms 0x10000"), 25 | TEST_ENTRY_C(0x4A1F8038, NULL, "vcallms 0x3F000"), 26 | TEST_ENTRY_C(0x4A1FFFB8, NULL, "vcallms 0x3FFF0"), 27 | 28 | TEST_ENTRY_C(0x70001030, NULL, "pmfhl.lw $v0"), 29 | TEST_ENTRY_C(0x70001070, NULL, "pmfhl.uw $v0"), 30 | TEST_ENTRY_C(0x700010B0, NULL, "pmfhl.slw $v0"), 31 | TEST_ENTRY_C(0x700010F0, NULL, "pmfhl.lh $v0"), 32 | TEST_ENTRY_C(0x70001130, NULL, "pmfhl.sh $v0"), 33 | TEST_ENTRY_C(0x70000031, NULL, "pmthl.lw $zero"), 34 | 35 | TEST_ENTRY_C(0x4B020BFE, NULL, "vilwr.x $vi2, ($vi1)"), 36 | TEST_ENTRY_C(0x4A820BFE, NULL, "vilwr.y $vi2, ($vi1)"), 37 | TEST_ENTRY_C(0x4A420BFE, NULL, "vilwr.z $vi2, ($vi1)"), 38 | TEST_ENTRY_C(0x4A220BFE, NULL, "vilwr.w $vi2, ($vi1)"), 39 | TEST_ENTRY_C(0x4B020BFF, NULL, "viswr.x $vi2, ($vi1)"), 40 | TEST_ENTRY_C(0x4A820BFF, NULL, "viswr.y $vi2, ($vi1)"), 41 | TEST_ENTRY_C(0x4A420BFF, NULL, "viswr.z $vi2, ($vi1)"), 42 | TEST_ENTRY_C(0x4A220BFF, NULL, "viswr.w $vi2, ($vi1)"), 43 | 44 | TEST_ENTRY_C(0x4A0307B2, NULL, "viaddi $vi3, $vi0, -0x2"), 45 | 46 | TEST_ENTRY_C(0x48500800, NULL, "cfc2.ni $s0, $vi1"), 47 | TEST_ENTRY_C(0x48500801, NULL, "cfc2.i $s0, $vi1"), 48 | }; 49 | 50 | size_t test_entries_len = ARRAY_COUNT(test_entries); 51 | --------------------------------------------------------------------------------