https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118816
Bug ID: 118816
Summary: Accessing MIPS coprocessor 2/3 register variables
generates invalid assembly
Product: gcc
Version: 14.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: johannes_schiller at web dot de
Target Milestone: ---
When using a global register variable to access registers on MIPS coprocessors
2 or 3, GCC will generate assembly when accessing those, that is incompatible
with the assembler.
It works perfectly for coprocessor 0, and coprocessor 1 can't be accessed this
way since it's the FPU.
Sample Code (also available via Godbolt: https://godbolt.org/z/e1vjsK7aE):
register unsigned int cop0_r0 asm("c0r0");
register unsigned int cop2_r0 asm("c2r0");
register unsigned int cop3_r0 asm("c3r0");
void test() {
cop0_r0 = 10;
cop2_r0 = 10;
cop3_r0 = 10;
}
GCC Output:
/tmp/cce5eUyF.s: Assembler messages:
/tmp/cce5eUyF.s:34: Error: invalid operands `mtc2 $2,$c2r0'
/tmp/cce5eUyF.s:37: Error: invalid operands `mtc3 $2,$c3r0'
Compiler returned: 1
Assembly Output:
test:
daddiu $sp,$sp,-16
sd $fp,8($sp)
move $fp,$sp
li $2,10 # 0xa
mtc0 $2,$0
mtc2 $2,$c2r0
mtc3 $2,$c3r0
nop
move $sp,$fp
ld $fp,8($sp)
daddiu $sp,$sp,16
jr $31
nop
So the problem seems to be, that GCC doesn't translate the register names for
COP2/3.
Looking at the code (gcc/config/mips/mipc.cc) it seems like the translation
from "cNr0" to "$0" is only done for COP0. Patching the code locally to also
perform the same for COP2/3 did resolve the issue for me.
I'll attach a patch, but unfortunately I don't have the capacity to go through
the proper steps to submit it.