Can anyone offer some back-of-envelope sort of estimates of what sort of gate count was needed to add a multiplier to 8-bit CPUs?
An 8x8 array multiplier build from 6T adders comes down to 8x8x6=384 transistors. With buffers/drivers this easily reaches beyond 400 transistors, maybe even near 600 when latching is needed. Further some decoding (PLA) and execution (random) might be needed, but that's just a few dozen transistors. In total this might increase the CPU by 20%.
The operation needs two 8 bit values as input and yields one 16 bit value. For a 6502 input would be naturally
A and a memory operand, but there is no 16 bit register. While storing the lower 8 bits again in
Amight sound useful,
Y could take the upper 8 bits - damaging the ability to use either in addressing. Or a new
Extension register would be needed. Not a bad idea in general (*1), but that adds something like another 50 transistors (*2).
I ask because I find it a bit odd that the 6809 had one, but none of the other chips of the era did.
The 6809 is a complete new design, and the next generation after a 6800 or 6502, more in line with upcoming 16-bit processors of the same time.
It seems that B or C models of the 6502 and Z80 would have the opportunity to add this,
These were just faster speed selections, not really new (or enhanced) CPUs.
so I assume there is a good reason why they didn't?
As so often it's the 'why' question. Why adding and complicating the CPU for such a minor add on? Sure, it'll speed up multiplying, but then again, it's not exactly the most needed operation. I can't remember having it used in all the years of 8086 programming. And even on /370 it was convenient, but not really necessary. Usually, multiplying by 2 or 4 is what's needed, and here a shift will always beat a multiply.
*1 - This might open the opportunity for some quite nice new operations, not at least 16 bit load and store, enabling fast movement of pointers (into ZP).
*2 - Renesas for example did not only add an 8x8 multiply and divide instruction to their 6502 (740 Family), but also avoided the addition of a new register by pushing the upper 8 bits of the multiplication result onto the stack - similarly, with a division, the negated(!) remainder is pushed.