There is no solution that does not also respect the following constraints. First, no matter how you set up the prioritization scheme, the only way for an interrupt to be able to directly pre-empt an interrupt at lower priority on the 8051 family is for it to either be set at high priority or to come before the other interrupt in the scanning sequence at a given priority. Second, the only way you're going to be able to pre-empt an interrupt that is able to pre-empt other interrupts at yet lower priority is for the middle priority interrupt to be at low priority when it is pre-empted or else to come after the interrupt pre-empting it, in the scanning sequence, at a given priority.
That, alone, says you have to be exploiting the scanning sequence and/or to be run-time switching the actual 8051 priorities for interrupts that are at anything other than the highest or lowest priority in your scheme.
To drop down to a lower priority level for a high-priority handler, during mid-process, keep the interrupt flag activated, drop the priority flag, and do a "reti". If nothing else is awaiting interrupt handling, then it goes right back into the interrupt handler ... at lower priority. When done, with the lower priority part of the handler, set it back for high priority before doing the second "reti". Now, all you have to do is make sure you have the priorities matched up correctly with the scanning order at low priority. If not, then it might actually be necessary to set the later-scanned "low priority" interrupts at high priority.
The drop-down is what was happening here multi-threaded 8051 data collection demo (meant to be assembled with the CAS 8051 assembler), which processes the (8051FA-specific) interrupt handler for 5 timers, alongside a handler for the (8052-specific) for timer #2 in a multi-threaded setup. So, effectively the drop-down to lower priority functions as a spooler. If you use something like the demo, by the way, it could be improved upon by adding a switch of the R0-R7 address area in with the context switch (as simple as a "pop PSW" provided the register window has been initialized appropriately for the thread). The registers R0-R7 were meant to be used as thread-local variables, which is why they were designed to target multiple register windows - just like RISC processors do. Unfortunately, hardly anyone uses the R0-R7 registers that way.