Description
Describe the bug
The PIC18 instruction definitions for RLNCF
and RRNCF
in pic18_instructions.sinc
implement a simple bit shift instead of the correct rotate logic. This leads to incorrect behavior during decompilation and emulation for these instructions.
Current (incorrect) implementation:
:RRNCF srcREG, D, A is op6=0x10 & srcREG & destREG & D & A {
tmp:1 = srcREG >> 1;
destREG = tmp;
setResultFlags(tmp);
}
:RLNCF srcREG, D, A is op6=0x11 & srcREG & destREG & D & A {
tmp:1 = srcREG << 1;
destREG = tmp;
setResultFlags(tmp);
}
Expected (correct) implementation (rotation logic):
:RRNCF srcREG, D, A is op6=0x10 & srcREG & destREG & D & A {
tmp:1 = srcREG >> 1 | srcREG << 7;
destREG = tmp;
setResultFlags(tmp);
}
:RLNCF srcREG, D, A is op6=0x11 & srcREG & destREG & D & A {
tmp:1 = srcREG << 1 | srcREG >> 7;
destREG = tmp;
setResultFlags(tmp);
}
This reflects the actual behavior of RLNCF and RRNCF as defined in the official Microchip PIC18 instruction set documentation.
To Reproduce
- Open a PIC18 firmware binary using Ghidra
- Analyze a function containing the
RLNCF
orRRNCF
instruction - Review the decompiled output or pcode
- Observe that only a shift is performed (not a rotate)
Expected behavior
RLNCF and RRNCF should perform a full rotate through the byte, not a simple logical shift. The current implementation discards the bits that should rotate back.
Environment (please complete the following information):
- OS: Any
- Java Version: 17
- Ghidra Version: 11.3.2 (and older)
- Ghidra Origin: Official GitHub release
Additional context
The source is located in:
pic18_instructions.sinc
This can cause incorrect binary analysis results, misleading reverse engineering output, and wrong emulator behavior in Ghidra’s decompiler/pcode engine for all code using RLNCF
/RRNCF
.