- December 17, 2016 at 10:11 am #55086
In my project, based on PIC32MZ (EF), i make extensive use of nearly all available shadow register sets. While switching them back and forth i stumbled upon something that looks like a bug in the MIPS core. The code in question is:
The above happens in a syscall, so i first change PSS to whatever register set i want to write to, and then restore the original PSS value. If the above executes as per the documentation i should end up with ‘v0’ equal to ‘s2’ in the register set pointed to by ‘v1’. What actually happens is that ‘wrpgpr’ reliably(*) writes in the PSS pointed to by ‘s1’, which is in the _next_ instruction.
Adding ‘ehb’ or even a single ‘nop’ between ‘wrpgpr’ and ‘mtc0’ seems to fix the issue. The above behavior is not documented so it took me a while to figure out what happens. I am not overly familiar with the MIPS pipeline, but it looks to me that ‘wrpgpr’ takes more than one cycle to complete and the subsequent ‘mtc0’ finishes before it. In this particular case these two instructions create a dependency, which the core does not detect. The presence or absence of the last ‘ehb’ does not seem to make any difference.
(*) This happens each time i execute a particular code sequence. A few smaller and simpler test cases that i wrote does not hit the bug.December 18, 2016 at 12:06 pm #55090April 28, 2017 at 10:31 pm #55731
It is documented in the software users manual:
See Table 2.9 Execution HazardsApril 29, 2017 at 8:36 am #55735
Hey Chris. Thanks for the reply.
This is how i read table 2.9: If there’s mtc0 to SRSCtl(pss) the _next_ instruction should not be rd/wrpgpr. IOW the hazard continues into the future few clocks.
In my code example the hazard appears to happen _back_ in time. wrpgpr fails if the _following_ instruction is mtc0. I realized that this issue manifests itself more reliably if there’s a long loop before wrpgpr.
My (maybe naive) take on the problem is this: wrpgpr depends on SRSCtl(pss) just as mtc0 to the same location. For some reason and at certain conditions (cpu pipeline feature) wrpgpr executes after the following instruction. If the next instruction happen to be “mtc0 SRSCtl(pss)” we hit the race.
All execution hazards are supposed to affect the following instruction. In this case it appears that execution hazard may also affects the _preceding_ instruction.
1 user thanked author for this post.June 1, 2017 at 8:44 pm #56031
Sorry for not getting back to you sooner I had some thinking to do about this and it does seem strange. I’m reaching out to the designers and will get back to you.
ChrisJune 1, 2017 at 10:28 pm #56032
Thanks Chris. I’ve worked around the issue, but I am really curious about what the designers have to say. 🙂
PetkoJune 2, 2017 at 1:28 am #56033
The designers said the right thing to do for this version of the processor is ehb or nop or another instruction between the wrpgpr and access to srsctl.