mirror of
https://github.com/Decompollaborate/rabbitizer.git
synced 2024-12-27 12:16:07 +00:00
Change flag_disasmAsData to flag_r5900DisasmAsData and redo the logic completely
This commit is contained in:
parent
8b9dddd3b4
commit
80aa0b6c20
@ -9,7 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add `flag_disasmAsData` member to the `Instruction` class.
|
- Add `flag_r5900DisasmAsData` member to the `Instruction` class.
|
||||||
|
- This flag allows to fine-tune R5900 instruction set that are affected by
|
||||||
|
the global `gnuMode` option.
|
||||||
|
- Currently these instructions are: `trunc.w.s`, `cvt.w.s`, `vclipw` and
|
||||||
|
`vsqrt`.
|
||||||
- `TrinaryValue.TRUE` forces the instruction to be disassembled as data.
|
- `TrinaryValue.TRUE` forces the instruction to be disassembled as data.
|
||||||
- `TrinaryValue.FALSE` bypasses the global checks for disassembling a word
|
- `TrinaryValue.FALSE` bypasses the global checks for disassembling a word
|
||||||
as data. A word will still be disassembled as data if it can't be decoded.
|
as data. A word will still be disassembled as data if it can't be decoded.
|
||||||
|
@ -149,8 +149,8 @@ namespace rabbitizer {
|
|||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
|
|
||||||
TrinaryValue FlagGet_disasmAsData() const;
|
TrinaryValue FlagGet_r5900DisasmAsData() const;
|
||||||
void FlagSet_disasmAsData(TrinaryValue value);
|
void FlagSet_r5900DisasmAsData(TrinaryValue value);
|
||||||
|
|
||||||
TrinaryValue FlagGet_r5900UseDollar() const;
|
TrinaryValue FlagGet_r5900UseDollar() const;
|
||||||
void FlagSet_r5900UseDollar(TrinaryValue value);
|
void FlagSet_r5900UseDollar(TrinaryValue value);
|
||||||
|
@ -648,11 +648,11 @@ void InstructionBase::Set_stype(uint8_t val) {
|
|||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
|
|
||||||
TrinaryValue InstructionBase::FlagGet_disasmAsData() const {
|
TrinaryValue InstructionBase::FlagGet_r5900DisasmAsData() const {
|
||||||
return static_cast<TrinaryValue>(RAB_INSTR_FLAGS_GET_disasmAsData(&this->instr));
|
return static_cast<TrinaryValue>(RAB_INSTR_FLAGS_GET_r5900DisasmAsData(&this->instr));
|
||||||
}
|
}
|
||||||
void InstructionBase::FlagSet_disasmAsData(TrinaryValue value) {
|
void InstructionBase::FlagSet_r5900DisasmAsData(TrinaryValue value) {
|
||||||
RAB_INSTR_FLAGS_SET_disasmAsData(&this->instr, static_cast<RabTrinaryValue>(value));
|
RAB_INSTR_FLAGS_SET_r5900DisasmAsData(&this->instr, static_cast<RabTrinaryValue>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TrinaryValue InstructionBase::FlagGet_r5900UseDollar() const {
|
TrinaryValue InstructionBase::FlagGet_r5900UseDollar() const {
|
||||||
|
@ -38,7 +38,7 @@ typedef struct RabbitizerInstruction {
|
|||||||
* Flags are bitpacked, refer to the `RAB_INSTR_FLAGS_` macros to access them.
|
* Flags are bitpacked, refer to the `RAB_INSTR_FLAGS_` macros to access them.
|
||||||
*
|
*
|
||||||
* Bit usage:
|
* Bit usage:
|
||||||
* - Bits 0 ~ 1: `disasmAsData`. Value of the `RabTrinaryValue` enum.
|
* - Bits 0 ~ 1: `r5900DisasmAsData`. Value of the `RabTrinaryValue` enum.
|
||||||
* - `RAB_TRINARY_VAL_TRUE` forces the instruction to be disassembled as data.
|
* - `RAB_TRINARY_VAL_TRUE` forces the instruction to be disassembled as data.
|
||||||
* - `RAB_TRINARY_VAL_FALSE` bypasses the global checks for disassembling a word as data. A word will still be disassembled as data if it can't be decoded.
|
* - `RAB_TRINARY_VAL_FALSE` bypasses the global checks for disassembling a word as data. A word will still be disassembled as data if it can't be decoded.
|
||||||
* - `RAB_TRINARY_VAL_NONE` leaves this decision to the global settings.
|
* - `RAB_TRINARY_VAL_NONE` leaves this decision to the global settings.
|
||||||
@ -145,8 +145,8 @@ typedef struct RabbitizerInstruction {
|
|||||||
#define RAB_INSTR_PACK_stype(word, value) (BITREPACK((word), (value), 6, 5))
|
#define RAB_INSTR_PACK_stype(word, value) (BITREPACK((word), (value), 6, 5))
|
||||||
|
|
||||||
|
|
||||||
#define RAB_INSTR_FLAGS_GET_disasmAsData(self) (RabTrinaryValue)(SHIFTR((self)->flags, 0, 2))
|
#define RAB_INSTR_FLAGS_GET_r5900DisasmAsData(self) (RabTrinaryValue)(SHIFTR((self)->flags, 0, 2))
|
||||||
#define RAB_INSTR_FLAGS_SET_disasmAsData(self, value) ((self)->flags = BITREPACK((self)->flags, (value), 0, 2))
|
#define RAB_INSTR_FLAGS_SET_r5900DisasmAsData(self, value) ((self)->flags = BITREPACK((self)->flags, (value), 0, 2))
|
||||||
|
|
||||||
#define RAB_INSTR_FLAGS_GET_r5900UseDollar(self) (RabTrinaryValue)(SHIFTR((self)->flags, 2, 2))
|
#define RAB_INSTR_FLAGS_GET_r5900UseDollar(self) (RabTrinaryValue)(SHIFTR((self)->flags, 2, 2))
|
||||||
#define RAB_INSTR_FLAGS_SET_r5900UseDollar(self, value) ((self)->flags = BITREPACK((self)->flags, (value), 2, 2))
|
#define RAB_INSTR_FLAGS_SET_r5900UseDollar(self, value) ((self)->flags = BITREPACK((self)->flags, (value), 2, 2))
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "rabbitizer"
|
name = "rabbitizer"
|
||||||
# Version should be synced with include/common/RabbitizerVersion.h
|
# Version should be synced with include/common/RabbitizerVersion.h
|
||||||
version = "1.8.0.dev0"
|
version = "1.8.0"
|
||||||
description = "MIPS instruction decoder"
|
description = "MIPS instruction decoder"
|
||||||
# license = "MIT"
|
# license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -61,8 +61,11 @@ class Instruction:
|
|||||||
inHandwrittenFunction: bool = False
|
inHandwrittenFunction: bool = False
|
||||||
"""Boolean value indicating if the current instruction is used on a handwritten function. This is intended to be determined by the user."""
|
"""Boolean value indicating if the current instruction is used on a handwritten function. This is intended to be determined by the user."""
|
||||||
|
|
||||||
flag_disasmAsData: Enum = TrinaryValue.NONE
|
flag_r5900DisasmAsData: Enum = TrinaryValue.NONE
|
||||||
"""Flag to override the disasmAsData global configuration.
|
"""Flag to override the r5900DisasmAsData global configuration.
|
||||||
|
|
||||||
|
- This flag allows to fine-tune R5900 instruction set that are affected by the global `gnuMode` option.
|
||||||
|
- Currently these instructions are: `trunc.w.s` (r5900 mode), `cvt.w.s` (r5900 mode), `vclipw` and `vsqrt`.
|
||||||
|
|
||||||
- `TrinaryValue.TRUE` forces the instruction to be disassembled as data.
|
- `TrinaryValue.TRUE` forces the instruction to be disassembled as data.
|
||||||
- `TrinaryValue.FALSE` bypasses the global checks for disassembling a word as data. A word will still be disassembled as data if it can't be decoded.
|
- `TrinaryValue.FALSE` bypasses the global checks for disassembling a word as data. A word will still be disassembled as data if it can't be decoded.
|
||||||
|
@ -242,7 +242,7 @@ static PyObject *rabbitizer_type_Instruction_member_get_instrIdType(PyRabbitizer
|
|||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_MEMBER_FLAG(disasmAsData)
|
DEF_MEMBER_FLAG(r5900DisasmAsData)
|
||||||
DEF_MEMBER_FLAG(r5900UseDollar)
|
DEF_MEMBER_FLAG(r5900UseDollar)
|
||||||
|
|
||||||
|
|
||||||
@ -250,6 +250,8 @@ DEF_MEMBER_FLAG(r5900UseDollar)
|
|||||||
#define MEMBER_SET(name, docs, closure) { #name, (getter) NULL, (setter) rabbitizer_type_Instruction_member_set_##name, PyDoc_STR(docs), closure }
|
#define MEMBER_SET(name, docs, closure) { #name, (getter) NULL, (setter) rabbitizer_type_Instruction_member_set_##name, PyDoc_STR(docs), closure }
|
||||||
#define MEMBER_GET_SET(name, docs, closure) { #name, (getter) rabbitizer_type_Instruction_member_get_##name, (setter) rabbitizer_type_Instruction_member_set_##name, PyDoc_STR(docs), closure }
|
#define MEMBER_GET_SET(name, docs, closure) { #name, (getter) rabbitizer_type_Instruction_member_get_##name, (setter) rabbitizer_type_Instruction_member_set_##name, PyDoc_STR(docs), closure }
|
||||||
|
|
||||||
|
#define MEMBER_FLAG_GET_SET(name, docs, closure) { #name, (getter) rabbitizer_type_Instruction_member_get_flag_##name, (setter) rabbitizer_type_Instruction_member_set_flag_##name, PyDoc_STR(docs), closure }
|
||||||
|
|
||||||
static PyGetSetDef rabbitizer_type_Instruction_getsetters[] = {
|
static PyGetSetDef rabbitizer_type_Instruction_getsetters[] = {
|
||||||
MEMBER_GET(rs, "", NULL),
|
MEMBER_GET(rs, "", NULL),
|
||||||
MEMBER_GET(rt, "", NULL),
|
MEMBER_GET(rt, "", NULL),
|
||||||
@ -261,8 +263,8 @@ static PyGetSetDef rabbitizer_type_Instruction_getsetters[] = {
|
|||||||
MEMBER_GET(uniqueId, "", NULL),
|
MEMBER_GET(uniqueId, "", NULL),
|
||||||
MEMBER_GET(instrIdType, "", NULL),
|
MEMBER_GET(instrIdType, "", NULL),
|
||||||
|
|
||||||
MEMBER_GET_SET(flag_disasmAsData, "", NULL),
|
MEMBER_FLAG_GET_SET(r5900DisasmAsData, "", NULL),
|
||||||
MEMBER_GET_SET(flag_r5900UseDollar, "", NULL),
|
MEMBER_FLAG_GET_SET(r5900UseDollar, "", NULL),
|
||||||
|
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
@ -454,10 +454,10 @@ impl Instruction {
|
|||||||
self.get_cop2t().try_into().unwrap()
|
self.get_cop2t().try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flags_get_disasm_as_data(&self) -> utils::TrinaryValue {
|
pub fn flags_get_r5900_disasm_as_data(&self) -> utils::TrinaryValue {
|
||||||
utils::shiftr(self.flags, 0, 2).try_into().unwrap()
|
utils::shiftr(self.flags, 0, 2).try_into().unwrap()
|
||||||
}
|
}
|
||||||
pub fn flags_set_disasm_as_data(&mut self, value: utils::TrinaryValue) {
|
pub fn flags_set_r5900_disasm_as_data(&mut self, value: utils::TrinaryValue) {
|
||||||
self.flags = utils::bitrepack(self.flags, value.try_into().unwrap(), 0, 2);
|
self.flags = utils::bitrepack(self.flags, value.try_into().unwrap(), 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ void RabbitizerInstruction_init(RabbitizerInstruction *self, uint32_t word, uint
|
|||||||
self->category = RABBITIZER_INSTRCAT_CPU;
|
self->category = RABBITIZER_INSTRCAT_CPU;
|
||||||
|
|
||||||
self->flags = 0;
|
self->flags = 0;
|
||||||
RAB_INSTR_FLAGS_SET_disasmAsData(self, RAB_TRINARY_VAL_NONE);
|
RAB_INSTR_FLAGS_SET_r5900DisasmAsData(self, RAB_TRINARY_VAL_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RabbitizerInstruction_destroy(UNUSED RabbitizerInstruction *self) {
|
void RabbitizerInstruction_destroy(UNUSED RabbitizerInstruction *self) {
|
||||||
|
@ -94,31 +94,29 @@ size_t RabbitizerInstruction_disassembleAsData(const RabbitizerInstruction *self
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RabbitizerInstruction_mustDisasmAsData(const RabbitizerInstruction *self) {
|
bool RabbitizerInstruction_mustDisasmAsData(const RabbitizerInstruction *self) {
|
||||||
switch (RAB_INSTR_FLAGS_GET_disasmAsData(self)) {
|
switch (self->uniqueId) {
|
||||||
case RAB_TRINARY_VAL_TRUE:
|
case RABBITIZER_INSTR_ID_cpu_break:
|
||||||
return true;
|
if (RabbitizerConfig_Cfg.toolchainTweaks.sn64DivFix) {
|
||||||
|
return true;
|
||||||
case RAB_TRINARY_VAL_FALSE:
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RAB_TRINARY_VAL_NONE:
|
case RABBITIZER_INSTR_ID_cpu_trunc_w_s:
|
||||||
if (RabbitizerConfig_Cfg.toolchainTweaks.sn64DivFix) {
|
case RABBITIZER_INSTR_ID_cpu_cvt_w_s:
|
||||||
if (self->uniqueId == RABBITIZER_INSTR_ID_cpu_break) {
|
if (self->category == RABBITIZER_INSTRCAT_R5900) {
|
||||||
return true;
|
switch (RAB_INSTR_FLAGS_GET_r5900DisasmAsData(self)) {
|
||||||
}
|
case RAB_TRINARY_VAL_TRUE:
|
||||||
}
|
return true;
|
||||||
|
|
||||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
case RAB_TRINARY_VAL_FALSE:
|
||||||
switch (self->uniqueId) {
|
break;
|
||||||
case RABBITIZER_INSTR_ID_cpu_trunc_w_s:
|
|
||||||
case RABBITIZER_INSTR_ID_cpu_cvt_w_s:
|
case RAB_TRINARY_VAL_NONE:
|
||||||
if (self->category == RABBITIZER_INSTRCAT_R5900) {
|
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||||
/**
|
/**
|
||||||
* Due to the R5900's FPU being non properly complaint, the instruction cvt.w.s always
|
* Due to the R5900's FPU being non properly complaint, the instruction cvt.w.s always behaves as trunc.w.s because EE can only do round-to-zero.
|
||||||
* behaves as trunc.w.s because EE can only do round-to-zero.
|
|
||||||
*
|
*
|
||||||
* Assemblers like GAS workaround this issue by decoding cvt.w.s as trunc.w.s, but other
|
* Assemblers like GAS workaround this issue by decoding cvt.w.s as trunc.w.s, but other assemblers just use trunc.w.s and cvt.w.s as-is.
|
||||||
* assemblers just use trunc.w.s and cvt.w.s as-is.
|
|
||||||
*
|
*
|
||||||
* Here's some reading about the binutils rationale:
|
* Here's some reading about the binutils rationale:
|
||||||
* - https://sourceware.org/legacy-ml/binutils/2012-11/msg00360.html
|
* - https://sourceware.org/legacy-ml/binutils/2012-11/msg00360.html
|
||||||
@ -128,26 +126,49 @@ bool RabbitizerInstruction_mustDisasmAsData(const RabbitizerInstruction *self) {
|
|||||||
* - trunc.w.s is built as the cvt.w.s instruction.
|
* - trunc.w.s is built as the cvt.w.s instruction.
|
||||||
* - cvt.w.s errors complaining as not being supported by the processor.
|
* - cvt.w.s errors complaining as not being supported by the processor.
|
||||||
*
|
*
|
||||||
* To ensure the produced disassembly will still match when built with GAS, we decode this
|
* To ensure the produced disassembly will still match when built with GAS, we decode this two instructions as .word
|
||||||
* two instructions as .word
|
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RABBITIZER_INSTR_ID_r5900_vclipw:
|
|
||||||
// The vclipw instruction has variants that are undocumented (vclipw.xy, vclipw.z) and don't
|
|
||||||
// assemble in gnu as
|
|
||||||
return true;
|
|
||||||
case RABBITIZER_INSTR_ID_r5900_vsqrt:
|
|
||||||
// The vclipw instruction seems to be representable in multiple ways, and we only disassemble
|
|
||||||
// one of them
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RABBITIZER_INSTR_ID_r5900_vclipw:
|
||||||
|
switch (RAB_INSTR_FLAGS_GET_r5900DisasmAsData(self)) {
|
||||||
|
case RAB_TRINARY_VAL_TRUE:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case RAB_TRINARY_VAL_FALSE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RAB_TRINARY_VAL_NONE:
|
||||||
|
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||||
|
// The vclipw instruction has variants that are undocumented (vclipw.xy, vclipw.z) and don't assemble in gnu as
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RABBITIZER_INSTR_ID_r5900_vsqrt:
|
||||||
|
switch (RAB_INSTR_FLAGS_GET_r5900DisasmAsData(self)) {
|
||||||
|
case RAB_TRINARY_VAL_TRUE:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case RAB_TRINARY_VAL_FALSE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RAB_TRINARY_VAL_NONE:
|
||||||
|
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||||
|
// The vclipw instruction seems to be representable in multiple ways, and we only disassemble one of them
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RabbitizerInstruction_isValid(self)) {
|
if (!RabbitizerInstruction_isValid(self)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user