About 8 years ago I worked on porting NetBSD to a custom MIPS platform. Most of the kernel work I did was in C, but just two things had to be done in assembler:
1. Putting the CPU into 'idle' mode when no processing needed doing.
2. Putting the CPU+memory into 'standby' mode when running on batteries and it hadn't been used for a while.
This second feature was slightly challenging as the memory had to be put into standby mode first, then the CPU put into standby mode, but of course you couldn't access the main memory after it had been put into standby mode, but did have to carry on running instructions to then put the CPU into standby! The solution was to ensure that all the code required to put the CPU into standby mode (and then after wake-up, get main memory back out of standby mode) was in the CPU cache, so it didn't need the main memory to execute.
I've also recently used a tiny amount of assembler to implement computed goto's when using a C compiler that didn't natively support them
I'm fairly sure that people who require insane speed in tight loops also code in assembler, but I've never needed that myself.
> The solution was to ensure that all the code...was in the CPU cache,
Can you give some details for the idly curious (i.e. me).
My naive implementation would be something like:
; do stuff
jmp A
B: STANDBY
; bring memory back up
jmp C
A: ; shutdown memory
jmp B
C: ; continue as normal
Also, I'm surprised a processor with standby capabilites doesn't do all this in hardware rather than relying on the programmer to write an implementation. You call STANDBY, and the processor itself shuts down memory and then shuts itself down. Comments?
Putting the memory and CPU into standby was done by setting/clearing variout bits and various control registers (memory mapped). The code to do this was in a loop that executed twice. A CPU register set to zero the first time round and set to 0xffffffff the second time round, to use as a mask.
All control register changes were then performed in the loop, with changes to the control registers masked by the mask register so that no changes were actually made the first time round the loop, but all code was loaded into the CPU cache, then the second time round the loop changes were made and the memory+CPU put to sleep.
The MIPS CPU was quite nice, because when it woke up after this all state was preserved, so it just carried on as if nothing had happened. And memory contents were preserved through standby as well, so it was all fairly simple.
This is in contrast to some ARM CPUs I've used where when they wake up after sleep, they jump to the reset address, so the boot code has to be aware of sleep/wake operations, which was a bit of a pain.
It can be done in SW and it removes the need to implement it in hardware. Most probably nothing is preserved over a stand-by in a CPU, and when a CPU comes back online, it needs to be set up from scratch.
1. Putting the CPU into 'idle' mode when no processing needed doing.
2. Putting the CPU+memory into 'standby' mode when running on batteries and it hadn't been used for a while.
This second feature was slightly challenging as the memory had to be put into standby mode first, then the CPU put into standby mode, but of course you couldn't access the main memory after it had been put into standby mode, but did have to carry on running instructions to then put the CPU into standby! The solution was to ensure that all the code required to put the CPU into standby mode (and then after wake-up, get main memory back out of standby mode) was in the CPU cache, so it didn't need the main memory to execute.
I've also recently used a tiny amount of assembler to implement computed goto's when using a C compiler that didn't natively support them
I'm fairly sure that people who require insane speed in tight loops also code in assembler, but I've never needed that myself.