flag_r5900UseDollar

This commit is contained in:
angie 2023-11-11 13:55:06 -03:00
parent 049b47b32c
commit 111ee90a3a
9 changed files with 157 additions and 67 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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.
"""

View File

@ -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 }
};

View File

@ -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()

View File

@ -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)) {

View File

@ -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;