Siemens S5 had loads of "un documented" instructions, well some I came across were not in the manuals.
some of their standard function blocks used system instructions not shown on any manuals I found.
In fact some i think were actual instructions but by using the way the ram structure was it was possible to create large DB's on the fly to fill the memory with a DB of several kilowords other RS instructions were used in standard blocks i.e. load a hex value into a flagword that is a MC5 machine code instruction then DO RSxx (process the instruction contained in the flagword).
It was possible to make self modifying code or transfer a datablock containing the MC5 instructions & create a function block nasty but have seen it done.
Once came across a system that checked how much memory was left in the plc & in the startup OB it created a DB just large enough to fill the memory, created the header for the block etc.
this was not to stop anybody from copying as if you uploaded it & tried to download it would say not enough memory.
but as a printer buffer on a critical process but then again unless you new how to re-load the plc you had great problems doing a mod.
Although not strictly an undocumented instruction I came across a function block that passed a timer (or the decimal value of a timer address) this foxed me for a while as the value was greater than 255 (the max number for a standard S5 timer, however I realised what the engineer had done.
Timers are addressed as an 8 bit word for the timer number, so 256 is timer 1 as it only processes the lower byte it sees the pointer as a "1". don't know what was in his mind apart from confusing other engineers but passing 0-255 would have done.