mirror of
https://github.com/Decompollaborate/rabbitizer.git
synced 2024-12-26 18:14:51 +00:00
flag_r5900UseDollar
This commit is contained in:
parent
049b47b32c
commit
111ee90a3a
11
CHANGELOG.md
11
CHANGELOG.md
@ -10,11 +10,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
|
||||
- Add `flag_disasmAsData` member to the `Instruction` class.
|
||||
- Flag to override the disasmAsData global configuration.
|
||||
- `TrinaryValue.TRUE` forces the instruction to be disassembled as data.
|
||||
- `RAB_TRINARY_VAL_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.
|
||||
- `RAB_TRINARY_VAL_NONE` leaves this decision to the global settings.
|
||||
- `TrinaryValue.NONE` leaves this decision to the global settings.
|
||||
- Add `flag_r5900UseDollar` member to the `Instruction` class.
|
||||
- `TrinaryValue.TRUE` forces the use of dollar signs ($) on R5900's VU
|
||||
instructions.
|
||||
- `TrinaryValue.FALSE` forces disassembling to not use of dollar signs ($) on
|
||||
R5900's VU instructions.
|
||||
- `TrinaryValue.NONE` leaves this decision to the global settings.
|
||||
|
||||
## [1.7.10] - 2023-09-24
|
||||
|
||||
|
@ -152,6 +152,9 @@ namespace rabbitizer {
|
||||
TrinaryValue FlagGet_disasmAsData() const;
|
||||
void FlagSet_disasmAsData(TrinaryValue value);
|
||||
|
||||
TrinaryValue FlagGet_r5900UseDollar() const;
|
||||
void FlagSet_r5900UseDollar(TrinaryValue value);
|
||||
|
||||
/* flags */
|
||||
|
||||
|
||||
|
@ -655,6 +655,13 @@ void InstructionBase::FlagSet_disasmAsData(TrinaryValue value) {
|
||||
RAB_INSTR_FLAGS_SET_disasmAsData(&this->instr, static_cast<RabTrinaryValue>(value));
|
||||
}
|
||||
|
||||
TrinaryValue InstructionBase::FlagGet_r5900UseDollar() const {
|
||||
return static_cast<TrinaryValue>(RAB_INSTR_FLAGS_GET_r5900UseDollar(&this->instr));
|
||||
}
|
||||
void InstructionBase::FlagSet_r5900UseDollar(TrinaryValue value) {
|
||||
RAB_INSTR_FLAGS_SET_r5900UseDollar(&this->instr, static_cast<RabTrinaryValue>(value));
|
||||
}
|
||||
|
||||
/* flags */
|
||||
|
||||
|
||||
|
@ -38,12 +38,16 @@ typedef struct RabbitizerInstruction {
|
||||
* Flags are bitpacked, refer to the `RAB_INSTR_FLAGS_` macros to access them.
|
||||
*
|
||||
* Bit usage:
|
||||
* - Bits 0 ~ 1: Value of the `RabTrinaryValue` enum.
|
||||
* - Bits 0 ~ 1: `disasmAsData`. Value of the `RabTrinaryValue` enum.
|
||||
* - `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_NONE` leaves this decision to the global settings.
|
||||
* - Defaults to `RAB_TRINARY_VAL_NONE`
|
||||
* - Bit 2 ~ 3: Reserved for future use.
|
||||
* - Bit 2 ~ 3: `r5900UseDollar`. Value of the `RabTrinaryValue` enum.
|
||||
* - `RAB_TRINARY_VAL_TRUE` forces the use of dollar signs ($) on R5900's VU instructions
|
||||
* - `RAB_TRINARY_VAL_FALSE` forces disassembling to not use of dollar signs ($) on R5900's VU instructions
|
||||
* - `RAB_TRINARY_VAL_NONE` leaves this decision to the global settings.
|
||||
* - Defaults to `RAB_TRINARY_VAL_NONE`
|
||||
* - Bit 4 ~ 5: Reserved for future use.
|
||||
* - Bit 6 ~ 7: Reserved for future use.
|
||||
* - Bit 8 ~ 9: Reserved for future use.
|
||||
@ -144,6 +148,9 @@ typedef struct RabbitizerInstruction {
|
||||
#define RAB_INSTR_FLAGS_GET_disasmAsData(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_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))
|
||||
|
||||
|
||||
NON_NULL(1)
|
||||
void RabbitizerInstruction_init(RabbitizerInstruction *self, uint32_t word, uint32_t vram);
|
||||
|
@ -65,8 +65,15 @@ class Instruction:
|
||||
"""Flag to override the disasmAsData global configuration.
|
||||
|
||||
- `TrinaryValue.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_NONE` leaves this decision to the global settings.
|
||||
- `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.NONE` leaves this decision to the global settings.
|
||||
"""
|
||||
flag_r5900UseDollar: Enum = TrinaryValue.NONE
|
||||
"""Flag to override the disasmAsData global configuration.
|
||||
|
||||
- `TrinaryValue.TRUE` forces the use of dollar signs ($) on R5900's VU instructions.
|
||||
- `TrinaryValue.FALSE` forces disassembling to not use of dollar signs ($) on R5900's VU instructions.
|
||||
- `TrinaryValue.NONE` leaves this decision to the global settings.
|
||||
"""
|
||||
|
||||
|
||||
|
@ -243,6 +243,7 @@ static PyObject *rabbitizer_type_Instruction_member_get_instrIdType(PyRabbitizer
|
||||
}
|
||||
|
||||
DEF_MEMBER_FLAG(disasmAsData)
|
||||
DEF_MEMBER_FLAG(r5900UseDollar)
|
||||
|
||||
|
||||
#define MEMBER_GET(name, docs, closure) { #name, (getter) rabbitizer_type_Instruction_member_get_##name, (setter) NULL, PyDoc_STR(docs), closure }
|
||||
@ -261,6 +262,7 @@ static PyGetSetDef rabbitizer_type_Instruction_getsetters[] = {
|
||||
MEMBER_GET(instrIdType, "", NULL),
|
||||
|
||||
MEMBER_GET_SET(flag_disasmAsData, "", NULL),
|
||||
MEMBER_GET_SET(flag_r5900UseDollar, "", NULL),
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
@ -461,6 +461,13 @@ impl Instruction {
|
||||
self.flags = utils::bitrepack(self.flags, value.try_into().unwrap(), 0, 2);
|
||||
}
|
||||
|
||||
pub fn flags_get_r5900_use_dollar(&self) -> utils::TrinaryValue {
|
||||
utils::shiftr(self.flags, 2, 2).try_into().unwrap()
|
||||
}
|
||||
pub fn flags_set_r5900_use_dollar(&mut self, value: utils::TrinaryValue) {
|
||||
self.flags = utils::bitrepack(self.flags, value.try_into().unwrap(), 2, 2);
|
||||
}
|
||||
|
||||
pub fn instr_id_type_name(&self) -> &'static str {
|
||||
unsafe { std::ffi::CStr::from_ptr(RabInstrIdType_getName(self.instr_id_type)) }
|
||||
.to_str()
|
||||
|
@ -94,56 +94,60 @@ size_t RabbitizerInstruction_disassembleAsData(const RabbitizerInstruction *self
|
||||
}
|
||||
|
||||
bool RabbitizerInstruction_mustDisasmAsData(const RabbitizerInstruction *self) {
|
||||
if (RAB_INSTR_FLAGS_GET_disasmAsData(self) == RAB_TRINARY_VAL_TRUE) {
|
||||
return true;
|
||||
}
|
||||
switch (RAB_INSTR_FLAGS_GET_disasmAsData(self)) {
|
||||
case RAB_TRINARY_VAL_TRUE:
|
||||
return true;
|
||||
|
||||
if (RAB_INSTR_FLAGS_GET_disasmAsData(self) != RAB_TRINARY_VAL_FALSE) {
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.sn64DivFix) {
|
||||
if (self->uniqueId == RABBITIZER_INSTR_ID_cpu_break) {
|
||||
return true;
|
||||
case RAB_TRINARY_VAL_FALSE:
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_NONE:
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.sn64DivFix) {
|
||||
if (self->uniqueId == RABBITIZER_INSTR_ID_cpu_break) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
switch (self->uniqueId) {
|
||||
case RABBITIZER_INSTR_ID_cpu_trunc_w_s:
|
||||
case RABBITIZER_INSTR_ID_cpu_cvt_w_s:
|
||||
if (self->category == RABBITIZER_INSTRCAT_R5900) {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Here's some reading about the binutils rationale:
|
||||
* - https://sourceware.org/legacy-ml/binutils/2012-11/msg00360.html
|
||||
* - https://sourceware.org/pipermail/binutils/2013-January/079863.html
|
||||
*
|
||||
* Because of this, building with GAS with the -march=r5900 flag produces:
|
||||
* - trunc.w.s is built as the cvt.w.s instruction.
|
||||
* - 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 two
|
||||
* instructions as .word
|
||||
*/
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
switch (self->uniqueId) {
|
||||
case RABBITIZER_INSTR_ID_cpu_trunc_w_s:
|
||||
case RABBITIZER_INSTR_ID_cpu_cvt_w_s:
|
||||
if (self->category == RABBITIZER_INSTRCAT_R5900) {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Here's some reading about the binutils rationale:
|
||||
* - https://sourceware.org/legacy-ml/binutils/2012-11/msg00360.html
|
||||
* - https://sourceware.org/pipermail/binutils/2013-January/079863.html
|
||||
*
|
||||
* Because of this, building with GAS with the -march=r5900 flag produces:
|
||||
* - trunc.w.s is built as the cvt.w.s instruction.
|
||||
* - 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 two
|
||||
* instructions as .word
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!RabbitizerInstruction_isValid(self)) {
|
||||
|
@ -15,10 +15,22 @@ size_t RabbitizerOperandType_process_r5900_I(UNUSED const RabbitizerInstruction
|
||||
UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
|
||||
size_t totalSize = 0;
|
||||
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$I");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "I");
|
||||
switch (RAB_INSTR_FLAGS_GET_r5900UseDollar(self)) {
|
||||
case RAB_TRINARY_VAL_NONE:
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$I");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "I");
|
||||
}
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_FALSE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "I");
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_TRUE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$I");
|
||||
break;
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
@ -28,10 +40,22 @@ size_t RabbitizerOperandType_process_r5900_Q(UNUSED const RabbitizerInstruction
|
||||
UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
|
||||
size_t totalSize = 0;
|
||||
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$Q");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "Q");
|
||||
switch (RAB_INSTR_FLAGS_GET_r5900UseDollar(self)) {
|
||||
case RAB_TRINARY_VAL_NONE:
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$Q");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "Q");
|
||||
}
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_FALSE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "Q");
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_TRUE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$Q");
|
||||
break;
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
@ -41,10 +65,22 @@ size_t RabbitizerOperandType_process_r5900_R(UNUSED const RabbitizerInstruction
|
||||
UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
|
||||
size_t totalSize = 0;
|
||||
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$R");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "R");
|
||||
switch (RAB_INSTR_FLAGS_GET_r5900UseDollar(self)) {
|
||||
case RAB_TRINARY_VAL_NONE:
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$R");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "R");
|
||||
}
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_FALSE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "R");
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_TRUE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$R");
|
||||
break;
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
@ -54,10 +90,22 @@ size_t RabbitizerOperandType_process_r5900_ACC(UNUSED const RabbitizerInstructio
|
||||
UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
|
||||
size_t totalSize = 0;
|
||||
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$ACC");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "ACC");
|
||||
switch (RAB_INSTR_FLAGS_GET_r5900UseDollar(self)) {
|
||||
case RAB_TRINARY_VAL_NONE:
|
||||
if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$ACC");
|
||||
} else {
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "ACC");
|
||||
}
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_FALSE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "ACC");
|
||||
break;
|
||||
|
||||
case RAB_TRINARY_VAL_TRUE:
|
||||
RABUTILS_BUFFER_CPY(dst, totalSize, "$ACC");
|
||||
break;
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
|
Loading…
Reference in New Issue
Block a user