A colleague mentioned that Thumb instructions were significantly slower than ARM instructions (this was for an AT91SAM7S32 processor). Is this true? What are the performance benefits of one instruction set over another?
THUMB instructions aren't to my knowledge intrinsically slower than ARM instructions, but rather are more limited in capability. If your code only needs the functionality of THUMB instructions, it will occupy less space than ARM, but would be the same number of instructions and, other things being equal, run at the same speed. If your code needs more functionality, than it would require more THUMB instructions than ARM instructions to execute and would take longer, again other things being equal (see below)
THUMB is popular in microcontrollers because of the smaller size instructions for two reasons:
- Program space is often limited
- Many microcontrollers have 16-bit data buses to their internal flash
For the second reason, when your code doesn't require functionality from the ARM instruction set, THUMB code actually runs faster. This is because your instruction can be fetched in one I/O cycle from the flash instead of two. Depending on the speed of your flash interface, that second read can incur one or more wait-cycles per instruction where your CPU is simply stalled and cannot do anything.
This becomes less of an issue if you can copy your code to RAM before executing (which I've usually seen as 32-bit for recent ARM microcontrollers), where the only concern is code density. For that, many tools will try to find which representation is more efficient for a given function. If the compiler can produce THUMB code in fewer instructions it will, but if ARM results in fewer instructions you get ARM. This is the default mode for Keil, if I recall correctly.
Your specific chip
For your particular chip (AT91SAM7S32) the documentation mentions that the flash controller has a prefetch buffer that can predict accesses to make things more efficient, which might improve ARM instruction execution. However, it also states that the prefetch is a "dual 32-bit" buffer that "optimizes 16-bit accesses" which is most suitable for "running in Thumb mode", which seems to indicate that it isn't intended to speed up ARM instructions, but to allow your core to run faster in THUMB mode.
From the diagrams, it looks like the flash on your chip actually has a 32bit data bus. The prefetcher seems to work by reading a whole 32bits, giving 16 to the CPU (in THUMB mode) and caching the whole 32bits. During the next cycle, when the CPU reads the second 16 bits, this time from cache, the flash controller is reading the next 32bits and caching it. In this way THUMB code can run without more than an initial wait even if the flash speed would be a bit slower than the CPU core speed. Section 19.2.2 "Read Operations" has more details.
Since your flash is a 32bit bus (as near as I can tell), if your CPU and Flash clocks are the same, THUMB will only give you code density over ARM. If you want your CPU core to run faster than Flash (and note, I didn't review all of the timing of this chip; I assume the CPU can run faster because they let you set wait states), than the prefetch gives a speed advantage to THUMB due to the reduction in actual flash accesses. However, that speed advantage is a per-instruction advantage. If the number of THUMB instructions vs ARM instructions is big enough, it will outweigh the per instruction speed resulting in ARM having a faster per-routine speed.