This macro (see below) toggles (0 becomes 1, 1 becomes 0) one of eight output pins of the Infineon TriCore 1797 port P9 by writing the appropriate value to the register P9_OMR. It uses an assembly string composed from string literals in the macro body and its "stringized" argument, #Pin, which is a value in the range 0..7. The final part of the inline assembly construct is the "clobber list", the list of registers changed (and not restored) by the assembly code. This macro is automatically inserted into PCP code by the RapiTime code instrumenter in order to monitor the different paths and times taken by software executing a number of tests (see RapiTime instrumentation).
#define RPT_TogglePin(Pin) __asm( \ "ldl.il r0,(1 << (" #Pin ")) \n\t" \ "ldl.iu r0,(1 << (" #Pin ")) \n\t" \ "ldl.iu r1,@HI(P9_OMR) \n\t" \ "ldl.il r1,@LO(P9_OMR) \n\t" \ "st.f r0,[r1],size=32" \ :::"r1","r0","r7")
It is not obvious that r7 is corrupted by the listed instructions. When we omitted r7 from the clobber list, the TASKING compiler generated code that, very efficiently, cached the result of a test in the Z flag, assuming that this flag was preserved by our RPT_TogglePin macro. However r7 contains the PRAM data pointer (DPTR) and the status flags, including the N and Z flags that are changed by the ldl instruction. When the compiled code read the corrupted Z flag immediately after the assembly code for RPT_TogglePin, the program failed, triggering an expensive debugging process. The fix was simply to add r7 to the clobber list, informing the compiler that r7 is not preserved by the inline assembly string and ensuring that it saves and restores the Z flag itself.
You have to include r7 in the clobber list for inline assembly unless you have checked each instruction to be sure that it affects neither DPTR nor the status flags.