Note: If you prefer video format to reading stuff, there's a companion video for this: https://youtu.be/ONQLWdd5nuc
Looking at instruction encodings, 'ROR r0, #0' should be the same as 'RRX r0, r0'.
Let's first take a look at the encoding for the ROR instruction:
So Rm gets rotated imm5 places and gets stored into Rd
Now let's look at the encoding for RRX:
Note that the encoding is identical to ROR, with the exception that the imm5 field is harcoded to 0.
So if we were to write 'ROR r0, #0', we should expect this to disassemble as an RRX instruction; as we are merely mimicking these hardcoded zeros by providing '#0' as the imm5 value:
Yep! wait wut? Very much no. What is the encoding for this MOV instruction?
Come on assembler, why don't you know that I wanted to do an RRX when properly writing ROR in such a way that should encode into RRX? You have no idea how many times I legitimately need to use ROR to use RRX instead of actually typing RRX in assembly (even if it's zero times).
As a reminder from ARM Assembly is Too High Level: Moving by Shifting, the MOV instruction is just an LSL with it's immediate value set to 0's. If we were to take the 5 (of the 8) zeros following Rd and make them something else, the above MOV instruction would become an LSL by that amount. After these 5 bytes, the next 2 bytes define what kind of shift, rotate (or MOV) we are doing. For example, MOV and LSL are '00', LSR is '01', ASR is '10', and RRX and ROR share '11' (you can see this '11' field occur after the imm5 field in the first screenshot above). I really don't know why the assembler jumped from a ROR instruction to the MOV/LSL type instruction when giving it an imm5 value of zero. Sometimes assembly language is too high level for me to comprehend.