capstone icon indicating copy to clipboard operation
capstone copied to clipboard

Sparc register name vs id mismatch

Open jiegec opened this issue 5 months ago • 4 comments

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

  1. 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);
  1. 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

jiegec avatar Jul 09 '25 09:07 jiegec

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.

Rot127 avatar Jul 09 '25 11:07 Rot127

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.

Rot127 avatar Jul 09 '25 12:07 Rot127

That's quite interesting...

Image

So basically, fstox %f0, %f4 reads f0 and writes to f4 & f5; fqtoi %f0, %f4 reads f0-f3 and writes to f4.

jiegec avatar Jul 09 '25 14:07 jiegec

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.

Rot127 avatar Jul 09 '25 14:07 Rot127