Sparc register name vs id mismatch
In sparc module, the register name and its id does not match the source definition:
Both SPARC_REG_F0(raw value is 122) and SPARC_REG_Q0(raw value is 190) are printed as f0. Both SPARC_REG_D2(raw value is 92) and SPARC_REG_F4(raw value is 126) are printed as f4.
Work environment
| Questions | Answers |
|---|---|
| System Capstone runs on OS/arch/bits | Debian amd64 |
| Capstone module affected | sparc |
| Source of Capstone | git clone |
| Version/git commit | 717d8b051997bacf48481eace9df357caedc0bca |
Expected behavior
The register id should match its printed name.
Actual behavior
Two register ids are mapped to the same name.
Steps to reproduce the behavior
- Ask cstool to print the actual register name:
diff --git a/cstool/cstool_sparc.c b/cstool/cstool_sparc.c
index 60795cf5..9aa577c2 100644
--- a/cstool/cstool_sparc.c
+++ b/cstool/cstool_sparc.c
@@ -31,7 +31,7 @@ void print_insn_detail_sparc(csh handle, cs_insn *ins)
printf("\t\toperands[%u].type: MEMBAR TAG = 0x%" PRIx64 "\n", i, (uint64_t) op->membar_tag);
break;
case SPARC_OP_REG:
- printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ printf("\t\toperands[%u].type: REG = %s(raw value = %d)\n", i, cs_reg_name(handle, op->reg), op->reg);
break;
case SPARC_OP_IMM:
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
- Run cstool:
$ ./cstool -d sparc+v9 81a80a2489a0102089a01a60
0 81 a8 0a 24 fcmps %f0, %f4
ID: 276 (fcmps)
Is alias: 662 (fcmps) with ALIAS operand set
op_count: 2
operands[0].type: REG = f0(raw value = 122)
operands[0].access: READ
operands[1].type: REG = f4(raw value = 126)
operands[1].access: READ
4 89 a0 10 20 fstox %f0, %f4
ID: 161 (fstox)
op_count: 2
operands[0].type: REG = f0(raw value = 122)
operands[0].access: READ
operands[1].type: REG = f4(raw value = 92)
operands[1].access: WRITE
Groups: Is64Bit
8 89 a0 1a 60 fqtoi %f0, %f4
ID: 139 (fqtoi)
op_count: 2
operands[0].type: REG = f0(raw value = 190)
operands[0].access: READ
operands[1].type: REG = f4(raw value = 126)
operands[1].access: WRITE
The width of the register (word, double word, quadruple word etc) should be implied by the instruction.
But generally it would be nice to somehow show the difference to the user. But I am not sure if printing magic numbers is meaningful. Because they don't necessarily match values in the ISA or dwarf IDs. They are just enum values.
We could add an extra API function for ~~AArch64~~ Sparc. Something like Sparc_get_pretty_reg_name() (something more meaningful, but you get the idea).
It could return q0 etc.
Sorry, I got confused and thought this is about AArch64. Just want to mention that this is how it is defined in the ISA.
The ISA doesn't have the concept of D0-D15 or Q0-Q7. It just has Fn registers.
The Dn and Qn registers are the representation of LLVM to signal it addresses two or four Fn registers at once.
That's quite interesting...
So basically, fstox %f0, %f4 reads f0 and writes to f4 & f5; fqtoi %f0, %f4 reads f0-f3 and writes to f4.
Yes. It also fails to assemble if you use reg numbers not a multiple of 1/2/4 respectively. Idk, a little in-intuitive if you ask me, but whatever.